PyGame重新连接时重新初始化USB MIDI设备

时间:2015-01-17 04:43:54

标签: python pygame midi udev pyudev

我使用PyGame来读取USB MIDI设备,与使用here非常相似,只不过我在Raspberry Pi上将其作为后台服务运行。

我希望能够断开并重新连接MIDI设备,并且仍然可以阅读它。

我尝试了两种方法:

  1. 使用pygame.midi.get_count()和info()定期枚举MIDI设备。
  2. 使用pyudev监控USB事件,类似于this示例。
  3. (1)的问题在于,无论设备是否仍然连接,pygame.midi似乎总是返回相同的值(get_count和info)。

    (2)的问题是它永远不会调用我为事件注册的异步函数(尽管独立示例工作正常,只是将子系统更改为usb)。我认为这可能是线程的一个问题,所以我调用一切来注册来自专用线程的事件,然后运行glib.MainLoop.run()到空闲等待,但发现pygame将无法读取midi设备如果我在运行我的AMK类之前启动任何线程,即使只是一个打印了一些东西并返回的线程。 (我使用glib,因为Pi repo中的pyudev版本是0.13,但我想更新的方式是gobject等价物。)

    因此我使用udevd检测连接事件并通过/etc/udev/rules.d/触发器重新启动我的服务,这可以正常工作,但是很麻烦,并且在我的脚本中丢失状态(我会喜欢保存)。

    所以,在我浪费更多时间调试之前(2),我希望有人能指出我正确的方向。

3 个答案:

答案 0 :(得分:1)

pygame使用PortMidi,它最初是为Windows MIDI API设计的,并假设MIDI端口集不会改变。

当MIDI端口发生变化时,您必须使用单独的监视器进程重新启动程序。

答案 1 :(得分:1)

我尚未对此进行彻底测试,但我相信如果您再次致电quit然后再init,则可以获得正确更新的MIDI设备列表。这是一个例子:

import pygame, pygame.midi    
pygame.midi.init()    
print pygame.midi.get_count()    
a=raw_input('Connect or disconnect some MIDI devices')    
pygame.midi.quit()    
pygame.midi.init()
print pygame.midi.get_count()

答案 2 :(得分:0)

这就是我监视现有或新添加的 Midi 设备的方式 - wait_for_midi() 将阻塞,直到系统中出现 MIDI 设备并返回 /dev/midi* 路径。

import re
import pyudev

def is_midi_device(dev_path):
    if dev_path is None: 
        return False
    if re.match(u"^/dev/midi[0-9]+$", dev_path):
        return True
    return False

# Return path to a MIDI device when found.
def wait_for_midi():
    context = pyudev.Context()

    #  Check for existing midi devices
    for device in context.list_devices():
        dev_path = device.device_node
        if is_midi_device(dev_path) :
            print('Found {}'.format(dev_path))
            return dev_path

    # Monitor for new midi devices as added
    monitor = pyudev.Monitor.from_netlink(context)
    monitor.filter_by(subsystem='sound')
    for action, device in monitor:
        if action != "add": 
            continue
        dev_path = device.device_node
        if is_midi_device(dev_path) :
            print('Just added: {}'.format(dev_path))
            return dev_path