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__))
80 extern PBD::EventLoop::InvalidationRecord* __invalidator (sigc::trackable& trackable, const char*, int);
81 #define invalidator() __invalidator ((*this), __FILE__, __LINE__)
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;
88 MackieControlProtocol* MackieControlProtocol::_instance = 0;
90 bool MackieControlProtocol::probe()
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))
104 , _scrub_mode (false)
105 , _current_selected_track (-1)
107 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
109 AudioEngine::instance()->PortConnectedOrDisconnected.connect (
110 audio_engine_connections, invalidator (), ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
117 MackieControlProtocol::~MackieControlProtocol()
119 DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol\n");
126 catch (exception & e) {
127 cout << "~MackieControlProtocol caught " << e.what() << endl;
130 cout << "~MackieControlProtocol caught unknown" << endl;
133 DEBUG_TRACE (DEBUG::MackieControl, "finished ~MackieControlProtocol::MackieControlProtocol\n");
139 MackieControlProtocol::thread_init ()
141 struct sched_param rtparam;
143 pthread_set_name (X_("MackieControl"));
145 PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
146 ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
148 memset (&rtparam, 0, sizeof (rtparam));
149 rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
151 if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
152 // do we care? not particularly.
156 // go to the previous track.
157 // Assume that get_sorted_routes().size() > route_table.size()
159 MackieControlProtocol::prev_track()
161 if (_current_initial_bank >= 1) {
162 session->set_dirty();
163 switch_banks (_current_initial_bank - 1);
167 // go to the next track.
168 // Assume that get_sorted_routes().size() > route_table.size()
170 MackieControlProtocol::next_track()
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);
179 // predicate for sort call in get_sorted_routes
180 struct RouteByRemoteId
182 bool operator () (const boost::shared_ptr<Route> & a, const boost::shared_ptr<Route> & b) const
184 return a->remote_control_id() < b->remote_control_id();
187 bool operator () (const Route & a, const Route & b) const
189 return a.remote_control_id() < b.remote_control_id();
192 bool operator () (const Route * a, const Route * b) const
194 return a->remote_control_id() < b->remote_control_id();
198 MackieControlProtocol::Sorted
199 MackieControlProtocol::get_sorted_routes()
204 boost::shared_ptr<RouteList> routes = session->get_routes();
205 set<uint32_t> remote_ids;
207 // routes with remote_id 0 should never be added
208 // TODO verify this with ardour devs
209 // remote_ids.insert (0);
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;
217 && !route.is_master()
218 && !route.is_hidden()
219 && !route.is_monitor()
220 && remote_ids.find (route.remote_control_id()) == remote_ids.end()
222 sorted.push_back (*it);
223 remote_ids.insert (route.remote_control_id());
226 sort (sorted.begin(), sorted.end(), RouteByRemoteId());
231 MackieControlProtocol::refresh_current_bank()
233 switch_banks (_current_initial_bank, true);
237 MackieControlProtocol::n_strips() const
239 uint32_t strip_count = 0;
241 for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
242 if ((*si)->active()) {
243 strip_count += (*si)->n_strips ();
251 MackieControlProtocol::switch_banks (uint32_t initial, bool force)
253 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch banking to start at %1 force ? %2 current = %3\n", initial, force, _current_initial_bank));
255 if (initial == _current_initial_bank && !force) {
256 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
260 Sorted sorted = get_sorted_routes();
261 uint32_t strip_cnt = n_strips();
263 if (sorted.size() <= strip_cnt && !force) {
265 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
269 uint32_t delta = sorted.size() - strip_cnt;
271 if (delta > 0 && initial > delta) {
272 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("not switching to %1\n", initial));
276 _current_initial_bank = initial;
277 _current_selected_track = -1;
279 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
280 (*si)->drop_routes ();
283 // Map current bank of routes onto each surface(+strip)
285 if (_current_initial_bank <= sorted.size()) {
287 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available routes %3\n", _current_initial_bank, strip_cnt, sorted.size()));
289 // link routes to strips
291 Sorted::iterator r = sorted.begin() + _current_initial_bank;
293 for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
294 vector<boost::shared_ptr<Route> > routes;
297 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface has %1 strips\n", (*si)->n_strips()));
299 for (; r != sorted.end() && added < (*si)->n_strips(); ++r, ++added) {
300 routes.push_back (*r);
301 cerr << "\t\tadded " << (*r)->name() << endl;
304 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("give surface %1 routes\n", routes.size()));
306 (*si)->map_routes (routes);
310 // display the current start bank.
311 surfaces.front()->display_bank_start (_current_initial_bank);
315 MackieControlProtocol::set_active (bool yn)
325 /* start event loop */
330 connect_session_signals ();
335 /* set up periodic task for metering and automation
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());
349 catch (exception & e) {
350 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
359 MackieControlProtocol::periodic ()
365 for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
369 update_timecode_display();
376 MackieControlProtocol::update_timecode_beats_led()
378 switch (_timecode_type) {
379 case ARDOUR::AnyTime::BBT:
380 update_global_led ("beats", on);
381 update_global_led ("timecode", off);
383 case ARDOUR::AnyTime::Timecode:
384 update_global_led ("timecode", on);
385 update_global_led ("beats", off);
389 os << "Unknown Anytime::Type " << _timecode_type;
390 throw runtime_error (os.str());
395 MackieControlProtocol::update_global_button (const string & name, LedState ls)
397 boost::shared_ptr<Surface> surface = surfaces.front();
399 if (!surface->type() == mcu) {
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));
407 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", name));
412 MackieControlProtocol::update_global_led (const string & name, LedState ls)
414 boost::shared_ptr<Surface> surface = surfaces.front();
416 if (!surface->type() == mcu) {
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));
424 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", name));
428 // send messages to surface to set controls to correct values
430 MackieControlProtocol::update_surfaces()
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);
440 // sometimes the jog wheel is a pot
441 surfaces.front()->blank_jog_ring ();
443 // update global buttons and displays
445 notify_record_state_changed();
446 notify_transport_state_changed();
447 update_timecode_beats_led();
451 MackieControlProtocol::connect_session_signals()
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);
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, 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, 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_record_state_changed()
738 // switch rec button on / off / flashing
739 Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
741 surfaces.front()->write (builder.build_led (*rec, record_release (*rec)));
746 MackieControlProtocol::notify_transport_state_changed()
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());
753 _transport_previously_rolling = session->transport_rolling();
755 // rec is special because it's tristate
756 Button * rec = reinterpret_cast<Button*> (surfaces.front()->controls_by_name["record"]);
758 surfaces.front()->write (builder.build_led (*rec, record_release (*rec)));
762 list<boost::shared_ptr<ARDOUR::Bundle> >
763 MackieControlProtocol::bundles ()
765 list<boost::shared_ptr<ARDOUR::Bundle> > b;
766 b.push_back (_input_bundle);
767 b.push_back (_output_bundle);
772 MackieControlProtocol::port_connected_or_disconnected (string a, string b, bool connected)
774 /* If something is connected to one of our output ports, send MIDI to update the surface
775 to whatever state it should have.
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) {
792 MackieControlProtocol::do_request (MackieControlUIRequest* req)
794 if (req->type == CallSlot) {
796 call_slot (invalidator(), req->the_slot);
798 } else if (req->type == Quit) {
805 MackieControlProtocol::stop ()
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.
817 MackieControlProtocol::add_in_use_timeout (Surface& surface, Control& in_use_control, Control* touch_control)
819 Glib::RefPtr<Glib::TimeoutSource> timeout (Glib::TimeoutSource::create (250)); // milliseconds
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;
826 timeout->attach (main_loop()->get_context());
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));}
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.
837 MackieControlProtocol::control_in_use_timeout (Surface* surface, Control* in_use_control, Control* touch_control)
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));
842 in_use_control->set_in_use (false);
845 // empty control_state
846 ControlState control_state;
847 surface->handle_control_event (*touch_control, control_state);
850 // only call this method once from the timer
855 MackieControlProtocol::update_led (Surface& surface, Button& button, Mackie::LedState ls)
858 surface.port().write (builder.build_led (button, ls));
863 MackieControlProtocol::handle_button_event (Surface& surface, Button& button, ButtonState bs)
865 if (bs != press && bs != release) {
866 update_led (surface, button, none);
872 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2\n", (bs == press ? "press" : "release"), button.raw_id()));
874 switch (button.raw_id()) {
877 case press: ls = io_press (button); break;
878 case release: ls = io_release (button); break;
885 case press: ls = sends_press (button); break;
886 case release: ls = sends_release (button); break;
893 case press: ls = pan_press (button); break;
894 case release: ls = pan_release (button); break;
901 case press: ls = plugin_press (button); break;
902 case release: ls = plugin_release (button); break;
909 case press: ls = eq_press (button); break;
910 case release: ls = eq_release (button); break;
917 case press: ls = dyn_press (button); break;
918 case release: ls = dyn_release (button); break;
925 case press: ls = left_press (button); break;
926 case release: ls = left_release (button); break;
933 case press: ls = right_press (button); break;
934 case release: ls = right_release (button); break;
939 case 0x30: // channel_left
941 case press: ls = channel_left_press (button); break;
942 case release: ls = channel_left_release (button); break;
947 case 0x31: // channel_right
949 case press: ls = channel_right_press (button); break;
950 case release: ls = channel_right_release (button); break;
957 case press: ls = flip_press (button); break;
958 case release: ls = flip_release (button); break;
965 case press: ls = edit_press (button); break;
966 case release: ls = edit_release (button); break;
971 case 0x34: // name_value
973 case press: ls = name_value_press (button); break;
974 case release: ls = name_value_release (button); break;
979 case 0x35: // timecode_beats
981 case press: ls = timecode_beats_press (button); break;
982 case release: ls = timecode_beats_release (button); break;
989 case press: ls = F1_press (button); break;
990 case release: ls = F1_release (button); break;
997 case press: ls = F2_press (button); break;
998 case release: ls = F2_release (button); break;
1005 case press: ls = F3_press (button); break;
1006 case release: ls = F3_release (button); break;
1007 case neither: break;
1013 case press: ls = F4_press (button); break;
1014 case release: ls = F4_release (button); break;
1015 case neither: break;
1021 case press: ls = F5_press (button); break;
1022 case release: ls = F5_release (button); break;
1023 case neither: break;
1029 case press: ls = F6_press (button); break;
1030 case release: ls = F6_release (button); break;
1031 case neither: break;
1037 case press: ls = F7_press (button); break;
1038 case release: ls = F7_release (button); break;
1039 case neither: break;
1045 case press: ls = F8_press (button); break;
1046 case release: ls = F8_release (button); break;
1047 case neither: break;
1053 case press: ls = F9_press (button); break;
1054 case release: ls = F9_release (button); break;
1055 case neither: break;
1061 case press: ls = F10_press (button); break;
1062 case release: ls = F10_release (button); break;
1063 case neither: break;
1069 case press: ls = F11_press (button); break;
1070 case release: ls = F11_release (button); break;
1071 case neither: break;
1077 case press: ls = F12_press (button); break;
1078 case release: ls = F12_release (button); break;
1079 case neither: break;
1085 case press: ls = F13_press (button); break;
1086 case release: ls = F13_release (button); break;
1087 case neither: break;
1093 case press: ls = F14_press (button); break;
1094 case release: ls = F14_release (button); break;
1095 case neither: break;
1101 case press: ls = F15_press (button); break;
1102 case release: ls = F15_release (button); break;
1103 case neither: break;
1109 case press: ls = F16_press (button); break;
1110 case release: ls = F16_release (button); break;
1111 case neither: break;
1117 case press: ls = shift_press (button); break;
1118 case release: ls = shift_release (button); break;
1119 case neither: break;
1123 case 0x47: // option
1125 case press: ls = option_press (button); break;
1126 case release: ls = option_release (button); break;
1127 case neither: break;
1131 case 0x48: // control
1133 case press: ls = control_press (button); break;
1134 case release: ls = control_release (button); break;
1135 case neither: break;
1139 case 0x49: // cmd_alt
1141 case press: ls = cmd_alt_press (button); break;
1142 case release: ls = cmd_alt_release (button); break;
1143 case neither: break;
1149 case press: ls = on_press (button); break;
1150 case release: ls = on_release (button); break;
1151 case neither: break;
1155 case 0x4b: // rec_ready
1157 case press: ls = rec_ready_press (button); break;
1158 case release: ls = rec_ready_release (button); break;
1159 case neither: break;
1165 case press: ls = undo_press (button); break;
1166 case release: ls = undo_release (button); break;
1167 case neither: break;
1171 case 0x4d: // snapshot
1173 case press: ls = snapshot_press (button); break;
1174 case release: ls = snapshot_release (button); break;
1175 case neither: break;
1181 case press: ls = touch_press (button); break;
1182 case release: ls = touch_release (button); break;
1183 case neither: break;
1189 case press: ls = redo_press (button); break;
1190 case release: ls = redo_release (button); break;
1191 case neither: break;
1195 case 0x50: // marker
1197 case press: ls = marker_press (button); break;
1198 case release: ls = marker_release (button); break;
1199 case neither: break;
1205 case press: ls = enter_press (button); break;
1206 case release: ls = enter_release (button); break;
1207 case neither: break;
1211 case 0x52: // cancel
1213 case press: ls = cancel_press (button); break;
1214 case release: ls = cancel_release (button); break;
1215 case neither: break;
1221 case press: ls = mixer_press (button); break;
1222 case release: ls = mixer_release (button); break;
1223 case neither: break;
1227 case 0x54: // frm_left
1229 case press: ls = frm_left_press (button); break;
1230 case release: ls = frm_left_release (button); break;
1231 case neither: break;
1235 case 0x55: // frm_right
1237 case press: ls = frm_right_press (button); break;
1238 case release: ls = frm_right_release (button); break;
1239 case neither: break;
1245 case press: ls = loop_press (button); break;
1246 case release: ls = loop_release (button); break;
1247 case neither: break;
1251 case 0x57: // punch_in
1253 case press: ls = punch_in_press (button); break;
1254 case release: ls = punch_in_release (button); break;
1255 case neither: break;
1259 case 0x58: // punch_out
1261 case press: ls = punch_out_press (button); break;
1262 case release: ls = punch_out_release (button); break;
1263 case neither: break;
1269 case press: ls = home_press (button); break;
1270 case release: ls = home_release (button); break;
1271 case neither: break;
1277 case press: ls = end_press (button); break;
1278 case release: ls = end_release (button); break;
1279 case neither: break;
1283 case 0x5b: // rewind
1285 case press: ls = rewind_press (button); break;
1286 case release: ls = rewind_release (button); break;
1287 case neither: break;
1293 case press: ls = ffwd_press (button); break;
1294 case release: ls = ffwd_release (button); break;
1295 case neither: break;
1301 case press: ls = stop_press (button); break;
1302 case release: ls = stop_release (button); break;
1303 case neither: break;
1309 case press: ls = play_press (button); break;
1310 case release: ls = play_release (button); break;
1311 case neither: break;
1315 case 0x5f: // record
1317 case press: ls = record_press (button); break;
1318 case release: ls = record_release (button); break;
1319 case neither: break;
1323 case 0x60: // cursor_up
1325 case press: ls = cursor_up_press (button); break;
1326 case release: ls = cursor_up_release (button); break;
1327 case neither: break;
1331 case 0x61: // cursor_down
1333 case press: ls = cursor_down_press (button); break;
1334 case release: ls = cursor_down_release (button); break;
1335 case neither: break;
1339 case 0x62: // cursor_left
1341 case press: ls = cursor_left_press (button); break;
1342 case release: ls = cursor_left_release (button); break;
1343 case neither: break;
1347 case 0x63: // cursor_right
1349 case press: ls = cursor_right_press (button); break;
1350 case release: ls = cursor_right_release (button); break;
1351 case neither: break;
1357 case press: ls = zoom_press (button); break;
1358 case release: ls = zoom_release (button); break;
1359 case neither: break;
1365 case press: ls = scrub_press (button); break;
1366 case release: ls = scrub_release (button); break;
1367 case neither: break;
1371 case 0x66: // user_a
1373 case press: ls = user_a_press (button); break;
1374 case release: ls = user_a_release (button); break;
1375 case neither: break;
1379 case 0x67: // user_b
1381 case press: ls = user_b_press (button); break;
1382 case release: ls = user_b_release (button); break;
1383 case neither: break;
1389 update_led (surface, button, ls);
1393 MackieControlProtocol::select_track (boost::shared_ptr<Route> r)
1395 if (_modifier_state == MODIFIER_SHIFT) {
1396 r->gain_control()->set_value (0.0);
1398 if (_current_selected_track > 0 && r->remote_control_id() == (uint32_t) _current_selected_track) {
1399 UnselectTrack (); /* EMIT SIGNAL */
1400 _current_selected_track = -1;
1402 SelectByRID (r->remote_control_id()); /* EMIT SIGNAL */
1403 _current_selected_track = r->remote_control_id();;
1409 MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
1411 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", port->name()));
1419 CrossThreadChannel::drain (port->selectable());
1421 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
1422 framepos_t now = session->engine().frame_time();
1430 MackieControlProtocol::clear_ports ()
1432 for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
1433 g_source_destroy (*i);
1434 g_source_unref (*i);
1437 port_sources.clear ();