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.
21 #include "ardour/debug.h"
22 #include "ardour/mute_control.h"
23 #include "ardour/session.h"
24 #include "ardour/solo_control.h"
25 #include "ardour/solo_isolate_control.h"
27 #include "launch_control_xl.h"
29 using namespace ArdourSurface;
30 using namespace ARDOUR;
35 LaunchControlXL::build_maps ()
39 boost::shared_ptr<Knob> knob;
41 #define MAKE_KNOB(i,cc, index) \
42 knob.reset (new Knob ((i), (cc), (index), (*this))); \
43 cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
44 id_knob_map.insert (std::make_pair (knob->id(), knob))
46 for (uint8_t n = 0; n < 8; ++n) {
47 MAKE_KNOB (static_cast<KnobID>(n), (n + 13), n);
48 MAKE_KNOB (static_cast<KnobID>(n + 8), (n + 29), (n + 8));
49 MAKE_KNOB (static_cast<KnobID>(n + 16), (n + 49), (n + 16));
54 boost::shared_ptr<Fader> fader;
56 #define MAKE_FADER(i,cc) \
57 fader.reset (new Fader ((i), (cc))); \
58 cc_fader_map.insert (std::make_pair (fader->controller_number(), fader)); \
59 id_fader_map.insert (std::make_pair (fader->id(), fader))
61 for (uint8_t n = 0; n < 8; ++n) {
62 MAKE_FADER (static_cast<FaderID>(n), (n + 77) );
67 boost::shared_ptr<ControllerButton> controller_button;
68 boost::shared_ptr<NoteButton> note_button;
71 #define MAKE_TRACK_BUTTON_PRESS(i,nn,index,color,p) \
72 note_button.reset (new TrackButton ((i), (nn), (index), (color), (p), (*this))); \
73 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
74 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
75 #define MAKE_SELECT_BUTTON_PRESS(i,cc,index,p) \
76 controller_button.reset (new SelectButton ((i), (cc), (index), (p), (*this))); \
77 cc_controller_button_map.insert (std::make_pair (controller_button->controller_number(), controller_button)); \
78 id_controller_button_map.insert (std::make_pair (controller_button->id(), controller_button))
79 #define MAKE_TRACK_STATE_BUTTON_PRESS(i,nn,index,p) \
80 note_button.reset (new TrackStateButton ((i), (nn), (index), (p), (*this))); \
81 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
82 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
83 #define MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(i,nn,index, p,r,l) \
84 note_button.reset (new TrackStateButton ((i), (nn), (index), (p), (r), (l), (*this))); \
85 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
86 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
89 MAKE_TRACK_BUTTON_PRESS(Focus1, 41, 24, YellowLow, &LaunchControlXL::button_track_focus_1);
90 MAKE_TRACK_BUTTON_PRESS(Focus2, 42, 25, YellowLow, &LaunchControlXL::button_track_focus_2);
91 MAKE_TRACK_BUTTON_PRESS(Focus3, 43, 26, YellowLow, &LaunchControlXL::button_track_focus_3);
92 MAKE_TRACK_BUTTON_PRESS(Focus4, 44, 27, YellowLow, &LaunchControlXL::button_track_focus_4);
93 MAKE_TRACK_BUTTON_PRESS(Focus5, 57, 28, YellowLow, &LaunchControlXL::button_track_focus_5);
94 MAKE_TRACK_BUTTON_PRESS(Focus6, 58, 29, YellowLow, &LaunchControlXL::button_track_focus_6);
95 MAKE_TRACK_BUTTON_PRESS(Focus7, 59, 30, YellowLow, &LaunchControlXL::button_track_focus_7);
96 MAKE_TRACK_BUTTON_PRESS(Focus8, 60, 31, YellowLow, &LaunchControlXL::button_track_focus_8);
97 MAKE_TRACK_BUTTON_PRESS(Control1, 73, 32, AmberLow, &LaunchControlXL::button_track_control_1);
98 MAKE_TRACK_BUTTON_PRESS(Control2, 74, 33, AmberLow, &LaunchControlXL::button_track_control_2);
99 MAKE_TRACK_BUTTON_PRESS(Control3, 75, 34, AmberLow, &LaunchControlXL::button_track_control_3);
100 MAKE_TRACK_BUTTON_PRESS(Control4, 76, 35, AmberLow, &LaunchControlXL::button_track_control_4);
101 MAKE_TRACK_BUTTON_PRESS(Control5, 89, 36, AmberLow, &LaunchControlXL::button_track_control_5);
102 MAKE_TRACK_BUTTON_PRESS(Control6, 90, 37, AmberLow, &LaunchControlXL::button_track_control_6);
103 MAKE_TRACK_BUTTON_PRESS(Control7, 91, 38, AmberLow, &LaunchControlXL::button_track_control_7);
104 MAKE_TRACK_BUTTON_PRESS(Control8, 92, 39, AmberLow, &LaunchControlXL::button_track_control_8);
106 MAKE_SELECT_BUTTON_PRESS(SelectUp, 104, 44, &LaunchControlXL::button_select_up);
107 MAKE_SELECT_BUTTON_PRESS(SelectDown, 105, 45, &LaunchControlXL::button_select_down);
108 MAKE_SELECT_BUTTON_PRESS(SelectLeft, 106, 46, &LaunchControlXL::button_select_left);
109 MAKE_SELECT_BUTTON_PRESS(SelectRight, 107, 47, &LaunchControlXL::button_select_right);
111 MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Device, 105, 40, &LaunchControlXL::relax, &LaunchControlXL::button_device, &LaunchControlXL::button_device_long_press);;
112 MAKE_TRACK_STATE_BUTTON_PRESS(Mute, 106, 41, &LaunchControlXL::button_mute);
113 MAKE_TRACK_STATE_BUTTON_PRESS(Solo, 107, 42, &LaunchControlXL::button_solo);
114 MAKE_TRACK_STATE_BUTTON_PRESS(Record, 108, 43, &LaunchControlXL::button_record);
119 LaunchControlXL::button_name_by_id (ButtonID id)
133 return "Select Down";
135 return "Select Right";
137 return "Select Left";
178 LaunchControlXL::knob_name_by_id (KnobID id)
237 LaunchControlXL::fader_name_by_id (FaderID id)
263 boost::shared_ptr<LaunchControlXL::TrackButton>
264 LaunchControlXL::track_button_by_range(uint8_t n, uint8_t first, uint8_t middle)
266 NNNoteButtonMap::iterator b;
268 b = nn_note_button_map.find (first + n);
270 b = nn_note_button_map.find (middle + n - 4);
273 if (b != nn_note_button_map.end()) {
277 return boost::shared_ptr<LaunchControlXL::TrackButton>();
281 LaunchControlXL::update_track_focus_led(uint8_t n)
283 boost::shared_ptr<TrackButton> b = focus_button_by_column(n);
290 if ( stripable[n]->is_selected() ) {
291 b->set_color(YellowFull);
293 b->set_color(AmberLow);
299 write (b->state_msg());
303 LaunchControlXL::button_track_focus(uint8_t n)
305 if (buttons_down.find(Device) != buttons_down.end()) {
306 DEBUG_TRACE (DEBUG::LaunchControlXL, "DEVICE BUTTON HOLD\n");
307 if (stripable[n]->solo_isolate_control()) {
308 bool solo_isolate_active = stripable[n]->solo_isolate_control()->get_value();
309 stripable[n]->solo_isolate_control()->set_value (!solo_isolate_active, PBD::Controllable::UseGroup);
315 if ( stripable[n]->is_selected() ) {
316 ControlProtocol::RemoveStripableFromSelection (stripable[n]);
318 ControlProtocol::AddStripableToSelection (stripable[n]);
325 boost::shared_ptr<AutomationControl>
326 LaunchControlXL::get_ac_by_state(uint8_t n) {
327 boost::shared_ptr<AutomationControl> ac;
329 switch(track_mode()) {
331 ac = stripable[n]->mute_control();
335 ac = stripable[n]->solo_control();
339 ac = stripable[n]->rec_enable_control();
348 boost::shared_ptr<LaunchControlXL::Knob>*
349 LaunchControlXL::knobs_by_column(uint8_t col, boost::shared_ptr<Knob>* knob_col)
351 for (uint8_t n = 0; n < 3; ++n) {
352 knob_col[n] = id_knob_map.find(static_cast<KnobID>(col+n*8))->second;
359 LaunchControlXL::update_knob_led(uint8_t n)
363 uint32_t absolute_strip_num = (n + bank_start) % 8;
366 switch (absolute_strip_num) {
369 if (stripable[n]->is_selected()) {
378 if (stripable[n]->is_selected()) {
387 if (stripable[n]->is_selected()) {
396 if (stripable[n]->is_master()) {
399 if (stripable[n]->is_selected()) {
408 boost::shared_ptr<Knob> knobs_col[3];
409 knobs_by_column(n, knobs_col);
411 for (uint8_t s = 0; s < 3; ++s)
414 knobs_col[s]->set_color(color);
416 knobs_col[s]->set_color(Off);
418 write (knobs_col[s]->state_msg());
423 LaunchControlXL::update_track_control_led(uint8_t n)
425 boost::shared_ptr<TrackButton> b = control_button_by_column(n);
432 boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
434 switch(track_mode()) {
436 if (ac->get_value()) {
437 b->set_color(YellowFull);
439 b->set_color(AmberLow);
443 if (ac && !(stripable[n]->is_master())) {
444 if (ac->get_value()) {
445 b->set_color(GreenFull);
447 b->set_color(GreenLow);
455 if (ac->get_value()) {
456 b->set_color(RedFull);
458 b->set_color(RedLow);
472 write (b->state_msg());
476 LaunchControlXL::solo_mute_rec_changed(uint32_t n) {
480 update_track_control_led(n);
484 LaunchControlXL::solo_iso_changed(uint32_t n)
494 LaunchControlXL::solo_iso_led_bank ()
496 int stripable_counter = get_amount_of_tracks();
498 if (!(buttons_down.find(Device) != buttons_down.end())) {
501 for (int n = 0; n < stripable_counter; ++n) {
502 boost::shared_ptr<TrackButton> b = focus_button_by_column(n);
503 if (stripable[n] && stripable[n]->solo_isolate_control()) {
504 if (stripable[n]->solo_isolate_control()->get_value()) {
505 b->set_color(RedFull);
509 write (b->state_msg());
512 LaunchControlXL::set_refresh_leds_flag(true);
518 LaunchControlXL::master_send_changed(uint32_t n)
523 master_send_led_bank();
529 LaunchControlXL::master_send_led_bank ()
531 if (!(buttons_down.find(Device) != buttons_down.end())) {
534 int stripable_counter = LaunchControlXL::get_amount_of_tracks();
536 for (int n = 0; n < stripable_counter; ++n) {
537 boost::shared_ptr<TrackButton> b = control_button_by_column(n);
538 if (stripable[n] && stripable[n]->master_send_enable_controllable()) {
539 if (stripable[n]->master_send_enable_controllable()->get_value()) {
540 b->set_color(GreenFull);
545 write (b->state_msg());
547 LaunchControlXL::set_refresh_leds_flag(true);
553 LaunchControlXL::button_track_control(uint8_t n) {
558 if (buttons_down.find(Device) != buttons_down.end()) {
559 DEBUG_TRACE (DEBUG::LaunchControlXL, "DEVICE BUTTON HOLD\n");
561 if (stripable[n]->master_send_enable_controllable()) {
562 bool master_send_active = stripable[n]->master_send_enable_controllable()->get_value();
564 DEBUG_TRACE (DEBUG::LaunchControlXL, "MIXBUS Master Assign\n");
565 stripable[n]->master_send_enable_controllable()->set_value (!master_send_active, PBD::Controllable::UseGroup);
569 /* something useful for Ardour */
574 boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
577 session->set_control (ac, !ac->get_value(), PBD::Controllable::UseGroup);
582 LaunchControlXL::button_track_mode(TrackMode state)
584 set_track_mode(state);
585 for (uint8_t n = 0; n < 8; ++n) {
586 update_track_control_led(n);
589 boost::shared_ptr<TrackStateButton> mute = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Mute]);
590 boost::shared_ptr<TrackStateButton> solo = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Solo]);
591 boost::shared_ptr<TrackStateButton> record = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Record]);
593 write(mute->state_msg((state == TrackMute)));
594 write(solo->state_msg((state == TrackSolo)));
595 write(record->state_msg((state == TrackRecord)));
599 LaunchControlXL::button_select_left()
601 switch_bank (max (0, bank_start - (7 + (fader8master() ? 0 : 1))));
605 LaunchControlXL::button_select_right()
607 switch_bank (max (0, bank_start + 7 + (fader8master() ? 0 : 1)));
611 LaunchControlXL::button_select_up()
617 LaunchControlXL::button_select_down()
623 LaunchControlXL::button_device()
629 LaunchControlXL::button_device_long_press()
633 master_send_led_bank();
638 LaunchControlXL::button_mute()
640 if (buttons_down.find(Device) != buttons_down.end()) {
641 access_action ("Editor/track-mute-toggle");
643 button_track_mode(TrackMute);
648 LaunchControlXL::button_solo()
650 if (buttons_down.find(Device) != buttons_down.end()) {
651 access_action ("Editor/track-solo-toggle");
653 button_track_mode(TrackSolo);
658 LaunchControlXL::button_record()
660 if (buttons_down.find(Device) != buttons_down.end()) {
661 access_action ("Editor/track-record-enable-toggle");
663 button_track_mode(TrackRecord);
668 LaunchControlXL::button_long_press_timeout (ButtonID id, boost::shared_ptr<Button> button)
670 if (buttons_down.find (id) != buttons_down.end()) {
671 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, invoking method\n", id));
672 (this->*button->long_press_method) ();
674 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, expired/cancelled\n", id));
675 /* release happened and somehow we were not cancelled */
678 /* whichever button this was, we've used it ... don't invoke the
681 consumed.insert (id);
683 return false; /* don't get called again */
688 LaunchControlXL::start_press_timeout (boost::shared_ptr<Button> button, ButtonID id)
690 Glib::RefPtr<Glib::TimeoutSource> timeout = Glib::TimeoutSource::create (500); // milliseconds
691 button->timeout_connection = timeout->connect (sigc::bind (sigc::mem_fun (*this, &LaunchControlXL::button_long_press_timeout), id, button));
692 timeout->attach (main_loop()->get_context());