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.
26 #include "midi++/port.h"
28 #include "pbd/compose.h"
29 #include "pbd/convert.h"
31 #include "ardour/amp.h"
32 #include "ardour/bundle.h"
33 #include "ardour/debug.h"
34 #include "ardour/midi_ui.h"
35 #include "ardour/meter.h"
36 #include "ardour/pannable.h"
37 #include "ardour/panner.h"
38 #include "ardour/panner_shell.h"
39 #include "ardour/rc_configuration.h"
40 #include "ardour/route.h"
41 #include "ardour/session.h"
42 #include "ardour/send.h"
43 #include "ardour/track.h"
44 #include "ardour/user_bundle.h"
46 #include "mackie_control_protocol.h"
47 #include "surface_port.h"
56 using namespace Mackie;
58 using namespace ARDOUR;
61 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
63 Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
76 , _controls_locked (false)
77 , _transport_is_rolling (false)
78 , _metering_active (true)
79 , _reset_display_at (0)
80 , _last_gain_position_written (-1.0)
81 , _last_pan_azi_position_written (-1.0)
82 , _last_pan_width_position_written (-1.0)
84 _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
85 _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
87 if (s.mcp().device_info().has_meters()) {
88 _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
91 for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
92 Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
93 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
94 _surface->number(), index, Button::id_to_name (bb->bid()),
95 bb->id(), b->second.base_id));
101 /* surface is responsible for deleting all controls */
105 Strip::add (Control & control)
109 Group::add (control);
111 /* fader, vpot, meter were all set explicitly */
113 if ((button = dynamic_cast<Button*>(&control)) != 0) {
114 switch (button->bid()) {
115 case Button::RecEnable:
127 case Button::VSelect:
130 case Button::FaderTouch:
131 _fader_touch = button;
140 Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
142 if (_controls_locked) {
146 route_connections.drop_connections ();
148 _solo->set_control (boost::shared_ptr<AutomationControl>());
149 _mute->set_control (boost::shared_ptr<AutomationControl>());
150 _select->set_control (boost::shared_ptr<AutomationControl>());
151 _recenable->set_control (boost::shared_ptr<AutomationControl>());
152 _fader->set_control (boost::shared_ptr<AutomationControl>());
153 _vpot->set_control (boost::shared_ptr<AutomationControl>());
157 control_by_parameter.clear ();
158 reset_saved_values ();
165 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
166 _surface->number(), _index, _route->name()));
168 _solo->set_control (_route->solo_control());
169 _mute->set_control (_route->mute_control());
171 set_vpot_parameter (PanAzimuthAutomation);
173 _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
174 _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
176 _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
178 boost::shared_ptr<Pannable> pannable = _route->pannable();
180 if (pannable && pannable->panner()) {
181 pannable->pan_azimuth_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
182 pannable->pan_width_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
184 _route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
185 _route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
187 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
190 _recenable->set_control (trk->rec_enable_control());
191 trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
196 // TODO this works when a currently-banked route is made inactive, but not
197 // when a route is activated which should be currently banked.
199 _route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
200 _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
206 /* setup legal VPot modes for this route */
208 build_input_list (_route->input()->n_ports());
209 build_output_list (_route->output()->n_ports());
211 possible_pot_parameters.clear();
214 boost::shared_ptr<Panner> panner = pannable->panner();
216 set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
217 set<Evoral::Parameter>::iterator a;
219 if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
220 possible_pot_parameters.push_back (PanAzimuthAutomation);
223 if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
224 possible_pot_parameters.push_back (PanWidthAutomation);
238 notify_solo_changed ();
239 notify_mute_changed ();
240 notify_gain_changed ();
241 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
242 notify_panner_azi_changed ();
243 notify_panner_width_changed ();
244 notify_record_enable_changed ();
248 Strip::notify_solo_changed ()
250 if (_route && _solo) {
251 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
256 Strip::notify_mute_changed ()
258 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
259 if (_route && _mute) {
260 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
261 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
263 _surface->write (_mute->set_state (_route->muted() ? on : off));
268 Strip::notify_record_enable_changed ()
270 if (_route && _recenable) {
271 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
276 Strip::notify_active_changed ()
278 _surface->mcp().refresh_current_bank();
282 Strip::notify_route_deleted ()
284 _surface->mcp().refresh_current_bank();
288 Strip::notify_gain_changed (bool force_update)
294 if (_surface->mcp().flip_mode()) {
300 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
302 float gain_coefficient = ac->get_value();
303 float normalized_position = ac->internal_to_interface (gain_coefficient);
305 if (force_update || normalized_position != _last_gain_position_written) {
307 if (_surface->mcp().flip_mode()) {
308 if (!control->in_use()) {
309 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
311 do_parameter_display (GainAutomation, gain_coefficient);
313 if (!control->in_use()) {
314 _surface->write (_fader->set_position (normalized_position));
316 do_parameter_display (GainAutomation, gain_coefficient);
319 queue_display_reset (2000);
320 _last_gain_position_written = normalized_position;
326 Strip::notify_property_changed (const PropertyChange& what_changed)
328 if (!what_changed.contains (ARDOUR::Properties::name)) {
334 string fullname = _route->name();
336 if (fullname.length() <= 6) {
339 line1 = PBD::short_version (fullname, 6);
342 _surface->write (display (0, line1));
347 Strip::notify_panner_azi_changed (bool force_update)
351 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
353 boost::shared_ptr<Pannable> pannable = _route->pannable();
355 if (!pannable || !pannable->panner()) {
356 _surface->write (_vpot->zero());
360 Control* control = control_by_parameter[PanAzimuthAutomation];
366 double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value());
368 if (force_update || pos != _last_pan_azi_position_written) {
370 if (control == _fader) {
371 if (!_fader->in_use()) {
372 _surface->write (_fader->set_position (pos));
374 } else if (control == _vpot) {
375 _surface->write (_vpot->set (pos, true, Pot::dot));
378 do_parameter_display (PanAzimuthAutomation, pos);
379 queue_display_reset (2000);
380 _last_pan_azi_position_written = pos;
386 Strip::notify_panner_width_changed (bool force_update)
390 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
392 boost::shared_ptr<Pannable> pannable = _route->pannable();
394 if (!pannable || !pannable->panner()) {
395 _surface->write (_vpot->zero());
400 Control* control = control_by_parameter[PanWidthAutomation];
406 double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
408 if (force_update || pos != _last_pan_azi_position_written) {
410 if (_surface->mcp().flip_mode()) {
412 if (control == _fader) {
413 if (!control->in_use()) {
414 _surface->write (_fader->set_position (pos));
418 } else if (control == _vpot) {
419 _surface->write (_vpot->set (pos, true, Pot::spread));
422 do_parameter_display (PanWidthAutomation, pos);
423 queue_display_reset (2000);
424 _last_pan_azi_position_written = pos;
430 Strip::select_event (Button&, ButtonState bs)
432 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
436 int ms = _surface->mcp().modifier_state();
438 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
439 _controls_locked = !_controls_locked;
440 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
441 queue_display_reset (1000);
445 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
446 /* reset to default */
447 boost::shared_ptr<AutomationControl> ac = _fader->control ();
449 ac->set_value (ac->normal());
454 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
455 _surface->mcp().add_down_select_button (_surface->number(), _index);
456 _surface->mcp().select_range ();
459 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
460 _surface->mcp().remove_down_select_button (_surface->number(), _index);
465 Strip::vselect_event (Button&, ButtonState bs)
469 int ms = _surface->mcp().modifier_state();
471 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
473 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
477 /* reset to default/normal value */
478 ac->set_value (ac->normal());
483 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
491 Strip::fader_touch_event (Button&, ButtonState bs)
493 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
497 boost::shared_ptr<AutomationControl> ac = _fader->control ();
499 if (_surface->mcp().modifier_state() == MackieControlProtocol::MODIFIER_SHIFT) {
501 ac->set_value (ac->normal());
505 _fader->set_in_use (true);
506 _fader->start_touch (_surface->mcp().transport_frame());
509 do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
510 queue_display_reset (2000);
516 _fader->set_in_use (false);
517 _fader->stop_touch (_surface->mcp().transport_frame(), true);
524 Strip::handle_button (Button& button, ButtonState bs)
526 boost::shared_ptr<AutomationControl> control;
529 button.set_in_use (true);
531 button.set_in_use (false);
534 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
536 switch (button.bid()) {
538 select_event (button, bs);
541 case Button::VSelect:
542 vselect_event (button, bs);
545 case Button::FaderTouch:
546 fader_touch_event (button, bs);
550 if ((control = button.control ())) {
552 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
553 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
556 int ms = _surface->mcp().modifier_state();
558 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
559 /* reset to default/normal value */
560 new_value = control->normal();
562 new_value = control->get_value() ? 0.0 : 1.0;
565 /* get all controls that either have their
566 * button down or are within a range of
567 * several down buttons
570 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
573 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
574 controls.size(), control->parameter().type(), new_value));
578 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
579 (*c)->set_value (new_value);
583 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
584 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
592 Strip::do_parameter_display (AutomationType type, float val)
597 _surface->write (display (1, " -inf "));
600 float dB = accurate_coefficient_to_dB (val);
601 snprintf (buf, sizeof (buf), "%6.1f", dB);
602 _surface->write (display (1, buf));
606 case PanAzimuthAutomation:
608 boost::shared_ptr<Pannable> p = _route->pannable();
609 if (p && p->panner()) {
610 string str = p->panner()->value_as_string (p->pan_azimuth_control);
611 _surface->write (display (1, str));
616 case PanWidthAutomation:
619 snprintf (buf, sizeof (buf), "%5ld%%", lrintf (val * 100.0));
620 _surface->write (display (1, buf));
630 Strip::handle_fader (Fader& fader, float position)
632 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
634 fader.set_value (position);
635 fader.start_touch (_surface->mcp().transport_frame());
636 queue_display_reset (2000);
638 // must echo bytes back to slider now, because
639 // the notifier only works if the fader is not being
640 // touched. Which it is if we're getting input.
642 _surface->write (fader.set_position (position));
646 Strip::handle_pot (Pot& pot, float delta)
648 /* Pots only emit events when they move, not when they
649 stop moving. So to get a stop event, we need to use a timeout.
652 boost::shared_ptr<AutomationControl> ac = pot.control();
653 double p = pot.get_value ();
655 p = max (ac->lower(), p);
656 p = min (ac->upper(), p);
661 Strip::periodic (uint64_t usecs)
667 update_automation ();
670 if (_reset_display_at && _reset_display_at < usecs) {
676 Strip::update_automation ()
678 ARDOUR::AutoState gain_state = _route->gain_control()->automation_state();
680 if (gain_state == Touch || gain_state == Play) {
681 notify_gain_changed (false);
684 if (_route->panner()) {
685 ARDOUR::AutoState panner_state = _route->panner()->automation_state();
686 if (panner_state == Touch || panner_state == Play) {
687 notify_panner_azi_changed (false);
688 notify_panner_width_changed (false);
694 Strip::update_meter ()
696 if (_meter && _transport_is_rolling && _metering_active) {
697 float dB = const_cast<PeakMeter&> (_route->peak_meter()).peak_power (0);
698 _meter->send_update (*_surface, dB);
705 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
706 _surface->write ((*it)->zero ());
709 _surface->write (blank_display (0));
710 _surface->write (blank_display (1));
714 Strip::blank_display (uint32_t line_number)
716 return display (line_number, string());
720 Strip::display (uint32_t line_number, const std::string& line)
722 assert (line_number <= 1);
724 MidiByteArray retval;
726 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
729 retval << _surface->sysex_hdr();
733 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
734 retval << (_index * 7 + (line_number * 0x38));
736 // ascii data to display
738 // pad with " " out to 6 chars
739 for (int i = line.length(); i < 6; ++i) {
743 // column spacer, unless it's the right-hand column
755 Strip::lock_controls ()
757 _controls_locked = true;
761 Strip::unlock_controls ()
763 _controls_locked = false;
767 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
769 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
770 if ((*i) == _route) {
771 _surface->write (_select->set_state (on));
776 _surface->write (_select->set_state (off));
780 Strip::vpot_mode_string () const
782 boost::shared_ptr<AutomationControl> ac = _vpot->control();
788 switch (ac->parameter().type()) {
791 case PanAzimuthAutomation:
793 case PanWidthAutomation:
795 case PanElevationAutomation:
797 case PanFrontBackAutomation:
799 case PanLFEAutomation:
807 Strip::flip_mode_changed (bool notify)
813 reset_saved_values ();
815 boost::shared_ptr<AutomationControl> fader_controllable = _fader->control ();
816 boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control ();
818 _fader->set_control (vpot_controllable);
819 _vpot->set_control (fader_controllable);
821 control_by_parameter[fader_controllable->parameter()] = _vpot;
822 control_by_parameter[vpot_controllable->parameter()] = _fader;
824 _surface->write (display (1, vpot_mode_string ()));
832 Strip::queue_display_reset (uint32_t msecs)
835 struct timeval delta;
837 gettimeofday (&now, 0);
839 delta.tv_sec = msecs/1000;
840 delta.tv_usec = (msecs - ((msecs/1000) * 1000)) * 1000;
842 timeradd (&now, &delta, &when);
844 _reset_display_at = (when.tv_sec * 1000000) + when.tv_usec;
848 Strip::clear_display_reset ()
850 _reset_display_at = 0;
854 Strip::reset_display ()
857 _surface->write (display (1, vpot_mode_string()));
859 _surface->write (blank_display (1));
862 clear_display_reset ();
865 struct RouteCompareByName {
866 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
867 return a->name().compare (b->name()) < 0;
872 Strip::maybe_add_to_bundle_map (BundleMap& bm, boost::shared_ptr<Bundle> b, bool for_input, const ChanCount& channels)
874 if (b->ports_are_outputs() == !for_input || b->nchannels() != channels) {
882 Strip::build_input_list (const ChanCount& channels)
884 boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
886 input_bundles.clear ();
888 /* give user bundles first chance at being in the menu */
890 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
891 if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
892 maybe_add_to_bundle_map (input_bundles, *i, true, channels);
896 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
897 if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
898 maybe_add_to_bundle_map (input_bundles, *i, true, channels);
902 boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
903 RouteList copy = *routes;
904 copy.sort (RouteCompareByName ());
906 for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
907 maybe_add_to_bundle_map (input_bundles, (*i)->output()->bundle(), true, channels);
913 Strip::build_output_list (const ChanCount& channels)
915 boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
917 output_bundles.clear ();
919 /* give user bundles first chance at being in the menu */
921 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
922 if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
923 maybe_add_to_bundle_map (output_bundles, *i, false, channels);
927 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
928 if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
929 maybe_add_to_bundle_map (output_bundles, *i, false, channels);
933 boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
934 RouteList copy = *routes;
935 copy.sort (RouteCompareByName ());
937 for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
938 maybe_add_to_bundle_map (output_bundles, (*i)->input()->bundle(), false, channels);
943 Strip::next_pot_mode ()
945 vector<Evoral::Parameter>::iterator i;
947 if (_surface->mcp().flip_mode()) {
948 /* do not change vpot mode while in flipped mode */
949 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
950 _surface->write (display (1, "Flip"));
951 queue_display_reset (1000);
956 boost::shared_ptr<AutomationControl> ac = _vpot->control();
962 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
966 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
967 if ((*i) == ac->parameter()) {
972 /* move to the next mode in the list, or back to the start (which will
973 also happen if the current mode is not in the current pot mode list)
976 if (i != possible_pot_parameters.end()) {
980 if (i == possible_pot_parameters.end()) {
981 i = possible_pot_parameters.begin();
984 set_vpot_parameter (*i);
988 Strip::set_vpot_parameter (Evoral::Parameter p)
990 boost::shared_ptr<Pannable> pannable;
992 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
994 reset_saved_values ();
997 case PanAzimuthAutomation:
998 pannable = _route->pannable ();
1000 if (_surface->mcp().flip_mode()) {
1001 /* gain to vpot, pan azi to fader */
1002 _vpot->set_control (_route->gain_control());
1003 control_by_parameter[GainAutomation] = _vpot;
1005 _fader->set_control (pannable->pan_azimuth_control);
1006 control_by_parameter[PanAzimuthAutomation] = _fader;
1008 _fader->set_control (boost::shared_ptr<AutomationControl>());
1009 control_by_parameter[PanAzimuthAutomation] = 0;
1012 /* gain to fader, pan azi to vpot */
1013 _fader->set_control (_route->gain_control());
1014 control_by_parameter[GainAutomation] = _fader;
1016 _vpot->set_control (pannable->pan_azimuth_control);
1017 control_by_parameter[PanAzimuthAutomation] = _vpot;
1019 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1020 control_by_parameter[PanAzimuthAutomation] = 0;
1025 case PanWidthAutomation:
1026 pannable = _route->pannable ();
1028 if (_surface->mcp().flip_mode()) {
1029 /* gain to vpot, pan width to fader */
1030 _vpot->set_control (_route->gain_control());
1031 control_by_parameter[GainAutomation] = _vpot;
1033 _fader->set_control (pannable->pan_width_control);
1034 control_by_parameter[PanWidthAutomation] = _fader;
1036 _fader->set_control (boost::shared_ptr<AutomationControl>());
1037 control_by_parameter[PanWidthAutomation] = 0;
1040 /* gain to fader, pan width to vpot */
1041 _fader->set_control (_route->gain_control());
1042 control_by_parameter[GainAutomation] = _fader;
1044 _vpot->set_control (pannable->pan_width_control);
1045 control_by_parameter[PanWidthAutomation] = _vpot;
1047 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1048 control_by_parameter[PanWidthAutomation] = 0;
1053 case PanElevationAutomation:
1055 case PanFrontBackAutomation:
1057 case PanLFEAutomation:
1061 _surface->write (display (1, vpot_mode_string()));
1065 Strip::reset_saved_values ()
1067 _last_pan_azi_position_written = -1.0;
1068 _last_pan_width_position_written = -1.0;
1069 _last_gain_position_written = -1.0;
1074 Strip::notify_metering_state_changed()
1076 if (!_route || !_meter) {
1080 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1081 bool metering_active = _surface->mcp().metering_active ();
1083 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1087 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1089 if (!transport_is_rolling || !metering_active) {
1090 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1091 notify_panner_azi_changed (true);
1094 _transport_is_rolling = transport_is_rolling;
1095 _metering_active = metering_active;