MCP: a fistful of improvements. probably best to just try it and see what it broken...
[ardour.git] / libs / surfaces / mackie / strip.cc
index 57693d0e8f829e92d90fc6747b91aa59668044e6..bf3ff0d588fe4dea19269061fe6a8f6e0d6a4416 100644 (file)
@@ -87,9 +87,14 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
        _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
        _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
 
+#ifndef NDEBUG 
        for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
-               (void) Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this);
+               Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
+               DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
+                                                                  _surface->number(), index, Button::id_to_name (bb->bid()), 
+                                                                  bb->id(), b->second.base_id));
        }
+#endif 
 }      
 
 Strip::~Strip ()
@@ -132,7 +137,7 @@ Strip::add (Control & control)
 }
 
 void
-Strip::set_route (boost::shared_ptr<Route> r)
+Strip::set_route (boost::shared_ptr<Route> r, bool with_messages)
 {
        if (_controls_locked) {
                return;
@@ -166,8 +171,8 @@ Strip::set_route (boost::shared_ptr<Route> r)
        boost::shared_ptr<Pannable> pannable = _route->pannable();
 
        if (pannable) {
-               pannable->pan_azimuth_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
-               pannable->pan_width_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
+               pannable->pan_azimuth_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
+               pannable->pan_width_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_width_changed, this, false), ui_context());
        }
        _route->gain_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_gain_changed, this, false), ui_context());
        _route->PropertyChanged.connect (route_connections, invalidator(), ui_bind (&Strip::notify_property_changed, this, _1), ui_context());
@@ -211,44 +216,22 @@ Strip::set_route (boost::shared_ptr<Route> r)
                        }
                }
        }
-
-       current_pot_modes.push_back (Input);
-       current_pot_modes.push_back (Output);
-
-       if (_route->nth_send (0) != 0) {
-               current_pot_modes.push_back (Send1);
-       }
-       if (_route->nth_send (1) != 0) {
-               current_pot_modes.push_back (Send2);
-       }
-       if (_route->nth_send (2) != 0) {
-               current_pot_modes.push_back (Send3);
-       }
-       if (_route->nth_send (3) != 0) {
-               current_pot_modes.push_back (Send4);
-       }
-       if (_route->nth_send (4) != 0) {
-               current_pot_modes.push_back (Send5);
-       }
-       if (_route->nth_send (5) != 0) {
-               current_pot_modes.push_back (Send6);
-       }
-       if (_route->nth_send (6) != 0) {
-               current_pot_modes.push_back (Send7);
-       }
-       if (_route->nth_send (7) != 0) {
-               current_pot_modes.push_back (Send8);
-       }
 }
 
 void 
 Strip::notify_all()
 {
+       if (!_route) {
+               zero ();
+               return;
+       }
+
        notify_solo_changed ();
        notify_mute_changed ();
        notify_gain_changed ();
        notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
-       notify_panner_changed ();
+       notify_panner_azi_changed ();
+       notify_panner_width_changed ();
        notify_record_enable_changed ();
 }
 
@@ -295,8 +278,6 @@ Strip::notify_route_deleted ()
 void 
 Strip::notify_gain_changed (bool force_update)
 {
-       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("gain changed for strip %1, flip mode %2\n", _index, _surface->mcp().flip_mode()));
-
        if (_route) {
                
                Control* control;
@@ -307,31 +288,29 @@ Strip::notify_gain_changed (bool force_update)
                        control = _fader;
                }
 
-               if (!control->in_use()) {
-
-                       float pos = _route->gain_control()->internal_to_interface (_route->gain_control()->get_value());
 
-                       if (force_update || pos != _last_gain_position_written) {
-
-                               if (_surface->mcp().flip_mode()) {
-                                       _surface->write (_vpot->set_all (pos, true, Pot::wrap));
-                                       do_parameter_display (GainAutomation, pos);
-                               } else {
-                                       _surface->write (_fader->set_position (pos));
-                                       do_parameter_display (GainAutomation, pos);
+               boost::shared_ptr<AutomationControl> ac = _route->gain_control();
+               
+               float gain_coefficient = ac->get_value();
+               float normalized_position = ac->internal_to_interface (gain_coefficient);
+               
+               if (force_update || normalized_position != _last_gain_position_written) {
+                       
+                       if (_surface->mcp().flip_mode()) {
+                               if (!control->in_use()) {
+                                       _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
                                }
-
-                               queue_display_reset (2000);
-                               _last_gain_position_written = pos;
-                               
+                               do_parameter_display (GainAutomation, gain_coefficient);
                        } else {
-                               DEBUG_TRACE (DEBUG::MackieControl, "value is stale, no message sent\n");
+                               if (!control->in_use()) {
+                                       _surface->write (_fader->set_position (normalized_position));
+                               }
+                               do_parameter_display (GainAutomation, gain_coefficient);
                        }
-               } else {
-                       DEBUG_TRACE (DEBUG::MackieControl, "fader in use, no message sent\n");
+
+                       queue_display_reset (2000);
+                       _last_gain_position_written = normalized_position;
                }
-       } else {
-               DEBUG_TRACE (DEBUG::MackieControl, "no route or no fader\n");
        }
 }
 
@@ -351,13 +330,13 @@ Strip::notify_property_changed (const PropertyChange& what_changed)
                } else {
                        line1 = PBD::short_version (fullname, 6);
                }
-               
+
                _surface->write (display (0, line1));
        }
 }
 
 void 
-Strip::notify_panner_changed (bool force_update)
+Strip::notify_panner_azi_changed (bool force_update)
 {
        if (_route) {
 
@@ -375,6 +354,9 @@ Strip::notify_panner_changed (bool force_update)
                if (_surface->mcp().flip_mode()) {
                        control = _fader;
                } else {
+                       if (_vpot_mode != PanAzimuth) {
+                               return;
+                       }
                        control = _vpot;
                }
 
@@ -389,7 +371,7 @@ Strip::notify_panner_changed (bool force_update)
                                        _surface->write (_fader->set_position (pos));
                                        do_parameter_display (PanAzimuthAutomation, pos);
                                } else {
-                                       _surface->write (_vpot->set_all (pos, true, Pot::dot));
+                                       _surface->write (_vpot->set (pos, true, Pot::dot));
                                        do_parameter_display (PanAzimuthAutomation, pos);
                                }
 
@@ -400,6 +382,53 @@ Strip::notify_panner_changed (bool force_update)
        }
 }
 
+void 
+Strip::notify_panner_width_changed (bool force_update)
+{
+       if (_route) {
+
+               DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
+
+               boost::shared_ptr<Pannable> pannable = _route->pannable();
+
+               if (!pannable) {
+                       _surface->write (_vpot->zero());
+                       return;
+               }
+
+               Control* control;
+
+               if (_surface->mcp().flip_mode()) {
+                       control = _fader;
+               } else {
+                       if (_vpot_mode != PanWidth) {
+                               return;
+                       }
+                       control = _vpot;
+               }
+
+               if (!control->in_use()) {
+                       
+                       double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
+                       
+                       if (force_update || pos != _last_pan_position_written) {
+                               
+                               if (_surface->mcp().flip_mode()) {
+                                       
+                                       _surface->write (_fader->set_position (pos));
+                                       do_parameter_display (PanWidthAutomation, pos);
+                               } else {
+                                       _surface->write (_vpot->set (pos, true, Pot::spread));
+                                       do_parameter_display (PanWidthAutomation, pos);
+                               }
+
+                               queue_display_reset (2000);
+                               _last_pan_position_written = pos;
+                       }
+               }
+       }
+}
+
 void
 Strip::select_event (Button& button, ButtonState bs)
 {
@@ -440,20 +469,23 @@ Strip::vselect_event (Button& button, ButtonState bs)
 {
        if (bs == press) {
 
-               boost::shared_ptr<AutomationControl> ac = button.control ();
 
-               if (ac) {
-                       
-                       int ms = _surface->mcp().modifier_state();
-                       
-                       if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
+               int ms = _surface->mcp().modifier_state();
+                               
+               if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
+                       boost::shared_ptr<AutomationControl> ac = button.control ();
+
+                       if (ac) {
+                               
                                /* reset to default/normal value */
                                ac->set_value (ac->normal());
-
-                       } else {
-                               next_pot_mode ();
                        }
+
+               }  else {
+                       DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
+                       next_pot_mode ();
                }
+
        }
 }
 
@@ -512,7 +544,7 @@ Strip::handle_button (Button& button, ButtonState bs)
        default:
                if ((control = button.control ())) {
                        if (bs == press) {
-                               DEBUG_TRACE (DEBUG::MackieControl, "add button on release\n");
+                               DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
                                _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
                                
                                float new_value;
@@ -554,16 +586,13 @@ Strip::handle_button (Button& button, ButtonState bs)
 void
 Strip::do_parameter_display (AutomationType type, float val)
 {
-       float dB;
-
        switch (type) {
        case GainAutomation:
-               dB = fast_coefficient_to_dB (val);
                if (val == 0.0) {
                        _surface->write (display (1, " -inf "));
                } else {
                        char buf[16];
-                       
+                       float dB = accurate_coefficient_to_dB (val);
                        snprintf (buf, sizeof (buf), "%6.1f", dB);
                        _surface->write (display (1, buf));
                }               
@@ -577,6 +606,16 @@ Strip::do_parameter_display (AutomationType type, float val)
                                _surface->write (display (1, str));
                        }
                }
+               break;
+
+       case PanWidthAutomation:
+               if (_route) {
+                       char buf[16];
+                       snprintf (buf, sizeof (buf), "%5ld%%", lrintf (val * 100.0));
+                       _surface->write (display (1, buf));
+               }
+               break;
+
        default:
                break;
        }
@@ -605,12 +644,11 @@ Strip::handle_pot (Pot& pot, float delta)
           stop moving. So to get a stop event, we need to use a timeout.
        */
        
-       pot.start_touch (_surface->mcp().transport_frame());
-
+       boost::shared_ptr<AutomationControl> ac = pot.control();
        double p = pot.get_value ();
        p += delta;
-       p = min (1.0, p);
-       p = max (0.0, p);
+       p = max (ac->lower(), p);
+       p = min (ac->upper(), p);
        pot.set_value (p);
 }
 
@@ -641,7 +679,8 @@ Strip::update_automation ()
        if (_route->panner()) {
                ARDOUR::AutoState panner_state = _route->panner()->automation_state();
                if (panner_state == Touch || panner_state == Play) {
-                       notify_panner_changed (false);
+                       notify_panner_azi_changed (false);
+                       notify_panner_width_changed (false);
                }
        }
 }
@@ -655,19 +694,15 @@ Strip::update_meter ()
        }
 }
 
-MidiByteArray
+void
 Strip::zero ()
 {
-       MidiByteArray retval;
-
        for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
-               retval << (*it)->zero ();
+               _surface->write ((*it)->zero ());
        }
 
-       retval << blank_display (0);
-       retval << blank_display (1);
-       
-       return retval;
+       _surface->write (blank_display (0));
+       _surface->write (blank_display (1));
 }
 
 MidiByteArray
@@ -708,8 +743,6 @@ Strip::display (uint32_t line_number, const std::string& line)
        // sysex trailer
        retval << MIDI::eox;
        
-       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieMidiBuilder::strip_display midi: %1\n", retval));
-
        return retval;
 }
 
@@ -785,6 +818,14 @@ Strip::flip_mode_changed (bool notify)
                return;
        }
 
+       if (_surface->mcp().flip_mode()) {
+               /* flip mode is on - save what it used to be */
+               _preflip_vpot_mode = _vpot_mode;
+       } else {
+               /* flip mode is off - restore flip mode to what it used to be */
+               _vpot_mode = _preflip_vpot_mode;
+       }
+
        boost::shared_ptr<AutomationControl> fader_controllable = _fader->control ();
        boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control ();
 
@@ -823,7 +864,12 @@ Strip::clear_display_reset ()
 void
 Strip::reset_display ()
 {
-       _surface->write (display (1, vpot_mode_string()));
+       if (_route) {
+               _surface->write (display (1, vpot_mode_string()));
+       } else {
+               _surface->write (blank_display (1));
+       }
+               
        clear_display_reset ();
 }
                         
@@ -911,8 +957,9 @@ Strip::next_pot_mode ()
 
        if (_surface->mcp().flip_mode()) {
                /* do not change vpot mode while in flipped mode */
+               DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
                _surface->write (display (1, "Flip"));
-               queue_display_reset (2000);
+               queue_display_reset (1000);
                return;
        }
 
@@ -943,12 +990,22 @@ Strip::set_vpot_mode (PotMode m)
        boost::shared_ptr<Send> send;
        boost::shared_ptr<Pannable> pannable;
 
+       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", m));
+
        if (!_route) {
                return;
        }
 
        _vpot_mode = m;
 
+       /* one of these is unnecessary, but its not worth trying to find
+          out which - it will just cause one additional message to be
+          sent to the surface.
+       */
+
+       _last_pan_position_written = -1;
+       _last_gain_position_written = -1;
+
        switch (_vpot_mode) {
        case Gain:
                break;
@@ -968,7 +1025,6 @@ Strip::set_vpot_mode (PotMode m)
                                if (pannable) {
                                        _vpot->set_control (pannable->pan_azimuth_control);
                                }
-                               _vpot_mode = PanAzimuth;
                        }
                }
                break;