2 Copyright (C) 2006 Paul Davis
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.
25 #include <glibmm/miscutils.h>
27 #include "pbd/controllable_descriptor.h"
28 #include "pbd/error.h"
29 #include "pbd/failed_constructor.h"
30 #include "pbd/pathscanner.h"
31 #include "pbd/xml++.h"
33 #include "midi++/port.h"
34 #include "midi++/manager.h"
36 #include "ardour/filesystem_paths.h"
37 #include "ardour/session.h"
38 #include "ardour/route.h"
39 #include "ardour/midi_ui.h"
40 #include "ardour/rc_configuration.h"
42 #include "generic_midi_control_protocol.h"
43 #include "midicontrollable.h"
44 #include "midifunction.h"
45 #include "midiaction.h"
47 using namespace ARDOUR;
53 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
54 #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
56 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
57 : ControlProtocol (s, _("Generic MIDI"))
61 _input_port = MIDI::Manager::instance()->midi_input_port ();
62 _output_port = MIDI::Manager::instance()->midi_output_port ();
65 _feedback_interval = 10000; // microseconds
66 last_feedback_time = 0;
71 /* these signals are emitted by the MidiControlUI's event loop thread
72 * and we may as well handle them right there in the same the same
76 Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
77 Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
78 Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
79 Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
81 Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, ui_bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
83 /* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
84 /* this signal is emitted by the process() callback, and if
85 * send_feedback() is going to do anything, it should do it in the
86 * context of the process() callback itself.
89 Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
91 /* this one is cross-thread */
93 Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, ui_bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
98 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
104 static const char * const midimap_env_variable_name = "ARDOUR_MIDIMAPS_PATH";
105 static const char* const midi_map_dir_name = "midi_maps";
106 static const char* const midi_map_suffix = ".map";
109 system_midi_map_search_path ()
111 bool midimap_path_defined = false;
112 sys::path spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
114 if (midimap_path_defined) {
118 SearchPath spath (system_data_search_path());
119 spath.add_subdirectory_to_paths(midi_map_dir_name);
121 // just return the first directory in the search path that exists
122 SearchPath::const_iterator i = std::find_if(spath.begin(), spath.end(), sys::exists);
124 if (i == spath.end()) return sys::path();
130 user_midi_map_directory ()
132 sys::path p(user_config_directory());
133 p /= midi_map_dir_name;
139 midi_map_filter (const string &str, void */*arg*/)
141 return (str.length() > strlen(midi_map_suffix) &&
142 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
146 GenericMidiControlProtocol::reload_maps ()
148 vector<string *> *midi_maps;
150 SearchPath spath (system_midi_map_search_path());
151 spath += user_midi_map_directory ();
153 midi_maps = scanner (spath.to_string(), midi_map_filter, 0, false, true);
156 cerr << "No MIDI maps found using " << spath.to_string() << endl;
160 for (vector<string*>::iterator i = midi_maps->begin(); i != midi_maps->end(); ++i) {
161 string fullpath = *(*i);
165 if (!tree.read (fullpath.c_str())) {
171 XMLProperty* prop = tree.root()->property ("name");
177 mi.name = prop->value ();
180 map_info.push_back (mi);
187 GenericMidiControlProtocol::drop_all ()
189 Glib::Mutex::Lock lm (pending_lock);
190 Glib::Mutex::Lock lm2 (controllables_lock);
192 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
195 controllables.clear ();
197 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
200 pending_controllables.clear ();
202 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
207 for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
214 GenericMidiControlProtocol::drop_bindings ()
216 Glib::Mutex::Lock lm2 (controllables_lock);
218 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
219 if (!(*i)->learned()) {
221 i = controllables.erase (i);
227 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
232 _current_binding = "";
238 GenericMidiControlProtocol::set_active (bool /*yn*/)
240 /* start/stop delivery/outbound thread */
245 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
247 _feedback_interval = ms;
251 GenericMidiControlProtocol::send_feedback ()
253 /* This is executed in RT "process" context", so no blocking calls
260 microseconds_t now = get_microseconds ();
262 if (last_feedback_time != 0) {
263 if ((now - last_feedback_time) < _feedback_interval) {
270 last_feedback_time = now;
274 GenericMidiControlProtocol::_send_feedback ()
276 /* This is executed in RT "process" context", so no blocking calls
279 const int32_t bufsize = 16 * 1024; /* XXX too big */
280 MIDI::byte buf[bufsize];
281 int32_t bsize = bufsize;
283 /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
284 writes for each controllable here; if we send more than one MIDI message
285 in a single jack_midi_event_write then some bridges will only pass the
288 for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
289 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
291 _output_port->write (buf, (int32_t) (end - buf), 0);
297 GenericMidiControlProtocol::start_learning (Controllable* c)
303 Glib::Mutex::Lock lm2 (controllables_lock);
305 MIDIControllables::iterator tmp;
306 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
309 if ((*i)->get_controllable() == c) {
311 controllables.erase (i);
317 Glib::Mutex::Lock lm (pending_lock);
319 MIDIPendingControllables::iterator ptmp;
320 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
323 if (((*i)->first)->get_controllable() == c) {
324 (*i)->second.disconnect();
327 pending_controllables.erase (i);
333 MIDIControllable* mc = 0;
335 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
336 if ((*i)->get_controllable() && ((*i)->get_controllable()->id() == c->id())) {
343 mc = new MIDIControllable (this, *_input_port, *c, false);
347 Glib::Mutex::Lock lm (pending_lock);
349 MIDIPendingControllable* element = new MIDIPendingControllable;
351 c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc));
353 pending_controllables.push_back (element);
356 mc->learn_about_external_control ();
361 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
363 Glib::Mutex::Lock lm (pending_lock);
364 Glib::Mutex::Lock lm2 (controllables_lock);
366 MIDIPendingControllables::iterator tmp;
368 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
372 if ( (*i)->first == mc) {
373 (*i)->second.disconnect();
375 pending_controllables.erase(i);
381 controllables.push_back (mc);
385 GenericMidiControlProtocol::stop_learning (Controllable* c)
387 Glib::Mutex::Lock lm (pending_lock);
388 Glib::Mutex::Lock lm2 (controllables_lock);
389 MIDIControllable* dptr = 0;
391 /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
392 relevant MIDIControllable and remove it from the pending list.
395 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
396 if (((*i)->first)->get_controllable() == c) {
397 (*i)->first->stop_learning ();
399 (*i)->second.disconnect();
402 pending_controllables.erase (i);
411 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
414 Glib::Mutex::Lock lm2 (controllables_lock);
416 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
417 MIDIControllable* existingBinding = (*iter);
419 if (control == (existingBinding->get_controllable())) {
420 delete existingBinding;
421 iter = controllables.erase (iter);
431 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
433 if (control != NULL) {
434 Glib::Mutex::Lock lm2 (controllables_lock);
436 MIDI::channel_t channel = (pos & 0xf);
437 MIDI::byte value = control_number;
439 // Create a MIDIControllable
440 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
442 // Remove any old binding for this midi channel/type/value pair
443 // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
444 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
445 MIDIControllable* existingBinding = (*iter);
447 if ((existingBinding->get_control_channel() & 0xf ) == channel &&
448 existingBinding->get_control_additional() == value &&
449 (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
451 delete existingBinding;
452 iter = controllables.erase (iter);
459 // Update the MIDI Controllable based on the the pos param
460 // Here is where a table lookup for user mappings could go; for now we'll just wing it...
461 mc->bind_midi(channel, MIDI::controller, value);
463 controllables.push_back (mc);
468 GenericMidiControlProtocol::get_state ()
470 XMLNode* node = new XMLNode ("Protocol");
473 node->add_property (X_("name"), _name);
474 node->add_property (X_("feedback"), do_feedback ? "1" : "0");
475 snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
476 node->add_property (X_("feedback_interval"), buf);
478 if (!_current_binding.empty()) {
479 node->add_property ("binding", _current_binding);
482 XMLNode* children = new XMLNode (X_("Controls"));
484 node->add_child_nocopy (*children);
486 Glib::Mutex::Lock lm2 (controllables_lock);
487 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
489 /* we don't care about bindings that come from a bindings map, because
490 they will all be reset/recreated when we load the relevant bindings
494 if ((*i)->learned()) {
495 children->add_child_nocopy ((*i)->get_state());
503 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
506 XMLNodeConstIterator niter;
507 const XMLProperty* prop;
509 if ((prop = node.property ("feedback")) != 0) {
510 do_feedback = (bool) atoi (prop->value().c_str());
515 if ((prop = node.property ("feedback_interval")) != 0) {
516 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
517 _feedback_interval = 10000;
520 _feedback_interval = 10000;
523 boost::shared_ptr<Controllable> c;
526 Glib::Mutex::Lock lm (pending_lock);
527 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
530 pending_controllables.clear ();
534 Glib::Mutex::Lock lm2 (controllables_lock);
535 controllables.clear ();
536 nlist = node.children(); // "Controls"
542 nlist = nlist.front()->children ();
544 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
546 if ((prop = (*niter)->property ("id")) != 0) {
548 cerr << "Looking for MIDI Controllable with ID " << prop->value() << endl;
550 ID id = prop->value ();
551 Controllable* c = Controllable::by_id (id);
553 cerr << "\tresult = " << c << endl;
556 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
558 if (mc->set_state (**niter, version) == 0) {
559 controllables.push_back (mc);
563 warning << string_compose (
564 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
572 if ((prop = node.property ("binding")) != 0) {
573 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
574 if (prop->value() == (*x).name) {
575 load_bindings ((*x).path);
585 GenericMidiControlProtocol::set_feedback (bool yn)
588 last_feedback_time = 0;
593 GenericMidiControlProtocol::get_feedback () const
599 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
603 if (!state_tree.read (xmlpath.c_str())) {
604 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
608 XMLNode* root = state_tree.root();
610 if (root->name() != X_("ArdourMIDIBindings")) {
611 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
615 const XMLProperty* prop;
617 if ((prop = root->property ("version")) == 0) {
624 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
625 Stateful::loading_state_version = (major * 1000) + minor;
628 const XMLNodeList& children (root->children());
629 XMLNodeConstIterator citer;
630 XMLNodeConstIterator gciter;
632 MIDIControllable* mc;
636 for (citer = children.begin(); citer != children.end(); ++citer) {
638 if ((*citer)->name() == "DeviceInfo") {
639 const XMLProperty* prop;
641 if ((prop = (*citer)->property ("bank-size")) != 0) {
642 _bank_size = atoi (prop->value());
646 if ((prop = (*citer)->property ("motorised")) != 0) {
647 _motorised = string_is_affirmative (prop->value ());
653 if ((*citer)->name() == "Binding") {
654 const XMLNode* child = *citer;
656 if (child->property ("uri")) {
659 if ((mc = create_binding (*child)) != 0) {
660 Glib::Mutex::Lock lm2 (controllables_lock);
661 controllables.push_back (mc);
664 } else if (child->property ("function")) {
669 if ((mf = create_function (*child)) != 0) {
670 functions.push_back (mf);
673 } else if (child->property ("action")) {
676 if ((ma = create_action (*child)) != 0) {
677 actions.push_back (ma);
683 if ((prop = root->property ("name")) != 0) {
684 _current_binding = prop->value ();
687 reset_controllables ();
693 GenericMidiControlProtocol::create_binding (const XMLNode& node)
695 const XMLProperty* prop;
697 MIDI::channel_t channel;
703 if ((prop = node.property (X_("ctl"))) != 0) {
704 ev = MIDI::controller;
705 } else if ((prop = node.property (X_("note"))) != 0) {
707 } else if ((prop = node.property (X_("pgm"))) != 0) {
709 } else if ((prop = node.property (X_("pb"))) != 0) {
710 ev = MIDI::pitchbend;
715 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
719 detail = (MIDI::byte) intval;
721 if ((prop = node.property (X_("channel"))) == 0) {
725 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
728 channel = (MIDI::channel_t) intval;
729 /* adjust channel to zero-based counting */
734 if ((prop = node.property (X_("momentary"))) != 0) {
735 momentary = string_is_affirmative (prop->value());
740 prop = node.property (X_("uri"));
743 MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
745 if (mc->init (uri)) {
750 mc->bind_midi (channel, ev, detail);
756 GenericMidiControlProtocol::reset_controllables ()
758 Glib::Mutex::Lock lm2 (controllables_lock);
760 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
761 MIDIControllable* existingBinding = (*iter);
762 MIDIControllables::iterator next = iter;
765 if (!existingBinding->learned()) {
766 ControllableDescriptor& desc (existingBinding->descriptor());
769 desc.set_bank_offset (_current_bank * _bank_size);
772 /* its entirely possible that the session doesn't have
773 * the specified controllable (e.g. it has too few
774 * tracks). if we find this to be the case, drop any
775 * bindings that would be left without controllables.
778 boost::shared_ptr<Controllable> c = session->controllable_by_descriptor (desc);
780 existingBinding->set_controllable (c.get());
782 controllables.erase (iter);
791 GenericMidiControlProtocol::create_function (const XMLNode& node)
793 const XMLProperty* prop;
795 MIDI::byte detail = 0;
796 MIDI::channel_t channel = 0;
799 MIDI::byte* data = 0;
800 uint32_t data_size = 0;
803 if ((prop = node.property (X_("ctl"))) != 0) {
804 ev = MIDI::controller;
805 } else if ((prop = node.property (X_("note"))) != 0) {
807 } else if ((prop = node.property (X_("pgm"))) != 0) {
809 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
811 if (prop->name() == X_("sysex")) {
822 stringstream ss (prop->value());
834 data = new MIDI::byte[cnt];
838 stringstream ss (prop->value());
843 data[cnt++] = (MIDI::byte) val;
848 warning << "Binding ignored - unknown type" << endmsg;
852 if (data_size == 0) {
853 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
857 detail = (MIDI::byte) intval;
859 if ((prop = node.property (X_("channel"))) == 0) {
863 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
866 channel = (MIDI::channel_t) intval;
867 /* adjust channel to zero-based counting */
873 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
874 argument = prop->value ();
877 prop = node.property (X_("function"));
879 MIDIFunction* mf = new MIDIFunction (*_input_port);
881 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
886 mf->bind_midi (channel, ev, detail);
892 GenericMidiControlProtocol::create_action (const XMLNode& node)
894 const XMLProperty* prop;
896 MIDI::byte detail = 0;
897 MIDI::channel_t channel = 0;
900 MIDI::byte* data = 0;
901 uint32_t data_size = 0;
903 if ((prop = node.property (X_("ctl"))) != 0) {
904 ev = MIDI::controller;
905 } else if ((prop = node.property (X_("note"))) != 0) {
907 } else if ((prop = node.property (X_("pgm"))) != 0) {
909 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
911 if (prop->name() == X_("sysex")) {
922 stringstream ss (prop->value());
934 data = new MIDI::byte[cnt];
938 stringstream ss (prop->value());
943 data[cnt++] = (MIDI::byte) val;
948 warning << "Binding ignored - unknown type" << endmsg;
952 if (data_size == 0) {
953 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
957 detail = (MIDI::byte) intval;
959 if ((prop = node.property (X_("channel"))) == 0) {
963 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
966 channel = (MIDI::channel_t) intval;
967 /* adjust channel to zero-based counting */
973 prop = node.property (X_("action"));
975 MIDIAction* ma = new MIDIAction (*_input_port);
977 if (ma->init (*this, prop->value(), data, data_size)) {
982 ma->bind_midi (channel, ev, detail);
988 GenericMidiControlProtocol::set_current_bank (uint32_t b)
991 reset_controllables ();
995 GenericMidiControlProtocol::next_bank ()
998 reset_controllables ();
1002 GenericMidiControlProtocol::prev_bank()
1004 if (_current_bank) {
1006 reset_controllables ();
1011 GenericMidiControlProtocol::set_motorised (bool m)