be3d6222138ca2741b7f4d3b1b4629a583715729
[ardour.git] / libs / surfaces / mackie / strip.cc
1 /*
2         Copyright (C) 2006,2007 John Anderson
3         Copyright (C) 2012 Paul Davis
4
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.
9
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.
14
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.
18 */
19
20 #include <sstream>
21 #include <stdint.h>
22 #include "strip.h"
23
24 #include <sys/time.h>
25
26 #include <glibmm/convert.h>
27
28 #include "midi++/port.h"
29
30 #include "pbd/compose.h"
31 #include "pbd/convert.h"
32
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/plugin_insert.h"
39 #include "ardour/pannable.h"
40 #include "ardour/panner.h"
41 #include "ardour/panner_shell.h"
42 #include "ardour/rc_configuration.h"
43 #include "ardour/route.h"
44 #include "ardour/session.h"
45 #include "ardour/send.h"
46 #include "ardour/track.h"
47 #include "ardour/midi_track.h"
48 #include "ardour/user_bundle.h"
49 #include "ardour/profile.h"
50
51 #include "mackie_control_protocol.h"
52 #include "surface_port.h"
53 #include "surface.h"
54 #include "button.h"
55 #include "led.h"
56 #include "pot.h"
57 #include "fader.h"
58 #include "jog.h"
59 #include "meter.h"
60
61 using namespace std;
62 using namespace ARDOUR;
63 using namespace PBD;
64 using namespace ArdourSurface;
65 using namespace Mackie;
66
67 #ifndef timeradd /// only avail with __USE_BSD
68 #define timeradd(a,b,result)                         \
69   do {                                               \
70     (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;    \
71     (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
72     if ((result)->tv_usec >= 1000000)                \
73     {                                                \
74       ++(result)->tv_sec;                            \
75       (result)->tv_usec -= 1000000;                  \
76     }                                                \
77   } while (0)
78 #endif
79
80 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
81
82 Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
83         : Group (name)
84         , _solo (0)
85         , _recenable (0)
86         , _mute (0)
87         , _select (0)
88         , _vselect (0)
89         , _fader_touch (0)
90         , _vpot (0)
91         , _fader (0)
92         , _meter (0)
93         , _index (index)
94         , _surface (&s)
95         , _controls_locked (false)
96         , _transport_is_rolling (false)
97         , _metering_active (true)
98         , _block_vpot_mode_redisplay_until (0)
99         , _block_screen_redisplay_until (0)
100         , _pan_mode (PanAzimuthAutomation)
101         , _trim_mode (TrimAutomation)
102         , vpot_parameter (PanAzimuthAutomation)
103         , _last_gain_position_written (-1.0)
104         , _last_pan_azi_position_written (-1.0)
105         , _last_pan_width_position_written (-1.0)
106         , _last_trim_position_written (-1.0)
107         , _current_send (0)
108         , redisplay_requests (256)
109 {
110         _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
111         _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
112
113         if (s.mcp().device_info().has_meters()) {
114                 _meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
115         }
116
117         for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
118                 Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
119                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
120                                                                    _surface->number(), index, Button::id_to_name (bb->bid()),
121                                                                    bb->id(), b->second.base_id));
122         }
123 }
124
125 Strip::~Strip ()
126 {
127         /* surface is responsible for deleting all controls */
128 }
129
130 void
131 Strip::add (Control & control)
132 {
133         Button* button;
134
135         Group::add (control);
136
137         /* fader, vpot, meter were all set explicitly */
138
139         if ((button = dynamic_cast<Button*>(&control)) != 0) {
140                 switch (button->bid()) {
141                 case Button::RecEnable:
142                         _recenable = button;
143                         break;
144                 case Button::Mute:
145                         _mute = button;
146                         break;
147                 case Button::Solo:
148                         _solo = button;
149                         break;
150                 case Button::Select:
151                         _select = button;
152                         break;
153                 case Button::VSelect:
154                         _vselect = button;
155                         break;
156                 case Button::FaderTouch:
157                         _fader_touch = button;
158                         break;
159                 default:
160                         break;
161                 }
162         }
163 }
164
165 void
166 Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
167 {
168         if (_controls_locked) {
169                 return;
170         }
171
172         mb_pan_controllable.reset();
173
174         route_connections.drop_connections ();
175
176         _solo->set_control (boost::shared_ptr<AutomationControl>());
177         _mute->set_control (boost::shared_ptr<AutomationControl>());
178         _select->set_control (boost::shared_ptr<AutomationControl>());
179         _recenable->set_control (boost::shared_ptr<AutomationControl>());
180         _fader->set_control (boost::shared_ptr<AutomationControl>());
181         _vpot->set_control (boost::shared_ptr<AutomationControl>());
182
183         _route = r;
184
185         control_by_parameter.clear ();
186
187         control_by_parameter[PanAzimuthAutomation] = (Control*) 0;
188         control_by_parameter[PanWidthAutomation] = (Control*) 0;
189         control_by_parameter[PanElevationAutomation] = (Control*) 0;
190         control_by_parameter[PanFrontBackAutomation] = (Control*) 0;
191         control_by_parameter[PanLFEAutomation] = (Control*) 0;
192         control_by_parameter[GainAutomation] = (Control*) 0;
193         control_by_parameter[TrimAutomation] = (Control*) 0;
194         control_by_parameter[PhaseAutomation] = (Control*) 0;
195         control_by_parameter[SendAutomation] = (Control*) 0;
196         control_by_parameter[EQParam1] = (Control*) 0;
197         control_by_parameter[EQParam2] = (Control*) 0;
198         control_by_parameter[EQParam3] = (Control*) 0;
199         control_by_parameter[EQParam4] = (Control*) 0;
200         control_by_parameter[EQParam5] = (Control*) 0;
201         control_by_parameter[EQParam6] = (Control*) 0;
202         control_by_parameter[EQParam7] = (Control*) 0;
203         control_by_parameter[EQParam8] = (Control*) 0;
204
205         reset_saved_values ();
206
207         if (!r) {
208                 zero ();
209                 return;
210         }
211
212         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
213                                                            _surface->number(), _index, _route->name()));
214
215         _solo->set_control (_route->solo_control());
216         _mute->set_control (_route->mute_control());
217
218         _route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
219         _route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
220
221         _route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
222
223         if (_route->trim() && route()->trim()->active()) {
224                 _route->trim_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trim_changed, this, false), ui_context());
225         }
226
227         if (_route->phase_invert().size()) {
228                 _route->phase_invert_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_phase_changed, this, false), ui_context());
229                 _route->phase_control()->set_channel(0);
230         }
231
232         boost::shared_ptr<Pannable> pannable = _route->pannable();
233
234         if(Profile->get_mixbus()) {
235                 const uint32_t port_channel_post_pan = 2; // gtk2_ardour/mixbus_ports.h
236                 boost::shared_ptr<ARDOUR::PluginInsert> plug = _route->ch_post();
237                 mb_pan_controllable = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (plug->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_channel_post_pan)));
238
239                 mb_pan_controllable->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
240         } else {
241                 if (pannable && _route->panner()) {
242                         pannable->pan_azimuth_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
243                         pannable->pan_width_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
244                 }
245         }
246
247         _route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
248         _route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
249
250         boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
251
252         if (trk) {
253                 _recenable->set_control (trk->rec_enable_control());
254                 trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
255
256
257         }
258
259         // TODO this works when a currently-banked route is made inactive, but not
260         // when a route is activated which should be currently banked.
261
262         _route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
263         _route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
264
265         /* setup legal VPot modes for this route */
266
267         possible_pot_parameters.clear();
268
269         if (Profile->get_mixbus()) {
270                 possible_pot_parameters.push_back (PanAzimuthAutomation);
271         } else {
272                 if (pannable) {
273                         boost::shared_ptr<Panner> panner = _route->panner();
274                         if (panner) {
275                                 set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
276                                 set<Evoral::Parameter>::iterator a;
277
278                                 if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
279                                         possible_pot_parameters.push_back (PanAzimuthAutomation);
280                                 }
281
282                                 if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
283                                         possible_pot_parameters.push_back (PanWidthAutomation);
284                                 }
285                         }
286                 }
287         }
288
289         if (_route->trim() && route()->trim()->active()) {
290                 possible_pot_parameters.push_back (TrimAutomation);
291         }
292
293         possible_trim_parameters.clear();
294
295         if (_route->trim() && route()->trim()->active()) {
296                 possible_trim_parameters.push_back (TrimAutomation);
297                 _trim_mode = TrimAutomation;
298         }
299
300         if (_route->phase_invert().size()) {
301                 possible_trim_parameters.push_back (PhaseAutomation);
302                 _route->phase_control()->set_channel(0);
303                 if (_trim_mode != TrimAutomation) {
304                         _trim_mode = PhaseAutomation;
305                 }
306         }
307         _current_send = 0;
308         /* Update */
309         _pan_mode = PanAzimuthAutomation;
310         potmode_changed (false);
311         notify_all ();
312
313 }
314
315 void
316 Strip::notify_all()
317 {
318         if (!_route) {
319                 zero ();
320                 return;
321         }
322
323         notify_solo_changed ();
324         notify_mute_changed ();
325         notify_gain_changed ();
326         notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
327         notify_panner_azi_changed ();
328         notify_panner_width_changed ();
329         notify_record_enable_changed ();
330         notify_trim_changed ();
331         notify_phase_changed ();
332         notify_processor_changed ();
333 }
334
335 void
336 Strip::notify_solo_changed ()
337 {
338         if (_route && _solo) {
339                 _surface->write (_solo->set_state ((_route->soloed() || _route->listening_via_monitor()) ? on : off));
340         }
341 }
342
343 void
344 Strip::notify_mute_changed ()
345 {
346         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
347         if (_route && _mute) {
348                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\troute muted ? %1\n", _route->muted()));
349                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_route->muted() ? on : off)));
350
351                 _surface->write (_mute->set_state (_route->muted() ? on : off));
352         }
353 }
354
355 void
356 Strip::notify_record_enable_changed ()
357 {
358         if (_route && _recenable)  {
359                 _surface->write (_recenable->set_state (_route->record_enabled() ? on : off));
360         }
361 }
362
363 void
364 Strip::notify_active_changed ()
365 {
366         _surface->mcp().refresh_current_bank();
367 }
368
369 void
370 Strip::notify_route_deleted ()
371 {
372         _surface->mcp().refresh_current_bank();
373 }
374
375 void
376 Strip::notify_gain_changed (bool force_update)
377 {
378         if (_route) {
379
380                 Control* control;
381
382                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
383                         control = _vpot;
384                 } else {
385                         control = _fader;
386                 }
387
388                 boost::shared_ptr<AutomationControl> ac = _route->gain_control();
389
390                 float gain_coefficient = ac->get_value();
391                 float normalized_position = ac->internal_to_interface (gain_coefficient);
392
393
394                 if (force_update || normalized_position != _last_gain_position_written) {
395
396                         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
397                                 if (!control->in_use()) {
398                                         _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
399                                 }
400                                 queue_parameter_display (GainAutomation, gain_coefficient);
401                         } else {
402                                 if (!control->in_use()) {
403                                         _surface->write (_fader->set_position (normalized_position));
404                                 }
405                                 queue_parameter_display (GainAutomation, gain_coefficient);
406                         }
407
408                         _last_gain_position_written = normalized_position;
409                 }
410         }
411 }
412
413 void
414 Strip::notify_trim_changed (bool force_update)
415 {
416         if (_route) {
417
418                 if (!_route->trim() || !route()->trim()->active()) {
419                         _surface->write (_vpot->zero());
420                         return;
421                 }
422                 Control* control = 0;
423                 ControlParameterMap::iterator i = control_by_parameter.find (TrimAutomation);
424
425                 if (i == control_by_parameter.end()) {
426                         return;
427                 }
428
429                 control = i->second;
430
431                 boost::shared_ptr<AutomationControl> ac = _route->trim_control();
432
433                 float gain_coefficient = ac->get_value();
434                 float normalized_position = ac->internal_to_interface (gain_coefficient);
435
436                 if (force_update || normalized_position != _last_trim_position_written) {
437                         if (control == _fader) {
438                                 if (!_fader->in_use()) {
439                                         _surface->write (_fader->set_position (normalized_position));
440                                         queue_parameter_display (TrimAutomation, gain_coefficient);
441                                 }
442                         } else if (control == _vpot) {
443                                 _surface->write (_vpot->set (normalized_position, true, Pot::dot));
444                                 queue_parameter_display (TrimAutomation, gain_coefficient);
445                         }
446                         _last_trim_position_written = normalized_position;
447                 }
448         }
449 }
450
451 void
452 Strip::notify_phase_changed (bool force_update)
453 {
454         if (_route) {
455                 if (!_route->phase_invert().size()) {
456                         _surface->write (_vpot->zero());
457                         return;
458                 }
459
460                 Control* control = 0;
461                 ControlParameterMap::iterator i = control_by_parameter.find (PhaseAutomation);
462
463                 if (i == control_by_parameter.end()) {
464                         return;
465                 }
466
467                 control = i->second;
468
469                 float normalized_position = _route->phase_control()->get_value();
470
471                 if (control == _fader) {
472                         if (!_fader->in_use()) {
473                                 _surface->write (_fader->set_position (normalized_position));
474                                 queue_parameter_display (PhaseAutomation, normalized_position);
475                         }
476                 } else if (control == _vpot) {
477                         _surface->write (_vpot->set (normalized_position, true, Pot::wrap));
478                         queue_parameter_display (PhaseAutomation, normalized_position);
479                 }
480         }
481 }
482
483 void
484 Strip::notify_processor_changed (bool force_update)
485 {
486         if (_route) {
487                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
488                 if (!p) {
489                         _surface->write (_vpot->zero());
490                         return;
491                 }
492
493                 Control* control = 0;
494                 ControlParameterMap::iterator i = control_by_parameter.find (SendAutomation);
495
496                 if (i == control_by_parameter.end()) {
497                         return;
498                 }
499
500                 control = i->second;
501
502                 boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
503                 boost::shared_ptr<Amp> a = s->amp();
504                 boost::shared_ptr<AutomationControl> ac = a->gain_control();
505
506                 float gain_coefficient = ac->get_value();
507                 float normalized_position = ac->internal_to_interface (gain_coefficient);
508
509                 if (control == _fader) {
510                         if (!_fader->in_use()) {
511                                 _surface->write (_fader->set_position (normalized_position));
512                                 queue_parameter_display (SendAutomation, gain_coefficient);
513                         }
514                 } else if (control == _vpot) {
515                         _surface->write (_vpot->set (normalized_position, true, Pot::dot));
516                         queue_parameter_display (SendAutomation, gain_coefficient);
517                 }
518         }
519 }
520
521 void
522 Strip::notify_property_changed (const PropertyChange& what_changed)
523 {
524         if (!what_changed.contains (ARDOUR::Properties::name)) {
525                 return;
526         }
527
528         show_route_name ();
529 }
530
531 void
532 Strip::show_route_name ()
533 {
534         MackieControlProtocol::SubViewMode svm = _surface->mcp().subview_mode();
535
536         if (svm == MackieControlProtocol::None) {
537                 if (!_route) {
538                         return;
539                 }
540                 string line1;
541                 string fullname = _route->name();
542
543                 if (fullname.length() <= 6) {
544                         line1 = fullname;
545                 } else {
546                         line1 = PBD::short_version (fullname, 6);
547                 }
548
549                 _surface->write (display (0, line1));
550
551         } else if (svm == MackieControlProtocol::EQ) {
552                 if (_vpot == control_by_parameter[EQParam1]) {
553                         _surface->write (display (0, "HiFreq"));
554                 } else if (_vpot == control_by_parameter[EQParam2]) {
555                         _surface->write (display (0, "HiGain"));
556                 } else if (_vpot == control_by_parameter[EQParam3]) {
557                         _surface->write (display (0, "MidFreq"));
558                 } else if (_vpot == control_by_parameter[EQParam4]) {
559                         _surface->write (display (0, "MidGain"));
560                 } else if (_vpot == control_by_parameter[EQParam5]) {
561                         _surface->write (display (0, "LoFreq"));
562                 } else if (_vpot == control_by_parameter[EQParam6]) {
563                         _surface->write (display (0, "LoGain"));
564                 } else if (_vpot == control_by_parameter[EQParam7]) {
565                         _surface->write (display (0, "HPFreq"));
566                 } else if (_vpot == control_by_parameter[EQParam8]) {
567                         _surface->write (display (0, "In/Out"));
568                 }
569         } else if (svm == MackieControlProtocol::Dynamics) {
570
571         }
572
573 }
574
575 void
576 Strip::notify_eq_change (AutomationType p, uint32_t port_number, bool force_update)
577 {
578         if (!_subview_route) {
579                 /* no longer in EQ subview mode */
580                 return;
581         }
582
583         if (_vpot != control_by_parameter[p]) {
584                 /* vpot is no longer controlling this EQ parameter */
585                 return;
586         }
587
588         boost::shared_ptr<PluginInsert> eq = _subview_route->ch_eq();
589
590         if (eq) {
591                 boost::shared_ptr<AutomationControl> control = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (eq->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_number)));
592
593                 if (control) {
594                         float val = control->get_value();
595                         queue_parameter_display (p, val);
596                         _surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
597                 }
598         }
599 }
600
601 void
602 Strip::notify_panner_azi_changed (bool force_update)
603 {
604         if (_route) {
605
606                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
607
608                 boost::shared_ptr<Pannable> pannable = _route->pannable();
609
610                 if (!pannable || !_route->panner()) {
611                         _surface->write (_vpot->zero());
612                         return;
613                 }
614
615                 Control* control = 0;
616                 ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
617
618                 if (i == control_by_parameter.end()) {
619                         return;
620                 }
621
622                 control = i->second;
623
624                 double pos = mb_pan_controllable->internal_to_interface (mb_pan_controllable->get_value());
625
626                 if (force_update || pos != _last_pan_azi_position_written) {
627
628                         if (control == _fader) {
629                                 if (!_fader->in_use()) {
630                                         _surface->write (_fader->set_position (pos));
631                                         queue_parameter_display (PanAzimuthAutomation, pos);
632                                 }
633                         } else if (control == _vpot) {
634                                 _surface->write (_vpot->set (pos, true, Pot::dot));
635                                 queue_parameter_display (PanAzimuthAutomation, pos);
636                         }
637
638                         _last_pan_azi_position_written = pos;
639                 }
640         }
641 }
642
643 void
644 Strip::notify_panner_width_changed (bool force_update)
645 {
646         if (_route) {
647
648                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
649
650                 boost::shared_ptr<Pannable> pannable = _route->pannable();
651
652                 if (!pannable || !_route->panner()) {
653                         _surface->write (_vpot->zero());
654                         return;
655                 }
656
657                 Control* control = 0;
658                 ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
659
660                 if (i == control_by_parameter.end()) {
661                         return;
662                 }
663
664                 control = i->second;
665
666                 double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
667
668                 if (force_update || pos != _last_pan_width_position_written) {
669
670                         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
671
672                                 if (control == _fader) {
673                                         if (!control->in_use()) {
674                                                 _surface->write (_fader->set_position (pos));
675                                                 queue_parameter_display (PanWidthAutomation, pos);
676                                         }
677                                 }
678
679                         } else if (control == _vpot) {
680                                 _surface->write (_vpot->set (pos, true, Pot::spread));
681                                 queue_parameter_display (PanWidthAutomation, pos);
682                         }
683
684                         _last_pan_width_position_written = pos;
685                 }
686         }
687 }
688
689 void
690 Strip::select_event (Button&, ButtonState bs)
691 {
692         DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
693
694         if (bs == press) {
695
696                 int ms = _surface->mcp().main_modifier_state();
697
698                 if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
699                         _controls_locked = !_controls_locked;
700                         _surface->write (display (1,_controls_locked ?  "Locked" : "Unlock"));
701                         block_vpot_mode_display_for (1000);
702                         return;
703                 }
704
705                 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
706                         /* reset to default */
707                         boost::shared_ptr<AutomationControl> ac = _fader->control ();
708                         if (ac) {
709                                 ac->set_value (ac->normal());
710                         }
711                         return;
712                 }
713
714                 DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
715                 _surface->mcp().add_down_select_button (_surface->number(), _index);
716                 _surface->mcp().select_range ();
717
718         } else {
719                 DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
720                 _surface->mcp().remove_down_select_button (_surface->number(), _index);
721         }
722 }
723
724 void
725 Strip::vselect_event (Button&, ButtonState bs)
726 {
727         if (bs == press) {
728
729                 int ms = _surface->mcp().main_modifier_state();
730
731                 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
732
733                         boost::shared_ptr<AutomationControl> ac = _vpot->control ();
734
735                         if (ac) {
736
737                                 /* reset to default/normal value */
738                                 ac->set_value (ac->normal());
739                         }
740
741                 }  else {
742
743                         DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
744                         next_pot_mode ();
745                 }
746
747         }
748 }
749
750 void
751 Strip::fader_touch_event (Button&, ButtonState bs)
752 {
753         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
754
755         if (bs == press) {
756
757                 boost::shared_ptr<AutomationControl> ac = _fader->control ();
758
759                 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
760                         if (ac) {
761                                 ac->set_value (ac->normal());
762                         }
763                 } else {
764
765                         _fader->set_in_use (true);
766                         _fader->start_touch (_surface->mcp().transport_frame());
767
768                         if (ac) {
769                                 queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
770                         }
771                 }
772
773         } else {
774
775                 _fader->set_in_use (false);
776                 _fader->stop_touch (_surface->mcp().transport_frame(), true);
777
778         }
779 }
780
781
782 void
783 Strip::handle_button (Button& button, ButtonState bs)
784 {
785         boost::shared_ptr<AutomationControl> control;
786
787         if (bs == press) {
788                 button.set_in_use (true);
789         } else {
790                 button.set_in_use (false);
791         }
792
793         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
794
795         switch (button.bid()) {
796         case Button::Select:
797                 select_event (button, bs);
798                 break;
799
800         case Button::VSelect:
801                 vselect_event (button, bs);
802                 break;
803
804         case Button::FaderTouch:
805                 fader_touch_event (button, bs);
806                 break;
807
808         default:
809                 if ((control = button.control ())) {
810                         if (bs == press) {
811                                 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
812                                 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
813
814                                 float new_value;
815                                 int ms = _surface->mcp().main_modifier_state();
816
817                                 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
818                                         /* reset to default/normal value */
819                                         new_value = control->normal();
820                                 } else {
821                                         new_value = control->get_value() ? 0.0 : 1.0;
822                                 }
823
824                                 /* get all controls that either have their
825                                  * button down or are within a range of
826                                  * several down buttons
827                                  */
828
829                                 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
830
831
832                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
833                                                                             controls.size(), control->parameter().type(), new_value));
834
835                                 /* apply change */
836
837                                 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
838                                         (*c)->set_value (new_value);
839                                 }
840
841                         } else {
842                                 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
843                                 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
844                         }
845                 }
846                 break;
847         }
848 }
849
850 void
851 Strip::queue_parameter_display (AutomationType type, float val)
852 {
853         RedisplayRequest req;
854
855         req.type = type;
856         req.val = val;
857
858         redisplay_requests.write (&req, 1);
859 }
860
861 void
862 Strip::do_parameter_display (AutomationType type, float val)
863 {
864         bool screen_hold = false;
865         char buf[16];
866
867         switch (type) {
868         case GainAutomation:
869                 if (val == 0.0) {
870                         _surface->write (display (1, " -inf "));
871                 } else {
872                         float dB = accurate_coefficient_to_dB (val);
873                         snprintf (buf, sizeof (buf), "%6.1f", dB);
874                         _surface->write (display (1, buf));
875                         screen_hold = true;
876                 }
877                 break;
878
879         case PanAzimuthAutomation:
880                 if (Profile->get_mixbus()) {
881                         snprintf (buf, sizeof (buf), "%2.1f", val);
882                         _surface->write (display (1, buf));
883                         screen_hold = true;
884                 } else {
885                         if (_route) {
886                                 boost::shared_ptr<Pannable> p = _route->pannable();
887                                 if (p && _route->panner()) {
888                                         string str =_route->panner()->value_as_string (p->pan_azimuth_control);
889                                         _surface->write (display (1, str));
890                                         screen_hold = true;
891                                 }
892                         }
893                 }
894                 break;
895
896         case PanWidthAutomation:
897                 if (_route) {
898                         snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
899                         _surface->write (display (1, buf));
900                         screen_hold = true;
901                 }
902                 break;
903
904         case TrimAutomation:
905                 if (_route) {
906                         float dB = accurate_coefficient_to_dB (val);
907                         snprintf (buf, sizeof (buf), "%6.1f", dB);
908                         _surface->write (display (1, buf));
909                         screen_hold = true;
910                 }
911                 break;
912
913         case PhaseAutomation:
914                 if (_route) {
915                         if (_route->phase_control()->get_value() < 0.5) {
916                                 _surface->write (display (1, "Normal"));
917                         } else {
918                                 _surface->write (display (1, "Invert"));
919                         }
920                         screen_hold = true;
921                 }
922                 break;
923
924         case SendAutomation:
925                 if (val == 0.0) {
926                         _surface->write (display (1, " -inf "));
927                 } else {
928                         float dB = accurate_coefficient_to_dB (val);
929                         snprintf (buf, sizeof (buf), "%6.1f", dB);
930                         _surface->write (display (1, buf));
931                         screen_hold = true;
932                 }
933                 break;
934         case EQParam1:
935         case EQParam2:
936         case EQParam3:
937         case EQParam4:
938         case EQParam5:
939         case EQParam6:
940         case EQParam7:
941         case EQParam8:
942                 snprintf (buf, sizeof (buf), "%6.1f", val);
943                 _surface->write (display (1, buf));
944                 screen_hold = true;
945         default:
946                 break;
947         }
948
949         if (screen_hold) {
950                 block_vpot_mode_display_for (1000);
951         }
952 }
953
954 void
955 Strip::handle_fader_touch (Fader& fader, bool touch_on)
956 {
957         if (touch_on) {
958                 fader.start_touch (_surface->mcp().transport_frame());
959         } else {
960                 fader.stop_touch (_surface->mcp().transport_frame(), false);
961         }
962 }
963
964 void
965 Strip::handle_fader (Fader& fader, float position)
966 {
967         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
968         boost::shared_ptr<AutomationControl> ac = fader.control();
969         if (!ac) {
970                 return;
971         }
972
973         fader.set_value (position);
974
975         /* From the Mackie Control MIDI implementation docs:
976
977            In order to ensure absolute synchronization with the host software,
978            Mackie Control uses a closed-loop servo system for the faders,
979            meaning the faders will always move to their last received position.
980            When a host receives a Fader Position Message, it must then
981            re-transmit that message to the Mackie Control or else the faders
982            will return to their last position.
983         */
984
985         _surface->write (fader.set_position (position));
986 }
987
988 void
989 Strip::handle_pot (Pot& pot, float delta)
990 {
991         /* Pots only emit events when they move, not when they
992            stop moving. So to get a stop event, we need to use a timeout.
993         */
994
995         boost::shared_ptr<AutomationControl> ac = pot.control();
996         if (!ac) {
997                 return;
998         }
999         double p = pot.get_value ();
1000         p += delta;
1001         // fader and pot should be the same and fader is hard coded 0 -> 1
1002         p = max (0.0, p);
1003         p = min (1.0, p);
1004         pot.set_value (p);
1005 }
1006
1007 void
1008 Strip::periodic (ARDOUR::microseconds_t now)
1009 {
1010         bool reshow_vpot_mode = false;
1011         bool reshow_name = false;
1012
1013         if (!_route) {
1014                 return;
1015         }
1016
1017         if (_block_screen_redisplay_until >= now) {
1018                 if (_surface->mcp().device_info().has_separate_meters()) {
1019                         goto meters;
1020                 }
1021                 /* no drawing here, for now */
1022                 return;
1023
1024         } else if (_block_screen_redisplay_until) {
1025
1026                 /* timeout reached, reset */
1027
1028                 _block_screen_redisplay_until = 0;
1029                 reshow_vpot_mode = true;
1030                 reshow_name = true;
1031         }
1032
1033         if (_block_vpot_mode_redisplay_until >= now) {
1034                 return;
1035         } else if (_block_vpot_mode_redisplay_until) {
1036
1037                 /* timeout reached, reset */
1038
1039                 _block_vpot_mode_redisplay_until = 0;
1040                 reshow_vpot_mode = true;
1041         }
1042
1043         if (reshow_name) {
1044                 show_route_name ();
1045         }
1046
1047         if (reshow_vpot_mode) {
1048                 return_to_vpot_mode_display ();
1049         } else {
1050                 /* no point doing this if we just switched back to vpot mode
1051                    display */
1052                 update_automation ();
1053         }
1054
1055   meters:
1056         update_meter ();
1057 }
1058
1059 void
1060 Strip::redisplay (ARDOUR::microseconds_t now)
1061 {
1062         RedisplayRequest req;
1063         bool have_request = false;
1064
1065         while (redisplay_requests.read (&req, 1) == 1) {
1066                 /* read them all */
1067                 have_request = true;
1068         }
1069
1070         if (_block_screen_redisplay_until >= now) {
1071                 return;
1072         }
1073
1074         if (have_request) {
1075                 do_parameter_display (req.type, req.val);
1076         }
1077 }
1078
1079 void
1080 Strip::update_automation ()
1081 {
1082         ARDOUR::AutoState gain_state = _route->gain_control()->automation_state();
1083
1084         if (gain_state == Touch || gain_state == Play) {
1085                 notify_gain_changed (false);
1086         }
1087
1088 if ( Profile->get_mixbus() ) {
1089         ARDOUR::AutoState panner_state = mb_pan_controllable->automation_state();
1090         if (panner_state == Touch || panner_state == Play) {
1091                 notify_panner_azi_changed (false);
1092         }
1093 } else {
1094         if (_route->panner()) {
1095                 ARDOUR::AutoState panner_state = _route->panner()->automation_state();
1096                 if (panner_state == Touch || panner_state == Play) {
1097                         notify_panner_azi_changed (false);
1098                         notify_panner_width_changed (false);
1099                 }
1100         }
1101 }
1102         if (_route->trim() && route()->trim()->active()) {
1103                 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1104                 if (trim_state == Touch || trim_state == Play) {
1105                         notify_trim_changed (false);
1106                 }
1107         }
1108 }
1109
1110 void
1111 Strip::update_meter ()
1112 {
1113         if (_meter && _transport_is_rolling && _metering_active) {
1114                 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1115                 _meter->send_update (*_surface, dB);
1116         }
1117 }
1118
1119 void
1120 Strip::zero ()
1121 {
1122         for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1123                 _surface->write ((*it)->zero ());
1124         }
1125
1126         _surface->write (blank_display (0));
1127         _surface->write (blank_display (1));
1128 }
1129
1130 MidiByteArray
1131 Strip::blank_display (uint32_t line_number)
1132 {
1133         return display (line_number, string());
1134 }
1135
1136 MidiByteArray
1137 Strip::display (uint32_t line_number, const std::string& line)
1138 {
1139         assert (line_number <= 1);
1140
1141         MidiByteArray retval;
1142
1143         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1144
1145         // sysex header
1146         retval << _surface->sysex_hdr();
1147
1148         // code for display
1149         retval << 0x12;
1150         // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1151         retval << (_index * 7 + (line_number * 0x38));
1152
1153         // ascii data to display. @param line is UTF-8
1154         string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1155         string::size_type len = ascii.length();
1156         if (len > 6) {
1157                 ascii = ascii.substr (0, 6);
1158                 len = 6;
1159         }
1160         retval << ascii;
1161         // pad with " " out to 6 chars
1162         for (int i = len; i < 6; ++i) {
1163                 retval << ' ';
1164         }
1165
1166         // column spacer, unless it's the right-hand column
1167         if (_index < 7) {
1168                 retval << ' ';
1169         }
1170
1171         // sysex trailer
1172         retval << MIDI::eox;
1173
1174         return retval;
1175 }
1176
1177 void
1178 Strip::lock_controls ()
1179 {
1180         _controls_locked = true;
1181 }
1182
1183 void
1184 Strip::unlock_controls ()
1185 {
1186         _controls_locked = false;
1187 }
1188
1189 void
1190 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1191 {
1192         for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1193                 if ((*i) == _route) {
1194                         _surface->write (_select->set_state (on));
1195                         return;
1196                 }
1197         }
1198
1199         _surface->write (_select->set_state (off));
1200 }
1201
1202 string
1203 Strip::vpot_mode_string ()
1204 {
1205         boost::shared_ptr<AutomationControl> ac = _vpot->control();
1206         if (!ac) {
1207                 return string();
1208         }
1209
1210         if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1211                 return "Fader";
1212         } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1213                 return "Trim";
1214         } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1215                 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1216         } else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
1217                 // should be bus name
1218                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1219                 if (p) {
1220                         return p->name();
1221                 }
1222         } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1223                 return "Pan";
1224         } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1225                 return "Width";
1226         } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1227                 return "Elev";
1228         } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1229                 return "F/Rear";
1230         } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1231                 return "LFE";
1232         }
1233
1234         if (_subview_route) {
1235                 return string();
1236         }
1237
1238         return "???";
1239 }
1240
1241  void
1242 Strip::potmode_changed (bool notify)
1243 {
1244         if (!_route) {
1245                 return;
1246         }
1247
1248         // WIP
1249         int pm = _surface->mcp().pot_mode();
1250         switch (pm) {
1251         case MackieControlProtocol::Pan:
1252                 // This needs to set current pan mode (azimuth or width... or whatever)
1253                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1254                 set_vpot_parameter (_pan_mode);
1255                 break;
1256         case MackieControlProtocol::Trim:
1257                 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
1258                 set_vpot_parameter (_trim_mode);
1259                 break;
1260         case MackieControlProtocol::Send:
1261                 // _current_send has the number of the send we will show
1262                 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
1263                 set_vpot_parameter (SendAutomation);
1264                 break;
1265         }
1266
1267         if (notify) {
1268                 notify_all ();
1269         }
1270 }
1271
1272 void
1273 Strip::block_screen_display_for (uint32_t msecs)
1274 {
1275         _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1276 }
1277
1278 void
1279 Strip::block_vpot_mode_display_for (uint32_t msecs)
1280 {
1281         _block_vpot_mode_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1282 }
1283
1284 void
1285 Strip::return_to_vpot_mode_display ()
1286 {
1287         /* returns the second line of the two-line per-strip display
1288            back the mode where it shows what the VPot controls.
1289         */
1290         if (_subview_route) {
1291                 /* do nothing - second line shows value of current subview parameter */
1292                 return;
1293         } else if (_route) {
1294                 _surface->write (display (1, vpot_mode_string()));
1295         } else {
1296                 _surface->write (blank_display (1));
1297         }
1298 }
1299
1300 void
1301 Strip::next_pot_mode ()
1302 {
1303         vector<Evoral::Parameter>::iterator i;
1304
1305         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1306                 /* do not change vpot mode while in flipped mode */
1307                 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1308                 _surface->write (display (1, "Flip"));
1309                 block_vpot_mode_display_for (1000);
1310                 return;
1311         }
1312
1313
1314         boost::shared_ptr<AutomationControl> ac = _vpot->control();
1315
1316         if (!ac) {
1317                 return;
1318         }
1319         if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1320                 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
1321                         return;
1322                 }
1323
1324                 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1325                         if ((*i) == ac->parameter()) {
1326                                 break;
1327                         }
1328                 }
1329
1330                 /* move to the next mode in the list, or back to the start (which will
1331                 also happen if the current mode is not in the current pot mode list)
1332                 */
1333
1334                 if (i != possible_pot_parameters.end()) {
1335                         ++i;
1336                 }
1337
1338                 if (i == possible_pot_parameters.end()) {
1339                         i = possible_pot_parameters.begin();
1340                 }
1341                 set_vpot_parameter (*i);
1342         } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
1343                                 if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter())) {
1344                         return;
1345                 }
1346
1347                 for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
1348                         if ((*i) == ac->parameter()) {
1349                                 break;
1350                         }
1351                 }
1352                 if ((*i).type() == PhaseAutomation && _route->phase_invert().size() > 1) {
1353                         // There are more than one channel of phase
1354                         if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
1355                                 _route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
1356                                 set_vpot_parameter (*i);
1357                                 return;
1358                         } else {
1359                                 _route->phase_control()->set_channel(0);
1360                         }
1361                 }
1362                 /* move to the next mode in the list, or back to the start (which will
1363                 also happen if the current mode is not in the current pot mode list)
1364                 */
1365
1366                 if (i != possible_trim_parameters.end()) {
1367                         ++i;
1368                 }
1369
1370                 if (i == possible_trim_parameters.end()) {
1371                         i = possible_trim_parameters.begin();
1372                 }
1373                 set_vpot_parameter (*i);
1374         } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
1375                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1376                 if (!p) {
1377                         return;
1378                 }
1379                 p = _route->nth_send (_current_send + 1);
1380                 if (p && p->name() != "Monitor 1") {
1381                         _current_send++;
1382                 } else {
1383                         _current_send = 0;
1384                 }
1385                 set_vpot_parameter (SendAutomation);
1386         }
1387 }
1388
1389 void
1390 Strip::use_subview (MackieControlProtocol::SubViewMode sm, boost::shared_ptr<Route> target_route)
1391 {
1392         if (!_route) {
1393                 return;
1394         }
1395
1396         switch (sm) {
1397         case MackieControlProtocol::None:
1398                 if (vpot_parameter != NullAutomation) {
1399                         set_vpot_parameter (vpot_parameter);
1400                 }
1401                 break;
1402
1403         case MackieControlProtocol::EQ:
1404                 switch (_index) {
1405                 case 0:
1406                         set_vpot_parameter (ARDOUR::EQParam1, target_route);
1407                         break;
1408                 case 1:
1409                         set_vpot_parameter (ARDOUR::EQParam2, target_route);
1410                         break;
1411                 case 2:
1412                         set_vpot_parameter (ARDOUR::EQParam3, target_route);
1413                         break;
1414                 case 3:
1415                         set_vpot_parameter (ARDOUR::EQParam4, target_route);
1416                         break;
1417                 case 4:
1418                         set_vpot_parameter (ARDOUR::EQParam5, target_route);
1419                         break;
1420                 case 5:
1421                         set_vpot_parameter (ARDOUR::EQParam6, target_route);
1422                         break;
1423                 case 6:
1424                         set_vpot_parameter (ARDOUR::EQParam7, target_route);
1425                         break;
1426                 case 7:
1427                         set_vpot_parameter (ARDOUR::EQParam8, target_route);
1428                         break;
1429                 }
1430                 break;
1431
1432         case MackieControlProtocol::Dynamics:
1433                 break;
1434         }
1435 }
1436
1437 void
1438 Strip::set_vpot_parameter (Evoral::Parameter p, boost::shared_ptr<Route> target_route)
1439 {
1440         boost::shared_ptr<Pannable> pannable;
1441
1442         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p.type()));
1443
1444         reset_saved_values ();
1445
1446         /* target route is either null, or points to a route other than the one
1447            we are controlling/viewing, to be used while in a particular subview
1448            state (e.g. EQ or Dynamics)
1449         */
1450
1451         if (target_route != _subview_route) {
1452                 subview_connections.drop_connections ();
1453         }
1454
1455         _subview_route = target_route;
1456
1457         /* unset any mapping between the vpot and any existing parameters */
1458
1459         for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1460
1461                 if (i != control_by_parameter.end() && i->second == _vpot) {
1462                         i->second = 0;
1463                 }
1464         }
1465
1466         switch (p.type()) {
1467         case PanAzimuthAutomation:
1468                 _pan_mode = PanAzimuthAutomation;
1469                 pannable = _route->pannable ();
1470                 vpot_parameter = PanAzimuthAutomation;
1471                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1472                         /* gain to vpot, pan azi to fader */
1473                         _vpot->set_control (_route->group_gain_control());
1474                         control_by_parameter[GainAutomation] = _vpot;
1475                         if (pannable) {
1476                                 _fader->set_control (mb_pan_controllable);
1477                                 control_by_parameter[PanAzimuthAutomation] = _fader;
1478                         } else {
1479                                 _fader->set_control (boost::shared_ptr<AutomationControl>());
1480                                 control_by_parameter[PanAzimuthAutomation] = 0;
1481                         }
1482                 } else {
1483                         /* gain to fader, pan azi to vpot */
1484                         _fader->set_control (_route->group_gain_control());
1485                         control_by_parameter[GainAutomation] = _fader;
1486                         if (pannable) {
1487                                 _vpot->set_control (mb_pan_controllable);
1488                                 control_by_parameter[PanAzimuthAutomation] = _vpot;
1489                         } else {
1490                                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1491                                 control_by_parameter[PanAzimuthAutomation] = 0;
1492                         }
1493                 }
1494                 break;
1495         case PanWidthAutomation:
1496                 _pan_mode = PanWidthAutomation;
1497                 pannable = _route->pannable ();
1498                 vpot_parameter = PanWidthAutomation;
1499                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1500                         /* gain to vpot, pan width to fader */
1501                         _vpot->set_control (_route->group_gain_control());
1502                         control_by_parameter[GainAutomation] = _vpot;
1503                         if (pannable) {
1504                                 _fader->set_control (pannable->pan_width_control);
1505                                 control_by_parameter[PanWidthAutomation] = _fader;
1506                         } else {
1507                                 _fader->set_control (boost::shared_ptr<AutomationControl>());
1508                                 control_by_parameter[PanWidthAutomation] = 0;
1509                         }
1510                 } else {
1511                         /* gain to fader, pan width to vpot */
1512                         _fader->set_control (_route->group_gain_control());
1513                         control_by_parameter[GainAutomation] = _fader;
1514                         if (pannable) {
1515                                 _vpot->set_control (pannable->pan_width_control);
1516                                 control_by_parameter[PanWidthAutomation] = _vpot;
1517                         } else {
1518                                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1519                                 control_by_parameter[PanWidthAutomation] = 0;
1520                         }
1521                 }
1522                 break;
1523         case PanElevationAutomation:
1524                 break;
1525         case PanFrontBackAutomation:
1526                 break;
1527         case PanLFEAutomation:
1528                 break;
1529         case TrimAutomation:
1530                 _trim_mode = TrimAutomation;
1531                 vpot_parameter = TrimAutomation;
1532                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1533                         /* gain to vpot, trim to fader */
1534                         _vpot->set_control (_route->group_gain_control());
1535                         control_by_parameter[GainAutomation] = _vpot;
1536                         if (_route->trim() && route()->trim()->active()) {
1537                                 _fader->set_control (_route->trim_control());
1538                                 control_by_parameter[TrimAutomation] = _fader;
1539                         } else {
1540                                 _fader->set_control (boost::shared_ptr<AutomationControl>());
1541                                 control_by_parameter[TrimAutomation] = 0;
1542                         }
1543                 } else {
1544                         /* gain to fader, trim to vpot */
1545                         _fader->set_control (_route->group_gain_control());
1546                         control_by_parameter[GainAutomation] = _fader;
1547                         if (_route->trim() && route()->trim()->active()) {
1548                                 _vpot->set_control (_route->trim_control());
1549                                 control_by_parameter[TrimAutomation] = _vpot;
1550                         } else {
1551                                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1552                                 control_by_parameter[TrimAutomation] = 0;
1553                         }
1554                 }
1555                 break;
1556         case PhaseAutomation:
1557                 _trim_mode = PhaseAutomation;
1558                 vpot_parameter = PhaseAutomation;
1559                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1560                         /* gain to vpot, phase to fader */
1561                         _vpot->set_control (_route->group_gain_control());
1562                         control_by_parameter[GainAutomation] = _vpot;
1563                         if (_route->phase_invert().size()) {
1564                                 _fader->set_control (_route->phase_control());
1565                                 control_by_parameter[PhaseAutomation] = _fader;
1566                         } else {
1567                                 _fader->set_control (boost::shared_ptr<AutomationControl>());
1568                                 control_by_parameter[PhaseAutomation] = 0;
1569                         }
1570                 } else {
1571                         /* gain to fader, phase to vpot */
1572                         _fader->set_control (_route->group_gain_control());
1573                         control_by_parameter[GainAutomation] = _fader;
1574                         if (_route->phase_invert().size()) {
1575                                 _vpot->set_control (_route->phase_control());
1576                                 control_by_parameter[PhaseAutomation] = _vpot;
1577                         } else {
1578                                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1579                                 control_by_parameter[PhaseAutomation] = 0;
1580                         }
1581                 }
1582                 break;
1583         case SendAutomation:
1584                 if (!Profile->get_mixbus()) {
1585                         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1586                                 // gain to vpot, send to fader
1587                                 _vpot->set_control (_route->group_gain_control());
1588                                 control_by_parameter[GainAutomation] = _vpot;
1589                                 // test for send to control
1590                                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1591                                 if (p && p->name() != "Monitor 1") {
1592                                         boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
1593                                         boost::shared_ptr<Amp> a = s->amp();
1594                                         _fader->set_control (a->gain_control());
1595                                         // connect to signal
1596                                         send_connections.drop_connections ();
1597                                         a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1598                                         control_by_parameter[SendAutomation] = _fader;
1599                                 } else {
1600                                         _fader->set_control (boost::shared_ptr<AutomationControl>());
1601                                         control_by_parameter[SendAutomation] = 0;
1602                                 }
1603                         } else {
1604                                 // gain to fader, send to vpot
1605                                 _fader->set_control (_route->group_gain_control());
1606                                 control_by_parameter[GainAutomation] = _fader;
1607                                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1608                                 if (p && p->name() != "Monitor 1") {
1609                                         boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
1610                                         boost::shared_ptr<Amp> a = s->amp();
1611                                         _vpot->set_control (a->gain_control());
1612                                         // connect to signal
1613                                         send_connections.drop_connections ();
1614                                         a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1615                                         control_by_parameter[SendAutomation] = _vpot;
1616                         } else {
1617                                 // gain to fader, send to vpot
1618                                 _fader->set_control (_route->group_gain_control());
1619                                 control_by_parameter[GainAutomation] = _fader;
1620                                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1621                                 if (p && p->name() != "Monitor 1") {
1622                                         boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
1623                                         boost::shared_ptr<Amp> a = s->amp();
1624                                         _vpot->set_control (a->gain_control());
1625                                         // connect to signal
1626                                         send_connections.drop_connections ();
1627                                         a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1628                                         control_by_parameter[SendAutomation] = _vpot;
1629                                 } else {
1630                                         _vpot->set_control (boost::shared_ptr<AutomationControl>());
1631                                         control_by_parameter[SendAutomation] = 0;
1632                                 }
1633                         }
1634                 }
1635                 break;
1636         case EQParam1: {
1637                 const uint32_t eq_hi_freq = 3; /* gtk2_ardour/mixbus_ports.h */
1638                 hookup_eq (EQParam1, eq_hi_freq);
1639                 break;
1640         }
1641         case EQParam2: {
1642                 const uint32_t eq_hi_gain = 4; /* gtk2_ardour/mixbus_ports.h */
1643                 hookup_eq (EQParam2, eq_hi_gain);
1644                 break;
1645         }
1646         case EQParam3: {
1647                 const uint32_t eq_mid_freq = 5; /* gtk2_ardour/mixbus_ports.h */
1648                 hookup_eq (EQParam3, eq_mid_freq);
1649                 break;
1650         }
1651         case EQParam4: {
1652                 const uint32_t eq_mid_gain = 6; /* gtk2_ardour/mixbus_ports.h */
1653                 hookup_eq (EQParam4, eq_mid_gain);
1654                 break;
1655         }
1656         case EQParam5: {
1657                 const uint32_t eq_lo_freq = 7; /* gtk2_ardour/mixbus_ports.h */
1658                 hookup_eq (EQParam5, eq_lo_freq);
1659                 break;
1660         }
1661         case EQParam6: {
1662                 const uint32_t eq_lo_gain = 8; /* gtk2_ardour/mixbus_ports.h */
1663                 hookup_eq (EQParam6, eq_lo_gain);
1664                 break;
1665         }
1666         case EQParam7: {
1667                 const uint32_t eq_hp_freq = 2; /* gtk2_ardour/mixbus_ports.h */
1668                 hookup_eq (EQParam7, eq_hp_freq);
1669                 break;
1670         }
1671         case EQParam8: {
1672                 const uint32_t eq_in = 1; /* gtk2_ardour/mixbus_ports.h */
1673                 hookup_eq (EQParam8, eq_in);
1674                 break;
1675         }
1676         default:
1677                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1678                 break;
1679
1680         }
1681
1682         _surface->write (display (1, vpot_mode_string()));
1683 }
1684
1685 bool
1686 Strip::is_midi_track () const
1687 {
1688         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1689 }
1690
1691 void
1692 Strip::reset_saved_values ()
1693 {
1694         _last_pan_azi_position_written = -1.0;
1695         _last_pan_width_position_written = -1.0;
1696         _last_gain_position_written = -1.0;
1697         _last_trim_position_written = -1.0;
1698
1699 }
1700
1701 void
1702 Strip::notify_metering_state_changed()
1703 {
1704         if (!_route || !_meter) {
1705                 return;
1706         }
1707
1708         bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1709         bool metering_active = _surface->mcp().metering_active ();
1710
1711         if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1712                 return;
1713         }
1714
1715         _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1716
1717         if (!transport_is_rolling || !metering_active) {
1718                 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1719                 notify_panner_azi_changed (true);
1720         }
1721
1722         _transport_is_rolling = transport_is_rolling;
1723         _metering_active = metering_active;
1724 }
1725
1726 void
1727 Strip::hookup_eq (AutomationType param, uint32_t port_number)
1728 {
1729         if (!_subview_route) {
1730                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1731                 return;
1732         }
1733
1734         boost::shared_ptr<PluginInsert> eq = _subview_route->ch_eq();
1735
1736         if (!eq) {
1737                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1738         }
1739
1740         boost::shared_ptr<AutomationControl> control = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (eq->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_number)));
1741
1742         if (control) {
1743                 control->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, port_number, false), ui_context());
1744                 _vpot->set_control (control);
1745                 control_by_parameter[param] = _vpot;
1746                 show_route_name ();
1747         }
1748 }