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), Controllable::UseGroup);
1237 ac->set_value (max (ac->lower(), ac->get_value() - 1.0), Controllable::UseGroup);
1242 double p = pot.get_value ();
1244 // fader and pot should be the same and fader is hard coded 0 -> 1
1252 Strip::periodic (ARDOUR::microseconds_t now)
1255 update_automation ();
1259 Strip::redisplay (ARDOUR::microseconds_t now, bool force)
1261 if (_block_screen_redisplay_until >= now) {
1262 /* no drawing allowed */
1266 if (_block_screen_redisplay_until) {
1267 /* we were blocked, but the time period has elapsed, so we must
1271 _block_screen_redisplay_until = 0;
1274 if (force || (current_display[0] != pending_display[0])) {
1275 _surface->write (display (0, pending_display[0]));
1276 current_display[0] = pending_display[0];
1279 if (return_to_vpot_mode_display_at <= now) {
1280 return_to_vpot_mode_display_at = UINT64_MAX;
1281 return_to_vpot_mode_display ();
1284 if (force || (current_display[1] != pending_display[1])) {
1285 _surface->write (display (1, pending_display[1]));
1286 current_display[1] = pending_display[1];
1291 Strip::update_automation ()
1297 ARDOUR::AutoState state = _route->gain_control()->automation_state();
1299 if (state == Touch || state == Play) {
1300 notify_gain_changed (false);
1303 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1305 state = pan_control->automation_state ();
1306 if (state == Touch || state == Play) {
1307 notify_panner_azi_changed (false);
1311 pan_control = _route->pan_width_control ();
1313 state = pan_control->automation_state ();
1314 if (state == Touch || state == Play) {
1315 notify_panner_width_changed (false);
1319 if (_route->trim() && route()->trim()->active()) {
1320 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1321 if (trim_state == Touch || trim_state == Play) {
1322 notify_trim_changed (false);
1328 Strip::update_meter ()
1334 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1338 if (_meter && _transport_is_rolling && _metering_active) {
1339 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1340 _meter->send_update (*_surface, dB);
1348 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1349 _surface->write ((*it)->zero ());
1352 _surface->write (blank_display (0));
1353 _surface->write (blank_display (1));
1354 pending_display[0] = string();
1355 pending_display[1] = string();
1356 current_display[0] = string();
1357 current_display[1] = string();
1361 Strip::blank_display (uint32_t line_number)
1363 return display (line_number, string());
1367 Strip::display (uint32_t line_number, const std::string& line)
1369 assert (line_number <= 1);
1371 MidiByteArray retval;
1373 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1376 retval << _surface->sysex_hdr();
1380 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1381 retval << (_index * 7 + (line_number * 0x38));
1383 // ascii data to display. @param line is UTF-8
1384 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1385 string::size_type len = ascii.length();
1387 ascii = ascii.substr (0, 6);
1391 // pad with " " out to 6 chars
1392 for (int i = len; i < 6; ++i) {
1396 // column spacer, unless it's the right-hand column
1402 retval << MIDI::eox;
1408 Strip::lock_controls ()
1410 _controls_locked = true;
1414 Strip::unlock_controls ()
1416 _controls_locked = false;
1420 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1422 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1423 if ((*i) == _route) {
1424 _surface->write (_select->set_state (on));
1429 _surface->write (_select->set_state (off));
1433 Strip::vpot_mode_string ()
1435 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1440 if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1442 } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1444 } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1445 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1446 } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1448 } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1450 } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1452 } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1454 } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1458 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1466 Strip::potmode_changed (bool notify)
1473 int pm = _surface->mcp().pot_mode();
1475 case MackieControlProtocol::Pan:
1476 // This needs to set current pan mode (azimuth or width... or whatever)
1477 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1478 set_vpot_parameter (_pan_mode);
1488 Strip::block_screen_display_for (uint32_t msecs)
1490 _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1494 Strip::block_vpot_mode_display_for (uint32_t msecs)
1496 return_to_vpot_mode_display_at = ARDOUR::get_microseconds() + (msecs * 1000);
1500 Strip::return_to_vpot_mode_display ()
1502 /* returns the second line of the two-line per-strip display
1503 back the mode where it shows what the VPot controls.
1506 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1507 /* do nothing - second line shows value of current subview parameter */
1509 } else if (_route) {
1510 pending_display[1] = vpot_mode_string();
1512 pending_display[1] = string();
1517 Strip::next_pot_mode ()
1519 vector<AutomationType>::iterator i;
1521 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1522 /* do not change vpot mode while in flipped mode */
1523 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1524 pending_display[1] = "Flip";
1525 block_vpot_mode_display_for (1000);
1530 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1537 if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1539 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
1543 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1544 if ((*i) == ac->parameter().type()) {
1549 /* move to the next mode in the list, or back to the start (which will
1550 also happen if the current mode is not in the current pot mode list)
1553 if (i != possible_pot_parameters.end()) {
1557 if (i == possible_pot_parameters.end()) {
1558 i = possible_pot_parameters.begin();
1561 set_vpot_parameter (*i);
1566 Strip::subview_mode_changed ()
1568 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1570 subview_connections.drop_connections ();
1572 switch (_surface->mcp().subview_mode()) {
1573 case MackieControlProtocol::None:
1574 set_vpot_parameter (vpot_parameter);
1575 /* need to show strip name again */
1577 notify_metering_state_changed ();
1581 case MackieControlProtocol::EQ:
1585 /* leave it as it was */
1589 case MackieControlProtocol::Dynamics:
1593 /* leave it as it was */
1598 case MackieControlProtocol::Sends:
1600 setup_sends_vpot (r);
1602 /* leave it as it was */
1606 case MackieControlProtocol::TrackView:
1608 setup_trackview_vpot (r);
1610 /* leave it as it was */
1618 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1624 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1625 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1626 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1627 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1628 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1629 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1631 uint32_t pos = _surface->mcp().global_index (*this);
1633 /* we will control the pos-th available parameter, from the list in the
1634 * order shown above.
1637 vector<boost::shared_ptr<AutomationControl> > available;
1638 vector<AutomationType> params;
1640 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1641 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1642 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1643 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1644 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1645 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1647 if (pos >= available.size()) {
1648 /* this knob is not needed to control the available parameters */
1649 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1650 pending_display[0] = string();
1651 pending_display[1] = string();
1655 boost::shared_ptr<AutomationControl> pc;
1656 AutomationType param;
1658 pc = available[pos];
1659 param = params[pos];
1661 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
1662 _vpot->set_control (pc);
1672 pot_id = r->comp_speed_name (mc->get_value());
1693 if (!pot_id.empty()) {
1694 pending_display[0] = pot_id;
1696 pending_display[0] = string();
1699 notify_dyn_change (param, true, false);
1703 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1705 uint32_t bands = r->eq_band_cnt ();
1708 /* should never get here */
1712 /* figure out how many params per band are available */
1714 boost::shared_ptr<AutomationControl> pc;
1715 uint32_t params_per_band = 0;
1717 if ((pc = r->eq_gain_controllable (0))) {
1718 params_per_band += 1;
1720 if ((pc = r->eq_freq_controllable (0))) {
1721 params_per_band += 1;
1723 if ((pc = r->eq_q_controllable (0))) {
1724 params_per_band += 1;
1726 if ((pc = r->eq_shape_controllable (0))) {
1727 params_per_band += 1;
1730 /* pick the one for this strip, based on its global position across
1736 const uint32_t total_band_parameters = bands * params_per_band;
1737 const uint32_t global_pos = _surface->mcp().global_index (*this);
1738 AutomationType param = NullAutomation;
1743 if (global_pos < total_band_parameters) {
1745 /* show a parameter for an EQ band */
1747 const uint32_t parameter = global_pos % params_per_band;
1748 eq_band = global_pos / params_per_band;
1749 band_name = r->eq_band_name (eq_band);
1751 switch (parameter) {
1753 pc = r->eq_gain_controllable (eq_band);
1757 pc = r->eq_freq_controllable (eq_band);
1758 param = EQFrequency;
1761 pc = r->eq_q_controllable (eq_band);
1765 pc = r->eq_shape_controllable (eq_band);
1772 /* show a non-band parameter (HPF or enable)
1775 uint32_t parameter = global_pos - total_band_parameters;
1777 switch (parameter) {
1778 case 0: /* first control after band parameters */
1779 pc = r->eq_hpf_controllable();
1782 case 1: /* second control after band parameters */
1783 pc = r->eq_enable_controllable();
1787 /* nothing to control */
1788 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1789 pending_display[0] = string();
1790 pending_display[1] = string();
1799 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1800 _vpot->set_control (pc);
1806 pot_id = band_name + "Gain";
1809 pot_id = band_name + "Freq";
1812 pot_id = band_name + " Q";
1815 pot_id = band_name + " Shp";
1827 if (!pot_id.empty()) {
1828 pending_display[0] = pot_id;
1830 pending_display[0] = string();
1833 notify_eq_change (param, eq_band, true);
1838 Strip::setup_sends_vpot (boost::shared_ptr<Route> r)
1844 const uint32_t global_pos = _surface->mcp().global_index (*this);
1846 boost::shared_ptr<AutomationControl> pc = r->send_level_controllable (global_pos);
1849 pending_display[0] = string();
1850 pending_display[1] = string();
1854 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_send_level_change, this, BusSendLevel, global_pos, false), ui_context());
1855 _vpot->set_control (pc);
1857 pending_display[0] = r->send_name (global_pos);
1859 notify_send_level_change (BusSendLevel, global_pos, true);
1863 Strip::setup_trackview_vpot (boost::shared_ptr<Route> r)
1869 const uint32_t global_pos = _surface->mcp().global_index (*this);
1871 if (global_pos >= 8) {
1872 pending_display[0] = string();
1873 pending_display[1] = string();
1877 boost::shared_ptr<AutomationControl> pc;
1878 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (r);
1881 switch (global_pos) {
1883 pc = r->trim_control ();
1885 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, TrimAutomation, global_pos, false), ui_context());
1886 pending_display[0] = "Trim";
1887 notify_trackview_change (TrimAutomation, global_pos, true);
1892 pc = track->monitoring_control();
1894 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, MonitoringAutomation, global_pos, false), ui_context());
1895 pending_display[0] = "Mon";
1896 notify_trackview_change (MonitoringAutomation, global_pos, true);
1901 pc = r->solo_isolate_control ();
1903 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, SoloIsolateAutomation, global_pos, false), ui_context());
1904 notify_trackview_change (SoloIsolateAutomation, global_pos, true);
1905 pending_display[0] = "S-Iso";
1909 pc = r->solo_safe_control ();
1911 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trackview_change, this, SoloSafeAutomation, global_pos, false), ui_context());
1912 notify_trackview_change (SoloSafeAutomation, global_pos, true);
1913 pending_display[0] = "S-Safe";
1917 //pc = r->trim_control ();
1920 // pc = r->trim_control ();
1923 // pc = r->trim_control ();
1926 // pc = r->trim_control ();
1931 pending_display[0] = string();
1932 pending_display[1] = string();
1936 _vpot->set_control (pc);
1940 Strip::set_vpot_parameter (AutomationType p)
1942 if (!_route || (p == NullAutomation)) {
1943 control_by_parameter[vpot_parameter] = 0;
1944 vpot_parameter = NullAutomation;
1945 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1946 pending_display[1] = string();
1950 boost::shared_ptr<AutomationControl> pan_control;
1952 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1954 reset_saved_values ();
1956 /* unset any mapping between the vpot and any existing parameters */
1958 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1960 if (i != control_by_parameter.end() && i->second == _vpot) {
1966 case PanAzimuthAutomation:
1967 if ((pan_control = _route->pan_azimuth_control ())) {
1968 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1969 _pan_mode = PanAzimuthAutomation;
1970 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1971 /* gain to vpot, pan azi to fader */
1972 _vpot->set_control (_route->gain_control());
1973 vpot_parameter = GainAutomation;
1974 control_by_parameter[GainAutomation] = _vpot;
1975 _fader->set_control (pan_control);
1976 control_by_parameter[PanAzimuthAutomation] = _fader;
1978 _fader->set_control (boost::shared_ptr<AutomationControl>());
1979 control_by_parameter[PanAzimuthAutomation] = 0;
1982 /* gain to fader, pan azi to vpot */
1983 vpot_parameter = PanAzimuthAutomation;
1984 _fader->set_control (_route->gain_control());
1985 control_by_parameter[GainAutomation] = _fader;
1986 _vpot->set_control (pan_control);
1987 control_by_parameter[PanAzimuthAutomation] = _vpot;
1990 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1991 control_by_parameter[PanAzimuthAutomation] = 0;
1995 case PanWidthAutomation:
1996 if ((pan_control = _route->pan_width_control ())) {
1997 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1998 _pan_mode = PanWidthAutomation;
1999 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2000 /* gain to vpot, pan width to fader */
2001 _vpot->set_control (_route->gain_control());
2002 vpot_parameter = GainAutomation;
2003 control_by_parameter[GainAutomation] = _vpot;
2004 _fader->set_control (pan_control);
2005 control_by_parameter[PanWidthAutomation] = _fader;
2007 _fader->set_control (boost::shared_ptr<AutomationControl>());
2008 control_by_parameter[PanWidthAutomation] = 0;
2011 /* gain to fader, pan width to vpot */
2012 vpot_parameter = PanWidthAutomation;
2013 _fader->set_control (_route->gain_control());
2014 control_by_parameter[GainAutomation] = _fader;
2015 _vpot->set_control (pan_control);
2016 control_by_parameter[PanWidthAutomation] = _vpot;
2019 _vpot->set_control (boost::shared_ptr<AutomationControl>());
2020 control_by_parameter[PanWidthAutomation] = 0;
2024 case PanElevationAutomation:
2026 case PanFrontBackAutomation:
2028 case PanLFEAutomation:
2030 case TrimAutomation:
2031 _trim_mode = TrimAutomation;
2032 vpot_parameter = TrimAutomation;
2033 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2034 /* gain to vpot, trim to fader */
2035 _vpot->set_control (_route->gain_control());
2036 control_by_parameter[GainAutomation] = _vpot;
2037 if (_route->trim() && route()->trim()->active()) {
2038 _fader->set_control (_route->trim_control());
2039 control_by_parameter[TrimAutomation] = _fader;
2041 _fader->set_control (boost::shared_ptr<AutomationControl>());
2042 control_by_parameter[TrimAutomation] = 0;
2045 /* gain to fader, trim to vpot */
2046 _fader->set_control (_route->gain_control());
2047 control_by_parameter[GainAutomation] = _fader;
2048 if (_route->trim() && route()->trim()->active()) {
2049 _vpot->set_control (_route->trim_control());
2050 control_by_parameter[TrimAutomation] = _vpot;
2052 _vpot->set_control (boost::shared_ptr<AutomationControl>());
2053 control_by_parameter[TrimAutomation] = 0;
2057 case PhaseAutomation:
2058 _trim_mode = PhaseAutomation;
2059 vpot_parameter = PhaseAutomation;
2060 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
2061 /* gain to vpot, phase to fader */
2062 _vpot->set_control (_route->gain_control());
2063 control_by_parameter[GainAutomation] = _vpot;
2064 if (_route->phase_invert().size()) {
2065 _fader->set_control (_route->phase_control());
2066 control_by_parameter[PhaseAutomation] = _fader;
2068 _fader->set_control (boost::shared_ptr<AutomationControl>());
2069 control_by_parameter[PhaseAutomation] = 0;
2072 /* gain to fader, phase to vpot */
2073 _fader->set_control (_route->gain_control());
2074 control_by_parameter[GainAutomation] = _fader;
2075 if (_route->phase_invert().size()) {
2076 _vpot->set_control (_route->phase_control());
2077 control_by_parameter[PhaseAutomation] = _vpot;
2079 _vpot->set_control (boost::shared_ptr<AutomationControl>());
2080 control_by_parameter[PhaseAutomation] = 0;
2085 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
2090 pending_display[1] = vpot_mode_string ();
2094 Strip::is_midi_track () const
2096 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
2100 Strip::reset_saved_values ()
2102 _last_pan_azi_position_written = -1.0;
2103 _last_pan_width_position_written = -1.0;
2104 _last_gain_position_written = -1.0;
2105 _last_trim_position_written = -1.0;
2110 Strip::notify_metering_state_changed()
2112 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
2116 if (!_route || !_meter) {
2120 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
2121 bool metering_active = _surface->mcp().metering_active ();
2123 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
2127 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
2129 if (!transport_is_rolling || !metering_active) {
2130 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
2131 notify_panner_azi_changed (true);
2134 _transport_is_rolling = transport_is_rolling;
2135 _metering_active = metering_active;