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