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