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

📄 rtmidi.cpp

📁 Mobile STK for Symbian OS V0.1
💻 CPP
📖 第 1 页 / 共 5 页
字号:
  }}RtMidiIn :: ~RtMidiIn(){  // Close a connection if it exists.  closePort();  // Cleanup.  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);  MIDIClientDispose( data->client );  if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );  delete data;}unsigned int RtMidiIn :: getPortCount(){  return MIDIGetNumberOfSources();}std::string RtMidiIn :: getPortName( unsigned int portNumber ){  CFStringRef nameRef;  MIDIEndpointRef portRef;  std::ostringstream ost;  char name[128];  if ( portNumber >= MIDIGetNumberOfSources() ) {    ost << "RtMidiIn::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  portRef = MIDIGetSource( portNumber );  MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &nameRef );  CFStringGetCString( nameRef, name, sizeof(name), 0);  CFRelease( nameRef );  std::string stringName = name;  return stringName;}//*********************************************************************////  API: OS-X//  Class Definitions: RtMidiOut//*********************************************************************//unsigned int RtMidiOut :: getPortCount(){  return MIDIGetNumberOfDestinations();}std::string RtMidiOut :: getPortName( unsigned int portNumber ){  CFStringRef nameRef;  MIDIEndpointRef portRef;  std::ostringstream ost;  char name[128];  if ( portNumber >= MIDIGetNumberOfDestinations() ) {    ost << "RtMidiOut::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  portRef = MIDIGetDestination( portNumber );  MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &nameRef );  CFStringGetCString( nameRef, name, sizeof(name), 0);  CFRelease( nameRef );  std::string stringName = name;  return stringName;}void RtMidiOut :: initialize( void ){  // Set up our client.  MIDIClientRef client;  OSStatus result = MIDIClientCreate( CFSTR("RtMidi Output Client"), NULL, NULL, &client );  if ( result != noErr ) {    errorString_ = "RtMidiOut::initialize: error creating OS-X MIDI client object.";    error( RtError::DRIVER_ERROR );  }  // Save our api-specific connection information.  CoreMidiData *data = (CoreMidiData *) new CoreMidiData;  data->client = client;  data->endpoint = 0;  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 nDest = MIDIGetNumberOfDestinations();  if (nDest < 1) {    errorString_ = "RtMidiOut::openPort: no MIDI output destinations found!";    error( RtError::NO_DEVICES_FOUND );  }  std::ostringstream ost;  if ( portNumber >= nDest ) {    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  MIDIPortRef port;  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);  OSStatus result = MIDIOutputPortCreate( data->client, CFSTR("RtMidi Virtual MIDI Output Port"), &port );  if ( result != noErr ) {    MIDIClientDispose( data->client );    errorString_ = "RtMidiOut::openPort: error creating OS-X MIDI output port.";    error( RtError::DRIVER_ERROR );  }  // Get the desired output port identifier.  MIDIEndpointRef destination = MIDIGetDestination( portNumber );  if ( destination == NULL ) {    MIDIPortDispose( port );    MIDIClientDispose( data->client );    errorString_ = "RtMidiOut::openPort: error getting MIDI output destination reference.";    error( RtError::DRIVER_ERROR );  }  // Save our api-specific connection information.  data->port = port;  data->destinationId = destination;  connected_ = true;}void RtMidiOut :: closePort( void ){  if ( connected_ ) {    CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);    MIDIPortDispose( data->port );    connected_ = false;  }}void RtMidiOut :: openVirtualPort(){  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);  if ( data->endpoint ) {    errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!";    error( RtError::WARNING );    return;  }  // Create a virtual MIDI output source.  MIDIEndpointRef endpoint;  OSStatus result = MIDISourceCreate( data->client, CFSTR("RtMidi Output"), &endpoint );  if ( result != noErr ) {    errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source.";    error( RtError::DRIVER_ERROR );  }  // Save our api-specific connection information.  data->endpoint = endpoint;}RtMidiOut :: ~RtMidiOut(){  // Close a connection if it exists.  closePort();  // Cleanup.  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);  MIDIClientDispose( data->client );  if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );  delete data;}void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ){  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 );  MIDITimeStamp timeStamp = 0;  curPacket = MIDIPacketListAdd( pktlist, sizeof(buffer), curPacket, timeStamp, nBytes, &message->at(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 );    }  }  // 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 );    }  }}#endif  // __MACOSX_CORE__//*********************************************************************////  API: LINUX ALSA SEQUENCER//*********************************************************************//// API information found at://   - http://www.alsa-project.org/documentation.php#Library#if defined(__LINUX_ALSASEQ__)// The ALSA Sequencer API is based on the use of a callback function for// MIDI input.//// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer// time stamps and other assorted fixes!!!#include <pthread.h>#include <sys/time.h>// ALSA header file.#include <alsa/asoundlib.h>// A structure to hold variables related to the ALSA API// implementation.struct AlsaMidiData {  snd_seq_t *seq;  int vport;  snd_seq_port_subscribe_t *subscription;  snd_midi_event_t *coder;  unsigned int bufferSize;  unsigned char *buffer;  pthread_t thread;  unsigned long long lastTime;  int queue_id; // an input queue is needed to get timestamped events};#define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))//*********************************************************************////  API: LINUX ALSA//  Class Definitions: RtMidiIn//*********************************************************************//extern "C" void *alsaMidiHandler( void *ptr ){  RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (ptr);  AlsaMidiData *apiData = static_cast<AlsaMidiData *> (data->apiData);  long nBytes;  unsigned long long time, lastTime;  bool continueSysex = false;  RtMidiIn::MidiMessage message;  snd_seq_event_t *ev;  int result;  apiData->bufferSize = 32;  result = snd_midi_event_new( 0, &apiData->coder );  if ( result < 0 ) {    data->doInput = false;    std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing MIDI event parser!\n\n";    return 0;  }  unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize );  if ( buffer == NULL ) {    data->doInput = false;    std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing buffer memory!\n\n";    return 0;  }  snd_midi_event_init( apiData->coder );  snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages  while ( data->doInput ) {    if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) {      // No data pending ... sleep a bit.      usleep( 1000 );      continue;    }    // If here, there should be data.    result = snd_seq_event_input( apiData->seq, &ev );    if ( result == -ENOSPC ) {      std::cerr << "\nRtMidiIn::alsaMidiHandler: MIDI input buffer overrun!\n\n";      continue;    }    else if ( result <= 0 ) {      std::cerr << "RtMidiIn::alsaMidiHandler: unknown MIDI input error!\n";      continue;    }    // 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();    switch ( ev->type ) {		case SND_SEQ_EVENT_PORT_SUBSCRIBED:#if defined(__RTMIDI_DEBUG__)      std::cout << "RtMidiIn::alsaMidiHandler: port connection made!\n";#endif      break;		case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:      std::cerr << "RtMidiIn::alsaMidiHandler: port connection has closed!\n";      data->doInput = false;      break;    case SND_SEQ_EVENT_QFRAME: // MIDI time code      if ( data->ignoreFlags & 0x02 ) break;    case SND_SEQ_EVENT_TICK: // MIDI timing tick      if ( data->ignoreFlags & 0x02 ) break;    case SND_SEQ_EVENT_SENSING: // Active sensing      if ( data->ignoreFlags & 0x04 ) break;		case SND_SEQ_EVENT_SYSEX:      if ( (data->ignoreFlags & 0x01) ) break;      if ( ev->data.ext.len > apiData->bufferSize ) {        apiData->bufferSize = ev->data.ext.len;        free( buffer );        buffer = (unsigned char *) malloc( apiData->bufferSize );        if ( buffer == NULL ) {          data->doInput = false;          std::cerr << "\nRtMidiIn::alsaMidiHandler: error resizing buffer memory!\n\n";          break;        }      }    default:      nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev );      if ( nBytes <= 0 ) {#if defined(__RTMIDI_DEBUG__)        std::cerr << "\nRtMidiIn::alsaMidiHandler: event parsing error or not a MIDI event!\n\n";#endif        break;      }      // The ALSA sequencer has a maximum buffer size for MIDI sysex      // events of 256 bytes.  If a device sends sysex messages larger      // than this, they are segmented into 256 byte chunks.  So,      // we'll watch for this and concatenate sysex chunks into a      // single sysex message if necessary.      if ( !continueSysex )        message.bytes.assign( buffer, &buffer[nBytes] );      else        message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] );      if ( ev->type == SND_SEQ_EVENT_SYSEX && message.bytes.back() == 0xF7 )        continueSysex = false;      else {        continueSysex = true;        break;      }      // Calculate the time stamp:      message.timeStamp = 0.0;      // Method 1: Use the system time.      //(void)gettimeofday(&tv, (struct timezone *)NULL);      //time = (tv.tv_sec * 1000000) + tv.tv_usec;      // Method 2: Use the ALSA sequencer event time data.      // (thanks to Pedro Lopez-Cabanillas!).      time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 );      lastTime = time;      time -= apiData->lastTime;      apiData->lastTime = lastTime;      if ( data->firstMessage == true )        data->firstMessage = false;      else        message.timeStamp = time * 0.000001;    }    snd_seq_free_event(ev);    if ( message.bytes.size() == 0 ) continue;    if ( data->usingCallback ) {      RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;      callback( message.timeStamp, &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( message );      else        std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";    }  }  if ( buffer ) free( buffer );  snd_midi_event_free( apiData->coder );  apiData->coder = 0;  return 0;}void RtMidiIn :: initialize( void ){

⌨️ 快捷键说明

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