Merge branch 'windows+cc' into cairocanvas
[ardour.git] / libs / midi++2 / channel.cc
1 /*
2     Copyright (C) 1998-99 Paul Barton-Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <cstring>
22 #include "midi++/types.h"
23 #include "midi++/port.h"
24 #include "midi++/channel.h"
25
26 using namespace MIDI;
27
28 Channel::Channel (MIDI::byte channelnum, Port &p) 
29         : _port (p)
30 {
31         _channel_number = channelnum;
32
33         reset (0, 1, false);
34 }       
35
36 void
37 Channel::connect_signals ()
38 {
39         _port.parser()->channel_pressure[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_chanpress, this, _1, _2));
40         _port.parser()->channel_note_on[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_note_on, this, _1, _2));
41         _port.parser()->channel_note_off[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_note_off, this, _1, _2));
42         _port.parser()->channel_poly_pressure[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_polypress, this, _1, _2));
43         _port.parser()->channel_program_change[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_program_change, this, _1, _2));
44         _port.parser()->channel_controller[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_controller, this, _1, _2));
45         _port.parser()->channel_pitchbend[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_pitchbend, this, _1, _2));
46
47         _port.parser()->reset.connect_same_thread (*this, boost::bind (&Channel::process_reset, this, _1));
48 }
49
50 void
51 Channel::reset (timestamp_t timestamp, framecnt_t /*nframes*/, bool notes_off)
52 {
53         _program_number = _channel_number;
54         _bank_number = 0;
55         _pitch_bend = 0;
56
57         _last_note_on = 0;
58         _last_note_off = 0;
59         _last_on_velocity = 0;
60         _last_off_velocity = 0;
61
62         if (notes_off) {
63                 all_notes_off (timestamp);
64         }
65
66         memset (_polypress, 0, sizeof (_polypress));
67         memset (_controller_msb, 0, sizeof (_controller_msb));
68         memset (_controller_lsb, 0, sizeof (_controller_lsb));
69        
70         /* zero all controllers XXX not necessarily the right thing */
71
72         memset (_controller_val, 0, sizeof (_controller_val));
73
74         for (int n = 0; n < 128; n++) {
75                 _controller_14bit[n] = false;
76         }
77
78         _rpn_msb = 0;
79         _rpn_lsb = 0;
80         _nrpn_msb = 0;
81         _nrpn_lsb = 0;
82
83         _omni = true;
84         _poly = false;
85         _mono = true;
86         _notes_on = 0;
87 }
88
89 void
90 Channel::process_note_off (Parser & /*parser*/, EventTwoBytes *tb) 
91 {
92         _last_note_off = tb->note_number;
93         _last_off_velocity = tb->velocity;
94
95         if (_notes_on) {
96                 _notes_on--;
97         }
98 }
99
100 void
101 Channel::process_note_on (Parser & /*parser*/, EventTwoBytes *tb) 
102 {
103         _last_note_on = tb->note_number;
104         _last_on_velocity = tb->velocity;
105         _notes_on++;
106 }
107
108 void
109 Channel::process_controller (Parser & /*parser*/, EventTwoBytes *tb) 
110 {
111         unsigned short cv;
112
113         /* XXX arguably need a lock here to protect non-atomic changes
114            to controller_val[...]. or rather, need to make sure that
115            all changes *are* atomic.
116         */
117
118         if (tb->controller_number <= 31) { /* unsigned: no test for >= 0 */
119
120                 /* if this controller is already known to use 14 bits,
121                    then treat this value as the MSB, and combine it 
122                    with the existing LSB.
123
124                    otherwise, just treat it as a 7 bit value, and set
125                    it directly.
126                 */
127
128                 cv = (unsigned short) _controller_val[tb->controller_number];
129
130                 if (_controller_14bit[tb->controller_number]) {
131                         cv = ((tb->value << 7) | (cv & 0x7f));
132                 } else {
133                         cv = tb->value;
134                 }
135
136                 _controller_val[tb->controller_number] = (controller_value_t)cv;
137
138         } else if ((tb->controller_number >= 32 && 
139                     tb->controller_number <= 63)) {
140                    
141                 cv = (unsigned short) _controller_val[tb->controller_number];
142
143                 /* LSB for CC 0-31 arrived. 
144
145                    If this is the first time (i.e. its currently
146                    flagged as a 7 bit controller), mark the
147                    controller as 14 bit, adjust the existing value
148                    to be the MSB, and OR-in the new LSB value. 
149
150                    otherwise, OR-in the new low 7bits with the old
151                    high 7.
152                 */
153
154                 int cn = tb->controller_number - 32;
155                    
156                 if (_controller_14bit[cn] == false) {
157                         _controller_14bit[cn] = true;
158                         cv = (cv << 7) | (tb->value & 0x7f);
159                 } else {
160                         cv = (cv & 0x3f80) | (tb->value & 0x7f);
161                 }
162
163                 _controller_val[tb->controller_number] = 
164                         (controller_value_t) cv;
165         } else {
166
167                 /* controller can only take 7 bit values */
168                 
169                 _controller_val[tb->controller_number] = 
170                         (controller_value_t) tb->value;
171         }
172
173         /* bank numbers are special, in that they have their own signal
174          */
175
176         if (tb->controller_number == 0) {
177                 _bank_number = (unsigned short) _controller_val[0];
178                 _port.parser()->bank_change (*_port.parser(), _bank_number);
179                 _port.parser()->channel_bank_change[_channel_number] (*_port.parser(), _bank_number);
180         }
181
182 }
183
184 void
185 Channel::process_program_change (Parser & /*parser*/, MIDI::byte val) 
186 {
187         _program_number = val;
188 }
189
190 void
191 Channel::process_chanpress (Parser & /*parser*/, MIDI::byte val) 
192 {
193         _chanpress = val;
194 }
195
196 void
197 Channel::process_polypress (Parser & /*parser*/, EventTwoBytes *tb) 
198 {
199         _polypress[tb->note_number] = tb->value;
200 }
201
202 void
203 Channel::process_pitchbend (Parser & /*parser*/, pitchbend_t val) 
204 {
205         _pitch_bend = val;
206 }
207
208 void
209 Channel::process_reset (Parser & /*parser*/) 
210 {
211         reset (0, 1);
212 }
213
214 /** Write a message to a channel.
215  * \return true if success
216  */
217 bool
218 Channel::channel_msg (MIDI::byte id, MIDI::byte val1, MIDI::byte val2, timestamp_t timestamp)
219 {
220         unsigned char msg[3];
221         int len = 0;
222
223         msg[0] = id | (_channel_number & 0xf);
224
225         switch (id) {
226         case off:
227                 msg[1] = val1 & 0x7F;
228                 msg[2] = val2 & 0x7F;
229                 len = 3;
230                 break;
231
232         case on:
233                 msg[1] = val1 & 0x7F;
234                 msg[2] = val2 & 0x7F;
235                 len = 3;
236                 break;
237
238         case MIDI::polypress:
239                 msg[1] = val1 & 0x7F;
240                 msg[2] = val2 & 0x7F;
241                 len = 3;
242                 break;
243
244         case controller:
245                 msg[1] = val1 & 0x7F;
246                 msg[2] = val2 & 0x7F;
247                 len = 3;
248                 break;
249
250         case MIDI::program:
251                 msg[1] = val1 & 0x7F;
252                 len = 2;
253                 break;
254
255         case MIDI::chanpress:
256                 msg[1] = val1 & 0x7F;
257                 len = 2;
258                 break;
259
260         case MIDI::pitchbend:
261                 msg[1] = val1 & 0x7F;
262                 msg[2] = val2 & 0x7F;
263                 len = 3;
264                 break;
265         }
266
267         return _port.midimsg (msg, len, timestamp);
268 }