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: midiio_win32.cpp
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 //-----------------------------------------------------------------------------
33 #include "midiio_win32.h"
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 #define BUFFER_SIZE 8192
47 //-----------------------------------------------------------------------------
50 //-----------------------------------------------------------------------------
60 //-----------------------------------------------------------------------------
63 //-----------------------------------------------------------------------------
66 if( m_midi_out
) this->close();
72 //-----------------------------------------------------------------------------
74 // desc: send 1 byte midi message
75 //-----------------------------------------------------------------------------
76 UINT
MidiOut::send( BYTE status
)
78 return this->send( status
, 0, 0 );
84 //-----------------------------------------------------------------------------
86 // desc: send 2 byte midi message
87 //-----------------------------------------------------------------------------
88 UINT
MidiOut::send( BYTE status
, BYTE data1
)
90 return this->send( status
, data1
, 0 );
96 //-----------------------------------------------------------------------------
98 // desc: send 3 byte midi message
99 //-----------------------------------------------------------------------------
100 UINT
MidiOut::send( BYTE status
, BYTE data1
, BYTE data2
)
104 msg
.data
[0] = status
;
109 return midiOutShortMsg( m_midi_out
, msg
.dw
);
115 //-----------------------------------------------------------------------------
118 //-----------------------------------------------------------------------------
119 UINT
MidiOut::send( const MidiMsg
* msg
)
121 return midiOutShortMsg( m_midi_out
, msg
->dw
);
127 //-----------------------------------------------------------------------------
129 // desc: open midi output
130 //-----------------------------------------------------------------------------
131 BOOL
MidiOut::open( UINT device_num
)
133 // close if already opened
138 m_device_num
= device_num
;
141 return midiOutOpen( &m_midi_out
, m_device_num
,
142 (DWORD
)cb_midi_output
, NULL
, CALLBACK_FUNCTION
) == 0;
148 //-----------------------------------------------------------------------------
150 // desc: close midi output
151 //-----------------------------------------------------------------------------
152 BOOL
MidiOut::close( )
157 // turn off everything
158 midiOutReset( m_midi_out
);
161 midiOutClose( m_midi_out
);
172 //-----------------------------------------------------------------------------
174 // desc: note on message
175 //-----------------------------------------------------------------------------
176 UINT
MidiOut::noteon( UINT channel
, UINT note
, UINT velocity
)
177 { return this->send( (BYTE
)(MIDI_NOTEON
+ channel
), note
, velocity
); }
182 //-----------------------------------------------------------------------------
184 // desc: note off message
185 //-----------------------------------------------------------------------------
186 UINT
MidiOut::noteoff( UINT channel
, UINT note
, UINT velocity
)
187 { return this->send( (BYTE
)(MIDI_NOTEOFF
+ channel
), note
, velocity
); }
192 //-----------------------------------------------------------------------------
194 // desc: polypress message
195 //-----------------------------------------------------------------------------
196 UINT
MidiOut::polypress( UINT channel
, UINT note
, UINT pressure
)
197 { return this->send( (BYTE
)(MIDI_POLYPRESS
+ channel
), note
, pressure
); }
202 //-----------------------------------------------------------------------------
203 // name: ctrlchange()
204 // desc: ctrl change message
205 //-----------------------------------------------------------------------------
206 UINT
MidiOut::ctrlchange( UINT channel
, UINT ctrl_num
, UINT ctrl_val
)
207 { return this->send( (BYTE
)(MIDI_CTRLCHANGE
+ channel
), ctrl_num
, ctrl_val
); }
212 //-----------------------------------------------------------------------------
213 // name: progchange()
214 // desc: prog change message
215 //-----------------------------------------------------------------------------
216 UINT
MidiOut::progchange( UINT channel
, UINT patch
)
217 { return this->send( (BYTE
)(MIDI_PROGCHANGE
+ channel
), patch
, 0 ); }
222 //-----------------------------------------------------------------------------
225 //-----------------------------------------------------------------------------
226 UINT
MidiOut::chanpress( UINT channel
, UINT pressure
)
227 { return this->send( (BYTE
)(MIDI_CHANPRESS
+ channel
), pressure
, 0 ); }
232 //-----------------------------------------------------------------------------
235 //-----------------------------------------------------------------------------
236 UINT
MidiOut::pitchbend( UINT channel
, UINT bend_val
)
238 return this->send( (BYTE
)(MIDI_PITCHBEND
+ channel
),
239 (BYTE
)(HIBYTE( bend_val
<< 1 )),
240 (BYTE
)(LOBYTE( bend_val
& 0x7f )) );
246 //-----------------------------------------------------------------------------
247 // name: allnotesoff()
249 //-----------------------------------------------------------------------------
250 UINT
MidiOut::allnotesoff( UINT channel
)
252 return this->send( (BYTE
)(MIDI_CTRLCHANGE
+ channel
),
253 (BYTE
)(MIDI_ALLNOTESOFF
), 0 );
259 //-----------------------------------------------------------------------------
260 // name: cb_midi_output
262 //-----------------------------------------------------------------------------
263 void CALLBACK
MidiOut::cb_midi_output( HMIDIOUT hm_out
, UINT msg
,
264 DWORD instance
, DWORD param1
, DWORD param2
)
267 MIDIHDR
* mhdr
= NULL
;
276 mhdr
= (MIDIHDR
*)param1
;
278 result
= midiOutUnprepareHeader( hm_out
, mhdr
, sizeof(MIDIHDR
) );
282 // TODO: handle the error
287 free( mhdr
->lpData
);
291 mhdr
= (MIDIHDR
*)param2
;
299 //-----------------------------------------------------------------------------
302 //-----------------------------------------------------------------------------
312 //-----------------------------------------------------------------------------
315 //-----------------------------------------------------------------------------
324 //-----------------------------------------------------------------------------
327 //-----------------------------------------------------------------------------
328 BOOL
MidiIn::open( UINT device_num
)
334 m_device_num
= device_num
;
337 result
= midiInOpen( &m_midi_in
, m_device_num
, (DWORD
)cb_midi_input
,
338 (DWORD
)this, CALLBACK_FUNCTION
);
344 // allocate the buffer
345 if( !m_buffer
.initialize( BUFFER_SIZE
, sizeof(MidiMsg
) ) )
351 return midiInStart( m_midi_in
) == 0;
357 //-----------------------------------------------------------------------------
360 //-----------------------------------------------------------------------------
367 midiInReset( m_midi_in
);
370 midiInClose( m_midi_in
);
375 // deallocate the buffer
384 //-----------------------------------------------------------------------------
387 //-----------------------------------------------------------------------------
388 UINT
MidiIn::recv( MidiMsg
* msg
)
390 return m_buffer
.get( msg
, 1 );
396 //-----------------------------------------------------------------------------
397 // name: cb_midi_input()
399 //-----------------------------------------------------------------------------
400 void CALLBACK
MidiIn::cb_midi_input( HMIDIIN hm_in
, UINT msg
, DWORD instance
,
401 DWORD param1
, DWORD param2
)
404 MidiIn
* midi_in
= (MidiIn
*)instance
;
416 m
.data
[0] = n
.data
[2];
417 m
.data
[1] = n
.data
[1];
418 m
.data
[2] = n
.data
[0];
419 m
.data
[3] = n
.data
[3];
421 // put in the buffer, make sure not active sensing
422 if( m
.data
[2] != 0xfe )
424 midi_in
->m_buffer
.put( &m
, 1 );