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(), Controllable::NoGroup);
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(), Controllable::NoGroup);
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(), Controllable::NoGroup);
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(), Controllable::NoGroup);
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, Controllable::NoGroup);
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);
1493 if (p->name() == "Monitor 1") { // skip monitor
1494 p = _route->nth_send (_current_send + 1);
1504 set_vpot_parameter (SendAutomation);
1509 Strip::subview_mode_changed ()
1511 boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1513 subview_connections.drop_connections ();
1515 switch (_surface->mcp().subview_mode()) {
1516 case MackieControlProtocol::None:
1517 set_vpot_parameter (vpot_parameter);
1518 notify_metering_state_changed ();
1522 case MackieControlProtocol::EQ:
1526 /* leave it as it was */
1530 case MackieControlProtocol::Dynamics:
1534 /* leave it as it was */
1541 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1547 boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1548 boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1549 boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1550 boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1551 boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1552 boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1554 uint32_t pos = _surface->mcp().global_index (*this);
1556 /* we will control the pos-th available parameter, from the list in the
1557 * order shown above.
1560 vector<boost::shared_ptr<AutomationControl> > available;
1561 vector<AutomationType> params;
1563 if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1564 if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1565 if (mc) { available.push_back (mc); params.push_back (CompMode); }
1566 if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1567 if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1568 if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1570 if (pos >= available.size()) {
1571 /* this knob is not needed to control the available parameters */
1572 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1573 _surface->write (display (0, string()));
1574 _surface->write (display (1, string()));
1578 boost::shared_ptr<AutomationControl> pc;
1579 AutomationType param;
1581 pc = available[pos];
1582 param = params[pos];
1584 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
1585 _vpot->set_control (pc);
1595 pot_id = r->comp_speed_name (mc->get_value());
1616 if (!pot_id.empty()) {
1617 _surface->write (display (0, pot_id));
1620 notify_dyn_change (param, true, false);
1624 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1626 uint32_t bands = r->eq_band_cnt ();
1629 /* should never get here */
1633 /* figure out how many params per band are available */
1635 boost::shared_ptr<AutomationControl> pc;
1636 uint32_t params_per_band = 0;
1638 if ((pc = r->eq_gain_controllable (0))) {
1639 params_per_band += 1;
1641 if ((pc = r->eq_freq_controllable (0))) {
1642 params_per_band += 1;
1644 if ((pc = r->eq_q_controllable (0))) {
1645 params_per_band += 1;
1647 if ((pc = r->eq_shape_controllable (0))) {
1648 params_per_band += 1;
1651 /* pick the one for this strip, based on its global position across
1657 const uint32_t total_band_parameters = bands * params_per_band;
1658 const uint32_t global_pos = _surface->mcp().global_index (*this);
1659 AutomationType param = NullAutomation;
1664 if (global_pos < total_band_parameters) {
1666 /* show a parameter for an EQ band */
1668 const uint32_t parameter = global_pos % params_per_band;
1669 eq_band = global_pos / params_per_band;
1670 band_name = r->eq_band_name (eq_band);
1672 switch (parameter) {
1674 pc = r->eq_gain_controllable (eq_band);
1678 pc = r->eq_freq_controllable (eq_band);
1679 param = EQFrequency;
1682 pc = r->eq_q_controllable (eq_band);
1686 pc = r->eq_shape_controllable (eq_band);
1693 /* show a non-band parameter (HPF or enable)
1696 uint32_t parameter = global_pos - total_band_parameters;
1698 switch (parameter) {
1699 case 0: /* first control after band parameters */
1700 pc = r->eq_hpf_controllable();
1703 case 1: /* second control after band parameters */
1704 pc = r->eq_enable_controllable();
1708 /* nothing to control */
1709 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1710 _surface->write (display (0, string()));
1711 _surface->write (display (1, string()));
1720 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1721 _vpot->set_control (pc);
1727 pot_id = band_name + "Gain";
1730 pot_id = band_name + "Freq";
1733 pot_id = band_name + " Q";
1736 pot_id = band_name + " Shp";
1748 if (!pot_id.empty()) {
1749 _surface->write (display (0, pot_id));
1752 notify_eq_change (param, eq_band, true);
1757 Strip::set_vpot_parameter (AutomationType p)
1759 if (!_route || (p == NullAutomation)) {
1760 control_by_parameter[vpot_parameter] = 0;
1761 vpot_parameter = NullAutomation;
1762 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1763 _surface->write (display (1, string()));
1767 boost::shared_ptr<AutomationControl> pan_control;
1769 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1771 reset_saved_values ();
1773 /* unset any mapping between the vpot and any existing parameters */
1775 for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1777 if (i != control_by_parameter.end() && i->second == _vpot) {
1783 case PanAzimuthAutomation:
1784 if ((pan_control = _route->pan_azimuth_control ())) {
1785 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1786 _pan_mode = PanAzimuthAutomation;
1787 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1788 /* gain to vpot, pan azi to fader */
1789 _vpot->set_control (_route->gain_control());
1790 vpot_parameter = GainAutomation;
1791 control_by_parameter[GainAutomation] = _vpot;
1792 _fader->set_control (pan_control);
1793 control_by_parameter[PanAzimuthAutomation] = _fader;
1795 _fader->set_control (boost::shared_ptr<AutomationControl>());
1796 control_by_parameter[PanAzimuthAutomation] = 0;
1799 /* gain to fader, pan azi to vpot */
1800 vpot_parameter = PanAzimuthAutomation;
1801 _fader->set_control (_route->gain_control());
1802 control_by_parameter[GainAutomation] = _fader;
1803 _vpot->set_control (pan_control);
1804 control_by_parameter[PanAzimuthAutomation] = _vpot;
1807 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1808 control_by_parameter[PanAzimuthAutomation] = 0;
1812 case PanWidthAutomation:
1813 if ((pan_control = _route->pan_width_control ())) {
1814 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1815 _pan_mode = PanWidthAutomation;
1816 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1817 /* gain to vpot, pan width to fader */
1818 _vpot->set_control (_route->gain_control());
1819 vpot_parameter = GainAutomation;
1820 control_by_parameter[GainAutomation] = _vpot;
1821 _fader->set_control (pan_control);
1822 control_by_parameter[PanWidthAutomation] = _fader;
1824 _fader->set_control (boost::shared_ptr<AutomationControl>());
1825 control_by_parameter[PanWidthAutomation] = 0;
1828 /* gain to fader, pan width to vpot */
1829 vpot_parameter = PanWidthAutomation;
1830 _fader->set_control (_route->gain_control());
1831 control_by_parameter[GainAutomation] = _fader;
1832 _vpot->set_control (pan_control);
1833 control_by_parameter[PanWidthAutomation] = _vpot;
1836 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1837 control_by_parameter[PanWidthAutomation] = 0;
1841 case PanElevationAutomation:
1843 case PanFrontBackAutomation:
1845 case PanLFEAutomation:
1847 case TrimAutomation:
1848 _trim_mode = TrimAutomation;
1849 vpot_parameter = TrimAutomation;
1850 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1851 /* gain to vpot, trim to fader */
1852 _vpot->set_control (_route->gain_control());
1853 control_by_parameter[GainAutomation] = _vpot;
1854 if (_route->trim() && route()->trim()->active()) {
1855 _fader->set_control (_route->trim_control());
1856 control_by_parameter[TrimAutomation] = _fader;
1858 _fader->set_control (boost::shared_ptr<AutomationControl>());
1859 control_by_parameter[TrimAutomation] = 0;
1862 /* gain to fader, trim to vpot */
1863 _fader->set_control (_route->gain_control());
1864 control_by_parameter[GainAutomation] = _fader;
1865 if (_route->trim() && route()->trim()->active()) {
1866 _vpot->set_control (_route->trim_control());
1867 control_by_parameter[TrimAutomation] = _vpot;
1869 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1870 control_by_parameter[TrimAutomation] = 0;
1874 case PhaseAutomation:
1875 _trim_mode = PhaseAutomation;
1876 vpot_parameter = PhaseAutomation;
1877 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1878 /* gain to vpot, phase to fader */
1879 _vpot->set_control (_route->gain_control());
1880 control_by_parameter[GainAutomation] = _vpot;
1881 if (_route->phase_invert().size()) {
1882 _fader->set_control (_route->phase_control());
1883 control_by_parameter[PhaseAutomation] = _fader;
1885 _fader->set_control (boost::shared_ptr<AutomationControl>());
1886 control_by_parameter[PhaseAutomation] = 0;
1889 /* gain to fader, phase to vpot */
1890 _fader->set_control (_route->gain_control());
1891 control_by_parameter[GainAutomation] = _fader;
1892 if (_route->phase_invert().size()) {
1893 _vpot->set_control (_route->phase_control());
1894 control_by_parameter[PhaseAutomation] = _vpot;
1896 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1897 control_by_parameter[PhaseAutomation] = 0;
1901 case SendAutomation:
1902 if (!Profile->get_mixbus()) {
1903 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1904 // gain to vpot, send to fader
1905 _vpot->set_control (_route->gain_control());
1906 control_by_parameter[GainAutomation] = _vpot;
1907 // test for send to control
1908 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1909 if (p && p->name() != "Monitor 1") {
1910 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1911 boost::shared_ptr<Amp> a = s->amp();
1912 _fader->set_control (a->gain_control());
1913 // connect to signal
1914 send_connections.drop_connections ();
1915 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1916 control_by_parameter[SendAutomation] = _fader;
1918 _fader->set_control (boost::shared_ptr<AutomationControl>());
1919 control_by_parameter[SendAutomation] = 0;
1922 // gain to fader, send to vpot
1923 _fader->set_control (_route->gain_control());
1924 control_by_parameter[GainAutomation] = _fader;
1925 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1926 if (p && p->name() != "Monitor 1") {
1927 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1928 boost::shared_ptr<Amp> a = s->amp();
1929 _vpot->set_control (a->gain_control());
1930 // connect to signal
1931 send_connections.drop_connections ();
1932 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1933 control_by_parameter[SendAutomation] = _vpot;
1935 // gain to fader, send to vpot
1936 _fader->set_control (_route->gain_control());
1937 control_by_parameter[GainAutomation] = _fader;
1938 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1939 if (p && p->name() != "Monitor 1") {
1940 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
1941 boost::shared_ptr<Amp> a = s->amp();
1942 _vpot->set_control (a->gain_control());
1943 // connect to signal
1944 send_connections.drop_connections ();
1945 a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1946 control_by_parameter[SendAutomation] = _vpot;
1948 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1949 control_by_parameter[SendAutomation] = 0;
1956 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1961 _surface->write (display (1, vpot_mode_string()));
1965 Strip::is_midi_track () const
1967 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1971 Strip::reset_saved_values ()
1973 _last_pan_azi_position_written = -1.0;
1974 _last_pan_width_position_written = -1.0;
1975 _last_gain_position_written = -1.0;
1976 _last_trim_position_written = -1.0;
1981 Strip::notify_metering_state_changed()
1983 if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1987 if (!_route || !_meter) {
1991 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1992 bool metering_active = _surface->mcp().metering_active ();
1994 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1998 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
2000 if (!transport_is_rolling || !metering_active) {
2001 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
2002 notify_panner_azi_changed (true);
2005 _transport_is_rolling = transport_is_rolling;
2006 _metering_active = metering_active;