summaryrefslogtreecommitdiff
path: root/libs/surfaces/launch_control_xl/controllers.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/surfaces/launch_control_xl/controllers.cc')
-rw-r--r--libs/surfaces/launch_control_xl/controllers.cc487
1 files changed, 487 insertions, 0 deletions
diff --git a/libs/surfaces/launch_control_xl/controllers.cc b/libs/surfaces/launch_control_xl/controllers.cc
new file mode 100644
index 0000000000..b686791405
--- /dev/null
+++ b/libs/surfaces/launch_control_xl/controllers.cc
@@ -0,0 +1,487 @@
+/*
+ Copyright (C) 2016 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <algorithm>
+
+#include "ardour/debug.h"
+#include "ardour/mute_control.h"
+#include "ardour/session.h"
+#include "ardour/solo_control.h"
+
+#include "launch_control_xl.h"
+
+using namespace ArdourSurface;
+using namespace ARDOUR;
+using namespace PBD;
+using std::cerr;
+
+void
+LaunchControlXL::build_maps ()
+{
+ /* Knobs */
+
+ Knob* knob;
+
+ #define MAKE_KNOB(i,cc, index, color) \
+ knob = new Knob ((i), (cc), (index), (color), (*this)); \
+ cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
+ id_knob_map.insert (std::make_pair (knob->id(), knob))
+
+ for (uint8_t n = 0; n < 8; ++n) {
+ MAKE_KNOB (static_cast<KnobID>(n), (n + 13), n, LEDColor::RedFull);
+ MAKE_KNOB (static_cast<KnobID>(n + 8), (n + 29), (n + 8), LEDColor::GreenFull);
+ MAKE_KNOB (static_cast<KnobID>(n + 16), (n + 49), (n + 16), LEDColor::Yellow);
+ }
+
+ /* Faders */
+
+ Fader* fader;
+
+ #define MAKE_FADER(i,cc) \
+ fader = new Fader ((i), (cc)); \
+ cc_fader_map.insert (std::make_pair (fader->controller_number(), fader)); \
+ id_fader_map.insert (std::make_pair (fader->id(), fader))
+
+ for (uint8_t n = 0; n < 8; ++n) {
+ MAKE_FADER (static_cast<FaderID>(n), (n + 77) );
+ }
+
+ /* Buttons */
+
+ ControllerButton *controller_button;
+ NoteButton *note_button;
+
+
+ #define MAKE_TRACK_BUTTON_PRESS(i,nn,index,color,p) \
+ note_button = new TrackButton ((i), (nn), (index), (color), (p), (*this)); \
+ nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
+ id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
+ #define MAKE_SELECT_BUTTON_PRESS(i,cc,index,p) \
+ controller_button = new SelectButton ((i), (cc), (index), (p), (*this)); \
+ cc_controller_button_map.insert (std::make_pair (controller_button->controller_number(), controller_button)); \
+ id_controller_button_map.insert (std::make_pair (controller_button->id(), controller_button))
+ #define MAKE_TRACK_STATE_BUTTON_PRESS(i,nn,index,p) \
+ note_button = new TrackStateButton ((i), (nn), (index), (p), (*this)); \
+ nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
+ id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
+ #define MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(i,nn,index, p,r,l) \
+ note_button = new TrackStateButton ((i), (nn), (index), (p), (r), (l), (*this)); \
+ nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
+ id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
+
+
+ MAKE_TRACK_BUTTON_PRESS(Focus1, 41, 24, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_1);
+ MAKE_TRACK_BUTTON_PRESS(Focus2, 42, 25, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_2);
+ MAKE_TRACK_BUTTON_PRESS(Focus3, 43, 26, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_3);
+ MAKE_TRACK_BUTTON_PRESS(Focus4, 44, 27, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_4);
+ MAKE_TRACK_BUTTON_PRESS(Focus5, 57, 28, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_5);
+ MAKE_TRACK_BUTTON_PRESS(Focus6, 58, 29, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_6);
+ MAKE_TRACK_BUTTON_PRESS(Focus7, 59, 30, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_7);
+ MAKE_TRACK_BUTTON_PRESS(Focus8, 60, 31, LEDColor::GreenFull, &LaunchControlXL::button_track_focus_8);
+ MAKE_TRACK_BUTTON_PRESS(Control1, 73, 32, LEDColor::Yellow, &LaunchControlXL::button_track_control_1);
+ MAKE_TRACK_BUTTON_PRESS(Control2, 74, 33, LEDColor::Yellow, &LaunchControlXL::button_track_control_2);
+ MAKE_TRACK_BUTTON_PRESS(Control3, 75, 34, LEDColor::Yellow, &LaunchControlXL::button_track_control_3);
+ MAKE_TRACK_BUTTON_PRESS(Control4, 76, 35, LEDColor::Yellow, &LaunchControlXL::button_track_control_4);
+ MAKE_TRACK_BUTTON_PRESS(Control5, 89, 36, LEDColor::Yellow, &LaunchControlXL::button_track_control_5);
+ MAKE_TRACK_BUTTON_PRESS(Control6, 90, 37, LEDColor::Yellow, &LaunchControlXL::button_track_control_6);
+ MAKE_TRACK_BUTTON_PRESS(Control7, 91, 38, LEDColor::Yellow, &LaunchControlXL::button_track_control_7);
+ MAKE_TRACK_BUTTON_PRESS(Control8, 92, 39, LEDColor::Yellow, &LaunchControlXL::button_track_control_8);
+
+ MAKE_SELECT_BUTTON_PRESS(SelectUp, 104, 44, &LaunchControlXL::button_select_up);
+ MAKE_SELECT_BUTTON_PRESS(SelectDown, 105, 45, &LaunchControlXL::button_select_down);
+ MAKE_SELECT_BUTTON_PRESS(SelectLeft, 106, 46, &LaunchControlXL::button_select_left);
+ MAKE_SELECT_BUTTON_PRESS(SelectRight, 107, 47, &LaunchControlXL::button_select_right);
+
+ MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Device, 105, 40, &LaunchControlXL::relax, &LaunchControlXL::button_device, &LaunchControlXL::button_device_long_press);;
+ MAKE_TRACK_STATE_BUTTON_PRESS(Mute, 106, 41, &LaunchControlXL::button_mute);
+ MAKE_TRACK_STATE_BUTTON_PRESS(Solo, 107, 42, &LaunchControlXL::button_solo);
+ MAKE_TRACK_STATE_BUTTON_PRESS(Record, 108, 43, &LaunchControlXL::button_record);
+
+}
+
+std::string
+LaunchControlXL::button_name_by_id (ButtonID id)
+{
+ switch (id) {
+ case Device:
+ return "Device";
+ case Mute:
+ return "Mute";
+ case Solo:
+ return "Solo";
+ case Record:
+ return "Record";
+ case SelectUp:
+ return "Select Up";
+ case SelectDown:
+ return "Select Down";
+ case SelectRight:
+ return "Select Right";
+ case SelectLeft:
+ return "Select Left";
+ case Focus1:
+ return "Focus 1";
+ case Focus2:
+ return "Focus 2";
+ case Focus3:
+ return "Focus 3";
+ case Focus4:
+ return "Focus 4";
+ case Focus5:
+ return "Focus 5";
+ case Focus6:
+ return "Focus 6";
+ case Focus7:
+ return "Focus 7";
+ case Focus8:
+ return "Focus 8";
+ case Control1:
+ return "Control 1";
+ case Control2:
+ return "Control 2";
+ case Control3:
+ return "Control 3";
+ case Control4:
+ return "Control 4";
+ case Control5:
+ return "Control 5";
+ case Control6:
+ return "Control 6";
+ case Control7:
+ return "Control 7";
+ case Control8:
+ return "Control 8";
+ default:
+ break;
+ }
+
+ return "???";
+}
+
+std::string
+LaunchControlXL::knob_name_by_id (KnobID id)
+{
+ switch (id) {
+ case SendA1:
+ return "SendA 1";
+ case SendA2:
+ return "SendA 2";
+ case SendA3:
+ return "SendA 3";
+ case SendA4:
+ return "SendA 4";
+ case SendA5:
+ return "SendA 5";
+ case SendA6:
+ return "SendA 6";
+ case SendA7:
+ return "SendA 7";
+ case SendA8:
+ return "SendA 8";
+ case SendB1:
+ return "SendB 1";
+ case SendB2:
+ return "SendB 2";
+ case SendB3:
+ return "SendB 3";
+ case SendB4:
+ return "SendB 4";
+ case SendB5:
+ return "SendB 5";
+ case SendB6:
+ return "SendB 6";
+ case SendB7:
+ return "SendB 7";
+ case SendB8:
+ return "SendB 8";
+ case Pan1:
+ return "Pan 1";
+ case Pan2:
+ return "Pan 2";
+ case Pan3:
+ return "Pan 3";
+ case Pan4:
+ return "Pan 4";
+ case Pan5:
+ return "Pan 5";
+ case Pan6:
+ return "Pan 6";
+ case Pan7:
+ return "Pan 7";
+ case Pan8:
+ return "Pan 8";
+ default:
+ break;
+ }
+
+ return "???";
+}
+
+std::string
+LaunchControlXL::fader_name_by_id (FaderID id)
+{
+ switch (id) {
+ case Fader1:
+ return "Fader 1";
+ case Fader2:
+ return "Fader 2";
+ case Fader3:
+ return "Fader 3";
+ case Fader4:
+ return "Fader 4";
+ case Fader5:
+ return "Fader 5";
+ case Fader6:
+ return "Fader 6";
+ case Fader7:
+ return "Fader 7";
+ case Fader8:
+ return "Fader 8";
+ default:
+ break;
+ }
+
+ return "???";
+}
+
+LaunchControlXL::TrackButton*
+LaunchControlXL::track_button_by_number(uint8_t n, uint8_t first, uint8_t middle)
+{
+ NNNoteButtonMap::iterator b;
+ if ( n < 5) {
+ b = nn_note_button_map.find (first + n);
+ }
+ else {
+ b = nn_note_button_map.find (middle + n);
+ }
+
+ TrackButton* button;
+
+ if (b != nn_note_button_map.end()) {
+ button = static_cast<TrackButton*>(b->second);
+ }
+
+ return button;
+
+}
+
+void
+LaunchControlXL::button_track_focus(uint8_t n)
+{
+ if (!stripable[n]) {
+ return;
+ }
+
+ TrackButton* b = focus_button_by_number(n);
+
+ if (b == 0) {
+ return;
+ }
+
+ if ( stripable[n]->is_selected() ) {
+ b->set_color(LEDColor::AmberFull);
+ }
+ else {
+ b->set_color(LEDColor::AmberLow);
+ }
+ write (b->state_msg());
+
+}
+
+boost::shared_ptr<AutomationControl>
+LaunchControlXL::get_ac_by_state(uint8_t n) {
+ boost::shared_ptr<AutomationControl> ac;
+
+ switch(track_mode()) {
+ case TrackMute:
+ ac = stripable[n]->mute_control();
+ break;
+
+ case TrackSolo:
+ ac = stripable[n]->solo_control();
+ break;
+
+ case TrackRecord:
+ ac = stripable[n]->rec_enable_control();
+ break;
+
+ default:
+ break;
+ }
+ return ac;
+}
+
+
+void
+LaunchControlXL::update_track_control_led(uint8_t n)
+{
+ TrackButton* b = control_button_by_number(n);
+
+ if (!stripable[n] || !b) {
+ return;
+ }
+
+ boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
+
+
+ switch(track_mode()) {
+ case TrackMute:
+ if (ac->get_value()) {
+ b->set_color(LEDColor::AmberFull);
+ }
+ else {
+ b->set_color(LEDColor::AmberLow);
+ }
+ break;
+
+ case TrackSolo:
+ if (ac && stripable[n] != master ) {
+ if (ac->get_value()) {
+ b->set_color(LEDColor::GreenFull);
+ }
+ else {
+ b->set_color(LEDColor::GreenLow);
+ }
+ }
+ else {
+ b->set_color(LEDColor::Off);
+ }
+ break;
+
+ case TrackRecord:
+ if (ac) {
+ if (ac->get_value()) {
+ b->set_color(LEDColor::RedFull);
+ }
+ else {
+ b->set_color(LEDColor::RedLow);
+ }
+ }
+ else {
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (ac) {
+ write (b->state_msg());
+ }
+}
+
+void
+LaunchControlXL::solo_mute_rec_changed(uint32_t n) {
+ if (!stripable[n]) {
+ return;
+ }
+ update_track_control_led(n);
+}
+
+void
+LaunchControlXL::button_track_control(uint8_t n) {
+ if (!stripable[n]) {
+ return;
+ }
+ boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
+
+ if (ac) {
+ session->set_control (ac, !ac->get_value(), PBD::Controllable::UseGroup);
+ }
+}
+
+void
+LaunchControlXL::button_track_mode(TrackMode state)
+{
+ set_track_mode(state);
+ for (uint8_t n = 0; n < 8; ++n) {
+ update_track_control_led(n);
+ }
+
+ TrackStateButton* mute = static_cast<TrackStateButton*>(id_note_button_map[Mute]);
+ TrackStateButton* solo = static_cast<TrackStateButton*>(id_note_button_map[Solo]);
+ TrackStateButton* record = static_cast<TrackStateButton*>(id_note_button_map[Record]);
+
+ write(mute->state_msg( (state == TrackMute) ));
+ write(solo->state_msg( (state == TrackSolo) ));
+ write(record->state_msg( (state == TrackRecord) ));
+}
+
+void
+LaunchControlXL::button_select_left()
+{
+ switch_bank (max (0, bank_start - 1));
+}
+
+void
+LaunchControlXL::button_select_right()
+{
+ switch_bank (max (0, bank_start + 1));
+}
+
+void
+LaunchControlXL::button_select_up()
+{
+
+}
+
+void
+LaunchControlXL::button_select_down()
+{
+
+}
+
+void
+LaunchControlXL::button_device()
+{
+
+}
+
+void
+LaunchControlXL::button_device_long_press()
+{
+
+}
+
+bool
+LaunchControlXL::button_long_press_timeout (ButtonID id, Button* button)
+{
+ if (buttons_down.find (id) != buttons_down.end()) {
+ DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, invoking method\n", id));
+ (this->*button->long_press_method) ();
+ } else {
+ DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, expired/cancelled\n", id));
+ /* release happened and somehow we were not cancelled */
+ }
+
+ /* whichever button this was, we've used it ... don't invoke the
+ release action.
+ */
+ consumed.insert (id);
+
+ return false; /* don't get called again */
+}
+
+
+void
+LaunchControlXL::start_press_timeout (Button* button, ButtonID id)
+{
+ Glib::RefPtr<Glib::TimeoutSource> timeout = Glib::TimeoutSource::create (500); // milliseconds
+ button->timeout_connection = timeout->connect (sigc::bind (sigc::mem_fun (*this, &LaunchControlXL::button_long_press_timeout), id, button));
+ timeout->attach (main_loop()->get_context());
+}