1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: skiniio_skini.cpp
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 //-----------------------------------------------------------------------------
34 #include "skiniio_skini.h"
35 #include "chuck_errmsg.h"
40 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
43 //#define BUFFER_SIZE 8192
45 //std::vector<RtMidiIn *> MidiInManager::the_mins;
46 //std::vector<CBuffer *> MidiInManager::the_bufs;
47 //std::vector<RtMidiOut *> MidiOutManager::the_mouts;
51 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
65 //-----------------------------------------------------------------------------
68 //-----------------------------------------------------------------------------
71 if( skout
) this->close();
78 //-----------------------------------------------------------------------------
80 // desc: send skini message
81 //-----------------------------------------------------------------------------
82 t_CKUINT
SkiniOut::send( const SkiniMsg
* msg
)
84 if( !m_valid
) return 0;
86 // write message in file
87 skout
->write_message( msg
->type
, msg
->time
, msg
->channel
, msg
->data1
, msg
->data2
);
95 //-----------------------------------------------------------------------------
97 // desc: open skini output
98 //-----------------------------------------------------------------------------
99 t_CKBOOL
SkiniOut::open( const char * filename
)
101 // close if already opened
105 m_valid
= skout
->setFile( filename
);
106 //if( m_valid ) strcpy( m_filename, filename );
114 //-----------------------------------------------------------------------------
116 // desc: close skini output
117 //-----------------------------------------------------------------------------
118 t_CKBOOL
SkiniOut::close( )
124 //MidiOutManager::close( this );
137 //-----------------------------------------------------------------------------
139 // desc: note on message
140 //-----------------------------------------------------------------------------
141 t_CKUINT MidiOut::noteon( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity )
142 { return this->send( (t_CKBYTE)(MIDI_NOTEON + channel), note, velocity ); }
147 //-----------------------------------------------------------------------------
149 // desc: note off message
150 //-----------------------------------------------------------------------------
151 t_CKUINT MidiOut::noteoff( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity )
152 { return this->send( (t_CKBYTE)(MIDI_NOTEOFF + channel), note, velocity ); }
157 //-----------------------------------------------------------------------------
159 // desc: polypress message
160 //-----------------------------------------------------------------------------
161 t_CKUINT MidiOut::polypress( t_CKUINT channel, t_CKUINT note, t_CKUINT pressure )
162 { return this->send( (t_CKBYTE)(MIDI_POLYPRESS + channel), note, pressure ); }
167 //-----------------------------------------------------------------------------
168 // name: ctrlchange()
169 // desc: ctrl change message
170 //-----------------------------------------------------------------------------
171 t_CKUINT MidiOut::ctrlchange( t_CKUINT channel, t_CKUINT ctrl_num, t_CKUINT ctrl_val )
172 { return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), ctrl_num, ctrl_val ); }
177 //-----------------------------------------------------------------------------
178 // name: progchange()
179 // desc: prog change message
180 //-----------------------------------------------------------------------------
181 t_CKUINT MidiOut::progchange( t_CKUINT channel, t_CKUINT patch )
182 { return this->send( (t_CKBYTE)(MIDI_PROGCHANGE + channel), patch, 0 ); }
187 //-----------------------------------------------------------------------------
190 //-----------------------------------------------------------------------------
191 t_CKUINT MidiOut::chanpress( t_CKUINT channel, t_CKUINT pressure )
192 { return this->send( (t_CKBYTE)(MIDI_CHANPRESS + channel), pressure, 0 ); }
197 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
201 t_CKUINT MidiOut::pitchbend( t_CKUINT channel, t_CKUINT bend_val )
205 // return this->send( (t_CKBYTE)(MIDI_PITCHBEND + channel),
206 // (t_CKBYTE)(HIBYTE( bend_val << 1 )),
207 // (t_CKBYTE)(LOBYTE( bend_val & 0x7f )) );
213 //-----------------------------------------------------------------------------
214 // name: allnotesoff()
216 //-----------------------------------------------------------------------------
217 t_CKUINT MidiOut::allnotesoff( t_CKUINT channel )
219 return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel),
220 (t_CKBYTE)(MIDI_ALLNOTESOFF), 0 );
226 //-----------------------------------------------------------------------------
229 //-----------------------------------------------------------------------------
242 //-----------------------------------------------------------------------------
245 //-----------------------------------------------------------------------------
249 // SAFE_DELETE( min );
255 //-----------------------------------------------------------------------------
258 //-----------------------------------------------------------------------------
259 t_CKBOOL
SkiniIn::open( const char * filename
)
261 // close if already opened
266 m_valid
= skin
->setFile( filename
);
267 //if( m_valid ) strcpy( m_filename, filename );
274 MidiInManager::MidiInManager()
276 the_mins.resize( 1024 );
277 the_bufs.resize( 1024 );
281 MidiInManager::~MidiInManager()
287 t_CKBOOL MidiInManager::open( MidiIn * min, t_CKINT device_num )
289 // see if port not already open
290 if( device_num >= the_mins.capacity() || !the_mins[device_num] )
293 // allocate the buffer
294 CBuffer * cbuf = new CBuffer;
295 if( !cbuf->initialize( BUFFER_SIZE, sizeof(MidiMsg) ) )
297 EM_error2( 0, "MidiIn: couldn't allocate CBuffer for port %i...", device_num );
303 RtMidiIn * rtmin = new RtMidiIn;
305 rtmin->openPort( device_num );
306 rtmin->setCallback( cb_midi_input, cbuf );
307 } catch( RtError & err ) {
309 EM_error2( 0, "MidiIn: couldn't open MIDI port %i...", device_num );
310 EM_error2( 0, "...(%s)", err.getMessage().c_str() );
316 if( device_num >= the_mins.capacity() )
318 t_CKINT size = the_mins.capacity() * 2;
319 if( device_num >= size ) size = device_num + 1;
320 the_mins.resize( size );
321 the_bufs.resize( size );
324 // put cbuf and rtmin in vector for future generations
325 the_mins[device_num] = rtmin;
326 the_bufs[device_num] = cbuf;
330 min->m_buffer = the_bufs[device_num];
331 // get an index into your (you are min here) own buffer,
332 // and a free ticket to your own workshop
333 min->m_read_index = min->m_buffer->join( (Chuck_Event *)min->SELF );
334 min->m_device_num = (t_CKUINT)device_num;
342 //-----------------------------------------------------------------------------
345 //-----------------------------------------------------------------------------
346 t_CKBOOL
SkiniIn::close()
352 // MidiInManager::close( this );
362 //-----------------------------------------------------------------------------
365 //-----------------------------------------------------------------------------
366 t_CKUINT
SkiniIn::recv( SkiniMsg
* msg
)
368 if( !m_valid
) return FALSE
;
369 //return m_buffer->get( msg, 1, m_read_index );
372 msg
->type
= skin
->nextMessage( mess
); // what????
373 msg
->time
= mess
.time
;
374 msg
->channel
= mess
.channel
;
375 if( mess
.floatValues
.size() > 0 )
376 msg
->data1
= mess
.floatValues
[0];
377 if( mess
.floatValues
.size() > 1 )
378 msg
->data2
= mess
.floatValues
[1];