Version 4.3.0

This commit is contained in:
Gary Scavone
2009-03-24 23:02:15 -04:00
committed by Stephen Sinclair
parent 2cbce2d8bd
commit 27d9b79dc7
271 changed files with 22219 additions and 8834 deletions

View File

@@ -35,7 +35,7 @@
*/
/**********************************************************************/
// RtMidi: Version 1.0.4, 14 October 2005
// RtMidi: Version 1.0.5, in development
#include "RtMidi.h"
#include <sstream>
@@ -383,13 +383,15 @@ void RtMidiIn :: openPort( unsigned int portNumber )
connected_ = true;
}
void RtMidiIn :: openVirtualPort()
void RtMidiIn :: openVirtualPort( const std::string portName )
{
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
// Create a virtual MIDI input destination.
MIDIEndpointRef endpoint;
OSStatus result = MIDIDestinationCreate( data->client, CFSTR("RtMidi Input"), midiInputCallback, (void *)&inputData_, &endpoint );
OSStatus result = MIDIDestinationCreate( data->client,
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
midiInputCallback, (void *)&inputData_, &endpoint );
if ( result != noErr ) {
errorString_ = "RtMidiIn::openVirtualPort: error creating virtual OS-X MIDI destination.";
error( RtError::DRIVER_ERROR );
@@ -548,7 +550,7 @@ void RtMidiOut :: closePort( void )
}
}
void RtMidiOut :: openVirtualPort()
void RtMidiOut :: openVirtualPort( std::string portName )
{
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
@@ -560,7 +562,9 @@ void RtMidiOut :: openVirtualPort()
// Create a virtual MIDI output source.
MIDIEndpointRef endpoint;
OSStatus result = MIDISourceCreate( data->client, CFSTR("RtMidi Output"), &endpoint );
OSStatus result = MIDISourceCreate( data->client,
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
&endpoint );
if ( result != noErr ) {
errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source.";
error( RtError::DRIVER_ERROR );
@@ -957,7 +961,7 @@ void RtMidiIn :: openPort( unsigned int portNumber )
connected_ = true;
}
void RtMidiIn :: openVirtualPort()
void RtMidiIn :: openVirtualPort( std::string portName )
{
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
if ( data->vport < 0 ) {
@@ -973,7 +977,7 @@ void RtMidiIn :: openVirtualPort()
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 ) {
@@ -1195,11 +1199,11 @@ void RtMidiOut :: closePort( void )
}
}
void RtMidiOut :: openVirtualPort()
void RtMidiOut :: openVirtualPort( std::string portName )
{
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
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 );
@@ -1484,7 +1488,7 @@ void RtMidiIn :: openPort( unsigned int portNumber )
connected_ = true;
}
void RtMidiIn :: openVirtualPort()
void RtMidiIn :: openVirtualPort( std::string portName )
{
// This function cannot be implemented for the Irix MIDI API.
errorString_ = "RtMidiIn::openVirtualPort: cannot be implemented in Irix MIDI API!";
@@ -1617,7 +1621,7 @@ void RtMidiOut :: closePort( void )
}
}
void RtMidiOut :: openVirtualPort()
void RtMidiOut :: openVirtualPort( std::string portName )
{
// This function cannot be implemented for the Irix MIDI API.
errorString_ = "RtMidiOut::openVirtualPort: cannot be implemented in Irix MIDI API!";
@@ -1676,6 +1680,8 @@ void RtMidiOut :: sendMessage( std::vector<unsigned char> *message )
// API information deciphered from:
// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp
// Thanks to Jean-Baptiste Berruchon for the sysex code.
#if defined(__WINDOWS_MM__)
// The Windows MM API is based on the use of a callback function for
@@ -1693,8 +1699,11 @@ struct WinMidiData {
HMIDIOUT outHandle; // Handle to Midi Output Device
DWORD lastTime;
RtMidiIn::MidiMessage message;
LPMIDIHDR sysexBuffer;
};
#define RT_SYSEX_BUFFER_SIZE 1024
//*********************************************************************//
// API: Windows MM
// Class Definitions: RtMidiIn
@@ -1748,11 +1757,21 @@ 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 { // Sysex message
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] );
if ( apiData->message.bytes.back() != 0xF7 ) return;
// 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).
if ( apiData->sysexBuffer->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->usingCallback ) {
@@ -1822,6 +1841,27 @@ void RtMidiIn :: openPort( unsigned int portNumber )
error( RtError::DRIVER_ERROR );
}
// 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->dwFlags = 0;
result = midiInPrepareHeader( data->inHandle, data->sysexBuffer, sizeof(MIDIHDR) );
if ( result != MMSYSERR_NOERROR ) {
midiInClose( data->inHandle );
errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (PrepareHeader).";
error( RtError::DRIVER_ERROR );
}
// Register the buffer.
result = midiInAddBuffer( data->inHandle, data->sysexBuffer, sizeof(MIDIHDR) );
if ( result != MMSYSERR_NOERROR ) {
midiInClose( data->inHandle );
errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (AddBuffer).";
error( RtError::DRIVER_ERROR );
}
result = midiInStart( data->inHandle );
if ( result != MMSYSERR_NOERROR ) {
midiInClose( data->inHandle );
@@ -1832,7 +1872,7 @@ void RtMidiIn :: openPort( unsigned int portNumber )
connected_ = true;
}
void RtMidiIn :: openVirtualPort()
void RtMidiIn :: openVirtualPort( std::string portName )
{
// This function cannot be implemented for the Windows MM MIDI API.
errorString_ = "RtMidiIn::openVirtualPort: cannot be implemented in Windows MM MIDI API!";
@@ -1845,6 +1885,16 @@ void RtMidiIn :: closePort( void )
WinMidiData *data = static_cast<WinMidiData *> (apiData_);
midiInReset( data->inHandle );
midiInStop( data->inHandle );
int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer, sizeof(MIDIHDR));
delete [] data->sysexBuffer->lpData;
delete [] data->sysexBuffer;
if ( result != MMSYSERR_NOERROR ) {
midiInClose( data->inHandle );
errorString_ = "RtMidiIn::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader).";
error( RtError::DRIVER_ERROR );
}
midiInClose( data->inHandle );
connected_ = false;
}
@@ -1878,7 +1928,14 @@ std::string RtMidiIn :: getPortName( unsigned int portNumber )
MIDIINCAPS deviceCaps;
MMRESULT result = midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS));
std::string stringName = std::string( deviceCaps.szPname );
// For some reason, we need to copy character by character with
// UNICODE (thanks to Eduardo Coutinho!).
//std::string stringName = std::string( deviceCaps.szPname );
char nameString[MAXPNAMELEN];
for( int i=0; i<MAXPNAMELEN; i++ )
nameString[i] = (char)( deviceCaps.szPname[i] );
std::string stringName( nameString );
return stringName;
}
@@ -1905,7 +1962,14 @@ std::string RtMidiOut :: getPortName( unsigned int portNumber )
MIDIOUTCAPS deviceCaps;
MMRESULT result = midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));
std::string stringName = std::string( deviceCaps.szPname );
// For some reason, we need to copy character by character with
// UNICODE (thanks to Eduardo Coutinho!).
//std::string stringName = std::string( deviceCaps.szPname );
char nameString[MAXPNAMELEN];
for( int i=0; i<MAXPNAMELEN; i++ )
nameString[i] = (char)( deviceCaps.szPname[i] );
std::string stringName( nameString );
return stringName;
}
@@ -1969,7 +2033,7 @@ void RtMidiOut :: closePort( void )
}
}
void RtMidiOut :: openVirtualPort()
void RtMidiOut :: openVirtualPort( std::string portName )
{
// This function cannot be implemented for the Windows MM MIDI API.
errorString_ = "RtMidiOut::openVirtualPort: cannot be implemented in Windows MM MIDI API!";