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)
767 if (_surface->mcp().subview_mode() != None) {
769 /* subview mode: vpot press acts like a button for toggle parameters */
775 boost::shared_ptr<AutomationControl> control = _vpot->control ();
780 if (control->toggled()) {
781 if (control->toggled()) {
782 control->set_value (!control->get_value());
791 int ms = _surface->mcp().main_modifier_state();
793 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
795 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
799 /* reset to default/normal value */
800 ac->set_value (ac->normal());
805 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
813 Strip::fader_touch_event (Button&, ButtonState bs)
815 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
819 boost::shared_ptr<AutomationControl> ac = _fader->control ();
821 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
823 ac->set_value (ac->normal());
827 _fader->set_in_use (true);
828 _fader->start_touch (_surface->mcp().transport_frame());
831 queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
837 _fader->set_in_use (false);
838 _fader->stop_touch (_surface->mcp().transport_frame(), true);
845 Strip::handle_button (Button& button, ButtonState bs)
847 boost::shared_ptr<AutomationControl> control;
850 button.set_in_use (true);
852 button.set_in_use (false);
855 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
857 switch (button.bid()) {
859 select_event (button, bs);
862 case Button::VSelect:
863 vselect_event (button, bs);
866 case Button::FaderTouch:
867 fader_touch_event (button, bs);
871 if ((control = button.control ())) {
873 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
874 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
877 int ms = _surface->mcp().main_modifier_state();
879 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
880 /* reset to default/normal value */
881 new_value = control->normal();
883 new_value = control->get_value() ? 0.0 : 1.0;
886 /* get all controls that either have their
887 * button down or are within a range of
888 * several down buttons
891 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
894 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
895 controls.size(), control->parameter().type(), new_value));
899 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
900 (*c)->set_value (new_value);
904 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
905 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
913 Strip::queue_parameter_display (AutomationType type, float val)
915 RedisplayRequest req;
920 redisplay_requests.write (&req, 1);
924 Strip::do_parameter_display (AutomationType type, float val)
926 bool screen_hold = false;
932 _surface->write (display (1, " -inf "));
934 float dB = accurate_coefficient_to_dB (val);
935 snprintf (buf, sizeof (buf), "%6.1f", dB);
936 _surface->write (display (1, buf));
941 case PanAzimuthAutomation:
942 if (Profile->get_mixbus()) {
943 snprintf (buf, sizeof (buf), "%2.1f", val);
944 _surface->write (display (1, buf));
948 boost::shared_ptr<Pannable> p = _route->pannable();
949 if (p && _route->panner()) {
950 string str =_route->panner()->value_as_string (p->pan_azimuth_control);
951 _surface->write (display (1, str));
958 case PanWidthAutomation:
960 snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
961 _surface->write (display (1, buf));
968 float dB = accurate_coefficient_to_dB (val);
969 snprintf (buf, sizeof (buf), "%6.1f", dB);
970 _surface->write (display (1, buf));
975 case PhaseAutomation:
977 if (_route->phase_control()->get_value() < 0.5) {
978 _surface->write (display (1, "Normal"));
980 _surface->write (display (1, "Invert"));
988 _surface->write (display (1, " -inf "));
990 float dB = accurate_coefficient_to_dB (val);
991 snprintf (buf, sizeof (buf), "%6.1f", dB);
992 _surface->write (display (1, buf));
1005 snprintf (buf, sizeof (buf), "%6.1f", val);
1006 _surface->write (display (1, buf));
1012 _surface->write (display (1, "on"));
1014 _surface->write (display (1, "off"));
1018 if (_surface->mcp().subview_route()) {
1019 _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
1027 block_vpot_mode_display_for (1000);
1032 Strip::handle_fader_touch (Fader& fader, bool touch_on)
1035 fader.start_touch (_surface->mcp().transport_frame());
1037 fader.stop_touch (_surface->mcp().transport_frame(), false);
1042 Strip::handle_fader (Fader& fader, float position)
1044 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
1045 boost::shared_ptr<AutomationControl> ac = fader.control();
1050 fader.set_value (position);
1052 /* From the Mackie Control MIDI implementation docs:
1054 In order to ensure absolute synchronization with the host software,
1055 Mackie Control uses a closed-loop servo system for the faders,
1056 meaning the faders will always move to their last received position.
1057 When a host receives a Fader Position Message, it must then
1058 re-transmit that message to the Mackie Control or else the faders
1059 will return to their last position.
1062 _surface->write (fader.set_position (position));
1066 Strip::handle_pot (Pot& pot, float delta)
1068 /* Pots only emit events when they move, not when they
1069 stop moving. So to get a stop event, we need to use a timeout.
1072 boost::shared_ptr<AutomationControl> ac = pot.control();
1076 double p = pot.get_value ();
1078 // fader and pot should be the same and fader is hard coded 0 -> 1
1085 Strip::periodic (ARDOUR::microseconds_t now)
1087 bool reshow_vpot_mode = false;
1088 bool reshow_name = false;
1094 if (_block_screen_redisplay_until >= now) {
1095 if (_surface->mcp().device_info().has_separate_meters()) {
1098 /* no drawing here, for now */
1101 } else if (_block_screen_redisplay_until) {
1103 /* timeout reached, reset */
1105 _block_screen_redisplay_until = 0;
1106 reshow_vpot_mode = true;
1110 if (_block_vpot_mode_redisplay_until >= now) {
1112 } else if (_block_vpot_mode_redisplay_until) {
1114 /* timeout reached, reset */
1116 _block_vpot_mode_redisplay_until = 0;
1117 reshow_vpot_mode = true;
1124 if (reshow_vpot_mode) {
1125 return_to_vpot_mode_display ();
1127 /* no point doing this if we just switched back to vpot mode
1129 update_automation ();
1137 Strip::redisplay (ARDOUR::microseconds_t now)
1139 RedisplayRequest req;
1140 bool have_request = false;
1142 while (redisplay_requests.read (&req, 1) == 1) {
1144 have_request = true;
1147 if (_block_screen_redisplay_until >= now) {
1152 do_parameter_display (req.type, req.val);
1157 Strip::update_automation ()
1163 ARDOUR::AutoState state = _route->gain_control()->automation_state();
1165 if (state == Touch || state == Play) {
1166 notify_gain_changed (false);
1169 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1171 state = pan_control->automation_state ();
1172 if (state == Touch || state == Play) {
1173 notify_panner_azi_changed (false);
1177 pan_control = _route->pan_width_control ();
1179 state = pan_control->automation_state ();
1180 if (state == Touch || state == Play) {
1181 notify_panner_width_changed (false);
1185 if (_route->trim() && route()->trim()->active()) {
1186 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1187 if (trim_state == Touch || trim_state == Play) {
1188 notify_trim_changed (false);
1194 Strip::update_meter ()
1196 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1200 if (_meter && _transport_is_rolling && _metering_active) {
1201 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1202 _meter->send_update (*_surface, dB);
1209 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1210 _surface->write ((*it)->zero ());
1213 _surface->write (blank_display (0));
1214 _surface->write (blank_display (1));
1218 Strip::blank_display (uint32_t line_number)
1220 return display (line_number, string());
1224 Strip::display (uint32_t line_number, const std::string& line)
1226 assert (line_number <= 1);
1228 MidiByteArray retval;
1230 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1233 retval << _surface->sysex_hdr();
1237 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1238 retval << (_index * 7 + (line_number * 0x38));
1240 // ascii data to display. @param line is UTF-8
1241 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1242 string::size_type len = ascii.length();
1244 ascii = ascii.substr (0, 6);
1248 // pad with " " out to 6 chars
1249 for (int i = len; i < 6; ++i) {
1253 // column spacer, unless it's the right-hand column
1259 retval << MIDI::eox;
1265 Strip::lock_controls ()
1267 _controls_locked = true;
1271 Strip::unlock_controls ()
1273 _controls_locked = false;
1277 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1279 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1280 if ((*i) == _route) {
1281 _surface->write (_select->set_state (on));
1286 _surface->write (_select->set_state (off));
1290 Strip::vpot_mode_string ()
1292 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1297 if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1299 } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1301 } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1302 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1303 } else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
1304 // should be bus name
1305 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1309 } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1311 } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1313 } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1315 } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1317 } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1321 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1329 Strip::potmode_changed (bool notify)
1336 int pm = _surface->mcp().pot_mode();
1338 case MackieControlProtocol::Pan:
1339 // This needs to set current pan mode (azimuth or width... or whatever)
1340 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1341 set_vpot_parameter (_pan_mode);
1343 case MackieControlProtocol::Trim:
1344 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
1345 set_vpot_parameter (_trim_mode);
1347 case MackieControlProtocol::Send:
1348 // _current_send has the number of the send we will show
1349 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
1350 set_vpot_parameter (SendAutomation);
1360 Strip::block_screen_display_for (uint32_t msecs)
1362 _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1366 Strip::block_vpot_mode_display_for (uint32_t msecs)
1368 _block_vpot_mode_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1372 Strip::return_to_vpot_mode_display ()
1374 /* returns the second line of the two-line per-strip display
1375 back the mode where it shows what the VPot controls.
1378 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1379 /* do nothing - second line shows value of current subview parameter */
1381 } else if (_route) {
1382 _surface->write (display (1, vpot_mode_string()));
1384 _surface->write (blank_display (1));
1389 Strip::next_pot_mode ()
1391 vector<AutomationType>::iterator i;
1393 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1394 /* do not change vpot mode while in flipped mode */
1395 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1396 _surface->write (display (1, "Flip"));
1397 block_vpot_mode_display_for (1000);
1402 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1407 if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1408 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
1412 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1413 if ((*i) == ac->parameter()) {
1418 /* move to the next mode in the list, or back to the start (which will
1419 also happen if the current mode is not in the current pot mode list)
1422 if (i != possible_pot_parameters.end()) {
1426 if (i == possible_pot_parameters.end()) {
1427 i = possible_pot_parameters.begin();
1429 set_vpot_parameter (*i);
1430 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
1431 if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter())) {
1435 for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
1436 if ((*i) == ac->parameter()) {
1440 if ((*i) == PhaseAutomation && _route->phase_invert().size() > 1) {
1441 // There are more than one channel of phase
1442 if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
1443 _route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
1444 set_vpot_parameter (*i);
1447 _route->phase_control()->set_channel(0);
1450 /* move to the next mode in the list, or back to the start (which will
1451 also happen if the current mode is not in the current pot mode list)
1454 if (i != possible_trim_parameters.end()) {
1458 if (i == possible_trim_parameters.end()) {
1459 i = possible_trim_parameters.begin();
1461 set_vpot_parameter (*i);
1462 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
1463 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1467 p = _route->nth_send (_current_send + 1);
1468 if (p && p->name() != "Monitor 1") {
1473 set_vpot_parameter (SendAutomation);
1478 Strip::subview_mode_changed ()
1480 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1482 subview_connections.drop_connections ();
1484 switch (_surface->mcp().subview_mode()) {
1485 case MackieControlProtocol::None:
1486 set_vpot_parameter (vpot_parameter);
1487 notify_metering_state_changed ();
1491 case MackieControlProtocol::EQ:
1495 case MackieControlProtocol::Dynamics:
1502 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1508 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1509 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1510 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1511 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1512 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1513 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1515 uint32_t pos = _surface->mcp().global_index (*this);
1517 /* we will control the pos-th available parameter, from the list in the
1518 * order shown above.
1521 vector<boost::shared_ptr<AutomationControl> > available;
1522 vector<AutomationType> params;
1524 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1525 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1526 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1527 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1528 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1529 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1531 if (pos >= available.size()) {
1532 /* this knob is not needed to control the available parameters */
1533 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1534 _surface->write (display (0, string()));
1535 _surface->write (display (1, string()));
1539 boost::shared_ptr<AutomationControl> pc;
1540 AutomationType param;
1542 pc = available[pos];
1543 param = params[pos];
1545 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false), ui_context());
1546 _vpot->set_control (pc);
1573 if (!pot_id.empty()) {
1574 _surface->write (display (0, pot_id));
1577 notify_dyn_change (param, true);
1581 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1583 uint32_t bands = r->eq_band_cnt ();
1586 /* should never get here */
1590 /* figure out how many params per band are available */
1592 boost::shared_ptr<AutomationControl> pc;
1593 uint32_t params_per_band = 0;
1595 if ((pc = r->eq_gain_controllable (0))) {
1596 params_per_band += 1;
1598 if ((pc = r->eq_freq_controllable (0))) {
1599 params_per_band += 1;
1601 if ((pc = r->eq_q_controllable (0))) {
1602 params_per_band += 1;
1604 if ((pc = r->eq_shape_controllable (0))) {
1605 params_per_band += 1;
1608 /* pick the one for this strip, based on its global position across
1614 const uint32_t total_band_parameters = bands * params_per_band;
1615 const uint32_t global_pos = _surface->mcp().global_index (*this);
1616 AutomationType param = NullAutomation;
1621 if (global_pos < total_band_parameters) {
1623 /* show a parameter for an EQ band */
1625 const uint32_t parameter = global_pos % params_per_band;
1626 eq_band = global_pos / params_per_band;
1627 band_name = r->eq_band_name (eq_band);
1629 switch (parameter) {
1631 pc = r->eq_gain_controllable (eq_band);
1635 pc = r->eq_freq_controllable (eq_band);
1636 param = EQFrequency;
1639 pc = r->eq_q_controllable (eq_band);
1643 pc = r->eq_shape_controllable (eq_band);
1650 /* show a non-band parameter (HPF or enable)
1653 uint32_t parameter = global_pos - total_band_parameters;
1655 switch (parameter) {
1656 case 0: /* first control after band parameters */
1657 pc = r->eq_hpf_controllable();
1660 case 1: /* second control after band parameters */
1661 pc = r->eq_enable_controllable();
1665 /* nothing to control */
1666 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1667 _surface->write (display (0, string()));
1668 _surface->write (display (1, string()));
1677 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1678 _vpot->set_control (pc);
1684 pot_id = band_name + "Gain";
1687 pot_id = band_name + "Freq";
1690 pot_id = band_name + " Q";
1693 pot_id = band_name + " Shp";
1705 if (!pot_id.empty()) {
1706 _surface->write (display (0, pot_id));
1709 notify_eq_change (param, eq_band, true);
1714 Strip::set_vpot_parameter (AutomationType p)
1716 if (!_route || (p == NullAutomation)) {
1717 control_by_parameter[vpot_parameter] = 0;
1718 vpot_parameter = NullAutomation;
1719 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1720 _surface->write (display (1, string()));
1724 boost::shared_ptr<AutomationControl> pan_control;
1726 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1728 reset_saved_values ();
1730 /* unset any mapping between the vpot and any existing parameters */
1732 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1734 if (i != control_by_parameter.end() && i->second == _vpot) {
1740 case PanAzimuthAutomation:
1741 if ((pan_control = _route->pan_azimuth_control ())) {
1742 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1743 _pan_mode = PanAzimuthAutomation;
1744 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1745 /* gain to vpot, pan azi to fader */
1746 _vpot->set_control (_route->group_gain_control());
1747 vpot_parameter = GainAutomation;
1748 control_by_parameter[GainAutomation] = _vpot;
1749 _fader->set_control (pan_control);
1750 control_by_parameter[PanAzimuthAutomation] = _fader;
1752 _fader->set_control (boost::shared_ptr<AutomationControl>());
1753 control_by_parameter[PanAzimuthAutomation] = 0;
1756 /* gain to fader, pan azi to vpot */
1757 vpot_parameter = PanAzimuthAutomation;
1758 _fader->set_control (_route->group_gain_control());
1759 control_by_parameter[GainAutomation] = _fader;
1760 _vpot->set_control (pan_control);
1761 control_by_parameter[PanAzimuthAutomation] = _vpot;
1764 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1765 control_by_parameter[PanAzimuthAutomation] = 0;
1769 case PanWidthAutomation:
1770 if ((pan_control = _route->pan_width_control ())) {
1771 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1772 _pan_mode = PanWidthAutomation;
1773 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1774 /* gain to vpot, pan width to fader */
1775 _vpot->set_control (_route->group_gain_control());
1776 vpot_parameter = GainAutomation;
1777 control_by_parameter[GainAutomation] = _vpot;
1778 _fader->set_control (pan_control);
1779 control_by_parameter[PanWidthAutomation] = _fader;
1781 _fader->set_control (boost::shared_ptr<AutomationControl>());
1782 control_by_parameter[PanWidthAutomation] = 0;
1785 /* gain to fader, pan width to vpot */
1786 vpot_parameter = PanWidthAutomation;
1787 _fader->set_control (_route->group_gain_control());
1788 control_by_parameter[GainAutomation] = _fader;
1789 _vpot->set_control (pan_control);
1790 control_by_parameter[PanWidthAutomation] = _vpot;
1793 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1794 control_by_parameter[PanWidthAutomation] = 0;
1798 case PanElevationAutomation:
1800 case PanFrontBackAutomation:
1802 case PanLFEAutomation:
1804 case TrimAutomation:
1805 _trim_mode = TrimAutomation;
1806 vpot_parameter = TrimAutomation;
1807 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1808 /* gain to vpot, trim to fader */
1809 _vpot->set_control (_route->group_gain_control());
1810 control_by_parameter[GainAutomation] = _vpot;
1811 if (_route->trim() && route()->trim()->active()) {
1812 _fader->set_control (_route->trim_control());
1813 control_by_parameter[TrimAutomation] = _fader;
1815 _fader->set_control (boost::shared_ptr<AutomationControl>());
1816 control_by_parameter[TrimAutomation] = 0;
1819 /* gain to fader, trim to vpot */
1820 _fader->set_control (_route->group_gain_control());
1821 control_by_parameter[GainAutomation] = _fader;
1822 if (_route->trim() && route()->trim()->active()) {
1823 _vpot->set_control (_route->trim_control());
1824 control_by_parameter[TrimAutomation] = _vpot;
1826 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1827 control_by_parameter[TrimAutomation] = 0;
1831 case PhaseAutomation:
1832 _trim_mode = PhaseAutomation;
1833 vpot_parameter = PhaseAutomation;
1834 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1835 /* gain to vpot, phase to fader */
1836 _vpot->set_control (_route->group_gain_control());
1837 control_by_parameter[GainAutomation] = _vpot;
1838 if (_route->phase_invert().size()) {
1839 _fader->set_control (_route->phase_control());
1840 control_by_parameter[PhaseAutomation] = _fader;
1842 _fader->set_control (boost::shared_ptr<AutomationControl>());
1843 control_by_parameter[PhaseAutomation] = 0;
1846 /* gain to fader, phase to vpot */
1847 _fader->set_control (_route->group_gain_control());
1848 control_by_parameter[GainAutomation] = _fader;
1849 if (_route->phase_invert().size()) {
1850 _vpot->set_control (_route->phase_control());
1851 control_by_parameter[PhaseAutomation] = _vpot;
1853 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1854 control_by_parameter[PhaseAutomation] = 0;
1858 case SendAutomation:
1859 if (!Profile->get_mixbus()) {
1860 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1861 // gain to vpot, send to fader
1862 _vpot->set_control (_route->group_gain_control());
1863 control_by_parameter[GainAutomation] = _vpot;
1864 // test for send to control
1865 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1866 if (p && p->name() != "Monitor 1") {
1867 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1868 boost::shared_ptr<Amp> a = s->amp();
1869 _fader->set_control (a->gain_control());
1870 // connect to signal
1871 send_connections.drop_connections ();
1872 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1873 control_by_parameter[SendAutomation] = _fader;
1875 _fader->set_control (boost::shared_ptr<AutomationControl>());
1876 control_by_parameter[SendAutomation] = 0;
1879 // gain to fader, send to vpot
1880 _fader->set_control (_route->group_gain_control());
1881 control_by_parameter[GainAutomation] = _fader;
1882 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1883 if (p && p->name() != "Monitor 1") {
1884 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1885 boost::shared_ptr<Amp> a = s->amp();
1886 _vpot->set_control (a->gain_control());
1887 // connect to signal
1888 send_connections.drop_connections ();
1889 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1890 control_by_parameter[SendAutomation] = _vpot;
1892 // gain to fader, send to vpot
1893 _fader->set_control (_route->group_gain_control());
1894 control_by_parameter[GainAutomation] = _fader;
1895 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1896 if (p && p->name() != "Monitor 1") {
1897 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1898 boost::shared_ptr<Amp> a = s->amp();
1899 _vpot->set_control (a->gain_control());
1900 // connect to signal
1901 send_connections.drop_connections ();
1902 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1903 control_by_parameter[SendAutomation] = _vpot;
1905 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1906 control_by_parameter[SendAutomation] = 0;
1912 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1917 _surface->write (display (1, vpot_mode_string()));
1921 Strip::is_midi_track () const
1923 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1927 Strip::reset_saved_values ()
1929 _last_pan_azi_position_written = -1.0;
1930 _last_pan_width_position_written = -1.0;
1931 _last_gain_position_written = -1.0;
1932 _last_trim_position_written = -1.0;
1937 Strip::notify_metering_state_changed()
1939 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1943 if (!_route || !_meter) {
1947 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1948 bool metering_active = _surface->mcp().metering_active ();
1950 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1954 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1956 if (!transport_is_rolling || !metering_active) {
1957 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1958 notify_panner_azi_changed (true);
1961 _transport_is_rolling = transport_is_rolling;
1962 _metering_active = metering_active;