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