| 
					
				 | 
			
			
				@@ -8,7 +8,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     RtMidi: realtime MIDI i/o C++ classes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Copyright (c) 2003-2007 Gary P. Scavone 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Copyright (c) 2003-2009 Gary P. Scavone 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Permission is hereby granted, free of charge, to any person 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     obtaining a copy of this software and associated documentation files 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -35,7 +35,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /**********************************************************************/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// RtMidi: Version 1.0.7 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// RtMidi: Version 1.0.8 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "RtMidi.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <sstream> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -69,9 +69,9 @@ void RtMidi :: error( RtError::Type type ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //  Common RtMidiIn Definitions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //*********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-RtMidiIn :: RtMidiIn() : RtMidi() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+RtMidiIn :: RtMidiIn( const std::string clientName ) : RtMidi() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  this->initialize(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  this->initialize( clientName ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -144,9 +144,9 @@ double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //  Common RtMidiOut Definitions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //*********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-RtMidiOut :: RtMidiOut() : RtMidi() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+RtMidiOut :: RtMidiOut( const std::string clientName ) : RtMidi() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  this->initialize(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  this->initialize( clientName ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -187,20 +187,24 @@ void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (procRef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   CoreMidiData *apiData = static_cast<CoreMidiData *> (data->apiData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool continueSysex = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unsigned char status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unsigned short nBytes, iByte, size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unsigned long long time; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  RtMidiIn::MidiMessage message; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bool& continueSysex = data->continueSysex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  RtMidiIn::MidiMessage& message = data->message; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const MIDIPacket *packet = &list->packet[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for ( unsigned int i=0; i<list->numPackets; ++i ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // My interpretation of the CoreMIDI documentation: all message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // types, except sysex, are complete within a packet and there may 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // be several of them in a single packet.  Sysex messages can be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // broken across multiple packets but are bundled alone within a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // packet.  I'm assuming that sysex messages, if segmented, must 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // be complete within the same MIDIPacketList. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // broken across multiple packets and PacketLists but are bundled 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // alone within each packet (these packets do not contain other 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // message types).  If sysex messages are split across multiple 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // MIDIPacketLists, they must be handled by multiple calls to this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // function. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     nBytes = packet->length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( nBytes == 0 ) continue; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -220,12 +224,13 @@ void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     iByte = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( continueSysex ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // We have a continuing, segmented sysex message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if ( !(data->ignoreFlags & 0x01) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if ( !( data->ignoreFlags & 0x01 ) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // If we're not ignoring sysex messages, copy the entire packet. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for ( unsigned int j=0; j<nBytes; j++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           message.bytes.push_back( packet->data[j] ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if ( packet->data[nBytes] == 0xF7 ) continueSysex = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      continueSysex = packet->data[nBytes-1] != 0xF7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if ( !continueSysex ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // If not a continuing sysex message, invoke the user callback function or queue the message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if ( data->usingCallback && message.bytes.size() > 0 ) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -259,7 +264,7 @@ void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             iByte = nBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           else size = nBytes - iByte; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if ( packet->data[nBytes] == 0xF7 ) continueSysex = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          continueSysex =  packet->data[nBytes-1] != 0xF7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         else if ( status < 0xF3 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -311,11 +316,11 @@ void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: initialize( const std::string& clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set up our client. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MIDIClientRef client; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  OSStatus result = MIDIClientCreate( CFSTR("RtMidi Input Client"), NULL, NULL, &client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::initialize: error creating OS-X MIDI client object."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     error( RtError::DRIVER_ERROR ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -329,7 +334,7 @@ void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   inputData_.apiData = (void *) data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -352,7 +357,9 @@ void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MIDIPortRef port; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  OSStatus result = MIDIInputPortCreate( data->client, CFSTR("RtMidi MIDI Input Port"), midiInputCallback, (void *)&inputData_, &port ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OSStatus result = MIDIInputPortCreate( data->client,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         midiInputCallback, (void *)&inputData_, &port ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     MIDIClientDispose( data->client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::openPort: error creating OS-X MIDI input port."; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -479,11 +486,11 @@ std::string RtMidiOut :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return stringName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: initialize( const std::string& clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set up our client. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MIDIClientRef client; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  OSStatus result = MIDIClientCreate( CFSTR("RtMidi Output Client"), NULL, NULL, &client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::initialize: error creating OS-X MIDI client object."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     error( RtError::DRIVER_ERROR ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -496,7 +503,7 @@ void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apiData_ = (void *) data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -519,7 +526,9 @@ void RtMidiOut :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MIDIPortRef port; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  OSStatus result = MIDIOutputPortCreate( data->client, CFSTR("RtMidi Virtual MIDI Output Port"), &port ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OSStatus result = MIDIOutputPortCreate( data->client,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                          CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                          &port ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     MIDIClientDispose( data->client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::openPort: error creating OS-X MIDI output port."; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -588,33 +597,59 @@ RtMidiOut :: ~RtMidiOut() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // The CoreMidi documentation indicates a maximum PackList size of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 64K, so we may need to break long sysex messages into pieces and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // send via separate lists. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unsigned int nBytes = message->size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Pad the buffer for extra (unknown) structure data. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  Byte buffer[nBytes+32]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  MIDIPacketList *pktlist = (MIDIPacketList *) buffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  MIDIPacket *curPacket = MIDIPacketListInit( pktlist ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if ( nBytes == 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    errorString_ = "RtMidiOut::sendMessage: no data in message argument!";       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error( RtError::WARNING ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  MIDITimeStamp timeStamp = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  curPacket = MIDIPacketListAdd( pktlist, sizeof(buffer), curPacket, timeStamp, nBytes, &message->at(0) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if ( nBytes > 3 && ( message->at(0) != 0xF0 ) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    errorString_ = "RtMidiOut::sendMessage: message format problem ... not sysex but > 3 bytes?";       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error( RtError::WARNING ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  unsigned int packetBytes, bytesLeft = nBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  unsigned int messageIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  MIDITimeStamp timeStamp = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Send to any destinations that may have connected to us. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  OSStatus result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( data->endpoint ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    result = MIDIReceived( data->endpoint, pktlist ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      errorString_ = "RtMidiOut::sendMessage: error sending MIDI to virtual destinations."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      error( RtError::WARNING ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while ( bytesLeft > 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    packetBytes = ( bytesLeft > 32736 ) ? 32736 : bytesLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Byte buffer[packetBytes + 32]; // extra memory for other structure variables 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MIDIPacketList *packetList = (MIDIPacketList *) buffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MIDIPacket *curPacket = MIDIPacketListInit( packetList ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curPacket = MIDIPacketListAdd( packetList, packetBytes+32, curPacket, timeStamp, packetBytes, (const Byte *) &message->at( messageIndex ) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( !curPacket ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errorString_ = "RtMidiOut::sendMessage: could not allocate packet list";       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      error( RtError::DRIVER_ERROR ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    messageIndex += packetBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bytesLeft -= packetBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Send to any destinations that may have connected to us. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    OSStatus result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( data->endpoint ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      result = MIDIReceived( data->endpoint, packetList ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        errorString_ = "RtMidiOut::sendMessage: error sending MIDI to virtual destinations."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        error( RtError::WARNING ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // And send to an explicit destination port if we're connected. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    result = MIDISend( data->port, data->destinationId, pktlist ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      errorString_ = "RtMidiOut::sendMessage: error sending MIDI message to port."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      error( RtError::WARNING ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // And send to an explicit destination port if we're connected. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      result = MIDISend( data->port, data->destinationId, packetList ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if ( result != noErr ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        errorString_ = "RtMidiOut::sendMessage: error sending MIDI message to port."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        error( RtError::WARNING ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -713,7 +748,9 @@ extern "C" void *alsaMidiHandler( void *ptr ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // This is a bit weird, but we now have to decode an ALSA MIDI 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // event (back) into MIDI bytes.  We'll ignore non-MIDI types. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    message.bytes.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( !continueSysex ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      message.bytes.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     switch ( ev->type ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		case SND_SEQ_EVENT_PORT_SUBSCRIBED: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -723,8 +760,15 @@ extern "C" void *alsaMidiHandler( void *ptr ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if defined(__RTMIDI_DEBUG__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       std::cerr << "RtMidiIn::alsaMidiHandler: port connection has closed!\n"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      data->doInput = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // FIXME: this is called for all unsubscribe events, even ones 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //not related to this particular connection.  As it stands, I 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //see no data provided in the "source" and "dest" fields so 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //there is nothing we can do about this at this time. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // std::cout << "sender = " << ev->source.client << ", dest = " << ev->dest.port << std::endl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //data->doInput = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case SND_SEQ_EVENT_QFRAME: // MIDI time code 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -768,7 +812,7 @@ extern "C" void *alsaMidiHandler( void *ptr ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      continueSysex = ( ev->type == SND_SEQ_EVENT_SYSEX && message.bytes.back() != 0xF7 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if ( continueSysex ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -794,7 +838,7 @@ extern "C" void *alsaMidiHandler( void *ptr ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     snd_seq_free_event(ev); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( message.bytes.size() == 0 ) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ( data->usingCallback ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( data->usingCallback && !continueSysex ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       callback( message.timeStamp, &message.bytes, data->userData ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -813,10 +857,10 @@ extern "C" void *alsaMidiHandler( void *ptr ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: initialize( const std::string& clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set up the ALSA sequencer client. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	snd_seq_t *seq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_t *seq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( result < 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::initialize: error creating ALSA sequencer input client object."; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -824,7 +868,7 @@ void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set client name. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  snd_seq_set_client_name(seq, "RtMidi Input Client"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_set_client_name( seq, clientName.c_str() ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Save our api-specific connection information. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -860,7 +904,10 @@ unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		snd_seq_port_info_set_client( pinfo, client ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		snd_seq_port_info_set_port( pinfo, -1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if ( !PORT_TYPE( pinfo, type ) )  continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      unsigned int atyp = snd_seq_port_info_get_type( pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      unsigned int caps = snd_seq_port_info_get_capability( pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if ( ( caps & type ) != type ) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if ( count == portNumber ) return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       count++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -871,7 +918,7 @@ unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -913,7 +960,7 @@ void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     snd_seq_port_info_set_timestamping(pinfo, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     snd_seq_port_info_set_timestamp_real(pinfo, 1);     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    snd_seq_port_info_set_name(pinfo, "RtMidi Input"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    snd_seq_port_info_set_name(pinfo,  portName.c_str() ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     data->vport = snd_seq_create_port(data->seq, pinfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( data->vport < 0 ) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1049,12 +1096,20 @@ unsigned int RtMidiIn :: getPortCount() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 std::string RtMidiIn :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	snd_seq_port_info_t *pinfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	snd_seq_port_info_alloca( &pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_client_info_t *cinfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_port_info_t *pinfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_client_info_alloca( &cinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_port_info_alloca( &pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::string stringName = std::string( snd_seq_port_info_get_name( pinfo ) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int cnum = snd_seq_port_info_get_client( pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    snd_seq_get_any_client_info( data->seq, cnum, cinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    std::ostringstream os; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os << snd_seq_client_info_get_name( cinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os << ":"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os << snd_seq_port_info_get_port( pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    std::string stringName = os.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return stringName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1080,12 +1135,20 @@ unsigned int RtMidiOut :: getPortCount() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 std::string RtMidiOut :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	snd_seq_port_info_t *pinfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	snd_seq_port_info_alloca( &pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_client_info_t *cinfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_port_info_t *pinfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_client_info_alloca( &cinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_port_info_alloca( &pinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::string stringName = std::string( snd_seq_port_info_get_name( pinfo ) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int cnum = snd_seq_port_info_get_client(pinfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    snd_seq_get_any_client_info( data->seq, cnum, cinfo ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    std::ostringstream os; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os << snd_seq_client_info_get_name(cinfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os << ":"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os << snd_seq_port_info_get_port(pinfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    std::string stringName = os.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return stringName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1095,18 +1158,18 @@ std::string RtMidiOut :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: initialize( const std::string& clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set up the ALSA sequencer client. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	snd_seq_t *seq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_t *seq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int result = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( result < 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::initialize: error creating ALSA sequencer client object."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     error( RtError::DRIVER_ERROR ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set client name. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  snd_seq_set_client_name(seq, "RtMidi Output Client"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  snd_seq_set_client_name( seq, clientName.c_str() ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Save our api-specific connection information. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1131,7 +1194,7 @@ void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apiData_ = (void *) data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1161,7 +1224,7 @@ void RtMidiOut :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sender.client = snd_seq_client_id( data->seq ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( data->vport < 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                               SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                               SND_SEQ_PORT_TYPE_MIDI_GENERIC ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( data->vport < 0 ) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1423,7 +1486,7 @@ extern "C" void *irixMidiHandler( void *ptr ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: initialize( const std::string& /*clientName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Initialize the Irix MIDI system.  At the moment, we will not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // worry about a return value of zero (ports) because there is a 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1436,7 +1499,7 @@ void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   inputData_.apiData = (void *) data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: openPort( unsigned int portNumber, const std::string /*portName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1564,7 +1627,7 @@ std::string RtMidiOut :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return stringName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: initialize( const std::string& /*clientName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Initialize the Irix MIDI system.  At the moment, we will not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // worry about a return value of zero (ports) because there is a 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1576,7 +1639,7 @@ void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apiData_ = (void *) data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: openPort( unsigned int portNumber, const std::string /*portName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1754,21 +1817,31 @@ static void CALLBACK midiInputCallback( HMIDIOUT hmin, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     unsigned char *ptr = (unsigned char *) &midiMessage; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for ( int i=0; i<nBytes; i++ ) apiData->message.bytes.push_back( *ptr++ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  else if ( !(data->ignoreFlags & 0x01) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Sysex message and we're not ignoring it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    MIDIHDR *sysex = ( MIDIHDR *) midiMessage; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for ( int i=0; i<(int)sysex->dwBytesRecorded; i++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      apiData->message.bytes.push_back( sysex->lpData[i] ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else { // Sysex message ( MIM_LONGDATA ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MIDIHDR *sysex = ( MIDIHDR *) midiMessage;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( !( data->ignoreFlags & 0x01 ) ) {   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // Sysex message and we're not ignoring it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for ( int i=0; i<(int)sysex->dwBytesRecorded; i++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        apiData->message.bytes.push_back( sysex->lpData[i] ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // When the callback has to be unaffected (application closes),  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // it seems WinMM calls it with an empty sysex to de-queue the buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // If the buffer is requeued afer that message, the PC suddenly reboots 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // after one or two minutes (JB). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // The WinMM API requires that the sysex buffer be requeued after 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // input of each sysex message.  Even if we are ignoring sysex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // messages, we still need to requeue the buffer in case the user 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // decides to not ignore sysex messages in the future.  However, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // it seems that WinMM calls this function with an empty sysex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // buffer when an application closes and in this case, we should 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // avoid requeueing it, else the computer suddenly reboots after 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // one or two minutes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if ( apiData->sysexBuffer->dwBytesRecorded > 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //if ( sysex->dwBytesRecorded > 0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer, sizeof(MIDIHDR) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if ( result != MMSYSERR_NOERROR ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if ( data->ignoreFlags & 0x01 ) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( data->usingCallback ) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1783,13 +1856,11 @@ static void CALLBACK midiInputCallback( HMIDIOUT hmin, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Clear the vector for the next input message.  Note that doing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // this here allows our code to work for sysex messages which are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // segmented across multiple buffers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Clear the vector for the next input message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apiData->message.bytes.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: initialize( const std::string& /*clientName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // We'll issue a warning here if no devices are available but not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // throw an error since the user can plugin something later. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1806,7 +1877,7 @@ void RtMidiIn :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   data->message.bytes.clear();  // needs to be empty for first input message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiIn :: openPort( unsigned int portNumber, const std::string /*portName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1840,8 +1911,8 @@ void RtMidiIn :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Allocate and init the sysex buffer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   data->sysexBuffer = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->sysexBuffer->lpData = new char[1024]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->sysexBuffer->dwBufferLength = 1024; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  data->sysexBuffer->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  data->sysexBuffer->dwBufferLength = RT_SYSEX_BUFFER_SIZE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   data->sysexBuffer->dwFlags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   result = midiInPrepareHeader( data->inHandle, data->sysexBuffer, sizeof(MIDIHDR) ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1970,7 +2041,7 @@ std::string RtMidiOut :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return stringName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: initialize( const std::string& /*clientName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // We'll issue a warning here if no devices are available but not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // throw an error since the user can plug something in later. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1985,7 +2056,7 @@ void RtMidiOut :: initialize( void ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apiData_ = (void *) data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void RtMidiOut :: openPort( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void RtMidiOut :: openPort( unsigned int portNumber, const std::string /*portName*/ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( connected_ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; 
			 |