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.
27 #include <glibmm/convert.h>
29 #include "midi++/port.h"
31 #include "pbd/compose.h"
32 #include "pbd/convert.h"
34 #include "ardour/amp.h"
35 #include "ardour/bundle.h"
36 #include "ardour/debug.h"
37 #include "ardour/midi_ui.h"
38 #include "ardour/meter.h"
39 #include "ardour/plugin_insert.h"
40 #include "ardour/pannable.h"
41 #include "ardour/panner.h"
42 #include "ardour/panner_shell.h"
43 #include "ardour/rc_configuration.h"
44 #include "ardour/route.h"
45 #include "ardour/session.h"
46 #include "ardour/send.h"
47 #include "ardour/track.h"
48 #include "ardour/midi_track.h"
49 #include "ardour/user_bundle.h"
50 #include "ardour/profile.h"
52 #include "mackie_control_protocol.h"
53 #include "surface_port.h"
64 using namespace ARDOUR;
66 using namespace ArdourSurface;
67 using namespace Mackie;
69 #ifndef timeradd /// only avail with __USE_BSD
70 #define timeradd(a,b,result) \
72 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
73 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
74 if ((result)->tv_usec >= 1000000) \
77 (result)->tv_usec -= 1000000; \
82 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
84 Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
97 , _controls_locked (false)
98 , _transport_is_rolling (false)
99 , _metering_active (true)
100 , _block_vpot_mode_redisplay_until (0)
101 , _block_screen_redisplay_until (0)
103 , _pan_mode (PanAzimuthAutomation)
104 , _trim_mode (TrimAutomation)
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)
111 , redisplay_requests (256)
113 _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
114 _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
116 if (s.mcp().device_info().has_meters()) {
117 _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
120 for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
121 Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
122 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
123 _surface->number(), index, Button::id_to_name (bb->bid()),
124 bb->id(), b->second.base_id));
130 /* surface is responsible for deleting all controls */
134 Strip::add (Control & control)
138 Group::add (control);
140 /* fader, vpot, meter were all set explicitly */
142 if ((button = dynamic_cast<Button*>(&control)) != 0) {
143 switch (button->bid()) {
144 case Button::RecEnable:
156 case Button::VSelect:
159 case Button::FaderTouch:
160 _fader_touch = button;
169 Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
171 if (_controls_locked) {
175 mb_pan_controllable.reset();
177 route_connections.drop_connections ();
179 _solo->set_control (boost::shared_ptr<AutomationControl>());
180 _mute->set_control (boost::shared_ptr<AutomationControl>());
181 _select->set_control (boost::shared_ptr<AutomationControl>());
182 _recenable->set_control (boost::shared_ptr<AutomationControl>());
183 _fader->set_control (boost::shared_ptr<AutomationControl>());
184 _vpot->set_control (boost::shared_ptr<AutomationControl>());
188 control_by_parameter.clear ();
190 control_by_parameter[PanAzimuthAutomation] = (Control*) 0;
191 control_by_parameter[PanWidthAutomation] = (Control*) 0;
192 control_by_parameter[PanElevationAutomation] = (Control*) 0;
193 control_by_parameter[PanFrontBackAutomation] = (Control*) 0;
194 control_by_parameter[PanLFEAutomation] = (Control*) 0;
195 control_by_parameter[GainAutomation] = (Control*) 0;
196 control_by_parameter[TrimAutomation] = (Control*) 0;
197 control_by_parameter[PhaseAutomation] = (Control*) 0;
198 control_by_parameter[SendAutomation] = (Control*) 0;
200 reset_saved_values ();
207 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
208 _surface->number(), _index, _route->name()));
210 _solo->set_control (_route->solo_control());
211 _mute->set_control (_route->mute_control());
213 _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
214 _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
216 _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
218 if (_route->trim() && route()->trim()->active()) {
219 _route->trim_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trim_changed, this, false), ui_context());
222 if (_route->phase_invert().size()) {
223 _route->phase_invert_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_phase_changed, this, false), ui_context());
224 _route->phase_control()->set_channel(0);
227 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control();
229 pan_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
232 pan_control = _route->pan_width_control();
234 pan_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
237 _route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
238 _route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
240 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
243 _recenable->set_control (trk->rec_enable_control());
244 trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
247 // TODO this works when a currently-banked route is made inactive, but not
248 // when a route is activated which should be currently banked.
250 _route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
251 _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
253 /* setup legal VPot modes for this route */
255 possible_pot_parameters.clear();
257 if (_route->pan_azimuth_control()) {
258 possible_pot_parameters.push_back (PanAzimuthAutomation);
260 if (_route->pan_width_control()) {
261 possible_pot_parameters.push_back (PanWidthAutomation);
263 if (_route->pan_elevation_control()) {
264 possible_pot_parameters.push_back (PanElevationAutomation);
266 if (_route->pan_frontback_control()) {
267 possible_pot_parameters.push_back (PanFrontBackAutomation);
269 if (_route->pan_lfe_control()) {
270 possible_pot_parameters.push_back (PanLFEAutomation);
273 if (_route->trim() && route()->trim()->active()) {
274 possible_pot_parameters.push_back (TrimAutomation);
277 possible_trim_parameters.clear();
279 if (_route->trim() && route()->trim()->active()) {
280 possible_trim_parameters.push_back (TrimAutomation);
281 _trim_mode = TrimAutomation;
284 if (_route->phase_invert().size()) {
285 possible_trim_parameters.push_back (PhaseAutomation);
286 _route->phase_control()->set_channel(0);
287 if (_trim_mode != TrimAutomation) {
288 _trim_mode = PhaseAutomation;
293 _pan_mode = PanAzimuthAutomation;
294 potmode_changed (false);
307 notify_solo_changed ();
308 notify_mute_changed ();
309 notify_gain_changed ();
310 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
311 notify_panner_azi_changed ();
312 notify_panner_width_changed ();
313 notify_record_enable_changed ();
314 notify_trim_changed ();
315 notify_phase_changed ();
316 notify_processor_changed ();
320 Strip::notify_solo_changed ()
322 if (_route && _solo) {
323 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
328 Strip::notify_mute_changed ()
330 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
331 if (_route && _mute) {
332 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
333 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
335 _surface->write (_mute->set_state (_route->muted() ? on : off));
340 Strip::notify_record_enable_changed ()
342 if (_route && _recenable) {
343 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
348 Strip::notify_active_changed ()
350 _surface->mcp().refresh_current_bank();
354 Strip::notify_route_deleted ()
356 _surface->mcp().refresh_current_bank();
360 Strip::notify_gain_changed (bool force_update)
366 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
372 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
374 float gain_coefficient = ac->get_value();
375 float normalized_position = ac->internal_to_interface (gain_coefficient);
378 if (force_update || normalized_position != _last_gain_position_written) {
380 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
381 if (!control->in_use()) {
382 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
384 queue_parameter_display (GainAutomation, gain_coefficient);
386 if (!control->in_use()) {
387 _surface->write (_fader->set_position (normalized_position));
389 queue_parameter_display (GainAutomation, gain_coefficient);
392 _last_gain_position_written = normalized_position;
398 Strip::notify_trim_changed (bool force_update)
402 if (!_route->trim() || !route()->trim()->active()) {
403 _surface->write (_vpot->zero());
406 Control* control = 0;
407 ControlParameterMap::iterator i = control_by_parameter.find (TrimAutomation);
409 if (i == control_by_parameter.end()) {
415 boost::shared_ptr<AutomationControl> ac = _route->trim_control();
417 float gain_coefficient = ac->get_value();
418 float normalized_position = ac->internal_to_interface (gain_coefficient);
420 if (force_update || normalized_position != _last_trim_position_written) {
421 if (control == _fader) {
422 if (!_fader->in_use()) {
423 _surface->write (_fader->set_position (normalized_position));
424 queue_parameter_display (TrimAutomation, gain_coefficient);
426 } else if (control == _vpot) {
427 _surface->write (_vpot->set (normalized_position, true, Pot::dot));
428 queue_parameter_display (TrimAutomation, gain_coefficient);
430 _last_trim_position_written = normalized_position;
436 Strip::notify_phase_changed (bool force_update)
439 if (!_route->phase_invert().size()) {
440 _surface->write (_vpot->zero());
444 Control* control = 0;
445 ControlParameterMap::iterator i = control_by_parameter.find (PhaseAutomation);
447 if (i == control_by_parameter.end()) {
453 float normalized_position = _route->phase_control()->get_value();
455 if (control == _fader) {
456 if (!_fader->in_use()) {
457 _surface->write (_fader->set_position (normalized_position));
458 queue_parameter_display (PhaseAutomation, normalized_position);
460 } else if (control == _vpot) {
461 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
462 queue_parameter_display (PhaseAutomation, normalized_position);
468 Strip::notify_processor_changed (bool force_update)
471 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
473 _surface->write (_vpot->zero());
477 Control* control = 0;
478 ControlParameterMap::iterator i = control_by_parameter.find (SendAutomation);
480 if (i == control_by_parameter.end()) {
486 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
487 boost::shared_ptr<Amp> a = s->amp();
488 boost::shared_ptr<AutomationControl> ac = a->gain_control();
490 float gain_coefficient = ac->get_value();
491 float normalized_position = ac->internal_to_interface (gain_coefficient);
493 if (control == _fader) {
494 if (!_fader->in_use()) {
495 _surface->write (_fader->set_position (normalized_position));
496 queue_parameter_display (SendAutomation, gain_coefficient);
498 } else if (control == _vpot) {
499 _surface->write (_vpot->set (normalized_position, true, Pot::dot));
500 queue_parameter_display (SendAutomation, gain_coefficient);
506 Strip::notify_property_changed (const PropertyChange& what_changed)
508 if (!what_changed.contains (ARDOUR::Properties::name)) {
516 Strip::show_route_name ()
518 MackieControlProtocol::SubViewMode svm = _surface->mcp().subview_mode();
520 if (svm != MackieControlProtocol::None) {
521 /* subview mode is responsible for upper line */
529 string fullname = _route->name();
531 if (fullname.length() <= 6) {
534 line1 = PBD::short_version (fullname, 6);
537 _surface->write (display (0, line1));
541 Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
543 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
546 /* not in subview mode */
550 if (_surface->mcp().subview_mode() != MackieControlProtocol::EQ) {
551 /* no longer in EQ subview mode */
555 boost::shared_ptr<AutomationControl> control;
559 control = r->eq_gain_controllable (band);
562 control = r->eq_freq_controllable (band);
565 control = r->eq_q_controllable (band);
568 control = r->eq_shape_controllable (band);
571 control = r->eq_hpf_controllable ();
574 control = r->eq_enable_controllable ();
581 float val = control->get_value();
582 queue_parameter_display (type, val);
583 /* update pot/encoder */
584 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
589 Strip::notify_dyn_change (AutomationType type, bool force_update)
591 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
594 /* not in subview mode */
598 if (_surface->mcp().subview_mode() != MackieControlProtocol::Dynamics) {
599 /* no longer in EQ subview mode */
603 boost::shared_ptr<AutomationControl> control;
607 control = r->comp_threshold_controllable ();
610 control = r->comp_speed_controllable ();
613 control = r->comp_mode_controllable ();
616 control = r->comp_makeup_controllable ();
619 control = r->comp_redux_controllable ();
622 control = r->comp_enable_controllable ();
629 float val = control->get_value();
630 queue_parameter_display (type, val);
631 /* update pot/encoder */
632 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
637 Strip::notify_panner_azi_changed (bool force_update)
643 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
645 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
648 _surface->write (_vpot->zero());
652 Control* control = 0;
653 ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
655 if (i == control_by_parameter.end()) {
661 double normalized_pos = pan_control->internal_to_interface (pan_control->get_value());
662 double internal_pos = pan_control->get_value();
664 if (force_update || (normalized_pos != _last_pan_azi_position_written)) {
666 if (control == _fader) {
667 if (!_fader->in_use()) {
668 _surface->write (_fader->set_position (normalized_pos));
669 /* show actual internal value to user */
670 queue_parameter_display (PanAzimuthAutomation, internal_pos);
672 } else if (control == _vpot) {
673 _surface->write (_vpot->set (normalized_pos, true, Pot::dot));
674 /* show actual internal value to user */
675 queue_parameter_display (PanAzimuthAutomation, internal_pos);
678 _last_pan_azi_position_written = normalized_pos;
683 Strip::notify_panner_width_changed (bool force_update)
689 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
691 boost::shared_ptr<AutomationControl> pan_control = _route->pan_width_control ();
694 _surface->write (_vpot->zero());
698 Control* control = 0;
699 ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
701 if (i == control_by_parameter.end()) {
707 double pos = pan_control->internal_to_interface (pan_control->get_value());
709 if (force_update || pos != _last_pan_width_position_written) {
711 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
713 if (control == _fader) {
714 if (!control->in_use()) {
715 _surface->write (_fader->set_position (pos));
716 queue_parameter_display (PanWidthAutomation, pos);
720 } else if (control == _vpot) {
721 _surface->write (_vpot->set (pos, true, Pot::spread));
722 queue_parameter_display (PanWidthAutomation, pos);
725 _last_pan_width_position_written = pos;
730 Strip::select_event (Button&, ButtonState bs)
732 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
736 int ms = _surface->mcp().main_modifier_state();
738 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
739 _controls_locked = !_controls_locked;
740 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
741 block_vpot_mode_display_for (1000);
745 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
746 /* reset to default */
747 boost::shared_ptr<AutomationControl> ac = _fader->control ();
749 ac->set_value (ac->normal());
754 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
755 _surface->mcp().add_down_select_button (_surface->number(), _index);
756 _surface->mcp().select_range ();
759 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
760 _surface->mcp().remove_down_select_button (_surface->number(), _index);
765 Strip::vselect_event (Button&, ButtonState bs)
769 int ms = _surface->mcp().main_modifier_state();
771 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
773 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
777 /* reset to default/normal value */
778 ac->set_value (ac->normal());
783 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
791 Strip::fader_touch_event (Button&, ButtonState bs)
793 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
797 boost::shared_ptr<AutomationControl> ac = _fader->control ();
799 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
801 ac->set_value (ac->normal());
805 _fader->set_in_use (true);
806 _fader->start_touch (_surface->mcp().transport_frame());
809 queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
815 _fader->set_in_use (false);
816 _fader->stop_touch (_surface->mcp().transport_frame(), true);
823 Strip::handle_button (Button& button, ButtonState bs)
825 boost::shared_ptr<AutomationControl> control;
828 button.set_in_use (true);
830 button.set_in_use (false);
833 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
835 switch (button.bid()) {
837 select_event (button, bs);
840 case Button::VSelect:
841 vselect_event (button, bs);
844 case Button::FaderTouch:
845 fader_touch_event (button, bs);
849 if ((control = button.control ())) {
851 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
852 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
855 int ms = _surface->mcp().main_modifier_state();
857 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
858 /* reset to default/normal value */
859 new_value = control->normal();
861 new_value = control->get_value() ? 0.0 : 1.0;
864 /* get all controls that either have their
865 * button down or are within a range of
866 * several down buttons
869 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
872 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
873 controls.size(), control->parameter().type(), new_value));
877 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
878 (*c)->set_value (new_value);
882 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
883 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
891 Strip::queue_parameter_display (AutomationType type, float val)
893 RedisplayRequest req;
898 redisplay_requests.write (&req, 1);
902 Strip::do_parameter_display (AutomationType type, float val)
904 bool screen_hold = false;
910 _surface->write (display (1, " -inf "));
912 float dB = accurate_coefficient_to_dB (val);
913 snprintf (buf, sizeof (buf), "%6.1f", dB);
914 _surface->write (display (1, buf));
919 case PanAzimuthAutomation:
920 if (Profile->get_mixbus()) {
921 snprintf (buf, sizeof (buf), "%2.1f", val);
922 _surface->write (display (1, buf));
926 boost::shared_ptr<Pannable> p = _route->pannable();
927 if (p && _route->panner()) {
928 string str =_route->panner()->value_as_string (p->pan_azimuth_control);
929 _surface->write (display (1, str));
936 case PanWidthAutomation:
938 snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
939 _surface->write (display (1, buf));
946 float dB = accurate_coefficient_to_dB (val);
947 snprintf (buf, sizeof (buf), "%6.1f", dB);
948 _surface->write (display (1, buf));
953 case PhaseAutomation:
955 if (_route->phase_control()->get_value() < 0.5) {
956 _surface->write (display (1, "Normal"));
958 _surface->write (display (1, "Invert"));
966 _surface->write (display (1, " -inf "));
968 float dB = accurate_coefficient_to_dB (val);
969 snprintf (buf, sizeof (buf), "%6.1f", dB);
970 _surface->write (display (1, buf));
983 snprintf (buf, sizeof (buf), "%6.1f", val);
984 _surface->write (display (1, buf));
990 _surface->write (display (1, "on"));
992 _surface->write (display (1, "off"));
996 if (_surface->mcp().subview_route()) {
997 _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
1005 block_vpot_mode_display_for (1000);
1010 Strip::handle_fader_touch (Fader& fader, bool touch_on)
1013 fader.start_touch (_surface->mcp().transport_frame());
1015 fader.stop_touch (_surface->mcp().transport_frame(), false);
1020 Strip::handle_fader (Fader& fader, float position)
1022 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
1023 boost::shared_ptr<AutomationControl> ac = fader.control();
1028 fader.set_value (position);
1030 /* From the Mackie Control MIDI implementation docs:
1032 In order to ensure absolute synchronization with the host software,
1033 Mackie Control uses a closed-loop servo system for the faders,
1034 meaning the faders will always move to their last received position.
1035 When a host receives a Fader Position Message, it must then
1036 re-transmit that message to the Mackie Control or else the faders
1037 will return to their last position.
1040 _surface->write (fader.set_position (position));
1044 Strip::handle_pot (Pot& pot, float delta)
1046 /* Pots only emit events when they move, not when they
1047 stop moving. So to get a stop event, we need to use a timeout.
1050 boost::shared_ptr<AutomationControl> ac = pot.control();
1054 double p = pot.get_value ();
1056 // fader and pot should be the same and fader is hard coded 0 -> 1
1063 Strip::periodic (ARDOUR::microseconds_t now)
1065 bool reshow_vpot_mode = false;
1066 bool reshow_name = false;
1072 if (_block_screen_redisplay_until >= now) {
1073 if (_surface->mcp().device_info().has_separate_meters()) {
1076 /* no drawing here, for now */
1079 } else if (_block_screen_redisplay_until) {
1081 /* timeout reached, reset */
1083 _block_screen_redisplay_until = 0;
1084 reshow_vpot_mode = true;
1088 if (_block_vpot_mode_redisplay_until >= now) {
1090 } else if (_block_vpot_mode_redisplay_until) {
1092 /* timeout reached, reset */
1094 _block_vpot_mode_redisplay_until = 0;
1095 reshow_vpot_mode = true;
1102 if (reshow_vpot_mode) {
1103 return_to_vpot_mode_display ();
1105 /* no point doing this if we just switched back to vpot mode
1107 update_automation ();
1115 Strip::redisplay (ARDOUR::microseconds_t now)
1117 RedisplayRequest req;
1118 bool have_request = false;
1120 while (redisplay_requests.read (&req, 1) == 1) {
1122 have_request = true;
1125 if (_block_screen_redisplay_until >= now) {
1130 do_parameter_display (req.type, req.val);
1135 Strip::update_automation ()
1141 ARDOUR::AutoState state = _route->gain_control()->automation_state();
1143 if (state == Touch || state == Play) {
1144 notify_gain_changed (false);
1147 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1149 state = pan_control->automation_state ();
1150 if (state == Touch || state == Play) {
1151 notify_panner_azi_changed (false);
1155 pan_control = _route->pan_width_control ();
1157 state = pan_control->automation_state ();
1158 if (state == Touch || state == Play) {
1159 notify_panner_width_changed (false);
1163 if (_route->trim() && route()->trim()->active()) {
1164 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1165 if (trim_state == Touch || trim_state == Play) {
1166 notify_trim_changed (false);
1172 Strip::update_meter ()
1174 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1178 if (_meter && _transport_is_rolling && _metering_active) {
1179 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1180 _meter->send_update (*_surface, dB);
1187 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1188 _surface->write ((*it)->zero ());
1191 _surface->write (blank_display (0));
1192 _surface->write (blank_display (1));
1196 Strip::blank_display (uint32_t line_number)
1198 return display (line_number, string());
1202 Strip::display (uint32_t line_number, const std::string& line)
1204 assert (line_number <= 1);
1206 MidiByteArray retval;
1208 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1211 retval << _surface->sysex_hdr();
1215 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1216 retval << (_index * 7 + (line_number * 0x38));
1218 // ascii data to display. @param line is UTF-8
1219 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1220 string::size_type len = ascii.length();
1222 ascii = ascii.substr (0, 6);
1226 // pad with " " out to 6 chars
1227 for (int i = len; i < 6; ++i) {
1231 // column spacer, unless it's the right-hand column
1237 retval << MIDI::eox;
1243 Strip::lock_controls ()
1245 _controls_locked = true;
1249 Strip::unlock_controls ()
1251 _controls_locked = false;
1255 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1257 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1258 if ((*i) == _route) {
1259 _surface->write (_select->set_state (on));
1264 _surface->write (_select->set_state (off));
1268 Strip::vpot_mode_string ()
1270 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1275 if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1277 } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1279 } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1280 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1281 } else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
1282 // should be bus name
1283 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1287 } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1289 } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1291 } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1293 } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1295 } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1299 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1307 Strip::potmode_changed (bool notify)
1314 int pm = _surface->mcp().pot_mode();
1316 case MackieControlProtocol::Pan:
1317 // This needs to set current pan mode (azimuth or width... or whatever)
1318 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1319 set_vpot_parameter (_pan_mode);
1321 case MackieControlProtocol::Trim:
1322 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
1323 set_vpot_parameter (_trim_mode);
1325 case MackieControlProtocol::Send:
1326 // _current_send has the number of the send we will show
1327 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
1328 set_vpot_parameter (SendAutomation);
1338 Strip::block_screen_display_for (uint32_t msecs)
1340 _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1344 Strip::block_vpot_mode_display_for (uint32_t msecs)
1346 _block_vpot_mode_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1350 Strip::return_to_vpot_mode_display ()
1352 /* returns the second line of the two-line per-strip display
1353 back the mode where it shows what the VPot controls.
1356 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1357 /* do nothing - second line shows value of current subview parameter */
1359 } else if (_route) {
1360 _surface->write (display (1, vpot_mode_string()));
1362 _surface->write (blank_display (1));
1367 Strip::next_pot_mode ()
1369 vector<AutomationType>::iterator i;
1371 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1372 /* do not change vpot mode while in flipped mode */
1373 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1374 _surface->write (display (1, "Flip"));
1375 block_vpot_mode_display_for (1000);
1380 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1385 if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1386 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
1390 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1391 if ((*i) == ac->parameter()) {
1396 /* move to the next mode in the list, or back to the start (which will
1397 also happen if the current mode is not in the current pot mode list)
1400 if (i != possible_pot_parameters.end()) {
1404 if (i == possible_pot_parameters.end()) {
1405 i = possible_pot_parameters.begin();
1407 set_vpot_parameter (*i);
1408 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
1409 if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter())) {
1413 for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
1414 if ((*i) == ac->parameter()) {
1418 if ((*i) == PhaseAutomation && _route->phase_invert().size() > 1) {
1419 // There are more than one channel of phase
1420 if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
1421 _route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
1422 set_vpot_parameter (*i);
1425 _route->phase_control()->set_channel(0);
1428 /* move to the next mode in the list, or back to the start (which will
1429 also happen if the current mode is not in the current pot mode list)
1432 if (i != possible_trim_parameters.end()) {
1436 if (i == possible_trim_parameters.end()) {
1437 i = possible_trim_parameters.begin();
1439 set_vpot_parameter (*i);
1440 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
1441 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1445 p = _route->nth_send (_current_send + 1);
1446 if (p && p->name() != "Monitor 1") {
1451 set_vpot_parameter (SendAutomation);
1456 Strip::subview_mode_changed ()
1458 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1460 subview_connections.drop_connections ();
1462 switch (_surface->mcp().subview_mode()) {
1463 case MackieControlProtocol::None:
1464 set_vpot_parameter (vpot_parameter);
1465 notify_metering_state_changed ();
1469 case MackieControlProtocol::EQ:
1473 case MackieControlProtocol::Dynamics:
1480 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1486 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1487 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1488 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1489 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1490 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1491 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1493 uint32_t pos = _surface->mcp().global_index (*this);
1495 /* we will control the pos-th available parameter, from the list in the
1496 * order shown above.
1499 vector<boost::shared_ptr<AutomationControl> > available;
1500 vector<AutomationType> params;
1502 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1503 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1504 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1505 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1506 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1507 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1509 if (pos >= available.size()) {
1510 /* this knob is not needed to control the available parameters */
1511 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1512 _surface->write (display (0, string()));
1513 _surface->write (display (1, string()));
1517 boost::shared_ptr<AutomationControl> pc;
1518 AutomationType param;
1520 pc = available[pos];
1521 param = params[pos];
1523 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false), ui_context());
1524 _vpot->set_control (pc);
1551 if (!pot_id.empty()) {
1552 _surface->write (display (0, pot_id));
1555 notify_dyn_change (param, true);
1559 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1561 uint32_t bands = r->eq_band_cnt ();
1564 /* should never get here */
1568 /* figure out how many params per band are available */
1570 boost::shared_ptr<AutomationControl> pc;
1571 uint32_t params_per_band = 0;
1573 if ((pc = r->eq_gain_controllable (0))) {
1574 params_per_band += 1;
1576 if ((pc = r->eq_freq_controllable (0))) {
1577 params_per_band += 1;
1579 if ((pc = r->eq_q_controllable (0))) {
1580 params_per_band += 1;
1582 if ((pc = r->eq_shape_controllable (0))) {
1583 params_per_band += 1;
1586 /* pick the one for this strip, based on its global position across
1592 const uint32_t total_band_parameters = bands * params_per_band;
1593 const uint32_t global_pos = _surface->mcp().global_index (*this);
1594 AutomationType param = NullAutomation;
1599 if (global_pos < total_band_parameters) {
1601 /* show a parameter for an EQ band */
1603 const uint32_t parameter = global_pos % params_per_band;
1604 eq_band = global_pos / params_per_band;
1605 band_name = r->eq_band_name (eq_band);
1607 switch (parameter) {
1609 pc = r->eq_gain_controllable (eq_band);
1613 pc = r->eq_freq_controllable (eq_band);
1614 param = EQFrequency;
1617 pc = r->eq_q_controllable (eq_band);
1621 pc = r->eq_shape_controllable (eq_band);
1628 /* show a non-band parameter (HPF or enable)
1631 uint32_t parameter = global_pos - total_band_parameters;
1633 switch (parameter) {
1634 case 0: /* first control after band parameters */
1635 pc = r->eq_hpf_controllable();
1638 case 1: /* second control after band parameters */
1639 pc = r->eq_enable_controllable();
1643 /* nothing to control */
1644 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1645 _surface->write (display (0, string()));
1646 _surface->write (display (1, string()));
1655 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1656 _vpot->set_control (pc);
1662 pot_id = band_name + "Gain";
1665 pot_id = band_name + "Freq";
1668 pot_id = band_name + " Q";
1671 pot_id = band_name + " Shp";
1683 if (!pot_id.empty()) {
1684 _surface->write (display (0, pot_id));
1687 notify_eq_change (param, eq_band, true);
1692 Strip::set_vpot_parameter (AutomationType p)
1694 if (!_route || (p == NullAutomation)) {
1695 control_by_parameter[vpot_parameter] = 0;
1696 vpot_parameter = NullAutomation;
1697 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1698 _surface->write (display (1, string()));
1702 boost::shared_ptr<AutomationControl> pan_control;
1704 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1706 reset_saved_values ();
1708 /* unset any mapping between the vpot and any existing parameters */
1710 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1712 if (i != control_by_parameter.end() && i->second == _vpot) {
1718 case PanAzimuthAutomation:
1719 if ((pan_control = _route->pan_azimuth_control ())) {
1720 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1721 _pan_mode = PanAzimuthAutomation;
1722 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1723 /* gain to vpot, pan azi to fader */
1724 _vpot->set_control (_route->group_gain_control());
1725 vpot_parameter = GainAutomation;
1726 control_by_parameter[GainAutomation] = _vpot;
1727 _fader->set_control (pan_control);
1728 control_by_parameter[PanAzimuthAutomation] = _fader;
1730 _fader->set_control (boost::shared_ptr<AutomationControl>());
1731 control_by_parameter[PanAzimuthAutomation] = 0;
1734 /* gain to fader, pan azi to vpot */
1735 vpot_parameter = PanAzimuthAutomation;
1736 _fader->set_control (_route->group_gain_control());
1737 control_by_parameter[GainAutomation] = _fader;
1738 _vpot->set_control (pan_control);
1739 control_by_parameter[PanAzimuthAutomation] = _vpot;
1742 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1743 control_by_parameter[PanAzimuthAutomation] = 0;
1747 case PanWidthAutomation:
1748 if ((pan_control = _route->pan_width_control ())) {
1749 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1750 _pan_mode = PanWidthAutomation;
1751 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1752 /* gain to vpot, pan width to fader */
1753 _vpot->set_control (_route->group_gain_control());
1754 vpot_parameter = GainAutomation;
1755 control_by_parameter[GainAutomation] = _vpot;
1756 _fader->set_control (pan_control);
1757 control_by_parameter[PanWidthAutomation] = _fader;
1759 _fader->set_control (boost::shared_ptr<AutomationControl>());
1760 control_by_parameter[PanWidthAutomation] = 0;
1763 /* gain to fader, pan width to vpot */
1764 vpot_parameter = PanWidthAutomation;
1765 _fader->set_control (_route->group_gain_control());
1766 control_by_parameter[GainAutomation] = _fader;
1767 _vpot->set_control (pan_control);
1768 control_by_parameter[PanWidthAutomation] = _vpot;
1771 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1772 control_by_parameter[PanWidthAutomation] = 0;
1776 case PanElevationAutomation:
1778 case PanFrontBackAutomation:
1780 case PanLFEAutomation:
1782 case TrimAutomation:
1783 _trim_mode = TrimAutomation;
1784 vpot_parameter = TrimAutomation;
1785 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1786 /* gain to vpot, trim to fader */
1787 _vpot->set_control (_route->group_gain_control());
1788 control_by_parameter[GainAutomation] = _vpot;
1789 if (_route->trim() && route()->trim()->active()) {
1790 _fader->set_control (_route->trim_control());
1791 control_by_parameter[TrimAutomation] = _fader;
1793 _fader->set_control (boost::shared_ptr<AutomationControl>());
1794 control_by_parameter[TrimAutomation] = 0;
1797 /* gain to fader, trim to vpot */
1798 _fader->set_control (_route->group_gain_control());
1799 control_by_parameter[GainAutomation] = _fader;
1800 if (_route->trim() && route()->trim()->active()) {
1801 _vpot->set_control (_route->trim_control());
1802 control_by_parameter[TrimAutomation] = _vpot;
1804 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1805 control_by_parameter[TrimAutomation] = 0;
1809 case PhaseAutomation:
1810 _trim_mode = PhaseAutomation;
1811 vpot_parameter = PhaseAutomation;
1812 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1813 /* gain to vpot, phase to fader */
1814 _vpot->set_control (_route->group_gain_control());
1815 control_by_parameter[GainAutomation] = _vpot;
1816 if (_route->phase_invert().size()) {
1817 _fader->set_control (_route->phase_control());
1818 control_by_parameter[PhaseAutomation] = _fader;
1820 _fader->set_control (boost::shared_ptr<AutomationControl>());
1821 control_by_parameter[PhaseAutomation] = 0;
1824 /* gain to fader, phase to vpot */
1825 _fader->set_control (_route->group_gain_control());
1826 control_by_parameter[GainAutomation] = _fader;
1827 if (_route->phase_invert().size()) {
1828 _vpot->set_control (_route->phase_control());
1829 control_by_parameter[PhaseAutomation] = _vpot;
1831 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1832 control_by_parameter[PhaseAutomation] = 0;
1836 case SendAutomation:
1837 if (!Profile->get_mixbus()) {
1838 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1839 // gain to vpot, send to fader
1840 _vpot->set_control (_route->group_gain_control());
1841 control_by_parameter[GainAutomation] = _vpot;
1842 // test for send to control
1843 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1844 if (p && p->name() != "Monitor 1") {
1845 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1846 boost::shared_ptr<Amp> a = s->amp();
1847 _fader->set_control (a->gain_control());
1848 // connect to signal
1849 send_connections.drop_connections ();
1850 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1851 control_by_parameter[SendAutomation] = _fader;
1853 _fader->set_control (boost::shared_ptr<AutomationControl>());
1854 control_by_parameter[SendAutomation] = 0;
1857 // gain to fader, send to vpot
1858 _fader->set_control (_route->group_gain_control());
1859 control_by_parameter[GainAutomation] = _fader;
1860 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1861 if (p && p->name() != "Monitor 1") {
1862 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1863 boost::shared_ptr<Amp> a = s->amp();
1864 _vpot->set_control (a->gain_control());
1865 // connect to signal
1866 send_connections.drop_connections ();
1867 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1868 control_by_parameter[SendAutomation] = _vpot;
1870 // gain to fader, send to vpot
1871 _fader->set_control (_route->group_gain_control());
1872 control_by_parameter[GainAutomation] = _fader;
1873 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1874 if (p && p->name() != "Monitor 1") {
1875 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1876 boost::shared_ptr<Amp> a = s->amp();
1877 _vpot->set_control (a->gain_control());
1878 // connect to signal
1879 send_connections.drop_connections ();
1880 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1881 control_by_parameter[SendAutomation] = _vpot;
1883 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1884 control_by_parameter[SendAutomation] = 0;
1890 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1895 _surface->write (display (1, vpot_mode_string()));
1899 Strip::is_midi_track () const
1901 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1905 Strip::reset_saved_values ()
1907 _last_pan_azi_position_written = -1.0;
1908 _last_pan_width_position_written = -1.0;
1909 _last_gain_position_written = -1.0;
1910 _last_trim_position_written = -1.0;
1915 Strip::notify_metering_state_changed()
1917 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1921 if (!_route || !_meter) {
1925 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1926 bool metering_active = _surface->mcp().metering_active ();
1928 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1932 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1934 if (!transport_is_rolling || !metering_active) {
1935 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1936 notify_panner_azi_changed (true);
1939 _transport_is_rolling = transport_is_rolling;
1940 _metering_active = metering_active;