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