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 #ifndef timeradd /// only avail with __USE_BSD
62 #define timeradd(a,b,result) \
64 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
65 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
66 if ((result)->tv_usec >= 1000000) \
69 (result)->tv_usec -= 1000000; \
74 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
76 Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
89 , _controls_locked (false)
90 , _transport_is_rolling (false)
91 , _metering_active (true)
92 , _reset_display_at (0)
93 , _last_gain_position_written (-1.0)
94 , _last_pan_azi_position_written (-1.0)
95 , _last_pan_width_position_written (-1.0)
97 _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
98 _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
100 if (s.mcp().device_info().has_meters()) {
101 _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
104 for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
105 Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
106 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
107 _surface->number(), index, Button::id_to_name (bb->bid()),
108 bb->id(), b->second.base_id));
114 /* surface is responsible for deleting all controls */
118 Strip::add (Control & control)
122 Group::add (control);
124 /* fader, vpot, meter were all set explicitly */
126 if ((button = dynamic_cast<Button*>(&control)) != 0) {
127 switch (button->bid()) {
128 case Button::RecEnable:
140 case Button::VSelect:
143 case Button::FaderTouch:
144 _fader_touch = button;
153 Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
155 if (_controls_locked) {
159 route_connections.drop_connections ();
161 _solo->set_control (boost::shared_ptr<AutomationControl>());
162 _mute->set_control (boost::shared_ptr<AutomationControl>());
163 _select->set_control (boost::shared_ptr<AutomationControl>());
164 _recenable->set_control (boost::shared_ptr<AutomationControl>());
165 _fader->set_control (boost::shared_ptr<AutomationControl>());
166 _vpot->set_control (boost::shared_ptr<AutomationControl>());
170 control_by_parameter.clear ();
171 reset_saved_values ();
178 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
179 _surface->number(), _index, _route->name()));
181 _solo->set_control (_route->solo_control());
182 _mute->set_control (_route->mute_control());
184 set_vpot_parameter (PanAzimuthAutomation);
186 _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
187 _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
189 _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
191 boost::shared_ptr<Pannable> pannable = _route->pannable();
193 if (pannable && _route->panner()) {
194 pannable->pan_azimuth_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
195 pannable->pan_width_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
197 _route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
198 _route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
200 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
203 _recenable->set_control (trk->rec_enable_control());
204 trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
209 // TODO this works when a currently-banked route is made inactive, but not
210 // when a route is activated which should be currently banked.
212 _route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
213 _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
219 /* setup legal VPot modes for this route */
221 build_input_list (_route->input()->n_ports());
222 build_output_list (_route->output()->n_ports());
224 possible_pot_parameters.clear();
227 boost::shared_ptr<Panner> panner = _route->panner();
229 set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
230 set<Evoral::Parameter>::iterator a;
232 if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
233 possible_pot_parameters.push_back (PanAzimuthAutomation);
236 if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
237 possible_pot_parameters.push_back (PanWidthAutomation);
251 notify_solo_changed ();
252 notify_mute_changed ();
253 notify_gain_changed ();
254 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
255 notify_panner_azi_changed ();
256 notify_panner_width_changed ();
257 notify_record_enable_changed ();
261 Strip::notify_solo_changed ()
263 if (_route && _solo) {
264 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
269 Strip::notify_mute_changed ()
271 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
272 if (_route && _mute) {
273 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
274 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
276 _surface->write (_mute->set_state (_route->muted() ? on : off));
281 Strip::notify_record_enable_changed ()
283 if (_route && _recenable) {
284 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
289 Strip::notify_active_changed ()
291 _surface->mcp().refresh_current_bank();
295 Strip::notify_route_deleted ()
297 _surface->mcp().refresh_current_bank();
301 Strip::notify_gain_changed (bool force_update)
307 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
313 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
315 float gain_coefficient = ac->get_value();
316 float normalized_position = ac->internal_to_interface (gain_coefficient);
318 if (force_update || normalized_position != _last_gain_position_written) {
320 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
321 if (!control->in_use()) {
322 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
324 do_parameter_display (GainAutomation, gain_coefficient);
326 if (!control->in_use()) {
327 _surface->write (_fader->set_position (normalized_position));
329 do_parameter_display (GainAutomation, gain_coefficient);
332 queue_display_reset (2000);
333 _last_gain_position_written = normalized_position;
339 Strip::notify_property_changed (const PropertyChange& what_changed)
341 if (!what_changed.contains (ARDOUR::Properties::name)) {
347 string fullname = _route->name();
349 if (fullname.length() <= 6) {
352 line1 = PBD::short_version (fullname, 6);
355 _surface->write (display (0, line1));
360 Strip::notify_panner_azi_changed (bool force_update)
364 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
366 boost::shared_ptr<Pannable> pannable = _route->pannable();
368 if (!pannable || !_route->panner()) {
369 _surface->write (_vpot->zero());
373 Control* control = control_by_parameter[PanAzimuthAutomation];
379 double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value());
381 if (force_update || pos != _last_pan_azi_position_written) {
383 if (control == _fader) {
384 if (!_fader->in_use()) {
385 _surface->write (_fader->set_position (pos));
387 } else if (control == _vpot) {
388 _surface->write (_vpot->set (pos, true, Pot::dot));
391 do_parameter_display (PanAzimuthAutomation, pos);
392 queue_display_reset (2000);
393 _last_pan_azi_position_written = pos;
399 Strip::notify_panner_width_changed (bool force_update)
403 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
405 boost::shared_ptr<Pannable> pannable = _route->pannable();
407 if (!pannable || !_route->panner()) {
408 _surface->write (_vpot->zero());
413 Control* control = control_by_parameter[PanWidthAutomation];
419 double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
421 if (force_update || pos != _last_pan_azi_position_written) {
423 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
425 if (control == _fader) {
426 if (!control->in_use()) {
427 _surface->write (_fader->set_position (pos));
431 } else if (control == _vpot) {
432 _surface->write (_vpot->set (pos, true, Pot::spread));
435 do_parameter_display (PanWidthAutomation, pos);
436 queue_display_reset (2000);
437 _last_pan_azi_position_written = pos;
443 Strip::select_event (Button&, ButtonState bs)
445 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
449 int ms = _surface->mcp().modifier_state();
451 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
452 _controls_locked = !_controls_locked;
453 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
454 queue_display_reset (1000);
458 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
459 /* reset to default */
460 boost::shared_ptr<AutomationControl> ac = _fader->control ();
462 ac->set_value (ac->normal());
467 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
468 _surface->mcp().add_down_select_button (_surface->number(), _index);
469 _surface->mcp().select_range ();
472 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
473 _surface->mcp().remove_down_select_button (_surface->number(), _index);
478 Strip::vselect_event (Button&, ButtonState bs)
482 int ms = _surface->mcp().modifier_state();
484 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
486 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
490 /* reset to default/normal value */
491 ac->set_value (ac->normal());
496 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
504 Strip::fader_touch_event (Button&, ButtonState bs)
506 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
510 boost::shared_ptr<AutomationControl> ac = _fader->control ();
512 if (_surface->mcp().modifier_state() == MackieControlProtocol::MODIFIER_SHIFT) {
514 ac->set_value (ac->normal());
518 _fader->set_in_use (true);
519 _fader->start_touch (_surface->mcp().transport_frame());
522 do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
523 queue_display_reset (2000);
529 _fader->set_in_use (false);
530 _fader->stop_touch (_surface->mcp().transport_frame(), true);
537 Strip::handle_button (Button& button, ButtonState bs)
539 boost::shared_ptr<AutomationControl> control;
542 button.set_in_use (true);
544 button.set_in_use (false);
547 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
549 switch (button.bid()) {
551 select_event (button, bs);
554 case Button::VSelect:
555 vselect_event (button, bs);
558 case Button::FaderTouch:
559 fader_touch_event (button, bs);
563 if ((control = button.control ())) {
565 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
566 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
569 int ms = _surface->mcp().modifier_state();
571 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
572 /* reset to default/normal value */
573 new_value = control->normal();
575 new_value = control->get_value() ? 0.0 : 1.0;
578 /* get all controls that either have their
579 * button down or are within a range of
580 * several down buttons
583 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
586 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
587 controls.size(), control->parameter().type(), new_value));
591 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
592 (*c)->set_value (new_value);
596 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
597 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
605 Strip::do_parameter_display (AutomationType type, float val)
610 _surface->write (display (1, " -inf "));
613 float dB = accurate_coefficient_to_dB (val);
614 snprintf (buf, sizeof (buf), "%6.1f", dB);
615 _surface->write (display (1, buf));
619 case PanAzimuthAutomation:
621 boost::shared_ptr<Pannable> p = _route->pannable();
622 if (p && _route->panner()) {
623 string str =_route->panner()->value_as_string (p->pan_azimuth_control);
624 _surface->write (display (1, str));
629 case PanWidthAutomation:
632 snprintf (buf, sizeof (buf), "%5ld%%", lrintf (val * 100.0));
633 _surface->write (display (1, buf));
643 Strip::handle_fader_touch (Fader& fader, bool touch_on)
646 fader.start_touch (_surface->mcp().transport_frame());
648 fader.stop_touch (_surface->mcp().transport_frame(), false);
653 Strip::handle_fader (Fader& fader, float position)
655 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
657 fader.set_value (position);
658 queue_display_reset (2000);
660 // must echo bytes back to slider now, because
661 // the notifier only works if the fader is not being
662 // touched. Which it is if we're getting input.
664 _surface->write (fader.set_position (position));
668 Strip::handle_pot (Pot& pot, float delta)
670 /* Pots only emit events when they move, not when they
671 stop moving. So to get a stop event, we need to use a timeout.
674 boost::shared_ptr<AutomationControl> ac = pot.control();
675 double p = pot.get_value ();
677 p = max (ac->lower(), p);
678 p = min (ac->upper(), p);
683 Strip::periodic (uint64_t usecs)
689 update_automation ();
692 if (_reset_display_at && _reset_display_at < usecs) {
698 Strip::update_automation ()
700 ARDOUR::AutoState gain_state = _route->gain_control()->automation_state();
702 if (gain_state == Touch || gain_state == Play) {
703 notify_gain_changed (false);
706 if (_route->panner()) {
707 ARDOUR::AutoState panner_state = _route->panner()->automation_state();
708 if (panner_state == Touch || panner_state == Play) {
709 notify_panner_azi_changed (false);
710 notify_panner_width_changed (false);
716 Strip::update_meter ()
718 if (_meter && _transport_is_rolling && _metering_active) {
719 float dB = const_cast<PeakMeter&> (_route->peak_meter()).peak_power (0);
720 _meter->send_update (*_surface, dB);
727 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
728 _surface->write ((*it)->zero ());
731 _surface->write (blank_display (0));
732 _surface->write (blank_display (1));
736 Strip::blank_display (uint32_t line_number)
738 return display (line_number, string());
742 Strip::display (uint32_t line_number, const std::string& line)
744 assert (line_number <= 1);
746 MidiByteArray retval;
748 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
751 retval << _surface->sysex_hdr();
755 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
756 retval << (_index * 7 + (line_number * 0x38));
758 // ascii data to display
760 // pad with " " out to 6 chars
761 for (int i = line.length(); i < 6; ++i) {
765 // column spacer, unless it's the right-hand column
777 Strip::lock_controls ()
779 _controls_locked = true;
783 Strip::unlock_controls ()
785 _controls_locked = false;
789 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
791 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
792 if ((*i) == _route) {
793 _surface->write (_select->set_state (on));
798 _surface->write (_select->set_state (off));
802 Strip::vpot_mode_string () const
804 boost::shared_ptr<AutomationControl> ac = _vpot->control();
810 switch (ac->parameter().type()) {
813 case PanAzimuthAutomation:
815 case PanWidthAutomation:
817 case PanElevationAutomation:
819 case PanFrontBackAutomation:
821 case PanLFEAutomation:
829 Strip::flip_mode_changed (bool notify)
835 reset_saved_values ();
837 boost::shared_ptr<AutomationControl> fader_controllable = _fader->control ();
838 boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control ();
840 _fader->set_control (vpot_controllable);
841 _vpot->set_control (fader_controllable);
843 control_by_parameter[fader_controllable->parameter()] = _vpot;
844 control_by_parameter[vpot_controllable->parameter()] = _fader;
846 _surface->write (display (1, vpot_mode_string ()));
854 Strip::queue_display_reset (uint32_t msecs)
857 struct timeval delta;
859 gettimeofday (&now, 0);
861 delta.tv_sec = msecs/1000;
862 delta.tv_usec = (msecs - ((msecs/1000) * 1000)) * 1000;
864 timeradd (&now, &delta, &when);
866 _reset_display_at = (when.tv_sec * 1000000) + when.tv_usec;
870 Strip::clear_display_reset ()
872 _reset_display_at = 0;
876 Strip::reset_display ()
879 _surface->write (display (1, vpot_mode_string()));
881 _surface->write (blank_display (1));
884 clear_display_reset ();
887 struct RouteCompareByName {
888 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
889 return a->name().compare (b->name()) < 0;
894 Strip::maybe_add_to_bundle_map (BundleMap& bm, boost::shared_ptr<Bundle> b, bool for_input, const ChanCount& channels)
896 if (b->ports_are_outputs() == !for_input || b->nchannels() != channels) {
904 Strip::build_input_list (const ChanCount& channels)
906 boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
908 input_bundles.clear ();
910 /* give user bundles first chance at being in the menu */
912 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
913 if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
914 maybe_add_to_bundle_map (input_bundles, *i, true, channels);
918 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
919 if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
920 maybe_add_to_bundle_map (input_bundles, *i, true, channels);
924 boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
925 RouteList copy = *routes;
926 copy.sort (RouteCompareByName ());
928 for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
929 maybe_add_to_bundle_map (input_bundles, (*i)->output()->bundle(), true, channels);
935 Strip::build_output_list (const ChanCount& channels)
937 boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
939 output_bundles.clear ();
941 /* give user bundles first chance at being in the menu */
943 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
944 if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
945 maybe_add_to_bundle_map (output_bundles, *i, false, channels);
949 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
950 if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
951 maybe_add_to_bundle_map (output_bundles, *i, false, channels);
955 boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
956 RouteList copy = *routes;
957 copy.sort (RouteCompareByName ());
959 for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
960 maybe_add_to_bundle_map (output_bundles, (*i)->input()->bundle(), false, channels);
965 Strip::next_pot_mode ()
967 vector<Evoral::Parameter>::iterator i;
969 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
970 /* do not change vpot mode while in flipped mode */
971 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
972 _surface->write (display (1, "Flip"));
973 queue_display_reset (1000);
978 boost::shared_ptr<AutomationControl> ac = _vpot->control();
984 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
988 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
989 if ((*i) == ac->parameter()) {
994 /* move to the next mode in the list, or back to the start (which will
995 also happen if the current mode is not in the current pot mode list)
998 if (i != possible_pot_parameters.end()) {
1002 if (i == possible_pot_parameters.end()) {
1003 i = possible_pot_parameters.begin();
1006 set_vpot_parameter (*i);
1010 Strip::set_vpot_parameter (Evoral::Parameter p)
1012 boost::shared_ptr<Pannable> pannable;
1014 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1016 reset_saved_values ();
1019 case PanAzimuthAutomation:
1020 pannable = _route->pannable ();
1022 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1023 /* gain to vpot, pan azi to fader */
1024 _vpot->set_control (_route->gain_control());
1025 control_by_parameter[GainAutomation] = _vpot;
1027 _fader->set_control (pannable->pan_azimuth_control);
1028 control_by_parameter[PanAzimuthAutomation] = _fader;
1030 _fader->set_control (boost::shared_ptr<AutomationControl>());
1031 control_by_parameter[PanAzimuthAutomation] = 0;
1034 /* gain to fader, pan azi to vpot */
1035 _fader->set_control (_route->gain_control());
1036 control_by_parameter[GainAutomation] = _fader;
1038 _vpot->set_control (pannable->pan_azimuth_control);
1039 control_by_parameter[PanAzimuthAutomation] = _vpot;
1041 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1042 control_by_parameter[PanAzimuthAutomation] = 0;
1047 case PanWidthAutomation:
1048 pannable = _route->pannable ();
1050 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1051 /* gain to vpot, pan width to fader */
1052 _vpot->set_control (_route->gain_control());
1053 control_by_parameter[GainAutomation] = _vpot;
1055 _fader->set_control (pannable->pan_width_control);
1056 control_by_parameter[PanWidthAutomation] = _fader;
1058 _fader->set_control (boost::shared_ptr<AutomationControl>());
1059 control_by_parameter[PanWidthAutomation] = 0;
1062 /* gain to fader, pan width to vpot */
1063 _fader->set_control (_route->gain_control());
1064 control_by_parameter[GainAutomation] = _fader;
1066 _vpot->set_control (pannable->pan_width_control);
1067 control_by_parameter[PanWidthAutomation] = _vpot;
1069 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1070 control_by_parameter[PanWidthAutomation] = 0;
1075 case PanElevationAutomation:
1077 case PanFrontBackAutomation:
1079 case PanLFEAutomation:
1083 _surface->write (display (1, vpot_mode_string()));
1087 Strip::reset_saved_values ()
1089 _last_pan_azi_position_written = -1.0;
1090 _last_pan_width_position_written = -1.0;
1091 _last_gain_position_written = -1.0;
1096 Strip::notify_metering_state_changed()
1098 if (!_route || !_meter) {
1102 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1103 bool metering_active = _surface->mcp().metering_active ();
1105 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1109 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1111 if (!transport_is_rolling || !metering_active) {
1112 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1113 notify_panner_azi_changed (true);
1116 _transport_is_rolling = transport_is_rolling;
1117 _metering_active = metering_active;