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