2 Copyright (C) 2006,2007 John Anderson
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.
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.
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.
33 #include <boost/shared_array.hpp>
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"
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"
54 #include "mackie_control_protocol.h"
56 #include "midi_byte_array.h"
57 #include "mackie_control_exception.h"
58 #include "mackie_midi_builder.h"
59 #include "surface_port.h"
63 #include "control_group.h"
69 using namespace ARDOUR;
71 using namespace Mackie;
77 #include "pbd/abstract_ui.cc" // instantiate template
79 #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
81 const int MackieControlProtocol::MODIFIER_OPTION = 0x1;
82 const int MackieControlProtocol::MODIFIER_CONTROL = 0x2;
83 const int MackieControlProtocol::MODIFIER_SHIFT = 0x3;
84 const int MackieControlProtocol::MODIFIER_CMDALT = 0x4;
86 MackieControlProtocol* MackieControlProtocol::_instance = 0;
88 bool MackieControlProtocol::probe()
93 MackieControlProtocol::MackieControlProtocol (Session& session)
94 : ControlProtocol (session, X_("Mackie"), this)
95 , AbstractUI<MackieControlUIRequest> ("mackie")
96 , _current_initial_bank (0)
97 , _timecode_type (ARDOUR::AnyTime::BBT)
98 , _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
99 , _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
102 , _scrub_mode (false)
104 , _current_selected_track (-1)
106 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
108 AudioEngine::instance()->PortConnectedOrDisconnected.connect (
109 audio_engine_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
116 MackieControlProtocol::~MackieControlProtocol()
118 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol\n");
125 catch (exception & e) {
126 cout << "~MackieControlProtocol caught " << e.what() << endl;
129 cout << "~MackieControlProtocol caught unknown" << endl;
132 DEBUG_TRACE (DEBUG::MackieControl, "finished ~MackieControlProtocol::MackieControlProtocol\n");
138 MackieControlProtocol::thread_init ()
140 struct sched_param rtparam;
142 pthread_set_name (X_("MackieControl"));
144 PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
145 ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
147 memset (&rtparam, 0, sizeof (rtparam));
148 rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
150 if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
151 // do we care? not particularly.
155 // go to the previous track.
156 // Assume that get_sorted_routes().size() > route_table.size()
158 MackieControlProtocol::prev_track()
160 if (_current_initial_bank >= 1) {
161 session->set_dirty();
162 switch_banks (_current_initial_bank - 1);
166 // go to the next track.
167 // Assume that get_sorted_routes().size() > route_table.size()
169 MackieControlProtocol::next_track()
171 Sorted sorted = get_sorted_routes();
172 if (_current_initial_bank + n_strips() < sorted.size()) {
173 session->set_dirty();
174 switch_banks (_current_initial_bank + 1);
178 // predicate for sort call in get_sorted_routes
179 struct RouteByRemoteId
181 bool operator () (const boost::shared_ptr<Route> & a, const boost::shared_ptr<Route> & b) const
183 return a->remote_control_id() < b->remote_control_id();
186 bool operator () (const Route & a, const Route & b) const
188 return a.remote_control_id() < b.remote_control_id();
191 bool operator () (const Route * a, const Route * b) const
193 return a->remote_control_id() < b->remote_control_id();
197 MackieControlProtocol::Sorted
198 MackieControlProtocol::get_sorted_routes()
203 boost::shared_ptr<RouteList> routes = session->get_routes();
204 set<uint32_t> remote_ids;
206 // routes with remote_id 0 should never be added
207 // TODO verify this with ardour devs
208 // remote_ids.insert (0);
210 // sort in remote_id order, and exclude master, control and hidden routes
211 // and any routes that are already set.
212 for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it) {
213 Route & route = **it;
216 && !route.is_master()
217 && !route.is_hidden()
218 && !route.is_monitor()
219 && remote_ids.find (route.remote_control_id()) == remote_ids.end()
221 sorted.push_back (*it);
222 remote_ids.insert (route.remote_control_id());
225 sort (sorted.begin(), sorted.end(), RouteByRemoteId());
230 MackieControlProtocol::refresh_current_bank()
232 switch_banks (_current_initial_bank, true);
236 MackieControlProtocol::n_strips() const
238 uint32_t strip_count = 0;
240 for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
241 if ((*si)->active()) {
242 strip_count += (*si)->n_strips ();
250 MackieControlProtocol::switch_banks (uint32_t initial, bool force)
252 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch banking to start at %1 force ? %2 current = %3\n", initial, force, _current_initial_bank));
254 if (initial == _current_initial_bank && !force) {
255 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
259 Sorted sorted = get_sorted_routes();
260 uint32_t strip_cnt = n_strips();
262 if (sorted.size() <= strip_cnt && !force) {
264 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
268 uint32_t delta = sorted.size() - strip_cnt;
270 if (delta > 0 && initial > delta) {
271 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
275 _current_initial_bank = initial;
276 _current_selected_track = -1;
278 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
279 (*si)->drop_routes ();
282 // Map current bank of routes onto each surface(+strip)
284 if (_current_initial_bank <= sorted.size()) {
286 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available routes %3\n", _current_initial_bank, strip_cnt, sorted.size()));
288 // link routes to strips
290 Sorted::iterator r = sorted.begin() + _current_initial_bank;
292 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
293 vector<boost::shared_ptr<Route> > routes;
296 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface has %1 strips\n", (*si)->n_strips()));
298 for (; r != sorted.end() && added < (*si)->n_strips(); ++r, ++added) {
299 routes.push_back (*r);
300 cerr << "\t\tadded " << (*r)->name() << endl;
303 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("give surface %1 routes\n", routes.size()));
305 (*si)->map_routes (routes);
309 // display the current start bank.
310 surfaces.front()->display_bank_start (_current_initial_bank);
314 MackieControlProtocol::set_active (bool yn)
324 /* start event loop */
329 connect_session_signals ();
334 /* set up periodic task for metering and automation
337 Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
338 periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
339 periodic_timeout->attach (main_loop()->get_context());
348 catch (exception & e) {
349 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
358 MackieControlProtocol::periodic ()
364 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
368 update_timecode_display();
375 MackieControlProtocol::update_timecode_beats_led()
377 switch (_timecode_type) {
378 case ARDOUR::AnyTime::BBT:
379 update_global_led ("beats", on);
380 update_global_led ("timecode", off);
382 case ARDOUR::AnyTime::Timecode:
383 update_global_led ("timecode", on);
384 update_global_led ("beats", off);
388 os << "Unknown Anytime::Type " << _timecode_type;
389 throw runtime_error (os.str());
394 MackieControlProtocol::update_global_button (const string & name, LedState ls)
396 boost::shared_ptr<Surface> surface = surfaces.front();
398 if (!surface->type() == mcu) {
402 if (surface->controls_by_name.find (name) != surface->controls_by_name.end()) {
403 Button * button = dynamic_cast<Button*> (surface->controls_by_name[name]);
404 surface->write (builder.build_led (button->led(), ls));
406 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", name));
411 MackieControlProtocol::update_global_led (const string & name, LedState ls)
413 boost::shared_ptr<Surface> surface = surfaces.front();
415 if (!surface->type() == mcu) {
419 if (surface->controls_by_name.find (name) != surface->controls_by_name.end()) {
420 Led * led = dynamic_cast<Led*> (surface->controls_by_name[name]);
421 surface->write (builder.build_led (*led, ls));
423 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", name));
427 // send messages to surface to set controls to correct values
429 MackieControlProtocol::update_surfaces()
435 // do the initial bank switch to connect signals
436 // _current_initial_bank is initialised by set_state
437 switch_banks (_current_initial_bank, true);
439 // sometimes the jog wheel is a pot
440 surfaces.front()->blank_jog_ring ();
442 // update global buttons and displays
444 notify_record_state_changed();
445 notify_transport_state_changed();
446 update_timecode_beats_led();
450 MackieControlProtocol::connect_session_signals()
452 // receive routes added
453 session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_route_added, this, _1), this);
454 // receive record state toggled
455 session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_record_state_changed, this), this);
456 // receive transport state changed
457 session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), this);
458 session->TransportLooped.connect (session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_loop_state_changed, this), this);
459 // receive punch-in and punch-out
460 Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
461 session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
462 // receive rude solo changed
463 session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), this);
465 // make sure remote id changed signals reach here
466 // see also notify_route_added
467 Sorted sorted = get_sorted_routes();
469 for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
470 (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), this);
475 MackieControlProtocol::create_surfaces ()
477 string device_name = "mcu";
478 surface_type_t stype = mcu;
480 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Create %1 surfaces\n",
481 1 + ARDOUR::Config->get_mackie_extenders()));
483 for (uint32_t n = 0; n < 1 + ARDOUR::Config->get_mackie_extenders(); ++n) {
485 boost::shared_ptr<Surface> surface (new Surface (*this, session->engine().jack(), device_name, n, stype));
486 surfaces.push_back (surface);
488 device_name = "mcu_xt";
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())
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())
504 MIDI::Port& input_port (surface->port().input_port());
506 if ((fd = input_port.selectable ()) >= 0) {
507 Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
509 psrc->connect (sigc::bind (sigc::mem_fun (this, &MackieControlProtocol::midi_input_handler), &input_port));
510 psrc->attach (main_loop()->get_context());
512 // glibmm hack: for now, store only the GSource*
514 port_sources.push_back (psrc->gobj());
515 g_source_ref (psrc->gobj());
521 MackieControlProtocol::close()
525 port_connections.drop_connections ();
526 session_connections.drop_connections ();
527 route_connections.drop_connections ();
528 periodic_connection.disconnect ();
534 MackieControlProtocol::get_state()
536 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state\n");
538 // add name of protocol
539 XMLNode* node = new XMLNode (X_("Protocol"));
540 node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
544 os << _current_initial_bank;
545 node->add_property (X_("bank"), os.str());
551 MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
553 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
557 // fetch current bank
559 if (node.property (X_("bank")) != 0) {
560 string bank = node.property (X_("bank"))->value();
563 uint32_t new_bank = atoi (bank.c_str());
564 if (_current_initial_bank != new_bank) {
565 switch_banks (new_bank);
568 catch (exception & e) {
569 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("exception in MackieControlProtocol::set_state: %1\n", e.what()));
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 /////////////////////////////////////////////////
585 // TODO handle plugin automation polling
587 MackieControlProtocol::format_bbt_timecode (framepos_t now_frame)
589 Timecode::BBT_Time bbt_time;
590 session->bbt_time (now_frame, bbt_time);
592 // According to the Logic docs
593 // digits: 888/88/88/888
594 // BBT mode: Bars/Beats/Subdivisions/Ticks
596 os << setw(3) << setfill('0') << bbt_time.bars;
597 os << setw(2) << setfill('0') << bbt_time.beats;
599 // figure out subdivisions per beat
600 const ARDOUR::Meter & meter = session->tempo_map().meter_at (now_frame);
602 if (meter.note_divisor() == 8 && (meter.divisions_per_bar() == 12.0 || meter.divisions_per_bar() == 9.0 || meter.divisions_per_bar() == 6.0)) {
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);
609 os << setw(2) << setfill('0') << subdivisions + 1;
610 os << setw(3) << setfill('0') << ticks;
616 MackieControlProtocol::format_timecode_timecode (framepos_t now_frame)
618 Timecode::Time timecode;
619 session->timecode_time (now_frame, timecode);
621 // According to the Logic docs
622 // digits: 888/88/88/888
623 // Timecode mode: Hours/Minutes/Seconds/Frames
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;
634 MackieControlProtocol::update_timecode_display()
636 boost::shared_ptr<Surface> surface = surfaces.front();
638 if (surface->type() != mcu || !surface->has_timecode_display()) {
642 // do assignment here so current_frame is fixed
643 framepos_t current_frame = session->transport_frame();
646 switch (_timecode_type) {
647 case ARDOUR::AnyTime::BBT:
648 timecode = format_bbt_timecode (current_frame);
650 case ARDOUR::AnyTime::Timecode:
651 timecode = format_timecode_timecode (current_frame);
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;
665 ///////////////////////////////////////////
667 ///////////////////////////////////////////
669 void MackieControlProtocol::notify_parameter_changed (std::string const & p)
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());
678 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
682 // RouteList is the set of routes that have just been added
684 MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
686 // currently assigned banks are less than the full set of
687 // strips, so activate the new strip now.
689 refresh_current_bank();
691 // otherwise route added, but current bank needs no updating
693 // make sure remote id changes in the new route are handled
694 typedef ARDOUR::RouteList ARS;
696 for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
697 (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
702 MackieControlProtocol::notify_solo_active_changed (bool active)
704 boost::shared_ptr<Surface> surface = surfaces.front();
706 Button * rude_solo = reinterpret_cast<Button*> (surface->controls_by_name["solo"]);
709 surface->write (builder.build_led (*rude_solo, active ? flashing : off));
714 MackieControlProtocol::notify_remote_id_changed()
716 Sorted sorted = get_sorted_routes();
717 uint32_t sz = n_strips();
719 // if a remote id has been moved off the end, we need to shift
720 // the current bank backwards.
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));
726 // Otherwise just refresh the current bank
727 refresh_current_bank();
731 ///////////////////////////////////////////
733 ///////////////////////////////////////////
736 MackieControlProtocol::notify_loop_state_changed()
738 update_global_button ("loop", session->get_play_loop());
742 MackieControlProtocol::notify_transport_state_changed()
744 // switch various play and stop buttons on / off
745 update_global_button ("play", session->transport_rolling());
746 update_global_button ("stop", !session->transport_rolling());
747 update_global_button ("rewind", session->transport_speed() < 0.0);
748 update_global_button ("ffwd", session->transport_speed() > 1.0);
750 _transport_previously_rolling = session->transport_rolling();
755 MackieControlProtocol::notify_record_state_changed ()
757 Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
761 switch (session->record_status()) {
762 case Session::Disabled:
765 case Session::Recording:
768 case Session::Enabled:
773 surfaces.front()->write (builder.build_led (*rec, ls));
777 list<boost::shared_ptr<ARDOUR::Bundle> >
778 MackieControlProtocol::bundles ()
780 list<boost::shared_ptr<ARDOUR::Bundle> > b;
781 b.push_back (_input_bundle);
782 b.push_back (_output_bundle);
787 MackieControlProtocol::port_connected_or_disconnected (string a, string b, bool connected)
789 /* If something is connected to one of our output ports, send MIDI to update the surface
790 to whatever state it should have.
797 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
798 string const n = AudioEngine::instance()->make_port_name_non_relative ((*s)->port().output_port().name ());
799 if (a == n || b == n) {
807 MackieControlProtocol::do_request (MackieControlUIRequest* req)
809 if (req->type == CallSlot) {
811 call_slot (MISSING_INVALIDATOR, req->the_slot);
813 } else if (req->type == Quit) {
820 MackieControlProtocol::stop ()
827 /** Add a timeout so that a control's in_use flag will be reset some time in the future.
828 * @param in_use_control the control whose in_use flag to reset.
829 * @param touch_control a touch control to emit an event for, or 0.
832 MackieControlProtocol::add_in_use_timeout (Surface& surface, Control& in_use_control, Control* touch_control)
834 Glib::RefPtr<Glib::TimeoutSource> timeout (Glib::TimeoutSource::create (250)); // milliseconds
836 in_use_control.in_use_connection.disconnect ();
837 in_use_control.in_use_connection = timeout->connect (
838 sigc::bind (sigc::mem_fun (*this, &MackieControlProtocol::control_in_use_timeout), &surface, &in_use_control, touch_control));
839 in_use_control.in_use_touch_control = touch_control;
841 timeout->attach (main_loop()->get_context());
843 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("timeout queued for surface %1, control %2 touch control %3\n",
844 surface.number(), &in_use_control, touch_control));}
846 /** Handle timeouts to reset in_use for controls that can't
847 * do this by themselves (e.g. pots, and faders without touch support).
848 * @param in_use_control the control whose in_use flag to reset.
849 * @param touch_control a touch control to emit an event for, or 0.
852 MackieControlProtocol::control_in_use_timeout (Surface* surface, Control* in_use_control, Control* touch_control)
854 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("timeout elapsed for surface %1, control %2 touch control %3\n",
855 surface->number(), in_use_control, touch_control));
857 in_use_control->set_in_use (false);
860 // empty control_state
861 ControlState control_state;
862 surface->handle_control_event (*touch_control, control_state);
865 // only call this method once from the timer
870 MackieControlProtocol::update_led (Surface& surface, Button& button, Mackie::LedState ls)
873 surface.port().write (builder.build_led (button, ls));
878 MackieControlProtocol::handle_button_event (Surface& surface, Button& button, ButtonState bs)
880 if (bs != press && bs != release) {
881 update_led (surface, button, none);
887 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2\n", (bs == press ? "press" : "release"), button.raw_id()));
889 switch (button.raw_id()) {
892 case press: ls = io_press (button); break;
893 case release: ls = io_release (button); break;
900 case press: ls = sends_press (button); break;
901 case release: ls = sends_release (button); break;
908 case press: ls = pan_press (button); break;
909 case release: ls = pan_release (button); break;
916 case press: ls = plugin_press (button); break;
917 case release: ls = plugin_release (button); break;
924 case press: ls = eq_press (button); break;
925 case release: ls = eq_release (button); break;
932 case press: ls = dyn_press (button); break;
933 case release: ls = dyn_release (button); break;
940 case press: ls = left_press (button); break;
941 case release: ls = left_release (button); break;
948 case press: ls = right_press (button); break;
949 case release: ls = right_release (button); break;
954 case 0x30: // channel_left
956 case press: ls = channel_left_press (button); break;
957 case release: ls = channel_left_release (button); break;
962 case 0x31: // channel_right
964 case press: ls = channel_right_press (button); break;
965 case release: ls = channel_right_release (button); break;
972 case press: ls = flip_press (button); break;
973 case release: ls = flip_release (button); break;
980 case press: ls = edit_press (button); break;
981 case release: ls = edit_release (button); break;
986 case 0x34: // name_value
988 case press: ls = name_value_press (button); break;
989 case release: ls = name_value_release (button); break;
994 case 0x35: // timecode_beats
996 case press: ls = timecode_beats_press (button); break;
997 case release: ls = timecode_beats_release (button); break;
1004 case press: ls = F1_press (button); break;
1005 case release: ls = F1_release (button); break;
1006 case neither: break;
1012 case press: ls = F2_press (button); break;
1013 case release: ls = F2_release (button); break;
1014 case neither: break;
1020 case press: ls = F3_press (button); break;
1021 case release: ls = F3_release (button); break;
1022 case neither: break;
1028 case press: ls = F4_press (button); break;
1029 case release: ls = F4_release (button); break;
1030 case neither: break;
1036 case press: ls = F5_press (button); break;
1037 case release: ls = F5_release (button); break;
1038 case neither: break;
1044 case press: ls = F6_press (button); break;
1045 case release: ls = F6_release (button); break;
1046 case neither: break;
1052 case press: ls = F7_press (button); break;
1053 case release: ls = F7_release (button); break;
1054 case neither: break;
1060 case press: ls = F8_press (button); break;
1061 case release: ls = F8_release (button); break;
1062 case neither: break;
1068 case press: ls = F9_press (button); break;
1069 case release: ls = F9_release (button); break;
1070 case neither: break;
1076 case press: ls = F10_press (button); break;
1077 case release: ls = F10_release (button); break;
1078 case neither: break;
1084 case press: ls = F11_press (button); break;
1085 case release: ls = F11_release (button); break;
1086 case neither: break;
1092 case press: ls = F12_press (button); break;
1093 case release: ls = F12_release (button); break;
1094 case neither: break;
1100 case press: ls = F13_press (button); break;
1101 case release: ls = F13_release (button); break;
1102 case neither: break;
1108 case press: ls = F14_press (button); break;
1109 case release: ls = F14_release (button); break;
1110 case neither: break;
1116 case press: ls = F15_press (button); break;
1117 case release: ls = F15_release (button); break;
1118 case neither: break;
1124 case press: ls = F16_press (button); break;
1125 case release: ls = F16_release (button); break;
1126 case neither: break;
1132 case press: ls = shift_press (button); break;
1133 case release: ls = shift_release (button); break;
1134 case neither: break;
1138 case 0x47: // option
1140 case press: ls = option_press (button); break;
1141 case release: ls = option_release (button); break;
1142 case neither: break;
1148 case press: ls = control_press (button); break;
1149 case release: ls = control_release (button); break;
1150 case neither: break;
1154 case 0x49: // cmd_alt
1156 case press: ls = cmd_alt_press (button); break;
1157 case release: ls = cmd_alt_release (button); break;
1158 case neither: break;
1164 case press: ls = on_press (button); break;
1165 case release: ls = on_release (button); break;
1166 case neither: break;
1170 case 0x4b: // rec_ready
1172 case press: ls = rec_ready_press (button); break;
1173 case release: ls = rec_ready_release (button); break;
1174 case neither: break;
1178 case Button::Undo: // undo
1180 case press: ls = undo_press (button); break;
1181 case release: ls = undo_release (button); break;
1182 case neither: break;
1188 case press: ls = save_press (button); break;
1189 case release: ls = save_release (button); break;
1190 case neither: break;
1194 case Button::Touch: // touch
1196 case press: ls = touch_press (button); break;
1197 case release: ls = touch_release (button); break;
1198 case neither: break;
1202 case Button::Redo: // redo
1204 case press: ls = redo_press (button); break;
1205 case release: ls = redo_release (button); break;
1206 case neither: break;
1210 case Button::Marker: // marker
1212 case press: ls = marker_press (button); break;
1213 case release: ls = marker_release (button); break;
1214 case neither: break;
1218 case Button::Enter: // enter
1220 case press: ls = enter_press (button); break;
1221 case release: ls = enter_release (button); break;
1222 case neither: break;
1226 case 0x52: // cancel
1228 case press: ls = cancel_press (button); break;
1229 case release: ls = cancel_release (button); break;
1230 case neither: break;
1236 case press: ls = mixer_press (button); break;
1237 case release: ls = mixer_release (button); break;
1238 case neither: break;
1242 case 0x54: // frm_left
1244 case press: ls = frm_left_press (button); break;
1245 case release: ls = frm_left_release (button); break;
1246 case neither: break;
1250 case 0x55: // frm_right
1252 case press: ls = frm_right_press (button); break;
1253 case release: ls = frm_right_release (button); break;
1254 case neither: break;
1260 case press: ls = loop_press (button); break;
1261 case release: ls = loop_release (button); break;
1262 case neither: break;
1266 case 0x57: // punch_in
1268 case press: ls = punch_in_press (button); break;
1269 case release: ls = punch_in_release (button); break;
1270 case neither: break;
1274 case 0x58: // punch_out
1276 case press: ls = punch_out_press (button); break;
1277 case release: ls = punch_out_release (button); break;
1278 case neither: break;
1284 case press: ls = home_press (button); break;
1285 case release: ls = home_release (button); break;
1286 case neither: break;
1292 case press: ls = end_press (button); break;
1293 case release: ls = end_release (button); break;
1294 case neither: break;
1298 case Button::Rewind:
1300 case press: ls = rewind_press (button); break;
1301 case release: ls = rewind_release (button); break;
1302 case neither: break;
1308 case press: ls = ffwd_press (button); break;
1309 case release: ls = ffwd_release (button); break;
1310 case neither: break;
1316 case press: ls = stop_press (button); break;
1317 case release: ls = stop_release (button); break;
1318 case neither: break;
1324 case press: ls = play_press (button); break;
1325 case release: ls = play_release (button); break;
1326 case neither: break;
1330 case 0x5f: // record
1332 case press: ls = record_press (button); break;
1333 case release: ls = record_release (button); break;
1334 case neither: break;
1338 case 0x60: // cursor_up
1340 case press: ls = cursor_up_press (button); break;
1341 case release: ls = cursor_up_release (button); break;
1342 case neither: break;
1346 case 0x61: // cursor_down
1348 case press: ls = cursor_down_press (button); break;
1349 case release: ls = cursor_down_release (button); break;
1350 case neither: break;
1354 case 0x62: // cursor_left
1356 case press: ls = cursor_left_press (button); break;
1357 case release: ls = cursor_left_release (button); break;
1358 case neither: break;
1362 case 0x63: // cursor_right
1364 case press: ls = cursor_right_press (button); break;
1365 case release: ls = cursor_right_release (button); break;
1366 case neither: break;
1372 case press: ls = zoom_press (button); break;
1373 case release: ls = zoom_release (button); break;
1374 case neither: break;
1380 case press: ls = scrub_press (button); break;
1381 case release: ls = scrub_release (button); break;
1382 case neither: break;
1386 case 0x66: // user_a
1388 case press: ls = user_a_press (button); break;
1389 case release: ls = user_a_release (button); break;
1390 case neither: break;
1394 case 0x67: // user_b
1396 case press: ls = user_b_press (button); break;
1397 case release: ls = user_b_release (button); break;
1398 case neither: break;
1404 update_led (surface, button, ls);
1408 MackieControlProtocol::select_track (boost::shared_ptr<Route> r)
1410 if (_modifier_state == MODIFIER_SHIFT) {
1411 r->gain_control()->set_value (0.0);
1413 if (_current_selected_track > 0 && r->remote_control_id() == (uint32_t) _current_selected_track) {
1414 UnselectTrack (); /* EMIT SIGNAL */
1415 _current_selected_track = -1;
1417 SelectByRID (r->remote_control_id()); /* EMIT SIGNAL */
1418 _current_selected_track = r->remote_control_id();;
1424 MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
1426 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", port->name()));
1434 CrossThreadChannel::drain (port->selectable());
1436 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
1437 framepos_t now = session->engine().frame_time();
1445 MackieControlProtocol::clear_ports ()
1447 for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
1448 g_source_destroy (*i);
1449 g_source_unref (*i);
1452 port_sources.clear ();