7a699ca90a812a114709836b88115f70b93e3f0a
[ardour.git] / libs / surfaces / mackie / mackie_control_protocol.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 <fcntl.h>
21 #include <iostream>
22 #include <algorithm>
23 #include <cmath>
24 #include <sstream>
25 #include <vector>
26 #include <iomanip>
27
28 #include <inttypes.h>
29 #include <float.h>
30 #include <sys/time.h>
31 #include <errno.h>
32
33 #include <boost/shared_array.hpp>
34 #include <glibmm/miscutils.h>
35
36 #include "midi++/types.h"
37 #include "midi++/port.h"
38 #include "midi++/ipmidi_port.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/error.h"
41 #include "pbd/memento_command.h"
42 #include "pbd/convert.h"
43
44 #include "ardour/audio_track.h"
45 #include "ardour/automation_control.h"
46 #include "ardour/async_midi_port.h"
47 #include "ardour/dB.h"
48 #include "ardour/debug.h"
49 #include "ardour/location.h"
50 #include "ardour/meter.h"
51 #include "ardour/midi_track.h"
52 #include "ardour/panner.h"
53 #include "ardour/panner_shell.h"
54 #include "ardour/profile.h"
55 #include "ardour/record_enable_control.h"
56 #include "ardour/route.h"
57 #include "ardour/route_group.h"
58 #include "ardour/session.h"
59 #include "ardour/tempo.h"
60 #include "ardour/track.h"
61 #include "ardour/types.h"
62 #include "ardour/audioengine.h"
63 #include "ardour/vca_manager.h"
64
65 #include "mackie_control_protocol.h"
66
67 #include "midi_byte_array.h"
68 #include "mackie_control_exception.h"
69 #include "device_profile.h"
70 #include "surface_port.h"
71 #include "surface.h"
72 #include "strip.h"
73 #include "control_group.h"
74 #include "meter.h"
75 #include "button.h"
76 #include "fader.h"
77 #include "pot.h"
78
79 using namespace ARDOUR;
80 using namespace std;
81 using namespace PBD;
82 using namespace Glib;
83 using namespace ArdourSurface;
84 using namespace Mackie;
85
86 #include "pbd/i18n.h"
87
88 #include "pbd/abstract_ui.cc" // instantiate template
89
90 const int MackieControlProtocol::MODIFIER_OPTION = 0x1;
91 const int MackieControlProtocol::MODIFIER_CONTROL = 0x2;
92 const int MackieControlProtocol::MODIFIER_SHIFT = 0x4;
93 const int MackieControlProtocol::MODIFIER_CMDALT = 0x8;
94 const int MackieControlProtocol::MODIFIER_ZOOM = 0x10;
95 const int MackieControlProtocol::MODIFIER_SCRUB = 0x20;
96 const int MackieControlProtocol::MODIFIER_MARKER = 0x40;
97 const int MackieControlProtocol::MODIFIER_NUDGE = 0x80;
98 const int MackieControlProtocol::MAIN_MODIFIER_MASK = (MackieControlProtocol::MODIFIER_OPTION|
99                                                        MackieControlProtocol::MODIFIER_CONTROL|
100                                                        MackieControlProtocol::MODIFIER_SHIFT|
101                                                        MackieControlProtocol::MODIFIER_CMDALT);
102
103 MackieControlProtocol* MackieControlProtocol::_instance = 0;
104
105 bool MackieControlProtocol::probe()
106 {
107         return true;
108 }
109
110 MackieControlProtocol::MackieControlProtocol (Session& session)
111         : ControlProtocol (session, X_("Mackie"))
112         , AbstractUI<MackieControlUIRequest> (name())
113         , _current_initial_bank (0)
114         , _frame_last (0)
115         , _timecode_type (ARDOUR::AnyTime::BBT)
116         , _gui (0)
117         , _scrub_mode (false)
118         , _flip_mode (Normal)
119         , _view_mode (Mixer)
120         , _subview_mode (None)
121         , _current_selected_track (-1)
122         , _modifier_state (0)
123         , _ipmidi_base (MIDI::IPMIDIPort::lowest_ipmidi_port_default)
124         , needs_ipmidi_restart (false)
125         , _metering_active (true)
126         , _initialized (false)
127         , configuration_state (0)
128         , state_version (0)
129         , marker_modifier_consumed_by_button (false)
130         , nudge_modifier_consumed_by_button (false)
131 {
132         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
133
134         DeviceInfo::reload_device_info ();
135         DeviceProfile::reload_device_profiles ();
136
137         for (int i = 0; i < 9; i++) {
138                 _last_bank[i] = 0;
139         }
140
141         PresentationInfo::Change.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_presentation_info_changed, this), this);
142
143         _instance = this;
144
145         build_button_map ();
146 }
147
148 MackieControlProtocol::~MackieControlProtocol()
149 {
150         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol init\n");
151
152         for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
153                 (*si)->reset ();
154         }
155
156         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol drop_connections ()\n");
157         drop_connections ();
158
159         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n");
160         tear_down_gui ();
161
162         delete configuration_state;
163
164         /* stop event loop */
165         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol BaseUI::quit ()\n");
166         BaseUI::quit ();
167
168         try {
169                 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol close()\n");
170                 close();
171         }
172         catch (exception & e) {
173                 cout << "~MackieControlProtocol caught " << e.what() << endl;
174         }
175         catch (...) {
176                 cout << "~MackieControlProtocol caught unknown" << endl;
177         }
178
179         _instance = 0;
180
181         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol done\n");
182 }
183
184 void
185 MackieControlProtocol::thread_init ()
186 {
187         struct sched_param rtparam;
188
189         pthread_set_name (event_loop_name().c_str());
190
191         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
192         ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
193
194         memset (&rtparam, 0, sizeof (rtparam));
195         rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
196
197         if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
198                 // do we care? not particularly.
199         }
200 }
201
202 void
203 MackieControlProtocol::ping_devices ()
204 {
205         /* should not be called if surfaces are not connected, but will not
206          * malfunction if it is.
207          */
208
209         for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
210                 (*si)->connected ();
211         }
212 }
213
214 // go to the previous track.
215 void
216 MackieControlProtocol::prev_track()
217 {
218         if (_current_initial_bank >= 1) {
219                 switch_banks (_current_initial_bank - 1);
220         }
221 }
222
223 // go to the next track.
224 void
225 MackieControlProtocol::next_track()
226 {
227         Sorted sorted = get_sorted_stripables();
228         if (_current_initial_bank + n_strips() < sorted.size()) {
229                 switch_banks (_current_initial_bank + 1);
230         }
231 }
232
233 bool
234 MackieControlProtocol::stripable_is_locked_to_strip (boost::shared_ptr<Stripable> r) const
235 {
236         for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
237                 if ((*si)->stripable_is_locked_to_strip (r)) {
238                         return true;
239                 }
240         }
241         return false;
242 }
243
244 // predicate for sort call in get_sorted_stripables
245 struct StripableByPresentationOrder
246 {
247         bool operator () (const boost::shared_ptr<Stripable> & a, const boost::shared_ptr<Stripable> & b) const
248         {
249                 return a->presentation_info().order() < b->presentation_info().order();
250         }
251
252         bool operator () (const Stripable & a, const Stripable & b) const
253         {
254                 return a.presentation_info().order() < b.presentation_info().order();
255         }
256
257         bool operator () (const Stripable * a, const Stripable * b) const
258         {
259                 return a->presentation_info().order() < b->presentation_info().order();
260         }
261 };
262
263 MackieControlProtocol::Sorted
264 MackieControlProtocol::get_sorted_stripables()
265 {
266         Sorted sorted;
267
268         // fetch all stripables
269         StripableList stripables;
270
271         session->get_stripables (stripables);
272
273         // sort in presentation order, and exclude master, control and hidden stripables
274         // and any stripables that are already set.
275
276         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
277
278                 boost::shared_ptr<Stripable> s = *it;
279
280                 if (s->presentation_info().special()) {
281                         continue;
282                 }
283
284                 /* don't include locked routes */
285
286                 if (stripable_is_locked_to_strip (s)) {
287                         continue;
288                 }
289
290                 switch (_view_mode) {
291                 case Mixer:
292                         if (!s->presentation_info().hidden()) {
293                                 sorted.push_back (s);
294                         }
295                         break;
296                 case AudioTracks:
297                         if (is_audio_track(s) && !s->presentation_info().hidden()) {
298                                 sorted.push_back (s);
299                         }
300                         break;
301                 case Busses:
302                         if (Profile->get_mixbus()) {
303 #ifdef MIXBUS
304                                 if (s->mixbus()) {
305                                         sorted.push_back (s);
306                                 }
307 #endif
308                         } else {
309                                 if (!is_track(s) && !s->presentation_info().hidden()) {
310                                         sorted.push_back (s);
311                                 }
312                         }
313                         break;
314                 case MidiTracks:
315                         if (is_midi_track(s) && !s->presentation_info().hidden()) {
316                                 sorted.push_back (s);
317                         }
318                         break;
319                 case Plugins:
320                         break;
321                 case Auxes: // in ardour, for now aux and buss are same. for mixbus, "Busses" are mixbuses, "Auxes" are ardour buses
322 #ifdef MIXBUS
323                         if (!s->mixbus() && !is_track(s) && !s->presentation_info().hidden())
324 #else
325                         if (!is_track(s) && !s->presentation_info().hidden())
326 #endif
327                         {
328                                 sorted.push_back (s);
329                         }
330                         break;
331                 case Hidden: // Show all the tracks we have hidden
332                         if (s->presentation_info().hidden()) {
333                                 // maybe separate groups
334                                 sorted.push_back (s);
335                         }
336                         break;
337                 case Selected: // For example: a group (this is USER)
338                         if (s->presentation_info().selected() && !s->presentation_info().hidden()) {
339                                 sorted.push_back (s);
340                         }
341                         break;
342                 }
343         }
344
345         sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
346         return sorted;
347 }
348
349 void
350 MackieControlProtocol::refresh_current_bank()
351 {
352         switch_banks (_current_initial_bank, true);
353 }
354
355 uint32_t
356 MackieControlProtocol::n_strips (bool with_locked_strips) const
357 {
358         uint32_t strip_count = 0;
359
360         for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
361                 strip_count += (*si)->n_strips (with_locked_strips);
362         }
363
364         return strip_count;
365 }
366
367 int
368 MackieControlProtocol::switch_banks (uint32_t initial, bool force)
369 {
370         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch banking to start at %1 force ? %2 current = %3\n", initial, force, _current_initial_bank));
371
372         if (initial == _current_initial_bank && !force) {
373                 /* everything is as it should be */
374                 return 0;
375         }
376
377         Sorted sorted = get_sorted_stripables();
378         uint32_t strip_cnt = n_strips (false); // do not include locked strips
379                                                // in this count
380
381         if (initial >= sorted.size() && !force) {
382                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("bank target %1 exceeds route range %2\n",
383                                                                    _current_initial_bank, sorted.size()));
384                 /* too high, we can't get there */
385                 return -1;
386         }
387
388         if (sorted.size() <= strip_cnt && _current_initial_bank == 0 && !force) {
389                 /* no banking - not enough stripables to fill all strips and we're
390                  * not at the first one.
391                  */
392                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("less routes (%1) than strips (%2) and we're at the end already (%3)\n",
393                                                                    sorted.size(), strip_cnt, _current_initial_bank));
394                 return -1;
395         }
396
397         _current_initial_bank = initial;
398         _current_selected_track = -1;
399
400         // Map current bank of stripables onto each surface(+strip)
401
402         if (_current_initial_bank < sorted.size()) {
403
404                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available stripables %3 on %4 surfaces\n",
405                                                                    _current_initial_bank, strip_cnt, sorted.size(),
406                                                                    surfaces.size()));
407
408                 // link stripables to strips
409
410                 Sorted::iterator r = sorted.begin() + _current_initial_bank;
411
412                 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
413                         vector<boost::shared_ptr<Stripable> > stripables;
414                         uint32_t added = 0;
415
416                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface has %1 unlocked strips\n", (*si)->n_strips (false)));
417
418                         for (; r != sorted.end() && added < (*si)->n_strips (false); ++r, ++added) {
419                                 stripables.push_back (*r);
420                         }
421
422                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("give surface %1 stripables\n", stripables.size()));
423
424                         (*si)->map_stripables (stripables);
425                 }
426
427         } else {
428                 /* all strips need to be reset */
429                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("clear all strips, bank target %1  is outside route range %2\n",
430                                                                    _current_initial_bank, sorted.size()));
431                 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
432                         vector<boost::shared_ptr<Stripable> > stripables;
433                         /* pass in an empty stripables list, so that all strips will be reset */
434                         (*si)->map_stripables (stripables);
435                 }
436                 return -1;
437         }
438
439         /* current bank has not been saved */
440         session->set_dirty();
441
442         return 0;
443 }
444
445 int
446 MackieControlProtocol::set_active (bool yn)
447 {
448         DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn));
449
450         if (yn == active()) {
451                 return 0;
452         }
453
454         if (yn) {
455
456                 /* start event loop */
457
458                 BaseUI::run ();
459
460                 connect_session_signals ();
461
462                 if (!_device_info.name().empty()) {
463                         set_device (_device_info.name(), true);
464                 }
465
466                 /* set up periodic task for timecode display and metering and automation
467                  */
468
469                 Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
470                 periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
471                 periodic_timeout->attach (main_loop()->get_context());
472
473                 /* periodic task used to update strip displays */
474
475                 Glib::RefPtr<Glib::TimeoutSource> redisplay_timeout = Glib::TimeoutSource::create (10); // milliseconds
476                 redisplay_connection = redisplay_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::redisplay));
477                 redisplay_timeout->attach (main_loop()->get_context());
478
479         } else {
480
481                 BaseUI::quit ();
482                 close ();
483
484         }
485
486         ControlProtocol::set_active (yn);
487
488         DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn));
489
490         return 0;
491 }
492
493 bool
494 MackieControlProtocol::hui_heartbeat ()
495 {
496         Glib::Threads::Mutex::Lock lm (surfaces_lock);
497
498         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
499                 (*s)->hui_heartbeat ();
500         }
501
502         return true;
503 }
504
505 bool
506 MackieControlProtocol::periodic ()
507 {
508         if (!active()) {
509                 return false;
510         }
511
512         if (!_initialized) {
513                 /* wait for higher-frequency redisplay() callback to initialize
514                  * us
515                  */
516                 return true;
517         }
518
519         update_timecode_display ();
520
521         ARDOUR::microseconds_t now_usecs = ARDOUR::get_microseconds ();
522
523         {
524                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
525
526                 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
527                         (*s)->periodic (now_usecs);
528                 }
529         }
530
531         return true;
532 }
533
534 bool
535 MackieControlProtocol::redisplay ()
536 {
537         if (!active()) {
538                 return false;
539         }
540
541         if (needs_ipmidi_restart) {
542                 ipmidi_restart ();
543                 return true;
544         }
545
546         if (!_initialized) {
547                 initialize();
548         }
549
550         ARDOUR::microseconds_t now = ARDOUR::get_microseconds ();
551
552         {
553                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
554
555                 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
556                         (*s)->redisplay (now, false);
557                 }
558         }
559
560         return true;
561 }
562
563 void
564 MackieControlProtocol::update_timecode_beats_led()
565 {
566         if (!_device_info.has_timecode_display()) {
567                 return;
568         }
569
570         DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::update_timecode_beats_led(): %1\n", _timecode_type));
571         switch (_timecode_type) {
572                 case ARDOUR::AnyTime::BBT:
573                         update_global_led (Led::Beats, on);
574                         update_global_led (Led::Timecode, off);
575                         break;
576                 case ARDOUR::AnyTime::Timecode:
577                         update_global_led (Led::Timecode, on);
578                         update_global_led (Led::Beats, off);
579                         break;
580                 default:
581                         ostringstream os;
582                         os << "Unknown Anytime::Type " << _timecode_type;
583                         throw runtime_error (os.str());
584         }
585 }
586
587 void
588 MackieControlProtocol::update_global_button (int id, LedState ls)
589 {
590         boost::shared_ptr<Surface> surface;
591
592         {
593                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
594
595                 if (surfaces.empty()) {
596                         return;
597                 }
598
599                 if (!_device_info.has_global_controls()) {
600                         return;
601                 }
602                 // surface needs to be master surface
603                 surface = _master_surface;
604         }
605
606         map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (id);
607         if (x != surface->controls_by_device_independent_id.end()) {
608                 Button * button = dynamic_cast<Button*> (x->second);
609                 surface->write (button->set_state (ls));
610         } else {
611                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", id));
612         }
613 }
614
615 void
616 MackieControlProtocol::update_global_led (int id, LedState ls)
617 {
618         Glib::Threads::Mutex::Lock lm (surfaces_lock);
619
620         if (surfaces.empty()) {
621                 return;
622         }
623
624         if (!_device_info.has_global_controls()) {
625                 return;
626         }
627         boost::shared_ptr<Surface> surface = _master_surface;
628
629         map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (id);
630
631         if (x != surface->controls_by_device_independent_id.end()) {
632                 Led * led = dynamic_cast<Led*> (x->second);
633                 DEBUG_TRACE (DEBUG::MackieControl, "Writing LedState\n");
634                 surface->write (led->set_state (ls));
635         } else {
636                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", id));
637         }
638 }
639
640 void
641 MackieControlProtocol::device_ready ()
642 {
643         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("device ready init (active=%1)\n", active()));
644         update_surfaces ();
645         set_subview_mode (MackieControlProtocol::None, boost::shared_ptr<Stripable>());
646         set_flip_mode (Normal);
647 }
648
649 // send messages to surface to set controls to correct values
650 void
651 MackieControlProtocol::update_surfaces()
652 {
653         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::update_surfaces() init (active=%1)\n", active()));
654         if (!active()) {
655                 return;
656         }
657
658         // do the initial bank switch to connect signals
659         // _current_initial_bank is initialised by set_state
660         (void) switch_banks (_current_initial_bank, true);
661
662         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() finished\n");
663 }
664
665 void
666 MackieControlProtocol::initialize()
667 {
668         {
669                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
670
671                 if (surfaces.empty()) {
672                         return;
673                 }
674
675                 if (!_master_surface->active ()) {
676                         return;
677                 }
678
679                 // sometimes the jog wheel is a pot
680                 if (_device_info.has_jog_wheel()) {
681                         _master_surface->blank_jog_ring ();
682                 }
683         }
684
685         // update global buttons and displays
686
687         notify_record_state_changed();
688         notify_transport_state_changed();
689         update_timecode_beats_led();
690
691         _initialized = true;
692 }
693
694 void
695 MackieControlProtocol::connect_session_signals()
696 {
697         // receive routes added
698         session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_routes_added, this, _1), this);
699         // receive VCAs added
700         session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_vca_added, this, _1), this);
701
702         // receive record state toggled
703         session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_record_state_changed, this), this);
704         // receive transport state changed
705         session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_transport_state_changed, this), this);
706         session->TransportLooped.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_loop_state_changed, this), this);
707         // receive punch-in and punch-out
708         Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
709         session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
710         // receive rude solo changed
711         session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), this);
712
713         // make sure remote id changed signals reach here
714         // see also notify_stripable_added
715         Sorted sorted = get_sorted_stripables();
716 }
717
718 void
719 MackieControlProtocol::set_profile (const string& profile_name)
720 {
721         map<string,DeviceProfile>::iterator d = DeviceProfile::device_profiles.find (profile_name);
722
723         if (d == DeviceProfile::device_profiles.end()) {
724                 _device_profile = DeviceProfile (profile_name);
725                 return;
726         }
727
728         _device_profile = d->second;
729 }
730
731 int
732 MackieControlProtocol::set_device_info (const string& device_name)
733 {
734         map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name);
735
736         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1\n", device_name));
737
738         if (d == DeviceInfo::device_info.end()) {
739                 return -1;
740         }
741
742         _device_info = d->second;
743
744         return 0;
745 }
746
747 int
748 MackieControlProtocol::set_device (const string& device_name, bool force)
749 {
750         if (device_name == device_info().name() && !force) {
751                 /* already using that device, nothing to do */
752                 return 0;
753         }
754         /* get state from the current setup, and make sure it is stored in
755            the configuration_states node so that if we switch back to this device,
756            we will have its state available.
757         */
758
759         {
760                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
761                 if (!surfaces.empty()) {
762                         update_configuration_state ();
763                 }
764         }
765
766         if (set_device_info (device_name)) {
767                 return -1;
768         }
769
770         clear_surfaces ();
771         port_connection.disconnect ();
772         hui_connection.disconnect ();
773
774         if (_device_info.device_type() == DeviceInfo::HUI) {
775                 Glib::RefPtr<Glib::TimeoutSource> hui_timeout = Glib::TimeoutSource::create (1000); // milliseconds
776                 hui_connection = hui_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::hui_heartbeat));
777                 hui_timeout->attach (main_loop()->get_context());
778         }
779
780         if (!_device_info.uses_ipmidi()) {
781                 /* notice that the handler for this will execute in our event
782                    loop, not in the thread where the
783                    PortConnectedOrDisconnected signal is emitted.
784                 */
785                 ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::connection_handler, this, _1, _2, _3, _4, _5), this);
786         }
787
788         if (create_surfaces ()) {
789                 return -1;
790         }
791
792         DeviceChanged ();
793
794         return 0;
795 }
796
797 gboolean
798 ArdourSurface::ipmidi_input_handler (GIOChannel*, GIOCondition condition, void *data)
799 {
800         ArdourSurface::MackieControlProtocol::ipMIDIHandler* ipm = static_cast<ArdourSurface::MackieControlProtocol::ipMIDIHandler*>(data);
801         return ipm->mcp->midi_input_handler (Glib::IOCondition (condition), ipm->port);
802 }
803
804 int
805 MackieControlProtocol::create_surfaces ()
806 {
807         string device_name;
808         surface_type_t stype = mcu; // type not yet determined
809
810         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Create %1 surfaces for %2\n", 1 + _device_info.extenders(), _device_info.name()));
811
812         if (!_device_info.uses_ipmidi()) {
813                 _input_bundle.reset (new ARDOUR::Bundle (_("Mackie Control In"), true));
814                 _output_bundle.reset (new ARDOUR::Bundle (_("Mackie Control Out"), false));
815         } else {
816                 _input_bundle.reset ();
817                 _output_bundle.reset ();
818
819         }
820         for (uint32_t n = 0; n < 1 + _device_info.extenders(); ++n) {
821                 bool is_master = false;
822
823                 if (n == _device_info.master_position()) {
824                         is_master = true;
825                         if (_device_info.extenders() == 0) {
826                                 device_name = _device_info.name();
827                         } else {
828                                 device_name = X_("mackie control");
829                         }
830
831                 }
832
833                 if (!is_master) {
834                         device_name = string_compose (X_("mackie control ext %1"), n+1);
835                 }
836
837                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Port Name for surface %1 is %2\n", n, device_name));
838
839                 boost::shared_ptr<Surface> surface;
840
841                 if (is_master) {
842                         stype = mcu;
843                 } else {
844                         stype = ext;
845                 }
846                 try {
847                         surface.reset (new Surface (*this, device_name, n, stype));
848                 } catch (...) {
849                         return -1;
850                 }
851
852                 if (is_master) {
853                         _master_surface = surface;
854                 }
855
856                 if (configuration_state) {
857                         XMLNode* this_device = 0;
858                         XMLNodeList const& devices = configuration_state->children();
859                         for (XMLNodeList::const_iterator d = devices.begin(); d != devices.end(); ++d) {
860                                 XMLProperty const * prop = (*d)->property (X_("name"));
861                                 if (prop && prop->value() == _device_info.name()) {
862                                         this_device = *d;
863                                         break;
864                                 }
865                         }
866                         if (this_device) {
867                                 XMLNode* snode = this_device->child (X_("Surfaces"));
868                                 if (snode) {
869                                         surface->set_state (*snode, state_version);
870                                 }
871                         }
872                 }
873
874                 {
875                         Glib::Threads::Mutex::Lock lm (surfaces_lock);
876                         surfaces.push_back (surface);
877                 }
878
879                 if (!_device_info.uses_ipmidi()) {
880
881                         _input_bundle->add_channel (
882                                 surface->port().input_port().name(),
883                                 ARDOUR::DataType::MIDI,
884                                 session->engine().make_port_name_non_relative (surface->port().input_port().name())
885                                 );
886
887                         _output_bundle->add_channel (
888                                 surface->port().output_port().name(),
889                                 ARDOUR::DataType::MIDI,
890                                 session->engine().make_port_name_non_relative (surface->port().output_port().name())
891                                 );
892                 }
893
894                 MIDI::Port& input_port (surface->port().input_port());
895                 AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*> (&input_port);
896
897                 if (asp) {
898
899                         /* async MIDI port */
900
901                         asp->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &MackieControlProtocol::midi_input_handler), &input_port));
902                         asp->xthread().attach (main_loop()->get_context());
903
904                 } else {
905
906                         /* ipMIDI port, no IOSource method at this time */
907
908                         int fd;
909
910                         if ((fd = input_port.selectable ()) >= 0) {
911
912                                 GIOChannel* ioc = g_io_channel_unix_new (fd);
913                                 surface->input_source = g_io_create_watch (ioc, GIOCondition (G_IO_IN|G_IO_HUP|G_IO_ERR));
914
915                                 /* make surface's input source now hold the
916                                  * only reference on the IO channel
917                                  */
918                                 g_io_channel_unref (ioc);
919
920                                 /* hack up an object so that in the callback from the event loop
921                                    we have both the MackieControlProtocol and the input port.
922
923                                    If we were using C++ for this stuff we wouldn't need this
924                                    but a nasty, not-fixable bug in the binding between C
925                                    and C++ makes it necessary to avoid C++ for the IO
926                                    callback setup.
927                                 */
928
929                                 ipMIDIHandler* ipm = new ipMIDIHandler (); /* we will leak this sizeof(pointer)*2 sized object */
930                                 ipm->mcp = this;
931                                 ipm->port = &input_port;
932
933                                 g_source_set_callback (surface->input_source, (GSourceFunc) ipmidi_input_handler, ipm, NULL);
934                                 g_source_attach (surface->input_source, main_loop()->get_context()->gobj());
935                         }
936                 }
937         }
938
939         if (!_device_info.uses_ipmidi()) {
940                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
941                 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
942                         (*s)->port().reconnect ();
943                 }
944         }
945
946         session->BundleAddedOrRemoved ();
947
948         assert (_master_surface);
949
950         return 0;
951 }
952
953 void
954 MackieControlProtocol::close()
955 {
956         port_connection.disconnect ();
957         session_connections.drop_connections ();
958         stripable_connections.drop_connections ();
959         periodic_connection.disconnect ();
960
961         clear_surfaces();
962 }
963
964 /** Ensure that the configuration_state XML node contains an up-to-date
965  *  copy of the state node the current device. If configuration_state already
966  *  contains a state node for the device, it will deleted and replaced.
967  */
968 void
969 MackieControlProtocol::update_configuration_state ()
970 {
971         /* CALLER MUST HOLD SURFACES LOCK */
972
973         if (!configuration_state) {
974                 configuration_state = new XMLNode (X_("Configurations"));
975         }
976
977         XMLNode* devnode = new XMLNode (X_("Configuration"));
978         devnode->add_property (X_("name"), _device_info.name());
979
980         configuration_state->remove_nodes_and_delete (X_("name"), _device_info.name());
981         configuration_state->add_child_nocopy (*devnode);
982
983         XMLNode* snode = new XMLNode (X_("Surfaces"));
984
985         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
986                 snode->add_child_nocopy ((*s)->get_state());
987         }
988
989         devnode->add_child_nocopy (*snode);
990 }
991
992 XMLNode&
993 MackieControlProtocol::get_state()
994 {
995         XMLNode& node (ControlProtocol::get_state());
996
997         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n");
998         char buf[16];
999
1000         // add current bank
1001         snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
1002         node.add_property (X_("bank"), buf);
1003
1004         // ipMIDI base port (possibly not used)
1005         snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
1006         node.add_property (X_("ipmidi-base"), buf);
1007
1008         node.add_property (X_("device-profile"), _device_profile.name());
1009         node.add_property (X_("device-name"), _device_info.name());
1010
1011         {
1012                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1013                 update_configuration_state ();
1014         }
1015
1016         /* force a copy of the _surfaces_state node, because we want to retain ownership */
1017         node.add_child_copy (*configuration_state);
1018
1019         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n");
1020
1021         return node;
1022 }
1023
1024 bool
1025 MackieControlProtocol::profile_exists (string const & name) const
1026 {
1027         return DeviceProfile::device_profiles.find (name) != DeviceProfile::device_profiles.end();
1028 }
1029
1030 int
1031 MackieControlProtocol::set_state (const XMLNode & node, int version)
1032 {
1033         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", active()));
1034
1035         int retval = 0;
1036         const XMLProperty* prop;
1037         uint32_t bank = 0;
1038
1039         if (ControlProtocol::set_state (node, version)) {
1040                 return -1;
1041         }
1042
1043         if ((prop = node.property (X_("ipmidi-base"))) != 0) {
1044                 set_ipmidi_base (atoi (prop->value()));
1045         }
1046
1047         // fetch current bank
1048         if ((prop = node.property (X_("bank"))) != 0) {
1049                 bank = atoi (prop->value());
1050         }
1051
1052         if ((prop = node.property (X_("device-name"))) != 0) {
1053                 set_device_info (prop->value());
1054         }
1055
1056         if ((prop = node.property (X_("device-profile"))) != 0) {
1057                 if (prop->value().empty()) {
1058                         string default_profile_name;
1059
1060                         /* start by looking for a user-edited profile for the current device name */
1061
1062                         default_profile_name = DeviceProfile::name_when_edited (_device_info.name());
1063
1064                         if (!profile_exists (default_profile_name)) {
1065
1066                                 /* no user-edited profile for this device name, so try the user-edited default profile */
1067
1068                                 default_profile_name = DeviceProfile::name_when_edited (DeviceProfile::default_profile_name);
1069
1070                                 if (!profile_exists (default_profile_name)) {
1071
1072                                         /* no user-edited version, so just try the device name */
1073
1074                                         default_profile_name = _device_info.name();
1075
1076                                         if (!profile_exists (default_profile_name)) {
1077
1078                                                 /* no generic device specific profile, just try the fixed default */
1079                                                 default_profile_name = DeviceProfile::default_profile_name;
1080                                         }
1081                                 }
1082                         }
1083
1084                         set_profile (default_profile_name);
1085
1086                 } else {
1087                         if (profile_exists (prop->value())) {
1088                                 set_profile (prop->value());
1089                         } else {
1090                                 set_profile (DeviceProfile::default_profile_name);
1091                         }
1092                 }
1093         }
1094
1095         XMLNode* dnode = node.child (X_("Configurations"));
1096
1097         delete configuration_state;
1098         configuration_state = 0;
1099
1100         if (dnode) {
1101                 configuration_state = new XMLNode (*dnode);
1102                 state_version = version;
1103         }
1104
1105         (void) switch_banks (bank, true);
1106
1107         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n");
1108
1109         return retval;
1110 }
1111
1112 string
1113 MackieControlProtocol::format_bbt_timecode (framepos_t now_frame)
1114 {
1115         Timecode::BBT_Time bbt_time;
1116
1117         session->bbt_time (now_frame, bbt_time);
1118
1119         // The Mackie protocol spec is built around a BBT time display of
1120         //
1121         // digits:     888/88/88/888
1122         // semantics:  BBB/bb/ss/ttt
1123         //
1124         // The third field is "subdivisions" which is a concept found in Logic
1125         // but not present in Ardour. Instead Ardour displays a 4 digit tick
1126         // count, which we need to spread across the 5 digits of ss/ttt.
1127
1128         ostringstream os;
1129
1130         os << setw(3) << setfill('0') << bbt_time.bars;
1131         os << setw(2) << setfill('0') << bbt_time.beats;
1132         os << ' ';
1133         os << setw(1) << setfill('0') << bbt_time.ticks / 1000;
1134         os << setw(3) << setfill('0') << bbt_time.ticks % 1000;
1135
1136         return os.str();
1137 }
1138
1139 string
1140 MackieControlProtocol::format_timecode_timecode (framepos_t now_frame)
1141 {
1142         Timecode::Time timecode;
1143         session->timecode_time (now_frame, timecode);
1144
1145         // According to the Logic docs
1146         // digits: 888/88/88/888
1147         // Timecode mode: Hours/Minutes/Seconds/Frames
1148         ostringstream os;
1149         os << setw(2) << setfill('0') << timecode.hours;
1150         os << ' ';
1151         os << setw(2) << setfill('0') << timecode.minutes;
1152         os << setw(2) << setfill('0') << timecode.seconds;
1153         os << ' ';
1154         os << setw(2) << setfill('0') << timecode.frames;
1155
1156         return os.str();
1157 }
1158
1159 void
1160 MackieControlProtocol::update_timecode_display()
1161 {
1162         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1163
1164         if (surfaces.empty()) {
1165                 return;
1166         }
1167
1168         boost::shared_ptr<Surface> surface = _master_surface;
1169
1170         if (surface->type() != mcu || !_device_info.has_timecode_display() || !surface->active ()) {
1171                 return;
1172         }
1173
1174         // do assignment here so current_frame is fixed
1175         framepos_t current_frame = session->transport_frame();
1176         string timecode;
1177         // For large jumps in play head possition do full reset
1178         int moved = (current_frame - _frame_last) / session->frame_rate ();
1179         if (moved) {
1180                 DEBUG_TRACE (DEBUG::MackieControl, "Timecode reset\n");
1181                 _timecode_last = string (10, ' ');
1182         }
1183         _frame_last = current_frame;
1184
1185         switch (_timecode_type) {
1186         case ARDOUR::AnyTime::BBT:
1187                 timecode = format_bbt_timecode (current_frame);
1188                 break;
1189         case ARDOUR::AnyTime::Timecode:
1190                 timecode = format_timecode_timecode (current_frame);
1191                 break;
1192         default:
1193                 return;
1194         }
1195
1196         // only write the timecode string to the MCU if it's changed
1197         // since last time. This is to reduce midi bandwidth used.
1198         if (timecode != _timecode_last) {
1199                 surface->display_timecode (timecode, _timecode_last);
1200                 _timecode_last = timecode;
1201         }
1202 }
1203
1204 ///////////////////////////////////////////
1205 // Session signals
1206 ///////////////////////////////////////////
1207
1208 void MackieControlProtocol::notify_parameter_changed (std::string const & p)
1209 {
1210         if (p == "punch-in") {
1211                 update_global_button (Button::Drop, session->config.get_punch_in() ? flashing : off);
1212         } else if (p == "punch-out") {
1213                 update_global_button (Button::Replace, session->config.get_punch_out() ? flashing : off);
1214         } else if (p == "clicking") {
1215                 update_global_button (Button::Click, Config->get_clicking());
1216         } else if (p == "follow-edits") {
1217                 /* we can't respond to this at present, because "follow-edits"
1218                  * is  a property of the (G)UI configuration object, to which we
1219                  * have no access. For now, this means that the lit state of
1220                  * this button (if there is one) won't reflect the setting.
1221                  */
1222
1223                 //update_global_button (Button::Enter, session->config.get_follow_edits() ? on : off);
1224         } else if (p == "external-sync") {
1225                 update_global_button (Button::Cancel, session->config.get_external_sync() ? on : off);
1226         } else {
1227                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
1228         }
1229 }
1230
1231 void
1232 MackieControlProtocol::notify_stripable_removed ()
1233 {
1234         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1235         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1236                 (*s)->master_monitor_may_have_changed ();
1237         }
1238 }
1239
1240 void
1241 MackieControlProtocol::notify_vca_added (ARDOUR::VCAList& vl)
1242 {
1243         refresh_current_bank ();
1244 }
1245
1246 // RouteList is the set of Routes that have just been added
1247 void
1248 MackieControlProtocol::notify_routes_added (ARDOUR::RouteList & rl)
1249 {
1250         {
1251                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1252
1253                 if (surfaces.empty()) {
1254                         return;
1255                 }
1256         }
1257
1258         /* special case: single route, and it is the monitor or master out */
1259
1260         if (rl.size() == 1 && (rl.front()->is_monitor() || rl.front()->is_master())) {
1261                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1262                 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1263                         (*s)->master_monitor_may_have_changed ();
1264                 }
1265         }
1266
1267         // currently assigned banks are less than the full set of
1268         // strips, so activate the new strip now.
1269
1270         refresh_current_bank();
1271
1272         // otherwise route added, but current bank needs no updating
1273 }
1274
1275 void
1276 MackieControlProtocol::notify_solo_active_changed (bool active)
1277 {
1278         boost::shared_ptr<Surface> surface;
1279
1280         {
1281                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1282
1283                 if (surfaces.empty()) {
1284                         return;
1285                 }
1286
1287                 surface = _master_surface;
1288         }
1289
1290         map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Led::RudeSolo);
1291         if (x != surface->controls_by_device_independent_id.end()) {
1292                 Led* rude_solo = dynamic_cast<Led*> (x->second);
1293                 if (rude_solo) {
1294                         surface->write (rude_solo->set_state (active ? flashing : off));
1295                 }
1296         }
1297 }
1298
1299 void
1300 MackieControlProtocol::notify_presentation_info_changed ()
1301 {
1302         {
1303                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1304
1305                 if (surfaces.empty()) {
1306                         return;
1307                 }
1308         }
1309
1310         Sorted sorted = get_sorted_stripables();
1311         uint32_t sz = n_strips();
1312
1313         // if a remote id has been moved off the end, we need to shift
1314         // the current bank backwards.
1315
1316         if (sorted.size() - _current_initial_bank < sz) {
1317                 // but don't shift backwards past the zeroth channel
1318                 if (sorted.size() < sz) {  // avoid unsigned math mistake below
1319                         (void) switch_banks(0, true);
1320                 } else {
1321                         (void) switch_banks (max((Sorted::size_type) 0, sorted.size() - sz), true);
1322                 }
1323         } else {
1324                 // Otherwise just refresh the current bank
1325                 refresh_current_bank();
1326         }
1327 }
1328
1329 ///////////////////////////////////////////
1330 // Transport signals
1331 ///////////////////////////////////////////
1332
1333 void
1334 MackieControlProtocol::notify_loop_state_changed()
1335 {
1336         update_global_button (Button::Loop, session->get_play_loop());
1337 }
1338
1339 void
1340 MackieControlProtocol::notify_transport_state_changed()
1341 {
1342         if (!_device_info.has_global_controls()) {
1343                 return;
1344         }
1345
1346         // switch various play and stop buttons on / off
1347         update_global_button (Button::Loop, session->get_play_loop());
1348         update_global_button (Button::Play, session->transport_speed() == 1.0);
1349         update_global_button (Button::Stop, session->transport_stopped ());
1350         update_global_button (Button::Rewind, session->transport_speed() < 0.0);
1351         update_global_button (Button::Ffwd, session->transport_speed() > 1.0);
1352
1353         // sometimes a return to start leaves time code at old time
1354         _timecode_last = string (10, ' ');
1355
1356         notify_metering_state_changed ();
1357 }
1358
1359 void
1360 MackieControlProtocol::notify_metering_state_changed()
1361 {
1362         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1363
1364         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1365                 (*s)->notify_metering_state_changed ();
1366         }
1367 }
1368
1369 void
1370 MackieControlProtocol::notify_record_state_changed ()
1371 {
1372         if (!_device_info.has_global_controls()) {
1373                 return;
1374         }
1375
1376         boost::shared_ptr<Surface> surface;
1377
1378         {
1379                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1380                 if (surfaces.empty()) {
1381                         return;
1382                 }
1383                 surface = _master_surface;
1384         }
1385
1386         /* rec is a tristate */
1387
1388         map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Button::Record);
1389         if (x != surface->controls_by_device_independent_id.end()) {
1390                 Button * rec = dynamic_cast<Button*> (x->second);
1391                 if (rec) {
1392                         LedState ls;
1393
1394                         switch (session->record_status()) {
1395                         case Session::Disabled:
1396                                 DEBUG_TRACE (DEBUG::MackieControl, "record state changed to disabled, LED off\n");
1397                                 ls = off;
1398                                 break;
1399                         case Session::Recording:
1400                                 DEBUG_TRACE (DEBUG::MackieControl, "record state changed to recording, LED on\n");
1401                                 ls = on;
1402                                 break;
1403                         case Session::Enabled:
1404                                 DEBUG_TRACE (DEBUG::MackieControl, "record state changed to enabled, LED flashing\n");
1405                                 ls = flashing;
1406                                 break;
1407                         }
1408
1409                         surface->write (rec->set_state (ls));
1410                 }
1411         }
1412 }
1413
1414 list<boost::shared_ptr<ARDOUR::Bundle> >
1415 MackieControlProtocol::bundles ()
1416 {
1417         list<boost::shared_ptr<ARDOUR::Bundle> > b;
1418
1419         if (_input_bundle) {
1420                 b.push_back (_input_bundle);
1421                 b.push_back (_output_bundle);
1422         }
1423
1424         return b;
1425 }
1426
1427 void
1428 MackieControlProtocol::do_request (MackieControlUIRequest* req)
1429 {
1430         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("doing request type %1\n", req->type));
1431         if (req->type == CallSlot) {
1432
1433                 call_slot (MISSING_INVALIDATOR, req->the_slot);
1434
1435         } else if (req->type == Quit) {
1436
1437                 stop ();
1438         }
1439 }
1440
1441 int
1442 MackieControlProtocol::stop ()
1443 {
1444         BaseUI::quit ();
1445
1446         return 0;
1447 }
1448
1449 void
1450 MackieControlProtocol::update_led (Surface& surface, Button& button, Mackie::LedState ls)
1451 {
1452         if (ls != none) {
1453                 surface.port().write (button.set_state (ls));
1454         }
1455 }
1456
1457 void
1458 MackieControlProtocol::build_button_map ()
1459 {
1460         /* this maps our device-independent button codes to the methods that handle them.
1461          */
1462
1463 #define DEFINE_BUTTON_HANDLER(b,p,r) button_map.insert (pair<Button::ID,ButtonHandlers> ((b), ButtonHandlers ((p),(r))));
1464
1465         DEFINE_BUTTON_HANDLER (Button::Track, &MackieControlProtocol::track_press, &MackieControlProtocol::track_release);
1466         DEFINE_BUTTON_HANDLER (Button::Send, &MackieControlProtocol::send_press, &MackieControlProtocol::send_release);
1467         DEFINE_BUTTON_HANDLER (Button::Pan, &MackieControlProtocol::pan_press, &MackieControlProtocol::pan_release);
1468         DEFINE_BUTTON_HANDLER (Button::Plugin, &MackieControlProtocol::plugin_press, &MackieControlProtocol::plugin_release);
1469         DEFINE_BUTTON_HANDLER (Button::Eq, &MackieControlProtocol::eq_press, &MackieControlProtocol::eq_release);
1470         DEFINE_BUTTON_HANDLER (Button::Dyn, &MackieControlProtocol::dyn_press, &MackieControlProtocol::dyn_release);
1471         DEFINE_BUTTON_HANDLER (Button::Left, &MackieControlProtocol::left_press, &MackieControlProtocol::left_release);
1472         DEFINE_BUTTON_HANDLER (Button::Right, &MackieControlProtocol::right_press, &MackieControlProtocol::right_release);
1473         DEFINE_BUTTON_HANDLER (Button::ChannelLeft, &MackieControlProtocol::channel_left_press, &MackieControlProtocol::channel_left_release);
1474         DEFINE_BUTTON_HANDLER (Button::ChannelRight, &MackieControlProtocol::channel_right_press, &MackieControlProtocol::channel_right_release);
1475         DEFINE_BUTTON_HANDLER (Button::Flip, &MackieControlProtocol::flip_press, &MackieControlProtocol::flip_release);
1476         DEFINE_BUTTON_HANDLER (Button::View, &MackieControlProtocol::view_press, &MackieControlProtocol::view_release);
1477         DEFINE_BUTTON_HANDLER (Button::NameValue, &MackieControlProtocol::name_value_press, &MackieControlProtocol::name_value_release);
1478         DEFINE_BUTTON_HANDLER (Button::TimecodeBeats, &MackieControlProtocol::timecode_beats_press, &MackieControlProtocol::timecode_beats_release);
1479         DEFINE_BUTTON_HANDLER (Button::F1, &MackieControlProtocol::F1_press, &MackieControlProtocol::F1_release);
1480         DEFINE_BUTTON_HANDLER (Button::F2, &MackieControlProtocol::F2_press, &MackieControlProtocol::F2_release);
1481         DEFINE_BUTTON_HANDLER (Button::F3, &MackieControlProtocol::F3_press, &MackieControlProtocol::F3_release);
1482         DEFINE_BUTTON_HANDLER (Button::F4, &MackieControlProtocol::F4_press, &MackieControlProtocol::F4_release);
1483         DEFINE_BUTTON_HANDLER (Button::F5, &MackieControlProtocol::F5_press, &MackieControlProtocol::F5_release);
1484         DEFINE_BUTTON_HANDLER (Button::F6, &MackieControlProtocol::F6_press, &MackieControlProtocol::F6_release);
1485         DEFINE_BUTTON_HANDLER (Button::F7, &MackieControlProtocol::F7_press, &MackieControlProtocol::F7_release);
1486         DEFINE_BUTTON_HANDLER (Button::F8, &MackieControlProtocol::F8_press, &MackieControlProtocol::F8_release);
1487         DEFINE_BUTTON_HANDLER (Button::MidiTracks, &MackieControlProtocol::miditracks_press, &MackieControlProtocol::miditracks_release);
1488         DEFINE_BUTTON_HANDLER (Button::Inputs, &MackieControlProtocol::inputs_press, &MackieControlProtocol::inputs_release);
1489         DEFINE_BUTTON_HANDLER (Button::AudioTracks, &MackieControlProtocol::audiotracks_press, &MackieControlProtocol::audiotracks_release);
1490         DEFINE_BUTTON_HANDLER (Button::AudioInstruments, &MackieControlProtocol::audioinstruments_press, &MackieControlProtocol::audioinstruments_release);
1491         DEFINE_BUTTON_HANDLER (Button::Aux, &MackieControlProtocol::aux_press, &MackieControlProtocol::aux_release);
1492         DEFINE_BUTTON_HANDLER (Button::Busses, &MackieControlProtocol::busses_press, &MackieControlProtocol::busses_release);
1493         DEFINE_BUTTON_HANDLER (Button::Outputs, &MackieControlProtocol::outputs_press, &MackieControlProtocol::outputs_release);
1494         DEFINE_BUTTON_HANDLER (Button::User, &MackieControlProtocol::user_press, &MackieControlProtocol::user_release);
1495         DEFINE_BUTTON_HANDLER (Button::Shift, &MackieControlProtocol::shift_press, &MackieControlProtocol::shift_release);
1496         DEFINE_BUTTON_HANDLER (Button::Option, &MackieControlProtocol::option_press, &MackieControlProtocol::option_release);
1497         DEFINE_BUTTON_HANDLER (Button::Ctrl, &MackieControlProtocol::control_press, &MackieControlProtocol::control_release);
1498         DEFINE_BUTTON_HANDLER (Button::CmdAlt, &MackieControlProtocol::cmd_alt_press, &MackieControlProtocol::cmd_alt_release);
1499         DEFINE_BUTTON_HANDLER (Button::Read, &MackieControlProtocol::read_press, &MackieControlProtocol::read_release);
1500         DEFINE_BUTTON_HANDLER (Button::Write, &MackieControlProtocol::write_press, &MackieControlProtocol::write_release);
1501         DEFINE_BUTTON_HANDLER (Button::Trim, &MackieControlProtocol::trim_press, &MackieControlProtocol::trim_release);
1502         DEFINE_BUTTON_HANDLER (Button::Touch, &MackieControlProtocol::touch_press, &MackieControlProtocol::touch_release);
1503         DEFINE_BUTTON_HANDLER (Button::Latch, &MackieControlProtocol::latch_press, &MackieControlProtocol::latch_release);
1504         DEFINE_BUTTON_HANDLER (Button::Grp, &MackieControlProtocol::grp_press, &MackieControlProtocol::grp_release);
1505         DEFINE_BUTTON_HANDLER (Button::Save, &MackieControlProtocol::save_press, &MackieControlProtocol::save_release);
1506         DEFINE_BUTTON_HANDLER (Button::Undo, &MackieControlProtocol::undo_press, &MackieControlProtocol::undo_release);
1507         DEFINE_BUTTON_HANDLER (Button::Cancel, &MackieControlProtocol::cancel_press, &MackieControlProtocol::cancel_release);
1508         DEFINE_BUTTON_HANDLER (Button::Enter, &MackieControlProtocol::enter_press, &MackieControlProtocol::enter_release);
1509         DEFINE_BUTTON_HANDLER (Button::Marker, &MackieControlProtocol::marker_press, &MackieControlProtocol::marker_release);
1510         DEFINE_BUTTON_HANDLER (Button::Nudge, &MackieControlProtocol::nudge_press, &MackieControlProtocol::nudge_release);
1511         DEFINE_BUTTON_HANDLER (Button::Loop, &MackieControlProtocol::loop_press, &MackieControlProtocol::loop_release);
1512         DEFINE_BUTTON_HANDLER (Button::Drop, &MackieControlProtocol::drop_press, &MackieControlProtocol::drop_release);
1513         DEFINE_BUTTON_HANDLER (Button::Replace, &MackieControlProtocol::replace_press, &MackieControlProtocol::replace_release);
1514         DEFINE_BUTTON_HANDLER (Button::Click, &MackieControlProtocol::click_press, &MackieControlProtocol::click_release);
1515         DEFINE_BUTTON_HANDLER (Button::ClearSolo, &MackieControlProtocol::clearsolo_press, &MackieControlProtocol::clearsolo_release);
1516         DEFINE_BUTTON_HANDLER (Button::Rewind, &MackieControlProtocol::rewind_press, &MackieControlProtocol::rewind_release);
1517         DEFINE_BUTTON_HANDLER (Button::Ffwd, &MackieControlProtocol::ffwd_press, &MackieControlProtocol::ffwd_release);
1518         DEFINE_BUTTON_HANDLER (Button::Stop, &MackieControlProtocol::stop_press, &MackieControlProtocol::stop_release);
1519         DEFINE_BUTTON_HANDLER (Button::Play, &MackieControlProtocol::play_press, &MackieControlProtocol::play_release);
1520         DEFINE_BUTTON_HANDLER (Button::Record, &MackieControlProtocol::record_press, &MackieControlProtocol::record_release);
1521         DEFINE_BUTTON_HANDLER (Button::CursorUp, &MackieControlProtocol::cursor_up_press, &MackieControlProtocol::cursor_up_release);
1522         DEFINE_BUTTON_HANDLER (Button::CursorDown, &MackieControlProtocol::cursor_down_press, &MackieControlProtocol::cursor_down_release);
1523         DEFINE_BUTTON_HANDLER (Button::CursorLeft, &MackieControlProtocol::cursor_left_press, &MackieControlProtocol::cursor_left_release);
1524         DEFINE_BUTTON_HANDLER (Button::CursorRight, &MackieControlProtocol::cursor_right_press, &MackieControlProtocol::cursor_right_release);
1525         DEFINE_BUTTON_HANDLER (Button::Zoom, &MackieControlProtocol::zoom_press, &MackieControlProtocol::zoom_release);
1526         DEFINE_BUTTON_HANDLER (Button::Scrub, &MackieControlProtocol::scrub_press, &MackieControlProtocol::scrub_release);
1527         DEFINE_BUTTON_HANDLER (Button::UserA, &MackieControlProtocol::user_a_press, &MackieControlProtocol::user_a_release);
1528         DEFINE_BUTTON_HANDLER (Button::UserB, &MackieControlProtocol::user_b_press, &MackieControlProtocol::user_b_release);
1529         DEFINE_BUTTON_HANDLER (Button::MasterFaderTouch, &MackieControlProtocol::master_fader_touch_press, &MackieControlProtocol::master_fader_touch_release);
1530 }
1531
1532 void
1533 MackieControlProtocol::handle_button_event (Surface& surface, Button& button, ButtonState bs)
1534 {
1535         Button::ID button_id = button.bid();
1536
1537         if  (bs != press && bs != release) {
1538                 update_led (surface, button, none);
1539                 return;
1540         }
1541
1542         if ((button_id != Button::Marker) && (modifier_state() & MODIFIER_MARKER)) {
1543                 marker_modifier_consumed_by_button = true;
1544         }
1545
1546         if ((button_id != Button::Nudge) && (modifier_state() & MODIFIER_NUDGE)) {
1547                 nudge_modifier_consumed_by_button = true;
1548         }
1549
1550         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2 (%3)\n", (bs == press ? "press" : "release"), button.id(),
1551                                                            Button::id_to_name (button.bid())));
1552
1553         /* check profile first */
1554
1555         string action = _device_profile.get_button_action (button.bid(), _modifier_state);
1556
1557         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("device profile returned [%1] for that button\n", action));
1558
1559         if (!action.empty()) {
1560
1561                 if (action.find ('/') != string::npos) { /* good chance that this is really an action */
1562
1563                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Looked up action for button %1 with modifier %2, got [%3]\n",
1564                                                                            button.bid(), _modifier_state, action));
1565
1566                         /* if there is a bound action for this button, and this is a press event,
1567                            carry out the action. If its a release event, do nothing since we
1568                            don't bind to them at all but don't want any other handling to
1569                            occur either.
1570                         */
1571                         if (bs == press) {
1572                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("executing action %1\n", action));
1573                                 access_action (action);
1574                         }
1575
1576                         return;
1577
1578                 } else {
1579
1580                         /* "action" is more likely to be a button name. We use this to
1581                          * allow remapping buttons to different (builtin) functionality
1582                          * associated with an existing button. This is similar to the
1583                          * way that (for example) Nuendo moves the "Shift" function to
1584                          * the "Enter" key of the MCU Pro.
1585                          */
1586
1587                         int bid = Button::name_to_id (action);
1588
1589                         if (bid < 0) {
1590                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("apparent button name %1 not found\n", action));
1591                                 return;
1592                         }
1593
1594                         button_id = (Button::ID) bid;
1595                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handling button %1 as if it was %2 (%3)\n", Button::id_to_name (button.bid()), button_id, Button::id_to_name (button_id)));
1596                 }
1597         }
1598
1599         /* lookup using the device-INDEPENDENT button ID */
1600
1601         ButtonMap::iterator b = button_map.find (button_id);
1602
1603         if (b != button_map.end()) {
1604
1605                 ButtonHandlers& bh (b->second);
1606
1607                 switch  (bs) {
1608                 case press:
1609                         surface.write (button.set_state ((this->*(bh.press)) (button)));
1610                         break;
1611                 case release:
1612                         surface.write (button.set_state ((this->*(bh.release)) (button)));
1613                         break;
1614                 default:
1615                         break;
1616                 }
1617         } else {
1618                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("no button handlers for button ID %1 (device ID %2)\n",
1619                                                                    button.bid(), button.id()));
1620                 error << string_compose ("no button handlers for button ID %1 (device ID %2)\n",
1621                                          button.bid(), button.id()) << endmsg;
1622         }
1623 }
1624
1625 bool
1626 MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
1627 {
1628         if (ioc & ~IO_IN) {
1629                 DEBUG_TRACE (DEBUG::MackieControl, "MIDI port closed\n");
1630                 return false;
1631         }
1632
1633         if (ioc & IO_IN) {
1634
1635                 // DEBUG_TRACE (DEBUG::MackieControl, string_compose ("something happend on  %1\n", port->name()));
1636
1637                 /* Devices using regular JACK MIDI ports will need to have
1638                    the x-thread FIFO drained to avoid burning endless CPU.
1639
1640                    Devices using ipMIDI have port->selectable() as the same
1641                    file descriptor that data arrives on, so doing this
1642                    for them will simply throw all incoming data away.
1643                 */
1644
1645                 if (!_device_info.uses_ipmidi()) {
1646                         AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*>(port);
1647                         if (asp) {
1648                                 asp->clear ();
1649                         }
1650                 }
1651
1652                 // DEBUG_TRACE (DEBUG::MackieControl, string_compose ("data available on %1\n", port->name()));
1653                 framepos_t now = session->engine().sample_time();
1654                 port->parse (now);
1655         }
1656
1657         return true;
1658 }
1659
1660 void
1661 MackieControlProtocol::clear_ports ()
1662 {
1663         if (_input_bundle) {
1664                 _input_bundle->remove_channels ();
1665                 _output_bundle->remove_channels ();
1666         }
1667 }
1668
1669 void
1670 MackieControlProtocol::notify_subview_stripable_deleted ()
1671 {
1672         /* return to global/mixer view */
1673         _subview_stripable.reset ();
1674         set_view_mode (Mixer);
1675 }
1676
1677 bool
1678 MackieControlProtocol::subview_mode_would_be_ok (SubViewMode mode, boost::shared_ptr<Stripable> r)
1679 {
1680         switch (mode) {
1681         case None:
1682                 return true;
1683                 break;
1684
1685         case Sends:
1686                 if (r && r->send_level_controllable (0)) {
1687                         return true;
1688                 }
1689                 break;
1690
1691         case EQ:
1692                 if (r && r->eq_band_cnt() > 0) {
1693                         return true;
1694                 }
1695                 break;
1696
1697         case Dynamics:
1698                 if (r && r->comp_enable_controllable()) {
1699                         return true;
1700                 }
1701                 break;
1702
1703         case TrackView:
1704                 if (r) {
1705                         return true;
1706                 }
1707         }
1708
1709         return false;
1710 }
1711
1712 bool
1713 MackieControlProtocol::redisplay_subview_mode ()
1714 {
1715         Surfaces copy; /* can't hold surfaces lock while calling Strip::subview_mode_changed */
1716
1717         {
1718                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1719                 copy = surfaces;
1720         }
1721
1722         for (Surfaces::iterator s = copy.begin(); s != copy.end(); ++s) {
1723                 (*s)->subview_mode_changed ();
1724         }
1725
1726         /* don't call this again from a timeout */
1727         return false;
1728 }
1729
1730 int
1731 MackieControlProtocol::set_subview_mode (SubViewMode sm, boost::shared_ptr<Stripable> r)
1732 {
1733         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set subview mode %1 with stripable %2, current flip mode %3\n", sm, (r ? r->name() : string ("null")), _flip_mode));
1734
1735         if (_flip_mode != Normal) {
1736                 set_flip_mode (Normal);
1737         }
1738
1739         if (!subview_mode_would_be_ok (sm, r)) {
1740
1741                 DEBUG_TRACE (DEBUG::MackieControl, "subview mode not OK\n");
1742
1743                 if (r) {
1744
1745                         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1746
1747                         if (!surfaces.empty()) {
1748
1749                                 string msg;
1750
1751                                 switch (sm) {
1752                                 case Sends:
1753                                         msg = _("no sends for selected track/bus");
1754                                         break;
1755                                 case EQ:
1756                                         msg = _("no EQ in the track/bus");
1757                                         break;
1758                                 case Dynamics:
1759                                         msg = _("no dynamics in selected track/bus");
1760                                         break;
1761                                 case TrackView:
1762                                         msg = _("no track view possible");
1763                                 default:
1764                                         break;
1765                                 }
1766                                 if (!msg.empty()) {
1767                                         surfaces.front()->display_message_for (msg, 1000);
1768                                         if (_subview_mode != None) {
1769                                                 /* redisplay current subview mode after
1770                                                    that message goes away.
1771                                                 */
1772                                                 Glib::RefPtr<Glib::TimeoutSource> redisplay_timeout = Glib::TimeoutSource::create (1000); // milliseconds
1773                                                 redisplay_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::redisplay_subview_mode));
1774                                                 redisplay_timeout->attach (main_loop()->get_context());
1775                                         }
1776                                 }
1777                         }
1778                 }
1779
1780                 return -1;
1781         }
1782
1783         boost::shared_ptr<Stripable> old_stripable = _subview_stripable;
1784
1785         _subview_mode = sm;
1786         _subview_stripable = r;
1787
1788         if (_subview_stripable != old_stripable) {
1789                 subview_stripable_connections.drop_connections ();
1790
1791                 /* Catch the current subview stripable going away */
1792                 if (_subview_stripable) {
1793                         _subview_stripable->DropReferences.connect (subview_stripable_connections, MISSING_INVALIDATOR,
1794                                                                     boost::bind (&MackieControlProtocol::notify_subview_stripable_deleted, this),
1795                                                                     this);
1796                 }
1797         }
1798
1799         redisplay_subview_mode ();
1800
1801         /* turn buttons related to vpot mode on or off as required */
1802
1803         switch (_subview_mode) {
1804         case MackieControlProtocol::None:
1805                 update_global_button (Button::Send, off);
1806                 update_global_button (Button::Plugin, off);
1807                 update_global_button (Button::Eq, off);
1808                 update_global_button (Button::Dyn, off);
1809                 update_global_button (Button::Track, off);
1810                 update_global_button (Button::Pan, on);
1811                 break;
1812         case MackieControlProtocol::EQ:
1813                 update_global_button (Button::Send, off);
1814                 update_global_button (Button::Plugin, off);
1815                 update_global_button (Button::Eq, on);
1816                 update_global_button (Button::Dyn, off);
1817                 update_global_button (Button::Track, off);
1818                 update_global_button (Button::Pan, off);
1819                 break;
1820         case MackieControlProtocol::Dynamics:
1821                 update_global_button (Button::Send, off);
1822                 update_global_button (Button::Plugin, off);
1823                 update_global_button (Button::Eq, off);
1824                 update_global_button (Button::Dyn, on);
1825                 update_global_button (Button::Track, off);
1826                 update_global_button (Button::Pan, off);
1827                 break;
1828         case MackieControlProtocol::Sends:
1829                 update_global_button (Button::Send, on);
1830                 update_global_button (Button::Plugin, off);
1831                 update_global_button (Button::Eq, off);
1832                 update_global_button (Button::Dyn, off);
1833                 update_global_button (Button::Track, off);
1834                 update_global_button (Button::Pan, off);
1835                 break;
1836         case MackieControlProtocol::TrackView:
1837                 update_global_button (Button::Send, off);
1838                 update_global_button (Button::Plugin, off);
1839                 update_global_button (Button::Eq, off);
1840                 update_global_button (Button::Dyn, off);
1841                 update_global_button (Button::Track, on);
1842                 update_global_button (Button::Pan, off);
1843                 break;
1844         }
1845
1846         return 0;
1847 }
1848
1849 void
1850 MackieControlProtocol::set_view_mode (ViewMode m)
1851 {
1852         if (_flip_mode != Normal) {
1853                 set_flip_mode (Normal);
1854         }
1855         ViewMode old_view_mode = _view_mode;
1856
1857         _view_mode = m;
1858         _last_bank[old_view_mode] = _current_initial_bank;
1859
1860         if (switch_banks(_last_bank[m], true)) {
1861                 _view_mode = old_view_mode;
1862                 return;
1863         }
1864
1865         /* leave subview mode, whatever it was */
1866         set_subview_mode (None, boost::shared_ptr<Stripable>());
1867         display_view_mode ();
1868 }
1869
1870 void
1871 MackieControlProtocol::display_view_mode ()
1872 {
1873         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1874
1875         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1876                 (*s)->update_view_mode_display (true);
1877         }
1878 }
1879
1880 void
1881 MackieControlProtocol::set_flip_mode (FlipMode fm)
1882 {
1883         if (fm == Normal) {
1884                 update_global_button (Button::Flip, off);
1885         } else {
1886                 update_global_button (Button::Flip, on);
1887         }
1888
1889         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1890
1891         _flip_mode = fm;
1892
1893         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1894                 (*s)->update_flip_mode_display ();
1895         }
1896 }
1897
1898 void
1899 MackieControlProtocol::set_master_on_surface_strip (uint32_t surface, uint32_t strip_number)
1900 {
1901         force_special_stripable_to_strip (session->master_out(), surface, strip_number);
1902 }
1903
1904 void
1905 MackieControlProtocol::set_monitor_on_surface_strip (uint32_t surface, uint32_t strip_number)
1906 {
1907         force_special_stripable_to_strip (session->monitor_out(), surface, strip_number);
1908 }
1909
1910 void
1911 MackieControlProtocol::force_special_stripable_to_strip (boost::shared_ptr<Stripable> r, uint32_t surface, uint32_t strip_number)
1912 {
1913         if (!r) {
1914                 return;
1915         }
1916
1917         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1918
1919         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1920                 if ((*s)->number() == surface) {
1921                         Strip* strip = (*s)->nth_strip (strip_number);
1922                         if (strip) {
1923                                 strip->set_stripable (session->master_out());
1924                                 strip->lock_controls ();
1925                         }
1926                 }
1927         }
1928 }
1929
1930 void
1931 MackieControlProtocol::check_fader_automation_state ()
1932 {
1933         fader_automation_connections.drop_connections ();
1934
1935         boost::shared_ptr<Stripable> r = first_selected_stripable ();
1936
1937         if (!r) {
1938                 update_global_button (Button::Read, off);
1939                 update_global_button (Button::Write, off);
1940                 update_global_button (Button::Touch, off);
1941                 update_global_button (Button::Trim, off);
1942                 update_global_button (Button::Latch, off);
1943                 update_global_button (Button::Grp, on);
1944                 return;
1945         }
1946
1947         r->gain_control()->alist()->automation_state_changed.connect (fader_automation_connections,
1948                                                                       MISSING_INVALIDATOR,
1949                                                                       boost::bind (&MackieControlProtocol::update_fader_automation_state, this),
1950                                                                       this);
1951
1952         update_fader_automation_state ();
1953 }
1954
1955 void
1956 MackieControlProtocol::update_fader_automation_state ()
1957 {
1958         boost::shared_ptr<Stripable> r = first_selected_stripable ();
1959
1960         if (!r) {
1961                 update_global_button (Button::Read, off);
1962                 update_global_button (Button::Write, off);
1963                 update_global_button (Button::Touch, off);
1964                 update_global_button (Button::Trim, off);
1965                 update_global_button (Button::Latch, off);
1966                 update_global_button (Button::Grp, on);
1967                 return;
1968         }
1969
1970         switch (r->gain_control()->automation_state()) {
1971         case Off:
1972                 update_global_button (Button::Read, off);
1973                 update_global_button (Button::Write, off);
1974                 update_global_button (Button::Touch, off);
1975                 update_global_button (Button::Trim, off);
1976                 update_global_button (Button::Latch, off);
1977                 update_global_button (Button::Grp, on);
1978                 break;
1979         case Play:
1980                 update_global_button (Button::Read, on);
1981                 update_global_button (Button::Write, off);
1982                 update_global_button (Button::Touch, off);
1983                 update_global_button (Button::Trim, off);
1984                 update_global_button (Button::Latch, off);
1985                 update_global_button (Button::Grp, off);
1986                 break;
1987         case Write:
1988                 update_global_button (Button::Read, off);
1989                 update_global_button (Button::Write, on);
1990                 update_global_button (Button::Touch, off);
1991                 update_global_button (Button::Trim, off);
1992                 update_global_button (Button::Latch, off);
1993                 update_global_button (Button::Grp, off);
1994                 break;
1995         case Touch:
1996                 update_global_button (Button::Read, off);
1997                 update_global_button (Button::Write, off);
1998                 update_global_button (Button::Touch, on);
1999                 update_global_button (Button::Trim, off);
2000                 update_global_button (Button::Latch, off);
2001                 update_global_button (Button::Grp, off);
2002                 break;
2003         }
2004 }
2005
2006 framepos_t
2007 MackieControlProtocol::transport_frame() const
2008 {
2009         return session->transport_frame();
2010 }
2011
2012 void
2013 MackieControlProtocol::add_down_select_button (int surface, int strip)
2014 {
2015         _down_select_buttons.insert ((surface<<8)|(strip&0xf));
2016 }
2017
2018 void
2019 MackieControlProtocol::remove_down_select_button (int surface, int strip)
2020 {
2021         DownButtonList::iterator x = find (_down_select_buttons.begin(), _down_select_buttons.end(), (uint32_t) (surface<<8)|(strip&0xf));
2022         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down select buttons\n", surface, strip));
2023         if (x != _down_select_buttons.end()) {
2024                 _down_select_buttons.erase (x);
2025         } else {
2026                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 not found in down select buttons\n",
2027                                                                    surface, strip));
2028         }
2029 }
2030
2031 void
2032 MackieControlProtocol::select_range (uint32_t pressed)
2033 {
2034         StripableList stripables;
2035
2036         pull_stripable_range (_down_select_buttons, stripables, pressed);
2037
2038         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("select range: found %1 stripables, first = %2\n", stripables.size(), stripables.front()->name()));
2039
2040         if (stripables.empty()) {
2041                 return;
2042         }
2043
2044         if (stripables.size() == 1 && ControlProtocol::last_selected().size() == 1 && stripables.front()->presentation_info().selected()) {
2045                 /* cancel selection for one and only selected stripable */
2046                 ToggleStripableSelection (stripables.front());
2047         } else {
2048                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2049
2050                         if (main_modifier_state() == MODIFIER_SHIFT) {
2051                                 ToggleStripableSelection (*s);
2052                         } else {
2053                                 if (s == stripables.begin()) {
2054                                         SetStripableSelection (*s);
2055                                 } else {
2056                                         AddStripableToSelection (*s);
2057                                 }
2058                         }
2059                 }
2060         }
2061 }
2062
2063 void
2064 MackieControlProtocol::add_down_button (AutomationType a, int surface, int strip)
2065 {
2066         DownButtonMap::iterator m = _down_buttons.find (a);
2067
2068         if (m == _down_buttons.end()) {
2069                 _down_buttons[a] = DownButtonList();
2070         }
2071
2072         _down_buttons[a].insert ((surface<<8)|(strip&0xf));
2073 }
2074
2075 void
2076 MackieControlProtocol::remove_down_button (AutomationType a, int surface, int strip)
2077 {
2078         DownButtonMap::iterator m = _down_buttons.find (a);
2079
2080         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down buttons for %3\n", surface, strip, (int) a));
2081
2082         if (m == _down_buttons.end()) {
2083                 return;
2084         }
2085
2086         DownButtonList& l (m->second);
2087         DownButtonList::iterator x = find (l.begin(), l.end(), (surface<<8)|(strip&0xf));
2088
2089         if (x != l.end()) {
2090                 l.erase (x);
2091         } else {
2092                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 not found in down buttons for %3\n",
2093                                                                    surface, strip, (int) a));
2094         }
2095 }
2096
2097 MackieControlProtocol::ControlList
2098 MackieControlProtocol::down_controls (AutomationType p, uint32_t pressed)
2099 {
2100         ControlList controls;
2101         StripableList stripables;
2102
2103         DownButtonMap::iterator m = _down_buttons.find (p);
2104
2105         if (m == _down_buttons.end()) {
2106                 return controls;
2107         }
2108
2109         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("looking for down buttons for %1, got %2\n",
2110                                                            p, m->second.size()));
2111
2112         pull_stripable_range (m->second, stripables, pressed);
2113
2114         switch (p) {
2115         case GainAutomation:
2116                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2117                         controls.push_back ((*s)->gain_control());
2118                 }
2119                 break;
2120         case SoloAutomation:
2121                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2122                         controls.push_back ((*s)->solo_control());
2123                 }
2124                 break;
2125         case MuteAutomation:
2126                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2127                         controls.push_back ((*s)->mute_control());
2128                 }
2129                 break;
2130         case RecEnableAutomation:
2131                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2132                         boost::shared_ptr<AutomationControl> ac = (*s)->rec_enable_control();
2133                         if (ac) {
2134                                 controls.push_back (ac);
2135                         }
2136                 }
2137                 break;
2138         default:
2139                 break;
2140         }
2141
2142         return controls;
2143
2144 }
2145
2146 struct ButtonRangeSorter {
2147     bool operator() (const uint32_t& a, const uint32_t& b) {
2148             return (a>>8) < (b>>8) // a.surface < b.surface
2149                     ||
2150                     ((a>>8) == (b>>8) && (a&0xf) < (b&0xf)); // a.surface == b.surface && a.strip < b.strip
2151     }
2152 };
2153
2154 void
2155 MackieControlProtocol::pull_stripable_range (DownButtonList& down, StripableList& selected, uint32_t pressed)
2156 {
2157         ButtonRangeSorter cmp;
2158
2159         if (down.empty()) {
2160                 return;
2161         }
2162
2163         list<uint32_t> ldown;
2164         ldown.insert (ldown.end(), down.begin(), down.end());
2165         ldown.sort (cmp);
2166
2167         uint32_t first = ldown.front();
2168         uint32_t last = ldown.back ();
2169
2170         uint32_t first_surface = first>>8;
2171         uint32_t first_strip = first&0xf;
2172
2173         uint32_t last_surface = last>>8;
2174         uint32_t last_strip = last&0xf;
2175
2176         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("PRR %5 in list %1.%2 - %3.%4\n", first_surface, first_strip, last_surface, last_strip,
2177                                                            down.size()));
2178
2179         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2180
2181         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2182
2183                 if ((*s)->number() >= first_surface && (*s)->number() <= last_surface) {
2184
2185                         uint32_t fs;
2186                         uint32_t ls;
2187
2188                         if ((*s)->number() == first_surface) {
2189                                 fs = first_strip;
2190                         } else {
2191                                 fs = 0;
2192                         }
2193
2194                         if ((*s)->number() == last_surface) {
2195                                 ls = last_strip;
2196                                 ls += 1;
2197                         } else {
2198                                 ls = (*s)->n_strips ();
2199                         }
2200
2201                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("adding strips for surface %1 (%2 .. %3)\n",
2202                                                                            (*s)->number(), fs, ls));
2203
2204                         for (uint32_t n = fs; n < ls; ++n) {
2205                                 Strip* strip = (*s)->nth_strip (n);
2206                                 boost::shared_ptr<Stripable> r = strip->stripable();
2207                                 if (r) {
2208                                         if (global_index_locked (*strip) == pressed) {
2209                                                 selected.push_front (r);
2210                                         } else {
2211                                                 selected.push_back (r);
2212                                         }
2213                                 }
2214                         }
2215                 }
2216         }
2217
2218 }
2219
2220 void
2221 MackieControlProtocol::set_ipmidi_base (int16_t portnum)
2222 {
2223         /* this will not be saved without a session save, so .. */
2224
2225         session->set_dirty ();
2226
2227         _ipmidi_base = portnum;
2228
2229         /* if the current device uses ipMIDI we need
2230            to restart.
2231         */
2232
2233         if (active() && _device_info.uses_ipmidi()) {
2234                 needs_ipmidi_restart = true;
2235         }
2236 }
2237
2238 int
2239 MackieControlProtocol::ipmidi_restart ()
2240 {
2241         clear_surfaces ();
2242         if (create_surfaces ()) {
2243                 return -1;
2244         }
2245         (void) switch_banks (_current_initial_bank, true);
2246         needs_ipmidi_restart = false;
2247         return 0;
2248 }
2249
2250 void
2251 MackieControlProtocol::clear_surfaces ()
2252 {
2253         clear_ports ();
2254
2255         {
2256                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
2257                 _master_surface.reset ();
2258                 surfaces.clear ();
2259         }
2260 }
2261
2262 void
2263 MackieControlProtocol::set_touch_sensitivity (int sensitivity)
2264 {
2265         sensitivity = min (9, sensitivity);
2266         sensitivity = max (0, sensitivity);
2267
2268         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2269
2270         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2271                 (*s)->set_touch_sensitivity (sensitivity);
2272         }
2273 }
2274
2275 void
2276 MackieControlProtocol::recalibrate_faders ()
2277 {
2278         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2279
2280         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2281                 (*s)->recalibrate_faders ();
2282         }
2283 }
2284
2285 void
2286 MackieControlProtocol::toggle_backlight ()
2287 {
2288         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2289
2290         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2291                 (*s)->toggle_backlight ();
2292         }
2293 }
2294
2295 boost::shared_ptr<Surface>
2296 MackieControlProtocol::get_surface_by_raw_pointer (void* ptr) const
2297 {
2298         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2299
2300         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2301                 if ((*s).get() == (Surface*) ptr) {
2302                         return *s;
2303                 }
2304         }
2305
2306         return boost::shared_ptr<Surface> ();
2307 }
2308
2309 boost::shared_ptr<Surface>
2310 MackieControlProtocol::nth_surface (uint32_t n) const
2311 {
2312         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2313
2314         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s, --n) {
2315                 if (n == 0) {
2316                         return *s;
2317                 }
2318         }
2319
2320         return boost::shared_ptr<Surface> ();
2321 }
2322
2323 void
2324 MackieControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port> wp1, std::string name1, boost::weak_ptr<ARDOUR::Port> wp2, std::string name2, bool yn)
2325 {
2326         Surfaces scopy;
2327         {
2328                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
2329                 scopy = surfaces;
2330         }
2331
2332         for (Surfaces::const_iterator s = scopy.begin(); s != scopy.end(); ++s) {
2333                 if ((*s)->connection_handler (wp1, name1, wp2, name2, yn)) {
2334                         ConnectionChange (*s);
2335                         break;
2336                 }
2337         }
2338 }
2339
2340 bool
2341 MackieControlProtocol::is_track (boost::shared_ptr<Stripable> r) const
2342 {
2343         return boost::dynamic_pointer_cast<Track>(r) != 0;
2344 }
2345
2346 bool
2347 MackieControlProtocol::is_audio_track (boost::shared_ptr<Stripable> r) const
2348 {
2349         return boost::dynamic_pointer_cast<AudioTrack>(r) != 0;
2350 }
2351
2352 bool
2353 MackieControlProtocol::is_midi_track (boost::shared_ptr<Stripable> r) const
2354 {
2355         return boost::dynamic_pointer_cast<MidiTrack>(r) != 0;
2356 }
2357
2358 bool
2359 MackieControlProtocol::is_mapped (boost::shared_ptr<Stripable> r) const
2360 {
2361         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2362
2363         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2364                 if ((*s)->stripable_is_mapped (r)) {
2365                         return true;
2366                 }
2367         }
2368
2369         return false;
2370 }
2371
2372 void
2373 MackieControlProtocol::update_selected (boost::shared_ptr<Stripable> s, bool became_selected)
2374 {
2375         if (became_selected) {
2376
2377                 check_fader_automation_state ();
2378
2379                 /* It is possible that first_selected_route() may return null if we
2380                  * are no longer displaying/mapping that route. In that case,
2381                  * we will exit subview mode. If first_selected_route() is
2382                  * null, and subview mode is not None, then the first call to
2383                  * set_subview_mode() will fail, and we will reset to None.
2384                  */
2385
2386                 if (set_subview_mode (_subview_mode, first_selected_stripable())) {
2387                         set_subview_mode (None, boost::shared_ptr<Stripable>());
2388                 }
2389
2390         }
2391 }
2392
2393 boost::shared_ptr<Stripable>
2394 MackieControlProtocol::first_selected_stripable () const
2395 {
2396         boost::shared_ptr<Stripable> s = ControlProtocol::first_selected_stripable();
2397
2398         if (s) {
2399                 /* check it is on one of our surfaces */
2400
2401                 if (is_mapped (s)) {
2402                         return s;
2403                 }
2404
2405                 /* stripable is not mapped. thus, the currently selected stripable is
2406                  * not on the surfaces, and so from our perspective, there is
2407                  * no currently selected stripable.
2408                  */
2409
2410                 s.reset ();
2411         }
2412
2413         return s; /* may be null */
2414 }
2415
2416 boost::shared_ptr<Stripable>
2417 MackieControlProtocol::subview_stripable () const
2418 {
2419         return _subview_stripable;
2420 }
2421
2422 uint32_t
2423 MackieControlProtocol::global_index (Strip& strip)
2424 {
2425         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2426         return global_index_locked (strip);
2427 }
2428
2429 uint32_t
2430 MackieControlProtocol::global_index_locked (Strip& strip)
2431 {
2432         uint32_t global = 0;
2433
2434         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2435                 if ((*s).get() == strip.surface()) {
2436                         return global + strip.index();
2437                 }
2438                 global += (*s)->n_strips ();
2439         }
2440
2441         return global;
2442 }
2443
2444 void*
2445 MackieControlProtocol::request_factory (uint32_t num_requests)
2446 {
2447         /* AbstractUI<T>::request_buffer_factory() is a template method only
2448            instantiated in this source module. To provide something visible for
2449            use in the interface/descriptor, we have this static method that is
2450            template-free.
2451         */
2452         return request_buffer_factory (num_requests);
2453 }
2454
2455 void
2456 MackieControlProtocol::set_automation_state (AutoState as)
2457 {
2458         boost::shared_ptr<Stripable> r = first_selected_stripable ();
2459
2460         if (!r) {
2461                 return;
2462         }
2463
2464         boost::shared_ptr<AutomationControl> ac = r->gain_control();
2465
2466         if (!ac) {
2467                 return;
2468         }
2469
2470         ac->set_automation_state (as);
2471 }