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