2148 lines · 55.7 KB · C++
RawDownload
/*----------------------------------------------------------------------------  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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t