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);
306 // The active V-pot control may not be active for this strip
307 // But if we zero it in the controls function it may erase
308 // the one we do want
309 _surface->write (_vpot->zero());
311 notify_solo_changed ();
312 notify_mute_changed ();
313 notify_gain_changed ();
314 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
315 notify_panner_azi_changed ();
316 notify_panner_width_changed ();
317 notify_record_enable_changed ();
318 notify_trim_changed ();
319 notify_phase_changed ();
320 notify_processor_changed ();
324 Strip::notify_solo_changed ()
326 if (_route && _solo) {
327 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
332 Strip::notify_mute_changed ()
334 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
335 if (_route && _mute) {
336 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
337 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
339 _surface->write (_mute->set_state (_route->muted() ? on : off));
344 Strip::notify_record_enable_changed ()
346 if (_route && _recenable) {
347 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
352 Strip::notify_active_changed ()
354 _surface->mcp().refresh_current_bank();
358 Strip::notify_route_deleted ()
360 _surface->mcp().refresh_current_bank();
364 Strip::notify_gain_changed (bool force_update)
370 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
376 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
378 float gain_coefficient = ac->get_value();
379 float normalized_position = ac->internal_to_interface (gain_coefficient);
382 if (force_update || normalized_position != _last_gain_position_written) {
384 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
385 if (!control->in_use()) {
386 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
388 queue_parameter_display (GainAutomation, gain_coefficient);
390 if (!control->in_use()) {
391 _surface->write (_fader->set_position (normalized_position));
393 queue_parameter_display (GainAutomation, gain_coefficient);
396 _last_gain_position_written = normalized_position;
402 Strip::notify_trim_changed (bool force_update)
406 if (!_route->trim() || !route()->trim()->active()) {
409 Control* control = 0;
410 ControlParameterMap::iterator i = control_by_parameter.find (TrimAutomation);
412 if (i == control_by_parameter.end()) {
418 boost::shared_ptr<AutomationControl> ac = _route->trim_control();
420 float gain_coefficient = ac->get_value();
421 float normalized_position = ac->internal_to_interface (gain_coefficient);
423 if (force_update || normalized_position != _last_trim_position_written) {
424 if (control == _fader) {
425 if (!_fader->in_use()) {
426 _surface->write (_fader->set_position (normalized_position));
427 queue_parameter_display (TrimAutomation, gain_coefficient);
429 } else if (control == _vpot) {
430 _surface->write (_vpot->set (normalized_position, true, Pot::dot));
431 queue_parameter_display (TrimAutomation, gain_coefficient);
433 _last_trim_position_written = normalized_position;
439 Strip::notify_phase_changed (bool force_update)
442 if (!_route->phase_invert().size()) {
446 Control* control = 0;
447 ControlParameterMap::iterator i = control_by_parameter.find (PhaseAutomation);
449 if (i == control_by_parameter.end()) {
455 float normalized_position = _route->phase_control()->get_value();
457 if (control == _fader) {
458 if (!_fader->in_use()) {
459 _surface->write (_fader->set_position (normalized_position));
460 queue_parameter_display (PhaseAutomation, normalized_position);
462 } else if (control == _vpot) {
463 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
464 queue_parameter_display (PhaseAutomation, normalized_position);
470 Strip::notify_processor_changed (bool force_update)
473 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
478 Control* control = 0;
479 ControlParameterMap::iterator i = control_by_parameter.find (SendAutomation);
481 if (i == control_by_parameter.end()) {
487 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
488 boost::shared_ptr<Amp> a = s->amp();
489 boost::shared_ptr<AutomationControl> ac = a->gain_control();
491 float gain_coefficient = ac->get_value();
492 float normalized_position = ac->internal_to_interface (gain_coefficient);
494 if (control == _fader) {
495 if (!_fader->in_use()) {
496 _surface->write (_fader->set_position (normalized_position));
497 queue_parameter_display (SendAutomation, gain_coefficient);
499 } else if (control == _vpot) {
500 _surface->write (_vpot->set (normalized_position, true, Pot::dot));
501 queue_parameter_display (SendAutomation, gain_coefficient);
507 Strip::notify_property_changed (const PropertyChange& what_changed)
509 if (!what_changed.contains (ARDOUR::Properties::name)) {
517 Strip::show_route_name ()
519 MackieControlProtocol::SubViewMode svm = _surface->mcp().subview_mode();
521 if (svm != MackieControlProtocol::None) {
522 /* subview mode is responsible for upper line */
526 string fullname = string();
528 // make sure first three strips get cleared of view mode
533 fullname = _route->name();
537 if (fullname.length() <= 6) {
540 line1 = PBD::short_version (fullname, 6);
543 _surface->write (display (0, line1));
547 Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
549 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
552 /* not in subview mode */
556 if (_surface->mcp().subview_mode() != MackieControlProtocol::EQ) {
557 /* no longer in EQ subview mode */
561 boost::shared_ptr<AutomationControl> control;
565 control = r->eq_gain_controllable (band);
568 control = r->eq_freq_controllable (band);
571 control = r->eq_q_controllable (band);
574 control = r->eq_shape_controllable (band);
577 control = r->eq_hpf_controllable ();
580 control = r->eq_enable_controllable ();
587 float val = control->get_value();
588 queue_parameter_display (type, val);
589 /* update pot/encoder */
590 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
595 Strip::notify_dyn_change (AutomationType type, bool force_update, bool propagate_mode)
597 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
600 /* not in subview mode */
604 if (_surface->mcp().subview_mode() != MackieControlProtocol::Dynamics) {
605 /* no longer in EQ subview mode */
609 boost::shared_ptr<AutomationControl> control;
610 bool reset_all = false;
614 control = r->comp_threshold_controllable ();
617 control = r->comp_speed_controllable ();
620 control = r->comp_mode_controllable ();
624 control = r->comp_makeup_controllable ();
627 control = r->comp_redux_controllable ();
630 control = r->comp_enable_controllable ();
636 if (propagate_mode && reset_all) {
637 _surface->subview_mode_changed ();
641 float val = control->get_value();
642 queue_parameter_display (type, val);
643 /* update pot/encoder */
644 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
649 Strip::notify_panner_azi_changed (bool force_update)
655 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
657 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
663 Control* control = 0;
664 ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
666 if (i == control_by_parameter.end()) {
672 double normalized_pos = pan_control->internal_to_interface (pan_control->get_value());
673 double internal_pos = pan_control->get_value();
675 if (force_update || (normalized_pos != _last_pan_azi_position_written)) {
677 if (control == _fader) {
678 if (!_fader->in_use()) {
679 _surface->write (_fader->set_position (normalized_pos));
680 /* show actual internal value to user */
681 queue_parameter_display (PanAzimuthAutomation, internal_pos);
683 } else if (control == _vpot) {
684 _surface->write (_vpot->set (normalized_pos, true, Pot::dot));
685 /* show actual internal value to user */
686 queue_parameter_display (PanAzimuthAutomation, internal_pos);
689 _last_pan_azi_position_written = normalized_pos;
694 Strip::notify_panner_width_changed (bool force_update)
700 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
702 boost::shared_ptr<AutomationControl> pan_control = _route->pan_width_control ();
708 Control* control = 0;
709 ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
711 if (i == control_by_parameter.end()) {
717 double pos = pan_control->internal_to_interface (pan_control->get_value());
719 if (force_update || pos != _last_pan_width_position_written) {
721 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
723 if (control == _fader) {
724 if (!control->in_use()) {
725 _surface->write (_fader->set_position (pos));
726 queue_parameter_display (PanWidthAutomation, pos);
730 } else if (control == _vpot) {
731 _surface->write (_vpot->set (pos, true, Pot::spread));
732 queue_parameter_display (PanWidthAutomation, pos);
735 _last_pan_width_position_written = pos;
740 Strip::select_event (Button&, ButtonState bs)
742 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
746 int ms = _surface->mcp().main_modifier_state();
748 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
749 _controls_locked = !_controls_locked;
750 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
751 block_vpot_mode_display_for (1000);
755 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
756 /* reset to default */
757 boost::shared_ptr<AutomationControl> ac = _fader->control ();
759 ac->set_value (ac->normal());
764 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
765 _surface->mcp().add_down_select_button (_surface->number(), _index);
766 _surface->mcp().select_range ();
769 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
770 _surface->mcp().remove_down_select_button (_surface->number(), _index);
775 Strip::vselect_event (Button&, ButtonState bs)
777 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
779 /* subview mode: vpot press acts like a button for toggle parameters */
785 boost::shared_ptr<AutomationControl> control = _vpot->control ();
790 if (control->toggled()) {
791 if (control->toggled()) {
792 control->set_value (!control->get_value());
801 int ms = _surface->mcp().main_modifier_state();
803 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
805 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
809 /* reset to default/normal value */
810 ac->set_value (ac->normal());
815 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
823 Strip::fader_touch_event (Button&, ButtonState bs)
825 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
829 boost::shared_ptr<AutomationControl> ac = _fader->control ();
831 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
833 ac->set_value (ac->normal());
837 _fader->set_in_use (true);
838 _fader->start_touch (_surface->mcp().transport_frame());
841 queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
847 _fader->set_in_use (false);
848 _fader->stop_touch (_surface->mcp().transport_frame(), true);
855 Strip::handle_button (Button& button, ButtonState bs)
857 boost::shared_ptr<AutomationControl> control;
860 button.set_in_use (true);
862 button.set_in_use (false);
865 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
867 switch (button.bid()) {
869 select_event (button, bs);
872 case Button::VSelect:
873 vselect_event (button, bs);
876 case Button::FaderTouch:
877 fader_touch_event (button, bs);
881 if ((control = button.control ())) {
883 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
884 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
887 int ms = _surface->mcp().main_modifier_state();
889 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
890 /* reset to default/normal value */
891 new_value = control->normal();
893 new_value = control->get_value() ? 0.0 : 1.0;
896 /* get all controls that either have their
897 * button down or are within a range of
898 * several down buttons
901 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
904 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
905 controls.size(), control->parameter().type(), new_value));
909 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
910 (*c)->set_value (new_value);
914 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
915 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
923 Strip::queue_parameter_display (AutomationType type, float val)
925 RedisplayRequest req;
930 redisplay_requests.write (&req, 1);
934 Strip::do_parameter_display (AutomationType type, float val)
936 bool screen_hold = false;
942 _surface->write (display (1, " -inf "));
944 float dB = accurate_coefficient_to_dB (val);
945 snprintf (buf, sizeof (buf), "%6.1f", dB);
946 _surface->write (display (1, buf));
951 case PanAzimuthAutomation:
952 if (Profile->get_mixbus()) {
953 snprintf (buf, sizeof (buf), "%2.1f", val);
954 _surface->write (display (1, buf));
958 boost::shared_ptr<Pannable> p = _route->pannable();
959 if (p && _route->panner()) {
960 string str =_route->panner()->value_as_string (p->pan_azimuth_control);
961 _surface->write (display (1, str));
968 case PanWidthAutomation:
970 snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
971 _surface->write (display (1, buf));
978 float dB = accurate_coefficient_to_dB (val);
979 snprintf (buf, sizeof (buf), "%6.1f", dB);
980 _surface->write (display (1, buf));
985 case PhaseAutomation:
987 if (_route->phase_control()->get_value() < 0.5) {
988 _surface->write (display (1, "Normal"));
990 _surface->write (display (1, "Invert"));
998 _surface->write (display (1, " -inf "));
1000 float dB = accurate_coefficient_to_dB (val);
1001 snprintf (buf, sizeof (buf), "%6.1f", dB);
1002 _surface->write (display (1, buf));
1015 snprintf (buf, sizeof (buf), "%6.1f", val);
1016 _surface->write (display (1, buf));
1022 _surface->write (display (1, "on"));
1024 _surface->write (display (1, "off"));
1028 if (_surface->mcp().subview_route()) {
1029 _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
1037 block_vpot_mode_display_for (1000);
1042 Strip::handle_fader_touch (Fader& fader, bool touch_on)
1045 fader.start_touch (_surface->mcp().transport_frame());
1047 fader.stop_touch (_surface->mcp().transport_frame(), false);
1052 Strip::handle_fader (Fader& fader, float position)
1054 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
1055 boost::shared_ptr<AutomationControl> ac = fader.control();
1060 fader.set_value (position);
1062 /* From the Mackie Control MIDI implementation docs:
1064 In order to ensure absolute synchronization with the host software,
1065 Mackie Control uses a closed-loop servo system for the faders,
1066 meaning the faders will always move to their last received position.
1067 When a host receives a Fader Position Message, it must then
1068 re-transmit that message to the Mackie Control or else the faders
1069 will return to their last position.
1072 _surface->write (fader.set_position (position));
1076 Strip::handle_pot (Pot& pot, float delta)
1078 /* Pots only emit events when they move, not when they
1079 stop moving. So to get a stop event, we need to use a timeout.
1082 boost::shared_ptr<AutomationControl> ac = pot.control();
1086 double p = pot.get_value ();
1088 // fader and pot should be the same and fader is hard coded 0 -> 1
1095 Strip::periodic (ARDOUR::microseconds_t now)
1097 bool reshow_vpot_mode = false;
1098 bool reshow_name = false;
1099 bool good_strip = true;
1102 // view mode may cover as many as 3 strips
1103 // needs to be cleared when there are less than 3 routes
1111 if (_block_screen_redisplay_until >= now) {
1112 if (_surface->mcp().device_info().has_separate_meters()) {
1115 /* no drawing here, for now */
1118 } else if (_block_screen_redisplay_until) {
1120 /* timeout reached, reset */
1122 _block_screen_redisplay_until = 0;
1123 reshow_vpot_mode = (true && good_strip);
1127 if (_block_vpot_mode_redisplay_until >= now) {
1129 } else if (_block_vpot_mode_redisplay_until) {
1131 /* timeout reached, reset */
1133 _block_vpot_mode_redisplay_until = 0;
1134 reshow_vpot_mode = (true && good_strip);
1141 if (reshow_vpot_mode) {
1142 return_to_vpot_mode_display ();
1143 } else if (good_strip) {
1144 /* no point doing this if we just switched back to vpot mode
1146 update_automation ();
1156 Strip::redisplay (ARDOUR::microseconds_t now)
1158 RedisplayRequest req;
1159 bool have_request = false;
1161 while (redisplay_requests.read (&req, 1) == 1) {
1163 have_request = true;
1166 if (_block_screen_redisplay_until >= now) {
1171 do_parameter_display (req.type, req.val);
1176 Strip::update_automation ()
1182 ARDOUR::AutoState state = _route->gain_control()->automation_state();
1184 if (state == Touch || state == Play) {
1185 notify_gain_changed (false);
1188 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1190 state = pan_control->automation_state ();
1191 if (state == Touch || state == Play) {
1192 notify_panner_azi_changed (false);
1196 pan_control = _route->pan_width_control ();
1198 state = pan_control->automation_state ();
1199 if (state == Touch || state == Play) {
1200 notify_panner_width_changed (false);
1204 if (_route->trim() && route()->trim()->active()) {
1205 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1206 if (trim_state == Touch || trim_state == Play) {
1207 notify_trim_changed (false);
1213 Strip::update_meter ()
1215 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1219 if (_meter && _transport_is_rolling && _metering_active) {
1220 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1221 _meter->send_update (*_surface, dB);
1228 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1229 _surface->write ((*it)->zero ());
1232 _surface->write (blank_display (0));
1233 _surface->write (blank_display (1));
1237 Strip::blank_display (uint32_t line_number)
1239 return display (line_number, string());
1243 Strip::display (uint32_t line_number, const std::string& line)
1245 assert (line_number <= 1);
1247 MidiByteArray retval;
1249 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1252 retval << _surface->sysex_hdr();
1256 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1257 retval << (_index * 7 + (line_number * 0x38));
1259 // ascii data to display. @param line is UTF-8
1260 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1261 string::size_type len = ascii.length();
1263 ascii = ascii.substr (0, 6);
1267 // pad with " " out to 6 chars
1268 for (int i = len; i < 6; ++i) {
1272 // column spacer, unless it's the right-hand column
1278 retval << MIDI::eox;
1284 Strip::lock_controls ()
1286 _controls_locked = true;
1290 Strip::unlock_controls ()
1292 _controls_locked = false;
1296 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1298 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1299 if ((*i) == _route) {
1300 _surface->write (_select->set_state (on));
1305 _surface->write (_select->set_state (off));
1309 Strip::vpot_mode_string ()
1311 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1316 if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1318 } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1320 } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1321 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1322 } else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
1323 // should be bus name
1324 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1328 } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1330 } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1332 } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1334 } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1336 } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1340 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1348 Strip::potmode_changed (bool notify)
1355 int pm = _surface->mcp().pot_mode();
1357 case MackieControlProtocol::Pan:
1358 // This needs to set current pan mode (azimuth or width... or whatever)
1359 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1360 set_vpot_parameter (_pan_mode);
1362 case MackieControlProtocol::Trim:
1363 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
1364 set_vpot_parameter (_trim_mode);
1366 case MackieControlProtocol::Send:
1367 // _current_send has the number of the send we will show
1368 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
1369 set_vpot_parameter (SendAutomation);
1379 Strip::block_screen_display_for (uint32_t msecs)
1381 _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1385 Strip::block_vpot_mode_display_for (uint32_t msecs)
1387 _block_vpot_mode_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1391 Strip::return_to_vpot_mode_display ()
1393 /* returns the second line of the two-line per-strip display
1394 back the mode where it shows what the VPot controls.
1397 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1398 /* do nothing - second line shows value of current subview parameter */
1400 } else if (_route) {
1401 _surface->write (display (1, vpot_mode_string()));
1403 _surface->write (blank_display (1));
1408 Strip::next_pot_mode ()
1410 vector<AutomationType>::iterator i;
1412 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1413 /* do not change vpot mode while in flipped mode */
1414 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1415 _surface->write (display (1, "Flip"));
1416 block_vpot_mode_display_for (1000);
1421 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1428 if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1430 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
1434 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1435 if ((*i) == ac->parameter().type()) {
1440 /* move to the next mode in the list, or back to the start (which will
1441 also happen if the current mode is not in the current pot mode list)
1444 if (i != possible_pot_parameters.end()) {
1448 if (i == possible_pot_parameters.end()) {
1449 i = possible_pot_parameters.begin();
1452 set_vpot_parameter (*i);
1453 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
1454 if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter().type())) {
1458 for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
1459 if ((*i) == ac->parameter().type()) {
1463 if ((*i) == PhaseAutomation && _route->phase_invert().size() > 1) {
1464 // There are more than one channel of phase
1465 if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
1466 _route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
1467 set_vpot_parameter (*i);
1470 _route->phase_control()->set_channel(0);
1473 /* move to the next mode in the list, or back to the start (which will
1474 also happen if the current mode is not in the current pot mode list)
1477 if (i != possible_trim_parameters.end()) {
1481 if (i == possible_trim_parameters.end()) {
1482 i = possible_trim_parameters.begin();
1484 set_vpot_parameter (*i);
1485 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
1486 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1490 p = _route->nth_send (_current_send + 1);
1491 if (p && p->name() != "Monitor 1") {
1496 set_vpot_parameter (SendAutomation);
1501 Strip::subview_mode_changed ()
1503 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1505 subview_connections.drop_connections ();
1507 switch (_surface->mcp().subview_mode()) {
1508 case MackieControlProtocol::None:
1509 set_vpot_parameter (vpot_parameter);
1510 notify_metering_state_changed ();
1514 case MackieControlProtocol::EQ:
1518 /* leave it as it was */
1522 case MackieControlProtocol::Dynamics:
1526 /* leave it as it was */
1533 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1539 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1540 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1541 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1542 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1543 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1544 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1546 uint32_t pos = _surface->mcp().global_index (*this);
1548 /* we will control the pos-th available parameter, from the list in the
1549 * order shown above.
1552 vector<boost::shared_ptr<AutomationControl> > available;
1553 vector<AutomationType> params;
1555 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1556 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1557 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1558 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1559 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1560 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1562 if (pos >= available.size()) {
1563 /* this knob is not needed to control the available parameters */
1564 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1565 _surface->write (display (0, string()));
1566 _surface->write (display (1, string()));
1570 boost::shared_ptr<AutomationControl> pc;
1571 AutomationType param;
1573 pc = available[pos];
1574 param = params[pos];
1576 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
1577 _vpot->set_control (pc);
1587 pot_id = r->comp_speed_name (mc->get_value());
1608 if (!pot_id.empty()) {
1609 _surface->write (display (0, pot_id));
1612 notify_dyn_change (param, true, false);
1616 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1618 uint32_t bands = r->eq_band_cnt ();
1621 /* should never get here */
1625 /* figure out how many params per band are available */
1627 boost::shared_ptr<AutomationControl> pc;
1628 uint32_t params_per_band = 0;
1630 if ((pc = r->eq_gain_controllable (0))) {
1631 params_per_band += 1;
1633 if ((pc = r->eq_freq_controllable (0))) {
1634 params_per_band += 1;
1636 if ((pc = r->eq_q_controllable (0))) {
1637 params_per_band += 1;
1639 if ((pc = r->eq_shape_controllable (0))) {
1640 params_per_band += 1;
1643 /* pick the one for this strip, based on its global position across
1649 const uint32_t total_band_parameters = bands * params_per_band;
1650 const uint32_t global_pos = _surface->mcp().global_index (*this);
1651 AutomationType param = NullAutomation;
1656 if (global_pos < total_band_parameters) {
1658 /* show a parameter for an EQ band */
1660 const uint32_t parameter = global_pos % params_per_band;
1661 eq_band = global_pos / params_per_band;
1662 band_name = r->eq_band_name (eq_band);
1664 switch (parameter) {
1666 pc = r->eq_gain_controllable (eq_band);
1670 pc = r->eq_freq_controllable (eq_band);
1671 param = EQFrequency;
1674 pc = r->eq_q_controllable (eq_band);
1678 pc = r->eq_shape_controllable (eq_band);
1685 /* show a non-band parameter (HPF or enable)
1688 uint32_t parameter = global_pos - total_band_parameters;
1690 switch (parameter) {
1691 case 0: /* first control after band parameters */
1692 pc = r->eq_hpf_controllable();
1695 case 1: /* second control after band parameters */
1696 pc = r->eq_enable_controllable();
1700 /* nothing to control */
1701 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1702 _surface->write (display (0, string()));
1703 _surface->write (display (1, string()));
1712 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1713 _vpot->set_control (pc);
1719 pot_id = band_name + "Gain";
1722 pot_id = band_name + "Freq";
1725 pot_id = band_name + " Q";
1728 pot_id = band_name + " Shp";
1740 if (!pot_id.empty()) {
1741 _surface->write (display (0, pot_id));
1744 notify_eq_change (param, eq_band, true);
1749 Strip::set_vpot_parameter (AutomationType p)
1751 if (!_route || (p == NullAutomation)) {
1752 control_by_parameter[vpot_parameter] = 0;
1753 vpot_parameter = NullAutomation;
1754 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1755 _surface->write (display (1, string()));
1759 boost::shared_ptr<AutomationControl> pan_control;
1761 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1763 reset_saved_values ();
1765 /* unset any mapping between the vpot and any existing parameters */
1767 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1769 if (i != control_by_parameter.end() && i->second == _vpot) {
1775 case PanAzimuthAutomation:
1776 if ((pan_control = _route->pan_azimuth_control ())) {
1777 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1778 _pan_mode = PanAzimuthAutomation;
1779 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1780 /* gain to vpot, pan azi to fader */
1781 _vpot->set_control (_route->group_gain_control());
1782 vpot_parameter = GainAutomation;
1783 control_by_parameter[GainAutomation] = _vpot;
1784 _fader->set_control (pan_control);
1785 control_by_parameter[PanAzimuthAutomation] = _fader;
1787 _fader->set_control (boost::shared_ptr<AutomationControl>());
1788 control_by_parameter[PanAzimuthAutomation] = 0;
1791 /* gain to fader, pan azi to vpot */
1792 vpot_parameter = PanAzimuthAutomation;
1793 _fader->set_control (_route->group_gain_control());
1794 control_by_parameter[GainAutomation] = _fader;
1795 _vpot->set_control (pan_control);
1796 control_by_parameter[PanAzimuthAutomation] = _vpot;
1799 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1800 control_by_parameter[PanAzimuthAutomation] = 0;
1804 case PanWidthAutomation:
1805 if ((pan_control = _route->pan_width_control ())) {
1806 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1807 _pan_mode = PanWidthAutomation;
1808 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1809 /* gain to vpot, pan width to fader */
1810 _vpot->set_control (_route->group_gain_control());
1811 vpot_parameter = GainAutomation;
1812 control_by_parameter[GainAutomation] = _vpot;
1813 _fader->set_control (pan_control);
1814 control_by_parameter[PanWidthAutomation] = _fader;
1816 _fader->set_control (boost::shared_ptr<AutomationControl>());
1817 control_by_parameter[PanWidthAutomation] = 0;
1820 /* gain to fader, pan width to vpot */
1821 vpot_parameter = PanWidthAutomation;
1822 _fader->set_control (_route->group_gain_control());
1823 control_by_parameter[GainAutomation] = _fader;
1824 _vpot->set_control (pan_control);
1825 control_by_parameter[PanWidthAutomation] = _vpot;
1828 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1829 control_by_parameter[PanWidthAutomation] = 0;
1833 case PanElevationAutomation:
1835 case PanFrontBackAutomation:
1837 case PanLFEAutomation:
1839 case TrimAutomation:
1840 _trim_mode = TrimAutomation;
1841 vpot_parameter = TrimAutomation;
1842 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1843 /* gain to vpot, trim to fader */
1844 _vpot->set_control (_route->group_gain_control());
1845 control_by_parameter[GainAutomation] = _vpot;
1846 if (_route->trim() && route()->trim()->active()) {
1847 _fader->set_control (_route->trim_control());
1848 control_by_parameter[TrimAutomation] = _fader;
1850 _fader->set_control (boost::shared_ptr<AutomationControl>());
1851 control_by_parameter[TrimAutomation] = 0;
1854 /* gain to fader, trim to vpot */
1855 _fader->set_control (_route->group_gain_control());
1856 control_by_parameter[GainAutomation] = _fader;
1857 if (_route->trim() && route()->trim()->active()) {
1858 _vpot->set_control (_route->trim_control());
1859 control_by_parameter[TrimAutomation] = _vpot;
1861 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1862 control_by_parameter[TrimAutomation] = 0;
1866 case PhaseAutomation:
1867 _trim_mode = PhaseAutomation;
1868 vpot_parameter = PhaseAutomation;
1869 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1870 /* gain to vpot, phase to fader */
1871 _vpot->set_control (_route->group_gain_control());
1872 control_by_parameter[GainAutomation] = _vpot;
1873 if (_route->phase_invert().size()) {
1874 _fader->set_control (_route->phase_control());
1875 control_by_parameter[PhaseAutomation] = _fader;
1877 _fader->set_control (boost::shared_ptr<AutomationControl>());
1878 control_by_parameter[PhaseAutomation] = 0;
1881 /* gain to fader, phase to vpot */
1882 _fader->set_control (_route->group_gain_control());
1883 control_by_parameter[GainAutomation] = _fader;
1884 if (_route->phase_invert().size()) {
1885 _vpot->set_control (_route->phase_control());
1886 control_by_parameter[PhaseAutomation] = _vpot;
1888 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1889 control_by_parameter[PhaseAutomation] = 0;
1893 case SendAutomation:
1894 if (!Profile->get_mixbus()) {
1895 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1896 // gain to vpot, send to fader
1897 _vpot->set_control (_route->group_gain_control());
1898 control_by_parameter[GainAutomation] = _vpot;
1899 // test for send to control
1900 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1901 if (p && p->name() != "Monitor 1") {
1902 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1903 boost::shared_ptr<Amp> a = s->amp();
1904 _fader->set_control (a->gain_control());
1905 // connect to signal
1906 send_connections.drop_connections ();
1907 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1908 control_by_parameter[SendAutomation] = _fader;
1910 _fader->set_control (boost::shared_ptr<AutomationControl>());
1911 control_by_parameter[SendAutomation] = 0;
1914 // gain to fader, send to vpot
1915 _fader->set_control (_route->group_gain_control());
1916 control_by_parameter[GainAutomation] = _fader;
1917 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1918 if (p && p->name() != "Monitor 1") {
1919 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1920 boost::shared_ptr<Amp> a = s->amp();
1921 _vpot->set_control (a->gain_control());
1922 // connect to signal
1923 send_connections.drop_connections ();
1924 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1925 control_by_parameter[SendAutomation] = _vpot;
1927 // gain to fader, send to vpot
1928 _fader->set_control (_route->group_gain_control());
1929 control_by_parameter[GainAutomation] = _fader;
1930 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1931 if (p && p->name() != "Monitor 1") {
1932 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1933 boost::shared_ptr<Amp> a = s->amp();
1934 _vpot->set_control (a->gain_control());
1935 // connect to signal
1936 send_connections.drop_connections ();
1937 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1938 control_by_parameter[SendAutomation] = _vpot;
1940 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1941 control_by_parameter[SendAutomation] = 0;
1948 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1953 _surface->write (display (1, vpot_mode_string()));
1957 Strip::is_midi_track () const
1959 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1963 Strip::reset_saved_values ()
1965 _last_pan_azi_position_written = -1.0;
1966 _last_pan_width_position_written = -1.0;
1967 _last_gain_position_written = -1.0;
1968 _last_trim_position_written = -1.0;
1973 Strip::notify_metering_state_changed()
1975 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1979 if (!_route || !_meter) {
1983 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1984 bool metering_active = _surface->mcp().metering_active ();
1986 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1990 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1992 if (!transport_is_rolling || !metering_active) {
1993 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1994 notify_panner_azi_changed (true);
1997 _transport_is_rolling = transport_is_rolling;
1998 _metering_active = metering_active;