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 */
525 string fullname = string();
527 // make sure first three strips get cleared of view mode
532 fullname = _route->name();
536 if (fullname.length() <= 6) {
539 line1 = PBD::short_version (fullname, 6);
542 _surface->write (display (0, line1));
546 Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
548 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
551 /* not in subview mode */
555 if (_surface->mcp().subview_mode() != MackieControlProtocol::EQ) {
556 /* no longer in EQ subview mode */
560 boost::shared_ptr<AutomationControl> control;
564 control = r->eq_gain_controllable (band);
567 control = r->eq_freq_controllable (band);
570 control = r->eq_q_controllable (band);
573 control = r->eq_shape_controllable (band);
576 control = r->eq_hpf_controllable ();
579 control = r->eq_enable_controllable ();
586 float val = control->get_value();
587 queue_parameter_display (type, val);
588 /* update pot/encoder */
589 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
594 Strip::notify_dyn_change (AutomationType type, bool force_update, bool propagate_mode)
596 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
599 /* not in subview mode */
603 if (_surface->mcp().subview_mode() != MackieControlProtocol::Dynamics) {
604 /* no longer in EQ subview mode */
608 boost::shared_ptr<AutomationControl> control;
609 bool reset_all = false;
613 control = r->comp_threshold_controllable ();
616 control = r->comp_speed_controllable ();
619 control = r->comp_mode_controllable ();
623 control = r->comp_makeup_controllable ();
626 control = r->comp_redux_controllable ();
629 control = r->comp_enable_controllable ();
635 if (propagate_mode && reset_all) {
636 _surface->subview_mode_changed ();
640 float val = control->get_value();
641 queue_parameter_display (type, val);
642 /* update pot/encoder */
643 _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
648 Strip::notify_panner_azi_changed (bool force_update)
654 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
656 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
659 _surface->write (_vpot->zero());
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 ();
705 _surface->write (_vpot->zero());
709 Control* control = 0;
710 ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
712 if (i == control_by_parameter.end()) {
718 double pos = pan_control->internal_to_interface (pan_control->get_value());
720 if (force_update || pos != _last_pan_width_position_written) {
722 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
724 if (control == _fader) {
725 if (!control->in_use()) {
726 _surface->write (_fader->set_position (pos));
727 queue_parameter_display (PanWidthAutomation, pos);
731 } else if (control == _vpot) {
732 _surface->write (_vpot->set (pos, true, Pot::spread));
733 queue_parameter_display (PanWidthAutomation, pos);
736 _last_pan_width_position_written = pos;
741 Strip::select_event (Button&, ButtonState bs)
743 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
747 int ms = _surface->mcp().main_modifier_state();
749 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
750 _controls_locked = !_controls_locked;
751 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
752 block_vpot_mode_display_for (1000);
756 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
757 /* reset to default */
758 boost::shared_ptr<AutomationControl> ac = _fader->control ();
760 ac->set_value (ac->normal());
765 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
766 _surface->mcp().add_down_select_button (_surface->number(), _index);
767 _surface->mcp().select_range ();
770 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
771 _surface->mcp().remove_down_select_button (_surface->number(), _index);
776 Strip::vselect_event (Button&, ButtonState bs)
778 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
780 /* subview mode: vpot press acts like a button for toggle parameters */
786 boost::shared_ptr<AutomationControl> control = _vpot->control ();
791 if (control->toggled()) {
792 if (control->toggled()) {
793 control->set_value (!control->get_value());
802 int ms = _surface->mcp().main_modifier_state();
804 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
806 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
810 /* reset to default/normal value */
811 ac->set_value (ac->normal());
816 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
824 Strip::fader_touch_event (Button&, ButtonState bs)
826 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
830 boost::shared_ptr<AutomationControl> ac = _fader->control ();
832 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
834 ac->set_value (ac->normal());
838 _fader->set_in_use (true);
839 _fader->start_touch (_surface->mcp().transport_frame());
842 queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
848 _fader->set_in_use (false);
849 _fader->stop_touch (_surface->mcp().transport_frame(), true);
856 Strip::handle_button (Button& button, ButtonState bs)
858 boost::shared_ptr<AutomationControl> control;
861 button.set_in_use (true);
863 button.set_in_use (false);
866 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
868 switch (button.bid()) {
870 select_event (button, bs);
873 case Button::VSelect:
874 vselect_event (button, bs);
877 case Button::FaderTouch:
878 fader_touch_event (button, bs);
882 if ((control = button.control ())) {
884 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
885 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
888 int ms = _surface->mcp().main_modifier_state();
890 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
891 /* reset to default/normal value */
892 new_value = control->normal();
894 new_value = control->get_value() ? 0.0 : 1.0;
897 /* get all controls that either have their
898 * button down or are within a range of
899 * several down buttons
902 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
905 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
906 controls.size(), control->parameter().type(), new_value));
910 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
911 (*c)->set_value (new_value);
915 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
916 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
924 Strip::queue_parameter_display (AutomationType type, float val)
926 RedisplayRequest req;
931 redisplay_requests.write (&req, 1);
935 Strip::do_parameter_display (AutomationType type, float val)
937 bool screen_hold = false;
943 _surface->write (display (1, " -inf "));
945 float dB = accurate_coefficient_to_dB (val);
946 snprintf (buf, sizeof (buf), "%6.1f", dB);
947 _surface->write (display (1, buf));
952 case PanAzimuthAutomation:
953 if (Profile->get_mixbus()) {
954 snprintf (buf, sizeof (buf), "%2.1f", val);
955 _surface->write (display (1, buf));
959 boost::shared_ptr<Pannable> p = _route->pannable();
960 if (p && _route->panner()) {
961 string str =_route->panner()->value_as_string (p->pan_azimuth_control);
962 _surface->write (display (1, str));
969 case PanWidthAutomation:
971 snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
972 _surface->write (display (1, buf));
979 float dB = accurate_coefficient_to_dB (val);
980 snprintf (buf, sizeof (buf), "%6.1f", dB);
981 _surface->write (display (1, buf));
986 case PhaseAutomation:
988 if (_route->phase_control()->get_value() < 0.5) {
989 _surface->write (display (1, "Normal"));
991 _surface->write (display (1, "Invert"));
999 _surface->write (display (1, " -inf "));
1001 float dB = accurate_coefficient_to_dB (val);
1002 snprintf (buf, sizeof (buf), "%6.1f", dB);
1003 _surface->write (display (1, buf));
1016 snprintf (buf, sizeof (buf), "%6.1f", val);
1017 _surface->write (display (1, buf));
1023 _surface->write (display (1, "on"));
1025 _surface->write (display (1, "off"));
1029 if (_surface->mcp().subview_route()) {
1030 _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
1038 block_vpot_mode_display_for (1000);
1043 Strip::handle_fader_touch (Fader& fader, bool touch_on)
1046 fader.start_touch (_surface->mcp().transport_frame());
1048 fader.stop_touch (_surface->mcp().transport_frame(), false);
1053 Strip::handle_fader (Fader& fader, float position)
1055 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
1056 boost::shared_ptr<AutomationControl> ac = fader.control();
1061 fader.set_value (position);
1063 /* From the Mackie Control MIDI implementation docs:
1065 In order to ensure absolute synchronization with the host software,
1066 Mackie Control uses a closed-loop servo system for the faders,
1067 meaning the faders will always move to their last received position.
1068 When a host receives a Fader Position Message, it must then
1069 re-transmit that message to the Mackie Control or else the faders
1070 will return to their last position.
1073 _surface->write (fader.set_position (position));
1077 Strip::handle_pot (Pot& pot, float delta)
1079 /* Pots only emit events when they move, not when they
1080 stop moving. So to get a stop event, we need to use a timeout.
1083 boost::shared_ptr<AutomationControl> ac = pot.control();
1087 double p = pot.get_value ();
1089 // fader and pot should be the same and fader is hard coded 0 -> 1
1096 Strip::periodic (ARDOUR::microseconds_t now)
1098 bool reshow_vpot_mode = false;
1099 bool reshow_name = false;
1100 bool good_strip = true;
1103 // view mode may cover as many as 3 strips
1104 // needs to be cleared when there are less than 3 routes
1112 if (_block_screen_redisplay_until >= now) {
1113 if (_surface->mcp().device_info().has_separate_meters()) {
1116 /* no drawing here, for now */
1119 } else if (_block_screen_redisplay_until) {
1121 /* timeout reached, reset */
1123 _block_screen_redisplay_until = 0;
1124 reshow_vpot_mode = (true && good_strip);
1128 if (_block_vpot_mode_redisplay_until >= now) {
1130 } else if (_block_vpot_mode_redisplay_until) {
1132 /* timeout reached, reset */
1134 _block_vpot_mode_redisplay_until = 0;
1135 reshow_vpot_mode = (true && good_strip);
1142 if (reshow_vpot_mode) {
1143 return_to_vpot_mode_display ();
1144 } else if (good_strip) {
1145 /* no point doing this if we just switched back to vpot mode
1147 update_automation ();
1157 Strip::redisplay (ARDOUR::microseconds_t now)
1159 RedisplayRequest req;
1160 bool have_request = false;
1162 while (redisplay_requests.read (&req, 1) == 1) {
1164 have_request = true;
1167 if (_block_screen_redisplay_until >= now) {
1172 do_parameter_display (req.type, req.val);
1177 Strip::update_automation ()
1183 ARDOUR::AutoState state = _route->gain_control()->automation_state();
1185 if (state == Touch || state == Play) {
1186 notify_gain_changed (false);
1189 boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1191 state = pan_control->automation_state ();
1192 if (state == Touch || state == Play) {
1193 notify_panner_azi_changed (false);
1197 pan_control = _route->pan_width_control ();
1199 state = pan_control->automation_state ();
1200 if (state == Touch || state == Play) {
1201 notify_panner_width_changed (false);
1205 if (_route->trim() && route()->trim()->active()) {
1206 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1207 if (trim_state == Touch || trim_state == Play) {
1208 notify_trim_changed (false);
1214 Strip::update_meter ()
1216 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1220 if (_meter && _transport_is_rolling && _metering_active) {
1221 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1222 _meter->send_update (*_surface, dB);
1229 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1230 _surface->write ((*it)->zero ());
1233 _surface->write (blank_display (0));
1234 _surface->write (blank_display (1));
1238 Strip::blank_display (uint32_t line_number)
1240 return display (line_number, string());
1244 Strip::display (uint32_t line_number, const std::string& line)
1246 assert (line_number <= 1);
1248 MidiByteArray retval;
1250 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1253 retval << _surface->sysex_hdr();
1257 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1258 retval << (_index * 7 + (line_number * 0x38));
1260 // ascii data to display. @param line is UTF-8
1261 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1262 string::size_type len = ascii.length();
1264 ascii = ascii.substr (0, 6);
1268 // pad with " " out to 6 chars
1269 for (int i = len; i < 6; ++i) {
1273 // column spacer, unless it's the right-hand column
1279 retval << MIDI::eox;
1285 Strip::lock_controls ()
1287 _controls_locked = true;
1291 Strip::unlock_controls ()
1293 _controls_locked = false;
1297 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1299 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1300 if ((*i) == _route) {
1301 _surface->write (_select->set_state (on));
1306 _surface->write (_select->set_state (off));
1310 Strip::vpot_mode_string ()
1312 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1317 if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1319 } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1321 } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1322 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1323 } else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
1324 // should be bus name
1325 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1329 } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1331 } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1333 } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1335 } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1337 } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1341 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1349 Strip::potmode_changed (bool notify)
1356 int pm = _surface->mcp().pot_mode();
1358 case MackieControlProtocol::Pan:
1359 // This needs to set current pan mode (azimuth or width... or whatever)
1360 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1361 set_vpot_parameter (_pan_mode);
1363 case MackieControlProtocol::Trim:
1364 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
1365 set_vpot_parameter (_trim_mode);
1367 case MackieControlProtocol::Send:
1368 // _current_send has the number of the send we will show
1369 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
1370 set_vpot_parameter (SendAutomation);
1380 Strip::block_screen_display_for (uint32_t msecs)
1382 _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1386 Strip::block_vpot_mode_display_for (uint32_t msecs)
1388 _block_vpot_mode_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1392 Strip::return_to_vpot_mode_display ()
1394 /* returns the second line of the two-line per-strip display
1395 back the mode where it shows what the VPot controls.
1398 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1399 /* do nothing - second line shows value of current subview parameter */
1401 } else if (_route) {
1402 _surface->write (display (1, vpot_mode_string()));
1404 _surface->write (blank_display (1));
1409 Strip::next_pot_mode ()
1411 vector<AutomationType>::iterator i;
1413 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1414 /* do not change vpot mode while in flipped mode */
1415 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1416 _surface->write (display (1, "Flip"));
1417 block_vpot_mode_display_for (1000);
1422 boost::shared_ptr<AutomationControl> ac = _vpot->control();
1429 if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1431 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
1435 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1436 if ((*i) == ac->parameter().type()) {
1441 /* move to the next mode in the list, or back to the start (which will
1442 also happen if the current mode is not in the current pot mode list)
1445 if (i != possible_pot_parameters.end()) {
1449 if (i == possible_pot_parameters.end()) {
1450 i = possible_pot_parameters.begin();
1453 set_vpot_parameter (*i);
1454 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
1455 if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter().type())) {
1459 for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
1460 if ((*i) == ac->parameter().type()) {
1464 if ((*i) == PhaseAutomation && _route->phase_invert().size() > 1) {
1465 // There are more than one channel of phase
1466 if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
1467 _route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
1468 set_vpot_parameter (*i);
1471 _route->phase_control()->set_channel(0);
1474 /* move to the next mode in the list, or back to the start (which will
1475 also happen if the current mode is not in the current pot mode list)
1478 if (i != possible_trim_parameters.end()) {
1482 if (i == possible_trim_parameters.end()) {
1483 i = possible_trim_parameters.begin();
1485 set_vpot_parameter (*i);
1486 } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
1487 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1491 p = _route->nth_send (_current_send + 1);
1492 if (p && p->name() != "Monitor 1") {
1497 set_vpot_parameter (SendAutomation);
1502 Strip::subview_mode_changed ()
1504 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1506 subview_connections.drop_connections ();
1508 switch (_surface->mcp().subview_mode()) {
1509 case MackieControlProtocol::None:
1510 set_vpot_parameter (vpot_parameter);
1511 notify_metering_state_changed ();
1515 case MackieControlProtocol::EQ:
1519 /* leave it as it was */
1523 case MackieControlProtocol::Dynamics:
1527 /* leave it as it was */
1534 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1540 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1541 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1542 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1543 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1544 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1545 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1547 uint32_t pos = _surface->mcp().global_index (*this);
1549 /* we will control the pos-th available parameter, from the list in the
1550 * order shown above.
1553 vector<boost::shared_ptr<AutomationControl> > available;
1554 vector<AutomationType> params;
1556 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1557 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1558 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1559 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1560 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1561 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1563 if (pos >= available.size()) {
1564 /* this knob is not needed to control the available parameters */
1565 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1566 _surface->write (display (0, string()));
1567 _surface->write (display (1, string()));
1571 boost::shared_ptr<AutomationControl> pc;
1572 AutomationType param;
1574 pc = available[pos];
1575 param = params[pos];
1577 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
1578 _vpot->set_control (pc);
1588 pot_id = r->comp_speed_name (mc->get_value());
1609 if (!pot_id.empty()) {
1610 _surface->write (display (0, pot_id));
1613 notify_dyn_change (param, true, false);
1617 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1619 uint32_t bands = r->eq_band_cnt ();
1622 /* should never get here */
1626 /* figure out how many params per band are available */
1628 boost::shared_ptr<AutomationControl> pc;
1629 uint32_t params_per_band = 0;
1631 if ((pc = r->eq_gain_controllable (0))) {
1632 params_per_band += 1;
1634 if ((pc = r->eq_freq_controllable (0))) {
1635 params_per_band += 1;
1637 if ((pc = r->eq_q_controllable (0))) {
1638 params_per_band += 1;
1640 if ((pc = r->eq_shape_controllable (0))) {
1641 params_per_band += 1;
1644 /* pick the one for this strip, based on its global position across
1650 const uint32_t total_band_parameters = bands * params_per_band;
1651 const uint32_t global_pos = _surface->mcp().global_index (*this);
1652 AutomationType param = NullAutomation;
1657 if (global_pos < total_band_parameters) {
1659 /* show a parameter for an EQ band */
1661 const uint32_t parameter = global_pos % params_per_band;
1662 eq_band = global_pos / params_per_band;
1663 band_name = r->eq_band_name (eq_band);
1665 switch (parameter) {
1667 pc = r->eq_gain_controllable (eq_band);
1671 pc = r->eq_freq_controllable (eq_band);
1672 param = EQFrequency;
1675 pc = r->eq_q_controllable (eq_band);
1679 pc = r->eq_shape_controllable (eq_band);
1686 /* show a non-band parameter (HPF or enable)
1689 uint32_t parameter = global_pos - total_band_parameters;
1691 switch (parameter) {
1692 case 0: /* first control after band parameters */
1693 pc = r->eq_hpf_controllable();
1696 case 1: /* second control after band parameters */
1697 pc = r->eq_enable_controllable();
1701 /* nothing to control */
1702 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1703 _surface->write (display (0, string()));
1704 _surface->write (display (1, string()));
1713 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1714 _vpot->set_control (pc);
1720 pot_id = band_name + "Gain";
1723 pot_id = band_name + "Freq";
1726 pot_id = band_name + " Q";
1729 pot_id = band_name + " Shp";
1741 if (!pot_id.empty()) {
1742 _surface->write (display (0, pot_id));
1745 notify_eq_change (param, eq_band, true);
1750 Strip::set_vpot_parameter (AutomationType p)
1752 if (!_route || (p == NullAutomation)) {
1753 control_by_parameter[vpot_parameter] = 0;
1754 vpot_parameter = NullAutomation;
1755 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1756 _surface->write (display (1, string()));
1760 boost::shared_ptr<AutomationControl> pan_control;
1762 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1764 reset_saved_values ();
1766 /* unset any mapping between the vpot and any existing parameters */
1768 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1770 if (i != control_by_parameter.end() && i->second == _vpot) {
1776 case PanAzimuthAutomation:
1777 if ((pan_control = _route->pan_azimuth_control ())) {
1778 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1779 _pan_mode = PanAzimuthAutomation;
1780 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1781 /* gain to vpot, pan azi to fader */
1782 _vpot->set_control (_route->group_gain_control());
1783 vpot_parameter = GainAutomation;
1784 control_by_parameter[GainAutomation] = _vpot;
1785 _fader->set_control (pan_control);
1786 control_by_parameter[PanAzimuthAutomation] = _fader;
1788 _fader->set_control (boost::shared_ptr<AutomationControl>());
1789 control_by_parameter[PanAzimuthAutomation] = 0;
1792 /* gain to fader, pan azi to vpot */
1793 vpot_parameter = PanAzimuthAutomation;
1794 _fader->set_control (_route->group_gain_control());
1795 control_by_parameter[GainAutomation] = _fader;
1796 _vpot->set_control (pan_control);
1797 control_by_parameter[PanAzimuthAutomation] = _vpot;
1800 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1801 control_by_parameter[PanAzimuthAutomation] = 0;
1805 case PanWidthAutomation:
1806 if ((pan_control = _route->pan_width_control ())) {
1807 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1808 _pan_mode = PanWidthAutomation;
1809 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1810 /* gain to vpot, pan width to fader */
1811 _vpot->set_control (_route->group_gain_control());
1812 vpot_parameter = GainAutomation;
1813 control_by_parameter[GainAutomation] = _vpot;
1814 _fader->set_control (pan_control);
1815 control_by_parameter[PanWidthAutomation] = _fader;
1817 _fader->set_control (boost::shared_ptr<AutomationControl>());
1818 control_by_parameter[PanWidthAutomation] = 0;
1821 /* gain to fader, pan width to vpot */
1822 vpot_parameter = PanWidthAutomation;
1823 _fader->set_control (_route->group_gain_control());
1824 control_by_parameter[GainAutomation] = _fader;
1825 _vpot->set_control (pan_control);
1826 control_by_parameter[PanWidthAutomation] = _vpot;
1829 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1830 control_by_parameter[PanWidthAutomation] = 0;
1834 case PanElevationAutomation:
1836 case PanFrontBackAutomation:
1838 case PanLFEAutomation:
1840 case TrimAutomation:
1841 _trim_mode = TrimAutomation;
1842 vpot_parameter = TrimAutomation;
1843 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1844 /* gain to vpot, trim to fader */
1845 _vpot->set_control (_route->group_gain_control());
1846 control_by_parameter[GainAutomation] = _vpot;
1847 if (_route->trim() && route()->trim()->active()) {
1848 _fader->set_control (_route->trim_control());
1849 control_by_parameter[TrimAutomation] = _fader;
1851 _fader->set_control (boost::shared_ptr<AutomationControl>());
1852 control_by_parameter[TrimAutomation] = 0;
1855 /* gain to fader, trim to vpot */
1856 _fader->set_control (_route->group_gain_control());
1857 control_by_parameter[GainAutomation] = _fader;
1858 if (_route->trim() && route()->trim()->active()) {
1859 _vpot->set_control (_route->trim_control());
1860 control_by_parameter[TrimAutomation] = _vpot;
1862 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1863 control_by_parameter[TrimAutomation] = 0;
1867 case PhaseAutomation:
1868 _trim_mode = PhaseAutomation;
1869 vpot_parameter = PhaseAutomation;
1870 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1871 /* gain to vpot, phase to fader */
1872 _vpot->set_control (_route->group_gain_control());
1873 control_by_parameter[GainAutomation] = _vpot;
1874 if (_route->phase_invert().size()) {
1875 _fader->set_control (_route->phase_control());
1876 control_by_parameter[PhaseAutomation] = _fader;
1878 _fader->set_control (boost::shared_ptr<AutomationControl>());
1879 control_by_parameter[PhaseAutomation] = 0;
1882 /* gain to fader, phase to vpot */
1883 _fader->set_control (_route->group_gain_control());
1884 control_by_parameter[GainAutomation] = _fader;
1885 if (_route->phase_invert().size()) {
1886 _vpot->set_control (_route->phase_control());
1887 control_by_parameter[PhaseAutomation] = _vpot;
1889 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1890 control_by_parameter[PhaseAutomation] = 0;
1894 case SendAutomation:
1895 if (!Profile->get_mixbus()) {
1896 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1897 // gain to vpot, send to fader
1898 _vpot->set_control (_route->group_gain_control());
1899 control_by_parameter[GainAutomation] = _vpot;
1900 // test for send to control
1901 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1902 if (p && p->name() != "Monitor 1") {
1903 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1904 boost::shared_ptr<Amp> a = s->amp();
1905 _fader->set_control (a->gain_control());
1906 // connect to signal
1907 send_connections.drop_connections ();
1908 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1909 control_by_parameter[SendAutomation] = _fader;
1911 _fader->set_control (boost::shared_ptr<AutomationControl>());
1912 control_by_parameter[SendAutomation] = 0;
1915 // gain to fader, send to vpot
1916 _fader->set_control (_route->group_gain_control());
1917 control_by_parameter[GainAutomation] = _fader;
1918 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1919 if (p && p->name() != "Monitor 1") {
1920 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1921 boost::shared_ptr<Amp> a = s->amp();
1922 _vpot->set_control (a->gain_control());
1923 // connect to signal
1924 send_connections.drop_connections ();
1925 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1926 control_by_parameter[SendAutomation] = _vpot;
1928 // gain to fader, send to vpot
1929 _fader->set_control (_route->group_gain_control());
1930 control_by_parameter[GainAutomation] = _fader;
1931 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1932 if (p && p->name() != "Monitor 1") {
1933 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1934 boost::shared_ptr<Amp> a = s->amp();
1935 _vpot->set_control (a->gain_control());
1936 // connect to signal
1937 send_connections.drop_connections ();
1938 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1939 control_by_parameter[SendAutomation] = _vpot;
1941 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1942 control_by_parameter[SendAutomation] = 0;
1949 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1954 _surface->write (display (1, vpot_mode_string()));
1958 Strip::is_midi_track () const
1960 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1964 Strip::reset_saved_values ()
1966 _last_pan_azi_position_written = -1.0;
1967 _last_pan_width_position_written = -1.0;
1968 _last_gain_position_written = -1.0;
1969 _last_trim_position_written = -1.0;
1974 Strip::notify_metering_state_changed()
1976 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1980 if (!_route || !_meter) {
1984 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1985 bool metering_active = _surface->mcp().metering_active ();
1987 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1991 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1993 if (!transport_is_rolling || !metering_active) {
1994 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1995 notify_panner_azi_changed (true);
1998 _transport_is_rolling = transport_is_rolling;
1999 _metering_active = metering_active;