600c4fccca831bf92966c8eb3836b0e9ef127f94
[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 (_surface->mcp().subview_mode() != None) {
768
769                 /* subview mode: vpot press acts like a button for toggle parameters */
770
771                 if (bs != press) {
772                         return;
773                 }
774
775                 boost::shared_ptr<AutomationControl> control = _vpot->control ();
776                 if (!control) {
777                         return;
778                 }
779
780                 if (control->toggled()) {
781                         if (control->toggled()) {
782                                 control->set_value (!control->get_value());
783                         }
784                 }
785
786                 return;
787         }
788
789         if (bs == press) {
790
791                 int ms = _surface->mcp().main_modifier_state();
792
793                 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
794
795                         boost::shared_ptr<AutomationControl> ac = _vpot->control ();
796
797                         if (ac) {
798
799                                 /* reset to default/normal value */
800                                 ac->set_value (ac->normal());
801                         }
802
803                 }  else {
804
805                         DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
806                         next_pot_mode ();
807                 }
808
809         }
810 }
811
812 void
813 Strip::fader_touch_event (Button&, ButtonState bs)
814 {
815         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
816
817         if (bs == press) {
818
819                 boost::shared_ptr<AutomationControl> ac = _fader->control ();
820
821                 if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
822                         if (ac) {
823                                 ac->set_value (ac->normal());
824                         }
825                 } else {
826
827                         _fader->set_in_use (true);
828                         _fader->start_touch (_surface->mcp().transport_frame());
829
830                         if (ac) {
831                                 queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
832                         }
833                 }
834
835         } else {
836
837                 _fader->set_in_use (false);
838                 _fader->stop_touch (_surface->mcp().transport_frame(), true);
839
840         }
841 }
842
843
844 void
845 Strip::handle_button (Button& button, ButtonState bs)
846 {
847         boost::shared_ptr<AutomationControl> control;
848
849         if (bs == press) {
850                 button.set_in_use (true);
851         } else {
852                 button.set_in_use (false);
853         }
854
855         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
856
857         switch (button.bid()) {
858         case Button::Select:
859                 select_event (button, bs);
860                 break;
861
862         case Button::VSelect:
863                 vselect_event (button, bs);
864                 break;
865
866         case Button::FaderTouch:
867                 fader_touch_event (button, bs);
868                 break;
869
870         default:
871                 if ((control = button.control ())) {
872                         if (bs == press) {
873                                 DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
874                                 _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
875
876                                 float new_value;
877                                 int ms = _surface->mcp().main_modifier_state();
878
879                                 if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
880                                         /* reset to default/normal value */
881                                         new_value = control->normal();
882                                 } else {
883                                         new_value = control->get_value() ? 0.0 : 1.0;
884                                 }
885
886                                 /* get all controls that either have their
887                                  * button down or are within a range of
888                                  * several down buttons
889                                  */
890
891                                 MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
892
893
894                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
895                                                                             controls.size(), control->parameter().type(), new_value));
896
897                                 /* apply change */
898
899                                 for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
900                                         (*c)->set_value (new_value);
901                                 }
902
903                         } else {
904                                 DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
905                                 _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
906                         }
907                 }
908                 break;
909         }
910 }
911
912 void
913 Strip::queue_parameter_display (AutomationType type, float val)
914 {
915         RedisplayRequest req;
916
917         req.type = type;
918         req.val = val;
919
920         redisplay_requests.write (&req, 1);
921 }
922
923 void
924 Strip::do_parameter_display (AutomationType type, float val)
925 {
926         bool screen_hold = false;
927         char buf[16];
928
929         switch (type) {
930         case GainAutomation:
931                 if (val == 0.0) {
932                         _surface->write (display (1, " -inf "));
933                 } else {
934                         float dB = accurate_coefficient_to_dB (val);
935                         snprintf (buf, sizeof (buf), "%6.1f", dB);
936                         _surface->write (display (1, buf));
937                         screen_hold = true;
938                 }
939                 break;
940
941         case PanAzimuthAutomation:
942                 if (Profile->get_mixbus()) {
943                         snprintf (buf, sizeof (buf), "%2.1f", val);
944                         _surface->write (display (1, buf));
945                         screen_hold = true;
946                 } else {
947                         if (_route) {
948                                 boost::shared_ptr<Pannable> p = _route->pannable();
949                                 if (p && _route->panner()) {
950                                         string str =_route->panner()->value_as_string (p->pan_azimuth_control);
951                                         _surface->write (display (1, str));
952                                         screen_hold = true;
953                                 }
954                         }
955                 }
956                 break;
957
958         case PanWidthAutomation:
959                 if (_route) {
960                         snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
961                         _surface->write (display (1, buf));
962                         screen_hold = true;
963                 }
964                 break;
965
966         case TrimAutomation:
967                 if (_route) {
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
975         case PhaseAutomation:
976                 if (_route) {
977                         if (_route->phase_control()->get_value() < 0.5) {
978                                 _surface->write (display (1, "Normal"));
979                         } else {
980                                 _surface->write (display (1, "Invert"));
981                         }
982                         screen_hold = true;
983                 }
984                 break;
985
986         case SendAutomation:
987                 if (val == 0.0) {
988                         _surface->write (display (1, " -inf "));
989                 } else {
990                         float dB = accurate_coefficient_to_dB (val);
991                         snprintf (buf, sizeof (buf), "%6.1f", dB);
992                         _surface->write (display (1, buf));
993                         screen_hold = true;
994                 }
995                 break;
996         case EQGain:
997         case EQFrequency:
998         case EQQ:
999         case EQShape:
1000         case EQHPF:
1001         case CompThreshold:
1002         case CompSpeed:
1003         case CompMakeup:
1004         case CompRedux:
1005                 snprintf (buf, sizeof (buf), "%6.1f", val);
1006                 _surface->write (display (1, buf));
1007                 screen_hold = true;
1008                 break;
1009         case EQEnable:
1010         case CompEnable:
1011                 if (val >= 0.5) {
1012                         _surface->write (display (1, "on"));
1013                 } else {
1014                         _surface->write (display (1, "off"));
1015                 }
1016                 break;
1017         case CompMode:
1018                 if (_surface->mcp().subview_route()) {
1019                         _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
1020                 }
1021                 break;
1022         default:
1023                 break;
1024         }
1025
1026         if (screen_hold) {
1027                 block_vpot_mode_display_for (1000);
1028         }
1029 }
1030
1031 void
1032 Strip::handle_fader_touch (Fader& fader, bool touch_on)
1033 {
1034         if (touch_on) {
1035                 fader.start_touch (_surface->mcp().transport_frame());
1036         } else {
1037                 fader.stop_touch (_surface->mcp().transport_frame(), false);
1038         }
1039 }
1040
1041 void
1042 Strip::handle_fader (Fader& fader, float position)
1043 {
1044         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
1045         boost::shared_ptr<AutomationControl> ac = fader.control();
1046         if (!ac) {
1047                 return;
1048         }
1049
1050         fader.set_value (position);
1051
1052         /* From the Mackie Control MIDI implementation docs:
1053
1054            In order to ensure absolute synchronization with the host software,
1055            Mackie Control uses a closed-loop servo system for the faders,
1056            meaning the faders will always move to their last received position.
1057            When a host receives a Fader Position Message, it must then
1058            re-transmit that message to the Mackie Control or else the faders
1059            will return to their last position.
1060         */
1061
1062         _surface->write (fader.set_position (position));
1063 }
1064
1065 void
1066 Strip::handle_pot (Pot& pot, float delta)
1067 {
1068         /* Pots only emit events when they move, not when they
1069            stop moving. So to get a stop event, we need to use a timeout.
1070         */
1071
1072         boost::shared_ptr<AutomationControl> ac = pot.control();
1073         if (!ac) {
1074                 return;
1075         }
1076         double p = pot.get_value ();
1077         p += delta;
1078         // fader and pot should be the same and fader is hard coded 0 -> 1
1079         p = max (0.0, p);
1080         p = min (1.0, p);
1081         pot.set_value (p);
1082 }
1083
1084 void
1085 Strip::periodic (ARDOUR::microseconds_t now)
1086 {
1087         bool reshow_vpot_mode = false;
1088         bool reshow_name = false;
1089
1090         if (!_route) {
1091                 return;
1092         }
1093
1094         if (_block_screen_redisplay_until >= now) {
1095                 if (_surface->mcp().device_info().has_separate_meters()) {
1096                         goto meters;
1097                 }
1098                 /* no drawing here, for now */
1099                 return;
1100
1101         } else if (_block_screen_redisplay_until) {
1102
1103                 /* timeout reached, reset */
1104
1105                 _block_screen_redisplay_until = 0;
1106                 reshow_vpot_mode = true;
1107                 reshow_name = true;
1108         }
1109
1110         if (_block_vpot_mode_redisplay_until >= now) {
1111                 return;
1112         } else if (_block_vpot_mode_redisplay_until) {
1113
1114                 /* timeout reached, reset */
1115
1116                 _block_vpot_mode_redisplay_until = 0;
1117                 reshow_vpot_mode = true;
1118         }
1119
1120         if (reshow_name) {
1121                 show_route_name ();
1122         }
1123
1124         if (reshow_vpot_mode) {
1125                 return_to_vpot_mode_display ();
1126         } else {
1127                 /* no point doing this if we just switched back to vpot mode
1128                    display */
1129                 update_automation ();
1130         }
1131
1132   meters:
1133         update_meter ();
1134 }
1135
1136 void
1137 Strip::redisplay (ARDOUR::microseconds_t now)
1138 {
1139         RedisplayRequest req;
1140         bool have_request = false;
1141
1142         while (redisplay_requests.read (&req, 1) == 1) {
1143                 /* read them all */
1144                 have_request = true;
1145         }
1146
1147         if (_block_screen_redisplay_until >= now) {
1148                 return;
1149         }
1150
1151         if (have_request) {
1152                 do_parameter_display (req.type, req.val);
1153         }
1154 }
1155
1156 void
1157 Strip::update_automation ()
1158 {
1159         if (!_route) {
1160                 return;
1161         }
1162
1163         ARDOUR::AutoState state = _route->gain_control()->automation_state();
1164
1165         if (state == Touch || state == Play) {
1166                 notify_gain_changed (false);
1167         }
1168
1169         boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
1170         if (pan_control) {
1171                 state = pan_control->automation_state ();
1172                 if (state == Touch || state == Play) {
1173                         notify_panner_azi_changed (false);
1174                 }
1175         }
1176
1177         pan_control = _route->pan_width_control ();
1178         if (pan_control) {
1179                 state = pan_control->automation_state ();
1180                 if (state == Touch || state == Play) {
1181                         notify_panner_width_changed (false);
1182                 }
1183         }
1184
1185         if (_route->trim() && route()->trim()->active()) {
1186                 ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
1187                 if (trim_state == Touch || trim_state == Play) {
1188                         notify_trim_changed (false);
1189                 }
1190         }
1191 }
1192
1193 void
1194 Strip::update_meter ()
1195 {
1196         if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1197                 return;
1198         }
1199
1200         if (_meter && _transport_is_rolling && _metering_active) {
1201                 float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
1202                 _meter->send_update (*_surface, dB);
1203         }
1204 }
1205
1206 void
1207 Strip::zero ()
1208 {
1209         for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
1210                 _surface->write ((*it)->zero ());
1211         }
1212
1213         _surface->write (blank_display (0));
1214         _surface->write (blank_display (1));
1215 }
1216
1217 MidiByteArray
1218 Strip::blank_display (uint32_t line_number)
1219 {
1220         return display (line_number, string());
1221 }
1222
1223 MidiByteArray
1224 Strip::display (uint32_t line_number, const std::string& line)
1225 {
1226         assert (line_number <= 1);
1227
1228         MidiByteArray retval;
1229
1230         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
1231
1232         // sysex header
1233         retval << _surface->sysex_hdr();
1234
1235         // code for display
1236         retval << 0x12;
1237         // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
1238         retval << (_index * 7 + (line_number * 0x38));
1239
1240         // ascii data to display. @param line is UTF-8
1241         string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
1242         string::size_type len = ascii.length();
1243         if (len > 6) {
1244                 ascii = ascii.substr (0, 6);
1245                 len = 6;
1246         }
1247         retval << ascii;
1248         // pad with " " out to 6 chars
1249         for (int i = len; i < 6; ++i) {
1250                 retval << ' ';
1251         }
1252
1253         // column spacer, unless it's the right-hand column
1254         if (_index < 7) {
1255                 retval << ' ';
1256         }
1257
1258         // sysex trailer
1259         retval << MIDI::eox;
1260
1261         return retval;
1262 }
1263
1264 void
1265 Strip::lock_controls ()
1266 {
1267         _controls_locked = true;
1268 }
1269
1270 void
1271 Strip::unlock_controls ()
1272 {
1273         _controls_locked = false;
1274 }
1275
1276 void
1277 Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
1278 {
1279         for (ARDOUR::StrongRouteNotificationList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
1280                 if ((*i) == _route) {
1281                         _surface->write (_select->set_state (on));
1282                         return;
1283                 }
1284         }
1285
1286         _surface->write (_select->set_state (off));
1287 }
1288
1289 string
1290 Strip::vpot_mode_string ()
1291 {
1292         boost::shared_ptr<AutomationControl> ac = _vpot->control();
1293         if (!ac) {
1294                 return string();
1295         }
1296
1297         if (control_by_parameter.find (GainAutomation)->second == _vpot) {
1298                 return "Fader";
1299         } else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
1300                 return "Trim";
1301         } else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
1302                 return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
1303         } else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
1304                 // should be bus name
1305                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1306                 if (p) {
1307                         return p->name();
1308                 }
1309         } else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
1310                 return "Pan";
1311         } else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
1312                 return "Width";
1313         } else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
1314                 return "Elev";
1315         } else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
1316                 return "F/Rear";
1317         } else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
1318                 return "LFE";
1319         }
1320
1321         if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1322                 return string();
1323         }
1324
1325         return "???";
1326 }
1327
1328  void
1329 Strip::potmode_changed (bool notify)
1330 {
1331         if (!_route) {
1332                 return;
1333         }
1334
1335         // WIP
1336         int pm = _surface->mcp().pot_mode();
1337         switch (pm) {
1338         case MackieControlProtocol::Pan:
1339                 // This needs to set current pan mode (azimuth or width... or whatever)
1340                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
1341                 set_vpot_parameter (_pan_mode);
1342                 break;
1343         case MackieControlProtocol::Trim:
1344                 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
1345                 set_vpot_parameter (_trim_mode);
1346                 break;
1347         case MackieControlProtocol::Send:
1348                 // _current_send has the number of the send we will show
1349                 DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
1350                 set_vpot_parameter (SendAutomation);
1351                 break;
1352         }
1353
1354         if (notify) {
1355                 notify_all ();
1356         }
1357 }
1358
1359 void
1360 Strip::block_screen_display_for (uint32_t msecs)
1361 {
1362         _block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1363 }
1364
1365 void
1366 Strip::block_vpot_mode_display_for (uint32_t msecs)
1367 {
1368         _block_vpot_mode_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
1369 }
1370
1371 void
1372 Strip::return_to_vpot_mode_display ()
1373 {
1374         /* returns the second line of the two-line per-strip display
1375            back the mode where it shows what the VPot controls.
1376         */
1377
1378         if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1379                 /* do nothing - second line shows value of current subview parameter */
1380                 return;
1381         } else if (_route) {
1382                 _surface->write (display (1, vpot_mode_string()));
1383         } else {
1384                 _surface->write (blank_display (1));
1385         }
1386 }
1387
1388 void
1389 Strip::next_pot_mode ()
1390 {
1391         vector<AutomationType>::iterator i;
1392
1393         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1394                 /* do not change vpot mode while in flipped mode */
1395                 DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
1396                 _surface->write (display (1, "Flip"));
1397                 block_vpot_mode_display_for (1000);
1398                 return;
1399         }
1400
1401
1402         boost::shared_ptr<AutomationControl> ac = _vpot->control();
1403
1404         if (!ac) {
1405                 return;
1406         }
1407         if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
1408                 if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
1409                         return;
1410                 }
1411
1412                 for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
1413                         if ((*i) == ac->parameter()) {
1414                                 break;
1415                         }
1416                 }
1417
1418                 /* move to the next mode in the list, or back to the start (which will
1419                 also happen if the current mode is not in the current pot mode list)
1420                 */
1421
1422                 if (i != possible_pot_parameters.end()) {
1423                         ++i;
1424                 }
1425
1426                 if (i == possible_pot_parameters.end()) {
1427                         i = possible_pot_parameters.begin();
1428                 }
1429                 set_vpot_parameter (*i);
1430         } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
1431                                 if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter())) {
1432                         return;
1433                 }
1434
1435                 for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
1436                         if ((*i) == ac->parameter()) {
1437                                 break;
1438                         }
1439                 }
1440                 if ((*i) == PhaseAutomation && _route->phase_invert().size() > 1) {
1441                         // There are more than one channel of phase
1442                         if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
1443                                 _route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
1444                                 set_vpot_parameter (*i);
1445                                 return;
1446                         } else {
1447                                 _route->phase_control()->set_channel(0);
1448                         }
1449                 }
1450                 /* move to the next mode in the list, or back to the start (which will
1451                 also happen if the current mode is not in the current pot mode list)
1452                 */
1453
1454                 if (i != possible_trim_parameters.end()) {
1455                         ++i;
1456                 }
1457
1458                 if (i == possible_trim_parameters.end()) {
1459                         i = possible_trim_parameters.begin();
1460                 }
1461                 set_vpot_parameter (*i);
1462         } else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
1463                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1464                 if (!p) {
1465                         return;
1466                 }
1467                 p = _route->nth_send (_current_send + 1);
1468                 if (p && p->name() != "Monitor 1") {
1469                         _current_send++;
1470                 } else {
1471                         _current_send = 0;
1472                 }
1473                 set_vpot_parameter (SendAutomation);
1474         }
1475 }
1476
1477 void
1478 Strip::subview_mode_changed ()
1479 {
1480         boost::shared_ptr<Route> r = _surface->mcp().subview_route();
1481
1482         subview_connections.drop_connections ();
1483
1484         switch (_surface->mcp().subview_mode()) {
1485         case MackieControlProtocol::None:
1486                 set_vpot_parameter (vpot_parameter);
1487                 notify_metering_state_changed ();
1488                 eq_band = -1;
1489                 break;
1490
1491         case MackieControlProtocol::EQ:
1492                 setup_eq_vpot (r);
1493                 break;
1494
1495         case MackieControlProtocol::Dynamics:
1496                 setup_dyn_vpot (r);
1497                 break;
1498         }
1499 }
1500
1501 void
1502 Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
1503 {
1504         if (!r) {
1505                 return;
1506         }
1507
1508         boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
1509         boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
1510         boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
1511         boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
1512         boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
1513         boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
1514
1515         uint32_t pos = _surface->mcp().global_index (*this);
1516
1517         /* we will control the pos-th available parameter, from the list in the
1518          * order shown above.
1519          */
1520
1521         vector<boost::shared_ptr<AutomationControl> > available;
1522         vector<AutomationType> params;
1523
1524         if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
1525         if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
1526         if (mc) { available.push_back (mc); params.push_back (CompMode); }
1527         if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
1528         if (rc) { available.push_back (rc); params.push_back (CompRedux); }
1529         if (ec) { available.push_back (ec); params.push_back (CompEnable); }
1530
1531         if (pos >= available.size()) {
1532                 /* this knob is not needed to control the available parameters */
1533                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1534                 _surface->write (display (0, string()));
1535                 _surface->write (display (1, string()));
1536                 return;
1537         }
1538
1539         boost::shared_ptr<AutomationControl> pc;
1540         AutomationType param;
1541
1542         pc = available[pos];
1543         param = params[pos];
1544
1545         pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false), ui_context());
1546         _vpot->set_control (pc);
1547
1548         string pot_id;
1549
1550         switch (param) {
1551         case CompThreshold:
1552                 pot_id = "Thresh";
1553                 break;
1554         case CompSpeed:
1555                 pot_id = "Speed";
1556                 break;
1557         case CompMode:
1558                 pot_id = "Mode";
1559                 break;
1560         case CompMakeup:
1561                 pot_id = "Makeup";
1562                 break;
1563         case CompRedux:
1564                 pot_id = "Redux";
1565                 break;
1566         case CompEnable:
1567                 pot_id = "on/off";
1568                 break;
1569         default:
1570                 break;
1571         }
1572
1573         if (!pot_id.empty()) {
1574                 _surface->write (display (0, pot_id));
1575         }
1576
1577         notify_dyn_change (param, true);
1578 }
1579
1580 void
1581 Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
1582 {
1583         uint32_t bands = r->eq_band_cnt ();
1584
1585         if (bands == 0) {
1586                 /* should never get here */
1587                 return;
1588         }
1589
1590         /* figure out how many params per band are available */
1591
1592         boost::shared_ptr<AutomationControl> pc;
1593         uint32_t params_per_band = 0;
1594
1595         if ((pc = r->eq_gain_controllable (0))) {
1596                 params_per_band += 1;
1597         }
1598         if ((pc = r->eq_freq_controllable (0))) {
1599                 params_per_band += 1;
1600         }
1601         if ((pc = r->eq_q_controllable (0))) {
1602                 params_per_band += 1;
1603         }
1604         if ((pc = r->eq_shape_controllable (0))) {
1605                 params_per_band += 1;
1606         }
1607
1608         /* pick the one for this strip, based on its global position across
1609          * all surfaces
1610          */
1611
1612         pc.reset ();
1613
1614         const uint32_t total_band_parameters = bands * params_per_band;
1615         const uint32_t global_pos = _surface->mcp().global_index (*this);
1616         AutomationType param = NullAutomation;
1617         string band_name;
1618
1619         eq_band = -1;
1620
1621         if (global_pos < total_band_parameters) {
1622
1623                 /* show a parameter for an EQ band */
1624
1625                 const uint32_t parameter = global_pos % params_per_band;
1626                 eq_band = global_pos / params_per_band;
1627                 band_name = r->eq_band_name (eq_band);
1628
1629                 switch (parameter) {
1630                 case 0:
1631                         pc = r->eq_gain_controllable (eq_band);
1632                         param = EQGain;
1633                         break;
1634                 case 1:
1635                         pc = r->eq_freq_controllable (eq_band);
1636                         param = EQFrequency;
1637                         break;
1638                 case 2:
1639                         pc = r->eq_q_controllable (eq_band);
1640                         param = EQQ;
1641                         break;
1642                 case 3:
1643                         pc = r->eq_shape_controllable (eq_band);
1644                         param = EQShape;
1645                         break;
1646                 }
1647
1648         } else {
1649
1650                 /* show a non-band parameter (HPF or enable)
1651                  */
1652
1653                 uint32_t parameter = global_pos - total_band_parameters;
1654
1655                 switch (parameter) {
1656                 case 0: /* first control after band parameters */
1657                         pc = r->eq_hpf_controllable();
1658                         param = EQHPF;
1659                         break;
1660                 case 1: /* second control after band parameters */
1661                         pc = r->eq_enable_controllable();
1662                         param = EQEnable;
1663                         break;
1664                 default:
1665                         /* nothing to control */
1666                         _vpot->set_control (boost::shared_ptr<AutomationControl>());
1667                         _surface->write (display (0, string()));
1668                         _surface->write (display (1, string()));
1669                         /* done */
1670                         return;
1671                         break;
1672                 }
1673
1674         }
1675
1676         if (pc) {
1677                 pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
1678                 _vpot->set_control (pc);
1679
1680                 string pot_id;
1681
1682                 switch (param) {
1683                 case EQGain:
1684                         pot_id = band_name + "Gain";
1685                         break;
1686                 case EQFrequency:
1687                         pot_id = band_name + "Freq";
1688                         break;
1689                 case EQQ:
1690                         pot_id = band_name + " Q";
1691                         break;
1692                 case EQShape:
1693                         pot_id = band_name + " Shp";
1694                         break;
1695                 case EQHPF:
1696                         pot_id = "HPFreq";
1697                         break;
1698                 case EQEnable:
1699                         pot_id = "on/off";
1700                         break;
1701                 default:
1702                         break;
1703                 }
1704
1705                 if (!pot_id.empty()) {
1706                         _surface->write (display (0, pot_id));
1707                 }
1708
1709                 notify_eq_change (param, eq_band, true);
1710         }
1711 }
1712
1713 void
1714 Strip::set_vpot_parameter (AutomationType p)
1715 {
1716         if (!_route || (p == NullAutomation)) {
1717                 control_by_parameter[vpot_parameter] = 0;
1718                 vpot_parameter = NullAutomation;
1719                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1720                 _surface->write (display (1, string()));
1721                 return;
1722         }
1723
1724         boost::shared_ptr<AutomationControl> pan_control;
1725
1726         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
1727
1728         reset_saved_values ();
1729
1730         /* unset any mapping between the vpot and any existing parameters */
1731
1732         for (ControlParameterMap::iterator i = control_by_parameter.begin(); i != control_by_parameter.end(); ++i) {
1733
1734                 if (i != control_by_parameter.end() && i->second == _vpot) {
1735                         i->second = 0;
1736                 }
1737         }
1738
1739         switch (p) {
1740         case PanAzimuthAutomation:
1741                 if ((pan_control = _route->pan_azimuth_control ())) {
1742                         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1743                                 _pan_mode = PanAzimuthAutomation;
1744                                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1745                                         /* gain to vpot, pan azi to fader */
1746                                         _vpot->set_control (_route->group_gain_control());
1747                                         vpot_parameter = GainAutomation;
1748                                         control_by_parameter[GainAutomation] = _vpot;
1749                                         _fader->set_control (pan_control);
1750                                         control_by_parameter[PanAzimuthAutomation] = _fader;
1751                                 } else {
1752                                         _fader->set_control (boost::shared_ptr<AutomationControl>());
1753                                         control_by_parameter[PanAzimuthAutomation] = 0;
1754                                 }
1755                         } else {
1756                                 /* gain to fader, pan azi to vpot */
1757                                 vpot_parameter = PanAzimuthAutomation;
1758                                 _fader->set_control (_route->group_gain_control());
1759                                 control_by_parameter[GainAutomation] = _fader;
1760                                 _vpot->set_control (pan_control);
1761                                 control_by_parameter[PanAzimuthAutomation] = _vpot;
1762                         }
1763                 } else {
1764                         _vpot->set_control (boost::shared_ptr<AutomationControl>());
1765                         control_by_parameter[PanAzimuthAutomation] = 0;
1766                 }
1767                 break;
1768
1769         case PanWidthAutomation:
1770                 if ((pan_control = _route->pan_width_control ())) {
1771                         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1772                                 _pan_mode = PanWidthAutomation;
1773                                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1774                                         /* gain to vpot, pan width to fader */
1775                                         _vpot->set_control (_route->group_gain_control());
1776                                         vpot_parameter = GainAutomation;
1777                                         control_by_parameter[GainAutomation] = _vpot;
1778                                         _fader->set_control (pan_control);
1779                                         control_by_parameter[PanWidthAutomation] = _fader;
1780                                 } else {
1781                                         _fader->set_control (boost::shared_ptr<AutomationControl>());
1782                                         control_by_parameter[PanWidthAutomation] = 0;
1783                                 }
1784                         } else {
1785                                 /* gain to fader, pan width to vpot */
1786                                 vpot_parameter = PanWidthAutomation;
1787                                 _fader->set_control (_route->group_gain_control());
1788                                 control_by_parameter[GainAutomation] = _fader;
1789                                 _vpot->set_control (pan_control);
1790                                 control_by_parameter[PanWidthAutomation] = _vpot;
1791                         }
1792                 } else {
1793                         _vpot->set_control (boost::shared_ptr<AutomationControl>());
1794                         control_by_parameter[PanWidthAutomation] = 0;
1795                 }
1796                 break;
1797
1798         case PanElevationAutomation:
1799                 break;
1800         case PanFrontBackAutomation:
1801                 break;
1802         case PanLFEAutomation:
1803                 break;
1804         case TrimAutomation:
1805                 _trim_mode = TrimAutomation;
1806                 vpot_parameter = TrimAutomation;
1807                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1808                         /* gain to vpot, trim to fader */
1809                         _vpot->set_control (_route->group_gain_control());
1810                         control_by_parameter[GainAutomation] = _vpot;
1811                         if (_route->trim() && route()->trim()->active()) {
1812                                 _fader->set_control (_route->trim_control());
1813                                 control_by_parameter[TrimAutomation] = _fader;
1814                         } else {
1815                                 _fader->set_control (boost::shared_ptr<AutomationControl>());
1816                                 control_by_parameter[TrimAutomation] = 0;
1817                         }
1818                 } else {
1819                         /* gain to fader, trim to vpot */
1820                         _fader->set_control (_route->group_gain_control());
1821                         control_by_parameter[GainAutomation] = _fader;
1822                         if (_route->trim() && route()->trim()->active()) {
1823                                 _vpot->set_control (_route->trim_control());
1824                                 control_by_parameter[TrimAutomation] = _vpot;
1825                         } else {
1826                                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1827                                 control_by_parameter[TrimAutomation] = 0;
1828                         }
1829                 }
1830                 break;
1831         case PhaseAutomation:
1832                 _trim_mode = PhaseAutomation;
1833                 vpot_parameter = PhaseAutomation;
1834                 if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1835                         /* gain to vpot, phase to fader */
1836                         _vpot->set_control (_route->group_gain_control());
1837                         control_by_parameter[GainAutomation] = _vpot;
1838                         if (_route->phase_invert().size()) {
1839                                 _fader->set_control (_route->phase_control());
1840                                 control_by_parameter[PhaseAutomation] = _fader;
1841                         } else {
1842                                 _fader->set_control (boost::shared_ptr<AutomationControl>());
1843                                 control_by_parameter[PhaseAutomation] = 0;
1844                         }
1845                 } else {
1846                         /* gain to fader, phase to vpot */
1847                         _fader->set_control (_route->group_gain_control());
1848                         control_by_parameter[GainAutomation] = _fader;
1849                         if (_route->phase_invert().size()) {
1850                                 _vpot->set_control (_route->phase_control());
1851                                 control_by_parameter[PhaseAutomation] = _vpot;
1852                         } else {
1853                                 _vpot->set_control (boost::shared_ptr<AutomationControl>());
1854                                 control_by_parameter[PhaseAutomation] = 0;
1855                         }
1856                 }
1857                 break;
1858         case SendAutomation:
1859                 if (!Profile->get_mixbus()) {
1860                         if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
1861                                 // gain to vpot, send to fader
1862                                 _vpot->set_control (_route->group_gain_control());
1863                                 control_by_parameter[GainAutomation] = _vpot;
1864                                 // test for send to control
1865                                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1866                                 if (p && p->name() != "Monitor 1") {
1867                                         boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
1868                                         boost::shared_ptr<Amp> a = s->amp();
1869                                         _fader->set_control (a->gain_control());
1870                                         // connect to signal
1871                                         send_connections.drop_connections ();
1872                                         a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1873                                         control_by_parameter[SendAutomation] = _fader;
1874                                 } else {
1875                                         _fader->set_control (boost::shared_ptr<AutomationControl>());
1876                                         control_by_parameter[SendAutomation] = 0;
1877                                 }
1878                         } else {
1879                                 // gain to fader, send to vpot
1880                                 _fader->set_control (_route->group_gain_control());
1881                                 control_by_parameter[GainAutomation] = _fader;
1882                                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1883                                 if (p && p->name() != "Monitor 1") {
1884                                         boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
1885                                         boost::shared_ptr<Amp> a = s->amp();
1886                                         _vpot->set_control (a->gain_control());
1887                                         // connect to signal
1888                                         send_connections.drop_connections ();
1889                                         a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1890                                         control_by_parameter[SendAutomation] = _vpot;
1891                         } else {
1892                                 // gain to fader, send to vpot
1893                                 _fader->set_control (_route->group_gain_control());
1894                                 control_by_parameter[GainAutomation] = _fader;
1895                                 boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
1896                                 if (p && p->name() != "Monitor 1") {
1897                                         boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
1898                                         boost::shared_ptr<Amp> a = s->amp();
1899                                         _vpot->set_control (a->gain_control());
1900                                         // connect to signal
1901                                         send_connections.drop_connections ();
1902                                         a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
1903                                         control_by_parameter[SendAutomation] = _vpot;
1904                                 } else {
1905                                         _vpot->set_control (boost::shared_ptr<AutomationControl>());
1906                                         control_by_parameter[SendAutomation] = 0;
1907                                 }
1908                         }
1909                 }
1910                 break;
1911         default:
1912                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("vpot mode %1 not known.\n", p));
1913                 break;
1914
1915         }
1916
1917         _surface->write (display (1, vpot_mode_string()));
1918 }
1919
1920 bool
1921 Strip::is_midi_track () const
1922 {
1923         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1924 }
1925
1926 void
1927 Strip::reset_saved_values ()
1928 {
1929         _last_pan_azi_position_written = -1.0;
1930         _last_pan_width_position_written = -1.0;
1931         _last_gain_position_written = -1.0;
1932         _last_trim_position_written = -1.0;
1933
1934 }
1935
1936 void
1937 Strip::notify_metering_state_changed()
1938 {
1939         if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
1940                 return;
1941         }
1942
1943         if (!_route || !_meter) {
1944                 return;
1945         }
1946
1947         bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
1948         bool metering_active = _surface->mcp().metering_active ();
1949
1950         if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
1951                 return;
1952         }
1953
1954         _meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
1955
1956         if (!transport_is_rolling || !metering_active) {
1957                 notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
1958                 notify_panner_azi_changed (true);
1959         }
1960
1961         _transport_is_rolling = transport_is_rolling;
1962         _metering_active = metering_active;
1963 }