⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtmidi.cpp

📁 Mobile STK for Symbian OS V0.1
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ){  int result;  MDevent event;  IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);  char *buffer = 0;  unsigned int nBytes = message->size();  if ( nBytes == 0 ) return;  event.stamp = 0;  if ( message->at(0) == 0xF0 ) {    if ( nBytes < 3 ) return; // check for bogus sysex    event.msg[0] = 0xF0;    event.msglen = nBytes;    buffer = (char *) malloc( nBytes );    for ( int i=0; i<nBytes; i++ ) buffer[i] = message->at(i);    event.sysexmsg = buffer;  }  else {    for ( int i=0; i<nBytes; i++ )      event.msg[i] = message->at(i);  }  // Send the event.  result = mdSend( data->port, &event, 1 );  if ( buffer ) free( buffer );  if ( result < 1 ) {    errorString_ = "RtMidiOut::sendMessage: IRIX error sending MIDI message!";    error( RtError::WARNING );    return;  }}#endif // __IRIX_MD__//*********************************************************************////  API: Windows Multimedia Library (MM)//*********************************************************************//// API information deciphered from://  - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp#if defined(__WINDOWS_MM__)// The Windows MM API is based on the use of a callback function for// MIDI input.  We convert the system specific time stamps to delta// time values.// Windows MM MIDI header files.#include <windows.h>#include <mmsystem.h>// A structure to hold variables related to the CoreMIDI API// implementation.struct WinMidiData {  HMIDIIN inHandle;    // Handle to Midi Input Device  HMIDIOUT outHandle;  // Handle to Midi Output Device  DWORD lastTime;  RtMidiIn::MidiMessage message;};//*********************************************************************////  API: Windows MM//  Class Definitions: RtMidiIn//*********************************************************************//static void CALLBACK midiInputCallback( HMIDIOUT hmin,                                        UINT inputStatus,                                         DWORD instancePtr,                                        DWORD midiMessage,                                        DWORD timestamp ){  if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA ) return;  //RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (instancePtr);  RtMidiIn::RtMidiInData *data = (RtMidiIn::RtMidiInData *)instancePtr;  WinMidiData *apiData = static_cast<WinMidiData *> (data->apiData);  // Calculate time stamp.  apiData->message.timeStamp = 0.0;  if ( data->firstMessage == true ) data->firstMessage = false;  else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;  apiData->lastTime = timestamp;  if ( inputStatus == MIM_DATA ) { // Channel or system message    // Make sure the first byte is a status byte.    unsigned char status = (unsigned char) (midiMessage & 0x000000FF);    if ( !(status & 0x80) ) return;    // Determine the number of bytes in the MIDI message.    unsigned short nBytes = 1;    if ( status < 0xC0 ) nBytes = 3;    else if ( status < 0xE0 ) nBytes = 2;    else if ( status < 0xF0 ) nBytes = 3;    else if ( status < 0xF3 ) {      // A MIDI time code message and we're ignoring it.      if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) return;      nBytes = 3;    }    else if ( status == 0xF3 ) nBytes = 2;    else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) {      // A MIDI timing tick message and we're ignoring it.      return;    }    else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {      // A MIDI active sensing message and we're ignoring it.      return;    }    // Copy bytes to our MIDI message.    unsigned char *ptr = (unsigned char *) &midiMessage;    for ( int i=0; i<nBytes; i++ ) apiData->message.bytes.push_back( *ptr++ );  }  else { // Sysex message    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;  }  if ( data->usingCallback ) {    RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;    callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );  }  else {    // As long as we haven't reached our queue size limit, push the message.    if ( data->queueLimit > data->queue.size() )      data->queue.push( apiData->message );    else      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.  apiData->message.bytes.clear();}void RtMidiIn :: initialize( void ){  // We'll issue a warning here if no devices are available but not  // throw an error since the user can plugin something later.  unsigned int nDevices = midiInGetNumDevs();  if ( nDevices == 0 ) {    errorString_ = "RtMidiIn::initialize: no MIDI input devices currently available.";    error( RtError::WARNING );  }  // Save our api-specific connection information.  WinMidiData *data = (WinMidiData *) new WinMidiData;  apiData_ = (void *) data;  inputData_.apiData = (void *) data;  data->message.bytes.clear();  // needs to be empty for first input message}void RtMidiIn :: openPort( unsigned int portNumber ){  if ( connected_ ) {    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";    error( RtError::WARNING );    return;  }  unsigned int nDevices = midiInGetNumDevs();  if (nDevices == 0) {    errorString_ = "RtMidiIn::openPort: no MIDI input sources found!";    error( RtError::NO_DEVICES_FOUND );  }  std::ostringstream ost;  if ( portNumber >= nDevices ) {    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  WinMidiData *data = static_cast<WinMidiData *> (apiData_);  MMRESULT result = midiInOpen( &data->inHandle,                                portNumber,                                (DWORD)&midiInputCallback,                                (DWORD)&inputData_,                                CALLBACK_FUNCTION );  if ( result != MMSYSERR_NOERROR ) {    errorString_ = "RtMidiIn::openPort: error creating Windows MM MIDI input port.";    error( RtError::DRIVER_ERROR );  }  result = midiInStart( data->inHandle );  if ( result != MMSYSERR_NOERROR ) {    midiInClose( data->inHandle );    errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port.";    error( RtError::DRIVER_ERROR );  }  connected_ = true;}void RtMidiIn :: openVirtualPort(){  // This function cannot be implemented for the Windows MM MIDI API.  errorString_ = "RtMidiIn::openVirtualPort: cannot be implemented in Windows MM MIDI API!";  error( RtError::WARNING );}void RtMidiIn :: closePort( void ){  if ( connected_ ) {    WinMidiData *data = static_cast<WinMidiData *> (apiData_);    midiInReset( data->inHandle );    midiInStop( data->inHandle );    midiInClose( data->inHandle );    connected_ = false;  }}RtMidiIn :: ~RtMidiIn(){  // Close a connection if it exists.  closePort();  // Cleanup.  WinMidiData *data = static_cast<WinMidiData *> (apiData_);  delete data;}unsigned int RtMidiIn :: getPortCount(){  return midiInGetNumDevs();}std::string RtMidiIn :: getPortName( unsigned int portNumber ){  unsigned int nDevices = midiInGetNumDevs();  if ( portNumber >= nDevices ) {    std::ostringstream ost;    ost << "RtMidiIn::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  MIDIINCAPS deviceCaps;  MMRESULT result = midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS));  std::string stringName = std::string( deviceCaps.szPname );  return stringName;}//*********************************************************************////  API: Windows MM//  Class Definitions: RtMidiOut//*********************************************************************//unsigned int RtMidiOut :: getPortCount(){  return midiOutGetNumDevs();}std::string RtMidiOut :: getPortName( unsigned int portNumber ){  unsigned int nDevices = midiOutGetNumDevs();  if ( portNumber >= nDevices ) {    std::ostringstream ost;    ost << "RtMidiOut::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  MIDIOUTCAPS deviceCaps;  MMRESULT result = midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));  std::string stringName = std::string( deviceCaps.szPname );  return stringName;}void RtMidiOut :: initialize( void ){  // We'll issue a warning here if no devices are available but not  // throw an error since the user can plug something in later.  unsigned int nDevices = midiOutGetNumDevs();  if ( nDevices == 0 ) {    errorString_ = "RtMidiOut::initialize: no MIDI output devices currently available.";    error( RtError::WARNING );  }  // Save our api-specific connection information.  WinMidiData *data = (WinMidiData *) new WinMidiData;  apiData_ = (void *) data;}void RtMidiOut :: openPort( unsigned int portNumber ){  if ( connected_ ) {    errorString_ = "RtMidiOut::openPort: a valid connection already exists!";    error( RtError::WARNING );    return;  }  unsigned int nDevices = midiOutGetNumDevs();  if (nDevices < 1) {    errorString_ = "RtMidiOut::openPort: no MIDI output destinations found!";    error( RtError::NO_DEVICES_FOUND );  }  std::ostringstream ost;  if ( portNumber >= nDevices ) {    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  WinMidiData *data = static_cast<WinMidiData *> (apiData_);  MMRESULT result = midiOutOpen( &data->outHandle,                                 portNumber,                                 (DWORD)NULL,                                 (DWORD)NULL,                                 CALLBACK_NULL );  if ( result != MMSYSERR_NOERROR ) {    errorString_ = "RtMidiOut::openPort: error creating Windows MM MIDI output port.";    error( RtError::DRIVER_ERROR );  }  connected_ = true;}void RtMidiOut :: closePort( void ){  if ( connected_ ) {    WinMidiData *data = static_cast<WinMidiData *> (apiData_);    midiOutReset( data->outHandle );    midiOutClose( data->outHandle );    connected_ = false;  }}void RtMidiOut :: openVirtualPort(){  // This function cannot be implemented for the Windows MM MIDI API.  errorString_ = "RtMidiOut::openVirtualPort: cannot be implemented in Windows MM MIDI API!";  error( RtError::WARNING );}RtMidiOut :: ~RtMidiOut(){  // Close a connection if it exists.  closePort();  // Cleanup.  WinMidiData *data = static_cast<WinMidiData *> (apiData_);  delete data;}void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ){  unsigned int nBytes = message->size();  if ( nBytes == 0 ) {    errorString_ = "RtMidiOut::sendMessage: message argument is empty!";    error( RtError::WARNING );    return;  }  MMRESULT result;  WinMidiData *data = static_cast<WinMidiData *> (apiData_);  if ( message->at(0) == 0xF0 ) { // Sysex message    // Allocate buffer for sysex data.    char *buffer = (char *) malloc( nBytes );    if ( buffer == NULL ) {      errorString_ = "RtMidiOut::sendMessage: error allocating sysex message memory!";      error( RtError::MEMORY_ERROR );    }    // Copy data to buffer.    for ( unsigned int i=0; i<nBytes; i++ ) buffer[i] = message->at(i);    // Create and prepare MIDIHDR structure.    MIDIHDR sysex;    sysex.lpData = (LPSTR) buffer;    sysex.dwBufferLength = nBytes;    sysex.dwFlags = 0;    result = midiOutPrepareHeader( data->outHandle,  &sysex, sizeof(MIDIHDR) );     if ( result != MMSYSERR_NOERROR ) {      free( buffer );      errorString_ = "RtMidiOut::sendMessage: error preparing sysex header.";      error( RtError::DRIVER_ERROR );    }    // Send the message.    result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) );    if ( result != MMSYSERR_NOERROR ) {      free( buffer );      errorString_ = "RtMidiOut::sendMessage: error sending sysex message.";      error( RtError::DRIVER_ERROR );    }    // Unprepare the buffer and MIDIHDR.    while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 );    free( buffer );  }  else { // Channel or system message.    // Make sure the message si

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -