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