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