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

📄 rtmidi.cpp

📁 Mobile STK for Symbian OS V0.1
💻 CPP
📖 第 1 页 / 共 5 页
字号:
  // Set up the ALSA sequencer client.	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.";    error( RtError::DRIVER_ERROR );	}  // Set client name.  snd_seq_set_client_name(seq, "RtMidi Input Client");  // Save our api-specific connection information.  AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;  data->seq = seq;  data->vport = -1;  apiData_ = (void *) data;  inputData_.apiData = (void *) data;  // Create the input queue  data->queue_id = snd_seq_alloc_named_queue(seq, "RtMidi Queue");  // Set arbitrary tempo (mm=100) and resolution (240)  snd_seq_queue_tempo_t *qtempo;  snd_seq_queue_tempo_alloca(&qtempo);  snd_seq_queue_tempo_set_tempo(qtempo, 600000);  snd_seq_queue_tempo_set_ppq(qtempo, 240);  snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo);  snd_seq_drain_output(data->seq);}// This function is used to count or get the pinfo structure for a given port number.unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ){	snd_seq_client_info_t *cinfo;  int client;  int count = 0;	snd_seq_client_info_alloca( &cinfo );	snd_seq_client_info_set_client( cinfo, -1 );	while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) {    client = snd_seq_client_info_get_client( cinfo );    if ( client == 0 ) continue;		// Reset query info		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;      if ( count == portNumber ) return 1;      count++;		}	}  // If a negative portNumber was used, return the port count.  if ( portNumber < 0 ) return count;  return 0;}void RtMidiIn :: openPort( unsigned int portNumber ){  if ( connected_ ) {    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";    error( RtError::WARNING );    return;  }  unsigned int nSrc = this->getPortCount();  if (nSrc < 1) {    errorString_ = "RtMidiIn::openPort: no MIDI input sources found!";    error( RtError::NO_DEVICES_FOUND );  }	snd_seq_port_info_t *pinfo;	snd_seq_port_info_alloca( &pinfo );  std::ostringstream ost;  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) {    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  snd_seq_addr_t sender, receiver;  sender.client = snd_seq_port_info_get_client( pinfo );  sender.port = snd_seq_port_info_get_port( pinfo );  receiver.client = snd_seq_client_id( data->seq );  if ( data->vport < 0 ) {    snd_seq_port_info_set_client( pinfo, 0 );    snd_seq_port_info_set_port( pinfo, 0 );    snd_seq_port_info_set_capability( pinfo,                                      SND_SEQ_PORT_CAP_WRITE |                                      SND_SEQ_PORT_CAP_SUBS_WRITE );    snd_seq_port_info_set_type( pinfo,                                SND_SEQ_PORT_TYPE_MIDI_GENERIC |                                SND_SEQ_PORT_TYPE_APPLICATION );    snd_seq_port_info_set_midi_channels(pinfo, 16);    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");    data->vport = snd_seq_create_port(data->seq, pinfo);      if ( data->vport < 0 ) {      errorString_ = "RtMidiIn::openPort: ALSA error creating input port.";      error( RtError::DRIVER_ERROR );    }  }  receiver.port = data->vport;  // Make subscription  snd_seq_port_subscribe_malloc( &data->subscription );  snd_seq_port_subscribe_set_sender(data->subscription, &sender);  snd_seq_port_subscribe_set_dest(data->subscription, &receiver);  if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {    errorString_ = "RtMidiIn::openPort: ALSA error making port connection.";    error( RtError::DRIVER_ERROR );  }  if ( inputData_.doInput == false ) {    // Start the input queue    snd_seq_start_queue( data->seq, data->queue_id, NULL );    snd_seq_drain_output( data->seq );    // Start our MIDI input thread.    pthread_attr_t attr;    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);    inputData_.doInput = true;    int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);    pthread_attr_destroy(&attr);    if (err) {      snd_seq_unsubscribe_port( data->seq, data->subscription );      snd_seq_port_subscribe_free( data->subscription );      inputData_.doInput = false;      errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!";      error( RtError::THREAD_ERROR );    }  }  connected_ = true;}void RtMidiIn :: openVirtualPort(){  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  if ( data->vport < 0 ) {    snd_seq_port_info_t *pinfo;    snd_seq_port_info_alloca( &pinfo );    snd_seq_port_info_set_capability( pinfo,				      SND_SEQ_PORT_CAP_WRITE |				      SND_SEQ_PORT_CAP_SUBS_WRITE );    snd_seq_port_info_set_type( pinfo,				SND_SEQ_PORT_TYPE_MIDI_GENERIC |				SND_SEQ_PORT_TYPE_APPLICATION );    snd_seq_port_info_set_midi_channels(pinfo, 16);    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");    data->vport = snd_seq_create_port(data->seq, pinfo);    if ( data->vport < 0 ) {      errorString_ = "RtMidiIn::openVirtualPort: ALSA error creating virtual port.";      error( RtError::DRIVER_ERROR );    }  }  if ( inputData_.doInput == false ) {    // Start the input queue    snd_seq_start_queue( data->seq, data->queue_id, NULL );    snd_seq_drain_output( data->seq );    // Start our MIDI input thread.    pthread_attr_t attr;    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);    inputData_.doInput = true;    int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);    pthread_attr_destroy(&attr);    if (err) {      snd_seq_unsubscribe_port( data->seq, data->subscription );      snd_seq_port_subscribe_free( data->subscription );      inputData_.doInput = false;      errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!";      error( RtError::THREAD_ERROR );    }  }}void RtMidiIn :: closePort( void ){  if ( connected_ ) {    AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);    snd_seq_unsubscribe_port( data->seq, data->subscription );    snd_seq_port_subscribe_free( data->subscription );    // Stop the input queue    snd_seq_stop_queue( data->seq, data->queue_id, NULL );    snd_seq_drain_output( data->seq );    connected_ = false;  }}RtMidiIn :: ~RtMidiIn(){  // Close a connection if it exists.  closePort();  // Shutdown the input thread.  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  if ( inputData_.doInput ) {    inputData_.doInput = false;    pthread_join( data->thread, NULL );  }  // Cleanup.  if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );  snd_seq_free_queue( data->seq, data->queue_id );  snd_seq_close( data->seq );  delete data;}unsigned int RtMidiIn :: getPortCount(){	snd_seq_port_info_t *pinfo;	snd_seq_port_info_alloca( &pinfo );  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 );}std::string RtMidiIn :: getPortName( unsigned int portNumber ){	snd_seq_port_info_t *pinfo;	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 ) );    return stringName;  }  // If we get here, we didn't find a match.  errorString_ = "RtMidiIn::getPortName: error looking for port name!";  error( RtError::INVALID_PARAMETER );  return 0;}//*********************************************************************////  API: LINUX ALSA//  Class Definitions: RtMidiOut//*********************************************************************//unsigned int RtMidiOut :: getPortCount(){	snd_seq_port_info_t *pinfo;	snd_seq_port_info_alloca( &pinfo );  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 );}std::string RtMidiOut :: getPortName( unsigned int portNumber ){	snd_seq_port_info_t *pinfo;	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 ) );    return stringName;  }  // If we get here, we didn't find a match.  errorString_ = "RtMidiOut::getPortName: error looking for port name!";  error( RtError::INVALID_PARAMETER );  return 0;}void RtMidiOut :: initialize( void ){  // Set up the ALSA sequencer client.	snd_seq_t *seq;  int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0);  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");  // Save our api-specific connection information.  AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;  data->seq = seq;  data->vport = -1;  data->bufferSize = 32;  data->coder = 0;  data->buffer = 0;  result = snd_midi_event_new( data->bufferSize, &data->coder );  if ( result < 0 ) {    delete data;    errorString_ = "RtMidiOut::initialize: error initializing MIDI event parser!\n\n";    error( RtError::DRIVER_ERROR );  }  data->buffer = (unsigned char *) malloc( data->bufferSize );  if ( data->buffer == NULL ) {    delete data;    errorString_ = "RtMidiOut::initialize: error allocating buffer memory!\n\n";    error( RtError::MEMORY_ERROR );  }  snd_midi_event_init( data->coder );  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 nSrc = this->getPortCount();  if (nSrc < 1) {    errorString_ = "RtMidiOut::openPort: no MIDI output sources found!";    error( RtError::NO_DEVICES_FOUND );  }	snd_seq_port_info_t *pinfo;	snd_seq_port_info_alloca( &pinfo );  std::ostringstream ost;  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) {    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";    errorString_ = ost.str();    error( RtError::INVALID_PARAMETER );  }  snd_seq_addr_t sender, receiver;  receiver.client = snd_seq_port_info_get_client( pinfo );  receiver.port = snd_seq_port_info_get_port( pinfo );  sender.client = snd_seq_client_id( data->seq );  if ( data->vport < 0 ) {    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output",                                              SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC );    if ( data->vport < 0 ) {      errorString_ = "RtMidiOut::openPort: ALSA error creating output port.";      error( RtError::DRIVER_ERROR );    }  }  sender.port = data->vport;  // Make subscription  snd_seq_port_subscribe_malloc( &data->subscription );  snd_seq_port_subscribe_set_sender(data->subscription, &sender);  snd_seq_port_subscribe_set_dest(data->subscription, &receiver);  snd_seq_port_subscribe_set_time_update(data->subscription, 1);  snd_seq_port_subscribe_set_time_real(data->subscription, 1);  if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {    errorString_ = "RtMidiOut::openPort: ALSA error making port connection.";    error( RtError::DRIVER_ERROR );  }  connected_ = true;}void RtMidiOut :: closePort( void ){  if ( connected_ ) {    AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);    snd_seq_unsubscribe_port( data->seq, data->subscription );    snd_seq_port_subscribe_free( data->subscription );    connected_ = false;  }}void RtMidiOut :: openVirtualPort(){  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  if ( data->vport < 0 ) {    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output",                                              SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC );    if ( data->vport < 0 ) {      errorString_ = "RtMidiOut::openVirtualPort: ALSA error creating virtual port.";      error( RtError::DRIVER_ERROR );    }  }}RtMidiOut :: ~RtMidiOut(){  // Close a connection if it exists.  closePort();  // Cleanup.  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);  if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );  if ( data->coder ) snd_midi_event_free( data->coder );  if ( data->buffer ) free( data->buffer );  snd_seq_close( data->seq );  delete data;}

⌨️ 快捷键说明

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