SVG of thorsten's editor track/bus list icons
[ardour2.git] / libs / midi++2 / channel.cc
blobae889058c4f973e0e66c28d9f6f3ac41f32a196f
1 /*
2 Copyright (C) 1998-99 Paul Barton-Davis
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.
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.
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.
18 $Id$
21 #include <cstring>
22 #include "midi++/types.h"
23 #include "midi++/port.h"
24 #include "midi++/channel.h"
26 using namespace MIDI;
28 Channel::Channel (byte channelnum, Port &p) : _port (p)
30 _channel_number = channelnum;
32 reset (0, 1, false);
35 void
36 Channel::connect_signals ()
38 _port.parser()->channel_pressure[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_chanpress, this, _1, _2));
39 _port.parser()->channel_note_on[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_note_on, this, _1, _2));
40 _port.parser()->channel_note_off[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_note_off, this, _1, _2));
41 _port.parser()->channel_poly_pressure[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_polypress, this, _1, _2));
42 _port.parser()->channel_program_change[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_program_change, this, _1, _2));
43 _port.parser()->channel_controller[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_controller, this, _1, _2));
44 _port.parser()->channel_pitchbend[_channel_number].connect_same_thread (*this, boost::bind (&Channel::process_pitchbend, this, _1, _2));
46 _port.parser()->reset.connect_same_thread (*this, boost::bind (&Channel::process_reset, this, _1));
49 void
50 Channel::reset (timestamp_t timestamp, framecnt_t /*nframes*/, bool notes_off)
52 _program_number = _channel_number;
53 _bank_number = 0;
54 _pitch_bend = 0;
56 _last_note_on = 0;
57 _last_note_off = 0;
58 _last_on_velocity = 0;
59 _last_off_velocity = 0;
61 if (notes_off) {
62 all_notes_off (timestamp);
65 memset (_polypress, 0, sizeof (_polypress));
66 memset (_controller_msb, 0, sizeof (_controller_msb));
67 memset (_controller_lsb, 0, sizeof (_controller_lsb));
69 /* zero all controllers XXX not necessarily the right thing */
71 memset (_controller_val, 0, sizeof (_controller_val));
73 for (int n = 0; n < 128; n++) {
74 _controller_14bit[n] = false;
77 _rpn_msb = 0;
78 _rpn_lsb = 0;
79 _nrpn_msb = 0;
80 _nrpn_lsb = 0;
82 _omni = true;
83 _poly = false;
84 _mono = true;
85 _notes_on = 0;
88 void
89 Channel::process_note_off (Parser & /*parser*/, EventTwoBytes *tb)
91 _last_note_off = tb->note_number;
92 _last_off_velocity = tb->velocity;
94 if (_notes_on) {
95 _notes_on--;
99 void
100 Channel::process_note_on (Parser & /*parser*/, EventTwoBytes *tb)
102 _last_note_on = tb->note_number;
103 _last_on_velocity = tb->velocity;
104 _notes_on++;
107 void
108 Channel::process_controller (Parser & /*parser*/, EventTwoBytes *tb)
110 unsigned short cv;
112 /* XXX arguably need a lock here to protect non-atomic changes
113 to controller_val[...]. or rather, need to make sure that
114 all changes *are* atomic.
117 if (tb->controller_number <= 31) { /* unsigned: no test for >= 0 */
119 /* if this controller is already known to use 14 bits,
120 then treat this value as the MSB, and combine it
121 with the existing LSB.
123 otherwise, just treat it as a 7 bit value, and set
124 it directly.
127 cv = (unsigned short) _controller_val[tb->controller_number];
129 if (_controller_14bit[tb->controller_number]) {
130 cv = ((tb->value << 7) | (cv & 0x7f));
131 } else {
132 cv = tb->value;
135 _controller_val[tb->controller_number] = (controller_value_t)cv;
137 } else if ((tb->controller_number >= 32 &&
138 tb->controller_number <= 63)) {
140 cv = (unsigned short) _controller_val[tb->controller_number];
142 /* LSB for CC 0-31 arrived.
144 If this is the first time (i.e. its currently
145 flagged as a 7 bit controller), mark the
146 controller as 14 bit, adjust the existing value
147 to be the MSB, and OR-in the new LSB value.
149 otherwise, OR-in the new low 7bits with the old
150 high 7.
153 int cn = tb->controller_number - 32;
155 if (_controller_14bit[cn] == false) {
156 _controller_14bit[cn] = true;
157 cv = (cv << 7) | (tb->value & 0x7f);
158 } else {
159 cv = (cv & 0x3f80) | (tb->value & 0x7f);
162 _controller_val[tb->controller_number] =
163 (controller_value_t) cv;
164 } else {
166 /* controller can only take 7 bit values */
168 _controller_val[tb->controller_number] =
169 (controller_value_t) tb->value;
172 /* bank numbers are special, in that they have their own signal
175 if (tb->controller_number == 0) {
176 _bank_number = (unsigned short) _controller_val[0];
177 _port.parser()->bank_change (*_port.parser(), _bank_number);
178 _port.parser()->channel_bank_change[_channel_number] (*_port.parser(), _bank_number);
183 void
184 Channel::process_program_change (Parser & /*parser*/, byte val)
186 _program_number = val;
189 void
190 Channel::process_chanpress (Parser & /*parser*/, byte val)
192 _chanpress = val;
195 void
196 Channel::process_polypress (Parser & /*parser*/, EventTwoBytes *tb)
198 _polypress[tb->note_number] = tb->value;
201 void
202 Channel::process_pitchbend (Parser & /*parser*/, pitchbend_t val)
204 _pitch_bend = val;
207 void
208 Channel::process_reset (Parser & /*parser*/)
210 reset (0, 1);
213 /** Write a message to a channel.
214 * \return true if success
216 bool
217 Channel::channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp)
219 unsigned char msg[3];
220 int len = 0;
222 msg[0] = id | (_channel_number & 0xf);
224 switch (id) {
225 case off:
226 msg[1] = val1 & 0x7F;
227 msg[2] = val2 & 0x7F;
228 len = 3;
229 break;
231 case on:
232 msg[1] = val1 & 0x7F;
233 msg[2] = val2 & 0x7F;
234 len = 3;
235 break;
237 case MIDI::polypress:
238 msg[1] = val1 & 0x7F;
239 msg[2] = val2 & 0x7F;
240 len = 3;
241 break;
243 case controller:
244 msg[1] = val1 & 0x7F;
245 msg[2] = val2 & 0x7F;
246 len = 3;
247 break;
249 case MIDI::program:
250 msg[1] = val1 & 0x7F;
251 len = 2;
252 break;
254 case MIDI::chanpress:
255 msg[1] = val1 & 0x7F;
256 len = 2;
257 break;
259 case MIDI::pitchbend:
260 msg[1] = val1 & 0x7F;
261 msg[2] = val2 & 0x7F;
262 len = 3;
263 break;
266 return _port.midimsg (msg, len, timestamp);