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