Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIDI port connection changes not detected #3301

Open
Erriez opened this issue Jul 13, 2022 · 4 comments
Open

MIDI port connection changes not detected #3301

Erriez opened this issue Jul 13, 2022 · 4 comments
Labels
bug midi pygame.midi

Comments

@Erriez
Copy link

Erriez commented Jul 13, 2022

Environment:

  • Operating system: Windows 10
  • Python version : 3.91.0
  • SDL version: N.A.
  • PyGame version : 2.1.2
  • Relevant hardware: N.A.

Current behavior:

The function pygame.midi.get_count() always returns the same number of MIDI ports after startup, even after a MIDI device connect/disconnect.

Application background: When clicking on a drop-down box, it should update new connected/disconnected MIDI ports.

Expected behavior:

Update number of MIDI ports after connect/disconnect.

Screenshots

N.A.

Test code

  1. Run test code:
import pygame

pygame.init()
pygame.midi.init()

while True:
    print(pygame.midi.get_count())
    time.sleep(1)

Output for example: 2 MIDI ports.

  1. Connect MIDI device.
  2. Output is still 2 MIDI ports.
  3. Restart Python script
  4. Output is for example: 4 MIDI ports.

Stack trace/error output/other error logs

N.A.

@Erriez Erriez added the bug label Jul 13, 2022
@Starbuck5
Copy link
Contributor

Would it work if you quit and re init the midi module?

pygame.midi.quit()
pygame.midi.init()

I don't think the portmidi backend has hotplugging support, see: mixxxdj/portmidi#8 (comment)

@Starbuck5 Starbuck5 added the midi pygame.midi label Jul 14, 2022
@Erriez
Copy link
Author

Erriez commented Jul 14, 2022

I created a test case which calls the quit() and init() functions before get_count() and then the number of ports is updated correctly. However, open MIDI connections are closed which is a problem for my application design.

Testcase:

import pygame
import pygame.midi
import time


def get_mini_ports():
    # Hack to re-initialize MIDI to return updated `get_count()`
    # Open MIDI connections are closed!
    pygame.midi.quit()
    pygame.midi.init()

    midi_ports = []
    for i in range(pygame.midi.get_count()):
        (midi_interface, midi_name, midi_input, midi_output, opened) = pygame.midi.get_device_info(i)

        midi_interface = midi_interface.decode('utf-8')
        midi_name = midi_name.decode('utf-8')

        midi_ports.append({
            'ID': i,
            # 'midi_interface': midi_interface,
            'midi_name': midi_name,
            'midi_input': midi_input,
            'midi_output': midi_output,
            'opened': opened
        })
    return midi_ports


def print_mini_ports(portout):
    # Send some Sysex data
    portout.write_sys_ex(pygame.midi.time(), [0xf0, 0x00, 0x00, 0x00, 0x00, 0xf7])
    print('Write before MIDI quit()/init(): OK')

    print('MIDI ports: ')
    for port in get_mini_ports():
        print('  {}'.format(port))

    # Send some Sysex data
    portout.write_sys_ex(pygame.midi.time(), [0xf0, 0x00, 0x00, 0x00, 0x00, 0xf7])
    print('Write after MIDI quit()/init(): OK')


if __name__ == '__main__':
    # Initialize Pygame
    pygame.init()
    pygame.fastevent.init()
    pygame.midi.init()

    # Open MIDI port
    portout = pygame.midi.Output(1)

    while True:
        print_mini_ports(portout)
        time.sleep(1)

I don't think the portmidi backend has hotplugging support, see: mixxxdj/portmidi#8 (comment)

Thanks for your confirmation.

It looks like correctly handled by Python https://github.com/mido/mido package, but need to investigate further:

import mido
import time

# Connect/disconnect MIDI devices while printing MIDI ports:
while True:
    print('MIDI inputs:')
    print(mido.get_input_names())
    print('MIDI outputs:')
    print(mido.get_output_names())
    time.sleep(1)

@Starbuck5
Copy link
Contributor

It looks like correctly handled by Python https://github.com/mido/mido package, but need to investigate further:

See, it's funny you say that, since mido says it has three backends:

  • pygame
  • portmidi (pygame's backend)
  • rtmidi (unrelated)

@Erriez
Copy link
Author

Erriez commented Jul 15, 2022

You're right, I used the mido API with backend python-rtmidi. After some additional investigation, I found a bug in python-rtmidi: Incorrect MIDI port names. I reported the bug in mido/mido#381, SpotlightKid/python-rtmidi#111.

So I'll continue with Pygame and implement a workaround where the MIDI ports are not updated after init and connect/disconnect. In this case the user should always disconnect an open MIDI port, then the MIDI ports are updated correctly as you suggested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug midi pygame.midi
Projects
None yet
Development

No branches or pull requests

2 participants