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