Fix Mackie surface after port rework.
[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 #define __STDC_FORMAT_MACROS
28 #include <inttypes.h>
29 #include <float.h>
30 #include <sys/time.h>
31 #include <errno.h>
32 #include <poll.h>
33
34 #include <boost/shared_array.hpp>
35
36 #include "midi++/types.h"
37 #include "midi++/port.h"
38 #include "midi++/manager.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/error.h"
41 #include "pbd/memento_command.h"
42 #include "pbd/convert.h"
43
44 #include "ardour/dB.h"
45 #include "ardour/debug.h"
46 #include "ardour/location.h"
47 #include "ardour/midi_ui.h"
48 #include "ardour/panner.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 using boost::shared_ptr;
72
73 #include "i18n.h"
74
75 MackieMidiBuilder builder;
76
77 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
78 #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
79
80 MackieControlProtocol::MackieControlProtocol (Session& session)
81         : ControlProtocol (session, X_("Mackie"), MidiControlUI::instance())
82         , _current_initial_bank (0)
83         , _surface (0)
84         , _jog_wheel (*this)
85         , _timecode_type (ARDOUR::AnyTime::BBT)
86 {
87         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
88 }
89
90 MackieControlProtocol::~MackieControlProtocol()
91 {
92         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol\n");
93
94         try {
95                 close();
96         }
97         catch (exception & e) {
98                 cout << "~MackieControlProtocol caught " << e.what() << endl;
99         }
100         catch (...) {
101                 cout << "~MackieControlProtocol caught unknown" << endl;
102         }
103
104         DEBUG_TRACE (DEBUG::MackieControl, "finished ~MackieControlProtocol::MackieControlProtocol\n");
105 }
106
107 Mackie::Surface& 
108 MackieControlProtocol::surface()
109 {
110         if (_surface == 0) {
111                 throw MackieControlException ("_surface is 0 in MackieControlProtocol::surface");
112         }
113         return *_surface;
114 }
115
116 const Mackie::SurfacePort& 
117 MackieControlProtocol::mcu_port() const
118 {
119         if (_ports.size() < 1) {
120                 return _dummy_port;
121         } else {
122                 return dynamic_cast<const MackiePort &> (*_ports[0]);
123         }
124 }
125
126 Mackie::SurfacePort& 
127 MackieControlProtocol::mcu_port()
128 {
129         if (_ports.size() < 1) {
130                 return _dummy_port;
131         } else {
132                 return dynamic_cast<MackiePort &> (*_ports[0]);
133         }
134 }
135
136 // go to the previous track.
137 // Assume that get_sorted_routes().size() > route_table.size()
138 void 
139 MackieControlProtocol::prev_track()
140 {
141         if (_current_initial_bank >= 1) {
142                 session->set_dirty();
143                 switch_banks (_current_initial_bank - 1);
144         }
145 }
146
147 // go to the next track.
148 // Assume that get_sorted_routes().size() > route_table.size()
149 void 
150 MackieControlProtocol::next_track()
151 {
152         Sorted sorted = get_sorted_routes();
153         if (_current_initial_bank + route_table.size() < sorted.size())
154         {
155                 session->set_dirty();
156                 switch_banks (_current_initial_bank + 1);
157         }
158 }
159
160 void 
161 MackieControlProtocol::clear_route_signals()
162 {
163         for (RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it) {
164                 delete *it;
165         }
166         route_signals.clear();
167 }
168
169 // return the port for a given id - 0 based
170 // throws an exception if no port found
171 MackiePort& 
172 MackieControlProtocol::port_for_id (uint32_t index)
173 {
174         uint32_t current_max = 0;
175         for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
176                 current_max += (*it)->strips();
177                 if (index < current_max) return **it;
178         }
179
180         // oops - no matching port
181         ostringstream os;
182         os << "No port for index " << index;
183         throw MackieControlException (os.str());
184 }
185
186 // predicate for sort call in get_sorted_routes
187 struct RouteByRemoteId
188 {
189         bool operator () (const shared_ptr<Route> & a, const shared_ptr<Route> & b) const
190         {
191                 return a->remote_control_id() < b->remote_control_id();
192         }
193
194         bool operator () (const Route & a, const Route & b) const
195         {
196                 return a.remote_control_id() < b.remote_control_id();
197         }
198
199         bool operator () (const Route * a, const Route * b) const
200         {
201                 return a->remote_control_id() < b->remote_control_id();
202         }
203 };
204
205 MackieControlProtocol::Sorted 
206 MackieControlProtocol::get_sorted_routes()
207 {
208         Sorted sorted;
209
210         // fetch all routes
211         boost::shared_ptr<RouteList> routes = session->get_routes();
212         set<uint32_t> remote_ids;
213
214         // routes with remote_id 0 should never be added
215         // TODO verify this with ardour devs
216         // remote_ids.insert (0);
217
218         // sort in remote_id order, and exclude master, control and hidden routes
219         // and any routes that are already set.
220         for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it)
221         {
222                 Route & route = **it;
223                 if (
224                                 route.active()
225                                 && !route.is_master()
226                                 && !route.is_hidden()
227                                 && !route.is_monitor()
228                                 && remote_ids.find (route.remote_control_id()) == remote_ids.end()
229                 )
230                 {
231                         sorted.push_back (*it);
232                         remote_ids.insert (route.remote_control_id());
233                 }
234         }
235         sort (sorted.begin(), sorted.end(), RouteByRemoteId());
236         return sorted;
237 }
238
239 void 
240 MackieControlProtocol::refresh_current_bank()
241 {
242         switch_banks (_current_initial_bank);
243 }
244
245 void 
246 MackieControlProtocol::switch_banks (int initial)
247 {
248         // DON'T prevent bank switch if initial == _current_initial_bank
249         // because then this method can't be used as a refresh
250
251         // sanity checking
252         Sorted sorted = get_sorted_routes();
253         int delta = sorted.size() - route_table.size();
254         if (initial < 0 || (delta > 0 && initial > delta))
255         {
256                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
257                 return;
258         }
259         _current_initial_bank = initial;
260
261         // first clear the signals from old routes
262         // taken care of by the RouteSignal destructors
263         clear_route_signals();
264
265         // now set the signals for new routes
266         if (_current_initial_bank <= sorted.size())
267         {
268                 // fetch the bank start and end to switch to
269                 uint32_t end_pos = min (route_table.size(), sorted.size());
270                 Sorted::iterator it = sorted.begin() + _current_initial_bank;
271                 Sorted::iterator end = sorted.begin() + _current_initial_bank + end_pos;
272
273                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2\n", _current_initial_bank, end_pos));
274
275                 // link routes to strips
276                 uint32_t i = 0;
277                 for (; it != end && it != sorted.end(); ++it, ++i)
278                 {
279                         boost::shared_ptr<Route> route = *it;
280                         Strip & strip = *surface().strips[i];
281
282                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("remote id %1 connecting %2 to %3 with port %4\n", 
283                                                                            route->remote_control_id(), route->name(), strip.name(), port_for_id(i)));
284                         route_table[i] = route;
285                         RouteSignal * rs = new RouteSignal (route, *this, strip, port_for_id(i));
286                         route_signals.push_back (rs);
287                         // update strip from route
288                         rs->notify_all();
289                 }
290
291                 // create dead strips if there aren't enough routes to
292                 // fill a bank
293                 for (; i < route_table.size(); ++i)
294                 {
295                         Strip & strip = *surface().strips[i];
296                         // send zero for this strip
297                         MackiePort & port = port_for_id(i);
298                         port.write (builder.zero_strip (port, strip));
299                 }
300         }
301
302         // display the current start bank.
303         surface().display_bank_start (mcu_port(), builder, _current_initial_bank);
304 }
305
306 void 
307 MackieControlProtocol::zero_all()
308 {
309         // TODO turn off Timecode displays
310
311         // zero all strips
312         for (Surface::Strips::iterator it = surface().strips.begin(); it != surface().strips.end(); ++it)
313         {
314                 MackiePort & port = port_for_id ((*it)->index());
315                 port.write (builder.zero_strip (port, **it));
316         }
317
318         // and the master strip
319         mcu_port().write (builder.zero_strip (dynamic_cast<MackiePort&> (mcu_port()), master_strip()));
320
321         // turn off global buttons and leds
322         // global buttons are only ever on mcu_port, so we don't have
323         // to figure out which port.
324         for (Surface::Controls::iterator it = surface().controls.begin(); it != surface().controls.end(); ++it)
325         {
326                 Control & control = **it;
327                 if (!control.group().is_strip() && control.accepts_feedback())
328                 {
329                         mcu_port().write (builder.zero_control (control));
330                 }
331         }
332
333         // any hardware-specific stuff
334         surface().zero_all (mcu_port(), builder);
335 }
336
337 int 
338 MackieControlProtocol::set_active (bool yn)
339 {
340         if (yn != _active)
341         {
342                 try
343                 {
344                         // the reason for the locking and unlocking is that
345                         // glibmm can't do a condition wait on a RecMutex
346                         if (yn)
347                         {
348                                 // TODO what happens if this fails half way?
349
350                                 // create MackiePorts
351                                 {
352                                         Glib::Mutex::Lock lock (update_mutex);
353                                         create_ports();
354                                 }
355
356                                 // now initialise MackiePorts - ie exchange sysex messages
357                                 for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
358                                         (*it)->open();
359                                 }
360
361                                 // wait until all ports are active
362                                 // TODO a more sophisticated approach would
363                                 // allow things to start up with only an MCU, even if
364                                 // extenders were specified but not responding.
365                                 for (MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it) {
366                                         (*it)->wait_for_init();
367                                 }
368
369                                 // create surface object. This depends on the ports being
370                                 // correctly initialised
371                                 initialize_surface();
372                                 connect_session_signals();
373
374                                 // yeehah!
375                                 _active = true;
376
377                                 // send current control positions to surface
378                                 // must come after _active = true otherwise it won't run
379                                 update_surface();
380                         } else {
381                                 close();
382                                 _active = false;
383                         }
384                 }
385
386                 catch (exception & e) {
387                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
388                         _active = false;
389                         throw;
390                 }
391         }
392
393         return 0;
394 }
395
396 bool 
397 MackieControlProtocol::handle_strip_button (Control & control, ButtonState bs, boost::shared_ptr<Route> route)
398 {
399         bool state = false;
400
401         if (bs == press)
402         {
403                 if (control.name() == "recenable")
404                 {
405                         state = !route->record_enabled();
406                         route->set_record_enable (state, this);
407                 }
408                 else if (control.name() == "mute")
409                 {
410                         state = !route->muted();
411                         route->set_mute (state, this);
412                 }
413                 else if (control.name() == "solo")
414                 {
415                         state = !route->soloed();
416                         route->set_solo (state, this);
417                 }
418                 else if (control.name() == "select")
419                 {
420                         // TODO make the track selected. Whatever that means.
421                         //state = default_button_press (dynamic_cast<Button&> (control));
422                 }
423                 else if (control.name() == "vselect")
424                 {
425                         // TODO could be used to select different things to apply the pot to?
426                         //state = default_button_press (dynamic_cast<Button&> (control));
427                 }
428         }
429
430         if (control.name() == "fader_touch")
431         {
432                 state = bs == press;
433                 control.strip().gain().in_use (state);
434         }
435
436         return state;
437 }
438
439 void 
440 MackieControlProtocol::update_led (Mackie::Button & button, Mackie::LedState ls)
441 {
442         if (ls != none)
443         {
444                 SurfacePort * port = 0;
445                 if (button.group().is_strip())
446                 {
447                         if (button.group().is_master())
448                         {
449                                 port = &mcu_port();
450                         }
451                         else
452                         {
453                                 port = &port_for_id (dynamic_cast<const Strip&> (button.group()).index());
454                         }
455                 }
456                 else
457                 {
458                         port = &mcu_port();
459                 }
460                 port->write (builder.build_led (button, ls));
461         }
462 }
463
464 void 
465 MackieControlProtocol::update_timecode_beats_led()
466 {
467         switch (_timecode_type)
468         {
469                 case ARDOUR::AnyTime::BBT:
470                         update_global_led ("beats", on);
471                         update_global_led ("timecode", off);
472                         break;
473                 case ARDOUR::AnyTime::Timecode:
474                         update_global_led ("timecode", on);
475                         update_global_led ("beats", off);
476                         break;
477                 default:
478                         ostringstream os;
479                         os << "Unknown Anytime::Type " << _timecode_type;
480                         throw runtime_error (os.str());
481         }
482 }
483
484 void 
485 MackieControlProtocol::update_global_button (const string & name, LedState ls)
486 {
487         if (surface().controls_by_name.find (name) != surface().controls_by_name.end())
488         {
489                 Button * button = dynamic_cast<Button*> (surface().controls_by_name[name]);
490                 mcu_port().write (builder.build_led (button->led(), ls));
491         }
492         else
493         {
494                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", name));
495         }
496 }
497
498 void 
499 MackieControlProtocol::update_global_led (const string & name, LedState ls)
500 {
501         if (surface().controls_by_name.find (name) != surface().controls_by_name.end())
502         {
503                 Led * led = dynamic_cast<Led*> (surface().controls_by_name[name]);
504                 mcu_port().write (builder.build_led (*led, ls));
505         }
506         else
507         {
508                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", name));
509         }
510 }
511
512 // send messages to surface to set controls to correct values
513 void 
514 MackieControlProtocol::update_surface()
515 {
516         if (_active)
517         {
518                 // do the initial bank switch to connect signals
519                 // _current_initial_bank is initialised by set_state
520                 switch_banks (_current_initial_bank);
521
522                 // create a RouteSignal for the master route
523
524  boost::shared_ptr<Route> mr = master_route ();
525  if (mr) {
526  master_route_signal = shared_ptr<RouteSignal> (new RouteSignal (mr, *this, master_strip(), mcu_port()));
527  // update strip from route
528  master_route_signal->notify_all();
529  }
530
531                 // sometimes the jog wheel is a pot
532                 surface().blank_jog_ring (mcu_port(), builder);
533
534                 // update global buttons and displays
535                 notify_record_state_changed();
536                 notify_transport_state_changed();
537                 update_timecode_beats_led();
538         }
539 }
540
541 void 
542 MackieControlProtocol::connect_session_signals()
543 {
544         // receive routes added
545         session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_route_added, this, _1), midi_ui_context());
546         // receive record state toggled
547         session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_record_state_changed, this), midi_ui_context());
548         // receive transport state changed
549         session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), midi_ui_context());
550         // receive punch-in and punch-out
551         Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
552         session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
553         // receive rude solo changed
554         session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), midi_ui_context());
555
556         // make sure remote id changed signals reach here
557         // see also notify_route_added
558         Sorted sorted = get_sorted_routes();
559
560         for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
561                 (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
562         }
563 }
564
565 void 
566 MackieControlProtocol::add_port (MIDI::Port & midi_port, int number)
567 {
568         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("add port %1\n", midi_port.name()));
569
570         MackiePort * sport = new MackiePort (*this, midi_port, number);
571         _ports.push_back (sport);
572         
573         sport->init_event.connect_same_thread (port_connections, boost::bind (&MackieControlProtocol::handle_port_init, this, sport));
574         sport->active_event.connect_same_thread (port_connections, boost::bind (&MackieControlProtocol::handle_port_active, this, sport));
575         sport->inactive_event.connect_same_thread (port_connections, boost::bind (&MackieControlProtocol::handle_port_inactive, this, sport));
576 }
577
578 void 
579 MackieControlProtocol::create_ports()
580 {
581         MIDI::Manager * mm = MIDI::Manager::instance();
582         MIDI::Port * midi_port = mm->add_port (new MIDI::Port (default_port_name, O_RDWR, session->engine().jack()));
583
584         // open main port               
585
586         if (!midi_port->ok()) {
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->add_port (new MIDI::Port (os.str(), O_RDWR, session->engine().jack()));
604                 if (midi_port->ok()) {
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_same_thread (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_property_changed (const PropertyChange& what_changed, RouteSignal * route_signal)
946 {
947         if (!what_changed.contains (Properties::name)) {
948                 return;
949         }
950
951         try
952         {
953                 Strip & strip = route_signal->strip();
954                 if (!strip.is_master())
955                 {
956                         string line1;
957                         string fullname = route_signal->route()->name();
958
959                         if (fullname.length() <= 6)
960                         {
961                                 line1 = fullname;
962                         }
963                         else
964                         {
965                                 line1 = PBD::short_version (fullname, 6);
966                         }
967
968                         SurfacePort & port = route_signal->port();
969                         port.write (builder.strip_display (port, strip, 0, line1));
970                         port.write (builder.strip_display_blank (port, strip, 1));
971                 }
972         }
973         catch (exception & e)
974         {
975                 cout << e.what() << endl;
976         }
977 }
978
979 void 
980 MackieControlProtocol::notify_panner_changed (RouteSignal * route_signal, bool force_update)
981 {
982         try
983         {
984                 Pot & pot = route_signal->strip().vpot();
985                 boost::shared_ptr<Panner> panner = route_signal->route()->panner();
986                 if ((panner && panner->npanners() == 1) || (panner->npanners() == 2 && panner->linked()))
987                 {
988                         float pos;
989                         route_signal->route()->panner()->streampanner(0).get_effective_position (pos);
990
991                         // cache the MidiByteArray here, because the mackie led control is much lower
992                         // resolution than the panner control. So we save lots of byte
993                         // sends in spite of more work on the comparison
994                         MidiByteArray bytes = builder.build_led_ring (pot, ControlState (on, pos), MackieMidiBuilder::midi_pot_mode_dot);
995                         // check that something has actually changed
996                         if (force_update || bytes != route_signal->last_pan_written())
997                         {
998                                 route_signal->port().write (bytes);
999                                 route_signal->last_pan_written (bytes);
1000                         }
1001                 }
1002                 else
1003                 {
1004                         route_signal->port().write (builder.zero_control (pot));
1005                 }
1006         }
1007         catch (exception & e)
1008         {
1009                 cout << e.what() << endl;
1010         }
1011 }
1012
1013 // TODO handle plugin automation polling
1014 void 
1015 MackieControlProtocol::update_automation (RouteSignal & rs)
1016 {
1017         ARDOUR::AutoState gain_state = rs.route()->gain_control()->automation_state();
1018
1019         if (gain_state == Touch || gain_state == Play)
1020         {
1021                 notify_gain_changed (&rs, false);
1022         }
1023
1024         if (rs.route()->panner()) {
1025                 ARDOUR::AutoState panner_state = rs.route()->panner()->automation_state();
1026                 if (panner_state == Touch || panner_state == Play)
1027                 {
1028                         notify_panner_changed (&rs, false);
1029                 }
1030         }
1031 }
1032
1033 string 
1034 MackieControlProtocol::format_bbt_timecode (nframes_t now_frame)
1035 {
1036         BBT_Time bbt_time;
1037         session->bbt_time (now_frame, bbt_time);
1038
1039         // According to the Logic docs
1040         // digits: 888/88/88/888
1041         // BBT mode: Bars/Beats/Subdivisions/Ticks
1042         ostringstream os;
1043         os << setw(3) << setfill('0') << bbt_time.bars;
1044         os << setw(2) << setfill('0') << bbt_time.beats;
1045
1046         // figure out subdivisions per beat
1047         const Meter & meter = session->tempo_map().meter_at (now_frame);
1048         int subdiv = 2;
1049         if (meter.note_divisor() == 8 && (meter.beats_per_bar() == 12.0 || meter.beats_per_bar() == 9.0 || meter.beats_per_bar() == 6.0))
1050         {
1051                 subdiv = 3;
1052         }
1053
1054         uint32_t subdivisions = bbt_time.ticks / uint32_t (Meter::ticks_per_beat / subdiv);
1055         uint32_t ticks = bbt_time.ticks % uint32_t (Meter::ticks_per_beat / subdiv);
1056
1057         os << setw(2) << setfill('0') << subdivisions + 1;
1058         os << setw(3) << setfill('0') << ticks;
1059
1060         return os.str();
1061 }
1062
1063 string 
1064 MackieControlProtocol::format_timecode_timecode (nframes_t now_frame)
1065 {
1066         Timecode::Time timecode;
1067         session->timecode_time (now_frame, timecode);
1068
1069         // According to the Logic docs
1070         // digits: 888/88/88/888
1071         // Timecode mode: Hours/Minutes/Seconds/Frames
1072         ostringstream os;
1073         os << setw(3) << setfill('0') << timecode.hours;
1074         os << setw(2) << setfill('0') << timecode.minutes;
1075         os << setw(2) << setfill('0') << timecode.seconds;
1076         os << setw(3) << setfill('0') << timecode.frames;
1077
1078         return os.str();
1079 }
1080
1081 void 
1082 MackieControlProtocol::update_timecode_display()
1083 {
1084         if (surface().has_timecode_display())
1085         {
1086                 // do assignment here so current_frame is fixed
1087                 nframes_t current_frame = session->transport_frame();
1088                 string timecode;
1089
1090                 switch (_timecode_type)
1091                 {
1092                         case ARDOUR::AnyTime::BBT:
1093                                 timecode = format_bbt_timecode (current_frame);
1094                                 break;
1095                         case ARDOUR::AnyTime::Timecode:
1096                                 timecode = format_timecode_timecode (current_frame);
1097                                 break;
1098                         default:
1099                                 ostringstream os;
1100                                 os << "Unknown timecode: " << _timecode_type;
1101                                 throw runtime_error (os.str());
1102                 }
1103
1104                 // only write the timecode string to the MCU if it's changed
1105                 // since last time. This is to reduce midi bandwidth used.
1106                 if (timecode != _timecode_last)
1107                 {
1108                         surface().display_timecode (mcu_port(), builder, timecode, _timecode_last);
1109                         _timecode_last = timecode;
1110                 }
1111         }
1112 }
1113
1114 void 
1115 MackieControlProtocol::poll_session_data()
1116 {
1117         // XXX need to attach this to a timer in the MIDI UI event loop (20msec)
1118
1119         if (_active) {
1120                 // do all currently mapped routes
1121                 for (RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it) {
1122                         update_automation (**it);
1123                 }
1124
1125                 // and the master strip
1126                 if (master_route_signal != 0) {
1127                         update_automation (*master_route_signal);
1128                 }
1129
1130                 update_timecode_display();
1131         }
1132 }
1133
1134 /////////////////////////////////////
1135 // Transport Buttons
1136 /////////////////////////////////////
1137
1138 LedState 
1139 MackieControlProtocol::frm_left_press (Button &)
1140 {
1141         // can use first_mark_before/after as well
1142         unsigned long elapsed = _frm_left_last.restart();
1143
1144         Location * loc = session->locations()->first_location_before (
1145                 session->transport_frame()
1146         );
1147
1148         // allow a quick double to go past a previous mark
1149         if (session->transport_rolling() && elapsed < 500 && loc != 0)
1150         {
1151                 Location * loc_two_back = session->locations()->first_location_before (loc->start());
1152                 if (loc_two_back != 0)
1153                 {
1154                         loc = loc_two_back;
1155                 }
1156         }
1157
1158         // move to the location, if it's valid
1159         if (loc != 0)
1160         {
1161                 session->request_locate (loc->start(), session->transport_rolling());
1162         }
1163
1164         return on;
1165 }
1166
1167 LedState 
1168 MackieControlProtocol::frm_left_release (Button &)
1169 {
1170         return off;
1171 }
1172
1173 LedState 
1174 MackieControlProtocol::frm_right_press (Button &)
1175 {
1176         // can use first_mark_before/after as well
1177         Location * loc = session->locations()->first_location_after (
1178                 session->transport_frame()
1179         );
1180         if (loc != 0) session->request_locate (loc->start(), session->transport_rolling());
1181         return on;
1182 }
1183
1184 LedState 
1185 MackieControlProtocol::frm_right_release (Button &)
1186 {
1187         return off;
1188 }
1189
1190 LedState 
1191 MackieControlProtocol::stop_press (Button &)
1192 {
1193         session->request_stop();
1194         return on;
1195 }
1196
1197 LedState 
1198 MackieControlProtocol::stop_release (Button &)
1199 {
1200         return session->transport_stopped();
1201 }
1202
1203 LedState 
1204 MackieControlProtocol::play_press (Button &)
1205 {
1206         session->request_transport_speed (1.0);
1207         return on;
1208 }
1209
1210 LedState 
1211 MackieControlProtocol::play_release (Button &)
1212 {
1213         return session->transport_rolling();
1214 }
1215
1216 LedState 
1217 MackieControlProtocol::record_press (Button &)
1218 {
1219         if (session->get_record_enabled()) {
1220                 session->disable_record (false);
1221         } else {
1222                 session->maybe_enable_record();
1223         }
1224         return on;
1225 }
1226
1227 LedState 
1228 MackieControlProtocol::record_release (Button &)
1229 {
1230         if (session->get_record_enabled()) {
1231                 if (session->transport_rolling()) {
1232                         return on;
1233                 } else {
1234                         return flashing;
1235                 }
1236         } else {
1237                 return off;
1238         }
1239 }
1240
1241 LedState 
1242 MackieControlProtocol::rewind_press (Button &)
1243 {
1244         _jog_wheel.push (JogWheel::speed);
1245         _jog_wheel.transport_direction (-1);
1246         session->request_transport_speed (-_jog_wheel.transport_speed());
1247         return on;
1248 }
1249
1250 LedState 
1251 MackieControlProtocol::rewind_release (Button &)
1252 {
1253         _jog_wheel.pop();
1254         _jog_wheel.transport_direction (0);
1255         if (_transport_previously_rolling)
1256                 session->request_transport_speed (1.0);
1257         else
1258                 session->request_stop();
1259         return off;
1260 }
1261
1262 LedState 
1263 MackieControlProtocol::ffwd_press (Button &)
1264 {
1265         _jog_wheel.push (JogWheel::speed);
1266         _jog_wheel.transport_direction (1);
1267         session->request_transport_speed (_jog_wheel.transport_speed());
1268         return on;
1269 }
1270
1271 LedState 
1272 MackieControlProtocol::ffwd_release (Button &)
1273 {
1274         _jog_wheel.pop();
1275         _jog_wheel.transport_direction (0);
1276         if (_transport_previously_rolling)
1277                 session->request_transport_speed (1.0);
1278         else
1279                 session->request_stop();
1280         return off;
1281 }
1282
1283 LedState 
1284 MackieControlProtocol::loop_press (Button &)
1285 {
1286         session->request_play_loop (!session->get_play_loop());
1287         return on;
1288 }
1289
1290 LedState 
1291 MackieControlProtocol::loop_release (Button &)
1292 {
1293         return session->get_play_loop();
1294 }
1295
1296 LedState 
1297 MackieControlProtocol::punch_in_press (Button &)
1298 {
1299         bool state = !session->config.get_punch_in();
1300         session->config.set_punch_in (state);
1301         return state;
1302 }
1303
1304 LedState 
1305 MackieControlProtocol::punch_in_release (Button &)
1306 {
1307         return session->config.get_punch_in();
1308 }
1309
1310 LedState 
1311 MackieControlProtocol::punch_out_press (Button &)
1312 {
1313         bool state = !session->config.get_punch_out();
1314         session->config.set_punch_out (state);
1315         return state;
1316 }
1317
1318 LedState 
1319 MackieControlProtocol::punch_out_release (Button &)
1320 {
1321         return session->config.get_punch_out();
1322 }
1323
1324 LedState 
1325 MackieControlProtocol::home_press (Button &)
1326 {
1327         session->goto_start();
1328         return on;
1329 }
1330
1331 LedState 
1332 MackieControlProtocol::home_release (Button &)
1333 {
1334         return off;
1335 }
1336
1337 LedState 
1338 MackieControlProtocol::end_press (Button &)
1339 {
1340         session->goto_end();
1341         return on;
1342 }
1343
1344 LedState 
1345 MackieControlProtocol::end_release (Button &)
1346 {
1347         return off;
1348 }
1349
1350 LedState 
1351 MackieControlProtocol::clicking_press (Button &)
1352 {
1353         bool state = !Config->get_clicking();
1354         Config->set_clicking (state);
1355         return state;
1356 }
1357
1358 LedState 
1359 MackieControlProtocol::clicking_release (Button &)
1360 {
1361         return Config->get_clicking();
1362 }
1363
1364 LedState MackieControlProtocol::global_solo_press (Button &)
1365 {
1366         bool state = !session->soloing();
1367         session->set_solo (session->get_routes(), state);
1368         return state;
1369 }
1370
1371 LedState MackieControlProtocol::global_solo_release (Button &)
1372 {
1373         return session->soloing();
1374 }
1375
1376 ///////////////////////////////////////////
1377 // Session signals
1378 ///////////////////////////////////////////
1379
1380 void MackieControlProtocol::notify_parameter_changed (std::string const & p)
1381 {
1382         if (p == "punch-in")
1383         {
1384                 update_global_button ("punch_in", session->config.get_punch_in());
1385         }
1386         else if (p == "punch-out")
1387         {
1388                 update_global_button ("punch_out", session->config.get_punch_out());
1389         }
1390         else if (p == "clicking")
1391         {
1392                 update_global_button ("clicking", Config->get_clicking());
1393         }
1394         else
1395         {
1396                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
1397         }
1398 }
1399
1400 // RouteList is the set of routes that have just been added
1401 void 
1402 MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
1403 {
1404         // currently assigned banks are less than the full set of
1405         // strips, so activate the new strip now.
1406         if (route_signals.size() < route_table.size())
1407         {
1408                 refresh_current_bank();
1409         }
1410         // otherwise route added, but current bank needs no updating
1411
1412         // make sure remote id changes in the new route are handled
1413         typedef ARDOUR::RouteList ARS;
1414
1415         for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
1416                 (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
1417         }
1418 }
1419
1420 void 
1421 MackieControlProtocol::notify_solo_active_changed (bool active)
1422 {
1423         Button * rude_solo = reinterpret_cast<Button*> (surface().controls_by_name["solo"]);
1424         mcu_port().write (builder.build_led (*rude_solo, active ? flashing : off));
1425 }
1426
1427 void 
1428 MackieControlProtocol::notify_remote_id_changed()
1429 {
1430         Sorted sorted = get_sorted_routes();
1431
1432         // if a remote id has been moved off the end, we need to shift
1433         // the current bank backwards.
1434         if (sorted.size() - _current_initial_bank < route_signals.size())
1435         {
1436                 // but don't shift backwards past the zeroth channel
1437                 switch_banks (max((Sorted::size_type) 0, sorted.size() - route_signals.size()));
1438         }
1439         // Otherwise just refresh the current bank
1440         else
1441         {
1442                 refresh_current_bank();
1443         }
1444 }
1445
1446 ///////////////////////////////////////////
1447 // Transport signals
1448 ///////////////////////////////////////////
1449
1450 void 
1451 MackieControlProtocol::notify_record_state_changed()
1452 {
1453         // switch rec button on / off / flashing
1454         Button * rec = reinterpret_cast<Button*> (surface().controls_by_name["record"]);
1455         mcu_port().write (builder.build_led (*rec, record_release (*rec)));
1456 }
1457
1458 void 
1459 MackieControlProtocol::notify_transport_state_changed()
1460 {
1461         // switch various play and stop buttons on / off
1462         update_global_button ("play", session->transport_rolling());
1463         update_global_button ("stop", !session->transport_rolling());
1464         update_global_button ("loop", session->get_play_loop());
1465
1466         _transport_previously_rolling = session->transport_rolling();
1467
1468         // rec is special because it's tristate
1469         Button * rec = reinterpret_cast<Button*> (surface().controls_by_name["record"]);
1470         mcu_port().write (builder.build_led (*rec, record_release (*rec)));
1471 }
1472
1473 /////////////////////////////////////
1474 // Bank Switching
1475 /////////////////////////////////////
1476 LedState 
1477 MackieControlProtocol::left_press (Button &)
1478 {
1479         Sorted sorted = get_sorted_routes();
1480         if (sorted.size() > route_table.size())
1481         {
1482                 int new_initial = _current_initial_bank - route_table.size();
1483                 if (new_initial < 0) new_initial = 0;
1484                 if (new_initial != int (_current_initial_bank))
1485                 {
1486                         session->set_dirty();
1487                         switch_banks (new_initial);
1488                 }
1489
1490                 return on;
1491         }
1492         else
1493         {
1494                 return flashing;
1495         }
1496 }
1497
1498 LedState 
1499 MackieControlProtocol::left_release (Button &)
1500 {
1501         return off;
1502 }
1503
1504 LedState 
1505 MackieControlProtocol::right_press (Button &)
1506 {
1507         Sorted sorted = get_sorted_routes();
1508         if (sorted.size() > route_table.size()) {
1509                 uint32_t delta = sorted.size() - (route_table.size() + _current_initial_bank);
1510                 if (delta > route_table.size()) delta = route_table.size();
1511                 if (delta > 0) {
1512                         session->set_dirty();
1513                         switch_banks (_current_initial_bank + delta);
1514                 }
1515
1516                 return on;
1517         } else {
1518                 return flashing;
1519         }
1520 }
1521
1522 LedState 
1523 MackieControlProtocol::right_release (Button &)
1524 {
1525         return off;
1526 }
1527
1528 LedState 
1529 MackieControlProtocol::channel_left_press (Button &)
1530 {
1531         Sorted sorted = get_sorted_routes();
1532         if (sorted.size() > route_table.size())
1533         {
1534                 prev_track();
1535                 return on;
1536         }
1537         else
1538         {
1539                 return flashing;
1540         }
1541 }
1542
1543 LedState 
1544 MackieControlProtocol::channel_left_release (Button &)
1545 {
1546         return off;
1547 }
1548
1549 LedState 
1550 MackieControlProtocol::channel_right_press (Button &)
1551 {
1552         Sorted sorted = get_sorted_routes();
1553         if (sorted.size() > route_table.size())
1554         {
1555                 next_track();
1556                 return on;
1557         }
1558         else
1559         {
1560                 return flashing;
1561         }
1562 }
1563
1564 LedState 
1565 MackieControlProtocol::channel_right_release (Button &)
1566 {
1567         return off;
1568 }
1569
1570 /////////////////////////////////////
1571 // Functions
1572 /////////////////////////////////////
1573 LedState 
1574 MackieControlProtocol::marker_press (Button &)
1575 {
1576         // cut'n'paste from LocationUI::add_new_location()
1577         string markername;
1578         nframes_t where = session->audible_frame();
1579         session->locations()->next_available_name(markername,"mcu");
1580         Location *location = new Location (where, where, markername, Location::IsMark);
1581         session->begin_reversible_command (_("add marker"));
1582         XMLNode &before = session->locations()->get_state();
1583         session->locations()->add (location, true);
1584         XMLNode &after = session->locations()->get_state();
1585         session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
1586         session->commit_reversible_command ();
1587         return on;
1588 }
1589
1590 LedState 
1591 MackieControlProtocol::marker_release (Button &)
1592 {
1593         return off;
1594 }
1595
1596 void 
1597 jog_wheel_state_display (JogWheel::State state, SurfacePort & port)
1598 {
1599         switch (state)
1600         {
1601                 case JogWheel::zoom: port.write (builder.two_char_display ("Zm")); break;
1602                 case JogWheel::scroll: port.write (builder.two_char_display ("Sc")); break;
1603                 case JogWheel::scrub: port.write (builder.two_char_display ("Sb")); break;
1604                 case JogWheel::shuttle: port.write (builder.two_char_display ("Sh")); break;
1605                 case JogWheel::speed: port.write (builder.two_char_display ("Sp")); break;
1606                 case JogWheel::select: port.write (builder.two_char_display ("Se")); break;
1607         }
1608 }
1609
1610 Mackie::LedState 
1611 MackieControlProtocol::zoom_press (Mackie::Button &)
1612 {
1613         _jog_wheel.zoom_state_toggle();
1614         update_global_button ("scrub", _jog_wheel.jog_wheel_state() == JogWheel::scrub);
1615         jog_wheel_state_display (_jog_wheel.jog_wheel_state(), mcu_port());
1616         return _jog_wheel.jog_wheel_state() == JogWheel::zoom;
1617 }
1618
1619 Mackie::LedState 
1620 MackieControlProtocol::zoom_release (Mackie::Button &)
1621 {
1622         return _jog_wheel.jog_wheel_state() == JogWheel::zoom;
1623 }
1624
1625 Mackie::LedState 
1626 MackieControlProtocol::scrub_press (Mackie::Button &)
1627 {
1628         _jog_wheel.scrub_state_cycle();
1629         update_global_button ("zoom", _jog_wheel.jog_wheel_state() == JogWheel::zoom);
1630         jog_wheel_state_display (_jog_wheel.jog_wheel_state(), mcu_port());
1631         return
1632                 _jog_wheel.jog_wheel_state() == JogWheel::scrub
1633                 ||
1634                 _jog_wheel.jog_wheel_state() == JogWheel::shuttle
1635         ;
1636 }
1637
1638 Mackie::LedState 
1639 MackieControlProtocol::scrub_release (Mackie::Button &)
1640 {
1641         return
1642                 _jog_wheel.jog_wheel_state() == JogWheel::scrub
1643                 ||
1644                 _jog_wheel.jog_wheel_state() == JogWheel::shuttle
1645         ;
1646 }
1647
1648 LedState 
1649 MackieControlProtocol::drop_press (Button &)
1650 {
1651         session->remove_last_capture();
1652         return on;
1653 }
1654
1655 LedState 
1656 MackieControlProtocol::drop_release (Button &)
1657 {
1658         return off;
1659 }
1660
1661 LedState 
1662 MackieControlProtocol::save_press (Button &)
1663 {
1664         session->save_state ("");
1665         return on;
1666 }
1667
1668 LedState 
1669 MackieControlProtocol::save_release (Button &)
1670 {
1671         return off;
1672 }
1673
1674 LedState 
1675 MackieControlProtocol::timecode_beats_press (Button &)
1676 {
1677         switch (_timecode_type)
1678         {
1679                 case ARDOUR::AnyTime::BBT:
1680                         _timecode_type = ARDOUR::AnyTime::Timecode;
1681                         break;
1682                 case ARDOUR::AnyTime::Timecode:
1683                         _timecode_type = ARDOUR::AnyTime::BBT;
1684                         break;
1685                 default:
1686                         ostringstream os;
1687                         os << "Unknown Anytime::Type " << _timecode_type;
1688                         throw runtime_error (os.str());
1689         }
1690         update_timecode_beats_led();
1691         return on;
1692 }
1693
1694 LedState 
1695 MackieControlProtocol::timecode_beats_release (Button &)
1696 {
1697         return off;
1698 }
1699