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/fileutils.h>
26 #include <glibmm/miscutils.h>
28 #include "pbd/controllable_descriptor.h"
29 #include "pbd/error.h"
30 #include "pbd/failed_constructor.h"
31 #include "pbd/pathscanner.h"
32 #include "pbd/xml++.h"
34 #include "midi++/port.h"
35 #include "midi++/manager.h"
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/session.h"
39 #include "ardour/route.h"
40 #include "ardour/midi_ui.h"
41 #include "ardour/rc_configuration.h"
43 #include "generic_midi_control_protocol.h"
44 #include "midicontrollable.h"
45 #include "midifunction.h"
46 #include "midiaction.h"
48 using namespace ARDOUR;
54 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
56 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
57 : ControlProtocol (s, _("Generic MIDI"))
62 _input_port = MIDI::Manager::instance()->midi_input_port ();
63 _output_port = MIDI::Manager::instance()->midi_output_port ();
66 _feedback_interval = 10000; // microseconds
67 last_feedback_time = 0;
72 /* these signals are emitted by the MidiControlUI's event loop thread
73 * and we may as well handle them right there in the same the same
77 Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
78 Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
79 Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
80 Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
82 Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
84 /* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
85 /* this signal is emitted by the process() callback, and if
86 * send_feedback() is going to do anything, it should do it in the
87 * context of the process() callback itself.
90 Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
92 /* this one is cross-thread */
94 Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
99 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
105 static const char * const midimap_env_variable_name = "ARDOUR_MIDIMAPS_PATH";
106 static const char* const midi_map_dir_name = "midi_maps";
107 static const char* const midi_map_suffix = ".map";
110 system_midi_map_search_path ()
112 bool midimap_path_defined = false;
113 std::string spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
115 if (midimap_path_defined) {
119 SearchPath spath (ardour_data_search_path());
120 spath.add_subdirectory_to_paths(midi_map_dir_name);
122 // just return the first directory in the search path that exists
123 for (SearchPath::const_iterator i = spath.begin(); i != spath.end(); ++i) {
124 if (Glib::file_test (*i, Glib::FILE_TEST_EXISTS)) {
128 return std::string();
132 user_midi_map_directory ()
134 return Glib::build_filename (user_config_directory(), 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 ID id = prop->value ();
548 Controllable* c = Controllable::by_id (id);
551 MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
553 if (mc->set_state (**niter, version) == 0) {
554 controllables.push_back (mc);
558 warning << string_compose (
559 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
567 if ((prop = node.property ("binding")) != 0) {
568 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
569 if (prop->value() == (*x).name) {
570 load_bindings ((*x).path);
580 GenericMidiControlProtocol::set_feedback (bool yn)
583 last_feedback_time = 0;
588 GenericMidiControlProtocol::get_feedback () const
594 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
598 if (!state_tree.read (xmlpath.c_str())) {
599 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
603 XMLNode* root = state_tree.root();
605 if (root->name() != X_("ArdourMIDIBindings")) {
606 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
610 const XMLProperty* prop;
612 if ((prop = root->property ("version")) == 0) {
619 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
620 Stateful::loading_state_version = (major * 1000) + minor;
623 const XMLNodeList& children (root->children());
624 XMLNodeConstIterator citer;
625 XMLNodeConstIterator gciter;
627 MIDIControllable* mc;
631 for (citer = children.begin(); citer != children.end(); ++citer) {
633 if ((*citer)->name() == "DeviceInfo") {
634 const XMLProperty* prop;
636 if ((prop = (*citer)->property ("bank-size")) != 0) {
637 _bank_size = atoi (prop->value());
641 if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
642 _motorised = string_is_affirmative (prop->value ());
647 if ((prop = (*citer)->property ("threshold")) != 0) {
648 _threshold = atoi (prop->value ());
655 if ((*citer)->name() == "Binding") {
656 const XMLNode* child = *citer;
658 if (child->property ("uri")) {
661 if ((mc = create_binding (*child)) != 0) {
662 Glib::Mutex::Lock lm2 (controllables_lock);
663 controllables.push_back (mc);
666 } else if (child->property ("function")) {
671 if ((mf = create_function (*child)) != 0) {
672 functions.push_back (mf);
675 } else if (child->property ("action")) {
678 if ((ma = create_action (*child)) != 0) {
679 actions.push_back (ma);
685 if ((prop = root->property ("name")) != 0) {
686 _current_binding = prop->value ();
689 reset_controllables ();
695 GenericMidiControlProtocol::create_binding (const XMLNode& node)
697 const XMLProperty* prop;
699 MIDI::channel_t channel;
705 if ((prop = node.property (X_("ctl"))) != 0) {
706 ev = MIDI::controller;
707 } else if ((prop = node.property (X_("note"))) != 0) {
709 } else if ((prop = node.property (X_("pgm"))) != 0) {
711 } else if ((prop = node.property (X_("pb"))) != 0) {
712 ev = MIDI::pitchbend;
717 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
721 detail = (MIDI::byte) intval;
723 if ((prop = node.property (X_("channel"))) == 0) {
727 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
730 channel = (MIDI::channel_t) intval;
731 /* adjust channel to zero-based counting */
736 if ((prop = node.property (X_("momentary"))) != 0) {
737 momentary = string_is_affirmative (prop->value());
742 prop = node.property (X_("uri"));
745 MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
747 if (mc->init (uri)) {
752 mc->bind_midi (channel, ev, detail);
758 GenericMidiControlProtocol::reset_controllables ()
760 Glib::Mutex::Lock lm2 (controllables_lock);
762 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
763 MIDIControllable* existingBinding = (*iter);
764 MIDIControllables::iterator next = iter;
767 if (!existingBinding->learned()) {
768 ControllableDescriptor& desc (existingBinding->descriptor());
771 desc.set_bank_offset (_current_bank * _bank_size);
774 /* its entirely possible that the session doesn't have
775 * the specified controllable (e.g. it has too few
776 * tracks). if we find this to be the case, we just leave
777 * the binding around, unbound, and it will do "late
778 * binding" (or "lazy binding") if/when any data arrives.
781 existingBinding->lookup_controllable ();
788 boost::shared_ptr<Controllable>
789 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
791 return session->controllable_by_descriptor (desc);
795 GenericMidiControlProtocol::create_function (const XMLNode& node)
797 const XMLProperty* prop;
799 MIDI::byte detail = 0;
800 MIDI::channel_t channel = 0;
803 MIDI::byte* data = 0;
804 uint32_t data_size = 0;
807 if ((prop = node.property (X_("ctl"))) != 0) {
808 ev = MIDI::controller;
809 } else if ((prop = node.property (X_("note"))) != 0) {
811 } else if ((prop = node.property (X_("pgm"))) != 0) {
813 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
815 if (prop->name() == X_("sysex")) {
826 stringstream ss (prop->value());
838 data = new MIDI::byte[cnt];
842 stringstream ss (prop->value());
847 data[cnt++] = (MIDI::byte) val;
852 warning << "Binding ignored - unknown type" << endmsg;
856 if (data_size == 0) {
857 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
861 detail = (MIDI::byte) intval;
863 if ((prop = node.property (X_("channel"))) == 0) {
867 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
870 channel = (MIDI::channel_t) intval;
871 /* adjust channel to zero-based counting */
877 if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
878 argument = prop->value ();
881 prop = node.property (X_("function"));
883 MIDIFunction* mf = new MIDIFunction (*_input_port);
885 if (mf->setup (*this, prop->value(), argument, data, data_size)) {
890 mf->bind_midi (channel, ev, detail);
896 GenericMidiControlProtocol::create_action (const XMLNode& node)
898 const XMLProperty* prop;
900 MIDI::byte detail = 0;
901 MIDI::channel_t channel = 0;
904 MIDI::byte* data = 0;
905 uint32_t data_size = 0;
907 if ((prop = node.property (X_("ctl"))) != 0) {
908 ev = MIDI::controller;
909 } else if ((prop = node.property (X_("note"))) != 0) {
911 } else if ((prop = node.property (X_("pgm"))) != 0) {
913 } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
915 if (prop->name() == X_("sysex")) {
926 stringstream ss (prop->value());
938 data = new MIDI::byte[cnt];
942 stringstream ss (prop->value());
947 data[cnt++] = (MIDI::byte) val;
952 warning << "Binding ignored - unknown type" << endmsg;
956 if (data_size == 0) {
957 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
961 detail = (MIDI::byte) intval;
963 if ((prop = node.property (X_("channel"))) == 0) {
967 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
970 channel = (MIDI::channel_t) intval;
971 /* adjust channel to zero-based counting */
977 prop = node.property (X_("action"));
979 MIDIAction* ma = new MIDIAction (*_input_port);
981 if (ma->init (*this, prop->value(), data, data_size)) {
986 ma->bind_midi (channel, ev, detail);
992 GenericMidiControlProtocol::set_current_bank (uint32_t b)
995 reset_controllables ();
999 GenericMidiControlProtocol::next_bank ()
1002 reset_controllables ();
1006 GenericMidiControlProtocol::prev_bank()
1008 if (_current_bank) {
1010 reset_controllables ();
1015 GenericMidiControlProtocol::set_motorised (bool m)
1021 GenericMidiControlProtocol::set_threshold (int t)