3

我正在使用 PyGame 读取 USB MIDI 设备,与此处使用的非常相似,除了我将它作为 Raspberry Pi 上的后台服务运行。

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

我尝试了两种方法:

  1. 使用 pygame.midi.get_count() 和 info() 定期枚举 MIDI 设备。
  2. 使用 pyudev 监控 USB 事件,类似于示例。

(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) 之前,我希望有人能指出我正确的方向。

4

3 回答 3

1

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

您必须使用单独的监视器进程来在 MIDI 端口更改时重新启动程序。

于 2015-01-17T08:45:32.303 回答
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()
于 2015-01-17T22:54:21.147 回答
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
于 2021-04-17T10:52:18.933 回答