enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[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->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         if (!action.empty()) {
1558
1559                 if (action.find ('/') != string::npos) { /* good chance that this is really an action */
1560
1561                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Looked up action for button %1 with modifier %2, got [%3]\n",
1562                                                                            button.bid(), _modifier_state, action));
1563
1564                         /* if there is a bound action for this button, and this is a press event,
1565                            carry out the action. If its a release event, do nothing since we
1566                            don't bind to them at all but don't want any other handling to
1567                            occur either.
1568                         */
1569                         if (bs == press) {
1570                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("executing action %1\n", action));
1571                                 access_action (action);
1572                         }
1573
1574                         return;
1575
1576                 } else {
1577
1578                         /* "action" is more likely to be a button name. We use this to
1579                          * allow remapping buttons to different (builtin) functionality
1580                          * associated with an existing button. This is similar to the
1581                          * way that (for example) Nuendo moves the "Shift" function to
1582                          * the "Enter" key of the MCU Pro.
1583                          */
1584
1585                         int bid = Button::name_to_id (action);
1586
1587                         if (bid < 0) {
1588                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("apparent button name %1 not found\n", action));
1589                                 return;
1590                         }
1591
1592                         button_id = (Button::ID) bid;
1593                         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)));
1594                 }
1595         }
1596
1597         /* lookup using the device-INDEPENDENT button ID */
1598
1599         ButtonMap::iterator b = button_map.find (button_id);
1600
1601         if (b != button_map.end()) {
1602
1603                 ButtonHandlers& bh (b->second);
1604
1605                 switch  (bs) {
1606                 case press:
1607                         surface.write (button.set_state ((this->*(bh.press)) (button)));
1608                         break;
1609                 case release:
1610                         surface.write (button.set_state ((this->*(bh.release)) (button)));
1611                         break;
1612                 default:
1613                         break;
1614                 }
1615         } else {
1616                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("no button handlers for button ID %1 (device ID %2)\n",
1617                                                                    button.bid(), button.id()));
1618                 error << string_compose ("no button handlers for button ID %1 (device ID %2)\n",
1619                                          button.bid(), button.id()) << endmsg;
1620         }
1621 }
1622
1623 bool
1624 MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
1625 {
1626         if (ioc & ~IO_IN) {
1627                 DEBUG_TRACE (DEBUG::MackieControl, "MIDI port closed\n");
1628                 return false;
1629         }
1630
1631         if (ioc & IO_IN) {
1632
1633                 // DEBUG_TRACE (DEBUG::MackieControl, string_compose ("something happend on  %1\n", port->name()));
1634
1635                 /* Devices using regular JACK MIDI ports will need to have
1636                    the x-thread FIFO drained to avoid burning endless CPU.
1637
1638                    Devices using ipMIDI have port->selectable() as the same
1639                    file descriptor that data arrives on, so doing this
1640                    for them will simply throw all incoming data away.
1641                 */
1642
1643                 if (!_device_info.uses_ipmidi()) {
1644                         AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*>(port);
1645                         if (asp) {
1646                                 asp->clear ();
1647                         }
1648                 }
1649
1650                 // DEBUG_TRACE (DEBUG::MackieControl, string_compose ("data available on %1\n", port->name()));
1651                 framepos_t now = session->engine().sample_time();
1652                 port->parse (now);
1653         }
1654
1655         return true;
1656 }
1657
1658 void
1659 MackieControlProtocol::clear_ports ()
1660 {
1661         if (_input_bundle) {
1662                 _input_bundle->remove_channels ();
1663                 _output_bundle->remove_channels ();
1664         }
1665 }
1666
1667 void
1668 MackieControlProtocol::notify_subview_stripable_deleted ()
1669 {
1670         /* return to global/mixer view */
1671         _subview_stripable.reset ();
1672         set_view_mode (Mixer);
1673 }
1674
1675 bool
1676 MackieControlProtocol::subview_mode_would_be_ok (SubViewMode mode, boost::shared_ptr<Stripable> r)
1677 {
1678         switch (mode) {
1679         case None:
1680                 return true;
1681                 break;
1682
1683         case Sends:
1684                 if (r && r->send_level_controllable (0)) {
1685                         return true;
1686                 }
1687                 break;
1688
1689         case EQ:
1690                 if (r && r->eq_band_cnt() > 0) {
1691                         return true;
1692                 }
1693                 break;
1694
1695         case Dynamics:
1696                 if (r && r->comp_enable_controllable()) {
1697                         return true;
1698                 }
1699                 break;
1700
1701         case TrackView:
1702                 if (r) {
1703                         return true;
1704                 }
1705         }
1706
1707         return false;
1708 }
1709
1710 bool
1711 MackieControlProtocol::redisplay_subview_mode ()
1712 {
1713         Surfaces copy; /* can't hold surfaces lock while calling Strip::subview_mode_changed */
1714
1715         {
1716                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
1717                 copy = surfaces;
1718         }
1719
1720         for (Surfaces::iterator s = copy.begin(); s != copy.end(); ++s) {
1721                 (*s)->subview_mode_changed ();
1722         }
1723
1724         /* don't call this again from a timeout */
1725         return false;
1726 }
1727
1728 int
1729 MackieControlProtocol::set_subview_mode (SubViewMode sm, boost::shared_ptr<Stripable> r)
1730 {
1731         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));
1732
1733         if (_flip_mode != Normal) {
1734                 set_flip_mode (Normal);
1735         }
1736
1737         if (!subview_mode_would_be_ok (sm, r)) {
1738
1739                 DEBUG_TRACE (DEBUG::MackieControl, "subview mode not OK\n");
1740
1741                 if (r) {
1742
1743                         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1744
1745                         if (!surfaces.empty()) {
1746
1747                                 string msg;
1748
1749                                 switch (sm) {
1750                                 case Sends:
1751                                         msg = _("no sends for selected track/bus");
1752                                         break;
1753                                 case EQ:
1754                                         msg = _("no EQ in the track/bus");
1755                                         break;
1756                                 case Dynamics:
1757                                         msg = _("no dynamics in selected track/bus");
1758                                         break;
1759                                 case TrackView:
1760                                         msg = _("no track view possible");
1761                                 default:
1762                                         break;
1763                                 }
1764                                 if (!msg.empty()) {
1765                                         surfaces.front()->display_message_for (msg, 1000);
1766                                         if (_subview_mode != None) {
1767                                                 /* redisplay current subview mode after
1768                                                    that message goes away.
1769                                                 */
1770                                                 Glib::RefPtr<Glib::TimeoutSource> redisplay_timeout = Glib::TimeoutSource::create (1000); // milliseconds
1771                                                 redisplay_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::redisplay_subview_mode));
1772                                                 redisplay_timeout->attach (main_loop()->get_context());
1773                                         }
1774                                 }
1775                         }
1776                 }
1777
1778                 return -1;
1779         }
1780
1781         boost::shared_ptr<Stripable> old_stripable = _subview_stripable;
1782
1783         _subview_mode = sm;
1784         _subview_stripable = r;
1785
1786         if (_subview_stripable != old_stripable) {
1787                 subview_stripable_connections.drop_connections ();
1788
1789                 /* Catch the current subview stripable going away */
1790                 if (_subview_stripable) {
1791                         _subview_stripable->DropReferences.connect (subview_stripable_connections, MISSING_INVALIDATOR,
1792                                                                     boost::bind (&MackieControlProtocol::notify_subview_stripable_deleted, this),
1793                                                                     this);
1794                 }
1795         }
1796
1797         redisplay_subview_mode ();
1798
1799         /* turn buttons related to vpot mode on or off as required */
1800
1801         switch (_subview_mode) {
1802         case MackieControlProtocol::None:
1803                 update_global_button (Button::Send, off);
1804                 update_global_button (Button::Plugin, off);
1805                 update_global_button (Button::Eq, off);
1806                 update_global_button (Button::Dyn, off);
1807                 update_global_button (Button::Track, off);
1808                 update_global_button (Button::Pan, on);
1809                 break;
1810         case MackieControlProtocol::EQ:
1811                 update_global_button (Button::Send, off);
1812                 update_global_button (Button::Plugin, off);
1813                 update_global_button (Button::Eq, on);
1814                 update_global_button (Button::Dyn, off);
1815                 update_global_button (Button::Track, off);
1816                 update_global_button (Button::Pan, off);
1817                 break;
1818         case MackieControlProtocol::Dynamics:
1819                 update_global_button (Button::Send, off);
1820                 update_global_button (Button::Plugin, off);
1821                 update_global_button (Button::Eq, off);
1822                 update_global_button (Button::Dyn, on);
1823                 update_global_button (Button::Track, off);
1824                 update_global_button (Button::Pan, off);
1825                 break;
1826         case MackieControlProtocol::Sends:
1827                 update_global_button (Button::Send, on);
1828                 update_global_button (Button::Plugin, off);
1829                 update_global_button (Button::Eq, off);
1830                 update_global_button (Button::Dyn, off);
1831                 update_global_button (Button::Track, off);
1832                 update_global_button (Button::Pan, off);
1833                 break;
1834         case MackieControlProtocol::TrackView:
1835                 update_global_button (Button::Send, off);
1836                 update_global_button (Button::Plugin, off);
1837                 update_global_button (Button::Eq, off);
1838                 update_global_button (Button::Dyn, off);
1839                 update_global_button (Button::Track, on);
1840                 update_global_button (Button::Pan, off);
1841                 break;
1842         }
1843
1844         return 0;
1845 }
1846
1847 void
1848 MackieControlProtocol::set_view_mode (ViewMode m)
1849 {
1850         if (_flip_mode != Normal) {
1851                 set_flip_mode (Normal);
1852         }
1853         ViewMode old_view_mode = _view_mode;
1854
1855         _view_mode = m;
1856         _last_bank[old_view_mode] = _current_initial_bank;
1857
1858         if (switch_banks(_last_bank[m], true)) {
1859                 _view_mode = old_view_mode;
1860                 return;
1861         }
1862
1863         /* leave subview mode, whatever it was */
1864         set_subview_mode (None, boost::shared_ptr<Stripable>());
1865         display_view_mode ();
1866 }
1867
1868 void
1869 MackieControlProtocol::display_view_mode ()
1870 {
1871         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1872
1873         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1874                 (*s)->update_view_mode_display (true);
1875         }
1876 }
1877
1878 void
1879 MackieControlProtocol::set_flip_mode (FlipMode fm)
1880 {
1881         if (fm == Normal) {
1882                 update_global_button (Button::Flip, off);
1883         } else {
1884                 update_global_button (Button::Flip, on);
1885         }
1886
1887         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1888
1889         _flip_mode = fm;
1890
1891         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1892                 (*s)->update_flip_mode_display ();
1893         }
1894 }
1895
1896 void
1897 MackieControlProtocol::set_master_on_surface_strip (uint32_t surface, uint32_t strip_number)
1898 {
1899         force_special_stripable_to_strip (session->master_out(), surface, strip_number);
1900 }
1901
1902 void
1903 MackieControlProtocol::set_monitor_on_surface_strip (uint32_t surface, uint32_t strip_number)
1904 {
1905         force_special_stripable_to_strip (session->monitor_out(), surface, strip_number);
1906 }
1907
1908 void
1909 MackieControlProtocol::force_special_stripable_to_strip (boost::shared_ptr<Stripable> r, uint32_t surface, uint32_t strip_number)
1910 {
1911         if (!r) {
1912                 return;
1913         }
1914
1915         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1916
1917         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
1918                 if ((*s)->number() == surface) {
1919                         Strip* strip = (*s)->nth_strip (strip_number);
1920                         if (strip) {
1921                                 strip->set_stripable (session->master_out());
1922                                 strip->lock_controls ();
1923                         }
1924                 }
1925         }
1926 }
1927
1928 void
1929 MackieControlProtocol::check_fader_automation_state ()
1930 {
1931         fader_automation_connections.drop_connections ();
1932
1933         boost::shared_ptr<Stripable> r = first_selected_stripable ();
1934
1935         if (!r) {
1936                 update_global_button (Button::Read, off);
1937                 update_global_button (Button::Write, off);
1938                 update_global_button (Button::Touch, off);
1939                 update_global_button (Button::Trim, off);
1940                 update_global_button (Button::Latch, off);
1941                 update_global_button (Button::Grp, on);
1942                 return;
1943         }
1944
1945         r->gain_control()->alist()->automation_state_changed.connect (fader_automation_connections,
1946                                                                       MISSING_INVALIDATOR,
1947                                                                       boost::bind (&MackieControlProtocol::update_fader_automation_state, this),
1948                                                                       this);
1949
1950         update_fader_automation_state ();
1951 }
1952
1953 void
1954 MackieControlProtocol::update_fader_automation_state ()
1955 {
1956         boost::shared_ptr<Stripable> r = first_selected_stripable ();
1957
1958         if (!r) {
1959                 update_global_button (Button::Read, off);
1960                 update_global_button (Button::Write, off);
1961                 update_global_button (Button::Touch, off);
1962                 update_global_button (Button::Trim, off);
1963                 update_global_button (Button::Latch, off);
1964                 update_global_button (Button::Grp, on);
1965                 return;
1966         }
1967
1968         switch (r->gain_control()->automation_state()) {
1969         case Off:
1970                 update_global_button (Button::Read, off);
1971                 update_global_button (Button::Write, off);
1972                 update_global_button (Button::Touch, off);
1973                 update_global_button (Button::Trim, off);
1974                 update_global_button (Button::Latch, off);
1975                 update_global_button (Button::Grp, on);
1976                 break;
1977         case Play:
1978                 update_global_button (Button::Read, on);
1979                 update_global_button (Button::Write, off);
1980                 update_global_button (Button::Touch, off);
1981                 update_global_button (Button::Trim, off);
1982                 update_global_button (Button::Latch, off);
1983                 update_global_button (Button::Grp, off);
1984                 break;
1985         case Write:
1986                 update_global_button (Button::Read, off);
1987                 update_global_button (Button::Write, on);
1988                 update_global_button (Button::Touch, off);
1989                 update_global_button (Button::Trim, off);
1990                 update_global_button (Button::Latch, off);
1991                 update_global_button (Button::Grp, off);
1992                 break;
1993         case Touch:
1994                 update_global_button (Button::Read, off);
1995                 update_global_button (Button::Write, off);
1996                 update_global_button (Button::Touch, on);
1997                 update_global_button (Button::Trim, off);
1998                 update_global_button (Button::Latch, off);
1999                 update_global_button (Button::Grp, off);
2000                 break;
2001         }
2002 }
2003
2004 framepos_t
2005 MackieControlProtocol::transport_frame() const
2006 {
2007         return session->transport_frame();
2008 }
2009
2010 void
2011 MackieControlProtocol::add_down_select_button (int surface, int strip)
2012 {
2013         _down_select_buttons.insert ((surface<<8)|(strip&0xf));
2014 }
2015
2016 void
2017 MackieControlProtocol::remove_down_select_button (int surface, int strip)
2018 {
2019         DownButtonList::iterator x = find (_down_select_buttons.begin(), _down_select_buttons.end(), (uint32_t) (surface<<8)|(strip&0xf));
2020         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down select buttons\n", surface, strip));
2021         if (x != _down_select_buttons.end()) {
2022                 _down_select_buttons.erase (x);
2023         } else {
2024                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 not found in down select buttons\n",
2025                                                                    surface, strip));
2026         }
2027 }
2028
2029 void
2030 MackieControlProtocol::select_range (uint32_t pressed)
2031 {
2032         StripableList stripables;
2033
2034         pull_stripable_range (_down_select_buttons, stripables, pressed);
2035
2036         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("select range: found %1 stripables, first = %2\n", stripables.size(), stripables.front()->name()));
2037
2038         if (stripables.empty()) {
2039                 return;
2040         }
2041
2042         if (stripables.size() == 1 && ControlProtocol::last_selected().size() == 1 && stripables.front()->presentation_info().selected()) {
2043                 /* cancel selection for one and only selected stripable */
2044                 ToggleStripableSelection (stripables.front());
2045         } else {
2046                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2047
2048                         if (main_modifier_state() == MODIFIER_SHIFT) {
2049                                 ToggleStripableSelection (*s);
2050                         } else {
2051                                 if (s == stripables.begin()) {
2052                                         SetStripableSelection (*s);
2053                                 } else {
2054                                         AddStripableToSelection (*s);
2055                                 }
2056                         }
2057                 }
2058         }
2059 }
2060
2061 void
2062 MackieControlProtocol::add_down_button (AutomationType a, int surface, int strip)
2063 {
2064         DownButtonMap::iterator m = _down_buttons.find (a);
2065
2066         if (m == _down_buttons.end()) {
2067                 _down_buttons[a] = DownButtonList();
2068         }
2069
2070         _down_buttons[a].insert ((surface<<8)|(strip&0xf));
2071 }
2072
2073 void
2074 MackieControlProtocol::remove_down_button (AutomationType a, int surface, int strip)
2075 {
2076         DownButtonMap::iterator m = _down_buttons.find (a);
2077
2078         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down buttons for %3\n", surface, strip, (int) a));
2079
2080         if (m == _down_buttons.end()) {
2081                 return;
2082         }
2083
2084         DownButtonList& l (m->second);
2085         DownButtonList::iterator x = find (l.begin(), l.end(), (surface<<8)|(strip&0xf));
2086
2087         if (x != l.end()) {
2088                 l.erase (x);
2089         } else {
2090                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 not found in down buttons for %3\n",
2091                                                                    surface, strip, (int) a));
2092         }
2093 }
2094
2095 MackieControlProtocol::ControlList
2096 MackieControlProtocol::down_controls (AutomationType p, uint32_t pressed)
2097 {
2098         ControlList controls;
2099         StripableList stripables;
2100
2101         DownButtonMap::iterator m = _down_buttons.find (p);
2102
2103         if (m == _down_buttons.end()) {
2104                 return controls;
2105         }
2106
2107         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("looking for down buttons for %1, got %2\n",
2108                                                            p, m->second.size()));
2109
2110         pull_stripable_range (m->second, stripables, pressed);
2111
2112         switch (p) {
2113         case GainAutomation:
2114                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2115                         controls.push_back ((*s)->gain_control());
2116                 }
2117                 break;
2118         case SoloAutomation:
2119                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2120                         controls.push_back ((*s)->solo_control());
2121                 }
2122                 break;
2123         case MuteAutomation:
2124                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2125                         controls.push_back ((*s)->mute_control());
2126                 }
2127                 break;
2128         case RecEnableAutomation:
2129                 for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
2130                         boost::shared_ptr<AutomationControl> ac = (*s)->rec_enable_control();
2131                         if (ac) {
2132                                 controls.push_back (ac);
2133                         }
2134                 }
2135                 break;
2136         default:
2137                 break;
2138         }
2139
2140         return controls;
2141
2142 }
2143
2144 struct ButtonRangeSorter {
2145     bool operator() (const uint32_t& a, const uint32_t& b) {
2146             return (a>>8) < (b>>8) // a.surface < b.surface
2147                     ||
2148                     ((a>>8) == (b>>8) && (a&0xf) < (b&0xf)); // a.surface == b.surface && a.strip < b.strip
2149     }
2150 };
2151
2152 void
2153 MackieControlProtocol::pull_stripable_range (DownButtonList& down, StripableList& selected, uint32_t pressed)
2154 {
2155         ButtonRangeSorter cmp;
2156
2157         if (down.empty()) {
2158                 return;
2159         }
2160
2161         list<uint32_t> ldown;
2162         ldown.insert (ldown.end(), down.begin(), down.end());
2163         ldown.sort (cmp);
2164
2165         uint32_t first = ldown.front();
2166         uint32_t last = ldown.back ();
2167
2168         uint32_t first_surface = first>>8;
2169         uint32_t first_strip = first&0xf;
2170
2171         uint32_t last_surface = last>>8;
2172         uint32_t last_strip = last&0xf;
2173
2174         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("PRR %5 in list %1.%2 - %3.%4\n", first_surface, first_strip, last_surface, last_strip,
2175                                                            down.size()));
2176
2177         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2178
2179         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2180
2181                 if ((*s)->number() >= first_surface && (*s)->number() <= last_surface) {
2182
2183                         uint32_t fs;
2184                         uint32_t ls;
2185
2186                         if ((*s)->number() == first_surface) {
2187                                 fs = first_strip;
2188                         } else {
2189                                 fs = 0;
2190                         }
2191
2192                         if ((*s)->number() == last_surface) {
2193                                 ls = last_strip;
2194                                 ls += 1;
2195                         } else {
2196                                 ls = (*s)->n_strips ();
2197                         }
2198
2199                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("adding strips for surface %1 (%2 .. %3)\n",
2200                                                                            (*s)->number(), fs, ls));
2201
2202                         for (uint32_t n = fs; n < ls; ++n) {
2203                                 Strip* strip = (*s)->nth_strip (n);
2204                                 boost::shared_ptr<Stripable> r = strip->stripable();
2205                                 if (r) {
2206                                         if (global_index_locked (*strip) == pressed) {
2207                                                 selected.push_front (r);
2208                                         } else {
2209                                                 selected.push_back (r);
2210                                         }
2211                                 }
2212                         }
2213                 }
2214         }
2215
2216 }
2217
2218 void
2219 MackieControlProtocol::set_ipmidi_base (int16_t portnum)
2220 {
2221         /* this will not be saved without a session save, so .. */
2222
2223         session->set_dirty ();
2224
2225         _ipmidi_base = portnum;
2226
2227         /* if the current device uses ipMIDI we need
2228            to restart.
2229         */
2230
2231         if (active() && _device_info.uses_ipmidi()) {
2232                 needs_ipmidi_restart = true;
2233         }
2234 }
2235
2236 int
2237 MackieControlProtocol::ipmidi_restart ()
2238 {
2239         clear_surfaces ();
2240         if (create_surfaces ()) {
2241                 return -1;
2242         }
2243         (void) switch_banks (_current_initial_bank, true);
2244         needs_ipmidi_restart = false;
2245         return 0;
2246 }
2247
2248 void
2249 MackieControlProtocol::clear_surfaces ()
2250 {
2251         clear_ports ();
2252
2253         {
2254                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
2255                 _master_surface.reset ();
2256                 surfaces.clear ();
2257         }
2258 }
2259
2260 void
2261 MackieControlProtocol::set_touch_sensitivity (int sensitivity)
2262 {
2263         sensitivity = min (9, sensitivity);
2264         sensitivity = max (0, sensitivity);
2265
2266         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2267
2268         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2269                 (*s)->set_touch_sensitivity (sensitivity);
2270         }
2271 }
2272
2273 void
2274 MackieControlProtocol::recalibrate_faders ()
2275 {
2276         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2277
2278         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2279                 (*s)->recalibrate_faders ();
2280         }
2281 }
2282
2283 void
2284 MackieControlProtocol::toggle_backlight ()
2285 {
2286         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2287
2288         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2289                 (*s)->toggle_backlight ();
2290         }
2291 }
2292
2293 boost::shared_ptr<Surface>
2294 MackieControlProtocol::get_surface_by_raw_pointer (void* ptr) const
2295 {
2296         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2297
2298         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2299                 if ((*s).get() == (Surface*) ptr) {
2300                         return *s;
2301                 }
2302         }
2303
2304         return boost::shared_ptr<Surface> ();
2305 }
2306
2307 boost::shared_ptr<Surface>
2308 MackieControlProtocol::nth_surface (uint32_t n) const
2309 {
2310         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2311
2312         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s, --n) {
2313                 if (n == 0) {
2314                         return *s;
2315                 }
2316         }
2317
2318         return boost::shared_ptr<Surface> ();
2319 }
2320
2321 void
2322 MackieControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port> wp1, std::string name1, boost::weak_ptr<ARDOUR::Port> wp2, std::string name2, bool yn)
2323 {
2324         Surfaces scopy;
2325         {
2326                 Glib::Threads::Mutex::Lock lm (surfaces_lock);
2327                 scopy = surfaces;
2328         }
2329
2330         for (Surfaces::const_iterator s = scopy.begin(); s != scopy.end(); ++s) {
2331                 if ((*s)->connection_handler (wp1, name1, wp2, name2, yn)) {
2332                         ConnectionChange (*s);
2333                         break;
2334                 }
2335         }
2336 }
2337
2338 bool
2339 MackieControlProtocol::is_track (boost::shared_ptr<Stripable> r) const
2340 {
2341         return boost::dynamic_pointer_cast<Track>(r) != 0;
2342 }
2343
2344 bool
2345 MackieControlProtocol::is_audio_track (boost::shared_ptr<Stripable> r) const
2346 {
2347         return boost::dynamic_pointer_cast<AudioTrack>(r) != 0;
2348 }
2349
2350 bool
2351 MackieControlProtocol::is_midi_track (boost::shared_ptr<Stripable> r) const
2352 {
2353         return boost::dynamic_pointer_cast<MidiTrack>(r) != 0;
2354 }
2355
2356 bool
2357 MackieControlProtocol::is_mapped (boost::shared_ptr<Stripable> r) const
2358 {
2359         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2360
2361         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2362                 if ((*s)->stripable_is_mapped (r)) {
2363                         return true;
2364                 }
2365         }
2366
2367         return false;
2368 }
2369
2370 void
2371 MackieControlProtocol::update_selected (boost::shared_ptr<Stripable> s, bool became_selected)
2372 {
2373         if (became_selected) {
2374
2375                 check_fader_automation_state ();
2376
2377                 /* It is possible that first_selected_route() may return null if we
2378                  * are no longer displaying/mapping that route. In that case,
2379                  * we will exit subview mode. If first_selected_route() is
2380                  * null, and subview mode is not None, then the first call to
2381                  * set_subview_mode() will fail, and we will reset to None.
2382                  */
2383
2384                 if (set_subview_mode (_subview_mode, first_selected_stripable())) {
2385                         set_subview_mode (None, boost::shared_ptr<Stripable>());
2386                 }
2387
2388         }
2389 }
2390
2391 boost::shared_ptr<Stripable>
2392 MackieControlProtocol::first_selected_stripable () const
2393 {
2394         boost::shared_ptr<Stripable> s = ControlProtocol::first_selected_stripable();
2395
2396         if (s) {
2397                 /* check it is on one of our surfaces */
2398
2399                 if (is_mapped (s)) {
2400                         return s;
2401                 }
2402
2403                 /* stripable is not mapped. thus, the currently selected stripable is
2404                  * not on the surfaces, and so from our perspective, there is
2405                  * no currently selected stripable.
2406                  */
2407
2408                 s.reset ();
2409         }
2410
2411         return s; /* may be null */
2412 }
2413
2414 boost::shared_ptr<Stripable>
2415 MackieControlProtocol::subview_stripable () const
2416 {
2417         return _subview_stripable;
2418 }
2419
2420 uint32_t
2421 MackieControlProtocol::global_index (Strip& strip)
2422 {
2423         Glib::Threads::Mutex::Lock lm (surfaces_lock);
2424         return global_index_locked (strip);
2425 }
2426
2427 uint32_t
2428 MackieControlProtocol::global_index_locked (Strip& strip)
2429 {
2430         uint32_t global = 0;
2431
2432         for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
2433                 if ((*s).get() == strip.surface()) {
2434                         return global + strip.index();
2435                 }
2436                 global += (*s)->n_strips ();
2437         }
2438
2439         return global;
2440 }
2441
2442 void*
2443 MackieControlProtocol::request_factory (uint32_t num_requests)
2444 {
2445         /* AbstractUI<T>::request_buffer_factory() is a template method only
2446            instantiated in this source module. To provide something visible for
2447            use in the interface/descriptor, we have this static method that is
2448            template-free.
2449         */
2450         return request_buffer_factory (num_requests);
2451 }
2452
2453 void
2454 MackieControlProtocol::set_automation_state (AutoState as)
2455 {
2456         boost::shared_ptr<Stripable> r = first_selected_stripable ();
2457
2458         if (!r) {
2459                 return;
2460         }
2461
2462         boost::shared_ptr<AutomationControl> ac = r->gain_control();
2463
2464         if (!ac) {
2465                 return;
2466         }
2467
2468         ac->set_automation_state (as);
2469 }