LCXL: complete overhaul and Mixbus support
[ardour.git] / libs / surfaces / launch_control_xl / controllers.cc
index eca0f7b7d7b24bc42571d80e7ffae1b3fb646603..37c048034f757cf7cf8ece4eafb5ce9390d9b96d 100644 (file)
@@ -34,44 +34,170 @@ using std::cerr;
 void
 LaunchControlXL::build_maps ()
 {
-       /* Knobs */
+       cc_knob_map.clear();
+       id_knob_map.clear();
+       cc_fader_map.clear();
+       id_fader_map.clear();
+       nn_note_button_map.clear();
+       id_note_button_map.clear();
+       cc_controller_button_map.clear();
+       id_controller_button_map.clear();
 
+       /* Knobs */
        boost::shared_ptr<Knob> knob;
 
-       #define MAKE_KNOB(i,cc,index,a) \
-               knob.reset (new Knob ((i), (cc), (index), (a), (*this))); \
+       #define MAKE_KNOB(i,cc,index,c_on,c_off,a) \
+               knob.reset (new Knob ((i), (cc), (index), (c_on), (c_off), (a), (*this))); \
                cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
-               id_knob_map.insert (std::make_pair (knob->id(), knob))
-
-       MAKE_KNOB (SendA1, 13, 0, &LaunchControlXL::knob_sendA1);
-       MAKE_KNOB (SendA2, 14, 1, &LaunchControlXL::knob_sendA2);
-       MAKE_KNOB (SendA3, 15, 2, &LaunchControlXL::knob_sendA3);
-       MAKE_KNOB (SendA4, 16, 3, &LaunchControlXL::knob_sendA4);
-       MAKE_KNOB (SendA5, 17, 4, &LaunchControlXL::knob_sendA5);
-       MAKE_KNOB (SendA6, 18, 5, &LaunchControlXL::knob_sendA6);
-       MAKE_KNOB (SendA7, 19, 6, &LaunchControlXL::knob_sendA7);
-       MAKE_KNOB (SendA8, 20, 7, &LaunchControlXL::knob_sendA8);
-
-       MAKE_KNOB (SendB1, 29, 8, &LaunchControlXL::knob_sendB1);
-       MAKE_KNOB (SendB2, 30, 9, &LaunchControlXL::knob_sendB2);
-       MAKE_KNOB (SendB3, 31, 10, &LaunchControlXL::knob_sendB3);
-       MAKE_KNOB (SendB4, 32, 11, &LaunchControlXL::knob_sendB4);
-       MAKE_KNOB (SendB5, 33, 12, &LaunchControlXL::knob_sendB5);
-       MAKE_KNOB (SendB6, 34, 13, &LaunchControlXL::knob_sendB6);
-       MAKE_KNOB (SendB7, 35, 14, &LaunchControlXL::knob_sendB7);
-       MAKE_KNOB (SendB8, 36, 15, &LaunchControlXL::knob_sendB8);
-
-       MAKE_KNOB (Pan1, 49, 16, &LaunchControlXL::knob_pan1);
-       MAKE_KNOB (Pan2, 50, 17, &LaunchControlXL::knob_pan2);
-       MAKE_KNOB (Pan3, 51, 18, &LaunchControlXL::knob_pan3);
-       MAKE_KNOB (Pan4, 52, 19, &LaunchControlXL::knob_pan4);
-       MAKE_KNOB (Pan5, 53, 20, &LaunchControlXL::knob_pan5);
-       MAKE_KNOB (Pan6, 54, 21, &LaunchControlXL::knob_pan6);
-       MAKE_KNOB (Pan7, 55, 22, &LaunchControlXL::knob_pan7);
-       MAKE_KNOB (Pan8, 56, 23, &LaunchControlXL::knob_pan8);
+               id_knob_map.insert (std::make_pair (knob->id(), knob));
+       #define MAKE_DM_KNOB(i,cc,index,c_on,c_off,action,check) \
+               knob.reset (new Knob ((i), (cc), (index), (c_on), (c_off), (action), (check), (*this))); \
+               cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
+               id_knob_map.insert (std::make_pair (knob->id(), knob));
+
+       if (!device_mode()) {   /* mixer mode */
+               MAKE_KNOB (SendA1, 13, 0, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 0)));
+               MAKE_KNOB (SendA2, 14, 1, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 1)));
+               MAKE_KNOB (SendA3, 15, 2, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 2)));
+               MAKE_KNOB (SendA4, 16, 3, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 3)));
+               MAKE_KNOB (SendA5, 17, 4, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 4)));
+               MAKE_KNOB (SendA6, 18, 5, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 5)));
+               MAKE_KNOB (SendA7, 19, 6, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 6)));
+               MAKE_KNOB (SendA8, 20, 7, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendA, this, 7)));
+
+               MAKE_KNOB (SendB1, 29, 8, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 0)));
+               MAKE_KNOB (SendB2, 30, 9, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 1)));
+               MAKE_KNOB (SendB3, 31, 10, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 2)));
+               MAKE_KNOB (SendB4, 32, 11, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 3)));
+               MAKE_KNOB (SendB5, 33, 12, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 4)));
+               MAKE_KNOB (SendB6, 34, 13, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 5)));
+               MAKE_KNOB (SendB7, 35, 14, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 6)));
+               MAKE_KNOB (SendB8, 36, 15, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_sendB, this, 7)));
+
+               MAKE_KNOB (Pan1, 49, 16, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 0)));
+               MAKE_KNOB (Pan2, 50, 17, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 1)));
+               MAKE_KNOB (Pan3, 51, 18, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 2)));
+               MAKE_KNOB (Pan4, 52, 19, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 3)));
+               MAKE_KNOB (Pan5, 53, 20, RedFull, RedLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 4)));
+               MAKE_KNOB (Pan6, 54, 21, YellowFull, YellowLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 5)));
+               MAKE_KNOB (Pan7, 55, 22, GreenFull, GreenLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 6)));
+               MAKE_KNOB (Pan8, 56, 23, AmberFull, AmberLow, boost::function<void ()> (boost::bind (&LaunchControlXL::knob_pan, this, 7)));
+
+       } else {        /* device mode */
+
+#ifdef MIXBUS // from here Mixbus Standard + 32C
+               MAKE_DM_KNOB (SendB5, 33, 12, RedFull, RedLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_trim, this, SendB5)),
+                               boost::bind(&LaunchControlXL::dm_check_trim, this));
+               MAKE_DM_KNOB (SendB6, 34, 13, GreenFull, GreenLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_comp, this, SendB6, CompMakeup)),
+                               boost::bind(&LaunchControlXL::dm_mb_comp_enabled,this));
+               MAKE_DM_KNOB (SendB7, 35, 14, GreenFull, GreenLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_comp, this, SendB7, CompSpeed)),
+                               boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
+               MAKE_DM_KNOB (SendB8, 36, 15, GreenFull, GreenLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_comp, this, SendB8, CompMode)),
+                               boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
+
+               /* Pan Knobs -> Sends */
+               for (uint8_t i = 0; i < 8; ++i) {
+                       MAKE_DM_KNOB (static_cast<KnobID>(i + 16), (i + 49), (i + 16), GreenLow, YellowLow, boost::function<void()>
+                               (boost::bind (&LaunchControlXL::dm_mb_sends, this, static_cast<KnobID>(i + 16))),
+                               boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_check_send_knob, this, static_cast<KnobID>(i + 16))));
+               }
 
-       /* Faders */
+#ifdef MIXBUS32C // from here 32C only
+
+               if (first_selected_stripable() && (first_selected_stripable()->is_master() || first_selected_stripable()->mixbus())) {
+                       MAKE_DM_KNOB (SendA1, 13, 0, AmberFull, AmberLow, boost::function<void ()>
+                                       (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA1, true, 0)),
+                                       boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
+                       MAKE_DM_KNOB (SendA2, 14, 1, AmberFull, AmberLow, boost::function<void ()>
+                                       (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA2, true, 1)),
+                                       boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 1)));
+                       MAKE_DM_KNOB (SendA3, 15, 2, AmberFull, AmberLow, boost::function<void ()>
+                                       (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA3, true, 2)),
+                                       boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 2)));
+                       MAKE_DM_KNOB (SendA6, 18, 5, RedLow, RedLow, boost::function<void ()>
+                                       (boost::bind (&LaunchControlXL::dm_pan_width, this, SendA6)),
+                                       boost::bind(&LaunchControlXL::dm_check_pan_width, this));
+                       MAKE_DM_KNOB (SendA7, 19, 6, AmberLow, AmberLow, boost::function<void ()>
+                                       (boost::bind (&LaunchControlXL::dm_mb_tapedrive, this, SendA7)),
+                                       boost::bind(&LaunchControlXL::dm_mb_has_tapedrive, this));
+               } else {
+                       MAKE_DM_KNOB (SendA1, 13, 0, AmberFull, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA1, false, 0)),
+                                     boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+                       MAKE_DM_KNOB (SendA2, 14, 1, AmberFull, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA2, true, 0)),
+                                     boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
+                       MAKE_DM_KNOB (SendA3, 15, 2, YellowLow, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA3, false, 1)),
+                                     boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+                       MAKE_DM_KNOB (SendA4, 16, 3, YellowLow, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA4, true, 1)),
+                                     boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 1)));
+                       MAKE_DM_KNOB (SendA5, 17, 4, AmberFull, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA5, false, 2)),
+                                     boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+                       MAKE_DM_KNOB (SendA6, 18, 5, AmberFull, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA6, true, 2)),
+                                     boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 2)));
+                       MAKE_DM_KNOB (SendA7, 19, 6, YellowLow, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA7, false, 3)),
+                                     boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+                       MAKE_DM_KNOB (SendA8, 20, 7, YellowLow, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA8, true, 3)),
+                                     boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 3)));
+               }
+                       MAKE_DM_KNOB (SendB1, 29, 8, YellowFull, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_flt_frq, this, SendB1, true)),
+                                     boost::bind(&LaunchControlXL::dm_mb_flt_enabled, this));
+                       MAKE_DM_KNOB (SendB2, 30, 9, YellowFull, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_mb_flt_frq, this, SendB2, false)),
+                                     boost::bind(&LaunchControlXL::dm_mb_flt_enabled, this));
+                       MAKE_DM_KNOB (SendB4, 32, 11, RedLow, AmberLow, boost::function<void ()>
+                                     (boost::bind (&LaunchControlXL::dm_pan_azi, this, SendB4)),
+                                     boost::bind(&LaunchControlXL::dm_check_pan_azi, this));
+
+#else  // from here Mixbus Standard only
+               MAKE_DM_KNOB (SendA1, 13, 0, AmberFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA1, true, 0)),
+                               boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
+               MAKE_DM_KNOB (SendA2, 14, 1, AmberFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA2, true, 1)),
+                               boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 1)));
+               MAKE_DM_KNOB (SendA3, 15, 2, AmberFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendA3, true, 2)),
+                               boost::function<uint8_t ()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 2)));
+               MAKE_DM_KNOB (SendA5, 17, 4, RedLow, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_pan_azi, this, SendA5)),
+                               boost::bind(&LaunchControlXL::dm_check_pan_azi, this));
+               MAKE_DM_KNOB (SendA6, 18, 5, RedLow, RedLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_pan_width, this, SendA6)),
+                               boost::bind(&LaunchControlXL::dm_check_pan_width, this));
+               MAKE_DM_KNOB (SendA7, 19, 6, AmberLow, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_tapedrive, this, SendA7)),
+                               boost::bind(&LaunchControlXL::dm_mb_has_tapedrive, this));
+               MAKE_DM_KNOB (SendB1, 29, 8, YellowFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendB1, false, 0)),
+                               boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+               MAKE_DM_KNOB (SendB2, 30, 9, YellowFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendB2, false, 1)),
+                               boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+               MAKE_DM_KNOB (SendB3, 31, 10, YellowFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_eq, this, SendB3, false, 2)),
+                               boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+               MAKE_DM_KNOB (SendB4, 32, 11, YellowFull, AmberLow, boost::function<void ()>
+                               (boost::bind (&LaunchControlXL::dm_mb_flt_frq, this, SendB4, true)),
+                               boost::bind(&LaunchControlXL::dm_mb_eq_freq_enabled, this));
+#endif
+#else // from here Ardour
+#endif
+       }
 
+
+       /* Faders */
        boost::shared_ptr<Fader> fader;
 
        #define MAKE_FADER(i,cc,a) \
@@ -79,32 +205,44 @@ LaunchControlXL::build_maps ()
                cc_fader_map.insert (std::make_pair (fader->controller_number(), fader)); \
                id_fader_map.insert (std::make_pair (fader->id(), fader))
 
-       MAKE_FADER (Fader1, 77, &LaunchControlXL::fader_1);
-       MAKE_FADER (Fader2, 78, &LaunchControlXL::fader_2);
-       MAKE_FADER (Fader3, 79, &LaunchControlXL::fader_3);
-       MAKE_FADER (Fader4, 80, &LaunchControlXL::fader_4);
-       MAKE_FADER (Fader5, 81, &LaunchControlXL::fader_5);
-       MAKE_FADER (Fader6, 82, &LaunchControlXL::fader_6);
-       MAKE_FADER (Fader7, 83, &LaunchControlXL::fader_7);
-       MAKE_FADER (Fader8, 84, &LaunchControlXL::fader_8);
+       if (!device_mode()) {   /* mix mode */
+               for (uint8_t i = 0; i < 8; ++i) {
+                       MAKE_FADER(static_cast<FaderID>(i), i+77, boost::function<void()>
+                               (boost::bind (&LaunchControlXL::fader, this, i)));
+               }
 
+       } else {        /* device mode */
+               MAKE_FADER(Fader1, 77,  boost::function<void()>
+                       (boost::bind (&LaunchControlXL::dm_fader, this, Fader1)));
+#ifdef MIXBUS
+               MAKE_FADER(Fader2, 78,  boost::function<void()>
+                       (boost::bind (&LaunchControlXL::dm_mb_comp_thresh, this, Fader2)));
+#endif
+       }
 
        /* Buttons */
-
        boost::shared_ptr<ControllerButton> controller_button;
        boost::shared_ptr<NoteButton> note_button;
 
 
-       #define MAKE_TRACK_BUTTON_PRESS(i,nn,index,color,p) \
-               note_button.reset (new TrackButton ((i), (nn), (index), (color), (p), (*this))); \
+       #define MAKE_TRACK_BUTTON_PRESS(i,nn,index,c_on,c_off,p,check) \
+               note_button.reset (new TrackButton ((i), (nn), (index), (c_on), (c_off), (p), \
+               boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (check), (*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_CTRL_BUTTON_PRESS(i,nn,index,c_on,c_off,p,check) \
+               note_button.reset (new TrackButton ((i), (nn), (index), (c_on), (c_off),  (p), \
+               boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (check), (*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.reset (new SelectButton ((i), (cc), (index), (p), (*this))); \
+               controller_button.reset (new SelectButton ((i), (cc), (index), (p), \
+               boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (*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.reset (new TrackStateButton ((i), (nn), (index), (p), (*this))); \
+               note_button.reset (new TrackStateButton ((i), (nn), (index), (p), \
+               boost::bind(&LaunchControlXL::relax, this), boost::bind(&LaunchControlXL::relax, this), (*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) \
@@ -112,34 +250,124 @@ LaunchControlXL::build_maps ()
                        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))
 
+       /* Track Focus Buttons */
+       if (!device_mode()) {   /* mixer mode */
+               for (uint8_t i = 0; i < 4; ++i) {
+                       MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i), i+41, i+24, YellowFull, YellowLow,
+                               boost::function<void()> (boost::bind (&LaunchControlXL::button_track_focus, this, i)),
+                               boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
+               }
+
+               for (uint8_t i = 0; i < 4; ++i) {
+                       MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i+4), i+57, i+28, YellowFull, YellowLow,
+                               boost::function<void()> (boost::bind (&LaunchControlXL::button_track_focus, this, i+4)),
+                               boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
+               }
+
+       } else {                /* device mode */
+#ifdef MIXBUS
+               for (uint8_t i = 0; i < 4; ++i) {
+                       MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i), i+41, i+24, GreenFull, YellowLow,
+                               boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_send_switch, this, static_cast<ButtonID>(i))),
+                               boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_mb_check_send_button, this, i)));
+
+               }
+
+               for (uint8_t i = 0; i < 4; ++i) {
+                       MAKE_TRACK_BUTTON_PRESS(static_cast<ButtonID>(i+4), i+57, i+28, GreenFull, YellowLow,
+                               boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_send_switch, this, static_cast<ButtonID>(i+4))),
+                               boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_mb_check_send_button, this, i+4)));
+               }
+#endif
+       }
+       /* Track Control Buttons */
+       if (!device_mode()) {   /* mixer mode */
+               /* Control Buttons in mix mode change their color dynamically so we won't set them here */
+               for (uint8_t i = 0; i < 4; ++i) {
+                       MAKE_CTRL_BUTTON_PRESS(static_cast<ButtonID>(i+8), i+73, i+32, Off, Off,
+                               boost::function<void()> (boost::bind (&LaunchControlXL::button_press_track_control, this, i)),
+                               boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
+               }
+
+               for (uint8_t i = 0; i < 4; ++i) {
+                       MAKE_CTRL_BUTTON_PRESS(static_cast<ButtonID>(i+12), i+89, i+36, Off, Off,
+                               boost::function<void()> (boost::bind (&LaunchControlXL::button_press_track_control, this, i+4)),
+                               boost::function<uint8_t()> (boost::bind (&LaunchControlXL::dm_check_dummy, this, dev_nonexistant)));
+               }
+
+       } else { /*device mode */
+#ifdef MIXBUS // from here Mixbus Standard + 32C
+               MAKE_CTRL_BUTTON_PRESS(Control1, 73, 32, YellowFull, YellowLow, (boost::bind (&LaunchControlXL::dm_mute_switch, this)),
+                       boost::bind (&LaunchControlXL::dm_mute_enabled, this));
+               MAKE_CTRL_BUTTON_PRESS(Control2, 74, 33, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_solo_switch, this)),
+                       boost::bind (&LaunchControlXL::dm_solo_enabled, this));
+               MAKE_CTRL_BUTTON_PRESS(Control3, 75, 34, AmberFull, AmberLow, (boost::bind (&LaunchControlXL::dm_mb_eq_switch, this)),
+                       boost::function<uint8_t()> (boost::bind(&LaunchControlXL::dm_mb_eq_gain_enabled, this, 0)));
+
+
+#ifdef MIXBUS32C // from here 32C only
+               MAKE_CTRL_BUTTON_PRESS(Control4, 76, 35, AmberFull, AmberLow,
+                       boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_eq_shape_switch, this, 0)),
+                       boost::function<uint8_t()> (boost::bind(&LaunchControlXL::dm_mb_eq_shape_enabled, this, 0 )));
+               MAKE_CTRL_BUTTON_PRESS(Control5, 89, 36, AmberFull, AmberLow,
+                       boost::function<void()> (boost::bind (&LaunchControlXL::dm_mb_eq_shape_switch, this, 3)),
+                       boost::function<uint8_t()> (boost::bind(&LaunchControlXL::dm_mb_eq_shape_enabled, this, 3 )));
+               MAKE_CTRL_BUTTON_PRESS(Control6, 90, 37, YellowFull, YellowLow, (boost::bind (&LaunchControlXL::dm_mb_flt_switch, this)),
+                       boost::bind(&LaunchControlXL::dm_mb_flt_enabled, this));
+               MAKE_CTRL_BUTTON_PRESS(Control7, 91, 38, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_master_assign_switch, this)),
+                       boost::bind(&LaunchControlXL::dm_mb_master_assign_enabled, this));
+               MAKE_CTRL_BUTTON_PRESS(Control8, 92, 39, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_comp_switch, this)),
+                       boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
+
+#else // from here Mixbus Standard only
+               MAKE_CTRL_BUTTON_PRESS(Control5, 89, 36, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_master_assign_switch, this)),
+                       boost::bind(&LaunchControlXL::dm_mb_master_assign_enabled, this));
+               MAKE_CTRL_BUTTON_PRESS(Control7, 91, 38, GreenFull, GreenLow, (boost::bind (&LaunchControlXL::dm_mb_comp_switch, this)),
+                       boost::bind(&LaunchControlXL::dm_mb_comp_enabled, this));
+               MAKE_CTRL_BUTTON_PRESS(Control8, 92, 39, RedFull, RedLow, (boost::bind (&LaunchControlXL::dm_recenable_switch, this)),
+                       boost::bind(&LaunchControlXL::dm_recenable_enabled, this));
+
+#endif
+#else // Ardour
+#endif
+       }
+
+       /* Select and Mode Buttons on the right side */
+
+       /* Sends Select buttons are independent of mode */
+       MAKE_SELECT_BUTTON_PRESS(SelectUp, 104, 44, boost::function<void()> (boost::bind (&LaunchControlXL::send_bank_switch, this, false)));
+       MAKE_SELECT_BUTTON_PRESS(SelectDown, 105, 45,  boost::function<void()> (boost::bind (&LaunchControlXL::send_bank_switch, this, true)));
 
-       MAKE_TRACK_BUTTON_PRESS(Focus1, 41, 24, YellowLow, &LaunchControlXL::button_track_focus_1);
-       MAKE_TRACK_BUTTON_PRESS(Focus2, 42, 25, YellowLow, &LaunchControlXL::button_track_focus_2);
-       MAKE_TRACK_BUTTON_PRESS(Focus3, 43, 26, YellowLow, &LaunchControlXL::button_track_focus_3);
-       MAKE_TRACK_BUTTON_PRESS(Focus4, 44, 27, YellowLow, &LaunchControlXL::button_track_focus_4);
-       MAKE_TRACK_BUTTON_PRESS(Focus5, 57, 28, YellowLow, &LaunchControlXL::button_track_focus_5);
-       MAKE_TRACK_BUTTON_PRESS(Focus6, 58, 29, YellowLow, &LaunchControlXL::button_track_focus_6);
-       MAKE_TRACK_BUTTON_PRESS(Focus7, 59, 30, YellowLow, &LaunchControlXL::button_track_focus_7);
-       MAKE_TRACK_BUTTON_PRESS(Focus8, 60, 31, YellowLow, &LaunchControlXL::button_track_focus_8);
-       MAKE_TRACK_BUTTON_PRESS(Control1, 73, 32, AmberLow, &LaunchControlXL::button_track_control_1);
-       MAKE_TRACK_BUTTON_PRESS(Control2, 74, 33, AmberLow, &LaunchControlXL::button_track_control_2);
-       MAKE_TRACK_BUTTON_PRESS(Control3, 75, 34, AmberLow, &LaunchControlXL::button_track_control_3);
-       MAKE_TRACK_BUTTON_PRESS(Control4, 76, 35, AmberLow, &LaunchControlXL::button_track_control_4);
-       MAKE_TRACK_BUTTON_PRESS(Control5, 89, 36, AmberLow, &LaunchControlXL::button_track_control_5);
-       MAKE_TRACK_BUTTON_PRESS(Control6, 90, 37, AmberLow, &LaunchControlXL::button_track_control_6);
-       MAKE_TRACK_BUTTON_PRESS(Control7, 91, 38, AmberLow, &LaunchControlXL::button_track_control_7);
-       MAKE_TRACK_BUTTON_PRESS(Control8, 92, 39, AmberLow, &LaunchControlXL::button_track_control_8);
+       /* Device Button needs to be always there */
+       MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Device, 105, 40,
+               boost::bind (&LaunchControlXL::relax, this) ,
+               boost::bind (&LaunchControlXL::button_device, this),
+               boost::bind (&LaunchControlXL::button_device_long_press, this));
 
-       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);
+       if (!device_mode()) {   /* mixer mode */
+               MAKE_SELECT_BUTTON_PRESS(SelectLeft, 106, 46, boost::bind (&LaunchControlXL::button_select_left, this));
+               MAKE_SELECT_BUTTON_PRESS(SelectRight, 107, 47, boost::bind (&LaunchControlXL::button_select_right, this));
 
+               //MAKE_TRACK_STATE_BUTTON_PRESS(Mute, 106, 41, boost::bind (&LaunchControlXL::button_mute, this));
+
+               MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Mute, 106, 41,
+                       boost::bind (&LaunchControlXL::relax, this) ,
+                       boost::bind (&LaunchControlXL::button_mute, this),
+               boost::bind (&LaunchControlXL::button_mute_long_press, this));
+
+               MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Solo, 107, 42,
+                       boost::bind (&LaunchControlXL::relax, this) ,
+                       boost::bind (&LaunchControlXL::button_solo, this),
+               boost::bind (&LaunchControlXL::button_solo_long_press, this));
+
+               //MAKE_TRACK_STATE_BUTTON_PRESS(Solo, 107, 42, boost::bind (&LaunchControlXL::button_solo, this));
+               MAKE_TRACK_STATE_BUTTON_PRESS(Record, 108, 43, boost::bind (&LaunchControlXL::button_record, this));
+
+       } else {        /* device mode */
+               MAKE_SELECT_BUTTON_PRESS(SelectLeft, 106, 46,  boost::bind (&LaunchControlXL::dm_select_prev_strip, this));
+               MAKE_SELECT_BUTTON_PRESS(SelectRight, 107, 47,  boost::bind (&LaunchControlXL::dm_select_next_strip, this));
+       }
 }
 
 std::string
@@ -349,77 +577,63 @@ LaunchControlXL::get_ac_by_state(uint8_t n) {
                return ac;
 }
 
+boost::shared_ptr<LaunchControlXL::Knob>
+LaunchControlXL::knob_by_id(KnobID id)
+{
+       IDKnobMap::iterator k = id_knob_map.find(id);
+       return boost::dynamic_pointer_cast<Knob> (k->second);
+
+}
+
 boost::shared_ptr<LaunchControlXL::Knob>*
 LaunchControlXL::knobs_by_column(uint8_t col, boost::shared_ptr<Knob>* knob_col)
 {
        for (uint8_t n = 0; n < 3; ++n) {
-               knob_col[n] = id_knob_map.find(static_cast<KnobID>(col+n*8))->second;
+               if (id_knob_map.find(static_cast<KnobID>(col+n*8)) != id_knob_map.end()) {
+                       knob_col[n] = id_knob_map.find(static_cast<KnobID>(col+n*8))->second;
+               }
        }
 
        return knob_col;
 }
 
 void
-LaunchControlXL::update_knob_led(uint8_t n)
+LaunchControlXL::update_knob_led_by_id (uint8_t id, LEDColor color)
 {
-       LEDColor color;
-
-       uint32_t absolute_strip_num = (n + bank_start) % 8;
 
-       if (stripable[n]) {
-               switch (absolute_strip_num) {
-                       case 0:
-                       case 4:
-                               if (stripable[n]->is_selected()) {
-                                       color = RedFull;
-                               } else {
-                                       color = RedLow;
-                               }
-                               break;
+       boost::shared_ptr<Knob> knob = 0;
+       IDKnobMap::iterator k = id_knob_map.find(static_cast<KnobID>(id));
 
-                       case 1:
-                       case 5:
-                               if (stripable[n]->is_selected()) {
-                                       color = YellowFull;
-                               } else {
-                                       color = YellowLow;
-                               }
-                               break;
+       if (k != id_knob_map.end()) {
+               knob = k->second;
+       }
 
-                       case 2:
-                       case 6:
-                               if (stripable[n]->is_selected()) {
-                                       color = GreenFull;
-                               } else {
-                                       color = GreenLow;
-                               }
-                               break;
+       knob->set_color(color);
+       write (knob->state_msg());
+}
 
-                       case 3:
-                       case 7:
-                               if (stripable[n]->is_master()) {
-                                       color = RedFull;
-                               } else {
-                                       if (stripable[n]->is_selected()) {
-                                               color = AmberFull;
-                                       } else {
-                                               color = AmberLow;
-                                       }
-                               }
-               }
-       }
+void
+LaunchControlXL::update_knob_led_by_strip(uint8_t n)
+{
+       LEDColor color;
 
        boost::shared_ptr<Knob> knobs_col[3];
        knobs_by_column(n, knobs_col);
 
-       for  (uint8_t s = 0; s < 3; ++s)
-       {
-               if (stripable[n]) {
-                       knobs_col[s]->set_color(color);
-               } else {
-                       knobs_col[s]->set_color(Off);
+       for  (uint8_t s = 0; s < 3; ++s) {
+               if (knobs_col[s]) {
+                       if (stripable[n]) {
+                               if (stripable[n]->is_selected()) {
+                                       color = knobs_col[s]->color_enabled();
+                               } else {
+                                       color = knobs_col[s]->color_disabled();
+                               }
+                               knobs_col[s]->set_color(color);
+                       } else {
+                               knobs_col[s]->set_color(Off);
+                       }
+                       write (knobs_col[s]->state_msg());
                }
-               write (knobs_col[s]->state_msg());
        }
 }
 
@@ -432,43 +646,22 @@ LaunchControlXL::update_track_control_led(uint8_t n)
                return;
        }
 
-       if (stripable[n]) {
-               boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
+       if ((buttons_down.find(Device) != buttons_down.end())) {
+               /* Don't update LEDs if Device button is hold - we are working on selected strips */
+               return;
+       }
 
-               switch(track_mode()) {
-                       case TrackMute:
+       if (stripable[n]) {
+                       boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
+                       if (ac) {
                                if (ac->get_value()) {
-                                       b->set_color(YellowFull);
-                               } else {
-                                       b->set_color(AmberLow);
-                               }
-                               break;
-                       case TrackSolo:
-                               if (ac && !(stripable[n]->is_master())) {
-                                       if (ac->get_value()) {
-                                               b->set_color(GreenFull);
-                                       } else {
-                                               b->set_color(GreenLow);
-                                       }
-                               } else {
-                                       b->set_color(Off);
-                               }
-                               break;
-                       case TrackRecord:
-                               if (ac) {
-                                       if (ac->get_value()) {
-                                               b->set_color(RedFull);
-                                       } else {
-                                               b->set_color(RedLow);
-                                       }
+                                       b->set_color(b->color_enabled());
                                } else {
-                                       b->set_color(Off);
+                               b->set_color(b->color_disabled());
                                }
-                               break;
-
-                       default:
-                       break;
-               }
+                       } else {
+                               b->set_color(Off);
+                       }
        } else {
                b->set_color(Off);
        }
@@ -481,7 +674,8 @@ LaunchControlXL::solo_mute_rec_changed(uint32_t n) {
        if (!stripable[n]) {
                return;
        }
-       update_track_control_led(n);
+       switch_bank(bank_start);
+       //update_track_control_led(n);
 }
 
 void
@@ -497,6 +691,8 @@ LaunchControlXL::solo_iso_changed(uint32_t n)
 void
 LaunchControlXL::solo_iso_led_bank ()
 {
+       if (device_mode()) { return; }
+
        int stripable_counter = get_amount_of_tracks();
 
        if (!(buttons_down.find(Device) != buttons_down.end())) {
@@ -510,7 +706,9 @@ LaunchControlXL::solo_iso_led_bank ()
                                } else {
                                        b->set_color(Off);
                                }
-                               write (b->state_msg());
+                               if (b) {
+                                       write (b->state_msg());
+                               }
                        }
                }
                LaunchControlXL::set_refresh_leds_flag(true);
@@ -526,12 +724,13 @@ LaunchControlXL::master_send_changed(uint32_t n)
        } else {
                master_send_led_bank();
        }
-
 }
 
 void
 LaunchControlXL::master_send_led_bank ()
 {
+       if (device_mode()) { return; }
+
        if (!(buttons_down.find(Device) != buttons_down.end())) {
                return;
        } else {
@@ -546,7 +745,9 @@ LaunchControlXL::master_send_led_bank ()
                                        b->set_color(Off);
                                }
                        }
-                       write (b->state_msg());
+                       if (b) {
+                               write (b->state_msg());
+                       }
                }
                LaunchControlXL::set_refresh_leds_flag(true);
        }
@@ -600,7 +801,7 @@ LaunchControlXL::knob_sendA(uint8_t n)
        if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
                ac = stripable[n]->trim_control();
        } else {
-               ac = stripable[n]->send_level_controllable (0);
+               ac = stripable[n]->send_level_controllable (send_bank_base());
        }
 
        if (ac && check_pick_up(knob, ac)) {
@@ -635,7 +836,7 @@ LaunchControlXL::knob_sendB(uint8_t n)
                /* something */
        #endif
        } else {
-               ac = stripable[n]->send_level_controllable (1);
+               ac = stripable[n]->send_level_controllable (send_bank_base() + 1);
        }
 
        if (ac && check_pick_up(knob, ac)) {
@@ -664,15 +865,16 @@ LaunchControlXL::knob_pan(uint8_t n)
        boost::shared_ptr<AutomationControl> ac;
 
        if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
-       #ifdef MIXBUS
+#ifdef MIXBUS
                ac = stripable[n]->comp_threshold_controllable();
-       #else
+#else
                ac = stripable[n]->pan_width_control();
-       #endif
+#endif
        } else {
                ac = stripable[n]->pan_azimuth_control();
        }
 
+
        if (ac && check_pick_up(knob, ac)) {
                ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
        }
@@ -702,7 +904,7 @@ LaunchControlXL::button_track_focus(uint8_t n)
 }
 
 void
-LaunchControlXL::button_track_control(uint8_t n) {
+LaunchControlXL::button_press_track_control(uint8_t n) {
        if (!stripable[n]) {
                return;
        }
@@ -742,9 +944,11 @@ LaunchControlXL::button_track_mode(TrackMode state)
                boost::shared_ptr<TrackStateButton> solo = boost::dynamic_pointer_cast<TrackStateButton> (id_note_button_map[Solo]);
                boost::shared_ptr<TrackStateButton> record = boost::dynamic_pointer_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)));
+               if (mute && solo && record) {
+                       write(mute->state_msg((state == TrackMute)));
+                       write(solo->state_msg((state == TrackSolo)));
+                       write(record->state_msg((state == TrackRecord)));
+               }
 }
 
 void
@@ -760,26 +964,29 @@ LaunchControlXL::button_select_right()
 }
 
 void
-LaunchControlXL::button_select_up()
-{
-
-}
-
-void
-LaunchControlXL::button_select_down()
-{
-
+LaunchControlXL::send_bank_switch(bool down) {
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("send_bank_switch - down: %1\n", down));
+       if (down) {
+               set_send_bank(+2);
+       } else {
+               set_send_bank(-2);
+       }
 }
 
 void
 LaunchControlXL::button_device()
 {
-
+#ifndef MIXBUS
+       return; // currently device mode only on Mixbus
+#endif
+       LaunchControlXL::set_device_mode(!device_mode());
 }
 
 void
 LaunchControlXL::button_device_long_press()
 {
+       if (device_mode()) { return ; }
+
        solo_iso_led_bank();
 #ifdef MIXBUS
        master_send_led_bank();
@@ -796,6 +1003,12 @@ LaunchControlXL::button_mute()
        }
 }
 
+void
+LaunchControlXL::button_mute_long_press()
+{
+       session->cancel_all_mute();
+}
+
 void
 LaunchControlXL::button_solo()
 {
@@ -806,6 +1019,12 @@ LaunchControlXL::button_solo()
        }
 }
 
+void
+LaunchControlXL::button_solo_long_press()
+{
+       cancel_all_solo();
+}
+
 void
 LaunchControlXL::button_record()
 {
@@ -821,7 +1040,7 @@ LaunchControlXL::button_long_press_timeout (ButtonID id, boost::shared_ptr<Butto
 {
        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) ();
+               (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 */
@@ -839,7 +1058,666 @@ LaunchControlXL::button_long_press_timeout (ButtonID id, boost::shared_ptr<Butto
 void
 LaunchControlXL::start_press_timeout (boost::shared_ptr<Button> button, ButtonID id)
 {
+       ButtonID no_timeout_buttons[] = { SelectUp, SelectDown, SelectLeft, SelectRight };
+
+       for (size_t n = 0; n < sizeof (no_timeout_buttons) / sizeof (no_timeout_buttons[0]); ++n) {
+               if (id == no_timeout_buttons[n]) {
+                       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("Not using timeout for button id %1\n", id));
+                       return;
+               }
+       }
+
        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());
 }
+
+
+/* Device Mode functions */
+
+void
+LaunchControlXL::dm_select_prev_strip()
+{
+       access_action ("Editor/select-prev-stripable");
+}
+
+void
+LaunchControlXL::dm_select_next_strip()
+{
+       access_action ("Editor/select-next-stripable");
+}
+
+uint8_t
+LaunchControlXL::dm_check_dummy (DeviceStatus ds)
+{
+       return ds;
+}
+
+void
+LaunchControlXL::dm_fader (FaderID id) {
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Fader> fader;
+
+       IDFaderMap::iterator f = id_fader_map.find(id);
+
+       if (f != id_fader_map.end()) {
+               fader = f->second;
+       }
+
+       ac = first_selected_stripable()->gain_control();
+       if (ac && check_pick_up(fader, ac)) {
+               ac->set_value ( ac->interface_to_internal( fader->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_check_pan_azi()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->pan_azimuth_control()) {
+                       dev_status = dev_active;
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_pan_azi (KnobID k)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+
+       ac = first_selected_stripable()->pan_azimuth_control();
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+
+uint8_t
+LaunchControlXL::dm_check_pan_width()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->pan_width_control()) {
+                       dev_status = dev_active;
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_pan_width (KnobID k)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_pan_width()\n");
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+
+       ac = first_selected_stripable()->pan_width_control();
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_check_trim()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->trim_control()) {
+                       dev_status = dev_active;
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_trim (KnobID k)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+
+       ac = first_selected_stripable()->trim_control();
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_mute_enabled()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->mute_control()->get_value()) {
+               dev_status = dev_active;
+       } else {
+               dev_status = dev_inactive;
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_mute_switch()
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->mute_control()) {
+               first_selected_stripable()->mute_control()->set_value(!first_selected_stripable()->mute_control()->get_value(), PBD::Controllable::NoGroup);
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_solo_enabled()
+{
+       if (!first_selected_stripable() || first_selected_stripable()->is_master()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->solo_control()) {
+               if (first_selected_stripable()->solo_control()->get_value()) {
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_solo_switch()
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->solo_control()) {
+               first_selected_stripable()->solo_control()->set_value(!first_selected_stripable()->solo_control()->get_value(), PBD::Controllable::NoGroup);
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_recenable_enabled()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->rec_enable_control()) {
+               if (first_selected_stripable()->rec_enable_control()->get_value()) {
+                       dev_status = dev_active;
+               }  else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_recenable_switch()
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->rec_enable_control()) {
+               first_selected_stripable()->rec_enable_control()->set_value(!first_selected_stripable()->rec_enable_control()->get_value(), PBD::Controllable::NoGroup);
+       }
+}
+
+
+#ifdef MIXBUS
+uint8_t
+LaunchControlXL::dm_mb_eq_freq_enabled()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->eq_enable_controllable()) {
+               if (first_selected_stripable()->eq_enable_controllable()->get_value()) {
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       if (first_selected_stripable()->mixbus() || first_selected_stripable()->is_master()) {
+               dev_status = dev_nonexistant;
+       }
+
+       return dev_status;
+}
+
+
+uint8_t
+LaunchControlXL::dm_mb_eq_gain_enabled(uint8_t band)
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->eq_enable_controllable()) {
+               if (first_selected_stripable()->eq_enable_controllable()->get_value()) {
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       if (first_selected_stripable()->mixbus() && band > 3) {
+               dev_status = dev_nonexistant;
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_mb_eq (KnobID k, bool gain, uint8_t band)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+       if (gain) {
+               ac = first_selected_stripable()->eq_gain_controllable(band);
+       } else {
+               ac = first_selected_stripable()->eq_freq_controllable(band);
+       }
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+void
+LaunchControlXL::dm_mb_eq_shape_switch (uint8_t band)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->eq_shape_controllable(band)) {
+       first_selected_stripable()->eq_shape_controllable(band)->set_value
+                       (!first_selected_stripable()->eq_shape_controllable(band)->get_value(), PBD::Controllable::NoGroup );
+       }
+}
+
+
+uint8_t
+LaunchControlXL::dm_mb_eq_shape_enabled(uint8_t band)
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->eq_shape_controllable(band)) {
+               if (first_selected_stripable()->eq_shape_controllable(band)->get_value()) {
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       return dev_status;
+}
+
+
+void
+LaunchControlXL::dm_mb_eq_switch()
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->eq_enable_controllable()) {
+               first_selected_stripable()->eq_enable_controllable()->set_value
+                       (!first_selected_stripable()->eq_enable_controllable()->get_value(), PBD::Controllable::NoGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_mb_flt_enabled()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_flt_enabled()\n");
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->filter_enable_controllable(true)) {
+               DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_flt_enabled() - filter exists\n");
+               if (first_selected_stripable()->filter_enable_controllable(true)->get_value()) {
+                       DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_flt_enabled: get_value true\n");
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_flt_enabled: dev_status: %1\n", (int)dev_status));
+       return dev_status;
+}
+
+
+void
+LaunchControlXL::dm_mb_flt_switch()
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->filter_enable_controllable(true)) {
+               first_selected_stripable()->filter_enable_controllable(true)->set_value
+                       (!first_selected_stripable()->filter_enable_controllable(true)->get_value(), PBD::Controllable::NoGroup );
+       }
+}
+
+
+
+void
+LaunchControlXL::dm_mb_flt_frq (KnobID k, bool hpf)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+       if (hpf) {
+               ac = first_selected_stripable()->filter_freq_controllable(true);
+       } else {
+               ac = first_selected_stripable()->filter_freq_controllable(false);
+       }
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_mb_check_send_knob (KnobID k)
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t send = static_cast<uint8_t> (k) - 16 + 4 * send_bank_base();
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->send_enable_controllable(send)) {
+               dev_status = dev_inactive;
+               if (first_selected_stripable()->send_enable_controllable(send)->get_value()) {
+                       dev_status = dev_active;
+               }
+       }
+
+       return dev_status;
+}
+
+uint8_t
+LaunchControlXL::dm_mb_check_send_button (uint8_t s)
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+
+       uint8_t send = s + 4 * send_bank_base();
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->send_enable_controllable(send)) {
+               dev_status = dev_inactive;
+               if (first_selected_stripable()->send_enable_controllable(send)->get_value()) {
+                       dev_status = dev_active;
+               }
+       }
+
+       return dev_status;
+}
+
+
+
+void
+LaunchControlXL::dm_mb_sends (KnobID k)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+
+       uint8_t send = static_cast<uint8_t> (k) - 16 + 4 * send_bank_base();
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: knobid '%1'\n", k));
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: send '%1'\n", (int)send));
+
+
+       if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
+               ac = first_selected_stripable()->send_pan_azi_controllable(send);
+       } else {
+               ac = first_selected_stripable()->send_level_controllable(send);
+       }
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_mb_comp_enabled()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+       if (first_selected_stripable()->comp_enable_controllable()) {
+               if (first_selected_stripable()->comp_enable_controllable()->get_value()) {
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_mb_comp_switch()
+{
+       DEBUG_TRACE (DEBUG::LaunchControlXL, "dm_mb_comp_siwtch() \n");
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->comp_enable_controllable()) {
+               DEBUG_TRACE (DEBUG::LaunchControlXL, "comp_enable_controllable exists\n");
+               DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("comp_enable_controllable(): '%1'\n", first_selected_stripable()->comp_enable_controllable()->get_value() ));
+               first_selected_stripable()->comp_enable_controllable()->set_value
+                       (!first_selected_stripable()->comp_enable_controllable()->get_value(), PBD::Controllable::NoGroup);
+       }
+
+}
+
+void
+LaunchControlXL::dm_mb_comp (KnobID k, CompParam c)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+
+       switch (c) {
+               case (CompMakeup):
+                       ac = first_selected_stripable()->comp_makeup_controllable();
+                       break;
+               case (CompMode):
+                       ac = first_selected_stripable()->comp_mode_controllable();
+                       break;
+               case (CompSpeed):
+                       ac = first_selected_stripable()->comp_speed_controllable();
+                       break;
+       }
+
+               if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+void
+LaunchControlXL::dm_mb_comp_thresh (FaderID id) {
+
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Fader> fader;
+
+       IDFaderMap::iterator f = id_fader_map.find(id);
+
+       if (f != id_fader_map.end()) {
+               fader = f->second;
+       }
+
+       ac = first_selected_stripable()->comp_threshold_controllable();
+       if (ac && check_pick_up(fader, ac)) {
+               ac->set_value ( ac->interface_to_internal( fader->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_mb_has_tapedrive()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->mixbus() || first_selected_stripable()->is_master()) {
+               dev_status = dev_active;
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_mb_tapedrive (KnobID k)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> ac;
+       boost::shared_ptr<Knob> knob = knob_by_id (k);
+
+       ac = first_selected_stripable()->tape_drive_controllable();
+
+       if (ac && check_pick_up(knob, ac)) {
+               ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
+       }
+}
+
+uint8_t
+LaunchControlXL::dm_mb_master_assign_enabled()
+{
+       if (!first_selected_stripable()) {
+               return dev_nonexistant;
+       }
+
+       uint8_t dev_status = dev_nonexistant;
+
+       if (first_selected_stripable()->master_send_enable_controllable()) {
+               if (first_selected_stripable()->master_send_enable_controllable()->get_value()) {
+                       dev_status = dev_active;
+               } else {
+                       dev_status = dev_inactive;
+               }
+       }
+
+       return dev_status;
+}
+
+void
+LaunchControlXL::dm_mb_master_assign_switch()
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       if (first_selected_stripable()->master_send_enable_controllable()) {
+               first_selected_stripable()->master_send_enable_controllable()->set_value
+                       (!first_selected_stripable()->master_send_enable_controllable()->get_value(), PBD::Controllable::NoGroup );
+       }
+}
+
+void
+LaunchControlXL::dm_mb_send_switch(ButtonID id)
+{
+       if (!first_selected_stripable()) {
+               return;
+       }
+
+       boost::shared_ptr<Button> button = id_note_button_map[id];;
+
+       uint8_t send = static_cast<uint8_t> (id) + 4 * send_bank_base();
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: buttonid '%1'\n", (int)id));
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: send '%1'\n", (int)send));
+
+       if (first_selected_stripable()->send_enable_controllable(send)) {
+               DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("dm_mb_send: send '%1' exists\n", (int)send));
+               first_selected_stripable()->send_enable_controllable(send)->set_value
+                       (!first_selected_stripable()->send_enable_controllable(send)->get_value(), PBD::Controllable::UseGroup);
+       }
+}
+
+#endif