1 //*****************************************// 2 // sysextest.cpp 3 // by Gary Scavone, 2003-2005. 4 // 5 // Simple program to test MIDI sysex sending and receiving. 6 // 7 //*****************************************// 8 9 #include <iostream> 10 #include <cstdlib> 11 #include <typeinfo> 12 #include "RtMidi.h" 13 14 void usage( void ) { 15 std::cout << "\nuseage: sysextest N\n"; 16 std::cout << " where N = length of sysex message to send / receive.\n\n"; 17 exit( 0 ); 18 } 19 20 // Platform-dependent sleep routines. 21 #if defined(WIN32) 22 #include <windows.h> 23 #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 24 #else // Unix variants 25 #include <unistd.h> 26 #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) 27 #endif 28 29 // This function should be embedded in a try/catch block in case of 30 // an exception. It offers the user a choice of MIDI ports to open. 31 // It returns false if there are no ports available. 32 bool chooseMidiPort( RtMidi *rtmidi ); 33 34 void mycallback( double deltatime, std::vector< unsigned char > *message, void * /*userData*/ ) 35 { 36 unsigned int nBytes = message->size(); 37 for ( unsigned int i=0; i<nBytes; i++ ) 38 std::cout << "Byte " << i << " = " << (int)message->at(i) << ", "; 39 if ( nBytes > 0 ) 40 std::cout << "stamp = " << deltatime << std::endl; 41 } 42 43 int main( int argc, char *argv[] ) 44 { 45 RtMidiOut *midiout = 0; 46 RtMidiIn *midiin = 0; 47 std::vector<unsigned char> message; 48 unsigned int i, nBytes; 49 50 // Minimal command-line check. 51 if ( argc != 2 ) usage(); 52 nBytes = (unsigned int) atoi( argv[1] ); 53 54 // RtMidiOut and RtMidiIn constructors 55 try { 56 midiout = new RtMidiOut(); 57 midiin = new RtMidiIn(); 58 } 59 catch ( RtMidiError &error ) { 60 error.printMessage(); 61 goto cleanup; 62 } 63 64 // Don't ignore sysex, timing, or active sensing messages. 65 midiin->ignoreTypes( false, true, true ); 66 67 try { 68 if ( chooseMidiPort( midiin ) == false ) goto cleanup; 69 if ( chooseMidiPort( midiout ) == false ) goto cleanup; 70 } 71 catch ( RtMidiError &error ) { 72 error.printMessage(); 73 goto cleanup; 74 } 75 76 midiin->setCallback( &mycallback ); 77 78 message.push_back( 0xF6 ); 79 midiout->sendMessage( &message ); 80 SLEEP( 500 ); // pause a little 81 82 // Create a long sysex message of numbered bytes and send it out ... twice. 83 for ( int n=0; n<2; n++ ) { 84 message.clear(); 85 message.push_back( 240 ); 86 for ( i=0; i<nBytes; i++ ) 87 message.push_back( i % 128 ); 88 message.push_back( 247 ); 89 midiout->sendMessage( &message ); 90 91 SLEEP( 500 ); // pause a little 92 } 93 94 // Clean up 95 cleanup: 96 delete midiout; 97 delete midiin; 98 99 return 0; 100 } 101 102 bool chooseMidiPort( RtMidi *rtmidi ) 103 { 104 bool isInput = false; 105 if ( typeid( *rtmidi ) == typeid( RtMidiIn ) ) 106 isInput = true; 107 108 if ( isInput ) 109 std::cout << "\nWould you like to open a virtual input port? [y/N] "; 110 else 111 std::cout << "\nWould you like to open a virtual output port? [y/N] "; 112 113 std::string keyHit; 114 std::getline( std::cin, keyHit ); 115 if ( keyHit == "y" ) { 116 rtmidi->openVirtualPort(); 117 return true; 118 } 119 120 std::string portName; 121 unsigned int i = 0, nPorts = rtmidi->getPortCount(); 122 if ( nPorts == 0 ) { 123 if ( isInput ) 124 std::cout << "No input ports available!" << std::endl; 125 else 126 std::cout << "No output ports available!" << std::endl; 127 return false; 128 } 129 130 if ( nPorts == 1 ) { 131 std::cout << "\nOpening " << rtmidi->getPortName() << std::endl; 132 } 133 else { 134 for ( i=0; i<nPorts; i++ ) { 135 portName = rtmidi->getPortName(i); 136 if ( isInput ) 137 std::cout << " Input port #" << i << ": " << portName << '\n'; 138 else 139 std::cout << " Output port #" << i << ": " << portName << '\n'; 140 } 141 142 do { 143 std::cout << "\nChoose a port number: "; 144 std::cin >> i; 145 } while ( i >= nPorts ); 146 } 147 148 std::cout << std::endl; 149 rtmidi->openPort( i ); 150 151 return true; 152 } 153