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