### Define Uninstall Target and PkgConfig Installation Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Creates a custom uninstall target and installs the pkg-config file to the library directory. ```cmake # Create uninstall target. add_custom_target(${RTMIDI_TARGETNAME_UNINSTALL} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/rtmidi.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) ``` -------------------------------- ### Install CMake Package Files Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Installs the generated CMake configuration and version files to the specified destination. ```cmake # Install package files install ( FILES "${CMAKE_CURRENT_BINARY_DIR}/rtmidi-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/rtmidi-config-version.cmake" DESTINATION "${RTMIDI_CMAKE_DESTINATION}" ) ``` -------------------------------- ### Implement MIDI I/O using the C API Source: https://context7.com/thestk/rtmidi/llms.txt Provides a complete example of using the C-style interface to list ports, set callbacks, and send MIDI messages. ```c #include #include "rtmidi_c.h" void midi_callback(double timestamp, const unsigned char *message, size_t messageSize, void *userData) { printf("Received %zu bytes, timestamp: %f\n", messageSize, timestamp); for (size_t i = 0; i < messageSize; i++) { printf(" Byte %zu: 0x%02X\n", i, message[i]); } } int main() { // Get version printf("RtMidi Version: %s\n", rtmidi_get_version()); // Get compiled APIs int numApis = rtmidi_get_compiled_api(NULL, 0); printf("Compiled APIs: %d\n", numApis); // Create MIDI input RtMidiInPtr midiin = rtmidi_in_create( RTMIDI_API_UNSPECIFIED, "MyCApp", 100 // Queue size ); if (!midiin->ok) { printf("Error creating MIDI input: %s\n", midiin->msg); return 1; } // Get port count unsigned int ports = rtmidi_get_port_count(midiin); printf("Input ports: %u\n", ports); // Get port names for (unsigned int i = 0; i < ports; i++) { char name[256]; int len = sizeof(name); rtmidi_get_port_name(midiin, i, name, &len); printf(" Port %u: %s\n", i, name); } if (ports > 0) { // Open port rtmidi_open_port(midiin, 0, "My Input Port"); // Set callback rtmidi_in_set_callback(midiin, midi_callback, NULL); // Configure message types rtmidi_in_ignore_types(midiin, false, true, true); printf("Listening... Press Enter to quit.\n"); getchar(); // Cleanup rtmidi_close_port(midiin); } rtmidi_in_free(midiin); // MIDI Output example RtMidiOutPtr midiout = rtmidi_out_create_default(); if (midiout->ok && rtmidi_get_port_count(midiout) > 0) { rtmidi_open_port(midiout, 0, "My Output Port"); // Send Note On unsigned char noteOn[] = {0x90, 64, 90}; rtmidi_out_send_message(midiout, noteOn, 3); rtmidi_close_port(midiout); } rtmidi_out_free(midiout); return 0; } ``` -------------------------------- ### MIDI Input with User Callback Example Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt This C++ example shows how to set up a user-defined callback function to process incoming MIDI messages. The callback is invoked automatically when a complete MIDI message is received. It's crucial to set the callback immediately after opening the port. ```cpp // cmidiin.cpp #include #include #include "RtMidi.h" void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData ) { unsigned int nBytes = message->size(); for ( unsigned int i=0; i 0 ) std::cout << "stamp = " << deltatime << std::endl; } int main() { RtMidiIn *midiin = new RtMidiIn(); // Check available ports. unsigned int nPorts = midiin->getPortCount(); if ( nPorts == 0 ) { std::cout << "No ports available!\n"; goto cleanup; } midiin->openPort( 0 ); // Set our callback function. This should be done immediately after // opening the port to avoid having incoming messages written to the // queue. midiin->setCallback( &mycallback ); // Don't ignore sysex, timing, or active sensing messages. midiin->ignoreTypes( false, false, false ); std::cout << "\nReading MIDI input ... press to quit.\n"; char input; std::cin.get(input); // Clean up cleanup: delete midiin; return 0; } ``` -------------------------------- ### MIDI Input Polling Example Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt This C++ snippet demonstrates how to poll for MIDI input messages from a specified port. It includes setting up an interrupt handler to gracefully exit the loop. Ensure RtMidi is installed and linked. ```cpp std::cout << "No ports available!\n"; goto cleanup; } midiin->openPort( 0 ); // Don't ignore sysex, timing, or active sensing messages. midiin->ignoreTypes( false, false, false ); // Install an interrupt handler function. done = false; (void) signal(SIGINT, finish); // Periodically check input queue. std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; while ( !done ) { stamp = midiin->getMessage( &message ); nBytes = message.size(); for ( i=0; i 0 ) std::cout << "stamp = " << stamp << std::endl; // Sleep for 10 milliseconds ... platform-dependent. SLEEP( 10 ); } // Clean up cleanup: delete midiin; return 0; } ``` -------------------------------- ### JACK MIDI Compilation Example Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Example compiler statement for linking RtMidi with the JACK MIDI API on Linux or macOS. This requires the __UNIX_JACK__ preprocessor definition and the 'jack' library. ```bash g++ -Wall -D__UNIX_JACK__ -o midiprobe midiprobe.cpp RtMidi.cpp -ljack ``` -------------------------------- ### Install RtMidi Targets and Headers Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Installs the RtMidi library targets (libraries, archives, runtime binaries) and public headers to their designated installation directories. It also exports targets for CMake's package management. ```cmake # Add install rule. install(TARGETS ${LIB_TARGETS} EXPORT RtMidiTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rtmidi) ``` -------------------------------- ### Mac CoreMIDI Compilation Example Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Example compiler statement for linking RtMidi with the CoreMIDI API on macOS. This requires the __MACOSX_CORE__ preprocessor definition and linking against the CoreMIDI, CoreAudio, and CoreFoundation frameworks. ```bash g++ -Wall -D__MACOSX_CORE__ -o midiprobe midiprobe.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation ``` -------------------------------- ### Linux ALSA Sequencer Compilation Example Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Example compiler statement for linking RtMidi with the ALSA Sequencer API on Linux. This requires the __LINUX_ALSA__ preprocessor definition and the 'asound' and 'pthread' libraries. ```bash g++ -Wall -D__LINUX_ALSA__ -o midiprobe midiprobe.cpp RtMidi.cpp -lasound -lpthread ``` -------------------------------- ### Set RtMidi Target Properties Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Configures versioning and header installation paths for the rtmidi library target. It sets the SOVERSION and VERSION properties, and defines the PUBLIC_HEADER property for install rules. ```cmake # Add headers destination for install rule. set_property(TARGET rtmidi PROPERTY PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/RtMidi.h" "${CMAKE_CURRENT_SOURCE_DIR}/rtmidi_c.h") set_target_properties(rtmidi PROPERTIES SOVERSION ${SO_VER} VERSION ${FULL_VER}) ``` -------------------------------- ### Configure RtMidi Include Directories Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Sets the include directories for the rtmidi target. It specifies private include paths and public interface include paths for both build and install trees. ```cmake # Set include paths, populate target interface. target_include_directories(rtmidi PRIVATE ${INCDIRS} PUBLIC $ $) ``` -------------------------------- ### Get Compiled and Current APIs in RtMidi Source: https://context7.com/thestk/rtmidi/llms.txt Queries which MIDI APIs are compiled into the library and which API a specific instance is using. Useful for systems with multiple APIs available. Ensure RtMidi.h is included. ```cpp #include "RtMidi.h" #include #include #include int main() { // Get list of compiled APIs std::vector apis; RtMidi::getCompiledApi(apis); std::cout << "RtMidi Version: " << RtMidi::getVersion() << std::endl; std::cout << "\nCompiled APIs (" << apis.size() << "):" << std::endl; for (size_t i = 0; i < apis.size(); i++) { // Get short name (for identification) std::string name = RtMidi::getApiName(apis[i]); // Get display name (human readable) std::string displayName = RtMidi::getApiDisplayName(apis[i]); std::cout << " " << name << " (" << displayName << ")" << std::endl; } // Look up API by name RtMidi::Api api = RtMidi::getCompiledApiByName("alsa"); if (api != RtMidi::UNSPECIFIED) { std::cout << "\nFound ALSA API" << std::endl; } // Create instance with specific API try { // Use first available API if (apis.size() > 0) { RtMidiIn *midiin = new RtMidiIn(apis[0]); std::cout << "\nCreated RtMidiIn with API: " << RtMidi::getApiDisplayName(midiin->getCurrentApi()) << std::endl; delete midiin; } } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Configure RtMidi Uninstall Target Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Configures the uninstall target for RtMidi by generating a CMake script that handles the removal of installed files. This ensures a clean uninstallation process. ```cmake # Configure uninstall target. configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/RtMidiConfigUninstall.cmake.in" "${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake" @ONLY) ``` -------------------------------- ### Send MIDI Messages Source: https://context7.com/thestk/rtmidi/llms.txt Sends MIDI messages through an open output port using either a std::vector or a raw byte array. Includes examples for Program Change, Control Change, Note On, Note Off, and System Exclusive messages. A platform-dependent sleep function is used to control message timing. ```cpp #include "RtMidi.h" #include #include // Platform-dependent sleep #ifdef _WIN32 #include #define SLEEP(ms) Sleep(ms) #else #include #define SLEEP(ms) usleep(ms * 1000) #endif int main() { try { RtMidiOut *midiout = new RtMidiOut(); if (midiout->getPortCount() == 0) { std::cout << "No output ports available!" << std::endl; delete midiout; return 1; } midiout->openPort(0); std::vector message; // Program Change: Channel 1, Program 5 message.push_back(192); // 0xC0 = Program Change, Channel 1 message.push_back(5); // Program number midiout->sendMessage(&message); // Control Change: Channel 1, Volume (CC 7), Value 100 message.clear(); message.push_back(176); // 0xB0 = Control Change, Channel 1 message.push_back(7); // Controller number (volume) message.push_back(100); // Value midiout->sendMessage(&message); // Note On: Channel 1, Note 64 (E4), Velocity 90 message[0] = 144; // 0x90 = Note On, Channel 1 message[1] = 64; // Note number message[2] = 90; // Velocity midiout->sendMessage(&message); SLEEP(500); // Hold note for 500ms // Note Off: Channel 1, Note 64, Velocity 40 message[0] = 128; // 0x80 = Note Off, Channel 1 message[1] = 64; // Note number message[2] = 40; // Release velocity midiout->sendMessage(&message); // Alternative: Send using raw pointer unsigned char sysex[] = {0xF0, 0x7E, 0x00, 0x06, 0x01, 0xF7}; midiout->sendMessage(sysex, sizeof(sysex)); midiout->closePort(); delete midiout; std::cout << "Messages sent successfully" << std::endl; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Export RtMidi CMake Targets Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Exports the RtMidi library targets for use in other CMake projects. This includes configurations for both the build tree and the install tree, using the RtMidi:: namespace. ```cmake # Store the package in the user registry. export(PACKAGE RtMidi) # Set installation path for CMake files. set(RTMIDI_CMAKE_DESTINATION share/rtmidi) # Export library target (build-tree). export(EXPORT RtMidiTargets NAMESPACE RtMidi::) # Export library target (install-tree). install(EXPORT RtMidiTargets DESTINATION ${RTMIDI_CMAKE_DESTINATION} NAMESPACE RtMidi::) ``` -------------------------------- ### Configure Client and Port Names in C++ Source: https://context7.com/thestk/rtmidi/llms.txt Demonstrates setting client names during construction and updating port names dynamically. Supported specifically on ALSA and JACK backends. ```cpp #include "RtMidi.h" #include int main() { try { RtMidiIn *midiin = new RtMidiIn( RtMidi::UNSPECIFIED, "MyApp Input Client" // Client name set in constructor ); RtMidiOut *midiout = new RtMidiOut( RtMidi::UNSPECIFIED, "MyApp Output Client" ); // Can also change client name after construction (ALSA/JACK) midiin->setClientName("Updated Input Client"); midiout->setClientName("Updated Output Client"); if (midiin->getPortCount() > 0) { midiin->openPort(0, "Keyboard Input"); // Change port name after opening (ALSA/JACK) midiin->setPortName("Main Keyboard"); } if (midiout->getPortCount() > 0) { midiout->openPort(0, "Synth Output"); midiout->setPortName("Primary Synth"); } std::cout << "Client and port names configured" << std::endl; delete midiin; delete midiout; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Initialize RtMidiOut Source: https://context7.com/thestk/rtmidi/llms.txt Creates a MIDI output instance. Automatically establishes connections with the underlying system MIDI framework. ```cpp #include "RtMidi.h" #include int main() { try { // Default constructor RtMidiOut *midiout = new RtMidiOut(); // Or specify API and client name RtMidiOut *midiout2 = new RtMidiOut( RtMidi::MACOSX_CORE, // API to use "MyOutputClient" // Client name ); std::cout << "RtMidiOut created successfully" << std::endl; delete midiout; delete midiout2; } catch (RtMidiError &error) { error.printMessage(); return 1; } return 0; } ``` -------------------------------- ### openVirtualPort - Creating Virtual Ports Source: https://context7.com/thestk/rtmidi/llms.txt Creates a virtual MIDI port that other software can connect to. Supported on ALSA, JACK, and CoreMIDI only. ```APIDOC ## openVirtualPort ### Description Creates a virtual MIDI port that other software can connect to. Supported on ALSA, JACK, and CoreMIDI only. ### Method Not explicitly defined, but implied to be a method of RtMidiIn or RtMidiOut classes. ### Endpoint N/A (This is a library function, not a network endpoint) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp RtMidiIn *midiin = new RtMidiIn(); midiin->openVirtualPort("My Virtual Input"); ``` ### Response #### Success Response (200) Indicates successful creation of the virtual port. No explicit return value mentioned. #### Response Example N/A ``` -------------------------------- ### Initialize RtMidiIn Source: https://context7.com/thestk/rtmidi/llms.txt Creates a MIDI input instance. Supports optional API selection, custom client names, and queue size configuration. ```cpp #include "RtMidi.h" #include int main() { try { // Default constructor - auto-selects best API RtMidiIn *midiin = new RtMidiIn(); // Or specify API, client name, and queue size RtMidiIn *midiin2 = new RtMidiIn( RtMidi::LINUX_ALSA, // API to use "MyMidiClient", // Client name 200 // Queue size limit ); std::cout << "RtMidiIn created successfully" << std::endl; std::cout << "Current API: " << midiin->getCurrentApi() << std::endl; delete midiin; delete midiin2; } catch (RtMidiError &error) { error.printMessage(); return 1; } return 0; } ``` -------------------------------- ### RtMidiOut Constructor Source: https://context7.com/thestk/rtmidi/llms.txt Creates a MIDI output instance. You can use the default constructor or specify the API and client name. ```APIDOC ## RtMidiOut Constructor ### Description Creates a MIDI output instance with optional API selection and client name. Automatically establishes connections with the underlying MIDI system. ### Method Constructor ### Endpoint N/A (Class Constructor) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp #include "RtMidi.h" #include int main() { try { // Default constructor RtMidiOut *midiout = new RtMidiOut(); // Or specify API and client name RtMidiOut *midiout2 = new RtMidiOut( RtMidi::MACOSX_CORE, // API to use "MyOutputClient" // Client name ); std::cout << "RtMidiOut created successfully" << std::endl; delete midiout; delete midiout2; } catch (RtMidiError &error) { error.printMessage(); return 1; } return 0; } ``` ### Response #### Success Response (Constructor) N/A (Constructor does not return a value directly, but initializes an object) #### Response Example N/A ``` -------------------------------- ### Implement MIDI Thru with RtMidi Source: https://context7.com/thestk/rtmidi/llms.txt Demonstrates receiving MIDI messages on an input port and forwarding them to an output port using a callback function. Requires linking against RtMidi and handling RtMidiError exceptions. ```cpp #include "RtMidi.h" #include #include bool running = true; RtMidiOut *midiout = nullptr; void signalHandler(int) { running = false; } void midiThruCallback(double deltatime, std::vector *message, void *userData) { // Forward message to output if (midiout && message->size() > 0) { midiout->sendMessage(message); // Print what we forwarded std::cout << "Forwarded: "; for (size_t i = 0; i < message->size(); i++) { std::cout << std::hex << (int)(*message)[i] << " "; } std::cout << std::dec << std::endl; } } int main() { RtMidiIn *midiin = nullptr; try { // Create instances midiin = new RtMidiIn(); midiout = new RtMidiOut(); // List available ports std::cout << "Input ports:" << std::endl; for (unsigned int i = 0; i < midiin->getPortCount(); i++) { std::cout << " " << i << ": " << midiin->getPortName(i) << std::endl; } std::cout << "\nOutput ports:" << std::endl; for (unsigned int i = 0; i < midiout->getPortCount(); i++) { std::cout << " " << i << ": " << midiout->getPortName(i) << std::endl; } if (midiin->getPortCount() == 0 || midiout->getPortCount() == 0) { std::cout << "Insufficient MIDI ports!" << std::endl; goto cleanup; } // Select ports unsigned int inPort, outPort; std::cout << "\nSelect input port: "; std::cin >> inPort; std::cout << "Select output port: "; std::cin >> outPort; // Open ports midiin->openPort(inPort, "MIDI Thru Input"); midiout->openPort(outPort, "MIDI Thru Output"); // Set up callback for MIDI thru midiin->setCallback(&midiThruCallback); midiin->ignoreTypes(false, false, false); // Run until interrupted signal(SIGINT, signalHandler); std::cout << "\nMIDI Thru active. Press Ctrl-C to quit." << std::endl; while (running) { #ifdef _WIN32 Sleep(100); #else usleep(100000); #endif } } catch (RtMidiError &error) { error.printMessage(); } cleanup: delete midiin; delete midiout; midiout = nullptr; std::cout << "\nMIDI Thru stopped." << std::endl; return 0; } ``` -------------------------------- ### Initialize RtMidi Objects Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Demonstrates the basic construction and destruction of RtMidiIn and RtMidiOut objects within a try/catch block. ```cpp #include #include "RtMidi.h" int main() { RtMidiIn *midiin = 0; RtMidiOut *midiout = 0; // RtMidiIn constructor try { midiin = new RtMidiIn(); } catch ( RtMidiError &error ) { error.printMessage(); exit( EXIT_FAILURE ); } // RtMidiOut constructor try { midiout = new RtMidiOut(); } catch ( RtMidiError &error ) { error.printMessage(); exit( EXIT_FAILURE ); } // Clean up delete midiin; delete midiout; return 0; } ``` -------------------------------- ### RtMidiIn Constructor Source: https://context7.com/thestk/rtmidi/llms.txt Creates a MIDI input instance. You can use the default constructor for auto-API selection or specify the API, client name, and queue size limit. ```APIDOC ## RtMidiIn Constructor ### Description Creates a MIDI input instance with optional API selection, client name, and queue size limit. The default queue size is 1024 messages. ### Method Constructor ### Endpoint N/A (Class Constructor) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp #include "RtMidi.h" #include int main() { try { // Default constructor - auto-selects best API RtMidiIn *midiin = new RtMidiIn(); // Or specify API, client name, and queue size RtMidiIn *midiin2 = new RtMidiIn( RtMidi::LINUX_ALSA, // API to use "MyMidiClient", // Client name 200 // Queue size limit ); std::cout << "RtMidiIn created successfully" << std::endl; std::cout << "Current API: " << midiin->getCurrentApi() << std::endl; delete midiin; delete midiin2; } catch (RtMidiError &error) { error.printMessage(); return 1; } return 0; } ``` ### Response #### Success Response (Constructor) N/A (Constructor does not return a value directly, but initializes an object) #### Response Example N/A ``` -------------------------------- ### Create Virtual MIDI Ports Source: https://context7.com/thestk/rtmidi/llms.txt Creates virtual MIDI input and output ports that can be used for inter-application MIDI communication. Note that isPortOpen() returns false for virtual ports. These ports remain open until the RtMidiIn/RtMidiOut objects are deleted. ```cpp #include "RtMidi.h" #include int main() { try { RtMidiIn *midiin = new RtMidiIn(); RtMidiOut *midiout = new RtMidiOut(); // Create virtual input port - other apps can send MIDI to this midiin->openVirtualPort("My Virtual Input"); std::cout << "Virtual input port created" << std::endl; // Create virtual output port - other apps can receive from this midiout->openVirtualPort("My Virtual Output"); std::cout << "Virtual output port created" << std::endl; // Virtual ports stay open until closed or object is deleted // Note: isPortOpen() returns false for virtual ports std::cout << "Press Enter to exit..." << std::endl; std::cin.get(); delete midiin; delete midiout; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Generate CMake Package Files Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Configures and writes the package version and configuration files required for CMake integration. ```cmake # Set up CMake package include(CMakePackageConfigHelpers) # Write cmake package version file write_basic_package_version_file( rtmidi-config-version.cmake VERSION ${FULL_VER} COMPATIBILITY SameMajorVersion ) string(REPLACE ";" "\n" package_dependencies "${PACKAGE_DEPENDENCIES}") # Write cmake package config file configure_package_config_file ( cmake/rtmidi-config.cmake.in rtmidi-config.cmake INSTALL_DESTINATION "${RTMIDI_CMAKE_DESTINATION}" ) ``` -------------------------------- ### Probe MIDI Ports Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Shows how to query the system for available MIDI input ports using the getPortCount method. ```cpp // midiprobe.cpp #include #include #include "RtMidi.h" int main() { RtMidiIn *midiin = 0; RtMidiOut *midiout = 0; // RtMidiIn constructor try { midiin = new RtMidiIn(); } catch ( RtMidiError &error ) { error.printMessage(); exit( EXIT_FAILURE ); } // Check inputs. unsigned int nPorts = midiin->getPortCount(); ``` -------------------------------- ### Port Enumeration (getPortCount / getPortName) Source: https://context7.com/thestk/rtmidi/llms.txt Queries available MIDI ports for input and output. Port names are returned as UTF-8 encoded strings. ```APIDOC ## getPortCount / getPortName - Port Enumeration ### Description Queries available MIDI ports. Port enumeration is system-specific and changes when devices are plugged/unplugged. Port names are returned as UTF-8 encoded strings. ### Method `getPortCount()`: Returns the number of available MIDI ports. `getPortName(unsigned int portIndex)`: Returns the name of the MIDI port at the specified index. ### Endpoint N/A (Class Methods) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp #include "RtMidi.h" #include int main() { try { RtMidiIn *midiin = new RtMidiIn(); RtMidiOut *midiout = new RtMidiOut(); // Enumerate input ports unsigned int nInputPorts = midiin->getPortCount(); std::cout << "MIDI Input Ports (" << nInputPorts << "):\n"; for (unsigned int i = 0; i < nInputPorts; i++) { std::string portName = midiin->getPortName(i); std::cout << " Port #" << i << ": " << portName << std::endl; } // Enumerate output ports unsigned int nOutputPorts = midiout->getPortCount(); std::cout << "\nMIDI Output Ports (" << nOutputPorts << "):\n"; for (unsigned int i = 0; i < nOutputPorts; i++) { std::string portName = midiout->getPortName(i); std::cout << " Port #" << i << ": " << portName << std::endl; } delete midiin; delete midiout; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` ### Response #### Success Response (200) - **nInputPorts** (unsigned int) - The number of available MIDI input ports. - **nOutputPorts** (unsigned int) - The number of available MIDI output ports. - **portName** (std::string) - The UTF-8 encoded name of the MIDI port. #### Response Example ``` MIDI Input Ports (2): Port #0: Built-in MIDI Keyboard Port #1: External MIDI Interface MIDI Output Ports (1): Port #0: Built-in MIDI Synthesizer ``` ``` -------------------------------- ### Send MIDI Messages with RtMidiOut Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Demonstrates opening a MIDI output port and sending various MIDI messages using a std::vector container. ```cpp // midiout.cpp #include #include #include "RtMidi.h" int main() { RtMidiOut *midiout = new RtMidiOut(); std::vector message; // Check available ports. unsigned int nPorts = midiout->getPortCount(); if ( nPorts == 0 ) { std::cout << "No ports available!\n"; goto cleanup; } // Open first available port. midiout->openPort( 0 ); // Send out a series of MIDI messages. // Program change: 192, 5 message.push_back( 192 ); message.push_back( 5 ); midiout->sendMessage( &message ); // Control Change: 176, 7, 100 (volume) message[0] = 176; message[1] = 7; message.push_back( 100 ); midiout->sendMessage( &message ); // Note On: 144, 64, 90 message[0] = 144; message[1] = 64; message[2] = 90; midiout->sendMessage( &message ); SLEEP( 500 ); // Platform-dependent ... see example in tests directory. // Note Off: 128, 64, 40 message[0] = 128; message[1] = 64; message[2] = 40; midiout->sendMessage( &message ); // Clean up cleanup: delete midiout; return 0; } ``` -------------------------------- ### Link Libraries to Target Source: https://github.com/thestk/rtmidi/blob/master/android/app/src/main/cpp/CMakeLists.txt Links the 'midireader' library with the NDK's log library, the 'amidi' library, and the 'nativehelper' library. This makes their functions available to your code. ```cmake target_link_libraries( # Specifies the target library. midireader # Links the target library to the log library # included in the NDK. ${log-lib} amidi nativehelper) ``` -------------------------------- ### Enumerate MIDI Ports Source: https://context7.com/thestk/rtmidi/llms.txt Queries available MIDI input and output ports. Port names are returned as UTF-8 strings and may change dynamically based on hardware state. ```cpp #include "RtMidi.h" #include int main() { try { RtMidiIn *midiin = new RtMidiIn(); RtMidiOut *midiout = new RtMidiOut(); // Enumerate input ports unsigned int nInputPorts = midiin->getPortCount(); std::cout << "MIDI Input Ports (" << nInputPorts << "):" << std::endl; for (unsigned int i = 0; i < nInputPorts; i++) { std::string portName = midiin->getPortName(i); std::cout << " Port #" << i << ": " << portName << std::endl; } // Enumerate output ports unsigned int nOutputPorts = midiout->getPortCount(); std::cout << "\nMIDI Output Ports (" << nOutputPorts << "):" << std::endl; for (unsigned int i = 0; i < nOutputPorts; i++) { std::string portName = midiout->getPortName(i); std::cout << " Port #" << i << ": " << portName << std::endl; } delete midiin; delete midiout; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Register MIDI Input Callback with setCallback Source: https://context7.com/thestk/rtmidi/llms.txt Use setCallback to register a function that is invoked immediately upon receiving MIDI messages. This is recommended over polling with getMessage to avoid messages going to the queue. ```cpp #include "RtMidi.h" #include // Callback function signature: (deltatime, message, userData) void midiCallback(double deltatime, std::vector *message, void *userData) { // Access custom data passed to callback int *messageCount = static_cast(userData); (*messageCount)++; std::cout << "Message #" << *messageCount << ": "; for (size_t i = 0; i < message->size(); i++) { std::cout << "0x" << std::hex << (int)message->at(i) << " "; } std::cout << std::dec << "delta=" << deltatime << "s" << std::endl; } int main() { try { RtMidiIn *midiin = new RtMidiIn(); int messageCount = 0; if (midiin->getPortCount() == 0) { std::cout << "No input ports available!" << std::endl; delete midiin; return 1; } midiin->openPort(0); // Set callback immediately after opening port midiin->setCallback(&midiCallback, &messageCount); // Configure which message types to receive midiin->ignoreTypes(false, false, false); // Receive all types std::cout << "Listening for MIDI... Press Enter to quit." << std::endl; std::cin.get(); // Cancel callback before cleanup midiin->cancelCallback(); std::cout << "Received " << messageCount << " messages total." << std::endl; midiin->closePort(); delete midiin; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Configure RtMidi Testing Options Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Sets up the option for building test programs, defaulting to ON. It also ensures RTMIDI_BUILD_TESTING is set based on the global BUILD_TESTING variable if not explicitly defined. ```cmake # Add tests if requested. option(RTMIDI_BUILD_TESTING "Build test programs" ON) if (NOT DEFINED RTMIDI_BUILD_TESTING OR RTMIDI_BUILD_TESTING STREQUAL "") set(RTMIDI_BUILD_TESTING ${BUILD_TESTING}) endif() ``` -------------------------------- ### Enumerate MIDI Ports Source: https://github.com/thestk/rtmidi/blob/master/doc/doxygen/tutorial.txt Iterate through available MIDI input and output ports. Port numbers should be verified immediately before opening as they are system-specific and can change. ```cpp std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n"; std::string portName; for ( unsigned int i=0; igetPortName(i); } catch ( RtMidiError &error ) { error.printMessage(); goto cleanup; } std::cout << " Input Port #" << i+1 << ": " << portName << '\n'; } // RtMidiOut constructor try { midiout = new RtMidiOut(); } catch ( RtMidiError &error ) { error.printMessage(); exit( EXIT_FAILURE ); } // Check outputs. nPorts = midiout->getPortCount(); std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n"; for ( unsigned int i=0; igetPortName(i); } catch (RtMidiError &error) { error.printMessage(); goto cleanup; } std::cout << " Output Port #" << i+1 << ": " << portName << '\n'; } std::cout << '\n'; // Clean up cleanup: delete midiin; delete midiout; return 0; } ``` -------------------------------- ### Generate RtMidi PkgConfig File Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Configures and generates the rtmidi.pc file, which is used by pkg-config to provide build information for RtMidi. It uses variables like CMAKE_INSTALL_PREFIX and various library/API definitions. ```cmake # Message string(REPLACE ";" " " apilist "${API_LIST}") message(STATUS "Compiling with support for: ${apilist}") # PkgConfig file string(REPLACE ";" " " req "${PKGCONFIG_REQUIRES}") string(REPLACE ";" " " req_libs "${LIBS_REQUIRES}") string(REPLACE ";" " " api "${API_DEFS}") set(prefix ${CMAKE_INSTALL_PREFIX}) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/rtmidi.pc.in" "rtmidi.pc" @ONLY) ``` -------------------------------- ### Open MIDI Ports Source: https://context7.com/thestk/rtmidi/llms.txt Opens the first available input and output MIDI ports. Ensure ports are available before attempting to open them. Ports are closed automatically when the RtMidiIn/RtMidiOut objects are deleted. ```cpp #include "RtMidi.h" #include int main() { try { RtMidiIn *midiin = new RtMidiIn(); RtMidiOut *midiout = new RtMidiOut(); // Check for available ports if (midiin->getPortCount() == 0 || midiout->getPortCount() == 0) { std::cout << "No MIDI ports available!" << std::endl; delete midiin; delete midiout; return 1; } // Open first available input port midiin->openPort(0, "My MIDI Input"); std::cout << "Opened input port: " << midiin->getPortName(0) << std::endl; // Open first available output port midiout->openPort(0, "My MIDI Output"); std::cout << "Opened output port: " << midiout->getPortName(0) << std::endl; // Check if ports are open if (midiin->isPortOpen()) { std::cout << "Input port is open" << std::endl; } // Close ports when done midiin->closePort(); midiout->closePort(); delete midiin; delete midiout; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### Configure Android AMIDI API Source: https://github.com/thestk/rtmidi/blob/master/CMakeLists.txt Enables the Android AMIDI API by setting necessary flags and finding required packages like JNI and log. This configuration is conditional on RTMIDI_API_AMIDI being defined. ```cmake if(RTMIDI_API_AMIDI) set(NEED_PTHREAD ON) set(JAVA_INCLUDE_PATH2 NotNeeded) set(JAVA_AWT_INCLUDE_PATH NotNeeded) find_package(JNI) # find_library(ALOG_LIB log android) list(APPEND API_DEFS "-D__AMIDI__") list(APPEND API_LIST "amidi") list(APPEND LINKLIBS log ${JNI_LIBRARIES} amidi) endif() ``` -------------------------------- ### Configure Input Buffer Size in RtMidi Source: https://context7.com/thestk/rtmidi/llms.txt Sets the buffer size and count for incoming MIDI messages. Primarily useful for Windows MM backend when expecting large SysEx messages. Must be called before openPort(). ```cpp #include "RtMidi.h" #include int main() { try { RtMidiIn *midiin = new RtMidiIn(); // Configure for large SysEx messages // Default is 1024 bytes with 4 buffers midiin->setBufferSize( 8192, // Buffer size in bytes 8 // Number of buffers ); // Must call before openPort() if (midiin->getPortCount() > 0) { midiin->openPort(0); // Now ready to receive large SysEx messages midiin->ignoreTypes(false, true, true); std::cout << "Configured for large SysEx reception" << std::endl; midiin->closePort(); } delete midiin; } catch (RtMidiError &error) { error.printMessage(); } return 0; } ``` -------------------------------- ### openPort - Opening a MIDI Port Source: https://context7.com/thestk/rtmidi/llms.txt Opens a connection to a specific MIDI port by its enumeration number. An optional port name can be specified for the application. ```APIDOC ## openPort ### Description Opens a connection to a specific MIDI port by its enumeration number. An optional port name can be specified for the application. ### Method Not explicitly defined, but implied to be a method of RtMidiIn or RtMidiOut classes. ### Endpoint N/A (This is a library function, not a network endpoint) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp RtMidiIn *midiin = new RtMidiIn(); midiin->openPort(0, "My MIDI Input"); ``` ### Response #### Success Response (200) Indicates successful opening of the port. No explicit return value mentioned, but subsequent calls like `isPortOpen()` would reflect the status. #### Response Example N/A ``` -------------------------------- ### Configure RtMidi C++ Module Target Source: https://github.com/thestk/rtmidi/blob/master/modules/CMakeLists.txt Sets up a C++ module target for RtMidi. Ensure C++20 is enabled for module support. ```cmake cmake_minimum_required(VERSION 3.28) add_library(rtmidi_modules) set(RTMIDI_MODULES RtMidi.cppm ) if(NOT COMMAND configure_cpp_module_target) function(configure_cpp_module_target target) target_sources(${target} PUBLIC FILE_SET CXX_MODULES FILES ${RTMIDI_MODULES}) endfunction() endif() if(RTMIDI_USE_NAMESPACE) target_compile_definitions(rtmidi_modules PRIVATE RTMIDI_USE_NAMESPACE) endif() configure_cpp_module_target(rtmidi_modules) target_link_libraries(rtmidi_modules PUBLIC rtmidi ) target_include_directories(rtmidi_modules PRIVATE ${PROJECT_SOURCE_DIR} ) target_compile_features(rtmidi_modules PUBLIC cxx_std_20) ```