2 Copyright (C) 2016 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #ifndef __ardour_launch_control_h__
20 #define __ardour_launch_control_h__
28 #define ABSTRACT_UI_EXPORTS
29 #include "pbd/abstract_ui.h"
31 #include "midi++/types.h"
33 #include "ardour/mode.h"
34 #include "ardour/types.h"
36 #include "control_protocol/control_protocol.h"
37 #include "control_protocol/types.h"
39 #include "midi_byte_array.h"
53 namespace ArdourSurface {
56 struct LaunchControlRequest : public BaseUI::BaseRequestObject {
58 LaunchControlRequest() {}
59 ~LaunchControlRequest() {}
63 class LaunchControlMenu;
65 class LaunchControlXL : public ARDOUR::ControlProtocol,
66 public AbstractUI<LaunchControlRequest> {
139 enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 };
141 enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, YellowLow = 34, YellowFull = 51, AmberLow = 18, AmberFull = 35};
145 Controller(uint8_t cn, uint8_t val = 0) : _controller_number(cn), _value(val) {}
147 uint8_t controller_number() const { return _controller_number; }
148 uint8_t value() const { return _value; }
149 void set_value(uint8_t val) { _value = val; }
152 uint8_t _controller_number;
157 LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l) {}
158 LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
161 LEDColor color() const { return _color; }
162 LEDFlag flag() const { return _flag; }
163 uint8_t index() const { return _index; }
164 void set_flag(LEDFlag f) { _flag = f; }
166 virtual MidiByteArray state_msg(bool light) const = 0;
172 MidiByteArray _state_msg;
173 LaunchControlXL* lcxl;
176 struct MultiColorLED : public LED {
177 MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
178 MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l)
181 void set_color(LEDColor c) { _color = c; }
186 : press_method(&LaunchControlXL::relax)
187 , release_method(&LaunchControlXL::relax)
188 , long_press_method(&LaunchControlXL::relax), _id(id) {}
190 Button(ButtonID id, void (LaunchControlXL::*press)())
191 : press_method(press)
192 , release_method(&LaunchControlXL::relax)
193 , long_press_method(&LaunchControlXL::relax), _id(id) {}
195 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)())
196 : press_method(press), release_method(release)
197 , long_press_method(&LaunchControlXL::relax), _id(id) {}
199 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)(), void (LaunchControlXL::*long_press)())
200 : press_method(press), release_method(release)
201 , long_press_method(long_press), _id(id) {}
205 ButtonID id() const { return _id; }
207 void (LaunchControlXL::*press_method)();
208 void (LaunchControlXL::*release_method)();
209 void (LaunchControlXL::*long_press_method)();
211 sigc::connection timeout_connection;
217 struct ControllerButton : public Button {
219 ControllerButton(ButtonID id, uint8_t cn,
220 void (LaunchControlXL::*press)())
221 : Button(id, press), _controller_number(cn) {}
223 ControllerButton(ButtonID id, uint8_t cn,
224 void (LaunchControlXL::*press)(),
225 void (LaunchControlXL::*release)())
226 : Button(id, press, release), _controller_number(cn) {}
228 ControllerButton(ButtonID id, uint8_t cn,
229 void (LaunchControlXL::*press)(),
230 void (LaunchControlXL::*release)(),
231 void (LaunchControlXL::*release_long)())
232 : Button(id, press, release, release_long), _controller_number(cn) {}
235 uint8_t controller_number() const { return _controller_number; }
238 uint8_t _controller_number;
241 struct NoteButton : public Button {
243 NoteButton(ButtonID id, uint8_t cn, void (LaunchControlXL::*press)())
244 : Button(id, press), _note_number(cn) {}
246 NoteButton(ButtonID id, uint8_t cn,
247 void (LaunchControlXL::*press)(),
248 void (LaunchControlXL::*release)())
249 : Button(id, press, release), _note_number(cn) {}
250 NoteButton(ButtonID id, uint8_t cn,
251 void (LaunchControlXL::*press)(),
252 void (LaunchControlXL::*release)(),
253 void (LaunchControlXL::*release_long)())
254 : Button(id, press, release, release_long), _note_number(cn) {}
256 uint8_t note_number() const { return _note_number; }
259 uint8_t _note_number;
262 struct TrackButton : public NoteButton, public MultiColorLED {
263 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
264 void (LaunchControlXL::*press)(), LaunchControlXL& l)
265 : NoteButton(id, nn, press), MultiColorLED(index, color, l) {}
267 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
268 void (LaunchControlXL::*press)(),
269 void (LaunchControlXL::*release)(),
271 : NoteButton(id, nn, press, release), MultiColorLED(index, color, l) {}
273 MidiByteArray state_msg(bool light = true) const;
276 struct SelectButton : public ControllerButton, public LED {
277 SelectButton(ButtonID id, uint8_t cn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
278 : ControllerButton(id, cn, press), LED(index, RedFull, l) {}
280 SelectButton(ButtonID id, uint8_t cn, uint8_t index,
281 void (LaunchControlXL::*press)(),
282 void (LaunchControlXL::*release)(),
283 void (LaunchControlXL::*release_long)(),
285 : ControllerButton(id, cn, press, release, release_long), LED(index, RedFull, l) {}
287 MidiByteArray state_msg(bool light) const;
290 struct TrackStateButton : public NoteButton, public LED {
291 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
292 : NoteButton(id, nn, press)
293 , LED(index, YellowLow, l) {}
295 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
296 void (LaunchControlXL::*release)(),
298 : NoteButton(id, nn, press, release)
299 , LED(index, YellowLow, l) {}
301 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
302 void (LaunchControlXL::*release)(),
303 void (LaunchControlXL::*release_long)(),
305 : NoteButton(id, nn, press, release, release_long)
306 , LED(index, YellowLow, l) {}
308 MidiByteArray state_msg(bool light) const;
311 struct Fader : public Controller {
312 Fader(FaderID id, uint8_t cn)
313 : Controller(cn, 0), _id(id) {} // minimal value
315 FaderID id() const { return _id; }
317 void controller_changed(Controller* controller);
323 struct Knob : public Controller, public MultiColorLED {
324 Knob(KnobID id, uint8_t cn, uint8_t index, LaunchControlXL& l)
326 , MultiColorLED(index, Off, l)
327 , _id(id) {} // knob 50/50 value
329 KnobID id() const { return _id; }
331 MidiByteArray state_msg(bool light = true) const;
338 LaunchControlXL(ARDOUR::Session &);
343 static void *request_factory(uint32_t);
345 std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles();
347 bool has_editor() const { return true; }
348 void *get_gui() const;
349 void tear_down_gui();
351 bool use_fader8master = false;
353 int set_active(bool yn);
354 XMLNode &get_state();
355 int set_state(const XMLNode &node, int version);
357 PBD::Signal0<void> ConnectionChange;
359 boost::shared_ptr<ARDOUR::Port> input_port();
360 boost::shared_ptr<ARDOUR::Port> output_port();
362 Button *button_by_id(ButtonID);
364 static std::string button_name_by_id(ButtonID);
365 static std::string knob_name_by_id(KnobID);
366 static std::string fader_name_by_id(FaderID);
368 void write(const MidiByteArray &);
369 void reset(uint8_t chan);
370 void set_fader8master (bool yn);
372 TrackMode track_mode() const { return _track_mode; }
373 void set_track_mode(TrackMode mode);
375 uint8_t template_number() const { return _template_number; }
379 TrackMode _track_mode;
380 uint8_t _template_number;
382 void do_request(LaunchControlRequest *);
384 int begin_using_device();
385 int stop_using_device();
387 void ports_release();
388 void run_event_loop();
389 void stop_event_loop();
393 /* map of NoteButtons by NoteNumber */
394 typedef std::map<int, NoteButton *> NNNoteButtonMap;
395 NNNoteButtonMap nn_note_button_map;
396 /* map of NoteButtons by ButtonID */
397 typedef std::map<ButtonID, NoteButton *> IDNoteButtonMap;
398 IDNoteButtonMap id_note_button_map;
399 /* map of ControllerNoteButtons by CC */
400 typedef std::map<int, ControllerButton *> CCControllerButtonMap;
401 CCControllerButtonMap cc_controller_button_map;
402 /* map of ControllerButtons by ButtonID */
403 typedef std::map<ButtonID, ControllerButton *> IDControllerButtonMap;
404 IDControllerButtonMap id_controller_button_map;
407 /* map of Fader by CC */
408 typedef std::map<int, Fader *> CCFaderMap;
409 CCFaderMap cc_fader_map;
410 /* map of Fader by FaderID */
411 typedef std::map<FaderID, Fader *> IDFaderMap;
412 IDFaderMap id_fader_map;
414 /* map of Knob by CC */
415 typedef std::map<int, Knob *> CCKnobMap;
416 CCKnobMap cc_knob_map;
417 /* map of Knob by KnobID */
418 typedef std::map<KnobID, Knob *> IDKnobMap;
419 IDKnobMap id_knob_map;
421 std::set<ButtonID> buttons_down;
422 std::set<ButtonID> consumed;
424 bool button_long_press_timeout(ButtonID id, Button *button);
425 void start_press_timeout(Button *, ButtonID);
427 void init_buttons(bool startup);
429 void switch_template(uint8_t t);
433 // Bundle to represent our input ports
434 boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
435 // Bundle to represent our output ports
436 boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
438 MIDI::Port *_input_port;
439 MIDI::Port *_output_port;
440 boost::shared_ptr<ARDOUR::Port> _async_in;
441 boost::shared_ptr<ARDOUR::Port> _async_out;
443 void connect_to_parser();
444 void handle_button_message(Button* button, MIDI::EventTwoBytes *);
445 void handle_fader_message(Fader* fader);
446 void handle_knob_message(Knob* knob);
448 bool check_pick_up(Controller* controller, boost::shared_ptr<ARDOUR::AutomationControl> ac);
450 void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
451 void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
452 void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
453 void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
455 bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
459 PBD::ScopedConnectionList session_connections;
460 void connect_session_signals();
461 void notify_transport_state_changed();
462 void notify_loop_state_changed();
463 void notify_parameter_changed(std::string);
467 Knob** knobs_by_column(uint8_t col, Knob** knob_col);
468 void update_knob_led(uint8_t n);
472 TrackButton* track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
473 TrackButton* focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
474 TrackButton* control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
477 void button_device();
478 void button_device_long_press();
479 void button_track_mode(TrackMode state);
482 void button_record();
483 void button_select_up();
484 void button_select_down();
485 void button_select_left();
486 void button_select_right();
487 void button_select_left_long_press();
488 void button_select_right_long_press();
490 void button_track_focus(uint8_t n);
491 void button_track_control(uint8_t n);
493 boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
494 void update_track_focus_led(uint8_t n);
495 void update_track_control_led(uint8_t n);
497 void button_track_focus_1() { button_track_focus(0); }
498 void button_track_focus_2() { button_track_focus(1); }
499 void button_track_focus_3() { button_track_focus(2); }
500 void button_track_focus_4() { button_track_focus(3); }
501 void button_track_focus_5() { button_track_focus(4); }
502 void button_track_focus_6() { button_track_focus(5); }
503 void button_track_focus_7() { button_track_focus(6); }
504 void button_track_focus_8() { button_track_focus(7); }
506 void button_track_control_1() { button_track_control(0); }
507 void button_track_control_2() { button_track_control(1); }
508 void button_track_control_3() { button_track_control(2); }
509 void button_track_control_4() { button_track_control(3); }
510 void button_track_control_5() { button_track_control(4); }
511 void button_track_control_6() { button_track_control(5); }
512 void button_track_control_7() { button_track_control(6); }
513 void button_track_control_8() { button_track_control(7); }
518 PBD::ScopedConnectionList stripable_connections;
519 boost::shared_ptr<ARDOUR::Stripable> stripable[8];
521 void stripables_added ();
523 void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
525 void switch_bank (uint32_t base);
527 void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
528 void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
529 void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
530 void solo_mute_rec_changed (uint32_t n);
532 /* special Stripable */
534 boost::shared_ptr<ARDOUR::Stripable> master;
536 PBD::ScopedConnection port_reg_connection;
537 void port_registration_handler();
539 enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
541 int connection_state;
542 bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
543 boost::weak_ptr<ARDOUR::Port>, std::string name2,
545 PBD::ScopedConnection port_connection;
550 mutable LCXLGUI *gui;
553 void stripable_selection_changed();
555 bool in_range_select;
559 } // namespace ArdourSurface
561 #endif /* __ardour_launch_control_h__ */