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