From 2e9de2def08c3f0241f198094c0206e765b449e7 Mon Sep 17 00:00:00 2001 From: Len Ovens Date: Sun, 1 Nov 2015 13:35:02 -0800 Subject: [PATCH] Added Phase control mackie controls as part of the Trim (track) vpot assignment. --- libs/ardour/ardour/route.h | 19 +++++ libs/ardour/ardour/types.h | 2 + libs/ardour/route.cc | 48 +++++++++++ libs/surfaces/mackie/mcp_buttons.cc | 2 - libs/surfaces/mackie/strip.cc | 127 +++++++++++++++++++++++++++- libs/surfaces/mackie/strip.h | 2 + 6 files changed, 194 insertions(+), 6 deletions(-) diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index da4f0f809e..d48519f952 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -410,6 +410,20 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou boost::weak_ptr _route; }; + class PhaseControllable : public AutomationControl { + public: + PhaseControllable (std::string name, boost::shared_ptr); + void set_value (double); + void set_channel (int); + double get_value () const; + int channel() const; + + private: + boost::weak_ptr _route; + int _current_phase; + }; + + boost::shared_ptr 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 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 _solo_control; boost::shared_ptr _mute_control; boost::shared_ptr _mute_master; + boost::shared_ptr _phase_control; virtual void act_on_mute () {} diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index d4c65f3871..4ad1391abe 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -140,6 +140,8 @@ namespace ARDOUR { EnvelopeAutomation, RecEnableAutomation, TrimAutomation, + PhaseAutomation, + SendAutomation, }; enum AutoState { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 56d1f69ebe..a0dc130a7b 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -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 r) + : AutomationControl (r->session(), + Evoral::Parameter (PhaseAutomation), + ParameterDescriptor (Evoral::Parameter (PhaseAutomation)), + boost::shared_ptr(), + name) + , _route (r) +{ + boost::shared_ptr 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 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 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) { diff --git a/libs/surfaces/mackie/mcp_buttons.cc b/libs/surfaces/mackie/mcp_buttons.cc index 31d2ad9ee2..6885acc97e 100644 --- a/libs/surfaces/mackie/mcp_buttons.cc +++ b/libs/surfaces/mackie/mcp_buttons.cc @@ -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; } diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc index 2031c09d2d..7b9d6a6864 100644 --- a/libs/surfaces/mackie/strip.cc +++ b/libs/surfaces/mackie/strip.cc @@ -184,6 +184,7 @@ Strip::set_route (boost::shared_ptr 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 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 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 = _route->pannable(); if (pannable && _route->panner()) { @@ -235,6 +238,8 @@ Strip::set_route (boost::shared_ptr 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 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()); + 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()); + 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()); + } else { + // gain to fader, trim to vpot + _fader->set_control (_route->gain_control()); + control_by_parameter[GainAutomation] = _fader; + _vpot->set_control (boost::shared_ptr()); + } + break; default: DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p)); break; diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h index d876339435..e2f701830a 100644 --- a/libs/surfaces/mackie/strip.h +++ b/libs/surfaces/mackie/strip.h @@ -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 possible_pot_parameters; + std::vector possible_trim_parameters; void next_pot_mode (); void set_vpot_parameter (Evoral::Parameter); void show_route_name ();