1eab8bf1d432b21a4aee599b8aaf4ddc735685cd
[ardour.git] / libs / surfaces / mackie / mackie_control_protocol.cc
1 /*
2         Copyright (C) 2006,2007 John Anderson
3
4         This program is free software; you can redistribute it and/or modify
5         it under the terms of the GNU General Public License as published by
6         the Free Software Foundation; either version 2 of the License, or
7         (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12         GNU General Public License for more details.
13
14         You should have received a copy of the GNU General Public License
15         along with this program; if not, write to the Free Software
16         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <fcntl.h>
20 #include <iostream>
21 #include <algorithm>
22 #include <cmath>
23 #include <sstream>
24 #include <vector>
25 #include <iomanip>
26
27 #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 "pbd/pthread_utils.h"
38 #include "pbd/error.h"
39 #include "pbd/memento_command.h"
40 #include "pbd/convert.h"
41
42 #include "ardour/dB.h"
43 #include "ardour/debug.h"
44 #include "ardour/location.h"
45 #include "ardour/meter.h"
46 #include "ardour/panner.h"
47 #include "ardour/panner_shell.h"
48 #include "ardour/route.h"
49 #include "ardour/session.h"
50 #include "ardour/tempo.h"
51 #include "ardour/types.h"
52 #include "ardour/audioengine.h"
53
54 #include "mackie_control_protocol.h"
55
56 #include "midi_byte_array.h"
57 #include "mackie_control_exception.h"
58 #include "mackie_midi_builder.h"
59 #include "surface_port.h"
60 #include "surface.h"
61
62 #include "strip.h"
63 #include "control_group.h"
64 #include "meter.h"
65 #include "button.h"
66 #include "fader.h"
67 #include "pot.h"
68
69 using namespace ARDOUR;
70 using namespace std;
71 using namespace Mackie;
72 using namespace PBD;
73 using namespace Glib;
74
75 #include "i18n.h"
76
77 #include "pbd/abstract_ui.cc" // instantiate template
78
79 #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
80 extern PBD::EventLoop::InvalidationRecord* __invalidator (sigc::trackable& trackable, const char*, int);
81 #define invalidator() __invalidator ((*this), __FILE__, __LINE__)
82
83 const int MackieControlProtocol::MODIFIER_OPTION = 0x1;
84 const int MackieControlProtocol::MODIFIER_CONTROL = 0x2;
85 const int MackieControlProtocol::MODIFIER_SHIFT = 0x3;
86 const int MackieControlProtocol::MODIFIER_CMDALT = 0x4;
87
88 MackieControlProtocol* MackieControlProtocol::_instance = 0;
89
90 bool MackieControlProtocol::probe()
91 {
92         return true;
93 }
94
95 MackieControlProtocol::MackieControlProtocol (Session& session)
96         : ControlProtocol (session, X_("Mackie"), this)
97         , AbstractUI<MackieControlUIRequest> ("mackie")
98         , _current_initial_bank (0)
99         , _timecode_type (ARDOUR::AnyTime::BBT)
100         , _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
101         , _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
102         , _gui (0)
103         , _zoom_mode (false)
104         , _scrub_mode (false)
105         , _current_selected_track (-1)
106 {
107         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
108
109         AudioEngine::instance()->PortConnectedOrDisconnected.connect (
110                 audio_engine_connections, invalidator (), ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
111                 this
112                 );
113
114         _instance = this;
115 }
116
117 MackieControlProtocol::~MackieControlProtocol()
118 {
119         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol\n");
120
121         _active = false;
122
123         try {
124                 close();
125         }
126         catch (exception & e) {
127                 cout << "~MackieControlProtocol caught " << e.what() << endl;
128         }
129         catch (...) {
130                 cout << "~MackieControlProtocol caught unknown" << endl;
131         }
132
133         DEBUG_TRACE (DEBUG::MackieControl, "finished ~MackieControlProtocol::MackieControlProtocol\n");
134
135         _instance = 0;
136 }
137
138 void
139 MackieControlProtocol::thread_init ()
140 {
141         struct sched_param rtparam;
142
143         pthread_set_name (X_("MackieControl"));
144
145         PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
146         ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
147
148         memset (&rtparam, 0, sizeof (rtparam));
149         rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
150
151         if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
152                 // do we care? not particularly.
153         }
154 }
155
156 // go to the previous track.
157 // Assume that get_sorted_routes().size() > route_table.size()
158 void 
159 MackieControlProtocol::prev_track()
160 {
161         if (_current_initial_bank >= 1) {
162                 session->set_dirty();
163                 switch_banks (_current_initial_bank - 1);
164         }
165 }
166
167 // go to the next track.
168 // Assume that get_sorted_routes().size() > route_table.size()
169 void 
170 MackieControlProtocol::next_track()
171 {
172         Sorted sorted = get_sorted_routes();
173         if (_current_initial_bank + n_strips() < sorted.size()) {
174                 session->set_dirty();
175                 switch_banks (_current_initial_bank + 1);
176         }
177 }
178
179 // predicate for sort call in get_sorted_routes
180 struct RouteByRemoteId
181 {
182         bool operator () (const boost::shared_ptr<Route> & a, const boost::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 
199 MackieControlProtocol::get_sorted_routes()
200 {
201         Sorted sorted;
202
203         // fetch all routes
204         boost::shared_ptr<RouteList> routes = session->get_routes();
205         set<uint32_t> remote_ids;
206
207         // routes with remote_id 0 should never be added
208         // TODO verify this with ardour devs
209         // remote_ids.insert (0);
210
211         // sort in remote_id order, and exclude master, control and hidden routes
212         // and any routes that are already set.
213         for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it) {
214                 Route & route = **it;
215                 if (
216                         route.active()
217                         && !route.is_master()
218                         && !route.is_hidden()
219                         && !route.is_monitor()
220                         && remote_ids.find (route.remote_control_id()) == remote_ids.end()
221                         ) {
222                         sorted.push_back (*it);
223                         remote_ids.insert (route.remote_control_id());
224                 }
225         }
226         sort (sorted.begin(), sorted.end(), RouteByRemoteId());
227         return sorted;
228 }
229
230 void 
231 MackieControlProtocol::refresh_current_bank()
232 {
233         switch_banks (_current_initial_bank, true);
234 }
235
236 uint32_t
237 MackieControlProtocol::n_strips() const
238 {
239         uint32_t strip_count = 0;
240
241         for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
242                 if ((*si)->active()) {
243                         strip_count += (*si)->n_strips ();
244                 }
245         }
246
247         return strip_count;
248 }
249
250 void 
251 MackieControlProtocol::switch_banks (uint32_t initial, bool force)
252 {
253         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch banking to start at %1 force ? %2 current = %3\n", initial, force, _current_initial_bank));
254
255         if (initial == _current_initial_bank && !force) {
256                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
257                 return;
258         }
259
260         Sorted sorted = get_sorted_routes();
261         uint32_t strip_cnt = n_strips();
262
263         if (sorted.size() <= strip_cnt && !force) {
264                 /* no banking */
265                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
266                 return;
267         }
268
269         uint32_t delta = sorted.size() - strip_cnt;
270
271         if (delta > 0 && initial > delta) {
272                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
273                 return;
274         }
275
276         _current_initial_bank = initial;
277         _current_selected_track = -1;
278
279         for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
280                 (*si)->drop_routes ();
281         }
282
283         // Map current bank of routes onto each surface(+strip)
284
285         if (_current_initial_bank <= sorted.size()) {
286
287                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available routes %3\n", _current_initial_bank, strip_cnt, sorted.size()));
288
289                 // link routes to strips
290
291                 Sorted::iterator r = sorted.begin() + _current_initial_bank;
292                 
293                 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
294                         vector<boost::shared_ptr<Route> > routes;
295                         uint32_t added = 0;
296
297                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface has %1 strips\n", (*si)->n_strips()));
298
299                         for (; r != sorted.end() && added < (*si)->n_strips(); ++r, ++added) {
300                                 routes.push_back (*r);
301                                 cerr << "\t\tadded " << (*r)->name() << endl;
302                         }
303
304                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("give surface %1 routes\n", routes.size()));
305
306                         (*si)->map_routes (routes);
307                 }
308         }
309
310         // display the current start bank.
311         surfaces.front()->display_bank_start (_current_initial_bank);
312 }
313
314 int 
315 MackieControlProtocol::set_active (bool yn)
316 {
317         if (yn == _active) {
318                 return 0;
319         }
320
321         try
322         {
323                 if (yn) {
324
325                         /* start event loop */
326
327                         BaseUI::run ();
328
329                         create_surfaces ();
330                         connect_session_signals ();
331                         
332                         _active = true;
333                         update_surfaces ();
334
335                         /* set up periodic task for metering and automation
336                          */
337
338                         Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
339                         periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
340                         periodic_timeout->attach (main_loop()->get_context());
341
342                 } else {
343                         BaseUI::quit ();
344                         close();
345                         _active = false;
346                 }
347         }
348         
349         catch (exception & e) {
350                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
351                 _active = false;
352                 throw;
353         }
354
355         return 0;
356 }
357
358 bool
359 MackieControlProtocol::periodic ()
360 {
361         if (!_active) {
362                 return false;
363         }
364
365         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
366                 (*s)->periodic ();
367         }
368         
369         update_timecode_display();
370
371         return true;
372 }
373
374
375 void 
376 MackieControlProtocol::update_timecode_beats_led()
377 {
378         switch (_timecode_type) {
379                 case ARDOUR::AnyTime::BBT:
380                         update_global_led ("beats", on);
381                         update_global_led ("timecode", off);
382                         break;
383                 case ARDOUR::AnyTime::Timecode:
384                         update_global_led ("timecode", on);
385                         update_global_led ("beats", off);
386                         break;
387                 default:
388                         ostringstream os;
389                         os << "Unknown Anytime::Type " << _timecode_type;
390                         throw runtime_error (os.str());
391         }
392 }
393
394 void 
395 MackieControlProtocol::update_global_button (const string & name, LedState ls)
396 {
397         boost::shared_ptr<Surface> surface = surfaces.front();
398
399         if (!surface->type() == mcu) {
400                 return;
401         }
402
403         if (surface->controls_by_name.find (name) != surface->controls_by_name.end()) {
404                 Button * button = dynamic_cast<Button*> (surface->controls_by_name[name]);
405                 surface->write (builder.build_led (button->led(), ls));
406         } else {
407                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", name));
408         }
409 }
410
411 void 
412 MackieControlProtocol::update_global_led (const string & name, LedState ls)
413 {
414         boost::shared_ptr<Surface> surface = surfaces.front();
415
416         if (!surface->type() == mcu) {
417                 return;
418         }
419
420         if (surface->controls_by_name.find (name) != surface->controls_by_name.end()) {
421                 Led * led = dynamic_cast<Led*> (surface->controls_by_name[name]);
422                 surface->write (builder.build_led (*led, ls));
423         } else {
424                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", name));
425         }
426 }
427
428 // send messages to surface to set controls to correct values
429 void 
430 MackieControlProtocol::update_surfaces()
431 {
432         if (!_active) {
433                 return;
434         }
435
436         // do the initial bank switch to connect signals
437         // _current_initial_bank is initialised by set_state
438         switch_banks (_current_initial_bank, true);
439         
440         // sometimes the jog wheel is a pot
441         surfaces.front()->blank_jog_ring ();
442         
443         // update global buttons and displays
444
445         notify_record_state_changed();
446         notify_transport_state_changed();
447         update_timecode_beats_led();
448 }
449
450 void 
451 MackieControlProtocol::connect_session_signals()
452 {
453         // receive routes added
454         session->RouteAdded.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_route_added, this, _1), this);
455         // receive record state toggled
456         session->RecordStateChanged.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_record_state_changed, this), this);
457         // receive transport state changed
458         session->TransportStateChange.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), this);
459         // receive punch-in and punch-out
460         Config->ParameterChanged.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
461         session->config.ParameterChanged.connect (session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
462         // receive rude solo changed
463         session->SoloActive.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), this);
464
465         // make sure remote id changed signals reach here
466         // see also notify_route_added
467         Sorted sorted = get_sorted_routes();
468
469         for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
470                 (*it)->RemoteControlIDChanged.connect (route_connections, invalidator(), ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), this);
471         }
472 }
473
474 void 
475 MackieControlProtocol::create_surfaces ()
476 {
477         string device_name = "mcu";
478         surface_type_t stype = mcu;
479
480         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Create %1 surfaces\n",
481                                                            1 + ARDOUR::Config->get_mackie_extenders()));
482
483         for (uint32_t n = 0; n < 1 + ARDOUR::Config->get_mackie_extenders(); ++n) {
484
485                 boost::shared_ptr<Surface> surface (new Surface (*this, session->engine().jack(), device_name, n, stype));
486                 surfaces.push_back (surface);
487                 
488                 device_name = "mcu_xt";
489                 stype = ext;
490
491                 _input_bundle->add_channel (
492                         surface->port().input_port().name(),
493                         ARDOUR::DataType::MIDI,
494                         session->engine().make_port_name_non_relative (surface->port().input_port().name())
495                         );
496                 
497                 _output_bundle->add_channel (
498                         surface->port().output_port().name(),
499                         ARDOUR::DataType::MIDI,
500                         session->engine().make_port_name_non_relative (surface->port().output_port().name())
501                         );
502
503                 int fd;
504                 MIDI::Port& input_port (surface->port().input_port());
505                 
506                 if ((fd = input_port.selectable ()) >= 0) {
507                         Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
508
509                         psrc->connect (sigc::bind (sigc::mem_fun (this, &MackieControlProtocol::midi_input_handler), &input_port));
510                         psrc->attach (main_loop()->get_context());
511                         
512                         // glibmm hack: for now, store only the GSource*
513
514                         port_sources.push_back (psrc->gobj());
515                         g_source_ref (psrc->gobj());
516                 }
517         }
518 }
519
520 void 
521 MackieControlProtocol::close()
522 {
523         clear_ports ();
524
525         port_connections.drop_connections ();
526         session_connections.drop_connections ();
527         route_connections.drop_connections ();
528         periodic_connection.disconnect ();
529
530         surfaces.clear ();
531 }
532
533 XMLNode& 
534 MackieControlProtocol::get_state()
535 {
536         DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state\n");
537
538         // add name of protocol
539         XMLNode* node = new XMLNode (X_("Protocol"));
540         node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
541
542         // add current bank
543         ostringstream os;
544         os << _current_initial_bank;
545         node->add_property (X_("bank"), os.str());
546
547         return *node;
548 }
549
550 int 
551 MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
552 {
553         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
554
555         int retval = 0;
556
557         // fetch current bank
558
559         if (node.property (X_("bank")) != 0) {
560                 string bank = node.property (X_("bank"))->value();
561                 try {
562                         set_active (true);
563                         uint32_t new_bank = atoi (bank.c_str());
564                         if (_current_initial_bank != new_bank) {
565                                 switch_banks (new_bank);
566                         }
567                 }
568                 catch (exception & e) {
569                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("exception in MackieControlProtocol::set_state: %1\n", e.what()));
570                         return -1;
571                 }
572         }
573
574         return retval;
575 }
576
577
578 /////////////////////////////////////////////////
579 // handlers for Route signals
580 // TODO should these be part of RouteSignal?
581 // They started off as signal/slot handlers for signals
582 // from Route, but they're also used in polling for automation
583 /////////////////////////////////////////////////
584
585 // TODO handle plugin automation polling
586 string 
587 MackieControlProtocol::format_bbt_timecode (framepos_t now_frame)
588 {
589         Timecode::BBT_Time bbt_time;
590         session->bbt_time (now_frame, bbt_time);
591
592         // According to the Logic docs
593         // digits: 888/88/88/888
594         // BBT mode: Bars/Beats/Subdivisions/Ticks
595         ostringstream os;
596         os << setw(3) << setfill('0') << bbt_time.bars;
597         os << setw(2) << setfill('0') << bbt_time.beats;
598
599         // figure out subdivisions per beat
600         const ARDOUR::Meter & meter = session->tempo_map().meter_at (now_frame);
601         int subdiv = 2;
602         if (meter.note_divisor() == 8 && (meter.divisions_per_bar() == 12.0 || meter.divisions_per_bar() == 9.0 || meter.divisions_per_bar() == 6.0)) {
603                 subdiv = 3;
604         }
605
606         uint32_t subdivisions = bbt_time.ticks / uint32_t (Timecode::BBT_Time::ticks_per_beat / subdiv);
607         uint32_t ticks = bbt_time.ticks % uint32_t (Timecode::BBT_Time::ticks_per_beat / subdiv);
608
609         os << setw(2) << setfill('0') << subdivisions + 1;
610         os << setw(3) << setfill('0') << ticks;
611
612         return os.str();
613 }
614
615 string 
616 MackieControlProtocol::format_timecode_timecode (framepos_t now_frame)
617 {
618         Timecode::Time timecode;
619         session->timecode_time (now_frame, timecode);
620
621         // According to the Logic docs
622         // digits: 888/88/88/888
623         // Timecode mode: Hours/Minutes/Seconds/Frames
624         ostringstream os;
625         os << setw(3) << setfill('0') << timecode.hours;
626         os << setw(2) << setfill('0') << timecode.minutes;
627         os << setw(2) << setfill('0') << timecode.seconds;
628         os << setw(3) << setfill('0') << timecode.frames;
629
630         return os.str();
631 }
632
633 void 
634 MackieControlProtocol::update_timecode_display()
635 {
636         boost::shared_ptr<Surface> surface = surfaces.front();
637
638         if (surface->type() != mcu || !surface->has_timecode_display()) {
639                 return;
640         }
641
642         // do assignment here so current_frame is fixed
643         framepos_t current_frame = session->transport_frame();
644         string timecode;
645
646         switch (_timecode_type) {
647         case ARDOUR::AnyTime::BBT:
648                 timecode = format_bbt_timecode (current_frame);
649                 break;
650         case ARDOUR::AnyTime::Timecode:
651                 timecode = format_timecode_timecode (current_frame);
652                 break;
653         default:
654                 return;
655         }
656         
657         // only write the timecode string to the MCU if it's changed
658         // since last time. This is to reduce midi bandwidth used.
659         if (timecode != _timecode_last) {
660                 surface->display_timecode (timecode, _timecode_last);
661                 _timecode_last = timecode;
662         }
663 }
664
665 ///////////////////////////////////////////
666 // Session signals
667 ///////////////////////////////////////////
668
669 void MackieControlProtocol::notify_parameter_changed (std::string const & p)
670 {
671         if (p == "punch-in") {
672                 update_global_button ("punch_in", session->config.get_punch_in());
673         } else if (p == "punch-out") {
674                 update_global_button ("punch_out", session->config.get_punch_out());
675         } else if (p == "clicking") {
676                 update_global_button ("clicking", Config->get_clicking());
677         } else {
678                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
679         }
680 }
681
682 // RouteList is the set of routes that have just been added
683 void 
684 MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
685 {
686         // currently assigned banks are less than the full set of
687         // strips, so activate the new strip now.
688
689         refresh_current_bank();
690
691         // otherwise route added, but current bank needs no updating
692
693         // make sure remote id changes in the new route are handled
694         typedef ARDOUR::RouteList ARS;
695
696         for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
697                 (*it)->RemoteControlIDChanged.connect (route_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
698         }
699 }
700
701 void 
702 MackieControlProtocol::notify_solo_active_changed (bool active)
703 {
704         boost::shared_ptr<Surface> surface = surfaces.front();
705         
706         Button * rude_solo = reinterpret_cast<Button*> (surface->controls_by_name["solo"]);
707
708         if (rude_solo) {
709                 surface->write (builder.build_led (*rude_solo, active ? flashing : off));
710         }
711 }
712
713 void 
714 MackieControlProtocol::notify_remote_id_changed()
715 {
716         Sorted sorted = get_sorted_routes();
717         uint32_t sz = n_strips();
718
719         // if a remote id has been moved off the end, we need to shift
720         // the current bank backwards.
721
722         if (sorted.size() - _current_initial_bank < sz) {
723                 // but don't shift backwards past the zeroth channel
724                 switch_banks (max((Sorted::size_type) 0, sorted.size() - sz));
725         } else {
726                 // Otherwise just refresh the current bank
727                 refresh_current_bank();
728         }
729 }
730
731 ///////////////////////////////////////////
732 // Transport signals
733 ///////////////////////////////////////////
734
735 void 
736 MackieControlProtocol::notify_record_state_changed()
737 {
738         // switch rec button on / off / flashing
739         Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
740         if (rec) {
741                 surfaces.front()->write (builder.build_led (*rec, record_release (*rec)));
742         }
743 }
744
745 void 
746 MackieControlProtocol::notify_transport_state_changed()
747 {
748         // switch various play and stop buttons on / off
749         update_global_button ("play", session->transport_rolling());
750         update_global_button ("stop", !session->transport_rolling());
751         update_global_button ("loop", session->get_play_loop());
752
753         _transport_previously_rolling = session->transport_rolling();
754
755         // rec is special because it's tristate
756         Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
757         if (rec) {
758                 surfaces.front()->write (builder.build_led (*rec, record_release (*rec)));
759         }
760 }
761
762 list<boost::shared_ptr<ARDOUR::Bundle> >
763 MackieControlProtocol::bundles ()
764 {
765         list<boost::shared_ptr<ARDOUR::Bundle> > b;
766         b.push_back (_input_bundle);
767         b.push_back (_output_bundle);
768         return b;
769 }
770
771 void
772 MackieControlProtocol::port_connected_or_disconnected (string a, string b, bool connected)
773 {
774         /* If something is connected to one of our output ports, send MIDI to update the surface
775            to whatever state it should have.
776         */
777
778         if (!connected) {
779                 return;
780         }
781
782         for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
783                 string const n = AudioEngine::instance()->make_port_name_non_relative ((*s)->port().output_port().name ());
784                 if (a == n || b == n) {
785                         update_surfaces ();
786                         return;
787                 }
788         }
789 }
790
791 void
792 MackieControlProtocol::do_request (MackieControlUIRequest* req)
793 {
794         if (req->type == CallSlot) {
795
796                 call_slot (invalidator(), req->the_slot);
797
798         } else if (req->type == Quit) {
799
800                 stop ();
801         }
802 }
803
804 int
805 MackieControlProtocol::stop ()
806 {
807         BaseUI::quit ();
808
809         return 0;
810 }
811
812 /** Add a timeout so that a control's in_use flag will be reset some time in the future.
813  *  @param in_use_control the control whose in_use flag to reset.
814  *  @param touch_control a touch control to emit an event for, or 0.
815  */
816 void
817 MackieControlProtocol::add_in_use_timeout (Surface& surface, Control& in_use_control, Control* touch_control)
818 {
819         Glib::RefPtr<Glib::TimeoutSource> timeout (Glib::TimeoutSource::create (250)); // milliseconds
820
821         in_use_control.in_use_connection.disconnect ();
822         in_use_control.in_use_connection = timeout->connect (
823                 sigc::bind (sigc::mem_fun (*this, &MackieControlProtocol::control_in_use_timeout), &surface, &in_use_control, touch_control));
824         in_use_control.in_use_touch_control = touch_control;
825         
826         timeout->attach (main_loop()->get_context());
827
828         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("timeout queued for surface %1, control %2 touch control %3\n",
829                                                            surface.number(), &in_use_control, touch_control));}
830
831 /** Handle timeouts to reset in_use for controls that can't
832  *  do this by themselves (e.g. pots, and faders without touch support).
833  *  @param in_use_control the control whose in_use flag to reset.
834  *  @param touch_control a touch control to emit an event for, or 0.
835  */
836 bool
837 MackieControlProtocol::control_in_use_timeout (Surface* surface, Control* in_use_control, Control* touch_control)
838 {
839         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("timeout elapsed for surface %1, control %2 touch control %3\n",
840                                                            surface->number(), in_use_control, touch_control));
841
842         in_use_control->set_in_use (false);
843
844         if (touch_control) {
845                 // empty control_state
846                 ControlState control_state;
847                 surface->handle_control_event (*touch_control, control_state);
848         }
849         
850         // only call this method once from the timer
851         return false;
852 }
853
854 void 
855 MackieControlProtocol::update_led (Surface& surface, Button& button, Mackie::LedState ls)
856 {
857         if (ls != none) {
858                 surface.port().write (builder.build_led (button, ls));
859         }
860 }
861
862 void 
863 MackieControlProtocol::handle_button_event (Surface& surface, Button& button, ButtonState bs)
864 {
865         if  (bs != press && bs != release) {
866                 update_led (surface, button, none);
867                 return;
868         }
869         
870         LedState ls;
871
872         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2\n", (bs == press ? "press" : "release"), button.raw_id()));
873
874         switch  (button.raw_id()) {
875         case 0x28: // io
876                 switch  (bs) {
877                 case press: ls = io_press (button); break;
878                 case release: ls = io_release (button); break;
879                 case neither: break;
880                 }
881                 break;
882                 
883         case 0x29: // sends
884                 switch  (bs) {
885                 case press: ls = sends_press (button); break;
886                 case release: ls = sends_release (button); break;
887                 case neither: break;
888                 }
889                 break;
890                 
891         case 0x2a: // pan
892                 switch  (bs) {
893                 case press: ls = pan_press (button); break;
894                 case release: ls = pan_release (button); break;
895                 case neither: break;
896                 }
897                 break;
898                 
899         case 0x2b: // plugin
900                 switch  (bs) {
901                 case press: ls = plugin_press (button); break;
902                 case release: ls = plugin_release (button); break;
903                 case neither: break;
904                 }
905                 break;
906                 
907         case 0x2c: // eq
908                 switch  (bs) {
909                 case press: ls = eq_press (button); break;
910                 case release: ls = eq_release (button); break;
911                 case neither: break;
912                 }
913                 break;
914                 
915         case 0x2d: // dyn
916                 switch  (bs) {
917                 case press: ls = dyn_press (button); break;
918                 case release: ls = dyn_release (button); break;
919                 case neither: break;
920                 }
921                 break;
922                 
923         case 0x2e: // left
924                 switch  (bs) {
925                 case press: ls = left_press (button); break;
926                 case release: ls = left_release (button); break;
927                 case neither: break;
928                 }
929                 break;
930                 
931         case 0x2f: // right
932                 switch  (bs) {
933                 case press: ls = right_press (button); break;
934                 case release: ls = right_release (button); break;
935                 case neither: break;
936                 }
937                 break;
938                 
939         case 0x30: // channel_left
940                 switch  (bs) {
941                 case press: ls = channel_left_press (button); break;
942                 case release: ls = channel_left_release (button); break;
943                 case neither: break;
944                 }
945                 break;
946                 
947         case 0x31: // channel_right
948                 switch  (bs) {
949                 case press: ls = channel_right_press (button); break;
950                 case release: ls = channel_right_release (button); break;
951                 case neither: break;
952                 }
953                 break;
954                 
955         case 0x32: // flip
956                 switch  (bs) {
957                 case press: ls = flip_press (button); break;
958                 case release: ls = flip_release (button); break;
959                 case neither: break;
960                 }
961                 break;
962
963         case 0x33: // edit
964                 switch  (bs) {
965                 case press: ls = edit_press (button); break;
966                 case release: ls = edit_release (button); break;
967                 case neither: break;
968                 }
969                 break;
970
971         case 0x34: // name_value
972                 switch  (bs) {
973                 case press: ls = name_value_press (button); break;
974                 case release: ls = name_value_release (button); break;
975                 case neither: break;
976                 }
977                 break;
978
979         case 0x35: // timecode_beats
980                 switch  (bs) {
981                 case press: ls = timecode_beats_press (button); break;
982                 case release: ls = timecode_beats_release (button); break;
983                 case neither: break;
984                 }
985                 break;
986
987         case 0x36: // F1
988                 switch  (bs) {
989                 case press: ls = F1_press (button); break;
990                 case release: ls = F1_release (button); break;
991                 case neither: break;
992                 }
993                 break;
994
995         case 0x37: // F2
996                 switch  (bs) {
997                 case press: ls = F2_press (button); break;
998                 case release: ls = F2_release (button); break;
999                 case neither: break;
1000                 }
1001                 break;
1002
1003         case 0x38: // F3
1004                 switch  (bs) {
1005                 case press: ls = F3_press (button); break;
1006                 case release: ls = F3_release (button); break;
1007                 case neither: break;
1008                 }
1009                 break;
1010
1011         case 0x39: // F4
1012                 switch  (bs) {
1013                 case press: ls = F4_press (button); break;
1014                 case release: ls = F4_release (button); break;
1015                 case neither: break;
1016                 }
1017                 break;
1018
1019         case 0x3a: // F5
1020                 switch  (bs) {
1021                 case press: ls = F5_press (button); break;
1022                 case release: ls = F5_release (button); break;
1023                 case neither: break;
1024                 }
1025                 break;
1026
1027         case 0x3b: // F6
1028                 switch  (bs) {
1029                 case press: ls = F6_press (button); break;
1030                 case release: ls = F6_release (button); break;
1031                 case neither: break;
1032                 }
1033                 break;
1034
1035         case 0x3c: // F7
1036                 switch  (bs) {
1037                 case press: ls = F7_press (button); break;
1038                 case release: ls = F7_release (button); break;
1039                 case neither: break;
1040                 }
1041                 break;
1042
1043         case 0x3d: // F8
1044                 switch  (bs) {
1045                 case press: ls = F8_press (button); break;
1046                 case release: ls = F8_release (button); break;
1047                 case neither: break;
1048                 }
1049                 break;
1050
1051         case 0x3e: // F9
1052                 switch  (bs) {
1053                 case press: ls = F9_press (button); break;
1054                 case release: ls = F9_release (button); break;
1055                 case neither: break;
1056                 }
1057                 break;
1058
1059         case 0x3f: // F10
1060                 switch  (bs) {
1061                 case press: ls = F10_press (button); break;
1062                 case release: ls = F10_release (button); break;
1063                 case neither: break;
1064                 }
1065                 break;
1066
1067         case 0x40: // F11
1068                 switch  (bs) {
1069                 case press: ls = F11_press (button); break;
1070                 case release: ls = F11_release (button); break;
1071                 case neither: break;
1072                 }
1073                 break;
1074
1075         case 0x41: // F12
1076                 switch  (bs) {
1077                 case press: ls = F12_press (button); break;
1078                 case release: ls = F12_release (button); break;
1079                 case neither: break;
1080                 }
1081                 break;
1082
1083         case 0x42: // F13
1084                 switch  (bs) {
1085                 case press: ls = F13_press (button); break;
1086                 case release: ls = F13_release (button); break;
1087                 case neither: break;
1088                 }
1089                 break;
1090
1091         case 0x43: // F14
1092                 switch  (bs) {
1093                 case press: ls = F14_press (button); break;
1094                 case release: ls = F14_release (button); break;
1095                 case neither: break;
1096                 }
1097                 break;
1098
1099         case 0x44: // F15
1100                 switch  (bs) {
1101                 case press: ls = F15_press (button); break;
1102                 case release: ls = F15_release (button); break;
1103                 case neither: break;
1104                 }
1105                 break;
1106
1107         case 0x45: // F16
1108                 switch  (bs) {
1109                 case press: ls = F16_press (button); break;
1110                 case release: ls = F16_release (button); break;
1111                 case neither: break;
1112                 }
1113                 break;
1114
1115         case 0x46: // shift
1116                 switch  (bs) {
1117                 case press: ls = shift_press (button); break;
1118                 case release: ls = shift_release (button); break;
1119                 case neither: break;
1120                 }
1121                 break;
1122
1123         case 0x47: // option
1124                 switch  (bs) {
1125                 case press: ls = option_press (button); break;
1126                 case release: ls = option_release (button); break;
1127                 case neither: break;
1128                 }
1129                 break;
1130
1131         case 0x48: // control
1132                 switch  (bs) {
1133                 case press: ls = control_press (button); break;
1134                 case release: ls = control_release (button); break;
1135                 case neither: break;
1136                 }
1137                 break;
1138
1139         case 0x49: // cmd_alt
1140                 switch  (bs) {
1141                 case press: ls = cmd_alt_press (button); break;
1142                 case release: ls = cmd_alt_release (button); break;
1143                 case neither: break;
1144                 }
1145                 break;
1146
1147         case 0x4a: // on
1148                 switch  (bs) {
1149                 case press: ls = on_press (button); break;
1150                 case release: ls = on_release (button); break;
1151                 case neither: break;
1152                 }
1153                 break;
1154
1155         case 0x4b: // rec_ready
1156                 switch  (bs) {
1157                 case press: ls = rec_ready_press (button); break;
1158                 case release: ls = rec_ready_release (button); break;
1159                 case neither: break;
1160                 }
1161                 break;
1162
1163         case 0x4c: // undo
1164                 switch  (bs) {
1165                 case press: ls = undo_press (button); break;
1166                 case release: ls = undo_release (button); break;
1167                 case neither: break;
1168                 }
1169                 break;
1170
1171         case 0x4d: // snapshot
1172                 switch  (bs) {
1173                 case press: ls = snapshot_press (button); break;
1174                 case release: ls = snapshot_release (button); break;
1175                 case neither: break;
1176                 }
1177                 break;
1178
1179         case 0x4e: // touch
1180                 switch  (bs) {
1181                 case press: ls = touch_press (button); break;
1182                 case release: ls = touch_release (button); break;
1183                 case neither: break;
1184                 }
1185                 break;
1186
1187         case 0x4f: // redo
1188                 switch  (bs) {
1189                 case press: ls = redo_press (button); break;
1190                 case release: ls = redo_release (button); break;
1191                 case neither: break;
1192                 }
1193                 break;
1194
1195         case 0x50: // marker
1196                 switch  (bs) {
1197                 case press: ls = marker_press (button); break;
1198                 case release: ls = marker_release (button); break;
1199                 case neither: break;
1200                 }
1201                 break;
1202
1203         case 0x51: // enter
1204                 switch  (bs) {
1205                 case press: ls = enter_press (button); break;
1206                 case release: ls = enter_release (button); break;
1207                 case neither: break;
1208                 }
1209                 break;
1210
1211         case 0x52: // cancel
1212                 switch  (bs) {
1213                 case press: ls = cancel_press (button); break;
1214                 case release: ls = cancel_release (button); break;
1215                 case neither: break;
1216                 }
1217                 break;
1218
1219         case 0x53: // mixer
1220                 switch  (bs) {
1221                 case press: ls = mixer_press (button); break;
1222                 case release: ls = mixer_release (button); break;
1223                 case neither: break;
1224                 }
1225                 break;
1226
1227         case 0x54: // frm_left
1228                 switch  (bs) {
1229                 case press: ls = frm_left_press (button); break;
1230                 case release: ls = frm_left_release (button); break;
1231                 case neither: break;
1232                 }
1233                 break;
1234
1235         case 0x55: // frm_right
1236                 switch  (bs) {
1237                 case press: ls = frm_right_press (button); break;
1238                 case release: ls = frm_right_release (button); break;
1239                 case neither: break;
1240                 }
1241                 break;
1242
1243         case 0x56: // loop
1244                 switch  (bs) {
1245                 case press: ls = loop_press (button); break;
1246                 case release: ls = loop_release (button); break;
1247                 case neither: break;
1248                 }
1249                 break;
1250
1251         case 0x57: // punch_in
1252                 switch  (bs) {
1253                 case press: ls = punch_in_press (button); break;
1254                 case release: ls = punch_in_release (button); break;
1255                 case neither: break;
1256                 }
1257                 break;
1258
1259         case 0x58: // punch_out
1260                 switch  (bs) {
1261                 case press: ls = punch_out_press (button); break;
1262                 case release: ls = punch_out_release (button); break;
1263                 case neither: break;
1264                 }
1265                 break;
1266
1267         case 0x59: // home
1268                 switch  (bs) {
1269                 case press: ls = home_press (button); break;
1270                 case release: ls = home_release (button); break;
1271                 case neither: break;
1272                 }
1273                 break;
1274
1275         case 0x5a: // end
1276                 switch  (bs) {
1277                 case press: ls = end_press (button); break;
1278                 case release: ls = end_release (button); break;
1279                 case neither: break;
1280                 }
1281                 break;
1282
1283         case 0x5b: // rewind
1284                 switch  (bs) {
1285                 case press: ls = rewind_press (button); break;
1286                 case release: ls = rewind_release (button); break;
1287                 case neither: break;
1288                 }
1289                 break;
1290
1291         case 0x5c: // ffwd
1292                 switch  (bs) {
1293                 case press: ls = ffwd_press (button); break;
1294                 case release: ls = ffwd_release (button); break;
1295                 case neither: break;
1296                 }
1297                 break;
1298
1299         case 0x5d: // stop
1300                 switch  (bs) {
1301                 case press: ls = stop_press (button); break;
1302                 case release: ls = stop_release (button); break;
1303                 case neither: break;
1304                 }
1305                 break;
1306
1307         case 0x5e: // play
1308                 switch  (bs) {
1309                 case press: ls = play_press (button); break;
1310                 case release: ls = play_release (button); break;
1311                 case neither: break;
1312                 }
1313                 break;
1314
1315         case 0x5f: // record
1316                 switch  (bs) {
1317                 case press: ls = record_press (button); break;
1318                 case release: ls = record_release (button); break;
1319                 case neither: break;
1320                 }
1321                 break;
1322
1323         case 0x60: // cursor_up
1324                 switch  (bs) {
1325                 case press: ls = cursor_up_press (button); break;
1326                 case release: ls = cursor_up_release (button); break;
1327                 case neither: break;
1328                 }
1329                 break;
1330
1331         case 0x61: // cursor_down
1332                 switch  (bs) {
1333                 case press: ls = cursor_down_press (button); break;
1334                 case release: ls = cursor_down_release (button); break;
1335                 case neither: break;
1336                 }
1337                 break;
1338
1339         case 0x62: // cursor_left
1340                 switch  (bs) {
1341                 case press: ls = cursor_left_press (button); break;
1342                 case release: ls = cursor_left_release (button); break;
1343                 case neither: break;
1344                 }
1345                 break;
1346
1347         case 0x63: // cursor_right
1348                 switch  (bs) {
1349                 case press: ls = cursor_right_press (button); break;
1350                 case release: ls = cursor_right_release (button); break;
1351                 case neither: break;
1352                 }
1353                 break;
1354
1355         case 0x64: // zoom
1356                 switch  (bs) {
1357                 case press: ls = zoom_press (button); break;
1358                 case release: ls = zoom_release (button); break;
1359                 case neither: break;
1360                 }
1361                 break;
1362
1363         case 0x65: // scrub
1364                 switch  (bs) {
1365                 case press: ls = scrub_press (button); break;
1366                 case release: ls = scrub_release (button); break;
1367                 case neither: break;
1368                 }
1369                 break;
1370
1371         case 0x66: // user_a
1372                 switch  (bs) {
1373                 case press: ls = user_a_press (button); break;
1374                 case release: ls = user_a_release (button); break;
1375                 case neither: break;
1376                 }
1377                 break;
1378
1379         case 0x67: // user_b
1380                 switch  (bs) {
1381                 case press: ls = user_b_press (button); break;
1382                 case release: ls = user_b_release (button); break;
1383                 case neither: break;
1384                 }
1385                 break;
1386
1387         }
1388
1389         update_led (surface, button, ls);
1390 }
1391
1392 void
1393 MackieControlProtocol::select_track (boost::shared_ptr<Route> r)
1394 {
1395         if (_modifier_state == MODIFIER_SHIFT) {
1396                 r->gain_control()->set_value (0.0);
1397         } else {
1398                 if (_current_selected_track > 0 && r->remote_control_id() == (uint32_t) _current_selected_track) {
1399                         UnselectTrack (); /* EMIT SIGNAL */
1400                         _current_selected_track = -1;
1401                 } else {
1402                         SelectByRID (r->remote_control_id()); /* EMIT SIGNAL */
1403                         _current_selected_track = r->remote_control_id();;
1404                 }
1405         }
1406 }
1407
1408 bool
1409 MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
1410 {
1411         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on  %1\n", port->name()));
1412
1413         if (ioc & ~IO_IN) {
1414                 return false;
1415         }
1416
1417         if (ioc & IO_IN) {
1418
1419                 CrossThreadChannel::drain (port->selectable());
1420
1421                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
1422                 framepos_t now = session->engine().frame_time();
1423                 port->parse (now);
1424         }
1425
1426         return true;
1427 }
1428
1429 void
1430 MackieControlProtocol::clear_ports ()
1431 {
1432         for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
1433                 g_source_destroy (*i);
1434                 g_source_unref (*i);
1435         }
1436
1437         port_sources.clear ();
1438 }
1439