Added Phase control mackie controls as part of the Trim (track) vpot assignment.
authorLen Ovens <len@ovenwerks.net>
Sun, 1 Nov 2015 21:35:02 +0000 (13:35 -0800)
committerLen Ovens <len@ovenwerks.net>
Sun, 1 Nov 2015 21:35:02 +0000 (13:35 -0800)
libs/ardour/ardour/route.h
libs/ardour/ardour/types.h
libs/ardour/route.cc
libs/surfaces/mackie/mcp_buttons.cc
libs/surfaces/mackie/strip.cc
libs/surfaces/mackie/strip.h

index da4f0f809e1c5f794a8bff048ef312346a9d47cc..d48519f9526a1b6bab075a3228329e8a39c012cd 100644 (file)
@@ -410,6 +410,20 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
                boost::weak_ptr<Route> _route;
        };
 
+       class PhaseControllable : public AutomationControl {
+       public:
+               PhaseControllable (std::string name, boost::shared_ptr<Route>);
+               void set_value (double);
+               void set_channel (int);
+               double get_value () const;
+               int channel() const;
+
+       private:
+               boost::weak_ptr<Route> _route;
+               int _current_phase;
+       };
+
+
        boost::shared_ptr<SoloControllable> solo_control() const {
                return _solo_control;
        }
@@ -422,6 +436,10 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
                return _mute_master;
        }
 
+       boost::shared_ptr<PhaseControllable> phase_control() const {
+               return _phase_control;
+       }
+
        /* Route doesn't own these items, but sub-objects that it does own have them
           and to make UI code a bit simpler, we provide direct access to them
           here.
@@ -560,6 +578,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        boost::shared_ptr<SoloControllable> _solo_control;
        boost::shared_ptr<MuteControllable> _mute_control;
        boost::shared_ptr<MuteMaster> _mute_master;
+       boost::shared_ptr<PhaseControllable> _phase_control;
 
        virtual void act_on_mute () {}
 
index d4c65f3871c3b3b20ed7e73b99ada6ba361056fe..4ad1391abe209df46b1476fe1c02cde0923e6235 100644 (file)
@@ -140,6 +140,8 @@ namespace ARDOUR {
                EnvelopeAutomation,
                RecEnableAutomation,
                TrimAutomation,
+               PhaseAutomation,
+               SendAutomation,
        };
 
        enum AutoState {
index 56d1f69ebec4d5308c1bce872e2d03a7609a5b6b..a0dc130a7b697be1cb6701a66ed88cb1e0278083 100644 (file)
@@ -135,12 +135,15 @@ Route::init ()
 
        _solo_control.reset (new SoloControllable (X_("solo"), shared_from_this ()));
        _mute_control.reset (new MuteControllable (X_("mute"), shared_from_this ()));
+       _phase_control.reset (new PhaseControllable (X_("phase"), shared_from_this ()));
 
        _solo_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
        _mute_control->set_flags (Controllable::Flag (_mute_control->flags() | Controllable::Toggle));
+       _phase_control->set_flags (Controllable::Flag (_phase_control->flags() | Controllable::Toggle));
 
        add_control (_solo_control);
        add_control (_mute_control);
+       add_control (_phase_control);
 
        /* panning */
 
@@ -3970,6 +3973,51 @@ Route::MuteControllable::get_value () const
        return (r && r->muted()) ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
 }
 
+Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr<Route> r)
+       : AutomationControl (r->session(),
+                            Evoral::Parameter (PhaseAutomation),
+                            ParameterDescriptor (Evoral::Parameter (PhaseAutomation)),
+                            boost::shared_ptr<AutomationList>(),
+                            name)
+       , _route (r)
+{
+       boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(PhaseAutomation)));
+       gl->set_interpolation(Evoral::ControlList::Discrete);
+       set_list (gl);
+}
+
+void
+Route::PhaseControllable::set_value (double v)
+{
+       boost::shared_ptr<Route> r = _route.lock ();
+       if (r->phase_invert().size()) {
+               if (v == 0 || (v < 1 && v > 0.9) ) {
+                       r->set_phase_invert (_current_phase, false);
+               } else {
+                       r->set_phase_invert (_current_phase, true);
+               }
+       }
+}
+
+double
+Route::PhaseControllable::get_value () const
+{
+       boost::shared_ptr<Route> r = _route.lock ();
+       return (double) r->phase_invert (_current_phase);
+}
+
+void
+Route::PhaseControllable::set_channel (int c)
+{
+       _current_phase = c;
+}
+
+int
+Route::PhaseControllable::channel () const
+{
+       return _current_phase;
+}
+
 void
 Route::set_block_size (pframes_t nframes)
 {
index 31d2ad9ee2099258638f1ae84c5858a922c7a87a..6885acc97e244781ab0a65fb38e875f97a2a69b6 100644 (file)
@@ -839,8 +839,6 @@ MackieControlProtocol::track_release (Mackie::Button&)
 Mackie::LedState
 MackieControlProtocol::send_press (Mackie::Button&)
 {
-       return none;
-       // remove above line when sends implemented
        set_pot_mode (Send);
        return none;
 }
index 2031c09d2d0a593629a74e8b4773587f24104a7d..7b9d6a6864676bb04c9a0cbe89b087f7c04f0127 100644 (file)
@@ -184,6 +184,7 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
        control_by_parameter[PanLFEAutomation] = (Control*) 0;
        control_by_parameter[GainAutomation] = (Control*) 0;
        control_by_parameter[TrimAutomation] = (Control*) 0;
+       control_by_parameter[PhaseAutomation] = (Control*) 0;
 
        reset_saved_values ();
 
@@ -198,9 +199,6 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
        _solo->set_control (_route->solo_control());
        _mute->set_control (_route->mute_control());
 
-       _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());
 
@@ -210,6 +208,11 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
                _route->trim_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trim_changed, this, false), ui_context());
        }
 
+       if (_route->phase_invert().size()) {
+               _route->phase_invert_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_phase_changed, this, false), ui_context());
+               _route->phase_control()->set_channel(0);
+       }
+
        boost::shared_ptr<Pannable> pannable = _route->pannable();
 
        if (pannable && _route->panner()) {
@@ -235,6 +238,8 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
        _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
 
        /* Update */
+       _pan_mode = PanAzimuthAutomation;
+       potmode_changed (true);
 
        notify_all ();
 
@@ -261,6 +266,16 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
        if (_route->trim() && route()->trim()->active()) {
                possible_pot_parameters.push_back (TrimAutomation);
        }
+
+       possible_trim_parameters.clear();
+
+       if (_route->trim() && route()->trim()->active()) {
+               possible_trim_parameters.push_back (TrimAutomation);
+       }
+
+       if (_route->phase_invert().size()) {
+               possible_trim_parameters.push_back (PhaseAutomation);
+       }
 }
 
 void
@@ -279,6 +294,7 @@ Strip::notify_all()
        notify_panner_width_changed ();
        notify_record_enable_changed ();
        notify_trim_changed ();
+       notify_phase_changed ();
 }
 
 void
@@ -397,6 +413,33 @@ Strip::notify_trim_changed (bool force_update)
        }
 }
 
+void
+Strip::notify_phase_changed (bool force_update)
+{
+       if (_route) {
+               Control* control = 0;
+               ControlParameterMap::iterator i = control_by_parameter.find (PhaseAutomation);
+
+               if (i == control_by_parameter.end()) {
+                       return;
+               }
+
+               control = i->second;
+
+               float normalized_position = _route->phase_control()->get_value();
+
+               if (control == _fader) {
+                       if (!_fader->in_use()) {
+                               _surface->write (_fader->set_position (normalized_position));
+                               queue_parameter_display (PhaseAutomation, normalized_position);
+                       }
+               } else if (control == _vpot) {
+                       _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
+                       queue_parameter_display (PhaseAutomation, normalized_position);
+               }
+       }
+}
+
 void
 Strip::notify_property_changed (const PropertyChange& what_changed)
 {
@@ -733,6 +776,17 @@ Strip::do_parameter_display (AutomationType type, float val)
                }
                break;
 
+       case PhaseAutomation:
+               if (_route) {
+                       if (_route->phase_control()->get_value() < 0.5) {
+                               _surface->write (display (1, "Normal"));
+                       } else {
+                               _surface->write (display (1, "Invert"));
+                       }
+                       screen_hold = true;
+               }
+               break;
+
        default:
                break;
        }
@@ -996,6 +1050,8 @@ Strip::vpot_mode_string () const
                return "Fader";
        case TrimAutomation:
                return "Trim";
+       case PhaseAutomation:
+               return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
        case PanAzimuthAutomation:
                return "Pan";
        case PanWidthAutomation:
@@ -1032,7 +1088,7 @@ Strip::potmode_changed (bool notify)
                break;
        case MackieControlProtocol::Send:
                DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
-               // set to current send
+               set_vpot_parameter (NullAutomation);
                break;
        }
 
@@ -1109,7 +1165,31 @@ Strip::next_pot_mode ()
                        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())) {
+                       return;
+               }
+
+               for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
+                       if ((*i) == ac->parameter()) {
+                               break;
+                       }
+               }
+               // check for phase and more than one phase control
+               /* 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_trim_parameters.end()) {
+                       ++i;
+               }
+
+               if (i == possible_trim_parameters.end()) {
+                       i = possible_trim_parameters.begin();
+               }
+               set_vpot_parameter (*i);
        }
+
 }
 
 void
@@ -1216,6 +1296,45 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
                        }
                }
                break;
+       case PhaseAutomation:
+               if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+                       /* gain to vpot, phase to fader */
+                       _vpot->set_control (_route->gain_control());
+                       control_by_parameter[GainAutomation] = _vpot;
+                       if (_route->phase_invert().size()) {
+                               _fader->set_control (_route->phase_control());
+                               control_by_parameter[PhaseAutomation] = _fader;
+                       } else {
+                               _fader->set_control (boost::shared_ptr<AutomationControl>());
+                               control_by_parameter[PhaseAutomation] = 0;
+                       }
+               } else {
+                       /* gain to fader, phase to vpot */
+                       _fader->set_control (_route->gain_control());
+                       control_by_parameter[GainAutomation] = _fader;
+                       if (_route->phase_invert().size()) {
+                               _vpot->set_control (_route->phase_control());
+                               control_by_parameter[PhaseAutomation] = _vpot;
+                       } else {
+                               _vpot->set_control (boost::shared_ptr<AutomationControl>());
+                               control_by_parameter[PhaseAutomation] = 0;
+                       }
+               }
+               break;
+       case NullAutomation:
+               // deal with sends, phase, hidden, etc.
+               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 (boost::shared_ptr<AutomationControl>());
+               } else {
+                       // gain to fader, trim to vpot
+                       _fader->set_control (_route->gain_control());
+                       control_by_parameter[GainAutomation] = _fader;
+                       _vpot->set_control (boost::shared_ptr<AutomationControl>());
+               }
+               break;
        default:
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
                break;
index d87633943571c36a4eec5062078186a8e84a49ae..e2f701830a0003cce56914b6850277656b5671cd 100644 (file)
@@ -125,6 +125,7 @@ private:
        void notify_active_changed ();
        void notify_route_deleted ();
        void notify_trim_changed (bool force_update = true);
+       void notify_phase_changed (bool force_update = true);
 
        void update_automation ();
        void update_meter ();
@@ -148,6 +149,7 @@ private:
        void fader_touch_event (Button&, ButtonState);
 
        std::vector<Evoral::Parameter> possible_pot_parameters;
+       std::vector<Evoral::Parameter> possible_trim_parameters;
        void next_pot_mode ();
        void set_vpot_parameter (Evoral::Parameter);
        void show_route_name ();