/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: midiio_rtmidi.cpp// desc: midi io header//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// Ananya Misra (amisra@cs.princeton.edu)// date: Summer 2005//-----------------------------------------------------------------------------#include "midiio_rtmidi.h" #ifndef __DISABLE_MIDI__ #include "chuck_errmsg.h"#include "chuck_vm.h"#include <vector>#include <map>#include <fstream> //-----------------------------------------------------------------------------// global variables//-----------------------------------------------------------------------------#define MIDI_BUFFER_SIZE 8192 std::vector<RtMidiIn *> MidiInManager::the_mins;std::vector< std::map< Chuck_VM *, CBufferAdvance * > > MidiInManager::the_bufs;std::vector<RtMidiOut *> MidiOutManager::the_mouts;std::map< Chuck_VM *, CBufferSimple * > MidiInManager::m_event_buffers; //-----------------------------------------------------------------------------// name: MidiOut()// desc: constructor//-----------------------------------------------------------------------------MidiOut::MidiOut(){ mout = NULL; m_device_num = 0; m_valid = FALSE; m_suppress_output = FALSE;} //-----------------------------------------------------------------------------// name: ~MidiOut()// desc: destructor//-----------------------------------------------------------------------------MidiOut::~MidiOut(){ if( mout ) this->close();// SAFE_DELETE( mout );} //-----------------------------------------------------------------------------// name: send()// desc: send 1 byte midi message//-----------------------------------------------------------------------------t_CKUINT MidiOut::send( t_CKBYTE status ){ return this->send( status, 0, 0 );} //-----------------------------------------------------------------------------// name: send()// desc: send 2 byte midi message//-----------------------------------------------------------------------------t_CKUINT MidiOut::send( t_CKBYTE status, t_CKBYTE data1 ){ return this->send( status, data1, 0 );} //-----------------------------------------------------------------------------// name: send()// desc: send 3 byte midi message//-----------------------------------------------------------------------------t_CKUINT MidiOut::send( t_CKBYTE status, t_CKBYTE data1, t_CKBYTE data2 ){ if( !m_valid ) return 0; // clear m_msg.clear(); // add m_msg.push_back( status ); m_msg.push_back( data1 ); m_msg.push_back( data2 ); mout->sendMessage( &m_msg ); return 3;} //-----------------------------------------------------------------------------// name: send()// desc: send//-----------------------------------------------------------------------------t_CKUINT MidiOut::send( const MidiMsg * msg ){ if( !m_valid ) return 0; // clear m_msg.clear(); // add m_msg.push_back( msg->data[0] ); m_msg.push_back( msg->data[1] ); m_msg.push_back( msg->data[2] ); mout->sendMessage( &m_msg ); return 3;} //-----------------------------------------------------------------------------// name: open// desc: open midi output//-----------------------------------------------------------------------------t_CKBOOL MidiOut::open( t_CKUINT device_num ){ // close if already opened if( m_valid ) this->close(); return m_valid = MidiOutManager::open( this, (t_CKINT)device_num );} //-----------------------------------------------------------------------------// name: open// desc: open midi output//-----------------------------------------------------------------------------t_CKBOOL MidiOut::open( const std::string & name ){ // close if already opened if( m_valid ) this->close(); return m_valid = MidiOutManager::open( this, name );} //-----------------------------------------------------------------------------// name: close( )// desc: close midi output//-----------------------------------------------------------------------------t_CKBOOL MidiOut::close( ){ if( !m_valid ) return FALSE; // close // MidiOutManager::close( this ); m_valid = FALSE; return TRUE;} //-----------------------------------------------------------------------------// name: noteon()// desc: note on message//-----------------------------------------------------------------------------t_CKUINT MidiOut::noteon( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ){ return this->send( (t_CKBYTE)(MIDI_NOTEON + channel), note, velocity ); } //-----------------------------------------------------------------------------// name: noteoff()// desc: note off message//-----------------------------------------------------------------------------t_CKUINT MidiOut::noteoff( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ){ return this->send( (t_CKBYTE)(MIDI_NOTEOFF + channel), note, velocity ); } //-----------------------------------------------------------------------------// name: polypress()// desc: polypress message//-----------------------------------------------------------------------------t_CKUINT MidiOut::polypress( t_CKUINT channel, t_CKUINT note, t_CKUINT pressure ){ return this->send( (t_CKBYTE)(MIDI_POLYPRESS + channel), note, pressure ); } //-----------------------------------------------------------------------------// name: ctrlchange()// desc: ctrl change message//-----------------------------------------------------------------------------t_CKUINT MidiOut::ctrlchange( t_CKUINT channel, t_CKUINT ctrl_num, t_CKUINT ctrl_val ){ return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), ctrl_num, ctrl_val ); } //-----------------------------------------------------------------------------// name: progchange()// desc: prog change message//-----------------------------------------------------------------------------t_CKUINT MidiOut::progchange( t_CKUINT channel, t_CKUINT patch ){ return this->send( (t_CKBYTE)(MIDI_PROGCHANGE + channel), patch, 0 ); } //-----------------------------------------------------------------------------// name: chanpress()// desc: chan press//-----------------------------------------------------------------------------t_CKUINT MidiOut::chanpress( t_CKUINT channel, t_CKUINT pressure ){ return this->send( (t_CKBYTE)(MIDI_CHANPRESS + channel), pressure, 0 ); } //-----------------------------------------------------------------------------// name: pitchbend()// desc: pitch bend//-----------------------------------------------------------------------------t_CKUINT MidiOut::pitchbend( t_CKUINT channel, t_CKUINT bend_val ){ assert( FALSE ); return 0;// return this->send( (t_CKBYTE)(MIDI_PITCHBEND + channel),// (t_CKBYTE)(HIBYTE( bend_val << 1 )),// (t_CKBYTE)(LOBYTE( bend_val & 0x7f )) );} //-----------------------------------------------------------------------------// name: allnotesoff()// desc: allnotesoff//-----------------------------------------------------------------------------t_CKUINT MidiOut::allnotesoff( t_CKUINT channel ){ return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), (t_CKBYTE)(MIDI_ALLNOTESOFF), 0 );} //-----------------------------------------------------------------------------// name: MidiIn()// desc: constructor//-----------------------------------------------------------------------------MidiIn::MidiIn(){ min = NULL; m_device_num = 0; m_valid = FALSE; m_read_index = 0; m_buffer = NULL; m_suppress_output = FALSE; SELF = NULL;} //-----------------------------------------------------------------------------// name: ~MidiIn()// desc: destructor//-----------------------------------------------------------------------------MidiIn::~MidiIn( ){ this->close(); // SAFE_DELETE( min );} //-----------------------------------------------------------------------------// name: open()// desc: open//-----------------------------------------------------------------------------t_CKBOOL MidiIn::open( Chuck_VM * vm, t_CKUINT device_num ){ // close if already opened if( m_valid ) this->close(); // open return m_valid = MidiInManager::open( this, vm, (t_CKINT)device_num );} //-----------------------------------------------------------------------------// name: open()// desc: open//-----------------------------------------------------------------------------t_CKBOOL MidiIn::open( Chuck_VM * vm, const std::string & name ){ // close if already opened if( m_valid ) this->close(); // open return m_valid = MidiInManager::open( this, vm, name );} MidiInManager::MidiInManager(){ the_mins.resize( 1024 ); the_bufs.resize( 1024 );} MidiInManager::~MidiInManager(){ // yeah right //vm->destroy_event_buffer( m_event_buffer );} t_CKBOOL MidiInManager::open( MidiIn * min, Chuck_VM * vm, t_CKINT device_num ){ // see if port not already open if( device_num >= (t_CKINT)the_mins.capacity() || !the_mins[device_num] ) { if( m_event_buffers.count( vm ) == 0 ) { m_event_buffers[vm] = vm->create_event_buffer(); } // allocate RtMidiIn * rtmin = new RtMidiIn; try { rtmin->openPort( (unsigned int) device_num ); // callback, userData. first cast device num to unsigned int, then to void * rtmin->setCallback( cb_midi_input, (void *) ( (t_CKUINT)device_num ) ); } catch( RtMidiError & err ) { if( !min->m_suppress_output ) { // print it EM_error2( 0, "MidiIn: couldn't open MIDI port %i...", device_num ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } // clear ignore types | 1.4.1.0 (mariobuoninfante) rtmin->ignoreTypes( false, false, false ); // resize? if( device_num >= (t_CKINT)the_mins.capacity() ) { t_CKINT size = the_mins.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_mins.resize( size ); the_bufs.resize( size ); } // put rtmin in vector for future generations the_mins[device_num] = rtmin; } // if it doesn't exist already, allocate the buffer and put it in the_bufs if( !add_vm( vm, device_num, min->m_suppress_output ) ) { return FALSE; } // set min min->min = the_mins[device_num]; // found min->m_buffer = the_bufs[device_num][vm]; // get an index into your (you are min here) own buffer, // and a free ticket to your own workshop min->m_read_index = min->m_buffer->join( (Chuck_Event *)min->SELF ); min->m_device_num = (t_CKUINT)device_num; // done return TRUE;} t_CKBOOL MidiInManager::close(MidiIn * min){ min->m_buffer->resign(min->m_read_index); return true;} t_CKBOOL MidiInManager::open( MidiIn * min, Chuck_VM * vm, const std::string & name ){ t_CKINT device_num = -1; try { RtMidiIn * rtmin = new RtMidiIn; t_CKINT count = rtmin->getPortCount(); for(t_CKINT i = 0; i < count; i++) { std::string port_name = rtmin->getPortName( (unsigned int) i ); if( port_name == name) { device_num = i; break; } } if( device_num == -1 ) { // search by substring for(t_CKINT i = 0; i < count; i++) { std::string port_name = rtmin->getPortName( (unsigned int) i ); if( port_name.find( name ) != std::string::npos ) { device_num = i; break; } } } } catch( RtMidiError & err ) { if( !min->m_suppress_output ) { // print it EM_error2( 0, "MidiOut: error locating MIDI port named %s", name.c_str() ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } if(device_num == -1) { EM_error2( 0, "MidiOut: error locating MIDI port named %s", name.c_str() ); return FALSE; } t_CKBOOL result = open( min, vm, device_num ); return result;}Lines 1–500 of 2148. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: midiio_rtmidi.cpp // desc: midi io header // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Summer 2005 //----------------------------------------------------------------------------- #include "midiio_rtmidi.h" #ifndef __DISABLE_MIDI__ #include "chuck_errmsg.h" #include "chuck_vm.h" #include <vector> #include <map> #include <fstream> //----------------------------------------------------------------------------- // global variables //----------------------------------------------------------------------------- #define MIDI_BUFFER_SIZE 8192 std::vector<RtMidiIn *> MidiInManager::the_mins; std::vector< std::map< Chuck_VM *, CBufferAdvance * > > MidiInManager::the_bufs; std::vector<RtMidiOut *> MidiOutManager::the_mouts; std::map< Chuck_VM *, CBufferSimple * > MidiInManager::m_event_buffers; //----------------------------------------------------------------------------- // name: MidiOut() // desc: constructor //----------------------------------------------------------------------------- MidiOut::MidiOut() { mout = NULL; m_device_num = 0; m_valid = FALSE; m_suppress_output = FALSE; } //----------------------------------------------------------------------------- // name: ~MidiOut() // desc: destructor //----------------------------------------------------------------------------- MidiOut::~MidiOut() { if( mout ) this->close(); // SAFE_DELETE( mout ); } //----------------------------------------------------------------------------- // name: send() // desc: send 1 byte midi message //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( t_CKBYTE status ) { return this->send( status, 0, 0 ); } //----------------------------------------------------------------------------- // name: send() // desc: send 2 byte midi message //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( t_CKBYTE status, t_CKBYTE data1 ) { return this->send( status, data1, 0 ); } //----------------------------------------------------------------------------- // name: send() // desc: send 3 byte midi message //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( t_CKBYTE status, t_CKBYTE data1, t_CKBYTE data2 ) { if( !m_valid ) return 0; // clear m_msg.clear(); // add m_msg.push_back( status ); m_msg.push_back( data1 ); m_msg.push_back( data2 ); mout->sendMessage( &m_msg ); return 3; } //----------------------------------------------------------------------------- // name: send() // desc: send //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( const MidiMsg * msg ) { if( !m_valid ) return 0; // clear m_msg.clear(); // add m_msg.push_back( msg->data[0] ); m_msg.push_back( msg->data[1] ); m_msg.push_back( msg->data[2] ); mout->sendMessage( &m_msg ); return 3; } //----------------------------------------------------------------------------- // name: open // desc: open midi output //----------------------------------------------------------------------------- t_CKBOOL MidiOut::open( t_CKUINT device_num ) { // close if already opened if( m_valid ) this->close(); return m_valid = MidiOutManager::open( this, (t_CKINT)device_num ); } //----------------------------------------------------------------------------- // name: open // desc: open midi output //----------------------------------------------------------------------------- t_CKBOOL MidiOut::open( const std::string & name ) { // close if already opened if( m_valid ) this->close(); return m_valid = MidiOutManager::open( this, name ); } //----------------------------------------------------------------------------- // name: close( ) // desc: close midi output //----------------------------------------------------------------------------- t_CKBOOL MidiOut::close( ) { if( !m_valid ) return FALSE; // close // MidiOutManager::close( this ); m_valid = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: noteon() // desc: note on message //----------------------------------------------------------------------------- t_CKUINT MidiOut::noteon( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ) { return this->send( (t_CKBYTE)(MIDI_NOTEON + channel), note, velocity ); } //----------------------------------------------------------------------------- // name: noteoff() // desc: note off message //----------------------------------------------------------------------------- t_CKUINT MidiOut::noteoff( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ) { return this->send( (t_CKBYTE)(MIDI_NOTEOFF + channel), note, velocity ); } //----------------------------------------------------------------------------- // name: polypress() // desc: polypress message //----------------------------------------------------------------------------- t_CKUINT MidiOut::polypress( t_CKUINT channel, t_CKUINT note, t_CKUINT pressure ) { return this->send( (t_CKBYTE)(MIDI_POLYPRESS + channel), note, pressure ); } //----------------------------------------------------------------------------- // name: ctrlchange() // desc: ctrl change message //----------------------------------------------------------------------------- t_CKUINT MidiOut::ctrlchange( t_CKUINT channel, t_CKUINT ctrl_num, t_CKUINT ctrl_val ) { return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), ctrl_num, ctrl_val ); } //----------------------------------------------------------------------------- // name: progchange() // desc: prog change message //----------------------------------------------------------------------------- t_CKUINT MidiOut::progchange( t_CKUINT channel, t_CKUINT patch ) { return this->send( (t_CKBYTE)(MIDI_PROGCHANGE + channel), patch, 0 ); } //----------------------------------------------------------------------------- // name: chanpress() // desc: chan press //----------------------------------------------------------------------------- t_CKUINT MidiOut::chanpress( t_CKUINT channel, t_CKUINT pressure ) { return this->send( (t_CKBYTE)(MIDI_CHANPRESS + channel), pressure, 0 ); } //----------------------------------------------------------------------------- // name: pitchbend() // desc: pitch bend //----------------------------------------------------------------------------- t_CKUINT MidiOut::pitchbend( t_CKUINT channel, t_CKUINT bend_val ) { assert( FALSE ); return 0; // return this->send( (t_CKBYTE)(MIDI_PITCHBEND + channel), // (t_CKBYTE)(HIBYTE( bend_val << 1 )), // (t_CKBYTE)(LOBYTE( bend_val & 0x7f )) ); } //----------------------------------------------------------------------------- // name: allnotesoff() // desc: allnotesoff //----------------------------------------------------------------------------- t_CKUINT MidiOut::allnotesoff( t_CKUINT channel ) { return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), (t_CKBYTE)(MIDI_ALLNOTESOFF), 0 ); } //----------------------------------------------------------------------------- // name: MidiIn() // desc: constructor //----------------------------------------------------------------------------- MidiIn::MidiIn() { min = NULL; m_device_num = 0; m_valid = FALSE; m_read_index = 0; m_buffer = NULL; m_suppress_output = FALSE; SELF = NULL; } //----------------------------------------------------------------------------- // name: ~MidiIn() // desc: destructor //----------------------------------------------------------------------------- MidiIn::~MidiIn( ) { this->close(); // SAFE_DELETE( min ); } //----------------------------------------------------------------------------- // name: open() // desc: open //----------------------------------------------------------------------------- t_CKBOOL MidiIn::open( Chuck_VM * vm, t_CKUINT device_num ) { // close if already opened if( m_valid ) this->close(); // open return m_valid = MidiInManager::open( this, vm, (t_CKINT)device_num ); } //----------------------------------------------------------------------------- // name: open() // desc: open //----------------------------------------------------------------------------- t_CKBOOL MidiIn::open( Chuck_VM * vm, const std::string & name ) { // close if already opened if( m_valid ) this->close(); // open return m_valid = MidiInManager::open( this, vm, name ); } MidiInManager::MidiInManager() { the_mins.resize( 1024 ); the_bufs.resize( 1024 ); } MidiInManager::~MidiInManager() { // yeah right //vm->destroy_event_buffer( m_event_buffer ); } t_CKBOOL MidiInManager::open( MidiIn * min, Chuck_VM * vm, t_CKINT device_num ) { // see if port not already open if( device_num >= (t_CKINT)the_mins.capacity() || !the_mins[device_num] ) { if( m_event_buffers.count( vm ) == 0 ) { m_event_buffers[vm] = vm->create_event_buffer(); } // allocate RtMidiIn * rtmin = new RtMidiIn; try { rtmin->openPort( (unsigned int) device_num ); // callback, userData. first cast device num to unsigned int, then to void * rtmin->setCallback( cb_midi_input, (void *) ( (t_CKUINT)device_num ) ); } catch( RtMidiError & err ) { if( !min->m_suppress_output ) { // print it EM_error2( 0, "MidiIn: couldn't open MIDI port %i...", device_num ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } // clear ignore types | 1.4.1.0 (mariobuoninfante) rtmin->ignoreTypes( false, false, false ); // resize? if( device_num >= (t_CKINT)the_mins.capacity() ) { t_CKINT size = the_mins.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_mins.resize( size ); the_bufs.resize( size ); } // put rtmin in vector for future generations the_mins[device_num] = rtmin; } // if it doesn't exist already, allocate the buffer and put it in the_bufs if( !add_vm( vm, device_num, min->m_suppress_output ) ) { return FALSE; } // set min min->min = the_mins[device_num]; // found min->m_buffer = the_bufs[device_num][vm]; // get an index into your (you are min here) own buffer, // and a free ticket to your own workshop min->m_read_index = min->m_buffer->join( (Chuck_Event *)min->SELF ); min->m_device_num = (t_CKUINT)device_num; // done return TRUE; } t_CKBOOL MidiInManager::close(MidiIn * min) { min->m_buffer->resign(min->m_read_index); return true; } t_CKBOOL MidiInManager::open( MidiIn * min, Chuck_VM * vm, const std::string & name ) { t_CKINT device_num = -1; try { RtMidiIn * rtmin = new RtMidiIn; t_CKINT count = rtmin->getPortCount(); for(t_CKINT i = 0; i < count; i++) { std::string port_name = rtmin->getPortName( (unsigned int) i ); if( port_name == name) { device_num = i; break; } } if( device_num == -1 ) { // search by substring for(t_CKINT i = 0; i < count; i++) { std::string port_name = rtmin->getPortName( (unsigned int) i ); if( port_name.find( name ) != std::string::npos ) { device_num = i; break; } } } } catch( RtMidiError & err ) { if( !min->m_suppress_output ) { // print it EM_error2( 0, "MidiOut: error locating MIDI port named %s", name.c_str() ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } if(device_num == -1) { EM_error2( 0, "MidiOut: error locating MIDI port named %s", name.c_str() ); return FALSE; } t_CKBOOL result = open( min, vm, device_num ); return result; }