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