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