Add Trim to Mackie controls.
authorLen Ovens <len@ovenwerks.net>
Thu, 8 Oct 2015 04:36:16 +0000 (21:36 -0700)
committerLen Ovens <len@ovenwerks.net>
Thu, 8 Oct 2015 04:36:16 +0000 (21:36 -0700)
libs/ardour/ardour/route.h
libs/ardour/route.cc
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol.h
libs/surfaces/mackie/mcp_buttons.cc
libs/surfaces/mackie/strip.cc
libs/surfaces/mackie/strip.h
libs/surfaces/mackie/surface.cc
libs/surfaces/mackie/surface.h

index 94d8837246ed2601189033e14bb7b76dafb23df2..001accb2e3473b13bfe236f79b20107fdf6f94a0 100644 (file)
@@ -429,6 +429,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        boost::shared_ptr<PannerShell> panner_shell() const;
        boost::shared_ptr<AutomationControl> gain_control() const;
        boost::shared_ptr<Pannable> pannable() const;
+       boost::shared_ptr<AutomationControl> trim_control() const;
 
        /**
           Return the first processor that accepts has at least one MIDI input
index ca01b597c0feed4669993bc3ca1363efba865d52..c3b09df2d36cf25b00857ad8f058d52f0a73c306 100644 (file)
@@ -4236,6 +4236,12 @@ Route::gain_control() const
        return _amp->gain_control();
 }
 
+boost::shared_ptr<AutomationControl>
+Route::trim_control() const
+{
+       return _trim->gain_control();
+}
+
 boost::shared_ptr<AutomationControl>
 Route::get_control (const Evoral::Parameter& param)
 {
index b20cbfa1d92f23ec7c0f318c5b5109b342733137..167a0053a659491b4d0221b72de71e54a5e21e0a 100644 (file)
@@ -107,6 +107,7 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
        , _scrub_mode (false)
        , _flip_mode (Normal)
        , _view_mode (Mixer)
+       , _pot_mode (Pan)
        , _current_selected_track (-1)
        , _modifier_state (0)
        , _ipmidi_base (MIDI::IPMIDIPort::lowest_ipmidi_port_default)
@@ -292,16 +293,8 @@ MackieControlProtocol::get_sorted_routes()
                        break;
                case MidiTracks:
                        break;
-               case Dynamics:
-                       break;
-               case EQ:
-                       break;
                case Loop:
                        break;
-               case Sends:
-                       break;
-               case Plugins:
-                       break;
                }
 
                sorted.push_back (*it);
@@ -1441,6 +1434,20 @@ MackieControlProtocol::set_flip_mode (FlipMode fm)
        }
 }
 
+void
+MackieControlProtocol::set_pot_mode (PotMode m)
+{
+       Glib::Threads::Mutex::Lock lm (surfaces_lock);
+
+       _pot_mode = m;
+
+       for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+               (*s)->update_potmode ();
+
+       }
+
+}
+
 void
 MackieControlProtocol::set_master_on_surface_strip (uint32_t surface, uint32_t strip_number)
 {
index 344a1e9ecb00fb4e93feebaf3ed5872499479e11..70b8f35ad2d2d1ef5338f7f88af16c0a95c42276 100644 (file)
@@ -102,16 +102,21 @@ class MackieControlProtocol
 
        enum ViewMode {
                Mixer,
-               Dynamics,
-               EQ,
                Loop,
                AudioTracks,
                MidiTracks,
                Busses,
-               Sends,
-               Plugins,
        };
 
+       enum PotMode {
+               Tracks,
+               Send,
+               Pan,
+               PlugIn,
+               EQ,
+               Instrument,
+       };
+
        enum FlipMode {
                Normal, /* fader controls primary, vpot controls secondary */
                Mirror, /* fader + vpot control secondary */
@@ -135,11 +140,13 @@ class MackieControlProtocol
 
        FlipMode flip_mode () const { return _flip_mode; }
        ViewMode view_mode () const { return _view_mode; }
+       PotMode pot_mode () const { return _pot_mode; }
        bool zoom_mode () const { return modifier_state() & MODIFIER_ZOOM; }
        bool     metering_active () const { return _metering_active; }
 
        void set_view_mode (ViewMode);
        void set_flip_mode (FlipMode);
+       void set_pot_mode (PotMode);
 
        XMLNode& get_state ();
        int set_state (const XMLNode&, int version);
@@ -302,6 +309,7 @@ class MackieControlProtocol
        bool                     _scrub_mode;
        FlipMode                 _flip_mode;
        ViewMode                 _view_mode;
+       PotMode                  _pot_mode;
        int                      _current_selected_track;
        int                      _modifier_state;
        ButtonMap                 button_map;
index fb6fbd3e5ad4469be945e13dc4b39d1270dcec50..781370a79ebbcf99d1563b757440ff922ed3f4c5 100644 (file)
@@ -659,7 +659,14 @@ MackieControlProtocol::F8_release (Button &)
 LedState
 MackieControlProtocol::pan_press (Button &)
 {
-       return off;
+       set_pot_mode (Pan);
+       update_global_button (Button::Track, off);
+       update_global_button (Button::Send, off);
+       update_global_button (Button::Plugin, off);
+       update_global_button (Button::Eq, off);
+       update_global_button (Button::Dyn, off);
+       return on;
+
 }
 LedState
 MackieControlProtocol::pan_release (Button &)
@@ -830,8 +837,14 @@ MackieControlProtocol::clearsolo_release (Mackie::Button&)
 Mackie::LedState
 MackieControlProtocol::track_press (Mackie::Button&)
 {
+       set_pot_mode (Tracks);
+       update_global_button (Button::Pan, off);
+       update_global_button (Button::Send, off);
+       update_global_button (Button::Plugin, off);
+       update_global_button (Button::Eq, off);
+       update_global_button (Button::Dyn, off);
+       return on;
 
-       return off;
 }
 Mackie::LedState
 MackieControlProtocol::track_release (Mackie::Button&)
@@ -841,13 +854,15 @@ MackieControlProtocol::track_release (Mackie::Button&)
 Mackie::LedState
 MackieControlProtocol::send_press (Mackie::Button&)
 {
-// code moved here from "sends_press"
-       //set_view_mode (Sends);
-       // Led state for vpot assignment should be radio button-ish
-       // Pressing any one should turn the rest off.
-       // but this is not implemented yet so leave off
-       //return on;
        return off;
+       // remove above line when sends implemented
+       set_pot_mode (Send);
+       update_global_button (Button::Track, off);
+       update_global_button (Button::Pan, off);
+       update_global_button (Button::Plugin, off);
+       update_global_button (Button::Eq, off);
+       update_global_button (Button::Dyn, off);
+       return on;
 }
 Mackie::LedState
 MackieControlProtocol::send_release (Mackie::Button&)
index 4528e7b1551be64e655febd509888b53d860741a..3633430e9843bcdd71dff0a0922fdd4f329c67a8 100644 (file)
@@ -93,9 +93,11 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
        , _transport_is_rolling (false)
        , _metering_active (true)
        , _reset_display_at (0)
+       , _pan_mode (PanAzimuthAutomation)
        , _last_gain_position_written (-1.0)
        , _last_pan_azi_position_written (-1.0)
        , _last_pan_width_position_written (-1.0)
+       , _last_trim_position_written (-1.0)
        , redisplay_requests (256)
 {
        _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
@@ -185,13 +187,19 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
        _solo->set_control (_route->solo_control());
        _mute->set_control (_route->mute_control());
 
-       set_vpot_parameter (PanAzimuthAutomation);
+       _pan_mode = PanAzimuthAutomation;
+       potmode_changed (true);
+
 
        _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
        _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
 
        _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
 
+       if (_route->trim()) {
+               _route->trim_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trim_changed, this, false), ui_context());
+       }
+
        boost::shared_ptr<Pannable> pannable = _route->pannable();
 
        if (pannable && _route->panner()) {
@@ -259,6 +267,7 @@ Strip::notify_all()
        notify_panner_azi_changed ();
        notify_panner_width_changed ();
        notify_record_enable_changed ();
+       notify_trim_changed ();
 }
 
 void
@@ -340,6 +349,39 @@ Strip::notify_gain_changed (bool force_update)
        }
 }
 
+void
+Strip::notify_trim_changed (bool force_update)
+{
+       if (_route) {
+
+               if (!_route->trim()) {
+                       _surface->write (_vpot->zero());
+                       return;
+               }
+               Control* control = control_by_parameter[TrimAutomation];
+
+               boost::shared_ptr<AutomationControl> ac = _route->trim_control();
+
+               float gain_coefficient = ac->get_value();
+               float normalized_position = ac->internal_to_interface (gain_coefficient);
+
+               if (force_update || normalized_position != _last_trim_position_written) {
+                       if (control == _fader) {
+                               if (!_fader->in_use()) {
+                                       _surface->write (_fader->set_position (normalized_position));
+                                       queue_parameter_display (TrimAutomation, gain_coefficient);
+                               }
+                       } else if (control == _vpot) {
+                               _surface->write (_vpot->set (normalized_position, true, Pot::dot));
+                               queue_parameter_display (TrimAutomation, gain_coefficient);
+                       }
+                       _last_trim_position_written = normalized_position;
+
+                       queue_display_reset (2000);
+               }
+       }
+}
+
 void
 Strip::notify_property_changed (const PropertyChange& what_changed)
 {
@@ -388,12 +430,13 @@ Strip::notify_panner_azi_changed (bool force_update)
                        if (control == _fader) {
                                if (!_fader->in_use()) {
                                        _surface->write (_fader->set_position (pos));
+                                       queue_parameter_display (PanAzimuthAutomation, pos);
                                }
                        } else if (control == _vpot) {
                                _surface->write (_vpot->set (pos, true, Pot::dot));
+                               queue_parameter_display (PanAzimuthAutomation, pos);
                        }
 
-                       queue_parameter_display (PanAzimuthAutomation, pos);
                        queue_display_reset (2000);
                        _last_pan_azi_position_written = pos;
                }
@@ -430,14 +473,15 @@ Strip::notify_panner_width_changed (bool force_update)
                                if (control == _fader) {
                                        if (!control->in_use()) {
                                                _surface->write (_fader->set_position (pos));
+                                               queue_parameter_display (PanWidthAutomation, pos);
                                        }
                                }
 
                        } else if (control == _vpot) {
                                _surface->write (_vpot->set (pos, true, Pot::spread));
+                               queue_parameter_display (PanWidthAutomation, pos);
                        }
 
-                       queue_parameter_display (PanWidthAutomation, pos);
                        queue_display_reset (2000);
                        _last_pan_azi_position_written = pos;
                }
@@ -650,6 +694,15 @@ Strip::do_parameter_display (AutomationType type, float val)
                }
                break;
 
+       case TrimAutomation:
+               if (_route) {
+                       char buf[16];
+                       float dB = accurate_coefficient_to_dB (val);
+                       snprintf (buf, sizeof (buf), "%6.1f", dB);
+                       _surface->write (display (1, buf));
+               }
+               break;
+
        default:
                break;
        }
@@ -747,6 +800,12 @@ Strip::update_automation ()
                        notify_panner_width_changed (false);
                }
        }
+       if (_route->trim()) {
+               ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
+               if (trim_state == Touch || trim_state == Play) {
+                       notify_trim_changed (false);
+               }
+       }
 }
 
 void
@@ -853,6 +912,8 @@ Strip::vpot_mode_string () const
        switch (ac->parameter().type()) {
        case GainAutomation:
                return "Fader";
+       case TrimAutomation:
+               return "Trim";
        case PanAzimuthAutomation:
                return "Pan";
        case PanWidthAutomation:
@@ -868,6 +929,45 @@ Strip::vpot_mode_string () const
        return "???";
 }
 
+ void
+Strip::potmode_changed (bool notify)
+{
+       if (!_route) {
+               return;
+       }
+
+       if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+               /* 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 (1000);
+               return;
+       }
+       // WIP
+       int pm = _surface->mcp().pot_mode();
+       switch (pm) {
+               case MackieControlProtocol::Pan:
+                       // This needs to set current pan mode (azimuth or width... or whatever)
+                       set_vpot_parameter (_pan_mode);
+                       DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Pan mode.\n");
+                       break;
+               case MackieControlProtocol::Tracks: // should change the Tracks to Trim
+                       DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
+                       set_vpot_parameter (TrimAutomation);
+                       break;
+               case MackieControlProtocol::Send:
+                       DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
+                       // set to current send
+                       break;
+               default:
+                       break;
+               }
+
+       if (notify) {
+               notify_all ();
+       }
+}
+
 void
 Strip::flip_mode_changed (bool notify)
 {
@@ -1023,30 +1123,30 @@ 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())) {
+                       return;
+               }
 
-       if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
-               return;
-       }
-
-       for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
-               if ((*i) == ac->parameter()) {
-                       break;
+               for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
+                       if ((*i) == ac->parameter()) {
+                               break;
+                       }
                }
-       }
 
-       /* move to the next mode in the list, or back to the start (which will
-          also happen if the current mode is not in the current pot mode list)
-       */
+               /* move to the next mode in the list, or back to the start (which will
+               also happen if the current mode is not in the current pot mode list)
+               */
 
-       if (i != possible_pot_parameters.end()) {
-               ++i;
-       }
+               if (i != possible_pot_parameters.end()) {
+                       ++i;
+               }
 
-       if (i == possible_pot_parameters.end()) {
-               i = possible_pot_parameters.begin();
+               if (i == possible_pot_parameters.end()) {
+                       i = possible_pot_parameters.begin();
+               }
+               set_vpot_parameter (*i);
        }
-
-       set_vpot_parameter (*i);
 }
 
 void
@@ -1057,9 +1157,15 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
 
        reset_saved_values ();
+       for (int i = 0;  i <= TrimAutomation; ++i) {
+               if (control_by_parameter[i] == _vpot) {
+                       control_by_parameter[i] = 0;
+               }
+       }
 
        switch (p.type()) {
        case PanAzimuthAutomation:
+               _pan_mode = PanAzimuthAutomation;
                pannable = _route->pannable ();
                if (pannable) {
                        if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
@@ -1088,6 +1194,7 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
                }
                break;
        case PanWidthAutomation:
+               _pan_mode = PanWidthAutomation;
                pannable = _route->pannable ();
                if (pannable) {
                        if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
@@ -1121,6 +1228,30 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
                break;
        case PanLFEAutomation:
                break;
+       case TrimAutomation:
+               if (_route->trim()) {
+                       if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+                               /* gain to vpot, trim to fader */
+                               _vpot->set_control (_route->gain_control());
+                               control_by_parameter[GainAutomation] = _vpot;
+                                       _fader->set_control (_route->trim_control());
+                                       control_by_parameter[TrimAutomation] = _fader;
+                       } else {
+                               /* gain to fader, trim to vpot */
+                               _fader->set_control (_route->gain_control());
+                               control_by_parameter[GainAutomation] = _fader;
+                                       _vpot->set_control (_route->trim_control());
+                                       control_by_parameter[TrimAutomation] = _vpot;
+                       }
+               } else {
+                       _vpot->set_control (boost::shared_ptr<AutomationControl>());
+                       control_by_parameter[TrimAutomation] = 0;
+               }
+               break;
+       default:
+               DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
+               break;
+
        }
 
        _surface->write (display (1, vpot_mode_string()));
@@ -1132,6 +1263,7 @@ Strip::reset_saved_values ()
        _last_pan_azi_position_written = -1.0;
        _last_pan_width_position_written = -1.0;
        _last_gain_position_written = -1.0;
+       _last_trim_position_written = -1.0;
 
 }
 
index c2cbfc2ee6d3d1d622d8df93318d1224f26272db..55a6fbef8c97b68d5245c5233a1295438cf8993e 100644 (file)
@@ -76,6 +76,7 @@ public:
        void zero ();
 
        void flip_mode_changed (bool notify=false);
+       void potmode_changed (bool notify=false);
 
        void lock_controls ();
        void unlock_controls ();
@@ -104,9 +105,12 @@ private:
        boost::shared_ptr<ARDOUR::Route> _route;
        PBD::ScopedConnectionList route_connections;
 
+       int      _pan_mode;
+
        float _last_gain_position_written;
        float _last_pan_azi_position_written;
        float _last_pan_width_position_written;
+       float _last_trim_position_written;
 
        void notify_solo_changed ();
        void notify_mute_changed ();
@@ -117,6 +121,7 @@ private:
        void notify_panner_width_changed (bool force_update = true);
        void notify_active_changed ();
        void notify_route_deleted ();
+       void notify_trim_changed (bool force_update = true);
 
        void update_automation ();
        void update_meter ();
index 8ace15a7ad2945f5c31f9a78fe782bf690df1a32..411a4ea47551e7d8e52e3a8da6d4afeccf82d9e7 100644 (file)
@@ -974,6 +974,14 @@ Surface::update_flip_mode_display ()
        }
 }
 
+ void
+Surface::update_potmode ()
+{
+       for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
+               (*s)->potmode_changed (false);
+       }
+}
+
 void
 Surface::update_view_mode_display ()
 {
@@ -987,15 +995,7 @@ Surface::update_view_mode_display ()
        switch (_mcp.view_mode()) {
        case MackieControlProtocol::Mixer:
                show_two_char_display ("Mx");
-               id = Button::Pan;
-               break;
-       case MackieControlProtocol::Dynamics:
-               show_two_char_display ("Dy");
-               id = Button::Dyn;
-               break;
-       case MackieControlProtocol::EQ:
-               show_two_char_display ("EQ");
-               id = Button::Eq;
+               //id = Button::Pan;
                break;
        case MackieControlProtocol::Loop:
                show_two_char_display ("LP");
@@ -1007,14 +1007,6 @@ Surface::update_view_mode_display ()
        case MackieControlProtocol::MidiTracks:
                show_two_char_display ("MT");
                break;
-       case MackieControlProtocol::Sends:
-               show_two_char_display ("Sn");
-               id = Button::Send;
-               break;
-       case MackieControlProtocol::Plugins:
-               show_two_char_display ("Pl");
-               id = Button::Plugin;
-               break;
        default:
                break;
        }
index 17b515e3d7d42086c340a4687e1a4d18a917a1f5..a0065e3cceac3e34c8e456b3bbf559253a990a2a 100644 (file)
@@ -151,6 +151,7 @@ public:
 
        void update_view_mode_display ();
        void update_flip_mode_display ();
+       void update_potmode ();
 
        void gui_selection_changed (const ARDOUR::StrongRouteNotificationList&);