1 /*
2 * Copyright (C) 2018-2019 Jan Lentfer <jan.lentfer@web.de>
3 * Copyright (C) 2018 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2018 Robin Gareus <robin@gareus.org>
5 * Copyright (C) 2018 Térence Clastres <t.clastres@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <algorithm>
23
24 #include "ardour/debug.h"
25 #include "ardour/mute_control.h"
26 #include "ardour/session.h"
27 #include "ardour/solo_control.h"
28 #include "ardour/solo_isolate_control.h"
29
30 #include "launch_control_xl.h"
31
32 using namespace ArdourSurface;
33 using namespace ARDOUR;
34 using namespace PBD;
35 using std::cerr;
36
37 void
build_maps()38 LaunchControlXL::build_maps ()
39 {
40 cc_knob_map.clear();
41 id_knob_map.clear();
42 cc_fader_map.clear();
43 id_fader_map.clear();
44 nn_note_button_map.clear();
45 id_note_button_map.clear();
46 cc_controller_button_map.clear();
47 id_controller_button_map.clear();
48
49 /* Knobs */
50 boost::shared_ptr<Knob> knob;
51
52 #define MAKE_KNOB(i,cc,index,c_on,c_off,a) \
53 knob.reset (new Knob ((i), (cc), (index), (c_on), (c_off), (a), (*this))); \
54 cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
55 id_knob_map.insert (std::make_pair (knob->id(), knob));
56 #define MAKE_DM_KNOB(i,cc,index,c_on,c_off,action,check) \
57 knob.reset (new Knob ((i), (cc), (index), (c_on), (c_off), (action), (check), (*this))); \
58 cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
59 id_knob_map.insert (std::make_pair (knob->id(), knob));
60
61 if (!device_mode()) { /* mixer mode */
62 MAKE_KNOB (SendA1, 13, 0, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 0)));
63 MAKE_KNOB (SendA2, 14, 1, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 1)));
64 MAKE_KNOB (SendA3, 15, 2, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 2)));
65 MAKE_KNOB (SendA4, 16, 3, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 3)));
66 MAKE_KNOB (SendA5, 17, 4, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 4)));
67 MAKE_KNOB (SendA6, 18, 5, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 5)));
68 MAKE_KNOB (SendA7, 19, 6, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 6)));
69 MAKE_KNOB (SendA8, 20, 7, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 7)));
70
71 MAKE_KNOB (SendB1, 29, 8, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 0)));
72 MAKE_KNOB (SendB2, 30, 9, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 1)));
73 MAKE_KNOB (SendB3, 31, 10, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 2)));
74 MAKE_KNOB (SendB4, 32, 11, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 3)));
75 MAKE_KNOB (SendB5, 33, 12, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 4)));
76 MAKE_KNOB (SendB6, 34, 13, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 5)));
77 MAKE_KNOB (SendB7, 35, 14, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 6)));
78 MAKE_KNOB (SendB8, 36, 15, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 7)));
79
80 MAKE_KNOB (Pan1, 49, 16, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 0)));
81 MAKE_KNOB (Pan2, 50, 17, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 1)));
82 MAKE_KNOB (Pan3, 51, 18, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 2)));
83 MAKE_KNOB (Pan4, 52, 19, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 3)));
84 MAKE_KNOB (Pan5, 53, 20, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 4)));
85 MAKE_KNOB (Pan6, 54, 21, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 5)));
86 MAKE_KNOB (Pan7, 55, 22, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 6)));
87 MAKE_KNOB (Pan8, 56, 23, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 7)));
88
89 } else { /* device mode */
90
91 #ifdef MIXBUS // from here Mixbus Standard + 32C
92 MAKE_DM_KNOB (SendB5, 33, 12, RedFull, RedLow, boost::function<void ()>
93 (boost::bind (&LaunchControlXL::dm_trim, this, SendB5)),
94 boost::bind(&LaunchControlXL::dm_check_trim, this));
95 MAKE_DM_KNOB (SendB6, 34, 13, GreenFull, GreenLow, boost::function<void ()>
96 (boost::bind (&LaunchControlXL::dm_mb_comp, this, SendB6, CompMakeup)),
97 boost::bind(&LaunchControlXL::dm_mb_comp_enabled,this));
98 MAKE_DM_KNOB (SendB7, 35, 14, GreenFull, GreenLow, boost::function<void ()>
99 (boost::bind (&LaunchControlXL::dm_mb_comp, this, SendB7, CompSpeed)),
100 boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
101 MAKE_DM_KNOB (SendB8, 36, 15, GreenFull, GreenLow, boost::function<void ()>
102 (boost::bind (&LaunchControlXL::dm_mb_comp, this, SendB8, CompMode)),
103 boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
104
105 /* Pan Knobs -> Sends */
106 for (uint8_t i = 0; i < 8; ++i) {
107 MAKE_DM_KNOB (static_cast<KnobID>(i + 16), (i + 49), (i + 16), GreenLow, YellowLow, boost::function<void()>
108 (boost::bind (&LaunchControlXL::dm_mb_sends, this, static_cast<KnobID>(i + 16))),
109 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_check_send_knob, this, static_cast<KnobID>(i + 16))));
110 }
111
112 #ifdef MIXBUS32C // from here 32C only
113
114 if (first_selected_stripable() && (first_selected_stripable()->is_master() || first_selected_stripable()->mixbus())) {
115 MAKE_DM_KNOB (SendA1, 13, 0, AmberFull, AmberLow, boost::function<void ()>
116 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA1, true, 0)),
117 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
118 MAKE_DM_KNOB (SendA2, 14, 1, AmberFull, AmberLow, boost::function<void ()>
119 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA2, true, 1)),
120 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 1)));
121 MAKE_DM_KNOB (SendA3, 15, 2, AmberFull, AmberLow, boost::function<void ()>
122 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA3, true, 2)),
123 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 2)));
124 MAKE_DM_KNOB (SendA6, 18, 5, RedLow, RedLow, boost::function<void ()>
125 (boost::bind (&LaunchControlXL::dm_pan_width, this, SendA6)),
126 boost::bind(&LaunchControlXL::dm_check_pan_width, this));
127 MAKE_DM_KNOB (SendA7, 19, 6, AmberLow, AmberLow, boost::function<void ()>
128 (boost::bind (&LaunchControlXL::dm_mb_tapedrive, this, SendA7)),
129 boost::bind(&LaunchControlXL::dm_mb_has_tapedrive, this));
130 } else {
131 MAKE_DM_KNOB (SendA1, 13, 0, AmberFull, AmberLow, boost::function<void ()>
132 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA1, false, 0)),
133 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
134 MAKE_DM_KNOB (SendA2, 14, 1, AmberFull, AmberLow, boost::function<void ()>
135 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA2, true, 0)),
136 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
137 MAKE_DM_KNOB (SendA3, 15, 2, YellowLow, AmberLow, boost::function<void ()>
138 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA3, false, 1)),
139 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
140 MAKE_DM_KNOB (SendA4, 16, 3, YellowLow, AmberLow, boost::function<void ()>
141 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA4, true, 1)),
142 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 1)));
143 MAKE_DM_KNOB (SendA5, 17, 4, AmberFull, AmberLow, boost::function<void ()>
144 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA5, false, 2)),
145 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
146 MAKE_DM_KNOB (SendA6, 18, 5, AmberFull, AmberLow, boost::function<void ()>
147 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA6, true, 2)),
148 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 2)));
149 MAKE_DM_KNOB (SendA7, 19, 6, YellowLow, AmberLow, boost::function<void ()>
150 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA7, false, 3)),
151 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
152 MAKE_DM_KNOB (SendA8, 20, 7, YellowLow, AmberLow, boost::function<void ()>
153 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA8, true, 3)),
154 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 3)));
155 }
156 MAKE_DM_KNOB (SendB1, 29, 8, YellowFull, AmberLow, boost::function<void ()>
157 (boost::bind (&LaunchControlXL::dm_mb_flt_frq, this, SendB1, true)),
158 boost::bind(&LaunchControlXL::dm_mb_flt_enabled, this));
159 MAKE_DM_KNOB (SendB2, 30, 9, YellowFull, AmberLow, boost::function<void ()>
160 (boost::bind (&LaunchControlXL::dm_mb_flt_frq, this, SendB2, false)),
161 boost::bind(&LaunchControlXL::dm_mb_flt_enabled, this));
162 MAKE_DM_KNOB (SendB4, 32, 11, RedLow, AmberLow, boost::function<void ()>
163 (boost::bind (&LaunchControlXL::dm_pan_azi, this, SendB4)),
164 boost::bind(&LaunchControlXL::dm_check_pan_azi, this));
165
166 #else // from here Mixbus Standard only
167 MAKE_DM_KNOB (SendA1, 13, 0, AmberFull, AmberLow, boost::function<void ()>
168 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA1, true, 0)),
169 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
170 MAKE_DM_KNOB (SendA2, 14, 1, AmberFull, AmberLow, boost::function<void ()>
171 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA2, true, 1)),
172 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 1)));
173 MAKE_DM_KNOB (SendA3, 15, 2, AmberFull, AmberLow, boost::function<void ()>
174 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA3, true, 2)),
175 boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 2)));
176 MAKE_DM_KNOB (SendA5, 17, 4, RedLow, AmberLow, boost::function<void ()>
177 (boost::bind (&LaunchControlXL::dm_pan_azi, this, SendA5)),
178 boost::bind(&LaunchControlXL::dm_check_pan_azi, this));
179 MAKE_DM_KNOB (SendA6, 18, 5, RedLow, RedLow, boost::function<void ()>
180 (boost::bind (&LaunchControlXL::dm_pan_width, this, SendA6)),
181 boost::bind(&LaunchControlXL::dm_check_pan_width, this));
182 MAKE_DM_KNOB (SendA7, 19, 6, AmberLow, AmberLow, boost::function<void ()>
183 (boost::bind (&LaunchControlXL::dm_mb_tapedrive, this, SendA7)),
184 boost::bind(&LaunchControlXL::dm_mb_has_tapedrive, this));
185 MAKE_DM_KNOB (SendB1, 29, 8, YellowFull, AmberLow, boost::function<void ()>
186 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendB1, false, 0)),
187 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
188 MAKE_DM_KNOB (SendB2, 30, 9, YellowFull, AmberLow, boost::function<void ()>
189 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendB2, false, 1)),
190 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
191 MAKE_DM_KNOB (SendB3, 31, 10, YellowFull, AmberLow, boost::function<void ()>
192 (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendB3, false, 2)),
193 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
194 MAKE_DM_KNOB (SendB4, 32, 11, YellowFull, AmberLow, boost::function<void ()>
195 (boost::bind (&LaunchControlXL::dm_mb_flt_frq, this, SendB4, true)),
196 boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
197 #endif
198 #else // from here Ardour
199 #endif
200 }
201
202
203 /* Faders */
204 boost::shared_ptr<Fader> fader;
205
206 #define MAKE_FADER(i,cc,a) \
207 fader.reset (new Fader ((i), (cc), (a))); \
208 cc_fader_map.insert (std::make_pair (fader->controller_number(), fader)); \
209 id_fader_map.insert (std::make_pair (fader->id(), fader))
210
211 if (!device_mode()) { /* mix mode */
212 for (uint8_t i = 0; i < 8; ++i) {
213 MAKE_FADER(static_cast<FaderID>(i), i+77, boost::function<void()>
214 (boost::bind (&LaunchControlXL::fader, this, i)));
215 }
216
217 } else { /* device mode */
218 MAKE_FADER(Fader1, 77, boost::function<void()>
219 (boost::bind (&LaunchControlXL::dm_fader, this, Fader1)));
220 #ifdef MIXBUS
221 MAKE_FADER(Fader2, 78, boost::function<void()>
222 (boost::bind (&LaunchControlXL::dm_mb_comp_thresh, this, Fader2)));
223 #endif
224 }
225
226 /* Buttons */
227 boost::shared_ptr<ControllerButton> controller_button;
228 boost::shared_ptr<NoteButton> note_button;
229
230
231 #define MAKE_TRACK_BUTTON_PRESS(i,nn,index,c_on,c_off,p,check) \
232 note_button.reset (new TrackButton ((i), (nn), (index), (c_on), (c_off), (p), \
233 boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (check), (*this))); \
234 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
235 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
236 #define MAKE_CTRL_BUTTON_PRESS(i,nn,index,c_on,c_off,p,check) \
237 note_button.reset (new TrackButton ((i), (nn), (index), (c_on), (c_off), (p), \
238 boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (check), (*this))); \
239 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
240 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
241 #define MAKE_SELECT_BUTTON_PRESS(i,cc,index,p) \
242 controller_button.reset (new SelectButton ((i), (cc), (index), (p), \
243 boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (*this))); \
244 cc_controller_button_map.insert (std::make_pair (controller_button->controller_number(), controller_button)); \
245 id_controller_button_map.insert (std::make_pair (controller_button->id(), controller_button))
246 #define MAKE_TRACK_STATE_BUTTON_PRESS(i,nn,index,p) \
247 note_button.reset (new TrackStateButton ((i), (nn), (index), (p), \
248 boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (*this))); \
249 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
250 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
251 #define MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(i,nn,index, p,r,l) \
252 note_button.reset (new TrackStateButton ((i), (nn), (index), (p), (r), (l), (*this))); \
253 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
254 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
255
256 /* Track Focus Buttons */
257 if (!device_mode()) { /* mixer mode */
258 for (uint8_t i = 0; i < 4; ++i) {
259 MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i), i+41, i+24, YellowFull, YellowLow,
260 boost::function<void()> (boost::bind (&LaunchControlXL::button_track_focus, this, i)),
261 boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
262 }
263
264 for (uint8_t i = 0; i < 4; ++i) {
265 MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i+4), i+57, i+28, YellowFull, YellowLow,
266 boost::function<void()> (boost::bind (&LaunchControlXL::button_track_focus, this, i+4)),
267 boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
268 }
269
270 } else { /* device mode */
271 #ifdef MIXBUS
272 for (uint8_t i = 0; i < 4; ++i) {
273 MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i), i+41, i+24, GreenFull, YellowLow,
274 boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_send_switch, this, static_cast<ButtonID>(i))),
275 boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_mb_check_send_button, this, i)));
276
277 }
278
279 for (uint8_t i = 0; i < 4; ++i) {
280 MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i+4), i+57, i+28, GreenFull, YellowLow,
281 boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_send_switch, this, static_cast<ButtonID>(i+4))),
282 boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_mb_check_send_button, this, i+4)));
283 }
284 #endif
285 }
286 /* Track Control Buttons */
287 if (!device_mode()) { /* mixer mode */
288 /* Control Buttons in mix mode change their color dynamically so we won't set them here */
289 for (uint8_t i = 0; i < 4; ++i) {
290 MAKE_CTRL_BUTTON_PRESS(static_cast<ButtonID>(i+8), i+73, i+32, Off, Off,
291 boost::function<void()> (boost::bind (&LaunchControlXL::button_press_track_control, this, i)),
292 boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
293 }
294
295 for (uint8_t i = 0; i < 4; ++i) {
296 MAKE_CTRL_BUTTON_PRESS(static_cast<ButtonID>(i+12), i+89, i+36, Off, Off,
297 boost::function<void()> (boost::bind (&LaunchControlXL::button_press_track_control, this, i+4)),
298 boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
299 }
300
301 } else { /*device mode */
302 #ifdef MIXBUS // from here Mixbus Standard + 32C
303 MAKE_CTRL_BUTTON_PRESS(Control1, 73, 32, YellowFull, YellowLow, (boost::bind (&LaunchControlXL::dm_mute_switch, this)),
304 boost::bind (&LaunchControlXL::dm_mute_enabled, this));
305 MAKE_CTRL_BUTTON_PRESS(Control2, 74, 33, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_solo_switch, this)),
306 boost::bind (&LaunchControlXL::dm_solo_enabled, this));
307 MAKE_CTRL_BUTTON_PRESS(Control3, 75, 34, AmberFull, AmberLow, (boost::bind (&LaunchControlXL::dm_mb_eq_switch, this)),
308 boost::function<uint8_t()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
309
310
311 #ifdef MIXBUS32C // from here 32C only
312 MAKE_CTRL_BUTTON_PRESS(Control4, 76, 35, AmberFull, AmberLow,
313 boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_eq_shape_switch, this, 0)),
314 boost::function<uint8_t()> (boost::bind(&LaunchControlXL::dm_mb_eq_shape_enabled, this, 0 )));
315 MAKE_CTRL_BUTTON_PRESS(Control5, 89, 36, AmberFull, AmberLow,
316 boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_eq_shape_switch, this, 3)),
317 boost::function<uint8_t()> (boost::bind(&LaunchControlXL::dm_mb_eq_shape_enabled, this, 3 )));
318 MAKE_CTRL_BUTTON_PRESS(Control6, 90, 37, YellowFull, YellowLow, (boost::bind (&LaunchControlXL::dm_mb_flt_switch, this)),
319 boost::bind(&LaunchControlXL::dm_mb_flt_enabled, this));
320 MAKE_CTRL_BUTTON_PRESS(Control7, 91, 38, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_master_assign_switch, this)),
321 boost::bind(&LaunchControlXL::dm_mb_master_assign_enabled, this));
322 MAKE_CTRL_BUTTON_PRESS(Control8, 92, 39, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_comp_switch, this)),
323 boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
324
325 #else // from here Mixbus Standard only
326 MAKE_CTRL_BUTTON_PRESS(Control5, 89, 36, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_master_assign_switch, this)),
327 boost::bind(&LaunchControlXL::dm_mb_master_assign_enabled, this));
328 MAKE_CTRL_BUTTON_PRESS(Control7, 91, 38, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_comp_switch, this)),
329 boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
330 MAKE_CTRL_BUTTON_PRESS(Control8, 92, 39, RedFull, RedLow, (boost::bind (&LaunchControlXL::dm_recenable_switch, this)),
331 boost::bind(&LaunchControlXL::dm_recenable_enabled, this));
332
333 #endif
334 #else // Ardour
335 #endif
336 }
337
338 /* Select and Mode Buttons on the right side */
339
340 /* Sends Select buttons are independent of mode */
341 MAKE_SELECT_BUTTON_PRESS(SelectUp, 104, 44, boost::function<void()> (boost::bind (&LaunchControlXL::send_bank_switch, this, false)));
342 MAKE_SELECT_BUTTON_PRESS(SelectDown, 105, 45, boost::function<void()> (boost::bind (&LaunchControlXL::send_bank_switch, this, true)));
343
344 /* Device Button needs to be always there */
345 MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Device, 105, 40,
346 boost::bind (&LaunchControlXL::relax, this) ,
347 boost::bind (&LaunchControlXL::button_device, this),
348 boost::bind (&LaunchControlXL::button_device_long_press, this));
349
350
351 /* Cancel all mute / solo is available in both modes */
352
353 MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Mute, 106, 41,
354 boost::bind (&LaunchControlXL::relax, this) ,
355 boost::bind (&LaunchControlXL::button_mute, this),
356 boost::bind (&LaunchControlXL::button_mute_long_press, this));
357
358 MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Solo, 107, 42,
359 boost::bind (&LaunchControlXL::relax, this) ,
360 boost::bind (&LaunchControlXL::button_solo, this),
361 boost::bind (&LaunchControlXL::button_solo_long_press, this));
362
363
364 if (!device_mode()) { /* mixer mode */
365 MAKE_SELECT_BUTTON_PRESS(SelectLeft, 106, 46, boost::bind (&LaunchControlXL::button_select_left, this));
366 MAKE_SELECT_BUTTON_PRESS(SelectRight, 107, 47, boost::bind (&LaunchControlXL::button_select_right, this));
367
368 MAKE_TRACK_STATE_BUTTON_PRESS(Record, 108, 43, boost::bind (&LaunchControlXL::button_record, this));
369
370 } else { /* device mode */
371 MAKE_SELECT_BUTTON_PRESS(SelectLeft, 106, 46, boost::bind (&LaunchControlXL::dm_select_prev_strip, this));
372 MAKE_SELECT_BUTTON_PRESS(SelectRight, 107, 47, boost::bind (&LaunchControlXL::dm_select_next_strip, this));
373 }
374 }
375
376 std::string
button_name_by_id(ButtonID id)377 LaunchControlXL::button_name_by_id (ButtonID id)
378 {
379 switch (id) {
380 case Device:
381 return "Device";
382 case Mute:
383 return "Mute";
384 case Solo:
385 return "Solo";
386 case Record:
387 return "Record";
388 case SelectUp:
389 return "Select Up";
390 case SelectDown:
391 return "Select Down";
392 case SelectRight:
393 return "Select Right";
394 case SelectLeft:
395 return "Select Left";
396 case Focus1:
397 return "Focus 1";
398 case Focus2:
399 return "Focus 2";
400 case Focus3:
401 return "Focus 3";
402 case Focus4:
403 return "Focus 4";
404 case Focus5:
405 return "Focus 5";
406 case Focus6:
407 return "Focus 6";
408 case Focus7:
409 return "Focus 7";
410 case Focus8:
411 return "Focus 8";
412 case Control1:
413 return "Control 1";
414 case Control2:
415 return "Control 2";
416 case Control3:
417 return "Control 3";
418 case Control4:
419 return "Control 4";
420 case Control5:
421 return "Control 5";
422 case Control6:
423 return "Control 6";
424 case Control7:
425 return "Control 7";
426 case Control8:
427 return "Control 8";
428 default:
429 break;
430 }
431
432 return "???";
433 }
434
435 std::string
knob_name_by_id(KnobID id)436 LaunchControlXL::knob_name_by_id (KnobID id)
437 {
438 switch (id) {
439 case SendA1:
440 return "SendA 1";
441 case SendA2:
442 return "SendA 2";
443 case SendA3:
444 return "SendA 3";
445 case SendA4:
446 return "SendA 4";
447 case SendA5:
448 return "SendA 5";
449 case SendA6:
450 return "SendA 6";
451 case SendA7:
452 return "SendA 7";
453 case SendA8:
454 return "SendA 8";
455 case SendB1:
456 return "SendB 1";
457 case SendB2:
458 return "SendB 2";
459 case SendB3:
460 return "SendB 3";
461 case SendB4:
462 return "SendB 4";
463 case SendB5:
464 return "SendB 5";
465 case SendB6:
466 return "SendB 6";
467 case SendB7:
468 return "SendB 7";
469 case SendB8:
470 return "SendB 8";
471 case Pan1:
472 return "Pan 1";
473 case Pan2:
474 return "Pan 2";
475 case Pan3:
476 return "Pan 3";
477 case Pan4:
478 return "Pan 4";
479 case Pan5:
480 return "Pan 5";
481 case Pan6:
482 return "Pan 6";
483 case Pan7:
484 return "Pan 7";
485 case Pan8:
486 return "Pan 8";
487 default:
488 break;
489 }
490
491 return "???";
492 }
493
494 std::string
fader_name_by_id(FaderID id)495 LaunchControlXL::fader_name_by_id (FaderID id)
496 {
497 switch (id) {
498 case Fader1:
499 return "Fader 1";
500 case Fader2:
501 return "Fader 2";
502 case Fader3:
503 return "Fader 3";
504 case Fader4:
505 return "Fader 4";
506 case Fader5:
507 return "Fader 5";
508 case Fader6:
509 return "Fader 6";
510 case Fader7:
511 return "Fader 7";
512 case Fader8:
513 return "Fader 8";
514 default:
515 break;
516 }
517
518 return "???";
519 }
520
521 boost::shared_ptr<LaunchControlXL::TrackButton>
track_button_by_range(uint8_t n,uint8_t first,uint8_t middle)522 LaunchControlXL::track_button_by_range(uint8_t n, uint8_t first, uint8_t middle)
523 {
524 NNNoteButtonMap::iterator b;
525 if ( n < 4) {
526 b = nn_note_button_map.find (first + n);
527 } else {
528 b = nn_note_button_map.find (middle + n - 4);
529 }
530
531 if (b != nn_note_button_map.end()) {
532 return boost::dynamic_pointer_cast<TrackButton> (b->second);
533 }
534
535 return boost::shared_ptr<TrackButton>();
536 }
537
538 void
update_track_focus_led(uint8_t n)539 LaunchControlXL::update_track_focus_led(uint8_t n)
540 {
541 boost::shared_ptr<TrackButton> b = focus_button_by_column(n);
542
543 if (!b) {
544 return;
545 }
546
547 if (stripable[n]) {
548 if ( stripable[n]->is_selected() ) {
549 b->set_color(YellowFull);
550 } else {
551 b->set_color(AmberLow);
552 }
553 } else {
554 b->set_color(Off);
555 }
556
557 write (b->state_msg());
558 }
559
560 boost::shared_ptr<AutomationControl>
get_ac_by_state(uint8_t n)561 LaunchControlXL::get_ac_by_state(uint8_t n) {
562 boost::shared_ptr<AutomationControl> ac;
563
564 switch(track_mode()) {
565 case TrackMute:
566 ac = stripable[n]->mute_control();
567 break;
568
569 case TrackSolo:
570 ac = stripable[n]->solo_control();
571 break;
572
573 case TrackRecord:
574 ac = stripable[n]->rec_enable_control();
575 break;
576
577 default:
578 break;
579 }
580 return ac;
581 }
582
583 boost::shared_ptr<LaunchControlXL::Knob>
knob_by_id(KnobID id)584 LaunchControlXL::knob_by_id(KnobID id)
585 {
586 IDKnobMap::iterator k = id_knob_map.find(id);
587 return boost::dynamic_pointer_cast<Knob> (k->second);
588
589 }
590
591 boost::shared_ptr<LaunchControlXL::Knob>*
knobs_by_column(uint8_t col,boost::shared_ptr<Knob> * knob_col)592 LaunchControlXL::knobs_by_column(uint8_t col, boost::shared_ptr<Knob>* knob_col)
593 {
594 for (uint8_t n = 0; n < 3; ++n) {
595 if (id_knob_map.find(static_cast<KnobID>(col+n*8)) != id_knob_map.end()) {
596 knob_col[n] = id_knob_map.find(static_cast<KnobID>(col+n*8))->second;
597 }
598 }
599
600 return knob_col;
601 }
602
603 void
update_knob_led_by_id(uint8_t id,LEDColor color)604 LaunchControlXL::update_knob_led_by_id (uint8_t id, LEDColor color)
605 {
606
607 boost::shared_ptr<Knob> knob;
608 IDKnobMap::iterator k = id_knob_map.find(static_cast<KnobID>(id));
609
610 if (k != id_knob_map.end()) {
611 knob = k->second;
612 }
613
614 knob->set_color(color);
615 write (knob->state_msg());
616 }
617
618 void
update_knob_led_by_strip(uint8_t n)619 LaunchControlXL::update_knob_led_by_strip(uint8_t n)
620 {
621 LEDColor color;
622
623 boost::shared_ptr<Knob> knobs_col[3];
624 knobs_by_column(n, knobs_col);
625
626 for (uint8_t s = 0; s < 3; ++s) {
627 if (knobs_col[s]) {
628 if (stripable[n]) {
629 if (stripable[n]->is_selected()) {
630 color = knobs_col[s]->color_enabled();
631 } else {
632 color = knobs_col[s]->color_disabled();
633 }
634 knobs_col[s]->set_color(color);
635 } else {
636 knobs_col[s]->set_color(Off);
637 }
638 write (knobs_col[s]->state_msg());
639 }
640 }
641 }
642
643 void
update_track_control_led(uint8_t n)644 LaunchControlXL::update_track_control_led(uint8_t n)
645 {
646 boost::shared_ptr<TrackButton> b = control_button_by_column(n);
647
648 if (!b) {
649 return;
650 }
651
652 if ((buttons_down.find(Device) != buttons_down.end())) {
653 /* Don't update LEDs if Device button is hold - we are working on selected strips */
654 return;
655 }
656
657 if (stripable[n]) {
658 boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
659 if (ac) {
660 if (ac->get_value()) {
661 b->set_color(b->color_enabled());
662 } else {
663 b->set_color(b->color_disabled());
664 }
665 } else {
666 b->set_color(Off);
667 }
668 } else {
669 b->set_color(Off);
670 }
671
672 write (b->state_msg());
673 }
674
675 void
solo_mute_rec_changed(uint32_t n)676 LaunchControlXL::solo_mute_rec_changed(uint32_t n) {
677 if (!stripable[n]) {
678 return;
679 }
680 DEBUG_TRACE (DEBUG::LaunchControlXL, "solo_mute_rec_changed - CALLING switch_bank(bank_start)\n");
681 switch_bank(bank_start);
682 //update_track_control_led(n);
683 }
684
685 void
solo_iso_changed(uint32_t n)686 LaunchControlXL::solo_iso_changed(uint32_t n)
687 {
688 if (!stripable[n]) {
689 return;
690 } else {
691 solo_iso_led_bank();
692 }
693 }
694
695 void
solo_iso_led_bank()696 LaunchControlXL::solo_iso_led_bank ()
697 {
698 if (device_mode()) { return; }
699
700 int stripable_counter = get_amount_of_tracks();
701
702 if (!(buttons_down.find(Device) != buttons_down.end())) {
703 return;
704 } else {
705 for (int n = 0; n < stripable_counter; ++n) {
706 boost::shared_ptr<TrackButton> b = focus_button_by_column(n);
707 if (stripable[n] && stripable[n]->solo_isolate_control()) {
708 if (stripable[n]->solo_isolate_control()->get_value()) {
709 b->set_color(RedFull);
710 } else {
711 b->set_color(Off);
712 }
713 if (b) {
714 write (b->state_msg());
715 }
716 }
717 }
718 LaunchControlXL::set_refresh_leds_flag(true);
719 }
720 }
721
722 #ifdef MIXBUS
723 void
master_send_changed(uint32_t n)724 LaunchControlXL::master_send_changed(uint32_t n)
725 {
726 if (!stripable[n]) {
727 return;
728 } else {
729 master_send_led_bank();
730 }
731 }
732
733 void
master_send_led_bank()734 LaunchControlXL::master_send_led_bank ()
735 {
736 if (device_mode()) { return; }
737
738 if (!(buttons_down.find(Device) != buttons_down.end())) {
739 return;
740 } else {
741 int stripable_counter = LaunchControlXL::get_amount_of_tracks();
742
743 for (int n = 0; n < stripable_counter; ++n) {
744 boost::shared_ptr<TrackButton> b = control_button_by_column(n);
745 if (stripable[n] && stripable[n]->master_send_enable_controllable()) {
746 if (stripable[n]->master_send_enable_controllable()->get_value()) {
747 b->set_color(GreenFull);
748 } else {
749 b->set_color(Off);
750 }
751 }
752 if (b) {
753 write (b->state_msg());
754 }
755 }
756 LaunchControlXL::set_refresh_leds_flag(true);
757 }
758 }
759 # endif
760
761 void
fader(uint8_t n)762 LaunchControlXL::fader(uint8_t n)
763 {
764 if (!stripable[n]) {
765 return;
766 }
767
768 boost::shared_ptr<Fader> fader;
769 IDFaderMap::iterator f = id_fader_map.find(static_cast<FaderID>(n));
770
771 if (f != id_fader_map.end()) {
772 fader = f->second;
773 }
774
775 if (!fader) {
776 return;
777 }
778
779 boost::shared_ptr<AutomationControl> ac = stripable[fader->id()]->gain_control();
780 if (ac && check_pick_up(fader, ac)) {
781 ac->set_value ( ac->interface_to_internal( fader->value() / 127.0), PBD::Controllable::UseGroup );
782 }
783 }
784
785 void
knob_sendA(uint8_t n)786 LaunchControlXL::knob_sendA(uint8_t n)
787 {
788 if (!stripable[n]) {
789 return;
790 }
791
792 boost::shared_ptr<Knob> knob;
793 IDKnobMap::iterator k = id_knob_map.find(static_cast<KnobID>(n));
794
795 if (k != id_knob_map.end()) {
796 knob = k->second;
797 }
798
799 if (!knob) {
800 return;
801 }
802
803 boost::shared_ptr<AutomationControl> ac;
804
805 if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
806 ac = stripable[n]->trim_control();
807 } else {
808 ac = stripable[n]->send_level_controllable (send_bank_base());
809 }
810
811 if (ac && check_pick_up(knob, ac)) {
812 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
813 }
814 }
815
816 void
knob_sendB(uint8_t n)817 LaunchControlXL::knob_sendB(uint8_t n)
818 {
819 if (!stripable[n]) {
820 return;
821 }
822
823 boost::shared_ptr<Knob> knob;
824 IDKnobMap::iterator k = id_knob_map.find(static_cast<KnobID>(n + 8));
825
826 if (k != id_knob_map.end()) {
827 knob = k->second;
828 }
829
830 if (!knob) {
831 return;
832 }
833
834 boost::shared_ptr<AutomationControl> ac;
835
836 if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
837 #ifdef MIXBUS
838 ac = stripable[n]->filter_freq_controllable (true);
839 #else
840 /* something */
841 #endif
842 } else {
843 ac = stripable[n]->send_level_controllable (send_bank_base() + 1);
844 }
845
846 if (ac && check_pick_up(knob, ac)) {
847 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
848 }
849 }
850
851 void
knob_pan(uint8_t n)852 LaunchControlXL::knob_pan(uint8_t n)
853 {
854 if (!stripable[n]) {
855 return;
856 }
857
858 boost::shared_ptr<Knob> knob;
859 IDKnobMap::iterator k = id_knob_map.find(static_cast<KnobID>(n + 16));
860
861 if (k != id_knob_map.end()) {
862 knob = k->second;
863 }
864
865 if (!knob) {
866 return;
867 }
868
869 boost::shared_ptr<AutomationControl> ac;
870
871 if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
872 #ifdef MIXBUS
873 ac = stripable[n]->comp_threshold_controllable();
874 #else
875 ac = stripable[n]->pan_width_control();
876 #endif
877 } else {
878 ac = stripable[n]->pan_azimuth_control();
879 }
880
881
882 if (ac && check_pick_up(knob, ac, true)) {
883 ac->set_value (ac->interface_to_internal((knob->value() / 127.0), true), PBD::Controllable::UseGroup);
884 }
885 }
886
887 void
button_track_focus(uint8_t n)888 LaunchControlXL::button_track_focus(uint8_t n)
889 {
890 if (buttons_down.find(Device) != buttons_down.end()) {
891 DEBUG_TRACE (DEBUG::LaunchControlXL, "DEVICE BUTTON HOLD\n");
892 if (stripable[n]->solo_isolate_control()) {
893 bool solo_isolate_active = stripable[n]->solo_isolate_control()->get_value();
894 stripable[n]->solo_isolate_control()->set_value (!solo_isolate_active, PBD::Controllable::UseGroup);
895 }
896 return;
897 }
898
899 if (stripable[n]) {
900 if ( stripable[n]->is_selected() ) {
901 ControlProtocol::remove_stripable_from_selection (stripable[n]);
902 } else {
903 ControlProtocol::add_stripable_to_selection (stripable[n]);
904 }
905 } else {
906 return;
907 }
908 }
909
910 void
button_press_track_control(uint8_t n)911 LaunchControlXL::button_press_track_control(uint8_t n) {
912 if (!stripable[n]) {
913 return;
914 }
915
916 if (buttons_down.find(Device) != buttons_down.end()) {
917 DEBUG_TRACE (DEBUG::LaunchControlXL, "DEVICE BUTTON HOLD\n");
918 #ifdef MIXBUS
919 if (stripable[n]->master_send_enable_controllable()) {
920 bool master_send_active = stripable[n]->master_send_enable_controllable()->get_value();
921
922 DEBUG_TRACE (DEBUG::LaunchControlXL, "MIXBUS Master Assign\n");
923 stripable[n]->master_send_enable_controllable()->set_value (!master_send_active, PBD::Controllable::UseGroup);
924 }
925
926 #else
927 /* something useful for Ardour */
928 #endif
929 return;
930 }
931
932 boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
933
934 if (ac) {
935 session->set_control (ac, !ac->get_value(), PBD::Controllable::UseGroup);
936 }
937 }
938
939 void
button_track_mode(TrackMode state)940 LaunchControlXL::button_track_mode(TrackMode state)
941 {
942 set_track_mode(state);
943 for (uint8_t n = 0; n < 8; ++n) {
944 update_track_control_led(n);
945 }
946
947 boost::shared_ptr<TrackStateButton> mute = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Mute]);
948 boost::shared_ptr<TrackStateButton> solo = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Solo]);
949 boost::shared_ptr<TrackStateButton> record = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Record]);
950
951 if (mute && solo && record) {
952 write(mute->state_msg((state == TrackMute)));
953 write(solo->state_msg((state == TrackSolo)));
954 write(record->state_msg((state == TrackRecord)));
955 }
956 }
957
958 void
button_select_left()959 LaunchControlXL::button_select_left()
960 {
961 switch_bank (std::max (0, bank_start - (7 + (fader8master() ? 0 : 1))));
962 }
963
964 void
button_select_right()965 LaunchControlXL::button_select_right()
966 {
967 switch_bank (std::max (0, bank_start + 7 + (fader8master() ? 0 : 1)));
968 }
969
970 void
send_bank_switch(bool down)971 LaunchControlXL::send_bank_switch(bool down) {
972 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("send_bank_switch - down: %1\n", down));
973 if (down) {
974 set_send_bank(+2);
975 } else {
976 set_send_bank(-2);
977 }
978 }
979
980 void
button_device()981 LaunchControlXL::button_device()
982 {
983 #ifndef MIXBUS
984 return; // currently device mode only on Mixbus
985 #endif
986 LaunchControlXL::set_device_mode(!device_mode());
987 }
988
989 void
button_device_long_press()990 LaunchControlXL::button_device_long_press()
991 {
992 if (device_mode()) { return ; }
993
994 solo_iso_led_bank();
995 #ifdef MIXBUS
996 master_send_led_bank();
997 #endif
998 }
999
1000 void
button_mute()1001 LaunchControlXL::button_mute()
1002 {
1003 if (device_mode()) { return ; }
1004
1005 if (buttons_down.find(Device) != buttons_down.end()) {
1006 access_action ("Editor/track-mute-toggle");
1007 } else {
1008 button_track_mode(TrackMute);
1009 }
1010 }
1011
1012 void
button_mute_long_press()1013 LaunchControlXL::button_mute_long_press()
1014 {
1015 session->cancel_all_mute();
1016 }
1017
1018 void
button_solo()1019 LaunchControlXL::button_solo()
1020 {
1021 if (device_mode()) { return ; }
1022
1023 if (buttons_down.find(Device) != buttons_down.end()) {
1024 access_action ("Editor/track-solo-toggle");
1025 } else {
1026 button_track_mode(TrackSolo);
1027 }
1028 }
1029
1030 void
button_solo_long_press()1031 LaunchControlXL::button_solo_long_press()
1032 {
1033 cancel_all_solo();
1034 }
1035
1036 void
button_record()1037 LaunchControlXL::button_record()
1038 {
1039 if (device_mode()) { return ; }
1040
1041 if (buttons_down.find(Device) != buttons_down.end()) {
1042 access_action ("Editor/track-record-enable-toggle");
1043 } else {
1044 button_track_mode(TrackRecord);
1045 }
1046 }
1047
1048 bool
button_long_press_timeout(ButtonID id,boost::shared_ptr<Button> button)1049 LaunchControlXL::button_long_press_timeout (ButtonID id, boost::shared_ptr<Button> button)
1050 {
1051 if (buttons_down.find (id) != buttons_down.end()) {
1052 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, invoking method\n", id));
1053 (button->long_press_method) ();
1054 } else {
1055 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, expired/cancelled\n", id));
1056 /* release happened and somehow we were not cancelled */
1057 }
1058
1059 /* whichever button this was, we've used it ... don't invoke the
1060 release action.
1061 */
1062 consumed.insert (id);
1063
1064 return false; /* don't get called again */
1065 }
1066
1067
1068 void
start_press_timeout(boost::shared_ptr<Button> button,ButtonID id)1069 LaunchControlXL::start_press_timeout (boost::shared_ptr<Button> button, ButtonID id)
1070 {
1071 ButtonID no_timeout_buttons[] = { SelectUp, SelectDown, SelectLeft, SelectRight };
1072
1073 for (size_t n = 0; n < sizeof (no_timeout_buttons) / sizeof (no_timeout_buttons[0]); ++n) {
1074 if (id == no_timeout_buttons[n]) {
1075 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("Not using timeout for button id %1\n", id));
1076 return;
1077 }
1078 }
1079
1080 Glib::RefPtr<Glib::TimeoutSource> timeout = Glib::TimeoutSource::create (500); // milliseconds
1081 button->timeout_connection = timeout->connect (sigc::bind (sigc::mem_fun (*this, &LaunchControlXL::button_long_press_timeout), id, button));
1082 timeout->attach (main_loop()->get_context());
1083 }
1084
1085
1086 /* Device Mode functions */
1087
1088 void
dm_select_prev_strip()1089 LaunchControlXL::dm_select_prev_strip()
1090 {
1091 access_action ("Editor/select-prev-stripable");
1092 }
1093
1094 void
dm_select_next_strip()1095 LaunchControlXL::dm_select_next_strip()
1096 {
1097 access_action ("Editor/select-next-stripable");
1098 }
1099
1100 uint8_t
dm_check_dummy(DeviceStatus ds)1101 LaunchControlXL::dm_check_dummy (DeviceStatus ds)
1102 {
1103 return ds;
1104 }
1105
1106 void
dm_fader(FaderID id)1107 LaunchControlXL::dm_fader (FaderID id) {
1108
1109 if (!first_selected_stripable()) {
1110 return;
1111 }
1112
1113 boost::shared_ptr<AutomationControl> ac;
1114 boost::shared_ptr<Fader> fader;
1115
1116 IDFaderMap::iterator f = id_fader_map.find(id);
1117
1118 if (f != id_fader_map.end()) {
1119 fader = f->second;
1120 }
1121
1122 ac = first_selected_stripable()->gain_control();
1123 if (ac && check_pick_up(fader, ac)) {
1124 ac->set_value ( ac->interface_to_internal( fader->value() / 127.0), PBD::Controllable::UseGroup );
1125 }
1126 }
1127
1128 uint8_t
dm_check_pan_azi()1129 LaunchControlXL::dm_check_pan_azi()
1130 {
1131 if (!first_selected_stripable()) {
1132 return dev_nonexistant;
1133 }
1134
1135 uint8_t dev_status = dev_nonexistant;
1136 if (first_selected_stripable()->pan_azimuth_control()) {
1137 dev_status = dev_active;
1138 }
1139
1140 return dev_status;
1141 }
1142
1143 void
dm_pan_azi(KnobID k)1144 LaunchControlXL::dm_pan_azi (KnobID k)
1145 {
1146 if (!first_selected_stripable()) {
1147 return;
1148 }
1149
1150 boost::shared_ptr<AutomationControl> ac;
1151 boost::shared_ptr<Knob> knob = knob_by_id (k);
1152
1153 ac = first_selected_stripable()->pan_azimuth_control();
1154
1155 if (ac && check_pick_up(knob, ac, true)) {
1156 ac->set_value (ac->interface_to_internal((knob->value() / 127.0), true), PBD::Controllable::UseGroup);
1157 }
1158 }
1159
1160
1161 uint8_t
dm_check_pan_width()1162 LaunchControlXL::dm_check_pan_width()
1163 {
1164 if (!first_selected_stripable()) {
1165 return dev_nonexistant;
1166 }
1167
1168 uint8_t dev_status = dev_nonexistant;
1169 if (first_selected_stripable()->pan_width_control()) {
1170 dev_status = dev_active;
1171 }
1172
1173 return dev_status;
1174 }
1175
1176 void
dm_pan_width(KnobID k)1177 LaunchControlXL::dm_pan_width (KnobID k)
1178 {
1179 if (!first_selected_stripable()) {
1180 return;
1181 }
1182
1183 DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_pan_width()\n");
1184 boost::shared_ptr<AutomationControl> ac;
1185 boost::shared_ptr<Knob> knob = knob_by_id (k);
1186
1187 ac = first_selected_stripable()->pan_width_control();
1188
1189 if (ac && check_pick_up(knob, ac)) {
1190 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1191 }
1192 }
1193
1194 uint8_t
dm_check_trim()1195 LaunchControlXL::dm_check_trim()
1196 {
1197 if (!first_selected_stripable()) {
1198 return dev_nonexistant;
1199 }
1200
1201 uint8_t dev_status = dev_nonexistant;
1202 if (first_selected_stripable()->trim_control()) {
1203 dev_status = dev_active;
1204 }
1205
1206 return dev_status;
1207 }
1208
1209 void
dm_trim(KnobID k)1210 LaunchControlXL::dm_trim (KnobID k)
1211 {
1212 if (!first_selected_stripable()) {
1213 return;
1214 }
1215
1216 boost::shared_ptr<AutomationControl> ac;
1217 boost::shared_ptr<Knob> knob = knob_by_id (k);
1218
1219 ac = first_selected_stripable()->trim_control();
1220
1221 if (ac && check_pick_up(knob, ac)) {
1222 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1223 }
1224 }
1225
1226 uint8_t
dm_mute_enabled()1227 LaunchControlXL::dm_mute_enabled()
1228 {
1229 if (!first_selected_stripable()) {
1230 return dev_nonexistant;
1231 }
1232
1233 uint8_t dev_status = dev_nonexistant;
1234 if (first_selected_stripable()->mute_control()->get_value()) {
1235 dev_status = dev_active;
1236 } else {
1237 dev_status = dev_inactive;
1238 }
1239
1240 return dev_status;
1241 }
1242
1243 void
dm_mute_switch()1244 LaunchControlXL::dm_mute_switch()
1245 {
1246 if (!first_selected_stripable()) {
1247 return;
1248 }
1249
1250 if (first_selected_stripable()->mute_control()) {
1251 first_selected_stripable()->mute_control()->set_value(!first_selected_stripable()->mute_control()->get_value(), PBD::Controllable::NoGroup);
1252 }
1253 }
1254
1255 uint8_t
dm_solo_enabled()1256 LaunchControlXL::dm_solo_enabled()
1257 {
1258 if (!first_selected_stripable() || first_selected_stripable()->is_master()) {
1259 return dev_nonexistant;
1260 }
1261
1262 uint8_t dev_status = dev_nonexistant;
1263 if (first_selected_stripable()->solo_control()) {
1264 if (first_selected_stripable()->solo_control()->get_value()) {
1265 dev_status = dev_active;
1266 } else {
1267 dev_status = dev_inactive;
1268 }
1269 }
1270
1271 return dev_status;
1272 }
1273
1274 void
dm_solo_switch()1275 LaunchControlXL::dm_solo_switch()
1276 {
1277 if (!first_selected_stripable()) {
1278 return;
1279 }
1280
1281 if (first_selected_stripable()->solo_control()) {
1282 first_selected_stripable()->solo_control()->set_value(!first_selected_stripable()->solo_control()->get_value(), PBD::Controllable::NoGroup);
1283 }
1284 }
1285
1286 uint8_t
dm_recenable_enabled()1287 LaunchControlXL::dm_recenable_enabled()
1288 {
1289 if (!first_selected_stripable()) {
1290 return dev_nonexistant;
1291 }
1292
1293 uint8_t dev_status = dev_nonexistant;
1294 if (first_selected_stripable()->rec_enable_control()) {
1295 if (first_selected_stripable()->rec_enable_control()->get_value()) {
1296 dev_status = dev_active;
1297 } else {
1298 dev_status = dev_inactive;
1299 }
1300 }
1301
1302 return dev_status;
1303 }
1304
1305 void
dm_recenable_switch()1306 LaunchControlXL::dm_recenable_switch()
1307 {
1308 if (!first_selected_stripable()) {
1309 return;
1310 }
1311
1312 if (first_selected_stripable()->rec_enable_control()) {
1313 first_selected_stripable()->rec_enable_control()->set_value(!first_selected_stripable()->rec_enable_control()->get_value(), PBD::Controllable::NoGroup);
1314 }
1315 }
1316
1317
1318 #ifdef MIXBUS
1319 uint8_t
dm_mb_eq_freq_enabled()1320 LaunchControlXL::dm_mb_eq_freq_enabled()
1321 {
1322 if (!first_selected_stripable()) {
1323 return dev_nonexistant;
1324 }
1325
1326 uint8_t dev_status = dev_nonexistant;
1327
1328 if (first_selected_stripable()->eq_enable_controllable()) {
1329 if (first_selected_stripable()->eq_enable_controllable()->get_value()) {
1330 dev_status = dev_active;
1331 } else {
1332 dev_status = dev_inactive;
1333 }
1334 }
1335
1336 if (first_selected_stripable()->mixbus() || first_selected_stripable()->is_master()) {
1337 dev_status = dev_nonexistant;
1338 }
1339
1340 return dev_status;
1341 }
1342
1343
1344 uint8_t
dm_mb_eq_gain_enabled(uint8_t band)1345 LaunchControlXL::dm_mb_eq_gain_enabled(uint8_t band)
1346 {
1347 if (!first_selected_stripable()) {
1348 return dev_nonexistant;
1349 }
1350
1351 uint8_t dev_status = dev_nonexistant;
1352
1353 if (first_selected_stripable()->eq_enable_controllable()) {
1354 if (first_selected_stripable()->eq_enable_controllable()->get_value()) {
1355 dev_status = dev_active;
1356 } else {
1357 dev_status = dev_inactive;
1358 }
1359 }
1360
1361 if (first_selected_stripable()->mixbus() && band > 3) {
1362 dev_status = dev_nonexistant;
1363 }
1364
1365 return dev_status;
1366 }
1367
1368 void
dm_mb_eq(KnobID k,bool gain,uint8_t band)1369 LaunchControlXL::dm_mb_eq (KnobID k, bool gain, uint8_t band)
1370 {
1371 if (!first_selected_stripable()) {
1372 return;
1373 }
1374
1375 boost::shared_ptr<AutomationControl> ac;
1376 boost::shared_ptr<Knob> knob = knob_by_id (k);
1377 if (gain) {
1378 ac = first_selected_stripable()->eq_gain_controllable(band);
1379 } else {
1380 ac = first_selected_stripable()->eq_freq_controllable(band);
1381 }
1382
1383 if (ac && check_pick_up(knob, ac)) {
1384 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1385 }
1386 }
1387
1388 void
dm_mb_eq_shape_switch(uint8_t band)1389 LaunchControlXL::dm_mb_eq_shape_switch (uint8_t band)
1390 {
1391 if (!first_selected_stripable()) {
1392 return;
1393 }
1394
1395 if (first_selected_stripable()->eq_shape_controllable(band)) {
1396 first_selected_stripable()->eq_shape_controllable(band)->set_value
1397 (!first_selected_stripable()->eq_shape_controllable(band)->get_value(), PBD::Controllable::NoGroup );
1398 }
1399 }
1400
1401
1402 uint8_t
dm_mb_eq_shape_enabled(uint8_t band)1403 LaunchControlXL::dm_mb_eq_shape_enabled(uint8_t band)
1404 {
1405 if (!first_selected_stripable()) {
1406 return dev_nonexistant;
1407 }
1408
1409 uint8_t dev_status = dev_nonexistant;
1410
1411 if (first_selected_stripable()->eq_shape_controllable(band)) {
1412 if (first_selected_stripable()->eq_shape_controllable(band)->get_value()) {
1413 dev_status = dev_active;
1414 } else {
1415 dev_status = dev_inactive;
1416 }
1417 }
1418
1419 return dev_status;
1420 }
1421
1422
1423 void
dm_mb_eq_switch()1424 LaunchControlXL::dm_mb_eq_switch()
1425 {
1426 if (!first_selected_stripable()) {
1427 return;
1428 }
1429
1430 if (first_selected_stripable()->eq_enable_controllable()) {
1431 first_selected_stripable()->eq_enable_controllable()->set_value
1432 (!first_selected_stripable()->eq_enable_controllable()->get_value(), PBD::Controllable::NoGroup );
1433 }
1434 }
1435
1436 uint8_t
dm_mb_flt_enabled()1437 LaunchControlXL::dm_mb_flt_enabled()
1438 {
1439 if (!first_selected_stripable()) {
1440 return dev_nonexistant;
1441 }
1442
1443 DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_flt_enabled()\n");
1444 uint8_t dev_status = dev_nonexistant;
1445
1446 if (first_selected_stripable()->filter_enable_controllable(true)) {
1447 DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_flt_enabled() - filter exists\n");
1448 if (first_selected_stripable()->filter_enable_controllable(true)->get_value()) {
1449 DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_flt_enabled: get_value true\n");
1450 dev_status = dev_active;
1451 } else {
1452 dev_status = dev_inactive;
1453 }
1454 }
1455 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_flt_enabled: dev_status: %1\n", (int)dev_status));
1456 return dev_status;
1457 }
1458
1459
1460 void
dm_mb_flt_switch()1461 LaunchControlXL::dm_mb_flt_switch()
1462 {
1463 if (!first_selected_stripable()) {
1464 return;
1465 }
1466
1467 if (first_selected_stripable()->filter_enable_controllable(true)) {
1468 first_selected_stripable()->filter_enable_controllable(true)->set_value
1469 (!first_selected_stripable()->filter_enable_controllable(true)->get_value(), PBD::Controllable::NoGroup );
1470 }
1471 }
1472
1473
1474
1475 void
dm_mb_flt_frq(KnobID k,bool hpf)1476 LaunchControlXL::dm_mb_flt_frq (KnobID k, bool hpf)
1477 {
1478 if (!first_selected_stripable()) {
1479 return;
1480 }
1481
1482 boost::shared_ptr<AutomationControl> ac;
1483 boost::shared_ptr<Knob> knob = knob_by_id (k);
1484 if (hpf) {
1485 ac = first_selected_stripable()->filter_freq_controllable(true);
1486 } else {
1487 ac = first_selected_stripable()->filter_freq_controllable(false);
1488 }
1489
1490 if (ac && check_pick_up(knob, ac)) {
1491 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1492 }
1493 }
1494
1495 uint8_t
dm_mb_check_send_knob(KnobID k)1496 LaunchControlXL::dm_mb_check_send_knob (KnobID k)
1497 {
1498 if (!first_selected_stripable()) {
1499 return dev_nonexistant;
1500 }
1501
1502 uint8_t send = static_cast<uint8_t> (k) - 16 + 4 * send_bank_base();
1503
1504 uint8_t dev_status = dev_nonexistant;
1505
1506 if (first_selected_stripable()->send_enable_controllable(send)) {
1507 dev_status = dev_inactive;
1508 if (first_selected_stripable()->send_enable_controllable(send)->get_value()) {
1509 dev_status = dev_active;
1510 }
1511 }
1512
1513 return dev_status;
1514 }
1515
1516 uint8_t
dm_mb_check_send_button(uint8_t s)1517 LaunchControlXL::dm_mb_check_send_button (uint8_t s)
1518 {
1519 if (!first_selected_stripable()) {
1520 return dev_nonexistant;
1521 }
1522
1523
1524 uint8_t send = s + 4 * send_bank_base();
1525
1526 uint8_t dev_status = dev_nonexistant;
1527
1528 if (first_selected_stripable()->send_enable_controllable(send)) {
1529 dev_status = dev_inactive;
1530 if (first_selected_stripable()->send_enable_controllable(send)->get_value()) {
1531 dev_status = dev_active;
1532 }
1533 }
1534
1535 return dev_status;
1536 }
1537
1538
1539
1540 void
dm_mb_sends(KnobID k)1541 LaunchControlXL::dm_mb_sends (KnobID k)
1542 {
1543 if (!first_selected_stripable()) {
1544 return;
1545 }
1546
1547 boost::shared_ptr<AutomationControl> ac;
1548 boost::shared_ptr<Knob> knob = knob_by_id (k);
1549
1550 uint8_t send = static_cast<uint8_t> (k) - 16 + 4 * send_bank_base();
1551 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: knobid '%1'\n", k));
1552 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: send '%1'\n", (int)send));
1553
1554
1555 if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
1556 ac = first_selected_stripable()->send_pan_azimuth_controllable(send);
1557 } else {
1558 ac = first_selected_stripable()->send_level_controllable(send);
1559 }
1560
1561 if (ac && check_pick_up(knob, ac)) {
1562 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1563 }
1564 }
1565
1566 uint8_t
dm_mb_comp_enabled()1567 LaunchControlXL::dm_mb_comp_enabled()
1568 {
1569 if (!first_selected_stripable()) {
1570 return dev_nonexistant;
1571 }
1572
1573 uint8_t dev_status = dev_nonexistant;
1574 if (first_selected_stripable()->comp_enable_controllable()) {
1575 if (first_selected_stripable()->comp_enable_controllable()->get_value()) {
1576 dev_status = dev_active;
1577 } else {
1578 dev_status = dev_inactive;
1579 }
1580 }
1581
1582 return dev_status;
1583 }
1584
1585 void
dm_mb_comp_switch()1586 LaunchControlXL::dm_mb_comp_switch()
1587 {
1588 DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_comp_siwtch() \n");
1589 if (!first_selected_stripable()) {
1590 return;
1591 }
1592
1593 if (first_selected_stripable()->comp_enable_controllable()) {
1594 DEBUG_TRACE (DEBUG::LaunchControlXL, "comp_enable_controllable exists\n");
1595 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("comp_enable_controllable(): '%1'\n", first_selected_stripable()->comp_enable_controllable()->get_value() ));
1596 first_selected_stripable()->comp_enable_controllable()->set_value
1597 (!first_selected_stripable()->comp_enable_controllable()->get_value(), PBD::Controllable::NoGroup);
1598 }
1599
1600 }
1601
1602 void
dm_mb_comp(KnobID k,CompParam c)1603 LaunchControlXL::dm_mb_comp (KnobID k, CompParam c)
1604 {
1605 if (!first_selected_stripable()) {
1606 return;
1607 }
1608
1609 boost::shared_ptr<AutomationControl> ac;
1610 boost::shared_ptr<Knob> knob = knob_by_id (k);
1611
1612 switch (c) {
1613 case (CompMakeup):
1614 ac = first_selected_stripable()->comp_makeup_controllable();
1615 break;
1616 case (CompMode):
1617 ac = first_selected_stripable()->comp_mode_controllable();
1618 break;
1619 case (CompSpeed):
1620 ac = first_selected_stripable()->comp_speed_controllable();
1621 break;
1622 }
1623
1624 if (ac && check_pick_up(knob, ac)) {
1625 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1626 }
1627 }
1628
1629 void
dm_mb_comp_thresh(FaderID id)1630 LaunchControlXL::dm_mb_comp_thresh (FaderID id) {
1631
1632 if (!first_selected_stripable()) {
1633 return;
1634 }
1635
1636 boost::shared_ptr<AutomationControl> ac;
1637 boost::shared_ptr<Fader> fader;
1638
1639 IDFaderMap::iterator f = id_fader_map.find(id);
1640
1641 if (f != id_fader_map.end()) {
1642 fader = f->second;
1643 }
1644
1645 ac = first_selected_stripable()->comp_threshold_controllable();
1646 if (ac && check_pick_up(fader, ac)) {
1647 ac->set_value ( ac->interface_to_internal( fader->value() / 127.0), PBD::Controllable::UseGroup );
1648 }
1649 }
1650
1651 uint8_t
dm_mb_has_tapedrive()1652 LaunchControlXL::dm_mb_has_tapedrive()
1653 {
1654 if (!first_selected_stripable()) {
1655 return dev_nonexistant;
1656 }
1657
1658 uint8_t dev_status = dev_nonexistant;
1659
1660 if (first_selected_stripable()->mixbus() || first_selected_stripable()->is_master()) {
1661 dev_status = dev_active;
1662 }
1663
1664 return dev_status;
1665 }
1666
1667 void
dm_mb_tapedrive(KnobID k)1668 LaunchControlXL::dm_mb_tapedrive (KnobID k)
1669 {
1670 if (!first_selected_stripable()) {
1671 return;
1672 }
1673
1674 boost::shared_ptr<AutomationControl> ac;
1675 boost::shared_ptr<Knob> knob = knob_by_id (k);
1676
1677 ac = first_selected_stripable()->tape_drive_controllable();
1678
1679 if (ac && check_pick_up(knob, ac)) {
1680 ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
1681 }
1682 }
1683
1684 uint8_t
dm_mb_master_assign_enabled()1685 LaunchControlXL::dm_mb_master_assign_enabled()
1686 {
1687 if (!first_selected_stripable()) {
1688 return dev_nonexistant;
1689 }
1690
1691 uint8_t dev_status = dev_nonexistant;
1692
1693 if (first_selected_stripable()->master_send_enable_controllable()) {
1694 if (first_selected_stripable()->master_send_enable_controllable()->get_value()) {
1695 dev_status = dev_active;
1696 } else {
1697 dev_status = dev_inactive;
1698 }
1699 }
1700
1701 return dev_status;
1702 }
1703
1704 void
dm_mb_master_assign_switch()1705 LaunchControlXL::dm_mb_master_assign_switch()
1706 {
1707 if (!first_selected_stripable()) {
1708 return;
1709 }
1710
1711 if (first_selected_stripable()->master_send_enable_controllable()) {
1712 first_selected_stripable()->master_send_enable_controllable()->set_value
1713 (!first_selected_stripable()->master_send_enable_controllable()->get_value(), PBD::Controllable::NoGroup );
1714 }
1715 }
1716
1717 void
dm_mb_send_switch(ButtonID id)1718 LaunchControlXL::dm_mb_send_switch(ButtonID id)
1719 {
1720 if (!first_selected_stripable()) {
1721 return;
1722 }
1723
1724 boost::shared_ptr<Button> button = id_note_button_map[id];;
1725
1726 uint8_t send = static_cast<uint8_t> (id) + 4 * send_bank_base();
1727 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: buttonid '%1'\n", (int)id));
1728 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: send '%1'\n", (int)send));
1729
1730 if (first_selected_stripable()->send_enable_controllable(send)) {
1731 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: send '%1' exists\n", (int)send));
1732 first_selected_stripable()->send_enable_controllable(send)->set_value
1733 (!first_selected_stripable()->send_enable_controllable(send)->get_value(), PBD::Controllable::UseGroup);
1734 }
1735 }
1736
1737 #endif
1738