Pull requests

#28 Open
Repository
SpotlightKid SpotlightKid
Branch
default
Repository
pygame pygame
Branch
default

Replace internals of pygame.midi with wrapper for python-rtmidi

Bitbucket cannot automatically merge this request.

The commits that make up this pull request have been removed.

Bitbucket cannot automatically merge this request due to conflicts.

Review the conflicts on the Overview tab. You can then either decline the request or merge it manually on your local system using the following commands:

hg update default
hg pull -r default https://bitbucket.org/SpotlightKid/pygame
hg merge 08aa97687b1c
hg commit -m 'Merged in SpotlightKid/pygame (pull request #28)'
Author
  1. SpotlightKid
Reviewers
Description

Further to todays discussion on the ML about pyportmidi, I replaced the internals of pygame.midi to use python-rtmidi instead. This is intended to be a backwards compatible API wrapper, to allow existing code using pygame.midi to run, in most cases without any changes. I think the API of portmidi is flawed in some ways and pygame.midi does not improve it, so I think pygame.midi should deprecated in future release. Also, I had to use a few ugly hacks to handle differences between portmidi and RtMidi, so this code is not made for eternity.

  • Input and Output devices are enumerated separately in RtMidi but consecutive in portmidi
  • RtMidi does not support any latency correction or event scheduling on MIDI output, but support in portmidi was never complete anyway. This code just ignores all timestamps completely for MIDI output.
  • RtMidi classes do not currently have an attribute to indicate whether they have an open port assigned to them, so I had to record which device IDs refer to opened ports seperately. This will probably break if devices are added or removed while Input/Output instances exist.

Anway, I do expect this code to be accepted as is, rather it should provide a basis for discussion. If pyportmidi should be removed from pygame, the documentation and examples would need to be adapted as well.

  • Learn about pull requests

Comments (8)

  1. illume

    Wow. Nice work :) I'll have a look at this in more detail later, but just wanted to let you know it is appreciated.

    Since pygame tries to be C++ free, how about having the python-rtmidi as a separate backend? So if python-rtmidi exists, use that, otherwise fall back?

    1. Lenard Lindstrom

      Well, Pygame was C++ free. Portmidi is C++, so a switch to RtMidi changes nothing in that respect. And personally, I'm tired of C coding, which is why I chose C++ for the ImgBlit library. C++ is not my language of choice, but it has allowed me to encapsulate dynamic memory management, something I no longer have the patience to do manually in C. Besides, RtMidi supports input callbacks, which means midi input events can be directly converted to SDL events without polling input.

  2. SpotlightKid author

    I personally think, pygame should not include any MIDI bindings at all.

    The code provided here is meant only as a backwards compatibilty layer for existing programs using pygame.midi, since apparently on some platforms it is too hard to compile portmidi and pygame with portmidi support and pyportmidi is unmaintained.

    MIDI nowadays is mostly used only for musical applications, not as a general means for games to produce sounds. Frankly, if your program wants to use MIDI (i.e. it needs MIDI I/O), I recommend that you just include python-rtmidi in 'install_requires'' in your setup.py and use its API.

    If your are looking for MIDI as a means to play music in your game, I would look at interfacing to a software synthesizer directly, for example with pyFluidSynth (http://code.google.com/p/pyfluidsynth/).

  3. illume

    A pygame.midi module which can use either the current portmidi, or the python-rtmidi depending on which is available would be the best solution I think. Then either would be available.

    If there are compilation issues with pygame.midi they should be listed in separate issues. I can't find any issues with it yet.

  4. SpotlightKid author

    I can't find a pygame issue for it, but here are some pointers to problems reported on the ML:

    Apparently some people had problems compiling pygame with portmidi support on OS X with the system Python:

    http://article.gmane.org/gmane.comp.python.pygame/24282

    It isn't clear to me from thread, though, what the exact problem was.

    Improperly compiled portmidi library on Ubuntu/debian:

    http://article.gmane.org/gmane.comp.python.pygame/24841

    Apparently the bug is still not fixed after years:

    https://bugs.launchpad.net/mixxx/+bug/1097286

    PyPortmidi is unmaintained:

    http://article.gmane.org/gmane.comp.python.pygame/24972

  5. illume

    Thanks for collecting those bug reports.

    pygame.midi should be in pygame, because people use it, and for backwards compatibility. I personally use it for a few projects too, and I'm happy maintaining the portmidi part at the moment.

    If you agree, I'll take your midi.py changes, and move them into a midi_rtmidi.py backend. So then pygame.midi can use either backend. Sound ok?

  6. SpotlightKid author

    Yes, that might be a way, but I wouldn't want developers to use the pygame.midi API to access python-rtmidi for new projects, only as fallback for backwards compatibility. The pygame.midi API is a thin wrapper around pyportmidi and shares its assumptions about the numbering of MIDI ports and timestamps (see above), which do not really map well to RtMidi, and the strategies I used to reconcile both in the code below are a bit hackish.

    Thatswhy I added the deprecation warning to the code. Problem is, deprecation warnings are ignored by default since Python 2.7.