Mackie Control, Fix sends after monitor not showing.
[ardour.git] / libs / surfaces / mackie / strip.cc
index 13211f3e9570b37215704b18768c8bd65ff67efa..fcb544a92ebd50a352a1198a28f5b8b868f84362 100644 (file)
@@ -18,8 +18,9 @@
 */
 
 #include <sstream>
+#include <vector>
+
 #include <stdint.h>
-#include "strip.h"
 
 #include <sys/time.h>
 
@@ -51,6 +52,7 @@
 #include "mackie_control_protocol.h"
 #include "surface_port.h"
 #include "surface.h"
+#include "strip.h"
 #include "button.h"
 #include "led.h"
 #include "pot.h"
@@ -301,6 +303,10 @@ Strip::notify_all()
                zero ();
                return;
        }
+       // The active V-pot control may not be active for this strip
+       // But if we zero it in the controls function it may erase
+       // the one we do want
+       _surface->write (_vpot->zero());
 
        notify_solo_changed ();
        notify_mute_changed ();
@@ -398,7 +404,6 @@ Strip::notify_trim_changed (bool force_update)
        if (_route) {
 
                if (!_route->trim() || !route()->trim()->active()) {
-                       _surface->write (_vpot->zero());
                        return;
                }
                Control* control = 0;
@@ -435,7 +440,6 @@ Strip::notify_phase_changed (bool force_update)
 {
        if (_route) {
                if (!_route->phase_invert().size()) {
-                       _surface->write (_vpot->zero());
                        return;
                }
 
@@ -468,7 +472,6 @@ Strip::notify_processor_changed (bool force_update)
        if (_route) {
                boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
                if (!p) {
-                       _surface->write (_vpot->zero());
                        return;
                }
 
@@ -520,11 +523,16 @@ Strip::show_route_name ()
                return;
        }
 
+       string fullname = string();
        if (!_route) {
-               return;
+               // make sure first three strips get cleared of view mode
+               if (_index > 2) {
+                       return;
+               }
+       } else {
+               fullname = _route->name();
        }
        string line1;
-       string fullname = _route->name();
 
        if (fullname.length() <= 6) {
                line1 = fullname;
@@ -545,7 +553,7 @@ Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
                return;
        }
 
-       if (_surface->mcp().subview_mode() == MackieControlProtocol::None) {
+       if (_surface->mcp().subview_mode() != MackieControlProtocol::EQ) {
                /* no longer in EQ subview mode */
                return;
        }
@@ -583,6 +591,60 @@ Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
        }
 }
 
+void
+Strip::notify_dyn_change (AutomationType type, bool force_update, bool propagate_mode)
+{
+       boost::shared_ptr<Route> r = _surface->mcp().subview_route();
+
+       if (!r) {
+               /* not in subview mode */
+               return;
+       }
+
+       if (_surface->mcp().subview_mode() != MackieControlProtocol::Dynamics) {
+               /* no longer in EQ subview mode */
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> control;
+       bool reset_all = false;
+
+       switch (type) {
+       case CompThreshold:
+               control = r->comp_threshold_controllable ();
+               break;
+       case CompSpeed:
+               control = r->comp_speed_controllable ();
+               break;
+       case CompMode:
+               control = r->comp_mode_controllable ();
+               reset_all = true;
+               break;
+       case CompMakeup:
+               control = r->comp_makeup_controllable ();
+               break;
+       case CompRedux:
+               control = r->comp_redux_controllable ();
+               break;
+       case CompEnable:
+               control = r->comp_enable_controllable ();
+               break;
+       default:
+               break;
+       }
+
+       if (propagate_mode && reset_all) {
+               _surface->subview_mode_changed ();
+       }
+
+       if (control) {
+               float val = control->get_value();
+               queue_parameter_display (type, val);
+               /* update pot/encoder */
+               _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
+       }
+}
+
 void
 Strip::notify_panner_azi_changed (bool force_update)
 {
@@ -595,7 +657,6 @@ Strip::notify_panner_azi_changed (bool force_update)
        boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
 
        if (!pan_control) {
-               _surface->write (_vpot->zero());
                return;
        }
 
@@ -641,7 +702,6 @@ Strip::notify_panner_width_changed (bool force_update)
        boost::shared_ptr<AutomationControl> pan_control = _route->pan_width_control ();
 
        if (!pan_control) {
-               _surface->write (_vpot->zero());
                return;
        }
 
@@ -696,7 +756,7 @@ Strip::select_event (Button&, ButtonState bs)
                        /* reset to default */
                        boost::shared_ptr<AutomationControl> ac = _fader->control ();
                        if (ac) {
-                               ac->set_value (ac->normal());
+                               ac->set_value (ac->normal(), Controllable::NoGroup);
                        }
                        return;
                }
@@ -714,6 +774,28 @@ Strip::select_event (Button&, ButtonState bs)
 void
 Strip::vselect_event (Button&, ButtonState bs)
 {
+       if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+
+               /* subview mode: vpot press acts like a button for toggle parameters */
+
+               if (bs != press) {
+                       return;
+               }
+
+               boost::shared_ptr<AutomationControl> control = _vpot->control ();
+               if (!control) {
+                       return;
+               }
+
+               if (control->toggled()) {
+                       if (control->toggled()) {
+                               control->set_value (!control->get_value(), Controllable::NoGroup);
+                       }
+               }
+
+               return;
+       }
+
        if (bs == press) {
 
                int ms = _surface->mcp().main_modifier_state();
@@ -725,7 +807,7 @@ Strip::vselect_event (Button&, ButtonState bs)
                        if (ac) {
 
                                /* reset to default/normal value */
-                               ac->set_value (ac->normal());
+                               ac->set_value (ac->normal(), Controllable::NoGroup);
                        }
 
                }  else {
@@ -748,7 +830,7 @@ Strip::fader_touch_event (Button&, ButtonState bs)
 
                if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
                        if (ac) {
-                               ac->set_value (ac->normal());
+                               ac->set_value (ac->normal(), Controllable::NoGroup);
                        }
                } else {
 
@@ -825,7 +907,7 @@ Strip::handle_button (Button& button, ButtonState bs)
                                /* apply change */
 
                                for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
-                                       (*c)->set_value (new_value);
+                                       (*c)->set_value (new_value, Controllable::NoGroup);
                                }
 
                        } else {
@@ -926,17 +1008,27 @@ Strip::do_parameter_display (AutomationType type, float val)
        case EQQ:
        case EQShape:
        case EQHPF:
+       case CompThreshold:
+       case CompSpeed:
+       case CompMakeup:
+       case CompRedux:
                snprintf (buf, sizeof (buf), "%6.1f", val);
                _surface->write (display (1, buf));
                screen_hold = true;
                break;
        case EQEnable:
+       case CompEnable:
                if (val >= 0.5) {
                        _surface->write (display (1, "on"));
                } else {
                        _surface->write (display (1, "off"));
                }
                break;
+       case CompMode:
+               if (_surface->mcp().subview_route()) {
+                       _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
+               }
+               break;
        default:
                break;
        }
@@ -1004,9 +1096,16 @@ Strip::periodic (ARDOUR::microseconds_t now)
 {
        bool reshow_vpot_mode = false;
        bool reshow_name = false;
+       bool good_strip = true;
 
        if (!_route) {
-               return;
+               // view mode may cover as many as 3 strips
+               // needs to be cleared when there are less than 3 routes
+               if (_index > 2) {
+                       return;
+               } else {
+                       good_strip = false;
+               }
        }
 
        if (_block_screen_redisplay_until >= now) {
@@ -1021,7 +1120,7 @@ Strip::periodic (ARDOUR::microseconds_t now)
                /* timeout reached, reset */
 
                _block_screen_redisplay_until = 0;
-               reshow_vpot_mode = true;
+               reshow_vpot_mode = (true && good_strip);
                reshow_name = true;
        }
 
@@ -1032,7 +1131,7 @@ Strip::periodic (ARDOUR::microseconds_t now)
                /* timeout reached, reset */
 
                _block_vpot_mode_redisplay_until = 0;
-               reshow_vpot_mode = true;
+               reshow_vpot_mode = (true && good_strip);
        }
 
        if (reshow_name) {
@@ -1041,14 +1140,16 @@ Strip::periodic (ARDOUR::microseconds_t now)
 
        if (reshow_vpot_mode) {
                return_to_vpot_mode_display ();
-       } else {
+       } else if (good_strip) {
                /* no point doing this if we just switched back to vpot mode
                   display */
                update_automation ();
        }
 
   meters:
-       update_meter ();
+       if (good_strip) {
+               update_meter ();
+       }
 }
 
 void
@@ -1322,13 +1423,16 @@ Strip::next_pot_mode ()
        if (!ac) {
                return;
        }
+
+
        if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
-               if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
+
+               if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
                        return;
                }
 
                for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
-                       if ((*i) == ac->parameter()) {
+                       if ((*i) == ac->parameter().type()) {
                                break;
                        }
                }
@@ -1344,14 +1448,15 @@ Strip::next_pot_mode ()
                if (i == possible_pot_parameters.end()) {
                        i = possible_pot_parameters.begin();
                }
+
                set_vpot_parameter (*i);
        } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
-                               if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter())) {
+               if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter().type())) {
                        return;
                }
 
                for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
-                       if ((*i) == ac->parameter()) {
+                       if ((*i) == ac->parameter().type()) {
                                break;
                        }
                }
@@ -1383,8 +1488,16 @@ Strip::next_pot_mode ()
                        return;
                }
                p = _route->nth_send (_current_send + 1);
-               if (p && p->name() != "Monitor 1") {
+               if (p) {
                        _current_send++;
+                       if (p->name() == "Monitor 1") { // skip monitor
+                               p = _route->nth_send (_current_send + 1);
+                               if (p) {
+                                       _current_send++;
+                               } else {
+                                       _current_send = 0;
+                               }
+                       }
                } else {
                        _current_send = 0;
                }
@@ -1407,16 +1520,108 @@ Strip::subview_mode_changed ()
                break;
 
        case MackieControlProtocol::EQ:
-               setup_eq_vpots (r);
+               if (r) {
+                       setup_eq_vpot (r);
+               } else {
+                       /* leave it as it was */
+               }
                break;
 
        case MackieControlProtocol::Dynamics:
+               if (r) {
+                       setup_dyn_vpot (r);
+               } else {
+                       /* leave it as it was */
+               }
+               break;
+       }
+}
+
+void
+Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
+{
+       if (!r) {
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
+       boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
+       boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
+       boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
+       boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
+       boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
+
+       uint32_t pos = _surface->mcp().global_index (*this);
+
+       /* we will control the pos-th available parameter, from the list in the
+        * order shown above.
+        */
+
+       vector<boost::shared_ptr<AutomationControl> > available;
+       vector<AutomationType> params;
+
+       if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
+       if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
+       if (mc) { available.push_back (mc); params.push_back (CompMode); }
+       if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
+       if (rc) { available.push_back (rc); params.push_back (CompRedux); }
+       if (ec) { available.push_back (ec); params.push_back (CompEnable); }
+
+       if (pos >= available.size()) {
+               /* this knob is not needed to control the available parameters */
+               _vpot->set_control (boost::shared_ptr<AutomationControl>());
+               _surface->write (display (0, string()));
+               _surface->write (display (1, string()));
+               return;
+       }
+
+       boost::shared_ptr<AutomationControl> pc;
+       AutomationType param;
+
+       pc = available[pos];
+       param = params[pos];
+
+       pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
+       _vpot->set_control (pc);
+
+       string pot_id;
+
+       switch (param) {
+       case CompThreshold:
+               pot_id = "Thresh";
+               break;
+       case CompSpeed:
+               if (mc) {
+                       pot_id = r->comp_speed_name (mc->get_value());
+               } else {
+                       pot_id = "Speed";
+               }
+               break;
+       case CompMode:
+               pot_id = "Mode";
+               break;
+       case CompMakeup:
+               pot_id = "Makeup";
+               break;
+       case CompRedux:
+               pot_id = "Redux";
+               break;
+       case CompEnable:
+               pot_id = "on/off";
+               break;
+       default:
                break;
        }
+
+       if (!pot_id.empty()) {
+               _surface->write (display (0, pot_id));
+       }
+
+       notify_dyn_change (param, true, false);
 }
 
 void
-Strip::setup_eq_vpots (boost::shared_ptr<Route> r)
+Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
 {
        uint32_t bands = r->eq_band_cnt ();
 
@@ -1581,7 +1786,7 @@ Strip::set_vpot_parameter (AutomationType p)
                                _pan_mode = PanAzimuthAutomation;
                                if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
                                        /* gain to vpot, pan azi to fader */
-                                       _vpot->set_control (_route->group_gain_control());
+                                       _vpot->set_control (_route->gain_control());
                                        vpot_parameter = GainAutomation;
                                        control_by_parameter[GainAutomation] = _vpot;
                                        _fader->set_control (pan_control);
@@ -1593,7 +1798,7 @@ Strip::set_vpot_parameter (AutomationType p)
                        } else {
                                /* gain to fader, pan azi to vpot */
                                vpot_parameter = PanAzimuthAutomation;
-                               _fader->set_control (_route->group_gain_control());
+                               _fader->set_control (_route->gain_control());
                                control_by_parameter[GainAutomation] = _fader;
                                _vpot->set_control (pan_control);
                                control_by_parameter[PanAzimuthAutomation] = _vpot;
@@ -1610,7 +1815,7 @@ Strip::set_vpot_parameter (AutomationType p)
                                _pan_mode = PanWidthAutomation;
                                if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
                                        /* gain to vpot, pan width to fader */
-                                       _vpot->set_control (_route->group_gain_control());
+                                       _vpot->set_control (_route->gain_control());
                                        vpot_parameter = GainAutomation;
                                        control_by_parameter[GainAutomation] = _vpot;
                                        _fader->set_control (pan_control);
@@ -1622,7 +1827,7 @@ Strip::set_vpot_parameter (AutomationType p)
                        } else {
                                /* gain to fader, pan width to vpot */
                                vpot_parameter = PanWidthAutomation;
-                               _fader->set_control (_route->group_gain_control());
+                               _fader->set_control (_route->gain_control());
                                control_by_parameter[GainAutomation] = _fader;
                                _vpot->set_control (pan_control);
                                control_by_parameter[PanWidthAutomation] = _vpot;
@@ -1644,7 +1849,7 @@ Strip::set_vpot_parameter (AutomationType p)
                vpot_parameter = TrimAutomation;
                if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
                        /* gain to vpot, trim to fader */
-                       _vpot->set_control (_route->group_gain_control());
+                       _vpot->set_control (_route->gain_control());
                        control_by_parameter[GainAutomation] = _vpot;
                        if (_route->trim() && route()->trim()->active()) {
                                _fader->set_control (_route->trim_control());
@@ -1655,7 +1860,7 @@ Strip::set_vpot_parameter (AutomationType p)
                        }
                } else {
                        /* gain to fader, trim to vpot */
-                       _fader->set_control (_route->group_gain_control());
+                       _fader->set_control (_route->gain_control());
                        control_by_parameter[GainAutomation] = _fader;
                        if (_route->trim() && route()->trim()->active()) {
                                _vpot->set_control (_route->trim_control());
@@ -1671,7 +1876,7 @@ Strip::set_vpot_parameter (AutomationType p)
                vpot_parameter = PhaseAutomation;
                if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
                        /* gain to vpot, phase to fader */
-                       _vpot->set_control (_route->group_gain_control());
+                       _vpot->set_control (_route->gain_control());
                        control_by_parameter[GainAutomation] = _vpot;
                        if (_route->phase_invert().size()) {
                                _fader->set_control (_route->phase_control());
@@ -1682,7 +1887,7 @@ Strip::set_vpot_parameter (AutomationType p)
                        }
                } else {
                        /* gain to fader, phase to vpot */
-                       _fader->set_control (_route->group_gain_control());
+                       _fader->set_control (_route->gain_control());
                        control_by_parameter[GainAutomation] = _fader;
                        if (_route->phase_invert().size()) {
                                _vpot->set_control (_route->phase_control());
@@ -1697,7 +1902,7 @@ Strip::set_vpot_parameter (AutomationType p)
                if (!Profile->get_mixbus()) {
                        if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
                                // gain to vpot, send to fader
-                               _vpot->set_control (_route->group_gain_control());
+                               _vpot->set_control (_route->gain_control());
                                control_by_parameter[GainAutomation] = _vpot;
                                // test for send to control
                                boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
@@ -1715,20 +1920,7 @@ Strip::set_vpot_parameter (AutomationType p)
                                }
                        } else {
                                // gain to fader, send to vpot
-                               _fader->set_control (_route->group_gain_control());
-                               control_by_parameter[GainAutomation] = _fader;
-                               boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
-                               if (p && p->name() != "Monitor 1") {
-                                       boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
-                                       boost::shared_ptr<Amp> a = s->amp();
-                                       _vpot->set_control (a->gain_control());
-                                       // connect to signal
-                                       send_connections.drop_connections ();
-                                       a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
-                                       control_by_parameter[SendAutomation] = _vpot;
-                       } else {
-                               // gain to fader, send to vpot
-                               _fader->set_control (_route->group_gain_control());
+                               _fader->set_control (_route->gain_control());
                                control_by_parameter[GainAutomation] = _fader;
                                boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
                                if (p && p->name() != "Monitor 1") {
@@ -1740,8 +1932,22 @@ Strip::set_vpot_parameter (AutomationType p)
                                        a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
                                        control_by_parameter[SendAutomation] = _vpot;
                                } else {
-                                       _vpot->set_control (boost::shared_ptr<AutomationControl>());
-                                       control_by_parameter[SendAutomation] = 0;
+                                       // gain to fader, send to vpot
+                                       _fader->set_control (_route->gain_control());
+                                       control_by_parameter[GainAutomation] = _fader;
+                                       boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+                                       if (p && p->name() != "Monitor 1") {
+                                               boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
+                                               boost::shared_ptr<Amp> a = s->amp();
+                                               _vpot->set_control (a->gain_control());
+                                               // connect to signal
+                                               send_connections.drop_connections ();
+                                               a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
+                                               control_by_parameter[SendAutomation] = _vpot;
+                                       } else {
+                                               _vpot->set_control (boost::shared_ptr<AutomationControl>());
+                                               control_by_parameter[SendAutomation] = 0;
+                                       }
                                }
                        }
                }
@@ -1799,8 +2005,3 @@ Strip::notify_metering_state_changed()
        _transport_is_rolling = transport_is_rolling;
        _metering_active = metering_active;
 }
-
-void
-Strip::hookup_eq (AutomationType param, uint32_t band)
-{
-}