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