8ad9db142e3e22358b2785edcb26414d5d717745
[ardour.git] / libs / surfaces / mackie / mackie_control_protocol.cc
1 /*
2         Copyright (C) 2006,2007 John Anderson
3
4         This program is free software; you can redistribute it and/or modify
5         it under the terms of the GNU General Public License as published by
6         the Free Software Foundation; either version 2 of the License, or
7         (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12         GNU General Public License for more details.
13
14         You should have received a copy of the GNU General Public License
15         along with this program; if not, write to the Free Software
16         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <fcntl.h>
20 #include <iostream>
21 #include <algorithm>
22 #include <cmath>
23 #include <sstream>
24 #include <vector>
25 #include <iomanip>
26
27 #include <inttypes.h>
28 #include <float.h>
29 #include <sys/time.h>
30 #include <errno.h>
31 #include <poll.h>
32
33 #include <boost/shared_array.hpp>
34
35 #include "midi++/types.h"
36 #include "midi++/port.h"
37 #include "midi++/manager.h"
38 #include "pbd/pthread_utils.h"
39 #include "pbd/error.h"
40 #include "pbd/memento_command.h"
41 #include "pbd/convert.h"
42
43 #include "ardour/dB.h"
44 #include "ardour/debug.h"
45 #include "ardour/location.h"
46 #include "ardour/midi_ui.h"
47 #include "ardour/panner.h"
48 #include "ardour/panner_shell.h"
49 #include "ardour/route.h"
50 #include "ardour/session.h"
51 #include "ardour/tempo.h"
52 #include "ardour/types.h"
53 #include "ardour/audioengine.h"
54
55 #include "mackie_control_protocol.h"
56
57 #include "midi_byte_array.h"
58 #include "mackie_control_exception.h"
59 #include "route_signal.h"
60 #include "mackie_midi_builder.h"
61 #include "surface_port.h"
62 #include "surface.h"
63 #include "bcf_surface.h"
64 #include "mackie_surface.h"
65
66 using namespace ARDOUR;
67 using namespace std;
68 using namespace Mackie;
69 using namespace PBD;
70
71 #include "i18n.h"
72
73 #include "pbd/abstract_ui.cc" // instantiate template
74
75 #define NUCLEUS_DEBUG 1
76
77 MackieMidiBuilder builder;
78
79 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
80 #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
81
82 extern PBD::EventLoop::InvalidationRecord* __invalidator (sigc::trackable& trackable, const char*, int);
83 #define invalidator(x) __invalidator ((x), __FILE__, __LINE__)
84
85 MackieControlProtocol::MackieControlProtocol (Session& session)
86         : ControlProtocol (session, X_("Mackie"), MidiControlUI::instance())
87         , AbstractUI<MackieControlUIRequest> ("mackie")
88         , _current_initial_bank (0)
89         , _surface (0)
90         , _jog_wheel (*this)
91         , _timecode_type (ARDOUR::AnyTime::BBT)
92         , _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
93         , _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
94         , _gui (0)
95 {
96         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
97
98         AudioEngine::instance()->PortConnectedOrDisconnected.connect (
99                 audio_engine_connections, invalidator (*this), ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
100                 midi_ui_context ()
101                 );
102 }
103
104 MackieControlProtocol::~MackieControlProtocol()
105 {
106         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol\n");
107
108         try {
109                 close();
110         }
111         catch (exception & e) {
112                 cout << "~MackieControlProtocol caught " << e.what() << endl;
113         }
114         catch (...) {
115                 cout << "~MackieControlProtocol caught unknown" << endl;
116         }
117
118         DEBUG_TRACE (DEBUG::MackieControl, "finished ~MackieControlProtocol::MackieControlProtocol\n");
119 }
120
121 Mackie::Surface& 
122 MackieControlProtocol::surface()
123 {
124         if (_surface == 0) {
125                 throw MackieControlException ("_surface is 0 in MackieControlProtocol::surface");
126         }
127         return *_surface;
128 }
129
130 const Mackie::SurfacePort& 
131 MackieControlProtocol::mcu_port() const
132 {
133         if (_ports.size() < 1) {
134                 return _dummy_port;
135         } else {
136                 return dynamic_cast<const MackiePort &> (*_ports[0]);
137         }
138 }
139
140 Mackie::SurfacePort& 
141 MackieControlProtocol::mcu_port()
142 {
143         if (_ports.size() < 1) {
144                 return _dummy_port;
145         } else {
146                 return dynamic_cast<MackiePort &> (*_ports[0]);
147         }
148 }
149
150 // go to the previous track.
151 // Assume that get_sorted_routes().size() > route_table.size()
152 void 
153 MackieControlProtocol::prev_track()
154 {
155         if (_current_initial_bank >= 1) {
156                 session->set_dirty();
157                 switch_banks (_current_initial_bank - 1);
158         }
159 }
160
161 // go to the next track.
162 // Assume that get_sorted_routes().size() > route_table.size()
163 void 
164 MackieControlProtocol::next_track()
165 {
166         Sorted sorted = get_sorted_routes();
167         if (_current_initial_bank + route_table.size() < sorted.size()) {
168                 session->set_dirty();
169                 switch_banks (_current_initial_bank + 1);
170         }
171 }
172
173 void 
174 MackieControlProtocol::clear_route_signals()
175 {
176         for (RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it) {
177                 delete *it;
178         }
179         route_signals.clear();
180 }
181
182 // return the port for a given id - 0 based
183 // throws an exception if no port found
184 MackiePort& 
185 MackieControlProtocol::port_for_id (uint32_t index)
186 {
187         uint32_t current_max = 0;
188
189         for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
190                 current_max += (*it)->strips();
191                 if (index < current_max) { 
192                         return **it;
193                 }
194         }
195
196         // oops - no matching port
197         ostringstream os;
198         os << "No port for index " << index;
199         cerr << "No port for index " << index << endl;
200         throw MackieControlException (os.str());
201 }
202
203 // predicate for sort call in get_sorted_routes
204 struct RouteByRemoteId
205 {
206         bool operator () (const boost::shared_ptr<Route> & a, const boost::shared_ptr<Route> & b) const
207         {
208                 return a->remote_control_id() < b->remote_control_id();
209         }
210
211         bool operator () (const Route & a, const Route & b) const
212         {
213                 return a.remote_control_id() < b.remote_control_id();
214         }
215
216         bool operator () (const Route * a, const Route * b) const
217         {
218                 return a->remote_control_id() < b->remote_control_id();
219         }
220 };
221
222 MackieControlProtocol::Sorted 
223 MackieControlProtocol::get_sorted_routes()
224 {
225         Sorted sorted;
226
227         // fetch all routes
228         boost::shared_ptr<RouteList> routes = session->get_routes();
229         set<uint32_t> remote_ids;
230
231         // routes with remote_id 0 should never be added
232         // TODO verify this with ardour devs
233         // remote_ids.insert (0);
234
235         // sort in remote_id order, and exclude master, control and hidden routes
236         // and any routes that are already set.
237         for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it) {
238                 Route & route = **it;
239                 if (
240                         route.active()
241                         && !route.is_master()
242                         && !route.is_hidden()
243                         && !route.is_monitor()
244                         && remote_ids.find (route.remote_control_id()) == remote_ids.end()
245                         ) {
246                         sorted.push_back (*it);
247                         remote_ids.insert (route.remote_control_id());
248                 }
249         }
250         sort (sorted.begin(), sorted.end(), RouteByRemoteId());
251         return sorted;
252 }
253
254 void 
255 MackieControlProtocol::refresh_current_bank()
256 {
257         switch_banks (_current_initial_bank);
258 }
259
260 void 
261 MackieControlProtocol::switch_banks (int initial)
262 {
263         // DON'T prevent bank switch if initial == _current_initial_bank
264         // because then this method can't be used as a refresh
265
266         // sanity checking
267         Sorted sorted = get_sorted_routes();
268         int delta = sorted.size() - route_table.size();
269         if (initial < 0 || (delta > 0 && initial > delta)) {
270                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
271                 return;
272         }
273         _current_initial_bank = initial;
274
275         // first clear the signals from old routes
276         // taken care of by the RouteSignal destructors
277         clear_route_signals();
278
279         // now set the signals for new routes
280         if (_current_initial_bank <= sorted.size()) {
281                 // fetch the bank start and end to switch to
282                 uint32_t end_pos = min (route_table.size(), sorted.size());
283                 Sorted::iterator it = sorted.begin() + _current_initial_bank;
284                 Sorted::iterator end = sorted.begin() + _current_initial_bank + end_pos;
285
286                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2\n", _current_initial_bank, end_pos));
287
288                 route_table.clear ();
289                 set_route_table_size (surface().strips.size());
290
291                 // link routes to strips
292                 uint32_t i = 0;
293                 for (; it != end && it != sorted.end(); ++it, ++i) {
294                         boost::shared_ptr<Route> route = *it;
295
296                         assert (surface().strips[i]);
297                         Strip & strip = *surface().strips[i];
298
299                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("remote id %1 connecting %2 to %3 with port %4\n", 
300                                                                            route->remote_control_id(), route->name(), strip.name(), port_for_id(i)));
301                         set_route_table (1, route);
302                         RouteSignal * rs = new RouteSignal (route, *this, strip, port_for_id(i));
303                         route_signals.push_back (rs);
304                         // update strip from route
305                         rs->notify_all();
306                 }
307
308                 // create dead strips if there aren't enough routes to
309                 // fill a bank
310                 for (; i < route_table.size(); ++i) {
311                         Strip & strip = *surface().strips[i];
312                         // send zero for this strip
313                         MackiePort & port = port_for_id(i);
314                         port.write (builder.zero_strip (port, strip));
315                 }
316         }
317
318         // display the current start bank.
319         surface().display_bank_start (mcu_port(), builder, _current_initial_bank);
320 }
321
322 void 
323 MackieControlProtocol::zero_all()
324 {
325         // TODO turn off Timecode displays
326
327         // zero all strips
328         for (Surface::Strips::iterator it = surface().strips.begin(); it != surface().strips.end(); ++it) {
329                 MackiePort & port = port_for_id ((*it)->index());
330                 port.write (builder.zero_strip (port, **it));
331         }
332
333         // and the master strip
334         mcu_port().write (builder.zero_strip (dynamic_cast<MackiePort&> (mcu_port()), master_strip()));
335
336         // turn off global buttons and leds
337         // global buttons are only ever on mcu_port, so we don't have
338         // to figure out which port.
339         for (Surface::Controls::iterator it = surface().controls.begin(); it != surface().controls.end(); ++it) {
340                 Control & control = **it;
341                 if (!control.group().is_strip() && control.accepts_feedback()) {
342                         mcu_port().write (builder.zero_control (control));
343                 }
344         }
345
346         // any hardware-specific stuff
347         surface().zero_all (mcu_port(), builder);
348 }
349
350 int 
351 MackieControlProtocol::set_active (bool yn)
352 {
353         if (yn == _active) {
354                 return 0;
355         }
356         
357         try
358         {
359                 // the reason for the locking and unlocking is that
360                 // glibmm can't do a condition wait on a RecMutex
361                 if (yn) {
362                         // TODO what happens if this fails half way?
363                         
364                         // create MackiePorts
365                         {
366                                 Glib::Mutex::Lock lock (update_mutex);
367                                 create_ports();
368                         }
369                         
370                         // now initialise MackiePorts - ie exchange sysex messages
371                         for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
372                                 (*it)->open();
373                         }
374                         
375                         // wait until all ports are active
376                         // TODO a more sophisticated approach would
377                         // allow things to start up with only an MCU, even if
378                         // extenders were specified but not responding.
379                         for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
380                                 (*it)->wait_for_init();
381                         }
382                         
383                         // create surface object. This depends on the ports being
384                         // correctly initialised
385                         initialize_surface();
386                         connect_session_signals();
387                         
388                         // yeehah!
389                         _active = true;
390                         
391                         // send current control positions to surface
392                         // must come after _active = true otherwise it won't run
393                         update_surface();
394                 } else {
395                         close();
396                         _active = false;
397                 }
398         }
399         
400         catch (exception & e) {
401                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
402                 _active = false;
403                 throw;
404         }
405
406         return 0;
407 }
408
409 bool 
410 MackieControlProtocol::handle_strip_button (SurfacePort & port, Control & control, ButtonState bs, boost::shared_ptr<Route> route)
411 {
412         bool state = false;
413
414         if (bs == press) {
415                 if (control.name() == "recenable") {
416                         state = !route->record_enabled();
417                         route->set_record_enabled (state, this);
418                 } else if (control.name() == "mute") {
419                         state = !route->muted();
420                         route->set_mute (state, this);
421                 } else if (control.name() == "solo") {
422                         state = !route->soloed();
423                         route->set_solo (state, this);
424                 } else if (control.name() == "select") {
425                         // TODO make the track selected. Whatever that means.
426                         //state = default_button_press (dynamic_cast<Button&> (control));
427                 } else if (control.name() == "vselect") {
428                         // TODO could be used to select different things to apply the pot to?
429                         //state = default_button_press (dynamic_cast<Button&> (control));
430                 }
431         }
432
433         if (control.name() == "fader_touch") {
434                 state = bs == press;
435                 control.strip().gain().set_in_use (state);
436
437                 if (ARDOUR::Config->get_mackie_emulation() == "bcf" && state) {
438                         /* BCF faders don't support touch, so add a timeout to reset
439                            their `in_use' state.
440                         */
441                         port.add_in_use_timeout (control.strip().gain(), &control.strip().fader_touch());
442                 }
443         }
444
445         return state;
446 }
447
448 void 
449 MackieControlProtocol::update_led (Mackie::Button & button, Mackie::LedState ls)
450 {
451         if (ls != none) {
452                 SurfacePort * port = 0;
453                 if (button.group().is_strip()) {
454                         if (button.group().is_master()) {
455                                 port = &mcu_port();
456                         } else {
457                                 port = &port_for_id (dynamic_cast<const Strip&> (button.group()).index());
458                         }
459                 } else {
460                         port = &mcu_port();
461                 }
462                 port->write (builder.build_led (button, ls));
463         }
464 }
465
466 void 
467 MackieControlProtocol::update_timecode_beats_led()
468 {
469         switch (_timecode_type) {
470                 case ARDOUR::AnyTime::BBT:
471                         update_global_led ("beats", on);
472                         update_global_led ("timecode", off);
473                         break;
474                 case ARDOUR::AnyTime::Timecode:
475                         update_global_led ("timecode", on);
476                         update_global_led ("beats", off);
477                         break;
478                 default:
479                         ostringstream os;
480                         os << "Unknown Anytime::Type " << _timecode_type;
481                         throw runtime_error (os.str());
482         }
483 }
484
485 void 
486 MackieControlProtocol::update_global_button (const string & name, LedState ls)
487 {
488         if (surface().controls_by_name.find (name) != surface().controls_by_name.end()) {
489                 Button * button = dynamic_cast<Button*> (surface().controls_by_name[name]);
490                 mcu_port().write (builder.build_led (button->led(), ls));
491         } else {
492                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", name));
493         }
494 }
495
496 void 
497 MackieControlProtocol::update_global_led (const string & name, LedState ls)
498 {
499         if (surface().controls_by_name.find (name) != surface().controls_by_name.end()) {
500                 Led * led = dynamic_cast<Led*> (surface().controls_by_name[name]);
501                 mcu_port().write (builder.build_led (*led, ls));
502         } else {
503                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", name));
504         }
505 }
506
507 // send messages to surface to set controls to correct values
508 void 
509 MackieControlProtocol::update_surface()
510 {
511         if (!_active) {
512                 return;
513         }
514
515         // do the initial bank switch to connect signals
516         // _current_initial_bank is initialised by set_state
517         switch_banks (_current_initial_bank);
518         
519         /* Create a RouteSignal for the master route, if we don't already have one */
520         if (!master_route_signal) {
521                 boost::shared_ptr<Route> mr = master_route ();
522                 if (mr) {
523                         master_route_signal = boost::shared_ptr<RouteSignal> (new RouteSignal (mr, *this, master_strip(), mcu_port()));
524                         // update strip from route
525                         master_route_signal->notify_all();
526                 }
527         }
528         
529         // sometimes the jog wheel is a pot
530         surface().blank_jog_ring (mcu_port(), builder);
531         
532         // update global buttons and displays
533         notify_record_state_changed();
534         notify_transport_state_changed();
535         update_timecode_beats_led();
536 }
537
538 void 
539 MackieControlProtocol::connect_session_signals()
540 {
541         // receive routes added
542         session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_route_added, this, _1), midi_ui_context());
543         // receive record state toggled
544         session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_record_state_changed, this), midi_ui_context());
545         // receive transport state changed
546         session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), midi_ui_context());
547         // receive punch-in and punch-out
548         Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
549         session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
550         // receive rude solo changed
551         session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), midi_ui_context());
552
553         // make sure remote id changed signals reach here
554         // see also notify_route_added
555         Sorted sorted = get_sorted_routes();
556
557         for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
558                 (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
559         }
560 }
561
562 void 
563 MackieControlProtocol::add_port (MIDI::Port & midi_input_port, MIDI::Port & midi_output_port, int number, MackiePort::port_type_t port_type)
564 {
565         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("add port %1 %2\n", midi_input_port.name(), midi_output_port.name()));
566
567         MackiePort * sport = new MackiePort (*this, midi_input_port, midi_output_port, number, port_type);
568         _ports.push_back (sport);
569         
570         sport->init_event.connect_same_thread (port_connections, boost::bind (&MackieControlProtocol::handle_port_init, this, sport));
571         sport->active_event.connect_same_thread (port_connections, boost::bind (&MackieControlProtocol::handle_port_active, this, sport));
572         sport->inactive_event.connect_same_thread (port_connections, boost::bind (&MackieControlProtocol::handle_port_inactive, this, sport));
573
574         _input_bundle->add_channel (
575                 midi_input_port.name(),
576                 ARDOUR::DataType::MIDI,
577                 session->engine().make_port_name_non_relative (midi_input_port.name())
578                 );
579         
580         _output_bundle->add_channel (
581                 midi_output_port.name(),
582                 ARDOUR::DataType::MIDI,
583                 session->engine().make_port_name_non_relative (midi_output_port.name())
584                 );
585 }
586
587 void 
588 MackieControlProtocol::create_ports()
589 {
590         MIDI::Manager * mm = MIDI::Manager::instance();
591         MIDI::Port * midi_input_port = mm->add_port (
592                 new MIDI::Port (string_compose (_("%1 in"), default_port_name), MIDI::Port::IsInput, session->engine().jack())
593                 );
594         MIDI::Port * midi_output_port = mm->add_port (
595                 new MIDI::Port (string_compose (_("%1 out"), default_port_name), MIDI::Port::IsOutput, session->engine().jack())
596                 );
597
598         /* Create main port */
599
600         if (!midi_input_port->ok() || !midi_output_port->ok()) {
601                 ostringstream os;
602                 os << _("Mackie control MIDI ports could not be created; Mackie control disabled");
603                 error << os.str() << endmsg;
604                 throw MackieControlException (os.str());
605         }
606
607         add_port (*midi_input_port, *midi_output_port, 0, MackiePort::mcu);
608
609         /* Create extender ports */
610
611         for (uint32_t index = 1; index <= Config->get_mackie_extenders(); ++index) {
612                 MIDI::Port * midi_input_port = mm->add_port (
613                         new MIDI::Port (string_compose (_("mcu_xt_%1 in"), index), MIDI::Port::IsInput, session->engine().jack())
614                         );
615                 MIDI::Port * midi_output_port = mm->add_port (
616                         new MIDI::Port (string_compose (_("mcu_xt_%1 out"), index), MIDI::Port::IsOutput, session->engine().jack())
617                         );
618                 if (midi_input_port->ok() && midi_output_port->ok()) {
619                         add_port (*midi_input_port, *midi_output_port, index, MackiePort::ext);
620                 }
621         }
622 }
623
624 boost::shared_ptr<Route> 
625 MackieControlProtocol::master_route()
626 {
627         return session->master_out ();
628 }
629
630 Strip& 
631 MackieControlProtocol::master_strip()
632 {
633         return dynamic_cast<Strip&> (*surface().groups["master"]);
634 }
635
636 void 
637 MackieControlProtocol::initialize_surface()
638 {
639         // set up the route table
640         int strips = 0;
641         for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
642                 strips += (*it)->strips();
643         }
644
645         set_route_table_size (strips);
646
647         // TODO same as code in mackie_port.cc
648         string emulation = ARDOUR::Config->get_mackie_emulation();
649         if (emulation == "bcf") {
650                 _surface = new BcfSurface (strips);
651         } else if (emulation == "mcu") {
652                 _surface = new MackieSurface (strips);
653         } else {
654                 ostringstream os;
655                 os << "no Surface class found for emulation: " << emulation;
656                 throw MackieControlException (os.str());
657         }
658
659         _surface->init();
660 }
661
662 void 
663 MackieControlProtocol::close()
664 {
665
666         // must be before other shutdown otherwise polling loop
667         // calls methods on objects that are deleted
668
669         port_connections.drop_connections ();
670         session_connections.drop_connections ();
671         route_connections.drop_connections ();
672
673         if (_surface != 0) {
674                 // These will fail if the port has gone away.
675                 // So catch the exception and do the rest of the
676                 // close afterwards
677                 // because the bcf doesn't respond to the next 3 sysex messages
678                 try {
679                         zero_all();
680                 }
681
682                 catch (exception & e) {
683                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::close caught exception: %1\n", e.what()));
684                 }
685
686                 for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
687                         try {
688                                 MackiePort & port = **it;
689                                 // faders to minimum
690                                 port.write_sysex (0x61);
691                                 // All LEDs off
692                                 port.write_sysex (0x62);
693                                 // Reset (reboot into offline mode)
694                                 port.write_sysex (0x63);
695                         }
696                         catch (exception & e) {
697                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::close caught exception: %1\n", e.what()));
698                         }
699                 }
700
701                 // disconnect routes from strips
702                 clear_route_signals();
703                 delete _surface;
704                 _surface = 0;
705         }
706
707         // shut down MackiePorts
708         for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
709                 delete *it;
710         }
711
712         _ports.clear();
713 }
714
715 XMLNode& 
716 MackieControlProtocol::get_state()
717 {
718         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state\n");
719
720         // add name of protocol
721         XMLNode* node = new XMLNode (X_("Protocol"));
722         node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
723
724         // add current bank
725         ostringstream os;
726         os << _current_initial_bank;
727         node->add_property (X_("bank"), os.str());
728
729         return *node;
730 }
731
732 int 
733 MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
734 {
735         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
736
737         int retval = 0;
738
739         // fetch current bank
740
741         if (node.property (X_("bank")) != 0) {
742                 string bank = node.property (X_("bank"))->value();
743                 try {
744                         set_active (true);
745                         uint32_t new_bank = atoi (bank.c_str());
746                         if (_current_initial_bank != new_bank) {
747                                 switch_banks (new_bank);
748                         }
749                 }
750                 catch (exception & e) {
751                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("exception in MackieControlProtocol::set_state: %1\n", e.what()));
752                         return -1;
753                 }
754         }
755
756         return retval;
757 }
758
759 void 
760 MackieControlProtocol::handle_control_event (SurfacePort & port, Control & control, const ControlState & state)
761 {
762         // find the route for the control, if there is one
763         boost::shared_ptr<Route> route;
764
765         if (control.group().is_strip()) {
766                 if (control.group().is_master()) {
767                         DEBUG_TRACE (DEBUG::MackieControl, "master strip control event\n");
768                         route = master_route();
769                 } else {
770                         uint32_t index = control.ordinal() - 1 + (port.number() * port.strips());
771                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip control event, index = %1, rt size = %2\n",
772                                                                            index, route_table.size()));
773                         if (index < route_table.size()) {
774                                 route = route_table[index];
775                                 if (route) {
776                                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("modifying %1\n", route->name()));
777                                 } else {
778                                         DEBUG_TRACE (DEBUG::MackieControl, "no route found!\n");
779                                 }
780                         } else {
781                                 cerr << "Warning: index is " << index << " which is not in the route table, size: " << route_table.size() << endl;
782                                 DEBUG_TRACE (DEBUG::MackieControl, "illegal route index found!\n");
783                         }
784                 }
785         }
786
787         // This handles control element events from the surface
788         // the state of the controls on the surface is usually updated
789         // from UI events.
790         switch (control.type()) {
791                 case Control::type_fader:
792                         // find the route in the route table for the id
793                         // if the route isn't available, skip it
794                         // at which point the fader should just reset itself
795                         if (route != 0)
796                         {
797                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", state.pos));
798
799                                 route->gain_control()->set_value (slider_position_to_gain (state.pos));
800
801                                 if (ARDOUR::Config->get_mackie_emulation() == "bcf") {
802                                         /* reset the timeout while we're still moving the fader */
803                                         port.add_in_use_timeout (control, control.in_use_touch_control);
804                                 }
805
806                                 // must echo bytes back to slider now, because
807                                 // the notifier only works if the fader is not being
808                                 // touched. Which it is if we're getting input.
809                                 port.write (builder.build_fader ((Fader&)control, state.pos));
810                         }
811                         break;
812
813                 case Control::type_button:
814                         if (control.group().is_strip()) {
815                                 // strips
816                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip button %1\n", control.id()));
817                                 if (route != 0) {
818                                         handle_strip_button (port, control, state.button_state, route);
819                                 } else {
820                                         // no route so always switch the light off
821                                         // because no signals will be emitted by a non-route
822                                         port.write (builder.build_led (control.led(), off));
823                                 }
824                         } else if (control.group().is_master()) {
825                                 // master fader touch
826                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("master strip button %1\n", control.id()));
827                                 if (route != 0) {
828                                         handle_strip_button (port, control, state.button_state, route);
829                                 }
830                         } else {
831                                 // handle all non-strip buttons
832                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("global button %1\n", control.id()));
833                                 surface().handle_button (*this, state.button_state, dynamic_cast<Button&> (control));
834                         }
835                         break;
836
837                 // pot (jog wheel, external control)
838                 case Control::type_pot:
839                         if (control.group().is_strip()) {
840                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip pot %1\n", control.id()));
841                                 if (route) {
842                                         boost::shared_ptr<Panner> panner = route->panner_shell()->panner();
843                                         // pan for mono input routes, or stereo linked panners
844                                         if (panner) {
845                                                 double p = panner->position ();
846                                                 
847                                                 // calculate new value, and adjust
848                                                 p += state.delta * state.sign;
849                                                 p = min (1.0, p);
850                                                 p = max (0.0, p);
851                                                 panner->set_position (p);
852                                         }
853                                 } else {
854                                         // it's a pot for an umnapped route, so turn all the lights off
855                                         port.write (builder.build_led_ring (dynamic_cast<Pot &> (control), off));
856                                 }
857                         } else {
858                                 if (control.is_jog()) {
859                                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", state.ticks));
860                                         _jog_wheel.jog_event (port, control, state);
861                                 } else {
862                                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("External controller moved %1\n", state.ticks));
863                                         cout << "external controller" << state.ticks * state.sign << endl;
864                                 }
865                         }
866                         break;
867
868                 default:
869                         cout << "Control::type not handled: " << control.type() << endl;
870         }
871 }
872
873 /////////////////////////////////////////////////
874 // handlers for Route signals
875 // TODO should these be part of RouteSignal?
876 // They started off as signal/slot handlers for signals
877 // from Route, but they're also used in polling for automation
878 /////////////////////////////////////////////////
879
880 void 
881 MackieControlProtocol::notify_solo_changed (RouteSignal * route_signal)
882 {
883         try {
884                 Button & button = route_signal->strip().solo();
885                 route_signal->port().write (builder.build_led (button, route_signal->route()->soloed()));
886         }
887         catch (exception & e) {
888                 cout << e.what() << endl;
889         }
890 }
891
892 void 
893 MackieControlProtocol::notify_mute_changed (RouteSignal * route_signal)
894 {
895         try {
896                 Button & button = route_signal->strip().mute();
897                 route_signal->port().write (builder.build_led (button, route_signal->route()->muted()));
898         }
899         catch (exception & e) {
900                 cout << e.what() << endl;
901         }
902 }
903
904 void 
905 MackieControlProtocol::notify_record_enable_changed (RouteSignal * route_signal)
906 {
907         try {
908                 Button & button = route_signal->strip().recenable();
909                 route_signal->port().write (builder.build_led (button, route_signal->route()->record_enabled()));
910         }
911         catch (exception & e) {
912                 cout << e.what() << endl;
913         }
914 }
915
916 void MackieControlProtocol::notify_active_changed (RouteSignal *)
917 {
918         try {
919                 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::notify_active_changed\n");
920                 refresh_current_bank();
921         }
922         catch (exception & e) {
923                 cout << e.what() << endl;
924         }
925 }
926
927 void 
928 MackieControlProtocol::notify_gain_changed (RouteSignal * route_signal, bool force_update)
929 {
930         try {
931                 Fader & fader = route_signal->strip().gain();
932                 if (!fader.in_use()) {
933                         float gain_value = gain_to_slider_position (route_signal->route()->gain_control()->get_value());
934                         // check that something has actually changed
935                         if (force_update || gain_value != route_signal->last_gain_written()) {
936                                 route_signal->port().write (builder.build_fader (fader, gain_value));
937                                 route_signal->last_gain_written (gain_value);
938                         }
939                 }
940         }
941         catch (exception & e) {
942                 cout << e.what() << endl;
943         }
944 }
945
946 void 
947 MackieControlProtocol::notify_property_changed (const PropertyChange& what_changed, RouteSignal * route_signal)
948 {
949         if (!what_changed.contains (Properties::name)) {
950                 return;
951         }
952
953         try {
954                 Strip & strip = route_signal->strip();
955                 
956                 if (!strip.is_master()) {
957                         string line1;
958                         string fullname = route_signal->route()->name();
959
960                         if (fullname.length() <= 6) {
961                                 line1 = fullname;
962                         } else {
963                                 line1 = PBD::short_version (fullname, 6);
964                         }
965
966 #ifdef NUCLEUS_DEBUG
967                         cerr << "show strip name from " << fullname << " as " << line1 << endl;
968 #endif
969
970                         SurfacePort & port = route_signal->port();
971                         port.write (builder.strip_display (port, strip, 0, line1));
972                         port.write (builder.strip_display_blank (port, strip, 1));
973                 }
974         }
975         catch (exception & e) {
976                 cout << e.what() << endl;
977         }
978 }
979
980 void 
981 MackieControlProtocol::notify_panner_changed (RouteSignal * route_signal, bool force_update)
982 {
983         try {
984                 Pot & pot = route_signal->strip().vpot();
985                 boost::shared_ptr<Panner> panner = route_signal->route()->panner();
986                 if (panner) {
987                         double pos = panner->position ();
988
989                         // cache the MidiByteArray here, because the mackie led control is much lower
990                         // resolution than the panner control. So we save lots of byte
991                         // sends in spite of more work on the comparison
992                         MidiByteArray bytes = builder.build_led_ring (pot, ControlState (on, pos), MackieMidiBuilder::midi_pot_mode_dot);
993                         // check that something has actually changed
994                         if (force_update || bytes != route_signal->last_pan_written())
995                         {
996                                 route_signal->port().write (bytes);
997                                 route_signal->last_pan_written (bytes);
998                         }
999                 } else {
1000                         route_signal->port().write (builder.zero_control (pot));
1001                 }
1002         }
1003         catch (exception & e) {
1004                 cout << e.what() << endl;
1005         }
1006 }
1007
1008 // TODO handle plugin automation polling
1009 void 
1010 MackieControlProtocol::update_automation (RouteSignal & rs)
1011 {
1012         ARDOUR::AutoState gain_state = rs.route()->gain_control()->automation_state();
1013
1014         if (gain_state == Touch || gain_state == Play) {
1015                 notify_gain_changed (&rs, false);
1016         }
1017
1018         if (rs.route()->panner()) {
1019                 ARDOUR::AutoState panner_state = rs.route()->panner()->automation_state();
1020                 if (panner_state == Touch || panner_state == Play) {
1021                         notify_panner_changed (&rs, false);
1022                 }
1023         }
1024 }
1025
1026 string 
1027 MackieControlProtocol::format_bbt_timecode (framepos_t now_frame)
1028 {
1029         Timecode::BBT_Time bbt_time;
1030         session->bbt_time (now_frame, bbt_time);
1031
1032         // According to the Logic docs
1033         // digits: 888/88/88/888
1034         // BBT mode: Bars/Beats/Subdivisions/Ticks
1035         ostringstream os;
1036         os << setw(3) << setfill('0') << bbt_time.bars;
1037         os << setw(2) << setfill('0') << bbt_time.beats;
1038
1039         // figure out subdivisions per beat
1040         const Meter & meter = session->tempo_map().meter_at (now_frame);
1041         int subdiv = 2;
1042         if (meter.note_divisor() == 8 && (meter.divisions_per_bar() == 12.0 || meter.divisions_per_bar() == 9.0 || meter.divisions_per_bar() == 6.0)) {
1043                 subdiv = 3;
1044         }
1045
1046         uint32_t subdivisions = bbt_time.ticks / uint32_t (Timecode::BBT_Time::ticks_per_beat / subdiv);
1047         uint32_t ticks = bbt_time.ticks % uint32_t (Timecode::BBT_Time::ticks_per_beat / subdiv);
1048
1049         os << setw(2) << setfill('0') << subdivisions + 1;
1050         os << setw(3) << setfill('0') << ticks;
1051
1052         return os.str();
1053 }
1054
1055 string 
1056 MackieControlProtocol::format_timecode_timecode (framepos_t now_frame)
1057 {
1058         Timecode::Time timecode;
1059         session->timecode_time (now_frame, timecode);
1060
1061         // According to the Logic docs
1062         // digits: 888/88/88/888
1063         // Timecode mode: Hours/Minutes/Seconds/Frames
1064         ostringstream os;
1065         os << setw(3) << setfill('0') << timecode.hours;
1066         os << setw(2) << setfill('0') << timecode.minutes;
1067         os << setw(2) << setfill('0') << timecode.seconds;
1068         os << setw(3) << setfill('0') << timecode.frames;
1069
1070         return os.str();
1071 }
1072
1073 void 
1074 MackieControlProtocol::update_timecode_display()
1075 {
1076         if (surface().has_timecode_display()) {
1077                 // do assignment here so current_frame is fixed
1078                 framepos_t current_frame = session->transport_frame();
1079                 string timecode;
1080
1081                 switch (_timecode_type) {
1082                         case ARDOUR::AnyTime::BBT:
1083                                 timecode = format_bbt_timecode (current_frame);
1084                                 break;
1085                         case ARDOUR::AnyTime::Timecode:
1086                                 timecode = format_timecode_timecode (current_frame);
1087                                 break;
1088                         default:
1089                                 ostringstream os;
1090                                 os << "Unknown timecode: " << _timecode_type;
1091                                 throw runtime_error (os.str());
1092                 }
1093
1094                 // only write the timecode string to the MCU if it's changed
1095                 // since last time. This is to reduce midi bandwidth used.
1096                 if (timecode != _timecode_last) {
1097                         surface().display_timecode (mcu_port(), builder, timecode, _timecode_last);
1098                         _timecode_last = timecode;
1099                 }
1100         }
1101 }
1102
1103 void 
1104 MackieControlProtocol::poll_session_data()
1105 {
1106         // XXX need to attach this to a timer in the MIDI UI event loop (20msec)
1107
1108         if (_active) {
1109                 // do all currently mapped routes
1110                 for (RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it) {
1111                         update_automation (**it);
1112                 }
1113
1114                 // and the master strip
1115                 if (master_route_signal != 0) {
1116                         update_automation (*master_route_signal);
1117                 }
1118
1119                 update_timecode_display();
1120         }
1121 }
1122
1123 /////////////////////////////////////
1124 // Transport Buttons
1125 /////////////////////////////////////
1126
1127 LedState 
1128 MackieControlProtocol::frm_left_press (Button &)
1129 {
1130         // can use first_mark_before/after as well
1131         unsigned long elapsed = _frm_left_last.restart();
1132
1133         Location * loc = session->locations()->first_location_before (
1134                 session->transport_frame()
1135         );
1136
1137         // allow a quick double to go past a previous mark
1138         if (session->transport_rolling() && elapsed < 500 && loc != 0) {
1139                 Location * loc_two_back = session->locations()->first_location_before (loc->start());
1140                 if (loc_two_back != 0)
1141                 {
1142                         loc = loc_two_back;
1143                 }
1144         }
1145
1146         // move to the location, if it's valid
1147         if (loc != 0) {
1148                 session->request_locate (loc->start(), session->transport_rolling());
1149         }
1150
1151         return on;
1152 }
1153
1154 LedState 
1155 MackieControlProtocol::frm_left_release (Button &)
1156 {
1157         return off;
1158 }
1159
1160 LedState 
1161 MackieControlProtocol::frm_right_press (Button &)
1162 {
1163         // can use first_mark_before/after as well
1164         Location * loc = session->locations()->first_location_after (session->transport_frame());
1165         
1166         if (loc != 0) {
1167                 session->request_locate (loc->start(), session->transport_rolling());
1168         }
1169                 
1170         return on;
1171 }
1172
1173 LedState 
1174 MackieControlProtocol::frm_right_release (Button &)
1175 {
1176         return off;
1177 }
1178
1179 LedState 
1180 MackieControlProtocol::stop_press (Button &)
1181 {
1182         session->request_stop();
1183         return on;
1184 }
1185
1186 LedState 
1187 MackieControlProtocol::stop_release (Button &)
1188 {
1189         return session->transport_stopped();
1190 }
1191
1192 LedState 
1193 MackieControlProtocol::play_press (Button &)
1194 {
1195         session->request_transport_speed (1.0);
1196         return on;
1197 }
1198
1199 LedState 
1200 MackieControlProtocol::play_release (Button &)
1201 {
1202         return session->transport_rolling();
1203 }
1204
1205 LedState 
1206 MackieControlProtocol::record_press (Button &)
1207 {
1208         if (session->get_record_enabled()) {
1209                 session->disable_record (false);
1210         } else {
1211                 session->maybe_enable_record();
1212         }
1213         return on;
1214 }
1215
1216 LedState 
1217 MackieControlProtocol::record_release (Button &)
1218 {
1219         if (session->get_record_enabled()) {
1220                 if (session->transport_rolling()) {
1221                         return on;
1222                 } else {
1223                         return flashing;
1224                 }
1225         } else {
1226                 return off;
1227         }
1228 }
1229
1230 LedState 
1231 MackieControlProtocol::rewind_press (Button &)
1232 {
1233         _jog_wheel.push (JogWheel::speed);
1234         _jog_wheel.transport_direction (-1);
1235         session->request_transport_speed (-_jog_wheel.transport_speed());
1236         return on;
1237 }
1238
1239 LedState 
1240 MackieControlProtocol::rewind_release (Button &)
1241 {
1242         _jog_wheel.pop();
1243         _jog_wheel.transport_direction (0);
1244         if (_transport_previously_rolling) {
1245                 session->request_transport_speed (1.0);
1246         } else {
1247                 session->request_stop();
1248         }
1249         return off;
1250 }
1251
1252 LedState 
1253 MackieControlProtocol::ffwd_press (Button &)
1254 {
1255         _jog_wheel.push (JogWheel::speed);
1256         _jog_wheel.transport_direction (1);
1257         session->request_transport_speed (_jog_wheel.transport_speed());
1258         return on;
1259 }
1260
1261 LedState 
1262 MackieControlProtocol::ffwd_release (Button &)
1263 {
1264         _jog_wheel.pop();
1265         _jog_wheel.transport_direction (0);
1266         if (_transport_previously_rolling) {
1267                 session->request_transport_speed (1.0);
1268         } else {
1269                 session->request_stop();
1270         }
1271         return off;
1272 }
1273
1274 LedState 
1275 MackieControlProtocol::loop_press (Button &)
1276 {
1277         session->request_play_loop (!session->get_play_loop());
1278         return on;
1279 }
1280
1281 LedState 
1282 MackieControlProtocol::loop_release (Button &)
1283 {
1284         return session->get_play_loop();
1285 }
1286
1287 LedState 
1288 MackieControlProtocol::punch_in_press (Button &)
1289 {
1290         bool const state = !session->config.get_punch_in();
1291         session->config.set_punch_in (state);
1292         return state;
1293 }
1294
1295 LedState 
1296 MackieControlProtocol::punch_in_release (Button &)
1297 {
1298         return session->config.get_punch_in();
1299 }
1300
1301 LedState 
1302 MackieControlProtocol::punch_out_press (Button &)
1303 {
1304         bool const state = !session->config.get_punch_out();
1305         session->config.set_punch_out (state);
1306         return state;
1307 }
1308
1309 LedState 
1310 MackieControlProtocol::punch_out_release (Button &)
1311 {
1312         return session->config.get_punch_out();
1313 }
1314
1315 LedState 
1316 MackieControlProtocol::home_press (Button &)
1317 {
1318         session->goto_start();
1319         return on;
1320 }
1321
1322 LedState 
1323 MackieControlProtocol::home_release (Button &)
1324 {
1325         return off;
1326 }
1327
1328 LedState 
1329 MackieControlProtocol::end_press (Button &)
1330 {
1331         session->goto_end();
1332         return on;
1333 }
1334
1335 LedState 
1336 MackieControlProtocol::end_release (Button &)
1337 {
1338         return off;
1339 }
1340
1341 LedState 
1342 MackieControlProtocol::clicking_press (Button &)
1343 {
1344         bool state = !Config->get_clicking();
1345         Config->set_clicking (state);
1346         return state;
1347 }
1348
1349 LedState 
1350 MackieControlProtocol::clicking_release (Button &)
1351 {
1352         return Config->get_clicking();
1353 }
1354
1355 LedState MackieControlProtocol::global_solo_press (Button &)
1356 {
1357         bool state = !session->soloing();
1358         session->set_solo (session->get_routes(), state);
1359         return state;
1360 }
1361
1362 LedState MackieControlProtocol::global_solo_release (Button &)
1363 {
1364         return session->soloing();
1365 }
1366
1367 ///////////////////////////////////////////
1368 // Session signals
1369 ///////////////////////////////////////////
1370
1371 void MackieControlProtocol::notify_parameter_changed (std::string const & p)
1372 {
1373         if (p == "punch-in") {
1374                 update_global_button ("punch_in", session->config.get_punch_in());
1375         } else if (p == "punch-out") {
1376                 update_global_button ("punch_out", session->config.get_punch_out());
1377         } else if (p == "clicking") {
1378                 update_global_button ("clicking", Config->get_clicking());
1379         } else {
1380                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
1381         }
1382 }
1383
1384 // RouteList is the set of routes that have just been added
1385 void 
1386 MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
1387 {
1388         // currently assigned banks are less than the full set of
1389         // strips, so activate the new strip now.
1390         if (route_signals.size() < route_table.size()) {
1391                 refresh_current_bank();
1392         }
1393         // otherwise route added, but current bank needs no updating
1394
1395         // make sure remote id changes in the new route are handled
1396         typedef ARDOUR::RouteList ARS;
1397
1398         for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
1399                 (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
1400         }
1401 }
1402
1403 void 
1404 MackieControlProtocol::notify_solo_active_changed (bool active)
1405 {
1406         Button * rude_solo = reinterpret_cast<Button*> (surface().controls_by_name["solo"]);
1407         mcu_port().write (builder.build_led (*rude_solo, active ? flashing : off));
1408 }
1409
1410 void 
1411 MackieControlProtocol::notify_remote_id_changed()
1412 {
1413         Sorted sorted = get_sorted_routes();
1414
1415         // if a remote id has been moved off the end, we need to shift
1416         // the current bank backwards.
1417         if (sorted.size() - _current_initial_bank < route_signals.size()) {
1418                 // but don't shift backwards past the zeroth channel
1419                 switch_banks (max((Sorted::size_type) 0, sorted.size() - route_signals.size()));
1420         } else {
1421                 // Otherwise just refresh the current bank
1422                 refresh_current_bank();
1423         }
1424 }
1425
1426 ///////////////////////////////////////////
1427 // Transport signals
1428 ///////////////////////////////////////////
1429
1430 void 
1431 MackieControlProtocol::notify_record_state_changed()
1432 {
1433         // switch rec button on / off / flashing
1434         Button * rec = reinterpret_cast<Button*> (surface().controls_by_name["record"]);
1435         mcu_port().write (builder.build_led (*rec, record_release (*rec)));
1436 }
1437
1438 void 
1439 MackieControlProtocol::notify_transport_state_changed()
1440 {
1441         // switch various play and stop buttons on / off
1442         update_global_button ("play", session->transport_rolling());
1443         update_global_button ("stop", !session->transport_rolling());
1444         update_global_button ("loop", session->get_play_loop());
1445
1446         _transport_previously_rolling = session->transport_rolling();
1447
1448         // rec is special because it's tristate
1449         Button * rec = reinterpret_cast<Button*> (surface().controls_by_name["record"]);
1450         mcu_port().write (builder.build_led (*rec, record_release (*rec)));
1451 }
1452
1453 /////////////////////////////////////
1454 // Bank Switching
1455 /////////////////////////////////////
1456 LedState 
1457 MackieControlProtocol::left_press (Button &)
1458 {
1459         Sorted sorted = get_sorted_routes();
1460         if (sorted.size() > route_table.size()) {
1461                 int new_initial = _current_initial_bank - route_table.size();
1462                 if (new_initial < 0) {
1463                         new_initial = 0;
1464                 }
1465                 
1466                 if (new_initial != int (_current_initial_bank)) {
1467                         session->set_dirty();
1468                         switch_banks (new_initial);
1469                 }
1470
1471                 return on;
1472         } else {
1473                 return flashing;
1474         }
1475 }
1476
1477 LedState 
1478 MackieControlProtocol::left_release (Button &)
1479 {
1480         return off;
1481 }
1482
1483 LedState 
1484 MackieControlProtocol::right_press (Button &)
1485 {
1486         Sorted sorted = get_sorted_routes();
1487         if (sorted.size() > route_table.size()) {
1488                 uint32_t delta = sorted.size() - (route_table.size() + _current_initial_bank);
1489
1490                 if (delta > route_table.size()) {
1491                         delta = route_table.size();
1492                 }
1493                 
1494                 if (delta > 0) {
1495                         session->set_dirty();
1496                         switch_banks (_current_initial_bank + delta);
1497                 }
1498
1499                 return on;
1500         } else {
1501                 return flashing;
1502         }
1503 }
1504
1505 LedState 
1506 MackieControlProtocol::right_release (Button &)
1507 {
1508         return off;
1509 }
1510
1511 LedState 
1512 MackieControlProtocol::channel_left_press (Button &)
1513 {
1514         Sorted sorted = get_sorted_routes();
1515         if (sorted.size() > route_table.size()) {
1516                 prev_track();
1517                 return on;
1518         } else {
1519                 return flashing;
1520         }
1521 }
1522
1523 LedState 
1524 MackieControlProtocol::channel_left_release (Button &)
1525 {
1526         return off;
1527 }
1528
1529 LedState 
1530 MackieControlProtocol::channel_right_press (Button &)
1531 {
1532         Sorted sorted = get_sorted_routes();
1533         if (sorted.size() > route_table.size()) {
1534                 next_track();
1535                 return on;
1536         } else {
1537                 return flashing;
1538         }
1539 }
1540
1541 LedState 
1542 MackieControlProtocol::channel_right_release (Button &)
1543 {
1544         return off;
1545 }
1546
1547 /////////////////////////////////////
1548 // Functions
1549 /////////////////////////////////////
1550 LedState 
1551 MackieControlProtocol::marker_press (Button &)
1552 {
1553         // cut'n'paste from LocationUI::add_new_location()
1554         string markername;
1555         framepos_t where = session->audible_frame();
1556         session->locations()->next_available_name(markername,"mcu");
1557         Location *location = new Location (*session, where, where, markername, Location::IsMark);
1558         session->begin_reversible_command (_("add marker"));
1559         XMLNode &before = session->locations()->get_state();
1560         session->locations()->add (location, true);
1561         XMLNode &after = session->locations()->get_state();
1562         session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
1563         session->commit_reversible_command ();
1564         return on;
1565 }
1566
1567 LedState 
1568 MackieControlProtocol::marker_release (Button &)
1569 {
1570         return off;
1571 }
1572
1573 void 
1574 jog_wheel_state_display (JogWheel::State state, SurfacePort & port)
1575 {
1576         switch (state) {
1577                 case JogWheel::zoom:
1578                         port.write (builder.two_char_display ("Zm"));
1579                         break;
1580                 case JogWheel::scroll:
1581                         port.write (builder.two_char_display ("Sc"));
1582                         break;
1583                 case JogWheel::scrub:
1584                         port.write (builder.two_char_display ("Sb"));
1585                         break;
1586                 case JogWheel::shuttle:
1587                         port.write (builder.two_char_display ("Sh"));
1588                         break;
1589                 case JogWheel::speed:
1590                         port.write (builder.two_char_display ("Sp"));
1591                         break;
1592                 case JogWheel::select:
1593                         port.write (builder.two_char_display ("Se"));
1594                         break;
1595         }
1596 }
1597
1598 Mackie::LedState 
1599 MackieControlProtocol::zoom_press (Mackie::Button &)
1600 {
1601         _jog_wheel.zoom_state_toggle();
1602         update_global_button ("scrub", _jog_wheel.jog_wheel_state() == JogWheel::scrub);
1603         jog_wheel_state_display (_jog_wheel.jog_wheel_state(), mcu_port());
1604         return _jog_wheel.jog_wheel_state() == JogWheel::zoom;
1605 }
1606
1607 Mackie::LedState 
1608 MackieControlProtocol::zoom_release (Mackie::Button &)
1609 {
1610         return _jog_wheel.jog_wheel_state() == JogWheel::zoom;
1611 }
1612
1613 Mackie::LedState 
1614 MackieControlProtocol::scrub_press (Mackie::Button &)
1615 {
1616         _jog_wheel.scrub_state_cycle();
1617         update_global_button ("zoom", _jog_wheel.jog_wheel_state() == JogWheel::zoom);
1618         jog_wheel_state_display (_jog_wheel.jog_wheel_state(), mcu_port());
1619         return (
1620                 _jog_wheel.jog_wheel_state() == JogWheel::scrub
1621                 ||
1622                 _jog_wheel.jog_wheel_state() == JogWheel::shuttle
1623                 );
1624 }
1625
1626 Mackie::LedState 
1627 MackieControlProtocol::scrub_release (Mackie::Button &)
1628 {
1629         return (
1630                 _jog_wheel.jog_wheel_state() == JogWheel::scrub
1631                 ||
1632                 _jog_wheel.jog_wheel_state() == JogWheel::shuttle
1633                 );
1634 }
1635
1636 LedState 
1637 MackieControlProtocol::drop_press (Button &)
1638 {
1639         session->remove_last_capture();
1640         return on;
1641 }
1642
1643 LedState 
1644 MackieControlProtocol::drop_release (Button &)
1645 {
1646         return off;
1647 }
1648
1649 LedState 
1650 MackieControlProtocol::save_press (Button &)
1651 {
1652         session->save_state ("");
1653         return on;
1654 }
1655
1656 LedState 
1657 MackieControlProtocol::save_release (Button &)
1658 {
1659         return off;
1660 }
1661
1662 LedState 
1663 MackieControlProtocol::timecode_beats_press (Button &)
1664 {
1665         switch (_timecode_type) {
1666         case ARDOUR::AnyTime::BBT:
1667                 _timecode_type = ARDOUR::AnyTime::Timecode;
1668                 break;
1669         case ARDOUR::AnyTime::Timecode:
1670                 _timecode_type = ARDOUR::AnyTime::BBT;
1671                 break;
1672         default:
1673                 ostringstream os;
1674                 os << "Unknown Anytime::Type " << _timecode_type;
1675                 throw runtime_error (os.str());
1676         }
1677         update_timecode_beats_led();
1678         return on;
1679 }
1680
1681 LedState 
1682 MackieControlProtocol::timecode_beats_release (Button &)
1683 {
1684         return off;
1685 }
1686
1687 list<boost::shared_ptr<ARDOUR::Bundle> >
1688 MackieControlProtocol::bundles ()
1689 {
1690         list<boost::shared_ptr<ARDOUR::Bundle> > b;
1691         b.push_back (_input_bundle);
1692         b.push_back (_output_bundle);
1693         return b;
1694 }
1695
1696 void
1697 MackieControlProtocol::port_connected_or_disconnected (string a, string b, bool connected)
1698 {
1699         /* If something is connected to one of our output ports, send MIDI to update the surface
1700            to whatever state it should have.
1701         */
1702
1703         if (!connected) {
1704                 return;
1705         }
1706
1707         MackiePorts::const_iterator i = _ports.begin();
1708         while (i != _ports.end()) {
1709
1710                 string const n = AudioEngine::instance()->make_port_name_non_relative ((*i)->output_port().name ());
1711
1712                 if (a == n || b == n) {
1713                         break;
1714                 }
1715
1716                 ++i;
1717         }
1718
1719         if (i != _ports.end ()) {
1720                 update_surface ();
1721         }
1722 }
1723
1724 void
1725 MackieControlProtocol::do_request (MackieControlUIRequest* req)
1726 {
1727         if (req->type == CallSlot) {
1728
1729                 call_slot (MISSING_INVALIDATOR, req->the_slot);
1730
1731         } else if (req->type == Quit) {
1732
1733                 stop ();
1734         }
1735 }
1736
1737 int
1738 MackieControlProtocol::stop ()
1739 {
1740         BaseUI::quit ();
1741
1742         return 0;
1743 }