LCXL: Add some Mixbus functionality
[ardour.git] / libs / surfaces / launch_control_xl / launch_control_xl.cc
index 699e7a84b58796c711de1c960982b2c9877a14a4..f92d6125aae9a99ee3fe8dfb5937252cbfa2e1de 100644 (file)
@@ -29,9 +29,6 @@
 
 #include "midi++/parser.h"
 
-#include "temporal/time.h"
-#include "temporal/bbt_time.h"
-
 #include "ardour/amp.h"
 #include "ardour/async_midi_port.h"
 #include "ardour/audioengine.h"
@@ -84,9 +81,6 @@ LaunchControlXL::LaunchControlXL (ARDOUR::Session& s)
 
        /* master cannot be removed, so no need to connect to going-away signal */
        master = session->master_out ();
-       /* the master bus will always be on the last channel on the lcxl */
-       stripable[7] = master;
-
 
        run_event_loop ();
 
@@ -123,6 +117,7 @@ LaunchControlXL::~LaunchControlXL ()
        ports_release ();
 
        stop_event_loop ();
+       tear_down_gui ();
 }
 
 
@@ -153,6 +148,9 @@ LaunchControlXL::begin_using_device ()
 
        in_use = true;
 
+       DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose("use_fader8master inital value  '%1'\n", use_fader8master));
+       set_fader8master(use_fader8master);
+
        return 0;
 }
 
@@ -444,6 +442,13 @@ LaunchControlXL::handle_button_message(Button* button, MIDI::EventTwoBytes* ev)
   }
 }
 
+bool
+LaunchControlXL::check_pick_up(Controller* controller, boost::shared_ptr<AutomationControl> ac)
+{
+       /* returns false until the controller value matches with the current setting of the stripable's ac */
+       return ( abs( controller->value() / 127.0 -  ac->internal_to_interface(ac->get_value()) ) < 0.007875 );
+}
+
 void
 LaunchControlXL::handle_knob_message (Knob* knob)
 {
@@ -454,15 +459,35 @@ LaunchControlXL::handle_knob_message (Knob* knob)
 
        boost::shared_ptr<AutomationControl> ac;
 
-       if (knob->id() < 8) { // sendA
-               ac = stripable[chan]->trim_control();
-       } else if (knob->id() >= 8 && knob->id() < 16) { // sendB
-               ac = stripable[chan]->pan_width_control();
-       } else if (knob->id() >= 16 && knob->id() < 24) { // pan
-               ac = stripable[chan]->pan_azimuth_control();
+       if (knob->id() < 8) { // sendA knob
+               if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
+                       ac = stripable[chan]->trim_control();
+               } else {
+                       ac = stripable[chan]->send_level_controllable (0);
+               }
+       } else if (knob->id() >= 8 && knob->id() < 16) { // sendB knob
+               if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
+#ifdef MIXBUS
+                       ac = stripable[chan]->filter_freq_controllable (true);
+#else
+                       /* something */
+#endif
+               } else {
+                       ac = stripable[chan]->send_level_controllable (1);
+               }
+       } else if (knob->id() >= 16 && knob->id() < 24) { // pan knob
+               if (buttons_down.find(Device) != buttons_down.end()) { // Device button hold
+#ifdef MIXBUS
+                       ac = stripable[chan]->comp_threshold_controllable();
+#else
+                       ac = stripable[chan]->pan_width_control();
+#endif
+               } else {
+                       ac = stripable[chan]->pan_azimuth_control();
+               }
        }
 
-       if (ac) {
+       if (ac && check_pick_up(knob, ac)) {
                ac->set_value ( ac->interface_to_internal( knob->value() / 127.0), PBD::Controllable::UseGroup );
        }
 }
@@ -476,7 +501,7 @@ LaunchControlXL::handle_fader_message (Fader* fader)
        }
 
        boost::shared_ptr<AutomationControl> ac = stripable[fader->id()]->gain_control();
-       if (ac) {
+       if (ac && check_pick_up(fader, ac)) {
                ac->set_value ( ac->interface_to_internal( fader->value() / 127.0), PBD::Controllable::UseGroup );
        }
 }
@@ -630,6 +655,10 @@ LaunchControlXL::get_state()
        child->add_child_nocopy (_async_out->get_state());
        node.add_child_nocopy (*child);
 
+       child = new XMLNode (X_("Configuration"));
+       child->set_property ("fader8master", LaunchControlXL::use_fader8master);
+       node.add_child_nocopy (*child);
+
        return node;
 }
 
@@ -660,6 +689,11 @@ LaunchControlXL::set_state (const XMLNode & node, int version)
                }
        }
 
+       if ((child = node.child (X_("Configuration"))) !=0) {
+               /* this should propably become a for-loop at some point */
+               child->get_property ("fader8master", use_fader8master);
+       }
+
        return retval;
 }
 
@@ -795,10 +829,10 @@ LaunchControlXL::stripable_property_change (PropertyChange const& what_changed,
                        return;
                }
                if (which < 8) {
-                       button_track_focus( (uint8_t)which );
+                       update_track_focus_led ((uint8_t) which);
+                       update_knob_led((uint8_t) which);
                }
        }
-
 }
 
 void
@@ -814,36 +848,38 @@ LaunchControlXL::switch_bank (uint32_t base)
        SelectButton* sl = static_cast<SelectButton*>(id_controller_button_map[SelectLeft]);
        SelectButton* sr = static_cast<SelectButton*>(id_controller_button_map[SelectRight]);
 
-       if (sl && sr) {
-               write(sl->state_msg( (base) ));
-               write(sr->state_msg( !(base) ));
-       }
-
-
-
-       stripable_connections.drop_connections ();
-
        /* work backwards so we can tell if we should actually switch banks */
 
        boost::shared_ptr<Stripable> s[8];
        uint32_t different = 0;
+       int stripable_counter;
 
-       for (int n = 0; n < 7; ++n) {
+       if (LaunchControlXL::use_fader8master) {
+               stripable_counter = 7;
+       } else {
+               stripable_counter = 8;
+       }
+
+       for (int n = 0; n < stripable_counter; ++n) {
                s[n] = session->get_remote_nth_stripable (base+n, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
                if (s[n] != stripable[n]) {
                        different++;
                }
        }
 
+       if (sl && sr) {
+               write(sl->state_msg((base)));
+               write(sr->state_msg((s[1] != 0)));
+       }
+
        if (!s[0]) {
                /* not even the first stripable exists, do nothing */
-               for (int n = 0; n < 7; ++n) {
-                       stripable[n].reset ();
-               }
                return;
        }
 
-       for (int n = 0; n < 7; ++n) {
+       stripable_connections.drop_connections ();
+
+       for (int n = 0; n < stripable_counter; ++n) {
                stripable[n] = s[n];
        }
 
@@ -863,11 +899,10 @@ LaunchControlXL::switch_bank (uint32_t base)
                        if (stripable[n]->rec_enable_control()) {
                                stripable[n]->rec_enable_control()->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&LaunchControlXL::rec_changed, this, n), lcxl);
                        }
-
-
-                       button_track_focus(n);
-                       button_track_mode(track_mode());
                }
+               update_track_focus_led(n);
+               button_track_mode(track_mode());
+               update_knob_led(n);
        }
 }
 
@@ -898,3 +933,12 @@ void LaunchControlXL::set_track_mode (TrackMode mode) {
                break;
        }
 }
+
+void
+LaunchControlXL::set_fader8master (bool yn)
+{
+       if (yn) {
+               stripable[7] = master;
+       }
+       switch_bank(bank_start);
+}