2015-01-17 63 views
2

我使用PyGame读取USB MIDI设备,非常类似于使用here,但我将它作为Raspberry Pi上的后台服务运行。PyGame在重新连接时重新初始化USB MIDI设备

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

我已经尝试了两种方法:

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

(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/触发器重启我的服务,该工作正常,但是kludgy,并且丢失了脚本中的状态(我想保存)。因此,在我浪费更多时间调试(2)之前,我希望有人能够指引我朝着正确的方向前进。

回答

1

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

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

+0

有趣,谢谢。这就解释了方法(1)的问题。 它似乎表明(2)是正确的路要走,但我想知道是否有必要在注册USB监视器后产生新的线程。如果是这样,那么我想知道为什么PyGame不能很好地与线程配合,如果没有,那么为什么我的运行程序在运行我的PyGame类时没有被调用。 – cwshep

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() 
+0

感谢您的提示。奇怪的是,如果我尝试quit()和init()然后重新初始化设备,后续调用midi_in.poll()失败: 'PortMidi调用失败... PortMidi:'Bad pointer' ENTER ... ' 而且我验证了新的midi_in是一个有效的对象('')。无论如何,这看起来像是一个非常丑陋的方式来做我想要的东西。由于我想实时阅读midi设备,因此不断退出和重新启动似乎是一个糟糕的主意。 – cwshep

+0

如果您不想诉诸外部程序,您可以监视主循环中的系统日志并查找MIDI连接/断开连接事件。例如,使用'mesg = commands.getoutput('dmesg | grep -i midi')'并检查mesg是否已经从先前的迭代中改变。只有在这种情况下,你才需要做midi quit和init。我现在在办公室,无法用midi_in.poll()检查问题,但是您是否记得再次重新关联midi端口(使用'midi_in = pygame.midi.Input(portnumber')? –