1 /*
2  * Copyright (C) 2018 Jan Lentfer <jan.lentfer@web.de>
3  * Copyright (C) 2018 Robin Gareus <robin@gareus.org>
4  * Copyright (C) 2018 Térence Clastres <t.clastres@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #ifndef __ardour_launch_control_h__
22 #define __ardour_launch_control_h__
23 
24 #include <vector>
25 #include <map>
26 #include <stack>
27 #include <list>
28 #include <set>
29 
30 #define ABSTRACT_UI_EXPORTS
31 #include "pbd/abstract_ui.h"
32 
33 #include "midi++/types.h"
34 
35 #include "ardour/mode.h"
36 #include "ardour/types.h"
37 
38 #include "control_protocol/control_protocol.h"
39 #include "control_protocol/types.h"
40 
41 #include "midi_byte_array.h"
42 
43 namespace MIDI {
44 class Parser;
45 class Port;
46 } // namespace MIDI
47 
48 namespace ARDOUR {
49 class AsyncMIDIPort;
50 class Port;
51 class MidiBuffer;
52 class MidiTrack;
53 } // namespace ARDOUR
54 
55 namespace ArdourSurface {
56 
57 
58 struct LaunchControlRequest : public BaseUI::BaseRequestObject {
59 	public:
LaunchControlRequestLaunchControlRequest60 		LaunchControlRequest() {}
~LaunchControlRequestLaunchControlRequest61 		~LaunchControlRequest() {}
62 };
63 
64 class LCXLGUI;
65 class LaunchControlMenu;
66 
67 class LaunchControlXL : public ARDOUR::ControlProtocol,
68                         public AbstractUI<LaunchControlRequest>
69 {
70 public:
71 	enum TrackMode {
72 		TrackMute,
73 		TrackSolo,
74 		TrackRecord
75 	};
76 
77 	enum ButtonID {
78 		Focus1 = 0,
79 		Focus2,
80 		Focus3,
81 		Focus4,
82 		Focus5,
83 		Focus6,
84 		Focus7,
85 		Focus8,
86 		Control1,
87 		Control2,
88 		Control3,
89 		Control4,
90 		Control5,
91 		Control6,
92 		Control7,
93 		Control8,
94 		Device,
95 		Mute,
96 		Solo,
97 		Record,
98 		SelectUp,
99 		SelectDown,
100 		SelectLeft,
101 		SelectRight
102 	};
103 
104 	enum FaderID {
105 		Fader1 = 0,
106 		Fader2,
107 		Fader3,
108 		Fader4,
109 		Fader5,
110 		Fader6,
111 		Fader7,
112 		Fader8
113 	};
114 
115 	enum KnobID {
116 		SendA1 = 0,
117 		SendA2,
118 		SendA3,
119 		SendA4,
120 		SendA5,
121 		SendA6,
122 		SendA7,
123 		SendA8,
124 		SendB1,
125 		SendB2,
126 		SendB3,
127 		SendB4,
128 		SendB5,
129 		SendB6,
130 		SendB7,
131 		SendB8,
132 		Pan1,
133 		Pan2,
134 		Pan3,
135 		Pan4,
136 		Pan5,
137 		Pan6,
138 		Pan7,
139 		Pan8
140 	};
141 
142 	enum DeviceStatus {
143 		dev_nonexistant = 0,
144 		dev_inactive,
145 		dev_active
146 	};
147 
148 	enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 };
149 	enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, YellowLow = 34, YellowFull = 51, AmberLow = 18, AmberFull = 35};
150 
151 
152 #ifdef MIXBUS
153 	enum CompParam {
154 		CompMakeup,
155 		CompMode,
156 		CompSpeed
157 	};
158 #endif
159 
160 	struct Controller {
ControllerController161 		Controller(uint8_t cn,  uint8_t val, boost::function<void ()> action)
162 		: _controller_number(cn)
163 		, _value(val)
164 		, action_method(action) {}
165 
controller_numberController166 		uint8_t  controller_number() const { return _controller_number; }
valueController167 		uint8_t value() const { return _value; }
set_valueController168 		void set_value(uint8_t val) { _value = val; }
169 
170 		protected:
171 		uint8_t _controller_number;
172 		uint8_t _value;
173 
174 		public:
175 		boost::function<void ()> action_method;
176 	};
177 
178 	struct LED {
LEDLED179 		LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l)  {}
LEDLED180 		LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
~LEDLED181 		virtual ~LED() {}
182 
colorLED183 		LEDColor color() const { return _color; }
flagLED184 		LEDFlag flag() const { return _flag; }
indexLED185 		uint8_t index() const { return _index; }
set_flagLED186 		void set_flag(LEDFlag f) { _flag = f; }
187 
188 		virtual MidiByteArray state_msg(bool light) const = 0;
189 
190 		protected:
191 		uint8_t _index;
192 		LEDColor _color;
193 		LEDFlag _flag;
194 		MidiByteArray _state_msg;
195 		LaunchControlXL* lcxl;
196 	};
197 
198 	struct MultiColorLED : public LED {
MultiColorLEDMultiColorLED199 		MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
MultiColorLEDMultiColorLED200 		MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l)
201 			: LED(i, c, f, l) {}
202 
set_colorMultiColorLED203 		void set_color(LEDColor c) { _color = c; }
204 	};
205 
206 	struct Button {
ButtonButton207 		Button(ButtonID id, boost::function<void ()> press, boost::function<void ()> release,
208 				boost::function<void ()> long_press)
209 			: press_method(press)
210 			, release_method(release)
211 			, long_press_method(long_press),
212 			_id(id) {}
213 
~ButtonButton214 		virtual ~Button() {}
215 
idButton216 		ButtonID id() const { return _id; }
217 
218 		boost::function<void ()> press_method;
219 		boost::function<void ()> release_method;
220 		boost::function<void ()> long_press_method;
221 
222 		sigc::connection timeout_connection;
223 
224 		protected:
225 		ButtonID _id;
226 	};
227 
228 	struct ControllerButton : public Button {
ControllerButtonControllerButton229 		ControllerButton(ButtonID id, uint8_t cn,
230 				boost::function<void ()> press,
231 				boost::function<void ()> release,
232 				boost::function<void ()> long_release)
233 			: Button(id, press, release, long_release), _controller_number(cn) {}
234 
235 
236 
controller_numberControllerButton237 		uint8_t controller_number() const { return _controller_number; }
238 
239 		private:
240 		uint8_t _controller_number;
241 	};
242 
243 	struct NoteButton : public Button {
NoteButtonNoteButton244 		NoteButton(ButtonID id, uint8_t cn,
245 				boost::function<void ()> press,
246 				boost::function<void ()> release,
247 				boost::function<void ()> release_long)
248 			: Button(id, press, release, release_long), _note_number(cn) {}
249 
note_numberNoteButton250 		uint8_t note_number() const { return _note_number; }
251 
252 		private:
253 		uint8_t _note_number;
254 	};
255 
256 	struct TrackButton : public NoteButton, public MultiColorLED {
TrackButtonTrackButton257 		TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor c_on, LEDColor c_off,
258 				boost::function<void ()> press,
259 				boost::function<void ()> release,
260 				boost::function<void ()> release_long,
261 				boost::function<uint8_t ()> check,
262 				LaunchControlXL& l)
263 			: NoteButton(id, nn, press, release, release_long)
264 			, MultiColorLED(index, Off, l)
265 			, check_method(check)
266 			, _color_enabled (c_on)
267 			, _color_disabled (c_off) {}
268 
269 
270 
271 
color_enabledTrackButton272 		LEDColor color_enabled() const { return _color_enabled; }
color_disabledTrackButton273 		LEDColor color_disabled() const { return _color_disabled; }
set_color_enabledTrackButton274 		void set_color_enabled (LEDColor c_on) { _color_enabled = c_on; }
set_color_disabledTrackButton275 		void set_color_disabled (LEDColor c_off) { _color_disabled = c_off; }
276 		boost::function<uint8_t ()> check_method;
277 
278 
279 		MidiByteArray state_msg(bool light = true) const;
280 
281 		private:
282 		LEDColor _color_enabled;
283 		LEDColor _color_disabled;
284 	};
285 
286 	struct SelectButton : public ControllerButton, public LED {
SelectButtonSelectButton287 		SelectButton(ButtonID id, uint8_t cn, uint8_t index,
288 				boost::function<void ()> press,
289 				boost::function<void ()> release,
290 				boost::function<void ()> long_release,
291 				LaunchControlXL& l)
292 			: ControllerButton(id, cn, press, release, long_release), LED(index, RedFull, l) {}
293 
294 
295 		MidiByteArray state_msg(bool light) const;
296 	};
297 
298 	struct TrackStateButton : public NoteButton, public LED {
TrackStateButtonTrackStateButton299 		TrackStateButton(ButtonID id, uint8_t nn, uint8_t index,
300 				boost::function<void ()> press,
301 				boost::function<void ()> release,
302 				boost::function<void ()> release_long,
303 				LaunchControlXL& l)
304 			: NoteButton(id, nn, press, release, release_long)
305 			, LED(index, YellowLow, l) {}
306 
307 		MidiByteArray state_msg(bool light) const;
308 	};
309 
310 	struct Fader : public Controller {
FaderFader311 		Fader(FaderID id, uint8_t cn, boost::function<void ()> action)
312 			: Controller(cn, 0, action), _id(id) {} // minimal value
313 
idFader314 		FaderID id() const { return _id; }
315 
316 		void controller_changed(Controller* controller);
317 
318 		private:
319 		FaderID _id;
320 	};
321 
322 	struct Knob : public Controller, public MultiColorLED {
KnobKnob323 		Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function<void ()> action,
324 			LaunchControlXL &l)
325 			: Controller(cn, 64, action)
326 			, MultiColorLED(index, Off, l)
327 			, _id(id)
328 			, _color_enabled (c_on)
329 			, _color_disabled (c_off) {} // knob 50/50 value
330 
KnobKnob331 		Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor c_on, LEDColor c_off, boost::function<void ()> action,
332 			boost::function<uint8_t ()> check, LaunchControlXL &l)
333 			: Controller(cn, 64, action)
334 			, MultiColorLED(index, Off, l)
335 			, check_method(check)
336 			, _id(id)
337 			, _color_enabled (c_on)
338 			, _color_disabled (c_off) {} // knob 50/50 value
339 
340 
341 
idKnob342 		KnobID id() const { return _id; }
color_enabledKnob343 		LEDColor color_enabled() const { return _color_enabled; }
color_disabledKnob344 		LEDColor color_disabled() const { return _color_disabled; }
345 		boost::function<uint8_t ()> check_method;
346 
347 		MidiByteArray state_msg(bool light = true) const;
348 
349 		private:
350 		KnobID _id;
351 		LEDColor _color_enabled;
352 		LEDColor _color_disabled;
353 	};
354 
355 public:
356 	LaunchControlXL(ARDOUR::Session &);
357 	~LaunchControlXL();
358 
359 
360 	static bool probe();
361 	static void *request_factory(uint32_t);
362 
363 	std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles();
364 
has_editor()365 	bool has_editor() const { return true; }
366 	void *get_gui() const;
367 	void tear_down_gui();
368 
369 	int get_amount_of_tracks();
370 
371 	int set_active(bool yn);
372 	XMLNode &get_state();
373 	int set_state(const XMLNode &node, int version);
374 
375 	PBD::Signal0<void> ConnectionChange;
376 
377 	boost::shared_ptr<ARDOUR::Port> input_port();
378 	boost::shared_ptr<ARDOUR::Port> output_port();
379 
380 	Button *button_by_id(ButtonID);
381 
382 	static std::string button_name_by_id(ButtonID);
383 	static std::string knob_name_by_id(KnobID);
384 	static std::string fader_name_by_id(FaderID);
385 
386 	void write(const MidiByteArray &);
387 	void reset(uint8_t chan);
388 
389 	void set_fader8master (bool yn);
fader8master()390 	bool fader8master () const { return _fader8master; }
391 
392 	void set_refresh_leds_flag (bool yn);
refresh_leds_flag()393 	bool refresh_leds_flag () const { return _refresh_leds_flag; }
394 
395 	void set_device_mode (bool yn);
device_mode()396 	bool device_mode () const { return _device_mode; }
397 
398 #ifdef MIXBUS32C
399 	void set_ctrllowersends (bool yn);
ctrllowersends()400 	bool ctrllowersends () const { return _ctrllowersends; }
401 
402 	void store_fss_type();
fss_is_mixbus()403 	bool fss_is_mixbus() const { return _fss_is_mixbus; }
404 #endif
track_mode()405 	TrackMode track_mode() const { return _track_mode; }
406 	void set_track_mode(TrackMode mode);
407 
template_number()408 	uint8_t template_number() const { return _template_number; }
409 
410 	void set_send_bank (int offset);
411 	void send_bank_switch(bool up);
send_bank_base()412 	int send_bank_base () const { return _send_bank_base; }
413 
414 private:
415 	bool in_use;
416 	TrackMode _track_mode;
417 	uint8_t _template_number;
418 
419 	bool _fader8master;
420 	bool _device_mode;
421 #ifdef MIXBUS32C
422 	bool _ctrllowersends;
423 	bool _fss_is_mixbus;
424 #endif
425 	bool _refresh_leds_flag;
426 
427 	int _send_bank_base;
428 
429 	void do_request(LaunchControlRequest *);
430 
431 	int begin_using_device();
432 	int stop_using_device();
433 	int ports_acquire();
434 	void ports_release();
435 	void run_event_loop();
436 	void stop_event_loop();
437 
relax()438 	void relax() {}
439 
440 	/* map of NoteButtons by NoteNumber */
441 	typedef std::map<int, boost::shared_ptr<NoteButton> > NNNoteButtonMap;
442 	NNNoteButtonMap nn_note_button_map;
443 	/* map of NoteButtons by ButtonID */
444 	typedef std::map<ButtonID, boost::shared_ptr<NoteButton> > IDNoteButtonMap;
445 	IDNoteButtonMap id_note_button_map;
446 	/* map of ControllerNoteButtons by CC */
447 	typedef std::map<int, boost::shared_ptr<ControllerButton> > CCControllerButtonMap;
448 	CCControllerButtonMap cc_controller_button_map;
449 	/* map of ControllerButtons by ButtonID */
450 	typedef std::map<ButtonID, boost::shared_ptr<ControllerButton> > IDControllerButtonMap;
451 	IDControllerButtonMap id_controller_button_map;
452 
453 
454 	/* map of Fader by CC */
455 	typedef std::map<int, boost::shared_ptr<Fader> > CCFaderMap;
456 	CCFaderMap cc_fader_map;
457 	/* map of Fader by FaderID */
458 	typedef std::map<FaderID, boost::shared_ptr<Fader> > IDFaderMap;
459 	IDFaderMap id_fader_map;
460 
461 	/* map of Knob by CC */
462 	typedef std::map<int, boost::shared_ptr<Knob> > CCKnobMap;
463 	CCKnobMap cc_knob_map;
464 	/* map of Knob by KnobID */
465 	typedef std::map<KnobID, boost::shared_ptr<Knob> > IDKnobMap;
466 	IDKnobMap id_knob_map;
467 
468 	std::set<ButtonID> buttons_down;
469 	std::set<ButtonID> consumed;
470 
471 	bool button_long_press_timeout(ButtonID id, boost::shared_ptr<Button> button);
472 	void start_press_timeout(boost::shared_ptr<Button> , ButtonID);
473 
474 	void init_buttons();
475 	void init_buttons(bool startup);
476 	void init_buttons (ButtonID buttons[], uint8_t i);
477 	void init_knobs();
478 	void init_knobs(KnobID knobs[], uint8_t i);
479 	void init_knobs_and_buttons();
480 
481 	void init_device_mode();
482 	void init_dm_callbacks();
483 
484 	void switch_template(uint8_t t);
485 	void filter_stripables (ARDOUR::StripableList& strips) const;
486 
487 	void build_maps();
488 
489 	// Bundle to represent our input ports
490 	boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
491 	// Bundle to represent our output ports
492 	boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
493 
494 	MIDI::Port *_input_port;
495 	MIDI::Port *_output_port;
496 	boost::shared_ptr<ARDOUR::Port> _async_in;
497 	boost::shared_ptr<ARDOUR::Port> _async_out;
498 
499 	void connect_to_parser();
500 	void handle_button_message(boost::shared_ptr<Button> button, MIDI::EventTwoBytes *);
501 
502 	bool check_pick_up(boost::shared_ptr<Controller> controller, boost::shared_ptr<ARDOUR::AutomationControl> ac, bool rotary = false);
503 
504 	void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
505 	void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
506 	void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
507 	void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
508 
509 	bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
510 
511 	void thread_init();
512 
513 	PBD::ScopedConnectionList session_connections;
514 	void connect_session_signals();
515 	void notify_transport_state_changed();
516 	void notify_loop_state_changed();
517 	void notify_parameter_changed(std::string);
518 
519 	/* Knob methods */
520 	boost::shared_ptr<Knob> knob_by_id(KnobID id);
521 	boost::shared_ptr<Knob>* knobs_by_column(uint8_t col, boost::shared_ptr<Knob>* knob_col);
522 	void update_knob_led_by_strip(uint8_t n);
523 	void update_knob_led_by_id(uint8_t id, LEDColor color);
524 
525 	void knob_sendA(uint8_t n);
526 	void knob_sendB(uint8_t n);
527 	void knob_pan(uint8_t n);
528 
529 	uint8_t dm_check_dummy(DeviceStatus ds);
530 
531 	void dm_fader(FaderID id);
532 	uint8_t dm_check_pan_azi ();
533 	void dm_pan_azi(KnobID k);
534 	uint8_t dm_check_pan_width();
535 	void dm_pan_width (KnobID k);
536 	uint8_t dm_check_trim ();
537 	void dm_trim(KnobID k);
538 	uint8_t dm_mute_enabled();
539 	void dm_mute_switch();
540 	uint8_t dm_solo_enabled();
541 	void dm_solo_switch();
542 	uint8_t dm_recenable_enabled();
543 	void dm_recenable_switch();
544 	void dm_select_prev_strip();
545 	void dm_select_next_strip();
546 
547 #ifdef MIXBUS
548 	void dm_mb_eq_switch();
549 	void dm_mb_eq (KnobID k, bool gain, uint8_t band);
550 	uint8_t dm_mb_eq_freq_enabled();
551 	uint8_t dm_mb_eq_gain_enabled(uint8_t band);
552 	void dm_mb_eq_shape_switch(uint8_t band);
553 	uint8_t dm_mb_eq_shape_enabled(uint8_t band);
554 	uint8_t dm_mb_flt_enabled();
555 	void dm_mb_flt_frq (KnobID k, bool hpf);
556 	void dm_mb_flt_switch();
557 	void dm_mb_send_enabled(KnobID k);
558 	uint8_t dm_mb_check_send_knob(KnobID k);
559 	uint8_t dm_mb_check_send_button(uint8_t s);
560 	void dm_mb_sends (KnobID k);
561 	void dm_mb_send_switch (ButtonID b);
562 	uint8_t dm_mb_comp_enabled();
563 	void dm_mb_comp_switch();
564 	void dm_mb_comp (KnobID k, CompParam c);
565 	void dm_mb_comp_thresh (FaderID id);
566 	uint8_t dm_mb_has_tapedrive();
567 	void dm_mb_tapedrive (KnobID k);
568 	uint8_t dm_mb_master_assign_enabled();
569 	void dm_mb_master_assign_switch();
570 #endif
571 
572 	/* Fader methods */
573 	void fader(uint8_t n);
574 
575 
576 	/* Button methods */
577 	boost::shared_ptr<TrackButton> track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
focus_button_by_column(uint8_t col)578 	boost::shared_ptr<TrackButton> focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
control_button_by_column(uint8_t col)579 	boost::shared_ptr<TrackButton> control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
580 
581 
582 	void button_device();
583 	void button_device_long_press();
584 	void button_track_mode(TrackMode state);
585 	void button_mute();
586 	void button_mute_long_press();
587 	void button_solo();
588 	void button_solo_long_press();
589 	void button_record();
590 	void button_select_up();
591 	void button_select_down();
592 	void button_select_left();
593 	void button_select_right();
594 
595 	void button_track_focus(uint8_t n);
596 	void button_press_track_control(uint8_t n);
597 	void button_release_track_control(uint8_t n);
598 
599 	boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
600 	void update_track_focus_led(uint8_t n);
601 	void update_track_control_led(uint8_t n);
602 
send_bank_switch_0()603 	void send_bank_switch_0() { send_bank_switch(0); }
send_bank_switch_1()604 	void send_bank_switch_1() { send_bank_switch(1); }
605 
606 	/* stripables */
607 
608 	int32_t bank_start;
609 	PBD::ScopedConnectionList stripable_connections;
610 	boost::shared_ptr<ARDOUR::Stripable> stripable[8];
611 
612 	void stripables_added ();
613 
614 	void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
615 
616 	void switch_bank (uint32_t base);
617 
solo_changed(uint32_t n)618 	void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
mute_changed(uint32_t n)619 	void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
rec_changed(uint32_t n)620 	void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
621 	void solo_iso_changed (uint32_t n);
622 	void solo_iso_led_bank ();
623 #ifdef MIXBUS
624 	void master_send_changed (uint32_t n);
625 	void master_send_led_bank ();
626 #endif
627 
628 	void solo_mute_rec_changed (uint32_t n);
629 
630 	/* special Stripable */
631 
632 	boost::shared_ptr<ARDOUR::Stripable> master;
633 
634 	void port_registration_handler();
635 
636 	enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
637 
638 	int connection_state;
639 	bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
640 			boost::weak_ptr<ARDOUR::Port>, std::string name2,
641 			bool yn);
642 	PBD::ScopedConnection port_connection;
643 	void connected();
644 
645 	/* GUI */
646 
647 	mutable LCXLGUI *gui;
648 	void build_gui();
649 
650 	void stripable_selection_changed();
651 
652 	bool in_range_select;
653 };
654 
655 
656 } // namespace ArdourSurface
657 
658 #endif /* __ardour_launch_control_h__ */
659