*** empty log message ***
[chuck-blob.git] / v1 / midiio_alsa.cpp
blob4faff85ba4d41eb7a827eeca0f00db4c6ca13943
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
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: midiio_alsa.cpp
27 // desc: midi io alsa implementation
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 //-----------------------------------------------------------------------------
32 #include "midiio_alsa.h"
33 #include <stdio.h>
34 #include <stdlib.h>
39 //-----------------------------------------------------------------------------
40 // name: MidiOut()
41 // desc: constructor
42 //-----------------------------------------------------------------------------
43 MidiOut::MidiOut()
45 UINT__ m_device_num = 0;
46 m_midi_out = NULL;
52 //-----------------------------------------------------------------------------
53 // name: ~MidiOut()
54 // desc: destructor
55 //-----------------------------------------------------------------------------
56 MidiOut::~MidiOut()
58 this->close();
64 //-----------------------------------------------------------------------------
65 // name: open()
66 // desc: open a device
67 //-----------------------------------------------------------------------------
68 BOOL__ MidiOut::open( int device_num )
70 int err = 0;
71 char buffer[256];
73 m_device_num = device_num;
75 // open the midi
76 sprintf( buffer, "hw:0,%d", m_device_num );
77 err = snd_rawmidi_open( NULL, &m_midi_out, buffer, 0 );
79 return err == 0;
85 //-----------------------------------------------------------------------------
86 // name: close()
87 // desc: close the device
88 //-----------------------------------------------------------------------------
89 BOOL__ MidiOut::close( )
91 // send everything in buffer
92 snd_rawmidi_drain( m_midi_out );
94 // close midi out
95 snd_rawmidi_close( m_midi_out );
97 return true;
103 //-----------------------------------------------------------------------------
104 // name: drain()
105 // desc: ...
106 //-----------------------------------------------------------------------------
107 BOOL__ MidiOut::drain()
109 snd_rawmidi_drain( m_midi_out );
111 return true;
117 //-----------------------------------------------------------------------------
118 // name: send()
119 // desc: send 1 BYTE__ midi message
120 //-----------------------------------------------------------------------------
121 UINT__ MidiOut::send( BYTE__ status )
123 // send
124 snd_rawmidi_write( m_midi_out, &status, 1 );
126 return true;
132 //-----------------------------------------------------------------------------
133 // name: send()
134 // desc: send 2 BYTE__ midi message
135 //-----------------------------------------------------------------------------
136 UINT__ MidiOut::send( BYTE__ status, BYTE__ data1 )
138 // send
139 snd_rawmidi_write( m_midi_out, &status, 1 );
140 snd_rawmidi_write( m_midi_out, &data1, 1 );
142 return true;
148 //-----------------------------------------------------------------------------
149 // name: send()
150 // desc: send 3 BYTE__ midi message
151 //-----------------------------------------------------------------------------
152 UINT__ MidiOut::send( BYTE__ status, BYTE__ data1, BYTE__ data2 )
154 // send the three BYTE__s
155 snd_rawmidi_write( m_midi_out, &status, 1 );
156 snd_rawmidi_write( m_midi_out, &data1, 1 );
157 snd_rawmidi_write( m_midi_out, &data2, 1 );
159 return true;
165 //-----------------------------------------------------------------------------
166 // name: send()
167 // desc: send midi message
168 //-----------------------------------------------------------------------------
169 UINT__ MidiOut::send( const MidiMsg * msg )
171 return this->send( msg->data[0], msg->data[1], msg->data[2] );
177 //-----------------------------------------------------------------------------
178 // name: MidiIn()
179 // desc: constructor
180 //-----------------------------------------------------------------------------
181 MidiIn::MidiIn()
183 m_midi_in = NULL;
184 m_device_num = 0;
185 pthread_mutex_init( &m_mutex, NULL );
191 //-----------------------------------------------------------------------------
192 // name: ~MidiIn()
193 // desc: destructor
194 //-----------------------------------------------------------------------------
195 MidiIn::~MidiIn( )
197 this->close();
203 //-----------------------------------------------------------------------------
204 // name: open()
205 // desc: open
206 //-----------------------------------------------------------------------------
207 BOOL__ MidiIn::open( int device_num )
209 int err = 0;
210 char buffer[256];
212 m_device_num = device_num;
214 // open the raw midi
215 sprintf( buffer, "hw:0,%d", m_device_num );
216 err = snd_rawmidi_open( &m_midi_in, NULL, buffer, 0 );
218 // initialize the buffer
219 m_buffer.initialize( 1024, sizeof( MidiMsg ) );
221 // thread
222 pthread_create( &m_cb_thread_id, NULL, midi_in_cb, this );
224 return err == 0;
230 //-----------------------------------------------------------------------------
231 // name: close()
232 // desc: close
233 //-----------------------------------------------------------------------------
234 BOOL__ MidiIn::close()
236 snd_rawmidi_drain( m_midi_in );
237 snd_rawmidi_close( m_midi_in );
239 pthread_cancel( m_cb_thread_id );
240 pthread_mutex_destroy( &m_mutex );
242 return true;
248 //-----------------------------------------------------------------------------
249 // name: get()
250 // desc: get message
251 //-----------------------------------------------------------------------------
252 UINT__ MidiIn::recv( MidiMsg * msg )
254 UINT__ r = 0;
255 //pthread_mutex_lock( &m_mutex );
256 r = m_buffer.get( msg, 1 );
257 //pthread_mutex_unlock( &m_mutex );
259 return r;
265 //-----------------------------------------------------------------------------
266 // name: midi_in_cb()
267 // desc: ...
268 //-----------------------------------------------------------------------------
269 void * MidiIn::midi_in_cb( void * arg )
271 MidiIn * min = (MidiIn *)arg;
272 BYTE__ byte = 0;
273 int n = 0, num_args = 0, num_left = 0;
274 MidiMsg msg;
276 while( true )
278 // get the next BYTE__
279 n = snd_rawmidi_read( min->m_midi_in, &byte, 1 );
280 if( n < 0 )
282 // encounter error
283 fprintf( stdout, "error: rawmidi_read...\n" );
284 continue;
287 while( n > 0 )
289 if( byte & 0x80 ) // status byte
291 if( (byte & 0xf0) == 0xf0 ) // system msg
293 n--;
294 continue;
297 if( ( (byte & 0xf0) == 0xc0 ) || ( (byte & 0xf0) == 0xd0 ) )
298 num_args = 1;
299 else
300 num_args = 2;
302 msg.data[3] = 0;
303 msg.data[2] = byte;
304 msg.data[1] = 0;
305 msg.data[0] = 0;
306 num_left = num_args;
308 else // data byte
310 if( num_left == num_args )
311 msg.data[1] = byte;
312 else
313 msg.data[0] = byte;
315 num_left--;
317 if( !num_left )
319 if( ((msg.data[2] & 0xf0) == 0xc0) || ((msg.data[2] & 0xf0) == 0xd0) )
320 num_left = 1;
321 else
322 num_left = 2;
324 //pthread_mutex_lock( &min->m_mutex );
325 min->m_buffer.put( &msg, 1 );
326 //pthread_mutex_unlock( &min->m_mutex );
329 n--;
333 return NULL;