ofxMidi
repository·master·Indexed 43 days ago
https://github.com/danomatika/ofxmidiAn openFrameworks addon providing MIDI input and output capabilities. It utilizes RtMidi for macOS, Windows, and Linux, and PGMidi for iOS. Core components include ofxMidiIn for receiving messages via ofxMidiListener, ofxMidiOut for sending data using a stream interface, and ofxMidiMessage for representing received MIDI data.
What's inside ofxMidi
- PGMidi is a simplified library for accessing MIDI devices via the CoreMidi framework on iOS. It provides a high-level interface to handle MIDI device attachment, detachment, and MIDI input reception. It is designed to be easily incorporated into iOS applications, with support for both ARC and non-ARC projects.
Overview of ofxMidi core components
masterofxMidi provides MIDI I/O capabilities for openFrameworks applications. It consists of three primary components:
ofxMidiIn: A single MIDI input port. To receive messages, you must derive a class fromofxMidiListener.ofxMidiMessage: Represents a single received MIDI message.ofxMidiOut: A single MIDI output port that supports a stream<<interface for sending data.
The addon uses
RtMidifor macOS, Windows, and Linux, andPGMidifor iOS.Overview of RtMidi C++ classes
masterRtMidi provides a common C++ API for real-time MIDI input and output across multiple platforms (Linux, macOS, Windows, iOS, and Android).
Core abstractions:
RtMidiIn: Handles MIDI input functionality. Each instance supports a single MIDI connection.RtMidiOut: Handles MIDI output functionality. Each instance supports a single MIDI connection.
Key technical details:
- Data Format: MIDI data is passed to the user as raw bytes using
std::vector<unsigned char>. - Timing: RtMidi does not provide internal timing functionality; output messages are sent immediately. Input messages are timestamped with delta times in seconds using a
doublefloating point type. - Portability: Designed to be easily included in projects via a single header and a single source file.
How to use the PGMidi class
masterThe core functionality is contained in thePGMidiclass located in theSources/PGMididirectory. This class handles the heavy lifting of MIDI management and uses a delegate interface to report events (such as device attachment/detachment or incoming MIDI data) to your application. To use it, you should implement the provided delegate interface to react to these events.Compile RtMidi test programs on Windows
masterTo compile the example programs on Windows, open the Visual C++ workspace file located in thetests/directory using your IDE.Install ofxMidi into openFrameworks
masterTo use ofxMidi, ensure you have openFrameworks installed. Download the ofxMidi source and place the addon directory into your openFrameworks addons folder:
openFrameworks/addons/ofxMidi/git clone git://github.com/danomatika/ofxMidi.gitRun ofxMidi example projects
masterExample projects are located in
ofxMidi/midiInputExample,ofxMidi/midiOutputExample, andofxMidi/midiExampleIOS.Since project files are not included, you must use the openFrameworks ProjectGenerator to create them:
- Click Import in ProjectGenerator.
- Select the parent folder (
ofxMidi) and then the specific example folder (e.g.,midiOutputExample). - Click Open, then click Update.
Platform-specific execution:
- macOS: Open the Xcode project, select the Debug scheme, and run.
- Linux: Open the QT Creator project or use the Makefile:
make make run - Windows: Open the Visual Studio project, build, and run.
make make runConfigure MIDI routing by platform
masterDepending on your operating system, you may need additional tools to route MIDI signals between applications:
- macOS: Use MIDI Patchbay.
- Linux: Use ALSA utilities like
aconnectoraconnectgui, or theqjackctlGUI. - Windows: Windows lacks a built-in virtual MIDI routing system. Use loopMIDI to create virtual ports for connecting to synths or DAWs.
Compile RtMidi test programs on Unix
masterTo compile the example programs included in the
tests/directory on Unix-based systems (Linux/macOS):- If you cloned the repository via git, run
./autogen.shfirst. - Run
./configurein the top-level directory. - Navigate to the
tests/directory and runmaketo compile the test programs.
./autogen.sh ./configure cd tests && make- If you cloned the repository via git, run
Configure MIDI functionality and compatibility
masterTo integrate PGMidi into your iOS project:
- Enable MIDI functionality: Use the header file provided in the
PGMididirectory to selectively enable MIDI features in your application. - Handle CoreMidi availability: PGMidi requires iOS 4.2 or higher to function because it relies on the CoreMidi framework.
- Weak Linking: If your application needs to support devices running iOS versions earlier than 4.2, you must link against
CoreMidiweakly to prevent crashes on older devices where the framework is unavailable.
- Enable MIDI functionality: Use the header file provided in the
Add ofxMidi to an existing project (Manual)
masterIf you are not using the ProjectGenerator, follow these manual steps to integrate ofxMidi:
Xcode
- Create a group
ofxMidiin youraddonsgroup. - Drag
ofxMidi/srcandofxMidi/libsinto this group.- For macOS: Remove
src/iosandlibs/pgmidireferences. - For iOS: Remove
src/desktopandlibs/rtmidireferences.
- For macOS: Remove
- Add the
CoreMIDI.frameworkvia the Project Summary tab -> Linked Frameworks & Libraries. - Add these paths to your
Project.xconfig:../../../addons/ofxMidi/src ../../../addons/ofxMidi/libs/rtmidi
Linux (Makefiles/CodeBlocks)
Add
ofxMidito the end of youraddons.makefile.Windows (CodeBlocks & Visual Studio)
- Add
ofxMidi/srcandofxMidi/libs/rtmidito your project tree. - Add the following search paths to your project settings:
..\..\..\addons\ofxMidi\src ..\..\..\addons\ofxMidi\libs\rtmidi
- Create a group
Avoid segmentation faults with static ofxMidi objects on Linux
masterOn Linux, creating static
ofxMidiInorofxMidiOutobjects can cause segmentation faults because they may be initialized before the ALSA library is ready.Solution: Use a
std::shared_ptrand initialize the object inside your application'ssetup()function rather than in a constructor or as a global static object.Example:
In
.h:class MyClass { static std::shared_ptr<ofxMidiOut> s_midiOut; };In
.cpp:std::shared_ptr<ofxMidiOut> MyClass::s_midiOut; void MyClass::setup() { if(s_midiOut == nullptr) { s_midiOut = std::shared_ptr<ofxMidiOut>(new ofxMidiOut("ofxMidi Client")); } }class MyClass { ... static std::shared_ptr<ofxMidiOut> s_midiOut; } std::shared_ptr<ofxMidiOut> MyClass::s_midiOut; // initialize somewhere else void MyClass::setup() { if(s_midiOut == NULL) { s_midiOut = std::shared_ptr<ofxMidiOut>(new ofxMidiOut("ofxMidi Client")); } }