2 Copyright (C) 2006,2007 John Anderson
3 Copyright (C) 2012 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <glibmm/convert.h>
30 #include "midi++/port.h"
32 #include "pbd/compose.h"
33 #include "pbd/convert.h"
35 #include "ardour/amp.h"
36 #include "ardour/bundle.h"
37 #include "ardour/debug.h"
38 #include "ardour/midi_ui.h"
39 #include "ardour/meter.h"
40 #include "ardour/plugin_insert.h"
41 #include "ardour/pannable.h"
42 #include "ardour/panner.h"
43 #include "ardour/panner_shell.h"
44 #include "ardour/rc_configuration.h"
45 #include "ardour/route.h"
46 #include "ardour/session.h"
47 #include "ardour/send.h"
48 #include "ardour/track.h"
49 #include "ardour/midi_track.h"
50 #include "ardour/user_bundle.h"
51 #include "ardour/profile.h"
53 #include "mackie_control_protocol.h"
54 #include "surface_port.h"
65 using namespace ARDOUR;
67 using namespace ArdourSurface;
68 using namespace Mackie;
70 #ifndef timeradd /// only avail with __USE_BSD
71 #define timeradd(a,b,result) \
73 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
74 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
75 if ((result)->tv_usec >= 1000000) \
78 (result)->tv_usec -= 1000000; \
83 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
85 Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
98 , _controls_locked (false)
99 , _transport_is_rolling (false)
100 , _metering_active (true)
101 , _block_screen_redisplay_until (0)
102 , return_to_vpot_mode_display_at (UINT64_MAX)
104 , _pan_mode (PanAzimuthAutomation)
105 , vpot_parameter (PanAzimuthAutomation)
106 , _last_gain_position_written (-1.0)
107 , _last_pan_azi_position_written (-1.0)
108 , _last_pan_width_position_written (-1.0)
109 , _last_trim_position_written (-1.0)
112 _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
113 _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
115 if (s.mcp().device_info().has_meters()) {
116 _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
119 for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
120 Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
121 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
122 _surface->number(), index, Button::id_to_name (bb->bid()),
123 bb->id(), b->second.base_id));
129 /* surface is responsible for deleting all controls */
133 Strip::add (Control & control)
137 Group::add (control);
139 /* fader, vpot, meter were all set explicitly */
141 if ((button = dynamic_cast<Button*>(&control)) != 0) {
142 switch (button->bid()) {
143 case Button::RecEnable:
155 case Button::VSelect:
158 case Button::FaderTouch:
159 _fader_touch = button;
168 Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
170 if (_controls_locked) {
174 mb_pan_controllable.reset();
176 route_connections.drop_connections ();
178 _solo->set_control (boost::shared_ptr<AutomationControl>());
179 _mute->set_control (boost::shared_ptr<AutomationControl>());
180 _select->set_control (boost::shared_ptr<AutomationControl>());
181 _recenable->set_control (boost::shared_ptr<AutomationControl>());
182 _fader->set_control (boost::shared_ptr<AutomationControl>());
183 _vpot->set_control (boost::shared_ptr<AutomationControl>());
187 control_by_parameter.clear ();
189 control_by_parameter[PanAzimuthAutomation] = (Control*) 0;
190 control_by_parameter[PanWidthAutomation] = (Control*) 0;
191 control_by_parameter[PanElevationAutomation] = (Control*) 0;
192 control_by_parameter[PanFrontBackAutomation] = (Control*) 0;
193 control_by_parameter[PanLFEAutomation] = (Control*) 0;
194 control_by_parameter[GainAutomation] = (Control*) 0;
195 control_by_parameter[PhaseAutomation] = (Control*) 0;
197 reset_saved_values ();
204 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
205 _surface->number(), _index, _route->name()));
207 _solo->set_control (_route->solo_control());
208 _mute->set_control (_route->mute_control());
210 _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
211 _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
213 _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
215 if (_route->trim() && route()->trim()->active()) {
216 _route->trim_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trim_changed, this, false), ui_context());
219 if (_route->phase_invert().size()) {
220 _route->phase_invert_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_phase_changed, this, false), ui_context());
221 _route->phase_control()->set_channel(0);
224 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control();
226 pan_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
229 pan_control = _route->pan_width_control();
231 pan_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
234 _route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
235 _route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
237 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
240 _recenable->set_control (trk->rec_enable_control());
241 trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
244 // TODO this works when a currently-banked route is made inactive, but not
245 // when a route is activated which should be currently banked.
247 _route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
248 _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
250 /* setup legal VPot modes for this route */
252 possible_pot_parameters.clear();
254 if (_route->pan_azimuth_control()) {
255 possible_pot_parameters.push_back (PanAzimuthAutomation);
257 if (_route->pan_width_control()) {
258 possible_pot_parameters.push_back (PanWidthAutomation);
260 if (_route->pan_elevation_control()) {
261 possible_pot_parameters.push_back (PanElevationAutomation);
263 if (_route->pan_frontback_control()) {
264 possible_pot_parameters.push_back (PanFrontBackAutomation);
266 if (_route->pan_lfe_control()) {
267 possible_pot_parameters.push_back (PanLFEAutomation);
270 if (_route->phase_invert().size()) {
271 possible_trim_parameters.push_back (PhaseAutomation);
272 _route->phase_control()->set_channel(0);
276 _pan_mode = PanAzimuthAutomation;
277 potmode_changed (false);
289 // The active V-pot control may not be active for this strip
290 // But if we zero it in the controls function it may erase
291 // the one we do want
292 _surface->write (_vpot->zero());
294 notify_solo_changed ();
295 notify_mute_changed ();
296 notify_gain_changed ();
297 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
298 notify_panner_azi_changed ();
299 notify_panner_width_changed ();
300 notify_record_enable_changed ();
301 notify_trim_changed ();
302 notify_phase_changed ();
303 notify_processor_changed ();
307 Strip::notify_solo_changed ()
309 if (_route && _solo) {
310 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
315 Strip::notify_mute_changed ()
317 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
318 if (_route && _mute) {
319 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
320 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
322 _surface->write (_mute->set_state (_route->muted() ? on : off));
327 Strip::notify_record_enable_changed ()
329 if (_route && _recenable) {
330 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
335 Strip::notify_active_changed ()
337 _surface->mcp().refresh_current_bank();
341 Strip::notify_route_deleted ()
343 _surface->mcp().refresh_current_bank();
347 Strip::notify_gain_changed (bool force_update)
353 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
359 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
361 float gain_coefficient = ac->get_value();
362 float normalized_position = ac->internal_to_interface (gain_coefficient);
364 if (force_update || normalized_position != _last_gain_position_written) {
366 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
367 if (!control->in_use()) {
368 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
370 do_parameter_display (GainAutomation, gain_coefficient);
372 if (!control->in_use()) {
373 _surface->write (_fader->set_position (normalized_position));
375 do_parameter_display (GainAutomation, gain_coefficient);
378 _last_gain_position_written = normalized_position;
384 Strip::notify_trim_changed (bool force_update)
388 if (!_route->trim() || !route()->trim()->active()) {
391 Control* control = 0;
392 ControlParameterMap::iterator i = control_by_parameter.find (TrimAutomation);
394 if (i == control_by_parameter.end()) {
400 boost::shared_ptr<AutomationControl> ac = _route->trim_control();
402 float gain_coefficient = ac->get_value();
403 float normalized_position = ac->internal_to_interface (gain_coefficient);
405 if (force_update || normalized_position != _last_trim_position_written) {
406 if (control == _fader) {
407 if (!_fader->in_use()) {
408 _surface->write (_fader->set_position (normalized_position));
409 do_parameter_display (TrimAutomation, gain_coefficient);
411 } else if (control == _vpot) {
412 _surface->write (_vpot->set (normalized_position, true, Pot::dot));
413 do_parameter_display (TrimAutomation, gain_coefficient);
415 _last_trim_position_written = normalized_position;
421 Strip::notify_phase_changed (bool force_update)
424 if (!_route->phase_invert().size()) {
428 Control* control = 0;
429 ControlParameterMap::iterator i = control_by_parameter.find (PhaseAutomation);
431 if (i == control_by_parameter.end()) {
437 float normalized_position = _route->phase_control()->get_value();
439 if (control == _fader) {
440 if (!_fader->in_use()) {
441 _surface->write (_fader->set_position (normalized_position));
442 do_parameter_display (PhaseAutomation, normalized_position);
444 } else if (control == _vpot) {
445 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
446 do_parameter_display (PhaseAutomation, normalized_position);
452 Strip::notify_processor_changed (bool force_update)
457 Strip::notify_property_changed (const PropertyChange& what_changed)
459 if (!what_changed.contains (ARDOUR::Properties::name)) {
467 Strip::show_route_name ()
469 MackieControlProtocol::SubViewMode svm = _surface->mcp().subview_mode();
471 if (svm != MackieControlProtocol::None) {
472 /* subview mode is responsible for upper line */
476 string fullname = string();
478 // make sure first three strips get cleared of view mode
483 fullname = _route->name();
487 if (fullname.length() <= 6) {
490 line1 = PBD::short_version (fullname, 6);
493 pending_display[0] = line1;
497 Strip::notify_send_level_change (AutomationType type, uint32_t send_num, bool force_update)
499 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
502 /* not in subview mode */
506 if (_surface->mcp().subview_mode() != MackieControlProtocol::Sends) {
507 /* no longer in Sends subview mode */
511 boost::shared_ptr<AutomationControl> control = r->send_level_controllable (send_num);
517 float val = control->get_value();
518 do_parameter_display (type, val);
519 /* update pot/encoder */
520 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
525 Strip::notify_trackview_change (AutomationType type, uint32_t send_num, bool force_update)
527 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
530 /* not in subview mode */
534 if (_surface->mcp().subview_mode() != MackieControlProtocol::TrackView) {
535 /* no longer in TrackViewsubview mode */
539 boost::shared_ptr<AutomationControl> control;
541 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (r);
545 control = r->trim_control();
547 case SoloIsolateAutomation:
548 control = r->solo_isolate_control ();
550 case SoloSafeAutomation:
551 control = r->solo_safe_control ();
553 case MonitoringAutomation:
555 control = track->monitoring_control();
563 float val = control->get_value();
564 if (control->desc().enumeration || control->desc().integer_step) {
565 do_parameter_display (type, val);
567 do_parameter_display (type, control->internal_to_interface (val));
569 /* update pot/encoder */
570 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
575 Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
577 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
580 /* not in subview mode */
584 if (_surface->mcp().subview_mode() != MackieControlProtocol::EQ) {
585 /* no longer in EQ subview mode */
589 boost::shared_ptr<AutomationControl> control;
593 control = r->eq_gain_controllable (band);
596 control = r->eq_freq_controllable (band);
599 control = r->eq_q_controllable (band);
602 control = r->eq_shape_controllable (band);
605 control = r->eq_hpf_controllable ();
608 control = r->eq_enable_controllable ();
615 float val = control->get_value();
616 do_parameter_display (type, val);
617 /* update pot/encoder */
618 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
623 Strip::notify_dyn_change (AutomationType type, bool force_update, bool propagate_mode)
625 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
628 /* not in subview mode */
632 if (_surface->mcp().subview_mode() != MackieControlProtocol::Dynamics) {
633 /* no longer in EQ subview mode */
637 boost::shared_ptr<AutomationControl> control;
638 bool reset_all = false;
642 control = r->comp_threshold_controllable ();
645 control = r->comp_speed_controllable ();
648 control = r->comp_mode_controllable ();
652 control = r->comp_makeup_controllable ();
655 control = r->comp_redux_controllable ();
658 control = r->comp_enable_controllable ();
664 if (propagate_mode && reset_all) {
665 _surface->subview_mode_changed ();
669 float val = control->get_value();
670 do_parameter_display (type, val);
671 /* update pot/encoder */
672 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
677 Strip::notify_panner_azi_changed (bool force_update)
683 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
685 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
691 Control* control = 0;
692 ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
694 if (i == control_by_parameter.end()) {
700 double normalized_pos = pan_control->internal_to_interface (pan_control->get_value());
701 double internal_pos = pan_control->get_value();
703 if (force_update || (normalized_pos != _last_pan_azi_position_written)) {
705 if (control == _fader) {
706 if (!_fader->in_use()) {
707 _surface->write (_fader->set_position (normalized_pos));
708 /* show actual internal value to user */
709 do_parameter_display (PanAzimuthAutomation, internal_pos);
711 } else if (control == _vpot) {
712 _surface->write (_vpot->set (normalized_pos, true, Pot::dot));
713 /* show actual internal value to user */
714 do_parameter_display (PanAzimuthAutomation, internal_pos);
717 _last_pan_azi_position_written = normalized_pos;
722 Strip::notify_panner_width_changed (bool force_update)
728 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
730 boost::shared_ptr<AutomationControl> pan_control = _route->pan_width_control ();
736 Control* control = 0;
737 ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
739 if (i == control_by_parameter.end()) {
745 double pos = pan_control->internal_to_interface (pan_control->get_value());
747 if (force_update || pos != _last_pan_width_position_written) {
749 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
751 if (control == _fader) {
752 if (!control->in_use()) {
753 _surface->write (_fader->set_position (pos));
754 do_parameter_display (PanWidthAutomation, pos);
758 } else if (control == _vpot) {
759 _surface->write (_vpot->set (pos, true, Pot::spread));
760 do_parameter_display (PanWidthAutomation, pos);
763 _last_pan_width_position_written = pos;
768 Strip::select_event (Button&, ButtonState bs)
770 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
774 int ms = _surface->mcp().main_modifier_state();
776 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
777 _controls_locked = !_controls_locked;
778 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
779 block_vpot_mode_display_for (1000);
783 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
784 /* reset to default */
785 boost::shared_ptr<AutomationControl> ac = _fader->control ();
787 ac->set_value (ac->normal(), Controllable::NoGroup);
792 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
793 _surface->mcp().add_down_select_button (_surface->number(), _index);
794 _surface->mcp().select_range ();
797 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
798 _surface->mcp().remove_down_select_button (_surface->number(), _index);
803 Strip::vselect_event (Button&, ButtonState bs)
805 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
807 /* most subview modes: vpot press acts like a button for toggle parameters */
813 if (_surface->mcp().subview_mode() != MackieControlProtocol::Sends) {
815 boost::shared_ptr<AutomationControl> control = _vpot->control ();
820 Controllable::GroupControlDisposition gcd;
821 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
822 gcd = Controllable::InverseGroup;
824 gcd = Controllable::UseGroup;
827 if (control->toggled()) {
828 if (control->toggled()) {
829 control->set_value (!control->get_value(), gcd);
832 } else if (control->desc().enumeration || control->desc().integer_step) {
834 double val = control->get_value ();
835 if (val <= control->upper() - 1.0) {
836 control->set_value (val + 1.0, gcd);
838 control->set_value (control->lower(), gcd);
844 /* Send mode: press enables/disables the relevant
845 * send, but the vpot is bound to the send-level so we
846 * need to lookup the enable/disable control
850 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
854 const uint32_t global_pos = _surface->mcp().global_index (*this);
855 boost::shared_ptr<AutomationControl> control = r->send_enable_controllable (global_pos);
858 bool currently_enabled = (bool) control->get_value();
859 Controllable::GroupControlDisposition gcd;
861 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
862 gcd = Controllable::InverseGroup;
864 gcd = Controllable::UseGroup;
867 control->set_value (!currently_enabled, gcd);
869 if (currently_enabled) {
870 /* we just turned it off */
871 pending_display[1] = "off";
873 /* we just turned it on, show the level
875 control = _route->send_level_controllable (global_pos);
876 do_parameter_display (BusSendLevel, control->get_value());
882 /* done with this event in subview mode */
889 int ms = _surface->mcp().main_modifier_state();
891 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
893 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
897 /* reset to default/normal value */
898 ac->set_value (ac->normal(), Controllable::NoGroup);
905 boost::shared_ptr<AutomationControl> ac = _route->master_send_enable_controllable ();
907 Controllable::GroupControlDisposition gcd;
909 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
910 gcd = Controllable::InverseGroup;
912 gcd = Controllable::UseGroup;
915 bool enabled = ac->get_value();
916 ac->set_value (!enabled, gcd);
919 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
928 Strip::fader_touch_event (Button&, ButtonState bs)
930 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
934 boost::shared_ptr<AutomationControl> ac = _fader->control ();
936 _fader->set_in_use (true);
937 _fader->start_touch (_surface->mcp().transport_frame());
940 do_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
945 _fader->set_in_use (false);
946 _fader->stop_touch (_surface->mcp().transport_frame(), true);
953 Strip::handle_button (Button& button, ButtonState bs)
955 boost::shared_ptr<AutomationControl> control;
958 button.set_in_use (true);
960 button.set_in_use (false);
963 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
965 switch (button.bid()) {
967 select_event (button, bs);
970 case Button::VSelect:
971 vselect_event (button, bs);
974 case Button::FaderTouch:
975 fader_touch_event (button, bs);
979 if ((control = button.control ())) {
981 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
982 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
984 float new_value = control->get_value() ? 0.0 : 1.0;
986 /* get all controls that either have their
987 * button down or are within a range of
988 * several down buttons
991 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
994 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
995 controls.size(), control->parameter().type(), new_value));
997 /* apply change, with potential modifier semantics */
999 Controllable::GroupControlDisposition gcd;
1001 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
1002 gcd = Controllable::InverseGroup;
1004 gcd = Controllable::UseGroup;
1007 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
1008 (*c)->set_value (new_value, gcd);
1012 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
1013 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
1021 Strip::do_parameter_display (AutomationType type, float val)
1023 bool screen_hold = false;
1027 case GainAutomation:
1029 pending_display[1] = " -inf ";
1031 float dB = accurate_coefficient_to_dB (val);
1032 snprintf (buf, sizeof (buf), "%6.1f", dB);
1033 pending_display[1] = buf;
1038 case PanAzimuthAutomation:
1039 if (Profile->get_mixbus()) {
1040 snprintf (buf, sizeof (buf), "%2.1f", val);
1041 pending_display[1] = buf;
1045 boost::shared_ptr<Pannable> p = _route->pannable();
1046 if (p && _route->panner()) {
1047 pending_display[1] =_route->panner()->value_as_string (p->pan_azimuth_control);
1054 case PanWidthAutomation:
1056 snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
1057 pending_display[1] = buf;
1062 case TrimAutomation:
1064 float dB = accurate_coefficient_to_dB (val);
1065 snprintf (buf, sizeof (buf), "%6.1f", dB);
1066 pending_display[1] = buf;
1071 case PhaseAutomation:
1073 if (_route->phase_control()->get_value() < 0.5) {
1074 pending_display[1] = "Normal";
1076 pending_display[1] = "Invert";
1084 float dB = accurate_coefficient_to_dB (val);
1085 snprintf (buf, sizeof (buf), "%6.1f", dB);
1086 pending_display[1] = buf;
1100 snprintf (buf, sizeof (buf), "%6.1f", val);
1101 pending_display[1] = buf;
1107 pending_display[1] = "on";
1109 pending_display[1] = "off";
1113 if (_surface->mcp().subview_route()) {
1114 pending_display[1] = _surface->mcp().subview_route()->comp_mode_name (val);
1117 case SoloSafeAutomation:
1118 case SoloIsolateAutomation:
1120 pending_display[1] = "on";
1122 pending_display[1] = "off";
1125 case MonitoringAutomation:
1126 switch (MonitorChoice ((int) val)) {
1128 pending_display[1] = "auto";
1131 pending_display[1] = "input";
1134 pending_display[1] = "disk";
1136 case MonitorCue: /* XXX not implemented as of jan 2016 */
1137 pending_display[1] = "cue";
1146 /* we just queued up a parameter to be displayed.
1147 1 second from now, switch back to vpot mode display.
1149 block_vpot_mode_display_for (1000);
1154 Strip::handle_fader_touch (Fader& fader, bool touch_on)
1157 fader.start_touch (_surface->mcp().transport_frame());
1159 fader.stop_touch (_surface->mcp().transport_frame(), false);
1164 Strip::handle_fader (Fader& fader, float position)
1166 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
1167 boost::shared_ptr<AutomationControl> ac = fader.control();
1172 Controllable::GroupControlDisposition gcd = Controllable::UseGroup;
1174 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
1175 gcd = Controllable::InverseGroup;
1178 fader.set_value (position, gcd);
1180 /* From the Mackie Control MIDI implementation docs:
1182 In order to ensure absolute synchronization with the host software,
1183 Mackie Control uses a closed-loop servo system for the faders,
1184 meaning the faders will always move to their last received position.
1185 When a host receives a Fader Position Message, it must then
1186 re-transmit that message to the Mackie Control or else the faders
1187 will return to their last position.
1190 _surface->write (fader.set_position (position));
1194 Strip::handle_pot (Pot& pot, float delta)
1196 /* Pots only emit events when they move, not when they
1197 stop moving. So to get a stop event, we need to use a timeout.
1200 boost::shared_ptr<AutomationControl> ac = pot.control();
1205 Controllable::GroupControlDisposition gcd;
1207 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
1208 gcd = Controllable::InverseGroup;
1210 gcd = Controllable::UseGroup;
1213 if (ac->toggled()) {
1215 /* make it like a single-step, directional switch */
1218 ac->set_value (1.0, gcd);
1220 ac->set_value (0.0, gcd);
1223 } else if (ac->desc().enumeration || ac->desc().integer_step) {
1225 /* use Controllable::get_value() to avoid the
1226 * "scaling-to-interface" that takes place in
1227 * Control::get_value() via the pot member.
1229 * an enumeration with 4 values will have interface values of
1230 * 0.0, 0.25, 0.5 and 0.75 or some similar oddness. Lets not
1235 ac->set_value (min (ac->upper(), ac->get_value() + 1.0), gcd);
1237 ac->set_value (max (ac->lower(), ac->get_value() - 1.0), gcd);
1242 double p = ac->get_value();
1246 p = max (ac->lower(), p);
1247 p = min (ac->upper(), p);
1249 ac->set_value (p, gcd);
1254 Strip::periodic (ARDOUR::microseconds_t now)
1257 update_automation ();
1261 Strip::redisplay (ARDOUR::microseconds_t now, bool force)
1263 if (_block_screen_redisplay_until >= now) {
1264 /* no drawing allowed */
1268 if (_block_screen_redisplay_until) {
1269 /* we were blocked, but the time period has elapsed, so we must
1273 _block_screen_redisplay_until = 0;
1276 if (force || (current_display[0] != pending_display[0])) {
1277 _surface->write (display (0, pending_display[0]));
1278 current_display[0] = pending_display[0];
1281 if (return_to_vpot_mode_display_at <= now) {
1282 return_to_vpot_mode_display_at = UINT64_MAX;
1283 return_to_vpot_mode_display ();
1286 if (force || (current_display[1] != pending_display[1])) {
1287 _surface->write (display (1, pending_display[1]));
1288 current_display[1] = pending_display[1];
1293 Strip::update_automation ()
1299 ARDOUR::AutoState state = _route->gain_control()->automation_state();
1301 if (state == Touch || state == Play) {
1302 notify_gain_changed (false);
1305 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1307 state = pan_control->automation_state ();
1308 if (state == Touch || state == Play) {
1309 notify_panner_azi_changed (false);
1313 pan_control = _route->pan_width_control ();
1315 state = pan_control->automation_state ();
1316 if (state == Touch || state == Play) {
1317 notify_panner_width_changed (false);
1321 if (_route->trim() && route()->trim()->active()) {
1322 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1323 if (trim_state == Touch || trim_state == Play) {
1324 notify_trim_changed (false);
1330 Strip::update_meter ()
1336 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1340 if (_meter && _transport_is_rolling && _metering_active) {
1341 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1342 _meter->send_update (*_surface, dB);
1350 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1351 _surface->write ((*it)->zero ());
1354 _surface->write (blank_display (0));
1355 _surface->write (blank_display (1));
1356 pending_display[0] = string();
1357 pending_display[1] = string();
1358 current_display[0] = string();
1359 current_display[1] = string();
1363 Strip::blank_display (uint32_t line_number)
1365 return display (line_number, string());
1369 Strip::display (uint32_t line_number, const std::string& line)
1371 assert (line_number <= 1);
1373 MidiByteArray retval;
1375 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1378 retval << _surface->sysex_hdr();
1382 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1383 retval << (_index * 7 + (line_number * 0x38));
1385 // ascii data to display. @param line is UTF-8
1386 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1387 string::size_type len = ascii.length();
1389 ascii = ascii.substr (0, 6);
1393 // pad with " " out to 6 chars
1394 for (int i = len; i < 6; ++i) {
1398 // column spacer, unless it's the right-hand column
1404 retval << MIDI::eox;
1410 Strip::lock_controls ()
1412 _controls_locked = true;
1416 Strip::unlock_controls ()
1418 _controls_locked = false;
1422 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1424 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1425 if ((*i) == _route) {
1426 _surface->write (_select->set_state (on));
1431 _surface->write (_select->set_state (off));
1435 Strip::vpot_mode_string ()
1437 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1442 if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1444 } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1446 } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1447 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1448 } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1450 } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1452 } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1454 } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1456 } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1460 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1468 Strip::potmode_changed (bool notify)
1475 int pm = _surface->mcp().pot_mode();
1477 case MackieControlProtocol::Pan:
1478 // This needs to set current pan mode (azimuth or width... or whatever)
1479 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1480 set_vpot_parameter (_pan_mode);
1490 Strip::block_screen_display_for (uint32_t msecs)
1492 _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1496 Strip::block_vpot_mode_display_for (uint32_t msecs)
1498 return_to_vpot_mode_display_at = ARDOUR::get_microseconds() + (msecs * 1000);
1502 Strip::return_to_vpot_mode_display ()
1504 /* returns the second line of the two-line per-strip display
1505 back the mode where it shows what the VPot controls.
1508 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1509 /* do nothing - second line shows value of current subview parameter */
1511 } else if (_route) {
1512 pending_display[1] = vpot_mode_string();
1514 pending_display[1] = string();
1519 Strip::next_pot_mode ()
1521 vector<AutomationType>::iterator i;
1523 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1524 /* do not change vpot mode while in flipped mode */
1525 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1526 pending_display[1] = "Flip";
1527 block_vpot_mode_display_for (1000);
1532 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1539 if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1541 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
1545 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1546 if ((*i) == ac->parameter().type()) {
1551 /* move to the next mode in the list, or back to the start (which will
1552 also happen if the current mode is not in the current pot mode list)
1555 if (i != possible_pot_parameters.end()) {
1559 if (i == possible_pot_parameters.end()) {
1560 i = possible_pot_parameters.begin();
1563 set_vpot_parameter (*i);
1568 Strip::subview_mode_changed ()
1570 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1572 subview_connections.drop_connections ();
1574 switch (_surface->mcp().subview_mode()) {
1575 case MackieControlProtocol::None:
1576 set_vpot_parameter (vpot_parameter);
1577 /* need to show strip name again */
1579 notify_metering_state_changed ();
1583 case MackieControlProtocol::EQ:
1587 /* leave it as it was */
1591 case MackieControlProtocol::Dynamics:
1595 /* leave it as it was */
1600 case MackieControlProtocol::Sends:
1602 setup_sends_vpot (r);
1604 /* leave it as it was */
1608 case MackieControlProtocol::TrackView:
1610 setup_trackview_vpot (r);
1612 /* leave it as it was */
1620 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1626 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1627 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1628 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1629 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1630 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1631 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1633 uint32_t pos = _surface->mcp().global_index (*this);
1635 /* we will control the pos-th available parameter, from the list in the
1636 * order shown above.
1639 vector<boost::shared_ptr<AutomationControl> > available;
1640 vector<AutomationType> params;
1642 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1643 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1644 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1645 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1646 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1647 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1649 if (pos >= available.size()) {
1650 /* this knob is not needed to control the available parameters */
1651 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1652 pending_display[0] = string();
1653 pending_display[1] = string();
1657 boost::shared_ptr<AutomationControl> pc;
1658 AutomationType param;
1660 pc = available[pos];
1661 param = params[pos];
1663 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
1664 _vpot->set_control (pc);
1674 pot_id = r->comp_speed_name (mc->get_value());
1695 if (!pot_id.empty()) {
1696 pending_display[0] = pot_id;
1698 pending_display[0] = string();
1701 notify_dyn_change (param, true, false);
1705 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1707 uint32_t bands = r->eq_band_cnt ();
1710 /* should never get here */
1714 /* figure out how many params per band are available */
1716 boost::shared_ptr<AutomationControl> pc;
1717 uint32_t params_per_band = 0;
1719 if ((pc = r->eq_gain_controllable (0))) {
1720 params_per_band += 1;
1722 if ((pc = r->eq_freq_controllable (0))) {
1723 params_per_band += 1;
1725 if ((pc = r->eq_q_controllable (0))) {
1726 params_per_band += 1;
1728 if ((pc = r->eq_shape_controllable (0))) {
1729 params_per_band += 1;
1732 /* pick the one for this strip, based on its global position across
1738 const uint32_t total_band_parameters = bands * params_per_band;
1739 const uint32_t global_pos = _surface->mcp().global_index (*this);
1740 AutomationType param = NullAutomation;
1745 if (global_pos < total_band_parameters) {
1747 /* show a parameter for an EQ band */
1749 const uint32_t parameter = global_pos % params_per_band;
1750 eq_band = global_pos / params_per_band;
1751 band_name = r->eq_band_name (eq_band);
1753 switch (parameter) {
1755 pc = r->eq_gain_controllable (eq_band);
1759 pc = r->eq_freq_controllable (eq_band);
1760 param = EQFrequency;
1763 pc = r->eq_q_controllable (eq_band);
1767 pc = r->eq_shape_controllable (eq_band);
1774 /* show a non-band parameter (HPF or enable)
1777 uint32_t parameter = global_pos - total_band_parameters;
1779 switch (parameter) {
1780 case 0: /* first control after band parameters */
1781 pc = r->eq_hpf_controllable();
1784 case 1: /* second control after band parameters */
1785 pc = r->eq_enable_controllable();
1789 /* nothing to control */
1790 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1791 pending_display[0] = string();
1792 pending_display[1] = string();
1801 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1802 _vpot->set_control (pc);
1808 pot_id = band_name + "Gain";
1811 pot_id = band_name + "Freq";
1814 pot_id = band_name + " Q";
1817 pot_id = band_name + " Shp";
1829 if (!pot_id.empty()) {
1830 pending_display[0] = pot_id;
1832 pending_display[0] = string();
1835 notify_eq_change (param, eq_band, true);
1840 Strip::setup_sends_vpot (boost::shared_ptr<Route> r)
1846 const uint32_t global_pos = _surface->mcp().global_index (*this);
1848 boost::shared_ptr<AutomationControl> pc = r->send_level_controllable (global_pos);
1851 pending_display[0] = string();
1852 pending_display[1] = string();
1856 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_send_level_change, this, BusSendLevel, global_pos, false), ui_context());
1857 _vpot->set_control (pc);
1859 pending_display[0] = r->send_name (global_pos);
1861 notify_send_level_change (BusSendLevel, global_pos, true);
1865 Strip::setup_trackview_vpot (boost::shared_ptr<Route> r)
1871 const uint32_t global_pos = _surface->mcp().global_index (*this);
1873 if (global_pos >= 8) {
1874 pending_display[0] = string();
1875 pending_display[1] = string();
1879 boost::shared_ptr<AutomationControl> pc;
1880 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (r);
1883 switch (global_pos) {
1885 pc = r->trim_control ();
1887 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, TrimAutomation, global_pos, false), ui_context());
1888 pending_display[0] = "Trim";
1889 notify_trackview_change (TrimAutomation, global_pos, true);
1894 pc = track->monitoring_control();
1896 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, MonitoringAutomation, global_pos, false), ui_context());
1897 pending_display[0] = "Mon";
1898 notify_trackview_change (MonitoringAutomation, global_pos, true);
1903 pc = r->solo_isolate_control ();
1905 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, SoloIsolateAutomation, global_pos, false), ui_context());
1906 notify_trackview_change (SoloIsolateAutomation, global_pos, true);
1907 pending_display[0] = "S-Iso";
1911 pc = r->solo_safe_control ();
1913 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, SoloSafeAutomation, global_pos, false), ui_context());
1914 notify_trackview_change (SoloSafeAutomation, global_pos, true);
1915 pending_display[0] = "S-Safe";
1919 //pc = r->trim_control ();
1922 // pc = r->trim_control ();
1925 // pc = r->trim_control ();
1928 // pc = r->trim_control ();
1933 pending_display[0] = string();
1934 pending_display[1] = string();
1938 _vpot->set_control (pc);
1942 Strip::set_vpot_parameter (AutomationType p)
1944 if (!_route || (p == NullAutomation)) {
1945 control_by_parameter[vpot_parameter] = 0;
1946 vpot_parameter = NullAutomation;
1947 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1948 pending_display[1] = string();
1952 boost::shared_ptr<AutomationControl> pan_control;
1954 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1956 reset_saved_values ();
1958 /* unset any mapping between the vpot and any existing parameters */
1960 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1962 if (i != control_by_parameter.end() && i->second == _vpot) {
1968 case PanAzimuthAutomation:
1969 if ((pan_control = _route->pan_azimuth_control ())) {
1970 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1971 _pan_mode = PanAzimuthAutomation;
1972 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1973 /* gain to vpot, pan azi to fader */
1974 _vpot->set_control (_route->gain_control());
1975 vpot_parameter = GainAutomation;
1976 control_by_parameter[GainAutomation] = _vpot;
1977 _fader->set_control (pan_control);
1978 control_by_parameter[PanAzimuthAutomation] = _fader;
1980 _fader->set_control (boost::shared_ptr<AutomationControl>());
1981 control_by_parameter[PanAzimuthAutomation] = 0;
1984 /* gain to fader, pan azi to vpot */
1985 vpot_parameter = PanAzimuthAutomation;
1986 _fader->set_control (_route->gain_control());
1987 control_by_parameter[GainAutomation] = _fader;
1988 _vpot->set_control (pan_control);
1989 control_by_parameter[PanAzimuthAutomation] = _vpot;
1992 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1993 control_by_parameter[PanAzimuthAutomation] = 0;
1997 case PanWidthAutomation:
1998 if ((pan_control = _route->pan_width_control ())) {
1999 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2000 _pan_mode = PanWidthAutomation;
2001 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2002 /* gain to vpot, pan width to fader */
2003 _vpot->set_control (_route->gain_control());
2004 vpot_parameter = GainAutomation;
2005 control_by_parameter[GainAutomation] = _vpot;
2006 _fader->set_control (pan_control);
2007 control_by_parameter[PanWidthAutomation] = _fader;
2009 _fader->set_control (boost::shared_ptr<AutomationControl>());
2010 control_by_parameter[PanWidthAutomation] = 0;
2013 /* gain to fader, pan width to vpot */
2014 vpot_parameter = PanWidthAutomation;
2015 _fader->set_control (_route->gain_control());
2016 control_by_parameter[GainAutomation] = _fader;
2017 _vpot->set_control (pan_control);
2018 control_by_parameter[PanWidthAutomation] = _vpot;
2021 _vpot->set_control (boost::shared_ptr<AutomationControl>());
2022 control_by_parameter[PanWidthAutomation] = 0;
2026 case PanElevationAutomation:
2028 case PanFrontBackAutomation:
2030 case PanLFEAutomation:
2032 case TrimAutomation:
2033 _trim_mode = TrimAutomation;
2034 vpot_parameter = TrimAutomation;
2035 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2036 /* gain to vpot, trim to fader */
2037 _vpot->set_control (_route->gain_control());
2038 control_by_parameter[GainAutomation] = _vpot;
2039 if (_route->trim() && route()->trim()->active()) {
2040 _fader->set_control (_route->trim_control());
2041 control_by_parameter[TrimAutomation] = _fader;
2043 _fader->set_control (boost::shared_ptr<AutomationControl>());
2044 control_by_parameter[TrimAutomation] = 0;
2047 /* gain to fader, trim to vpot */
2048 _fader->set_control (_route->gain_control());
2049 control_by_parameter[GainAutomation] = _fader;
2050 if (_route->trim() && route()->trim()->active()) {
2051 _vpot->set_control (_route->trim_control());
2052 control_by_parameter[TrimAutomation] = _vpot;
2054 _vpot->set_control (boost::shared_ptr<AutomationControl>());
2055 control_by_parameter[TrimAutomation] = 0;
2059 case PhaseAutomation:
2060 _trim_mode = PhaseAutomation;
2061 vpot_parameter = PhaseAutomation;
2062 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2063 /* gain to vpot, phase to fader */
2064 _vpot->set_control (_route->gain_control());
2065 control_by_parameter[GainAutomation] = _vpot;
2066 if (_route->phase_invert().size()) {
2067 _fader->set_control (_route->phase_control());
2068 control_by_parameter[PhaseAutomation] = _fader;
2070 _fader->set_control (boost::shared_ptr<AutomationControl>());
2071 control_by_parameter[PhaseAutomation] = 0;
2074 /* gain to fader, phase to vpot */
2075 _fader->set_control (_route->gain_control());
2076 control_by_parameter[GainAutomation] = _fader;
2077 if (_route->phase_invert().size()) {
2078 _vpot->set_control (_route->phase_control());
2079 control_by_parameter[PhaseAutomation] = _vpot;
2081 _vpot->set_control (boost::shared_ptr<AutomationControl>());
2082 control_by_parameter[PhaseAutomation] = 0;
2087 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
2092 pending_display[1] = vpot_mode_string ();
2096 Strip::is_midi_track () const
2098 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
2102 Strip::reset_saved_values ()
2104 _last_pan_azi_position_written = -1.0;
2105 _last_pan_width_position_written = -1.0;
2106 _last_gain_position_written = -1.0;
2107 _last_trim_position_written = -1.0;
2112 Strip::notify_metering_state_changed()
2114 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
2118 if (!_route || !_meter) {
2122 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
2123 bool metering_active = _surface->mcp().metering_active ();
2125 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
2129 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
2131 if (!transport_is_rolling || !metering_active) {
2132 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
2133 notify_panner_azi_changed (true);
2136 _transport_is_rolling = transport_is_rolling;
2137 _metering_active = metering_active;