PyGame повторно инициализирует USB MIDI-устройство при переподключении

Я использую PyGame для чтения USB MIDI-устройства, очень похожего на то, что используется здесь, за исключением того, что я запускаю его в качестве фоновой службы на Raspberry Pi.

Я хотел бы иметь возможность отключить и повторно подключить MIDI-устройство, и все же иметь возможность читать его.

Я попробовал два подхода:

  1. Регулярно перечисляйте MIDI-устройства, используя pygame.midi.get_count() и info().
  2. Используйте pyudev для мониторинга событий USB, аналогично этому примеру.

Проблема с (1) заключается в том, что pygame.midi всегда возвращает одинаковые значения (как get_count, так и info), независимо от того, подключено ли устройство.

Проблема с (2) состоит в том, что он никогда не будет вызывать асинхронную функцию, которую я зарегистрировал для событий (хотя автономный пример работает нормально, просто меняя подсистему на usb). Я подумал, что это может быть проблемой с многопоточностью, поэтому я вызвал все для регистрации событий из выделенного потока, который затем запустил glib.MainLoop.run() для ожидания простоя, но обнаружил, что pygame не сможет прочитать устройство midi. если я запустил какой-либо поток перед запуском своего класса AMK, даже просто поток, который что-то напечатал и вернул. (Я использую glib, так как версия pyudev в репозитории Pi равна 0,13, но я думаю, что более новый путь - это эквивалент gobject).

Таким образом, я прибег к использованию udevd для обнаружения события подключения и перезапуска службы с помощью триггера /etc/udev/rules.d/, который работает нормально, но не работает и теряет состояние в моем сценарии (который я хотел бы сохранить).

Поэтому, прежде чем я потратил еще много часов на отладку (2), я надеялся, что кто-то может указать мне правильное направление.

3 ответа

Pygame использует PortMidi, который был изначально разработан для Windows MIDI API и предполагает, что набор портов MIDI никогда не меняется.

Вы должны использовать отдельный процесс мониторинга, который перезапускает вашу программу всякий раз, когда меняются MIDI-порты.

Я еще не проверил это полностью, но я считаю, что если вы позвоните 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()

Вот как я отслеживаю существующие или недавно добавленные устройства 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
Другие вопросы по тегам