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 <glibmm/convert.h>
28 #include "midi++/port.h"
30 #include "pbd/compose.h"
31 #include "pbd/convert.h"
33 #include "ardour/amp.h"
34 #include "ardour/bundle.h"
35 #include "ardour/debug.h"
36 #include "ardour/midi_ui.h"
37 #include "ardour/meter.h"
38 #include "ardour/pannable.h"
39 #include "ardour/panner.h"
40 #include "ardour/panner_shell.h"
41 #include "ardour/rc_configuration.h"
42 #include "ardour/route.h"
43 #include "ardour/session.h"
44 #include "ardour/send.h"
45 #include "ardour/track.h"
46 #include "ardour/user_bundle.h"
48 #include "mackie_control_protocol.h"
49 #include "surface_port.h"
59 using namespace ARDOUR;
61 using namespace ArdourSurface;
62 using namespace Mackie;
64 #ifndef timeradd /// only avail with __USE_BSD
65 #define timeradd(a,b,result) \
67 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
68 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
69 if ((result)->tv_usec >= 1000000) \
72 (result)->tv_usec -= 1000000; \
77 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
79 Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
92 , _controls_locked (false)
93 , _transport_is_rolling (false)
94 , _metering_active (true)
95 , _reset_display_at (0)
96 , _last_gain_position_written (-1.0)
97 , _last_pan_azi_position_written (-1.0)
98 , _last_pan_width_position_written (-1.0)
100 _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
101 _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
103 if (s.mcp().device_info().has_meters()) {
104 _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
107 for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
108 Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
109 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
110 _surface->number(), index, Button::id_to_name (bb->bid()),
111 bb->id(), b->second.base_id));
117 /* surface is responsible for deleting all controls */
121 Strip::add (Control & control)
125 Group::add (control);
127 /* fader, vpot, meter were all set explicitly */
129 if ((button = dynamic_cast<Button*>(&control)) != 0) {
130 switch (button->bid()) {
131 case Button::RecEnable:
143 case Button::VSelect:
146 case Button::FaderTouch:
147 _fader_touch = button;
156 Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
158 if (_controls_locked) {
162 route_connections.drop_connections ();
164 _solo->set_control (boost::shared_ptr<AutomationControl>());
165 _mute->set_control (boost::shared_ptr<AutomationControl>());
166 _select->set_control (boost::shared_ptr<AutomationControl>());
167 _recenable->set_control (boost::shared_ptr<AutomationControl>());
168 _fader->set_control (boost::shared_ptr<AutomationControl>());
169 _vpot->set_control (boost::shared_ptr<AutomationControl>());
173 control_by_parameter.clear ();
174 reset_saved_values ();
181 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
182 _surface->number(), _index, _route->name()));
184 _solo->set_control (_route->solo_control());
185 _mute->set_control (_route->mute_control());
187 set_vpot_parameter (PanAzimuthAutomation);
189 _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
190 _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
192 _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
194 boost::shared_ptr<Pannable> pannable = _route->pannable();
196 if (pannable && _route->panner()) {
197 pannable->pan_azimuth_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
198 pannable->pan_width_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
200 _route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
201 _route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
203 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
206 _recenable->set_control (trk->rec_enable_control());
207 trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
212 // TODO this works when a currently-banked route is made inactive, but not
213 // when a route is activated which should be currently banked.
215 _route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
216 _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
222 /* setup legal VPot modes for this route */
224 build_input_list (_route->input()->n_ports());
225 build_output_list (_route->output()->n_ports());
227 possible_pot_parameters.clear();
230 boost::shared_ptr<Panner> panner = _route->panner();
232 set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
233 set<Evoral::Parameter>::iterator a;
235 if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
236 possible_pot_parameters.push_back (PanAzimuthAutomation);
239 if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
240 possible_pot_parameters.push_back (PanWidthAutomation);
254 notify_solo_changed ();
255 notify_mute_changed ();
256 notify_gain_changed ();
257 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
258 notify_panner_azi_changed ();
259 notify_panner_width_changed ();
260 notify_record_enable_changed ();
264 Strip::notify_solo_changed ()
266 if (_route && _solo) {
267 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
272 Strip::notify_mute_changed ()
274 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
275 if (_route && _mute) {
276 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
277 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
279 _surface->write (_mute->set_state (_route->muted() ? on : off));
284 Strip::notify_record_enable_changed ()
286 if (_route && _recenable) {
287 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
292 Strip::notify_active_changed ()
294 _surface->mcp().refresh_current_bank();
298 Strip::notify_route_deleted ()
300 _surface->mcp().refresh_current_bank();
304 Strip::notify_gain_changed (bool force_update)
310 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
316 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
318 float gain_coefficient = ac->get_value();
319 float normalized_position = ac->internal_to_interface (gain_coefficient);
321 if (force_update || normalized_position != _last_gain_position_written) {
323 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
324 if (!control->in_use()) {
325 _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
327 do_parameter_display (GainAutomation, gain_coefficient);
329 if (!control->in_use()) {
330 _surface->write (_fader->set_position (normalized_position));
332 do_parameter_display (GainAutomation, gain_coefficient);
335 queue_display_reset (2000);
336 _last_gain_position_written = normalized_position;
342 Strip::notify_property_changed (const PropertyChange& what_changed)
344 if (!what_changed.contains (ARDOUR::Properties::name)) {
350 string fullname = _route->name();
352 if (fullname.length() <= 6) {
355 line1 = PBD::short_version (fullname, 6);
358 _surface->write (display (0, line1));
363 Strip::notify_panner_azi_changed (bool force_update)
367 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
369 boost::shared_ptr<Pannable> pannable = _route->pannable();
371 if (!pannable || !_route->panner()) {
372 _surface->write (_vpot->zero());
376 Control* control = control_by_parameter[PanAzimuthAutomation];
382 double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value());
384 if (force_update || pos != _last_pan_azi_position_written) {
386 if (control == _fader) {
387 if (!_fader->in_use()) {
388 _surface->write (_fader->set_position (pos));
390 } else if (control == _vpot) {
391 _surface->write (_vpot->set (pos, true, Pot::dot));
394 do_parameter_display (PanAzimuthAutomation, pos);
395 queue_display_reset (2000);
396 _last_pan_azi_position_written = pos;
402 Strip::notify_panner_width_changed (bool force_update)
406 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
408 boost::shared_ptr<Pannable> pannable = _route->pannable();
410 if (!pannable || !_route->panner()) {
411 _surface->write (_vpot->zero());
416 Control* control = control_by_parameter[PanWidthAutomation];
422 double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
424 if (force_update || pos != _last_pan_azi_position_written) {
426 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
428 if (control == _fader) {
429 if (!control->in_use()) {
430 _surface->write (_fader->set_position (pos));
434 } else if (control == _vpot) {
435 _surface->write (_vpot->set (pos, true, Pot::spread));
438 do_parameter_display (PanWidthAutomation, pos);
439 queue_display_reset (2000);
440 _last_pan_azi_position_written = pos;
446 Strip::select_event (Button&, ButtonState bs)
448 DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
452 int ms = _surface->mcp().modifier_state();
454 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
455 _controls_locked = !_controls_locked;
456 _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
457 queue_display_reset (1000);
461 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
462 /* reset to default */
463 boost::shared_ptr<AutomationControl> ac = _fader->control ();
465 ac->set_value (ac->normal());
470 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
471 _surface->mcp().add_down_select_button (_surface->number(), _index);
472 _surface->mcp().select_range ();
475 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
476 _surface->mcp().remove_down_select_button (_surface->number(), _index);
481 Strip::vselect_event (Button&, ButtonState bs)
485 int ms = _surface->mcp().modifier_state();
487 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
489 boost::shared_ptr<AutomationControl> ac = _vpot->control ();
493 /* reset to default/normal value */
494 ac->set_value (ac->normal());
499 DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
507 Strip::fader_touch_event (Button&, ButtonState bs)
509 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
513 boost::shared_ptr<AutomationControl> ac = _fader->control ();
515 if (_surface->mcp().modifier_state() == MackieControlProtocol::MODIFIER_SHIFT) {
517 ac->set_value (ac->normal());
521 _fader->set_in_use (true);
522 _fader->start_touch (_surface->mcp().transport_frame());
525 do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
526 queue_display_reset (2000);
532 _fader->set_in_use (false);
533 _fader->stop_touch (_surface->mcp().transport_frame(), true);
540 Strip::handle_button (Button& button, ButtonState bs)
542 boost::shared_ptr<AutomationControl> control;
545 button.set_in_use (true);
547 button.set_in_use (false);
550 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
552 switch (button.bid()) {
554 select_event (button, bs);
557 case Button::VSelect:
558 vselect_event (button, bs);
561 case Button::FaderTouch:
562 fader_touch_event (button, bs);
566 if ((control = button.control ())) {
568 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
569 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
572 int ms = _surface->mcp().modifier_state();
574 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
575 /* reset to default/normal value */
576 new_value = control->normal();
578 new_value = control->get_value() ? 0.0 : 1.0;
581 /* get all controls that either have their
582 * button down or are within a range of
583 * several down buttons
586 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
589 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
590 controls.size(), control->parameter().type(), new_value));
594 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
595 (*c)->set_value (new_value);
599 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
600 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
608 Strip::do_parameter_display (AutomationType type, float val)
613 _surface->write (display (1, " -inf "));
616 float dB = accurate_coefficient_to_dB (val);
617 snprintf (buf, sizeof (buf), "%6.1f", dB);
618 _surface->write (display (1, buf));
622 case PanAzimuthAutomation:
624 boost::shared_ptr<Pannable> p = _route->pannable();
625 if (p && _route->panner()) {
626 string str =_route->panner()->value_as_string (p->pan_azimuth_control);
627 _surface->write (display (1, str));
632 case PanWidthAutomation:
635 snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
636 _surface->write (display (1, buf));
646 Strip::handle_fader_touch (Fader& fader, bool touch_on)
649 fader.start_touch (_surface->mcp().transport_frame());
651 fader.stop_touch (_surface->mcp().transport_frame(), false);
656 Strip::handle_fader (Fader& fader, float position)
658 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
660 fader.set_value (position);
661 queue_display_reset (2000);
663 // must echo bytes back to slider now, because
664 // the notifier only works if the fader is not being
665 // touched. Which it is if we're getting input.
667 _surface->write (fader.set_position (position));
671 Strip::handle_pot (Pot& pot, float delta)
673 /* Pots only emit events when they move, not when they
674 stop moving. So to get a stop event, we need to use a timeout.
677 boost::shared_ptr<AutomationControl> ac = pot.control();
678 double p = pot.get_value ();
680 p = max (ac->lower(), p);
681 p = min (ac->upper(), p);
686 Strip::periodic (uint64_t usecs)
692 update_automation ();
695 if (_reset_display_at && _reset_display_at < usecs) {
701 Strip::update_automation ()
703 ARDOUR::AutoState gain_state = _route->gain_control()->automation_state();
705 if (gain_state == Touch || gain_state == Play) {
706 notify_gain_changed (false);
709 if (_route->panner()) {
710 ARDOUR::AutoState panner_state = _route->panner()->automation_state();
711 if (panner_state == Touch || panner_state == Play) {
712 notify_panner_azi_changed (false);
713 notify_panner_width_changed (false);
719 Strip::update_meter ()
721 if (_meter && _transport_is_rolling && _metering_active) {
722 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
723 _meter->send_update (*_surface, dB);
730 for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
731 _surface->write ((*it)->zero ());
734 _surface->write (blank_display (0));
735 _surface->write (blank_display (1));
739 Strip::blank_display (uint32_t line_number)
741 return display (line_number, string());
745 Strip::display (uint32_t line_number, const std::string& line)
747 assert (line_number <= 1);
749 MidiByteArray retval;
751 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
754 retval << _surface->sysex_hdr();
758 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
759 retval << (_index * 7 + (line_number * 0x38));
761 // ascii data to display. @param line is UTF-8
762 string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
763 string::size_type len = ascii.length();
765 ascii = ascii.substr (0, 6);
769 // pad with " " out to 6 chars
770 for (int i = len; i < 6; ++i) {
774 // column spacer, unless it's the right-hand column
786 Strip::lock_controls ()
788 _controls_locked = true;
792 Strip::unlock_controls ()
794 _controls_locked = false;
798 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
800 for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
801 if ((*i) == _route) {
802 _surface->write (_select->set_state (on));
807 _surface->write (_select->set_state (off));
811 Strip::vpot_mode_string () const
813 boost::shared_ptr<AutomationControl> ac = _vpot->control();
819 switch (ac->parameter().type()) {
822 case PanAzimuthAutomation:
824 case PanWidthAutomation:
826 case PanElevationAutomation:
828 case PanFrontBackAutomation:
830 case PanLFEAutomation:
838 Strip::flip_mode_changed (bool notify)
844 reset_saved_values ();
846 boost::shared_ptr<AutomationControl> fader_controllable = _fader->control ();
847 boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control ();
849 _fader->set_control (vpot_controllable);
850 _vpot->set_control (fader_controllable);
852 control_by_parameter[fader_controllable->parameter()] = _vpot;
853 control_by_parameter[vpot_controllable->parameter()] = _fader;
855 _surface->write (display (1, vpot_mode_string ()));
863 Strip::queue_display_reset (uint32_t msecs)
866 struct timeval delta;
868 gettimeofday (&now, 0);
870 delta.tv_sec = msecs/1000;
871 delta.tv_usec = (msecs - ((msecs/1000) * 1000)) * 1000;
873 timeradd (&now, &delta, &when);
875 _reset_display_at = (when.tv_sec * 1000000) + when.tv_usec;
879 Strip::clear_display_reset ()
881 _reset_display_at = 0;
885 Strip::reset_display ()
888 _surface->write (display (1, vpot_mode_string()));
890 _surface->write (blank_display (1));
893 clear_display_reset ();
896 struct RouteCompareByName {
897 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
898 return a->name().compare (b->name()) < 0;
903 Strip::maybe_add_to_bundle_map (BundleMap& bm, boost::shared_ptr<Bundle> b, bool for_input, const ChanCount& channels)
905 if (b->ports_are_outputs() == !for_input || b->nchannels() != channels) {
913 Strip::build_input_list (const ChanCount& channels)
915 boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
917 input_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 (input_bundles, *i, true, 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 (input_bundles, *i, true, 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 (input_bundles, (*i)->output()->bundle(), true, channels);
944 Strip::build_output_list (const ChanCount& channels)
946 boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
948 output_bundles.clear ();
950 /* give user bundles first chance at being in the menu */
952 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
953 if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
954 maybe_add_to_bundle_map (output_bundles, *i, false, channels);
958 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
959 if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
960 maybe_add_to_bundle_map (output_bundles, *i, false, channels);
964 boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
965 RouteList copy = *routes;
966 copy.sort (RouteCompareByName ());
968 for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
969 maybe_add_to_bundle_map (output_bundles, (*i)->input()->bundle(), false, channels);
974 Strip::next_pot_mode ()
976 vector<Evoral::Parameter>::iterator i;
978 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
979 /* do not change vpot mode while in flipped mode */
980 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
981 _surface->write (display (1, "Flip"));
982 queue_display_reset (1000);
987 boost::shared_ptr<AutomationControl> ac = _vpot->control();
993 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
997 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
998 if ((*i) == ac->parameter()) {
1003 /* move to the next mode in the list, or back to the start (which will
1004 also happen if the current mode is not in the current pot mode list)
1007 if (i != possible_pot_parameters.end()) {
1011 if (i == possible_pot_parameters.end()) {
1012 i = possible_pot_parameters.begin();
1015 set_vpot_parameter (*i);
1019 Strip::set_vpot_parameter (Evoral::Parameter p)
1021 boost::shared_ptr<Pannable> pannable;
1023 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1025 reset_saved_values ();
1028 case PanAzimuthAutomation:
1029 pannable = _route->pannable ();
1031 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1032 /* gain to vpot, pan azi to fader */
1033 _vpot->set_control (_route->gain_control());
1034 control_by_parameter[GainAutomation] = _vpot;
1036 _fader->set_control (pannable->pan_azimuth_control);
1037 control_by_parameter[PanAzimuthAutomation] = _fader;
1039 _fader->set_control (boost::shared_ptr<AutomationControl>());
1040 control_by_parameter[PanAzimuthAutomation] = 0;
1043 /* gain to fader, pan azi to vpot */
1044 _fader->set_control (_route->gain_control());
1045 control_by_parameter[GainAutomation] = _fader;
1047 _vpot->set_control (pannable->pan_azimuth_control);
1048 control_by_parameter[PanAzimuthAutomation] = _vpot;
1050 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1051 control_by_parameter[PanAzimuthAutomation] = 0;
1056 case PanWidthAutomation:
1057 pannable = _route->pannable ();
1059 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1060 /* gain to vpot, pan width to fader */
1061 _vpot->set_control (_route->gain_control());
1062 control_by_parameter[GainAutomation] = _vpot;
1064 _fader->set_control (pannable->pan_width_control);
1065 control_by_parameter[PanWidthAutomation] = _fader;
1067 _fader->set_control (boost::shared_ptr<AutomationControl>());
1068 control_by_parameter[PanWidthAutomation] = 0;
1071 /* gain to fader, pan width to vpot */
1072 _fader->set_control (_route->gain_control());
1073 control_by_parameter[GainAutomation] = _fader;
1075 _vpot->set_control (pannable->pan_width_control);
1076 control_by_parameter[PanWidthAutomation] = _vpot;
1078 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1079 control_by_parameter[PanWidthAutomation] = 0;
1084 case PanElevationAutomation:
1086 case PanFrontBackAutomation:
1088 case PanLFEAutomation:
1092 _surface->write (display (1, vpot_mode_string()));
1096 Strip::reset_saved_values ()
1098 _last_pan_azi_position_written = -1.0;
1099 _last_pan_width_position_written = -1.0;
1100 _last_gain_position_written = -1.0;
1105 Strip::notify_metering_state_changed()
1107 if (!_route || !_meter) {
1111 bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1112 bool metering_active = _surface->mcp().metering_active ();
1114 if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1118 _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1120 if (!transport_is_rolling || !metering_active) {
1121 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1122 notify_panner_azi_changed (true);
1125 _transport_is_rolling = transport_is_rolling;
1126 _metering_active = metering_active;