poll for automation
[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
20 #include <iostream>
21 #include <algorithm>
22 #include <cmath>
23 #include <sstream>
24 #include <vector>
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
41 #include <ardour/route.h>
42 #include <ardour/session.h>
43 #include <ardour/location.h>
44 #include <ardour/dB.h>
45 #include <ardour/panner.h>
46
47 #include "mackie_control_protocol.h"
48
49 #include "midi_byte_array.h"
50 #include "mackie_control_exception.h"
51 #include "route_signal.h"
52 #include "mackie_midi_builder.h"
53 #include "surface_port.h"
54 #include "surface.h"
55 #include "bcf_surface.h"
56 #include "mackie_surface.h"
57
58 using namespace ARDOUR;
59 using namespace std;
60 using namespace sigc;
61 using namespace Mackie;
62 using namespace PBD;
63
64 using boost::shared_ptr;
65
66 #include "i18n.h"
67
68 MackieMidiBuilder builder;
69
70 // Copied from tranzport_control_protocol.cc
71 static inline double 
72 gain_to_slider_position (ARDOUR::gain_t g)
73 {
74         if (g == 0) return 0;
75         return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
76 }
77
78 /*
79         Copied from tranzport_control_protocol.cc
80         TODO this seems to return slightly wrong values, namely
81         with the UI slider at max, we get a 0.99something value.
82 */
83 static inline ARDOUR::gain_t 
84 slider_position_to_gain (double pos)
85 {
86         /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
87         if (pos == 0.0) return 0;
88         return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
89 }
90
91 MackieControlProtocol::MackieControlProtocol (Session& session)
92         : ControlProtocol  (session, X_("Mackie"))
93         , _current_initial_bank( 0 )
94         , connections_back( _connections )
95         , _surface( 0 )
96         , _ports_changed( false )
97         , pfd( 0 )
98         , nfds( 0 )
99 {
100         cout << "MackieControlProtocol::MackieControlProtocol" << endl;
101         // will start reading from ports, as soon as there are some
102         pthread_create_and_store (X_("mackie monitor"), &thread, 0, _monitor_work, this);
103 }
104
105 MackieControlProtocol::~MackieControlProtocol()
106 {
107         cout << "~MackieControlProtocol::MackieControlProtocol" << endl;
108         try
109         {
110                 close();
111         }
112         catch ( exception & e )
113         {
114                 cout << "~MackieControlProtocol caught " << e.what() << endl;
115         }
116         catch ( ... )
117         {
118                 cout << "~MackieControlProtocol caught unknown" << endl;
119         }
120 }
121
122 Mackie::Surface & MackieControlProtocol::surface()
123 {
124         if ( _surface == 0 )
125         {
126                 throw MackieControlException( "_surface is 0 in MackieControlProtocol::surface" );
127         }
128         return *_surface;
129 }
130
131 const Mackie::MackiePort & MackieControlProtocol::mcu_port() const
132 {
133         return dynamic_cast<const MackiePort &>( *_ports[0] );
134 }
135
136 Mackie::MackiePort & MackieControlProtocol::mcu_port()
137 {
138         return dynamic_cast<const MackiePort &>( *_ports[0] );
139 }
140
141 // go to the previous track.
142 // Assume that get_sorted_routes().size() > route_table.size()
143 void MackieControlProtocol::prev_track()
144 {
145         if ( _current_initial_bank >= 1 )
146         {
147                 session->set_dirty();
148                 switch_banks( _current_initial_bank - 1 );
149         }
150 }
151
152 // go to the next track.
153 // Assume that get_sorted_routes().size() > route_table.size()
154 void MackieControlProtocol::next_track()
155 {
156         Sorted sorted = get_sorted_routes();
157         if ( _current_initial_bank + route_table.size() < sorted.size() )
158         {
159                 session->set_dirty();
160                 switch_banks( _current_initial_bank + 1 );
161         }
162 }
163
164 void MackieControlProtocol::clear_route_signals()
165 {
166         for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it )
167         {
168                 delete *it;
169         }
170         route_signals.clear();
171 }
172
173 // return the port for a given id - 0 based
174 // throws an exception if no port found
175 MackiePort & MackieControlProtocol::port_for_id( uint32_t index )
176 {
177         uint32_t current_max = 0;
178         for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
179         {
180                 current_max += (*it)->strips();
181                 if ( index < current_max ) return **it;
182         }
183         
184         // oops - no matching port
185         ostringstream os;
186         os << "No port for index " << index;
187         throw MackieControlException( os.str() );
188 }
189
190 // predicate for sort call in get_sorted_routes
191 struct RouteByRemoteId
192 {
193         bool operator () ( const shared_ptr<Route> & a, const shared_ptr<Route> & b ) const
194         {
195                 return a->remote_control_id() < b->remote_control_id();
196         }
197
198         bool operator () ( const Route & a, const Route & b ) const
199         {
200                 return a.remote_control_id() < b.remote_control_id();
201         }
202
203         bool operator () ( const Route * a, const Route * b ) const
204         {
205                 return a->remote_control_id() < b->remote_control_id();
206         }
207 };
208
209 MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
210 {
211         Sorted sorted;
212         
213         // fetch all routes
214         boost::shared_ptr<Session::RouteList> routes = session->get_routes();
215         set<uint32_t> remote_ids;
216         
217         // routes with remote_id 0 should never be added
218         // TODO verify this with ardour devs
219         // remote_ids.insert( 0 );
220         
221         // sort in remote_id order, and exclude master, control and hidden routes
222         // and any routes that are already set.
223         for ( Session::RouteList::iterator it = routes->begin(); it != routes->end(); ++it )
224         {
225                 Route & route = **it;
226                 if (
227                                 route.active()
228                                 && !route.master()
229                                 && !route.hidden()
230                                 && !route.control()
231                                 && remote_ids.find( route.remote_control_id() ) == remote_ids.end()
232                 )
233                 {
234                         sorted.push_back( *it );
235                         remote_ids.insert( route.remote_control_id() );
236                 }
237         }
238         sort( sorted.begin(), sorted.end(), RouteByRemoteId() );
239         return sorted;
240 }
241
242 void MackieControlProtocol::refresh_current_bank()
243 {
244         switch_banks( _current_initial_bank );
245 }
246
247 void MackieControlProtocol::switch_banks( int initial )
248 {
249         // DON'T prevent bank switch if initial == _current_initial_bank
250         // because then this method can't be used as a refresh
251         
252         // sanity checking
253         Sorted sorted = get_sorted_routes();
254         int delta = sorted.size() - route_table.size();
255         if ( initial < 0 || ( delta > 0 && initial > delta ) )
256         {
257                 cout << "not switching to " << initial << endl;
258                 return;
259         }
260         _current_initial_bank = initial;
261         
262         // first clear the signals from old routes
263         // taken care of by the RouteSignal destructors
264         clear_route_signals();
265         
266         // now set the signals for new routes
267         if ( _current_initial_bank <= sorted.size() )
268         {
269                 // fetch the bank start and end to switch to
270                 uint32_t end_pos = min( route_table.size(), sorted.size() );
271                 Sorted::iterator it = sorted.begin() + _current_initial_bank;
272                 Sorted::iterator end = sorted.begin() + _current_initial_bank + end_pos;
273                 //cout << "switch to " << _current_initial_bank << ", " << end_pos << endl;
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                         //cout << "remote id " << route->remote_control_id() << " connecting " << route->name() << " to " << strip.name() << " with port " << port_for_id(i) << endl;
282                         route_table[i] = route;
283                         RouteSignal * rs = new RouteSignal( *route, *this, strip, port_for_id(i) );
284                         route_signals.push_back( rs );
285                         // update strip from route
286                         rs->notify_all();
287                 }
288                 
289                 // create dead strips if there aren't enough routes to
290                 // fill a bank
291                 for ( ; i < route_table.size(); ++i )
292                 {
293                         Strip & strip = *surface().strips[i];
294                         // send zero for this strip
295                         port_for_id(i).write( builder.zero_strip( strip ) );
296                 }
297         }
298         
299         // display the current start bank.
300         if ( mcu_port().emulation() == MackiePort::bcf2000 )
301         {
302                 if ( _current_initial_bank == 0 )
303                 {
304                         // send Ar. to 2-char display on the master
305                         mcu_port().write( builder.two_char_display( "Ar", ".." ) );
306                 }
307                 else
308                 {
309                         // write the current first remote_id to the 2-char display
310                         mcu_port().write( builder.two_char_display( _current_initial_bank ) );
311                 }
312         }
313 }
314
315 void MackieControlProtocol::zero_all()
316 {
317         // TODO turn off 55-char and SMPTE displays
318         
319         if ( mcu_port().emulation() == MackiePort::bcf2000 )
320         {
321                 // clear 2-char display
322                 mcu_port().write( builder.two_char_display( "LC" ) );
323         }
324         
325         // zero all strips
326         for ( Surface::Strips::iterator it = surface().strips.begin(); it != surface().strips.end(); ++it )
327         {
328                 port_for_id( (*it)->index() ).write( builder.zero_strip( **it ) );
329         }
330         
331         // and the master strip
332         mcu_port().write( builder.zero_strip( master_strip() ) );
333         
334         // and the led ring for the master strip, in bcf mode
335         if ( mcu_port().emulation() == MackiePort::bcf2000 )
336         {
337                 Control & control = *surface().controls_by_name["jog"];
338                 mcu_port().write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
339         }
340         
341         // turn off global buttons and leds
342         // global buttons are only ever on mcu_port, so we don't have
343         // to figure out which port.
344         for ( Surface::Controls::iterator it = surface().controls.begin(); it != surface().controls.end(); ++it )
345         {
346                 Control & control = **it;
347                 if ( !control.group().is_strip() && control.accepts_feedback() )
348                 {
349                         mcu_port().write( builder.zero_control( control ) );
350                 }
351         }
352 }
353
354 int MackieControlProtocol::set_active (bool yn)
355 {
356         if ( yn != _active )
357         {
358                 try
359                 {
360                         // the reason for the locking and unlocking is that
361                         // glibmm can't do a condition wait on a RecMutex
362                         if ( yn )
363                         {
364                                 // TODO what happens if this fails half way?
365                                 cout << "set_active true" << endl;
366                                 
367                                 // create MackiePorts
368                                 {
369                                         Glib::Mutex::Lock lock( update_mutex );
370                                         create_ports();
371                                 }
372                                 
373                                 // wait until poll thread is running, with ports to poll
374                                 // the mutex is only there because conditions require a mutex
375                                 {
376                                         Glib::Mutex::Lock lock( update_mutex );
377                                         while ( nfds == 0 ) update_cond.wait( update_mutex );
378                                 }
379                                 
380                                 // now initialise MackiePorts - ie exchange sysex messages
381                                 for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
382                                 {
383                                         (*it)->open();
384                                 }
385                                 
386                                 // wait until all ports are active
387                                 // TODO a more sophisticate approach would
388                                 // allow things to start up with only an MCU, even if
389                                 // extenders were specified but not responding.
390                                 for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
391                                 {
392                                         (*it)->wait_for_init();
393                                 }
394                                 
395                                 // create surface object. This depends on the ports being
396                                 // correctly initialised
397                                 initialize_surface();
398                                 connect_session_signals();
399                                 
400                                 // yeehah!
401                                 _active = true;
402                                 
403                                 // send current control positions to surface
404                                 // must come after _active = true otherwise it won't run
405                                 update_surface();
406                         }
407                         else
408                         {
409                                 cout << "set_active false" << endl;
410                                 close();
411                                 _active = false;
412                         }
413                 }
414                 catch( exception & e )
415                 {
416                         cout << "set_active to false because " << e.what() << endl;
417                         _active = false;
418                         throw;
419                 }
420         }
421
422         return 0;
423 }
424
425 bool MackieControlProtocol::handle_strip_button( Control & control, ButtonState bs, boost::shared_ptr<Route> route )
426 {
427         bool state = false;
428
429         if ( bs == press )
430         {
431                 if ( control.name() == "recenable" )
432                 {
433                         state = !route->record_enabled();
434                         route->set_record_enable( state, this );
435                 }
436                 else if ( control.name() == "mute" )
437                 {
438                         state = !route->muted();
439                         route->set_mute( state, this );
440                 }
441                 else if ( control.name() == "solo" )
442                 {
443                         state = !route->soloed();
444                         route->set_solo( state, this );
445                 }
446                 else if ( control.name() == "select" )
447                 {
448                         // TODO make the track selected. Whatever that means.
449                         //state = default_button_press( dynamic_cast<Button&>( control ) );
450                 }
451                 else if ( control.name() == "vselect" )
452                 {
453                         // TODO could be used to select different things to apply the pot to?
454                         //state = default_button_press( dynamic_cast<Button&>( control ) );
455                 }
456         }
457         
458         if ( control.name() == "fader_touch" )
459         {
460                 state = bs == press;
461                 control.strip().gain().touch( state );
462         }
463         
464         return state;
465 }
466
467 void MackieControlProtocol::update_led( Mackie::Button & button, Mackie::LedState ls )
468 {
469         MackiePort * port = 0;
470         if ( button.group().is_strip() )
471         {
472                 if ( button.group().is_master() )
473                 {
474                         port = &mcu_port();
475                 }
476                 else
477                 {
478                         port = &port_for_id( dynamic_cast<const Strip&>( button.group() ).index() );
479                 }
480         }
481         else
482         {
483                 port = &mcu_port();
484         }
485         if ( ls != none ) port->write( builder.build_led( button, ls ) );
486 }
487
488 void MackieControlProtocol::update_global_button( const string & name, LedState ls )
489 {
490         if ( surface().controls_by_name.find( name ) !=surface().controls_by_name.end() )
491         {
492                 Button * button = dynamic_cast<Button*>( surface().controls_by_name[name] );
493                 mcu_port().write( builder.build_led( button->led(), ls ) );
494         }
495         else
496         {
497                 cout << "Button " << name << " not found" << endl;
498         }
499 }
500
501 // send messages to surface to set controls to correct values
502 void MackieControlProtocol::update_surface()
503 {
504         if ( _active )
505         {
506                 // do the initial bank switch to connect signals
507                 // _current_initial_bank is initialised by set_state
508                 switch_banks( _current_initial_bank );
509                 
510                 // create a RouteSignal for the master route
511                 // but only the first time around
512                 master_route_signal = shared_ptr<RouteSignal>( new RouteSignal( *master_route(), *this, master_strip(), mcu_port() ) );
513                 // update strip from route
514                 master_route_signal->notify_all();
515                 
516                 // update global buttons and displays
517                 notify_record_state_changed();
518                 notify_transport_state_changed();
519         }
520 }
521
522 void MackieControlProtocol::connect_session_signals()
523 {
524         // receive routes added
525         connections_back = session->RouteAdded.connect( ( mem_fun (*this, &MackieControlProtocol::notify_route_added) ) );
526         // receive record state toggled
527         connections_back = session->RecordStateChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_record_state_changed) ) );
528         // receive transport state changed
529         connections_back = session->TransportStateChange.connect( ( mem_fun (*this, &MackieControlProtocol::notify_transport_state_changed) ) );
530         // receive punch-in and punch-out
531         connections_back = Config->ParameterChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_parameter_changed) ) );
532         // receive rude solo changed
533         connections_back = session->SoloActive.connect( ( mem_fun (*this, &MackieControlProtocol::notify_solo_active_changed) ) );
534         
535         // make sure remote id changed signals reach here
536         // see also notify_route_added
537         Sorted sorted = get_sorted_routes();
538         for ( Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it )
539         {
540                 (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
541         }
542 }
543
544 void MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
545 {
546         MackiePort * sport = new MackiePort( *this, midi_port, number );
547         _ports.push_back( sport );
548
549         connections_back = sport->init_event.connect(
550                 sigc::bind (
551                         mem_fun (*this, &MackieControlProtocol::handle_port_init)
552                         , sport
553                 )
554         );
555
556         connections_back = sport->active_event.connect(
557                 sigc::bind (
558                         mem_fun (*this, &MackieControlProtocol::handle_port_changed)
559                         , sport
560                         , true
561                 )
562         );
563
564         connections_back = sport->inactive_event.connect(
565                 sigc::bind (
566                         mem_fun (*this, &MackieControlProtocol::handle_port_changed)
567                         , sport
568                         , false
569                 )
570         );
571         
572         _ports_changed = true;
573 }
574
575 void MackieControlProtocol::create_ports()
576 {
577         MIDI::Manager * mm = MIDI::Manager::instance();
578
579         // open main port
580         {
581                 MIDI::Port * midi_port = mm->port( default_port_name );
582
583                 if ( midi_port == 0 ) {
584                         ostringstream os;
585                         os << string_compose( _("no MIDI port named \"%1\" exists - Mackie control disabled"), default_port_name );
586                         error << os.str() << endmsg;
587                         throw MackieControlException( os.str() );
588                 }
589                 add_port( *midi_port, 0 );
590         }
591         
592         // open extender ports. Up to 9. Should be enough.
593         // could also use mm->get_midi_ports()
594         string ext_port_base = "mcu_xt_";
595         for ( int index = 1; index <= 9; ++index )
596         {
597                 ostringstream os;
598                 os << ext_port_base << index;
599                 MIDI::Port * midi_port = mm->port( os.str() );
600                 if ( midi_port != 0 ) add_port( *midi_port, index );
601         }
602 }
603
604 shared_ptr<Route> MackieControlProtocol::master_route()
605 {
606         shared_ptr<Route> retval;
607         retval = session->route_by_name( "master" );
608         if ( retval == 0 )
609         {
610                 // TODO search through all routes for one with the master attribute set
611         }
612         return retval;
613 }
614
615 Strip & MackieControlProtocol::master_strip()
616 {
617         return dynamic_cast<Strip&>( *surface().groups["master"] );
618 }
619
620 void MackieControlProtocol::initialize_surface()
621 {
622         // set up the route table
623         int strips = 0;
624         for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
625         {
626                 strips += (*it)->strips();
627         }
628         
629         set_route_table_size( strips );
630         
631         switch ( mcu_port().emulation() )
632         {
633                 case MackiePort::bcf2000: _surface = new BcfSurface( strips ); break;
634                 case MackiePort::mackie: _surface = new MackieSurface( strips ); break;
635                 default:
636                         ostringstream os;
637                         os << "no Surface class found for emulation: " << mcu_port().emulation();
638                         throw MackieControlException( os.str() );
639         }
640         _surface->init();
641         
642         // Connect events. Must be after route table otherwise there will be trouble
643         for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
644         {
645                 (*it)->control_event.connect( ( mem_fun (*this, &MackieControlProtocol::handle_control_event) ) );
646         }
647 }
648
649 void MackieControlProtocol::close()
650 {
651         // TODO disconnect port active/inactive signals
652         // Or at least put a lock here
653         
654         if ( _surface != 0 )
655         {
656                 // These will fail if the port has gone away.
657                 // So catch the exception and do the rest of the
658                 // close afterwards
659                 // because the bcf doesn't respond to the next 3 sysex messages
660                 try
661                 {
662                         zero_all();
663                 }
664                 catch ( exception & e )
665                 {
666                         cout << "MackieControlProtocol::close caught exception: " << e.what() << endl;
667                 }
668                 
669                 for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
670                 {
671                         try
672                         {
673                                 MackiePort & port = **it;
674                                 // faders to minimum
675                                 port.write_sysex( 0x61 );
676                                 // All LEDs off
677                                 port.write_sysex( 0x62 );
678                                 // Reset (reboot into offline mode)
679                                 port.write_sysex( 0x63 );
680                         }
681                         catch ( exception & e )
682                         {
683                                 cout << "MackieControlProtocol::close caught exception: " << e.what() << endl;
684                         }
685                 }
686                 
687                 // disconnect global signals from Session
688                 // TODO Since *this is a sigc::trackable, this shouldn't be necessary
689                 for( vector<sigc::connection>::iterator it = _connections.begin(); it != _connections.end(); ++it )
690                 {
691                         it->disconnect();
692                 }
693                 
694                 // disconnect routes from strips
695                 clear_route_signals();
696         }
697         
698         // stop polling, and wait for it...
699         pthread_cancel_one( thread );
700         pthread_join( thread, 0 );
701         
702         // shut down MackiePorts
703         for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
704         {
705                 delete *it;
706         }
707         _ports.clear();
708         
709         delete[] pfd;
710 }
711
712 void* MackieControlProtocol::_monitor_work (void* arg)
713 {
714         return static_cast<MackieControlProtocol*>(arg)->monitor_work ();
715 }
716
717 XMLNode & MackieControlProtocol::get_state()
718 {
719         cout << "MackieControlProtocol::get_state" << endl;
720         
721         // add name of protocol
722         XMLNode* node = new XMLNode( X_("Protocol") );
723         node->add_property( X_("name"), _name );
724         
725         // add current bank
726         ostringstream os;
727         os << _current_initial_bank;
728         node->add_property( X_("bank"), os.str() );
729         
730         return *node;
731 }
732
733 int MackieControlProtocol::set_state( const XMLNode & node )
734 {
735         cout << "MackieControlProtocol::set_state: active " << _active << endl;
736         int retval = 0;
737         
738         // fetch current bank
739         if ( node.property( X_("bank") ) != 0 )
740         {
741                 string bank = node.property( X_("bank") )->value();
742                 try
743                 {
744                         set_active( true );
745                         uint32_t new_bank = atoi( bank.c_str() );
746                         if ( _current_initial_bank != new_bank ) switch_banks( new_bank );
747                 }
748                 catch ( exception & e )
749                 {
750                         cout << "exception in MackieControlProtocol::set_state: " << e.what() << endl;
751                         return -1;
752                 }
753         }
754         
755         return retval;
756 }
757
758 void MackieControlProtocol::handle_control_event( SurfacePort & port, Control & control, const ControlState & state )
759 {
760         uint32_t index = control.ordinal() - 1 + ( port.number() * port.strips() );
761         boost::shared_ptr<Route> route;
762         if ( control.group().is_strip() )
763         {
764                 if ( control.group().is_master() )
765                 {
766                         route = master_route();
767                 }
768                 else if ( index < route_table.size() )
769                         route = route_table[index];
770                 else
771                         cerr << "Warning: index is " << index << " which is not in the route table, size: " << route_table.size() << endl;
772         }
773         
774         // This handles control element events from the surface
775         // the state of the controls on the surface is usually updated
776         // from UI events.
777         switch ( control.type() )
778         {
779                 case Control::type_fader:
780                         if ( control.group().is_strip() )
781                         {
782                                 // find the route in the route table for the id
783                                 // if the route isn't available, skip it
784                                 // at which point the fader should just reset itself
785                                 if ( route != 0 )
786                                 {
787                                         route->set_gain( slider_position_to_gain( state.pos ), this );
788                                         
789                                         // must echo bytes back to slider now, because
790                                         // the notifier only works if the fader is not being
791                                         // touched. Which it is if we're getting input.
792                                         port.write( builder.build_fader( (Fader&)control, state.pos ) );
793                                 }
794                         }
795                         else
796                         {
797                                 // master fader
798                                 boost::shared_ptr<Route> route = master_route();
799                                 if ( route )
800                                 {
801                                         route->set_gain( slider_position_to_gain( state.pos ), this );
802                                         port.write( builder.build_fader( (Fader&)control, state.pos ) );
803                                 }
804                         }
805                         break;
806                         
807                 case Control::type_button:
808                         if ( control.group().is_strip() )
809                         {
810                                 // strips
811                                 if ( route != 0 )
812                                 {
813                                         handle_strip_button( control, state.button_state, route );
814                                 }
815                                 else
816                                 {
817                                         // no route so always switch the light off
818                                         // because no signals will be emitted by a non-route
819                                         port.write( builder.build_led( control.led(), off ) );
820                                 }
821                         }
822                         else if ( control.group().is_master() )
823                         {
824                                 // master fader touch
825                                 boost::shared_ptr<Route> route = master_route();
826                                 if ( route )
827                                         handle_strip_button( control, state.button_state, route );
828                         }
829                         else
830                         {
831                                 // handle all non-strip buttons
832                                 surface().handle_button( *this, state.button_state, dynamic_cast<Button&>( control ) );
833                         }
834                         break;
835                         
836                 // pot (jog wheel, external control)
837                 case Control::type_pot:
838                         if ( control.group().is_strip() )
839                         {
840                                 if ( route != 0 )
841                                 {
842                                         if ( route->panner().size() == 1 )
843                                         {
844                                                 // assume pan for now
845                                                 float xpos;
846                                                 route->panner()[0]->get_effective_position (xpos);
847                                                 
848                                                 // calculate new value, and trim
849                                                 xpos += state.delta;
850                                                 if ( xpos > 1.0 )
851                                                         xpos = 1.0;
852                                                 else if ( xpos < 0.0 )
853                                                         xpos = 0.0;
854                                                 
855                                                 route->panner()[0]->set_position( xpos );
856                                         }
857                                 }
858                                 else
859                                 {
860                                         // it's a pot for an umnapped route, so turn all the lights off
861                                         port.write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
862                                 }
863                         }
864                         else
865                         {
866                                 if ( control.name() == "jog" )
867                                 {
868                                         // TODO use current snap-to setting?
869                                         long delta = state.ticks * 1000;
870                                         nframes_t next = session->transport_frame() + delta;
871                                         if ( delta < 0 && session->transport_frame() < (nframes_t) abs( delta )  )
872                                         {
873                                                 next = session->current_start_frame();
874                                         }
875                                         else if ( next > session->current_end_frame() )
876                                         {
877                                                 next = session->current_end_frame();
878                                         }
879                                         
880                                         // doesn't work very well
881                                         session->request_locate( next, session->transport_rolling() );
882                                         
883                                         // turn off the led ring, for bcf emulation mode
884                                         port.write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
885                                 }
886                                 else
887                                 {
888                                         cout << "external controller" << state.ticks << endl;
889                                 }
890                         }
891                         break;
892                         
893                 default:
894                         cout << "Control::type not handled: " << control.type() << endl;
895         }
896 }
897
898 /////////////////////////////////////////////////////////
899 // Notifications from UI
900 /////////////////////////////////////////////////////////
901 struct RouteSignalByRoute
902 {
903         RouteSignalByRoute( Route & route ): _route( route ) {}
904                 
905         bool operator () ( const RouteSignal & rs ) const
906         {
907                 return rs.route().id() == _route.id();
908         }
909         
910         bool operator () ( const RouteSignal * rs ) const
911         {
912                 return rs->route().id() == _route.id();
913         }
914
915         Route & _route;
916 };
917
918 Strip & MackieControlProtocol::strip_from_route( Route * route )
919 {
920         if ( route == 0 )
921         {
922                 throw MackieControlException( "route is null in MackieControlProtocol::strip_from_route" );
923         }
924         
925         if ( route->master() )
926         {
927                 return master_strip();
928         }
929         
930         RouteSignals::iterator it = find_if(
931                 route_signals.begin()
932                 , route_signals.end()
933                 , RouteSignalByRoute( *route )
934         );
935         
936         if ( it == route_signals.end() )
937         {
938                 ostringstream os;
939                 os << "No strip for route " << route->name();
940                 throw MackieControlException( os.str() );
941         }
942         
943         return (*it)->strip();
944 }
945
946 /////////////////////////////////////////////////
947 // handlers for Route signals
948 // TODO should these be part of RouteSignal?
949 /////////////////////////////////////////////////
950
951 void MackieControlProtocol::notify_solo_changed( ARDOUR::Route * route, MackiePort * port )
952 {
953         try
954         {
955                 Button & button = strip_from_route( route ).solo();
956                 port->write( builder.build_led( button, route->soloed() ) );
957         }
958         catch( exception & e )
959         {
960                 cout << e.what() << endl;
961         }
962 }
963
964 void MackieControlProtocol::notify_mute_changed( ARDOUR::Route * route, MackiePort * port )
965 {
966         try
967         {
968                 Button & button = strip_from_route( route ).mute();
969                 port->write( builder.build_led( button, route->muted() ) );
970         }
971         catch( exception & e )
972         {
973                 cout << e.what() << endl;
974         }
975 }
976
977 void MackieControlProtocol::notify_record_enable_changed( ARDOUR::Route * route, MackiePort * port )
978 {
979         try
980         {
981                 Button & button = strip_from_route( route ).recenable();
982                 port->write( builder.build_led( button, route->record_enabled() ) );
983         }
984         catch( exception & e )
985         {
986                 cout << e.what() << endl;
987         }
988 }
989
990 void MackieControlProtocol::notify_gain_changed(  ARDOUR::Route * route, MackiePort * port )
991 {
992         try
993         {
994                 Fader & fader = strip_from_route( route ).gain();
995                 if ( !fader.touch() )
996                 {
997                         port->write( builder.build_fader( fader, gain_to_slider_position( route->effective_gain() ) ) );
998                 }
999         }
1000         catch( exception & e )
1001         {
1002                 cout << e.what() << endl;
1003         }
1004 }
1005
1006 void MackieControlProtocol::notify_name_changed( void *, ARDOUR::Route * route, MackiePort * port )
1007 {
1008         try
1009         {
1010                 // TODO implement MackieControlProtocol::notify_name_changed
1011         }
1012         catch( exception & e )
1013         {
1014                 cout << e.what() << endl;
1015         }
1016 }
1017
1018 // TODO deal with > 1 channel being panned
1019 void MackieControlProtocol::notify_panner_changed( ARDOUR::Route * route, MackiePort * port )
1020 {
1021         try
1022         {
1023                 Pot & pot = strip_from_route( route ).vpot();
1024                 if ( route->panner().size() == 1 )
1025                 {
1026                         float pos;
1027                         route->panner()[0]->get_effective_position( pos);
1028                         port->write( builder.build_led_ring( pot, ControlState( on, pos ) ) );
1029                 }
1030                 else
1031                 {
1032                         port->write( builder.zero_control( pot ) );
1033                 }
1034         }
1035         catch( exception & e )
1036         {
1037                 cout << e.what() << endl;
1038         }
1039 }
1040
1041 void MackieControlProtocol::poll_automation()
1042 {
1043         for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it )
1044         {
1045                 // update strip from route
1046                 ARDOUR::AutoState state = (*it)->route().gain_automation_state();
1047                 if ( state == Touch || state == Play )
1048                 {
1049                         (*it)->notify_all();
1050                 }
1051         }
1052 }
1053
1054 /////////////////////////////////////
1055 // Transport Buttons
1056 /////////////////////////////////////
1057
1058 LedState MackieControlProtocol::rewind_press( Button & button )
1059 {
1060         // can use first_mark_before/after as well
1061         Location * loc = session->locations()->first_location_before (
1062                 session->transport_frame()
1063         );
1064         if ( loc != 0 ) session->request_locate( loc->start(), session->transport_rolling() );
1065         return on;
1066 }
1067
1068 LedState MackieControlProtocol::rewind_release( Button & button )
1069 {
1070         return off;
1071 }
1072
1073 LedState MackieControlProtocol::ffwd_press( Button & button )
1074 {
1075         // can use first_mark_before/after as well
1076         Location * loc = session->locations()->first_location_after (
1077                 session->transport_frame()
1078         );
1079         if ( loc != 0 ) session->request_locate( loc->start(), session->transport_rolling() );
1080         return on;
1081 }
1082
1083 LedState MackieControlProtocol::ffwd_release( Button & button )
1084 {
1085         return off;
1086 }
1087
1088 LedState MackieControlProtocol::stop_press( Button & button )
1089 {
1090         session->request_stop();
1091         return on;
1092 }
1093
1094 LedState MackieControlProtocol::stop_release( Button & button )
1095 {
1096         return session->transport_stopped();
1097 }
1098
1099 LedState MackieControlProtocol::play_press( Button & button )
1100 {
1101         session->request_transport_speed( 1.0 );
1102         return on;
1103 }
1104
1105 LedState MackieControlProtocol::play_release( Button & button )
1106 {
1107         return session->transport_rolling();
1108 }
1109
1110 LedState MackieControlProtocol::record_press( Button & button )
1111 {
1112         if ( session->get_record_enabled() )
1113                 session->disable_record( false );
1114         else
1115                 session->maybe_enable_record();
1116         return on;
1117 }
1118
1119 LedState MackieControlProtocol::record_release( Button & button )
1120 {
1121         if ( session->get_record_enabled() )
1122         {
1123                 if ( session->transport_rolling() )
1124                         return on;
1125                 else
1126                         return flashing;
1127         }
1128         else
1129                 return off;
1130 }
1131
1132 ///////////////////////////////////////////
1133 // Session signals
1134 ///////////////////////////////////////////
1135
1136 void MackieControlProtocol::notify_parameter_changed( const char * name_str )
1137 {
1138         string name( name_str );
1139         if ( name == "punch-in" )
1140         {
1141                 update_global_button( "punch_in", Config->get_punch_in() );
1142         }
1143         else if ( name == "punch-out" )
1144         {
1145                 update_global_button( "punch_out", Config->get_punch_out() );
1146         }
1147 }
1148
1149 // RouteList is the set of routes that have just been added
1150 void MackieControlProtocol::notify_route_added( ARDOUR::Session::RouteList & rl )
1151 {
1152         // currently assigned banks are less than the full set of
1153         // strips, so activate the new strip now.
1154         if ( route_signals.size() < route_table.size() )
1155         {
1156                 refresh_current_bank();
1157         }
1158         // otherwise route added, but current bank needs no updating
1159         
1160         // make sure remote id changes in the new route are handled
1161         typedef ARDOUR::Session::RouteList ARS;
1162         for ( ARS::iterator it = rl.begin(); it != rl.end(); ++it )
1163         {
1164                 (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
1165         }
1166 }
1167
1168 void MackieControlProtocol::notify_solo_active_changed( bool active )
1169 {
1170         Button * rude_solo = reinterpret_cast<Button*>( surface().controls_by_name["solo"] );
1171         mcu_port().write( builder.build_led( *rude_solo, active ? flashing : off ) );
1172 }
1173
1174 void MackieControlProtocol::notify_remote_id_changed()
1175 {
1176         Sorted sorted = get_sorted_routes();
1177         
1178         // if a remote id has been moved off the end, we need to shift
1179         // the current bank backwards.
1180         if ( sorted.size() - _current_initial_bank < route_signals.size() )
1181         {
1182                 // but don't shift backwards past the zeroth channel
1183                 switch_banks( max((Sorted::size_type) 0, sorted.size() - route_signals.size() ) );
1184         }
1185         // Otherwise just refresh the current bank
1186         else
1187         {
1188                 refresh_current_bank();
1189         }
1190 }
1191
1192 ///////////////////////////////////////////
1193 // Transport signals
1194 ///////////////////////////////////////////
1195
1196 void MackieControlProtocol::notify_record_state_changed()
1197 {
1198         // switch rec button on / off / flashing
1199         Button * rec = reinterpret_cast<Button*>( surface().controls_by_name["record"] );
1200         mcu_port().write( builder.build_led( *rec, record_release( *rec ) ) );
1201 }
1202
1203 void MackieControlProtocol::notify_transport_state_changed()
1204 {
1205         // switch various play and stop buttons on / off
1206         update_global_button( "play", session->transport_rolling() );
1207         update_global_button( "stop", !session->transport_rolling() );
1208         update_global_button( "loop", session->get_play_loop() );
1209         
1210         // rec is special because it's tristate
1211         Button * rec = reinterpret_cast<Button*>( surface().controls_by_name["record"] );
1212         mcu_port().write( builder.build_led( *rec, record_release( *rec ) ) );
1213 }
1214
1215 LedState MackieControlProtocol::loop_press( Button & button )
1216 {
1217         session->request_play_loop( !session->get_play_loop() );
1218         return on;
1219 }
1220
1221 LedState MackieControlProtocol::loop_release( Button & button )
1222 {
1223         return session->get_play_loop();
1224 }
1225
1226 LedState MackieControlProtocol::punch_in_press( Button & button )
1227 {
1228         bool state = !Config->get_punch_in();
1229         Config->set_punch_in( state );
1230         return state;
1231 }
1232
1233 LedState MackieControlProtocol::punch_in_release( Button & button )
1234 {
1235         return Config->get_punch_in();
1236 }
1237
1238 LedState MackieControlProtocol::punch_out_press( Button & button )
1239 {
1240         bool state = !Config->get_punch_out();
1241         Config->set_punch_out( state );
1242         return state;
1243 }
1244
1245 LedState MackieControlProtocol::punch_out_release( Button & button )
1246 {
1247         return Config->get_punch_out();
1248 }
1249
1250 LedState MackieControlProtocol::home_press( Button & button )
1251 {
1252         session->goto_start();
1253         return on;
1254 }
1255
1256 LedState MackieControlProtocol::home_release( Button & button )
1257 {
1258         return off;
1259 }
1260
1261 LedState MackieControlProtocol::end_press( Button & button )
1262 {
1263         session->goto_end();
1264         return on;
1265 }
1266
1267 LedState MackieControlProtocol::end_release( Button & button )
1268 {
1269         return off;
1270 }
1271
1272 /////////////////////////////////////
1273 // Bank Switching
1274 /////////////////////////////////////
1275 LedState MackieControlProtocol::left_press( Button & button )
1276 {
1277         Sorted sorted = get_sorted_routes();
1278         if ( sorted.size() > route_table.size() )
1279         {
1280                 int new_initial = _current_initial_bank - route_table.size();
1281                 if ( new_initial < 0 ) new_initial = 0;
1282                 if ( new_initial != int( _current_initial_bank ) )
1283                 {
1284                         session->set_dirty();
1285                         switch_banks( new_initial );
1286                 }
1287                 
1288                 return on;
1289         }
1290         else
1291         {
1292                 return flashing;
1293         }
1294 }
1295
1296 LedState MackieControlProtocol::left_release( Button & button )
1297 {
1298         return off;
1299 }
1300
1301 LedState MackieControlProtocol::right_press( Button & button )
1302 {
1303         Sorted sorted = get_sorted_routes();
1304         if ( sorted.size() > route_table.size() )
1305         {
1306                 uint32_t delta = sorted.size() - ( route_table.size() + _current_initial_bank );
1307                 if ( delta > route_table.size() ) delta = route_table.size();
1308                 if ( delta > 0 )
1309                 {
1310                         session->set_dirty();
1311                         switch_banks( _current_initial_bank + delta );
1312                 }
1313                 
1314                 return on;
1315         }
1316         else
1317         {
1318                 return flashing;
1319         }
1320 }
1321
1322 LedState MackieControlProtocol::right_release( Button & button )
1323 {
1324         return off;
1325 }
1326
1327 LedState MackieControlProtocol::channel_left_press( Button & button )
1328 {
1329         Sorted sorted = get_sorted_routes();
1330         if ( sorted.size() > route_table.size() )
1331         {
1332                 prev_track();
1333                 return on;
1334         }
1335         else
1336         {
1337                 return flashing;
1338         }
1339 }
1340
1341 LedState MackieControlProtocol::channel_left_release( Button & button )
1342 {
1343         return off;
1344 }
1345
1346 LedState MackieControlProtocol::channel_right_press( Button & button )
1347 {
1348         Sorted sorted = get_sorted_routes();
1349         if ( sorted.size() > route_table.size() )
1350         {
1351                 next_track();
1352                 return on;
1353         }
1354         else
1355         {
1356                 return flashing;
1357         }
1358 }
1359
1360 LedState MackieControlProtocol::channel_right_release( Button & button )
1361 {
1362         return off;
1363 }