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