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