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