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 */
55 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
56 : ControlProtocol (s, _("Generic MIDI"))
60 _input_port = MIDI::Manager::instance()->midi_input_port ();
61 _output_port = MIDI::Manager::instance()->midi_output_port ();
64 _feedback_interval = 10000; // microseconds
65 last_feedback_time = 0;
70 /* these signals are emitted by the MidiControlUI's event loop thread
71 * and we may as well handle them right there in the same the same
75 Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
76 Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
77 Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
78 Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
80 Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
82 /* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
83 /* this signal is emitted by the process() callback, and if
84 * send_feedback() is going to do anything, it should do it in the
85 * context of the process() callback itself.
88 Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
90 /* this one is cross-thread */
92 Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
97 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
103 static const char * const midimap_env_variable_name = "ARDOUR_MIDIMAPS_PATH";
104 static const char* const midi_map_dir_name = "midi_maps";
105 static const char* const midi_map_suffix = ".map";
108 system_midi_map_search_path ()
110 bool midimap_path_defined = false;
111 sys::path spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
113 if (midimap_path_defined) {
117 SearchPath spath (ardour_data_search_path());
118 spath.add_subdirectory_to_paths(midi_map_dir_name);
120 // just return the first directory in the search path that exists
121 SearchPath::const_iterator i = std::find_if(spath.begin(), spath.end(), sys::exists);
123 if (i == spath.end()) return sys::path();
129 user_midi_map_directory ()
131 sys::path p(user_config_directory());
132 p /= midi_map_dir_name;
138 midi_map_filter (const string &str, void */*arg*/)
140 return (str.length() > strlen(midi_map_suffix) &&
141 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
145 GenericMidiControlProtocol::reload_maps ()
147 vector<string *> *midi_maps;
149 SearchPath spath (system_midi_map_search_path());
150 spath += user_midi_map_directory ();
152 midi_maps = scanner (spath.to_string(), midi_map_filter, 0, false, true);
155 cerr << "No MIDI maps found using " << spath.to_string() << endl;
159 for (vector<string*>::iterator i = midi_maps->begin(); i != midi_maps->end(); ++i) {
160 string fullpath = *(*i);
164 if (!tree.read (fullpath.c_str())) {
170 XMLProperty* prop = tree.root()->property ("name");
176 mi.name = prop->value ();
179 map_info.push_back (mi);
186 GenericMidiControlProtocol::drop_all ()
188 Glib::Mutex::Lock lm (pending_lock);
189 Glib::Mutex::Lock lm2 (controllables_lock);
191 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
194 controllables.clear ();
196 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
199 pending_controllables.clear ();
201 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
206 for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
213 GenericMidiControlProtocol::drop_bindings ()
215 Glib::Mutex::Lock lm2 (controllables_lock);
217 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
218 if (!(*i)->learned()) {
220 i = controllables.erase (i);
226 for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
231 _current_binding = "";
237 GenericMidiControlProtocol::set_active (bool /*yn*/)
239 /* start/stop delivery/outbound thread */
244 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
246 _feedback_interval = ms;
250 GenericMidiControlProtocol::send_feedback ()
252 /* This is executed in RT "process" context", so no blocking calls
259 microseconds_t now = get_microseconds ();
261 if (last_feedback_time != 0) {
262 if ((now - last_feedback_time) < _feedback_interval) {
269 last_feedback_time = now;
273 GenericMidiControlProtocol::_send_feedback ()
275 /* This is executed in RT "process" context", so no blocking calls
278 const int32_t bufsize = 16 * 1024; /* XXX too big */
279 MIDI::byte buf[bufsize];
280 int32_t bsize = bufsize;
282 /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
283 writes for each controllable here; if we send more than one MIDI message
284 in a single jack_midi_event_write then some bridges will only pass the
287 for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
288 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
290 _output_port->write (buf, (int32_t) (end - buf), 0);
296 GenericMidiControlProtocol::start_learning (Controllable* c)
302 Glib::Mutex::Lock lm2 (controllables_lock);
304 MIDIControllables::iterator tmp;
305 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
308 if ((*i)->get_controllable() == c) {
310 controllables.erase (i);
316 Glib::Mutex::Lock lm (pending_lock);
318 MIDIPendingControllables::iterator ptmp;
319 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
322 if (((*i)->first)->get_controllable() == c) {
323 (*i)->second.disconnect();
326 pending_controllables.erase (i);
332 MIDIControllable* mc = 0;
334 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
335 if ((*i)->get_controllable() && ((*i)->get_controllable()->id() == c->id())) {
342 mc = new MIDIControllable (this, *_input_port, *c, false);
346 Glib::Mutex::Lock lm (pending_lock);
348 MIDIPendingControllable* element = new MIDIPendingControllable;
350 c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc));
352 pending_controllables.push_back (element);
355 mc->learn_about_external_control ();
360 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
362 Glib::Mutex::Lock lm (pending_lock);
363 Glib::Mutex::Lock lm2 (controllables_lock);
365 MIDIPendingControllables::iterator tmp;
367 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
371 if ( (*i)->first == mc) {
372 (*i)->second.disconnect();
374 pending_controllables.erase(i);
380 controllables.push_back (mc);
384 GenericMidiControlProtocol::stop_learning (Controllable* c)
386 Glib::Mutex::Lock lm (pending_lock);
387 Glib::Mutex::Lock lm2 (controllables_lock);
388 MIDIControllable* dptr = 0;
390 /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
391 relevant MIDIControllable and remove it from the pending list.
394 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
395 if (((*i)->first)->get_controllable() == c) {
396 (*i)->first->stop_learning ();
398 (*i)->second.disconnect();
401 pending_controllables.erase (i);
410 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
413 Glib::Mutex::Lock lm2 (controllables_lock);
415 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
416 MIDIControllable* existingBinding = (*iter);
418 if (control == (existingBinding->get_controllable())) {
419 delete existingBinding;
420 iter = controllables.erase (iter);
430 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
432 if (control != NULL) {
433 Glib::Mutex::Lock lm2 (controllables_lock);
435 MIDI::channel_t channel = (pos & 0xf);
436 MIDI::byte value = control_number;
438 // Create a MIDIControllable
439 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
441 // Remove any old binding for this midi channel/type/value pair
442 // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
443 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
444 MIDIControllable* existingBinding = (*iter);
446 if ((existingBinding->get_control_channel() & 0xf ) == channel &&
447 existingBinding->get_control_additional() == value &&
448 (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
450 delete existingBinding;
451 iter = controllables.erase (iter);
458 // Update the MIDI Controllable based on the the pos param
459 // Here is where a table lookup for user mappings could go; for now we'll just wing it...
460 mc->bind_midi(channel, MIDI::controller, value);
462 controllables.push_back (mc);
467 GenericMidiControlProtocol::get_state ()
469 XMLNode* node = new XMLNode ("Protocol");
472 node->add_property (X_("name"), _name);
473 node->add_property (X_("feedback"), do_feedback ? "1" : "0");
474 snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
475 node->add_property (X_("feedback_interval"), buf);
477 if (!_current_binding.empty()) {
478 node->add_property ("binding", _current_binding);
481 XMLNode* children = new XMLNode (X_("Controls"));
483 node->add_child_nocopy (*children);
485 Glib::Mutex::Lock lm2 (controllables_lock);
486 for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
488 /* we don't care about bindings that come from a bindings map, because
489 they will all be reset/recreated when we load the relevant bindings
493 if ((*i)->learned()) {
494 children->add_child_nocopy ((*i)->get_state());
502 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
505 XMLNodeConstIterator niter;
506 const XMLProperty* prop;
508 if ((prop = node.property ("feedback")) != 0) {
509 do_feedback = (bool) atoi (prop->value().c_str());
514 if ((prop = node.property ("feedback_interval")) != 0) {
515 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
516 _feedback_interval = 10000;
519 _feedback_interval = 10000;
522 boost::shared_ptr<Controllable> c;
525 Glib::Mutex::Lock lm (pending_lock);
526 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
529 pending_controllables.clear ();
533 Glib::Mutex::Lock lm2 (controllables_lock);
534 controllables.clear ();
535 nlist = node.children(); // "Controls"
541 nlist = nlist.front()->children ();
543 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
545 if ((prop = (*niter)->property ("id")) != 0) {
547 cerr << "Looking for MIDI Controllable with ID " << prop->value() << endl;
549 ID id = prop->value ();
550 Controllable* c = Controllable::by_id (id);
552 cerr << "\tresult = " << c << endl;
555 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
557 if (mc->set_state (**niter, version) == 0) {
558 controllables.push_back (mc);
562 warning << string_compose (
563 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
571 if ((prop = node.property ("binding")) != 0) {
572 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
573 if (prop->value() == (*x).name) {
574 load_bindings ((*x).path);
584 GenericMidiControlProtocol::set_feedback (bool yn)
587 last_feedback_time = 0;
592 GenericMidiControlProtocol::get_feedback () const
598 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
602 if (!state_tree.read (xmlpath.c_str())) {
603 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
607 XMLNode* root = state_tree.root();
609 if (root->name() != X_("ArdourMIDIBindings")) {
610 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
614 const XMLProperty* prop;
616 if ((prop = root->property ("version")) == 0) {
623 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
624 Stateful::loading_state_version = (major * 1000) + minor;
627 const XMLNodeList& children (root->children());
628 XMLNodeConstIterator citer;
629 XMLNodeConstIterator gciter;
631 MIDIControllable* mc;
635 for (citer = children.begin(); citer != children.end(); ++citer) {
637 if ((*citer)->name() == "DeviceInfo") {
638 const XMLProperty* prop;
640 if ((prop = (*citer)->property ("bank-size")) != 0) {
641 _bank_size = atoi (prop->value());
645 if ((prop = (*citer)->property ("motorised")) != 0) {
646 _motorised = string_is_affirmative (prop->value ());
652 if ((*citer)->name() == "Binding") {
653 const XMLNode* child = *citer;
655 if (child->property ("uri")) {
658 if ((mc = create_binding (*child)) != 0) {
659 Glib::Mutex::Lock lm2 (controllables_lock);
660 controllables.push_back (mc);
663 } else if (child->property ("function")) {
668 if ((mf = create_function (*child)) != 0) {
669 functions.push_back (mf);
672 } else if (child->property ("action")) {
675 if ((ma = create_action (*child)) != 0) {
676 actions.push_back (ma);
682 if ((prop = root->property ("name")) != 0) {
683 _current_binding = prop->value ();
686 reset_controllables ();
692 GenericMidiControlProtocol::create_binding (const XMLNode& node)
694 const XMLProperty* prop;
696 MIDI::channel_t channel;
702 if ((prop = node.property (X_("ctl"))) != 0) {
703 ev = MIDI::controller;
704 } else if ((prop = node.property (X_("note"))) != 0) {
706 } else if ((prop = node.property (X_("pgm"))) != 0) {
708 } else if ((prop = node.property (X_("pb"))) != 0) {
709 ev = MIDI::pitchbend;
714 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
718 detail = (MIDI::byte) intval;
720 if ((prop = node.property (X_("channel"))) == 0) {
724 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
727 channel = (MIDI::channel_t) intval;
728 /* adjust channel to zero-based counting */
733 if ((prop = node.property (X_("momentary"))) != 0) {
734 momentary = string_is_affirmative (prop->value());
739 prop = node.property (X_("uri"));
742 MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
744 if (mc->init (uri)) {
749 mc->bind_midi (channel, ev, detail);
755 GenericMidiControlProtocol::reset_controllables ()
757 Glib::Mutex::Lock lm2 (controllables_lock);
759 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
760 MIDIControllable* existingBinding = (*iter);
761 MIDIControllables::iterator next = iter;
764 if (!existingBinding->learned()) {
765 ControllableDescriptor& desc (existingBinding->descriptor());
768 desc.set_bank_offset (_current_bank * _bank_size);
771 /* its entirely possible that the session doesn't have
772 * the specified controllable (e.g. it has too few
773 * tracks). if we find this to be the case, drop any
774 * bindings that would be left without controllables.
777 boost::shared_ptr<Controllable> c = session->controllable_by_descriptor (desc);
779 existingBinding->set_controllable (c.get());
781 controllables.erase (iter);
790 GenericMidiControlProtocol::create_function (const XMLNode& node)
792 const XMLProperty* prop;
794 MIDI::byte detail = 0;
795 MIDI::channel_t channel = 0;
798 MIDI::byte* data = 0;
799 uint32_t data_size = 0;
802 if ((prop = node.property (X_("ctl"))) != 0) {
803 ev = MIDI::controller;
804 } else if ((prop = node.property (X_("note"))) != 0) {
806 } else if ((prop = node.property (X_("pgm"))) != 0) {
808 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
810 if (prop->name() == X_("sysex")) {
821 stringstream ss (prop->value());
833 data = new MIDI::byte[cnt];
837 stringstream ss (prop->value());
842 data[cnt++] = (MIDI::byte) val;
847 warning << "Binding ignored - unknown type" << endmsg;
851 if (data_size == 0) {
852 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
856 detail = (MIDI::byte) intval;
858 if ((prop = node.property (X_("channel"))) == 0) {
862 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
865 channel = (MIDI::channel_t) intval;
866 /* adjust channel to zero-based counting */
872 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
873 argument = prop->value ();
876 prop = node.property (X_("function"));
878 MIDIFunction* mf = new MIDIFunction (*_input_port);
880 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
885 mf->bind_midi (channel, ev, detail);
891 GenericMidiControlProtocol::create_action (const XMLNode& node)
893 const XMLProperty* prop;
895 MIDI::byte detail = 0;
896 MIDI::channel_t channel = 0;
899 MIDI::byte* data = 0;
900 uint32_t data_size = 0;
902 if ((prop = node.property (X_("ctl"))) != 0) {
903 ev = MIDI::controller;
904 } else if ((prop = node.property (X_("note"))) != 0) {
906 } else if ((prop = node.property (X_("pgm"))) != 0) {
908 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
910 if (prop->name() == X_("sysex")) {
921 stringstream ss (prop->value());
933 data = new MIDI::byte[cnt];
937 stringstream ss (prop->value());
942 data[cnt++] = (MIDI::byte) val;
947 warning << "Binding ignored - unknown type" << endmsg;
951 if (data_size == 0) {
952 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
956 detail = (MIDI::byte) intval;
958 if ((prop = node.property (X_("channel"))) == 0) {
962 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
965 channel = (MIDI::channel_t) intval;
966 /* adjust channel to zero-based counting */
972 prop = node.property (X_("action"));
974 MIDIAction* ma = new MIDIAction (*_input_port);
976 if (ma->init (*this, prop->value(), data, data_size)) {
981 ma->bind_midi (channel, ev, detail);
987 GenericMidiControlProtocol::set_current_bank (uint32_t b)
990 reset_controllables ();
994 GenericMidiControlProtocol::next_bank ()
997 reset_controllables ();
1001 GenericMidiControlProtocol::prev_bank()
1003 if (_current_bank) {
1005 reset_controllables ();
1010 GenericMidiControlProtocol::set_motorised (bool m)