8d1952d5f283e3ab981a274b6177ff30d0e7faf6
[ardour.git] / libs / surfaces / generic_midi / generic_midi_control_protocol.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3  
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.
8
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.
13
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.
17
18 */
19
20 #include <stdint.h>
21
22 #include <sstream>
23 #include <algorithm>
24
25 #include <glibmm/fileutils.h>
26 #include <glibmm/miscutils.h>
27
28 #include "pbd/controllable_descriptor.h"
29 #include "pbd/error.h"
30 #include "pbd/failed_constructor.h"
31 #include "pbd/file_utils.h"
32 #include "pbd/xml++.h"
33 #include "pbd/compose.h"
34
35 #include "midi++/port.h"
36
37 #include "ardour/audioengine.h"
38 #include "ardour/filesystem_paths.h"
39 #include "ardour/session.h"
40 #include "ardour/route.h"
41 #include "ardour/midi_ui.h"
42 #include "ardour/rc_configuration.h"
43 #include "ardour/midiport_manager.h"
44 #include "ardour/debug.h"
45
46 #include "generic_midi_control_protocol.h"
47 #include "midicontrollable.h"
48 #include "midifunction.h"
49 #include "midiaction.h"
50
51 using namespace ARDOUR;
52 using namespace PBD;
53 using namespace std;
54
55 #include "i18n.h"
56
57 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
58
59 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
60         : ControlProtocol (s, _("Generic MIDI"))
61         , _motorised (false)
62         , _threshold (10)
63         , gui (0)
64 {
65         _input_port = s.midi_input_port ();
66         _output_port = s.midi_output_port ();
67
68         do_feedback = false;
69         _feedback_interval = 10000; // microseconds
70         last_feedback_time = 0;
71
72         _current_bank = 0;
73         _bank_size = 0;
74
75         /* these signals are emitted by the MidiControlUI's event loop thread
76          * and we may as well handle them right there in the same the same
77          * thread
78          */
79
80         Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1));
81         Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1));
82         Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
83         Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
84
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.
88          */
89
90         Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
91         //Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
92
93         /* this one is cross-thread */
94
95         Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
96
97         reload_maps ();
98 }
99
100 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
101 {
102         drop_all ();
103         tear_down_gui ();
104 }
105
106 static const char * const midimap_env_variable_name = "ARDOUR_MIDIMAPS_PATH";
107 static const char* const midi_map_dir_name = "midi_maps";
108 static const char* const midi_map_suffix = ".map";
109
110 Searchpath
111 system_midi_map_search_path ()
112 {
113         bool midimap_path_defined = false;
114         std::string spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
115
116         if (midimap_path_defined) {
117                 return spath_env;
118         }
119
120         Searchpath spath (ardour_data_search_path());
121         spath.add_subdirectory_to_paths(midi_map_dir_name);
122         return spath;
123 }
124
125 static std::string
126 user_midi_map_directory ()
127 {
128         return Glib::build_filename (user_config_directory(), midi_map_dir_name);
129 }
130
131 static bool
132 midi_map_filter (const string &str, void* /*arg*/)
133 {
134         return (str.length() > strlen(midi_map_suffix) &&
135                 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
136 }
137
138 void
139 GenericMidiControlProtocol::reload_maps ()
140 {
141         vector<string> midi_maps;
142         Searchpath spath (system_midi_map_search_path());
143         spath += user_midi_map_directory ();
144
145         find_files_matching_filter (midi_maps, spath, midi_map_filter, 0, false, true);
146
147         if (midi_maps.empty()) {
148                 cerr << "No MIDI maps found using " << spath.to_string() << endl;
149                 return;
150         }
151
152         for (vector<string>::iterator i = midi_maps.begin(); i != midi_maps.end(); ++i) {
153                 string fullpath = *i;
154
155                 XMLTree tree;
156
157                 if (!tree.read (fullpath.c_str())) {
158                         continue;
159                 }
160
161                 MapInfo mi;
162
163                 XMLProperty* prop = tree.root()->property ("name");
164
165                 if (!prop) {
166                         continue;
167                 }
168
169                 mi.name = prop->value ();
170                 mi.path = fullpath;
171                 
172                 map_info.push_back (mi);
173         }
174 }
175         
176 void
177 GenericMidiControlProtocol::drop_all ()
178 {
179         DEBUG_TRACE (DEBUG::GenericMidi, "Drop all bindings\n");
180         Glib::Threads::Mutex::Lock lm (pending_lock);
181         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
182
183         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
184                 delete *i;
185         }
186         controllables.clear ();
187
188         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
189                 delete *i;
190         }
191         pending_controllables.clear ();
192
193         for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
194                 delete *i;
195         }
196         functions.clear ();
197
198         for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
199                 delete *i;
200         }
201         actions.clear ();
202 }
203
204 void
205 GenericMidiControlProtocol::drop_bindings ()
206 {
207         DEBUG_TRACE (DEBUG::GenericMidi, "Drop bindings, leave learned\n");
208         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
209
210         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
211                 if (!(*i)->learned()) {
212                         delete *i;
213                         i = controllables.erase (i);
214                 } else {
215                         ++i;
216                 }
217         }
218
219         for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
220                 delete *i;
221         }
222         functions.clear ();
223
224         _current_binding = "";
225         _bank_size = 0;
226         _current_bank = 0;
227 }
228
229 int
230 GenericMidiControlProtocol::set_active (bool /*yn*/)
231 {
232         /* start/stop delivery/outbound thread */
233         return 0;
234 }
235
236 void
237 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
238 {
239         _feedback_interval = ms;
240 }
241
242 void 
243 GenericMidiControlProtocol::send_feedback ()
244 {
245         /* This is executed in RT "process" context", so no blocking calls
246          */
247
248         if (!do_feedback) {
249                 return;
250         }
251
252         microseconds_t now = get_microseconds ();
253
254         if (last_feedback_time != 0) {
255                 if ((now - last_feedback_time) < _feedback_interval) {
256                         return;
257                 }
258         }
259
260         _send_feedback ();
261         
262         last_feedback_time = now;
263 }
264
265 void 
266 GenericMidiControlProtocol::_send_feedback ()
267 {
268         /* This is executed in RT "process" context", so no blocking calls
269          */
270
271         const int32_t bufsize = 16 * 1024; /* XXX too big */
272         MIDI::byte buf[bufsize];
273         int32_t bsize = bufsize;
274
275         /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
276            writes for each controllable here; if we send more than one MIDI message
277            in a single jack_midi_event_write then some bridges will only pass the
278            first on to ALSA.
279         */
280
281         Glib::Threads::Mutex::Lock lm (controllables_lock, Glib::Threads::TRY_LOCK);
282         if (!lm.locked ()) {
283                 return;
284         }
285         
286         for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
287                 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
288                 if (end != buf) {
289                         _output_port->write (buf, (int32_t) (end - buf), 0);
290                 }
291         }
292 }
293
294 bool
295 GenericMidiControlProtocol::start_learning (Controllable* c)
296 {
297         if (c == 0) {
298                 return false;
299         }
300
301         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
302         DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Learn binding: Controlable number: %1\n", c));
303
304         MIDIControllables::iterator tmp;
305         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
306                 tmp = i;
307                 ++tmp;
308                 if ((*i)->get_controllable() == c) {
309                         delete (*i);
310                         controllables.erase (i);
311                 }
312                 i = tmp;
313         }
314
315         {
316                 Glib::Threads::Mutex::Lock lm (pending_lock);
317                 
318                 MIDIPendingControllables::iterator ptmp;
319                 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
320                         ptmp = i;
321                         ++ptmp;
322                         if (((*i)->first)->get_controllable() == c) {
323                                 (*i)->second.disconnect();
324                                 delete (*i)->first;
325                                 delete *i;
326                                 pending_controllables.erase (i);
327                         }
328                         i = ptmp;
329                 }
330         }
331
332         MIDIControllable* mc = 0;
333
334         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
335                 if ((*i)->get_controllable() && ((*i)->get_controllable()->id() == c->id())) {
336                         mc = *i;
337                         break;
338                 }
339         }
340
341         if (!mc) {
342                 mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
343         }
344         
345         {
346                 Glib::Threads::Mutex::Lock lm (pending_lock);
347
348                 MIDIPendingControllable* element = new MIDIPendingControllable;
349                 element->first = mc;
350                 c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc));
351
352                 pending_controllables.push_back (element);
353         }
354         mc->learn_about_external_control ();
355         return true;
356 }
357
358 void
359 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
360 {
361         Glib::Threads::Mutex::Lock lm (pending_lock);
362         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
363         
364         MIDIPendingControllables::iterator tmp;
365
366         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
367                 tmp = i;
368                 ++tmp;
369
370                 if ( (*i)->first == mc) {
371                         (*i)->second.disconnect();
372                         delete *i;
373                         pending_controllables.erase(i);
374                 }
375
376                 i = tmp;
377         }
378
379         controllables.push_back (mc);
380 }
381
382 void
383 GenericMidiControlProtocol::stop_learning (Controllable* c)
384 {
385         Glib::Threads::Mutex::Lock lm (pending_lock);
386         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
387         MIDIControllable* dptr = 0;
388
389         /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
390            relevant MIDIControllable and remove it from the pending list.
391         */
392
393         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
394                 if (((*i)->first)->get_controllable() == c) {
395                         (*i)->first->stop_learning ();
396                         dptr = (*i)->first;
397                         (*i)->second.disconnect();
398
399                         delete *i;
400                         pending_controllables.erase (i);
401                         break;
402                 }
403         }
404         
405         delete dptr;
406 }
407
408 void
409 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
410 {
411         if (control != 0) {
412                 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
413                 
414                 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
415                         MIDIControllable* existingBinding = (*iter);
416                         
417                         if (control == (existingBinding->get_controllable())) {
418                                 delete existingBinding;
419                                 iter = controllables.erase (iter);
420                         } else {
421                                 ++iter;
422                         }
423                         
424                 }
425         }
426 }
427
428 // This next function seems unused
429 void
430 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
431 {
432         if (control != NULL) {
433                 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
434                 
435                 MIDI::channel_t channel = (pos & 0xf);
436                 MIDI::byte value = control_number;
437                 
438                 // Create a MIDIControllable
439                 MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
440
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);
445                         
446                         if ((existingBinding->get_control_channel() & 0xf ) == channel &&
447                             existingBinding->get_control_additional() == value &&
448                             (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
449                                 
450                                 delete existingBinding;
451                                 iter = controllables.erase (iter);
452                         } else {
453                                 ++iter;
454                         }
455                         
456                 }
457                 
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);
461                 DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Create binding: Channel: %1 Controller: %2 Value: %3 \n", channel, MIDI::controller, value));
462                 controllables.push_back (mc);
463         }
464 }
465
466 void
467 GenericMidiControlProtocol::check_used_event (int pos, int control_number)
468 {
469         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
470
471         MIDI::channel_t channel = (pos & 0xf);
472         MIDI::byte value = control_number;
473
474         DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("checking for used event: Channel: %1 Controller: %2 value: %3\n", (int) channel, (pos & 0xf0), (int) value));
475
476         // Remove any old binding for this midi channel/type/value pair
477         // Note:  can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
478         for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
479                 MIDIControllable* existingBinding = (*iter);
480                 if ( (existingBinding->get_control_type() & 0xf0 ) == (pos & 0xf0) && (existingBinding->get_control_channel() & 0xf ) == channel ) {
481                         if ( ((int) existingBinding->get_control_additional() == (int) value) || ((pos & 0xf0) == MIDI::pitchbend)) {
482                                 DEBUG_TRACE (DEBUG::GenericMidi, "checking: found match, delete old binding.\n");
483                                 delete existingBinding;
484                                 iter = controllables.erase (iter);
485                         } else {
486                                 ++iter;
487                         }
488                 } else {
489                         ++iter;
490                 }
491         }
492
493         for (MIDIFunctions::iterator iter = functions.begin(); iter != functions.end();) {
494                 MIDIFunction* existingBinding = (*iter);
495                 if ( (existingBinding->get_control_type() & 0xf0 ) == (pos & 0xf0) && (existingBinding->get_control_channel() & 0xf ) == channel ) {
496                         if ( ((int) existingBinding->get_control_additional() == (int) value) || ((pos & 0xf0) == MIDI::pitchbend)) {
497                                 DEBUG_TRACE (DEBUG::GenericMidi, "checking: found match, delete old binding.\n");
498                                 delete existingBinding;
499                                 iter = functions.erase (iter);
500                         } else {
501                                 ++iter;
502                         }
503                 } else {
504                         ++iter;
505                 }
506         }
507
508         for (MIDIActions::iterator iter = actions.begin(); iter != actions.end();) {
509                 MIDIAction* existingBinding = (*iter);
510                 if ( (existingBinding->get_control_type() & 0xf0 ) == (pos & 0xf0) && (existingBinding->get_control_channel() & 0xf ) == channel ) {
511                         if ( ((int) existingBinding->get_control_additional() == (int) value) || ((pos & 0xf0) == MIDI::pitchbend)) {
512                                 DEBUG_TRACE (DEBUG::GenericMidi, "checking: found match, delete old binding.\n");
513                                 delete existingBinding;
514                                 iter = actions.erase (iter);
515                         } else {
516                                 ++iter;
517                         }
518                 } else {
519                         ++iter;
520                 }
521         }
522
523 }
524
525 XMLNode&
526 GenericMidiControlProtocol::get_state () 
527 {
528         XMLNode& node (ControlProtocol::get_state());
529         char buf[32];
530
531         snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
532         node.add_property (X_("feedback_interval"), buf);
533         snprintf (buf, sizeof (buf), "%d", _threshold);
534         node.add_property (X_("threshold"), buf);
535
536         if (!_current_binding.empty()) {
537                 node.add_property ("binding", _current_binding);
538         }
539
540         XMLNode* children = new XMLNode (X_("Controls"));
541
542         node.add_child_nocopy (*children);
543
544         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
545         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
546
547                 /* we don't care about bindings that come from a bindings map, because
548                    they will all be reset/recreated when we load the relevant bindings
549                    file.
550                 */
551
552                 if ((*i)->get_controllable() && (*i)->learned()) {
553                         children->add_child_nocopy ((*i)->get_state());
554                 }
555         }
556
557         return node;
558 }
559
560 int
561 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
562 {
563         XMLNodeList nlist;
564         XMLNodeConstIterator niter;
565         const XMLProperty* prop;
566
567         if (ControlProtocol::set_state (node, version)) {
568                 return -1;
569         }
570
571         if ((prop = node.property ("feedback_interval")) != 0) {
572                 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
573                         _feedback_interval = 10000;
574                 }
575         } else {
576                 _feedback_interval = 10000;
577         }
578
579         if ((prop = node.property ("threshold")) != 0) {
580                 if (sscanf (prop->value().c_str(), "%d", &_threshold) != 1) {
581                         _threshold = 10;
582                 }
583         } else {
584                 _threshold = 10;
585         }
586
587         boost::shared_ptr<Controllable> c;
588         
589         {
590                 Glib::Threads::Mutex::Lock lm (pending_lock);
591                 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
592                         delete *i;
593                 }
594                 pending_controllables.clear ();
595         }
596
597         // midi map has to be loaded first so learned binding can go on top
598         if ((prop = node.property ("binding")) != 0) {
599                 for (list<MapInfo>::iterator x = map_info.begin(); x != map_info.end(); ++x) {
600                         if (prop->value() == (*x).name) {
601                                 load_bindings ((*x).path);
602                                 break;
603                         }
604                 }
605         }
606
607         /* Load up specific bindings from the
608          * <Controls><MidiControllable>...</MidiControllable><Controls> section
609          */
610
611         {
612                 Glib::Threads::Mutex::Lock lm2 (controllables_lock);
613                 nlist = node.children(); // "Controls"
614
615                 if (!nlist.empty()) {
616                         nlist = nlist.front()->children(); // "MIDIControllable" ...
617
618                         if (!nlist.empty()) {
619                                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
620                                         
621                                         if ((prop = (*niter)->property ("id")) != 0) {
622                                                 
623                                                 ID id = prop->value ();
624                                                 DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Relearned binding for session: Control ID: %1\n", id.to_s()));
625                                                 Controllable* c = Controllable::by_id (id);
626                                                 
627                                                 if (c) {
628                                                         MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
629                                                         
630                                                         if (mc->set_state (**niter, version) == 0) {
631                                                                 controllables.push_back (mc);
632                                                         }
633                                                         
634                                                 } else {
635                                                         warning << string_compose (
636                                                                 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
637                                                                 id.to_s()) << endmsg;
638                                                 }
639                                         }
640                                 }
641                         }
642                 }
643         }
644
645         return 0;
646 }
647
648 int
649 GenericMidiControlProtocol::set_feedback (bool yn)
650 {
651         do_feedback = yn;
652         last_feedback_time = 0;
653         return 0;
654 }
655
656 bool
657 GenericMidiControlProtocol::get_feedback () const
658 {
659         return do_feedback;
660 }
661
662 int
663 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
664 {
665         DEBUG_TRACE (DEBUG::GenericMidi, "Load bindings: Reading midi map\n");
666         XMLTree state_tree;
667
668         if (!state_tree.read (xmlpath.c_str())) {
669                 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
670                 return -1;
671         }
672
673         XMLNode* root = state_tree.root();
674
675         if (root->name() != X_("ArdourMIDIBindings")) {
676                 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
677                 return -1;
678         }
679
680         const XMLProperty* prop;
681
682         if ((prop = root->property ("version")) == 0) {
683                 return -1;
684         } else {
685                 int major;
686                 int minor;
687                 int micro;
688
689                 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
690                 Stateful::loading_state_version = (major * 1000) + minor;
691         }
692         
693         const XMLNodeList& children (root->children());
694         XMLNodeConstIterator citer;
695         XMLNodeConstIterator gciter;
696
697         MIDIControllable* mc;
698
699         drop_all ();
700
701         DEBUG_TRACE (DEBUG::GenericMidi, "Loading bindings\n");
702         for (citer = children.begin(); citer != children.end(); ++citer) {
703                 
704                 if ((*citer)->name() == "DeviceInfo") {
705                         const XMLProperty* prop;
706
707                         if ((prop = (*citer)->property ("bank-size")) != 0) {
708                                 _bank_size = atoi (prop->value());
709                                 _current_bank = 0;
710                         }
711
712                         if ((prop = (*citer)->property ("motorised")) != 0 || ((prop = (*citer)->property ("motorized")) != 0)) {
713                                 _motorised = string_is_affirmative (prop->value ());
714                         } else {
715                                 _motorised = false;
716                         }
717
718                         if ((prop = (*citer)->property ("threshold")) != 0) {
719                                 _threshold = atoi (prop->value ());
720                         } else {
721                                 _threshold = 10;
722                         }
723
724                 }
725
726                 if ((*citer)->name() == "Binding") {
727                         const XMLNode* child = *citer;
728
729                         if (child->property ("uri")) {
730                                 /* controllable */
731                                 
732                                 if ((mc = create_binding (*child)) != 0) {
733                                         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
734                                         controllables.push_back (mc);
735                                 }
736
737                         } else if (child->property ("function")) {
738
739                                 /* function */
740                                 MIDIFunction* mf;
741
742                                 if ((mf = create_function (*child)) != 0) {
743                                         functions.push_back (mf);
744                                 }
745
746                         } else if (child->property ("action")) {
747                                 MIDIAction* ma;
748
749                                 if ((ma = create_action (*child)) != 0) {
750                                         actions.push_back (ma);
751                                 }
752                         }
753                 }
754         }
755         
756         if ((prop = root->property ("name")) != 0) {
757                 _current_binding = prop->value ();
758         }
759
760         reset_controllables ();
761
762         return 0;
763 }
764
765 MIDIControllable*
766 GenericMidiControlProtocol::create_binding (const XMLNode& node)
767 {
768         const XMLProperty* prop;
769         MIDI::byte detail;
770         MIDI::channel_t channel;
771         string uri;
772         MIDI::eventType ev;
773         int intval;
774         bool momentary;
775
776         if ((prop = node.property (X_("ctl"))) != 0) {
777                 ev = MIDI::controller;
778         } else if ((prop = node.property (X_("note"))) != 0) {
779                 ev = MIDI::on;
780         } else if ((prop = node.property (X_("pgm"))) != 0) {
781                 ev = MIDI::program;
782         } else if ((prop = node.property (X_("pb"))) != 0) {
783                 ev = MIDI::pitchbend;
784         } else {
785                 return 0;
786         }
787         
788         if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
789                 return 0;
790         }
791         
792         detail = (MIDI::byte) intval;
793
794         if ((prop = node.property (X_("channel"))) == 0) {
795                 return 0;
796         }
797         
798         if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
799                 return 0;
800         }
801         channel = (MIDI::channel_t) intval;
802         /* adjust channel to zero-based counting */
803         if (channel > 0) {
804                 channel -= 1;
805         }
806
807         if ((prop = node.property (X_("momentary"))) != 0) {
808                 momentary = string_is_affirmative (prop->value());
809         } else {
810                 momentary = false;
811         }
812         
813         prop = node.property (X_("uri"));
814         uri = prop->value();
815
816         MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
817
818         if (mc->init (uri)) {
819                 delete mc;
820                 return 0;
821         }
822
823         mc->bind_midi (channel, ev, detail);
824
825         return mc;
826 }
827
828 void
829 GenericMidiControlProtocol::reset_controllables ()
830 {
831         Glib::Threads::Mutex::Lock lm2 (controllables_lock);
832
833         for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
834                 MIDIControllable* existingBinding = (*iter);
835                 MIDIControllables::iterator next = iter;
836                 ++next;
837
838                 if (!existingBinding->learned()) {
839                         ControllableDescriptor& desc (existingBinding->descriptor());
840
841                         if (desc.banked()) {
842                                 desc.set_bank_offset (_current_bank * _bank_size);
843                         }
844
845                         /* its entirely possible that the session doesn't have
846                          * the specified controllable (e.g. it has too few
847                          * tracks). if we find this to be the case, we just leave
848                          * the binding around, unbound, and it will do "late
849                          * binding" (or "lazy binding") if/when any data arrives.
850                          */
851
852                         existingBinding->lookup_controllable ();
853                 }
854
855                 iter = next;
856         }
857 }
858
859 boost::shared_ptr<Controllable>
860 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
861 {
862         return session->controllable_by_descriptor (desc);
863 }
864
865 MIDIFunction*
866 GenericMidiControlProtocol::create_function (const XMLNode& node)
867 {
868         const XMLProperty* prop;
869         int intval;
870         MIDI::byte detail = 0;
871         MIDI::channel_t channel = 0;
872         string uri;
873         MIDI::eventType ev;
874         MIDI::byte* data = 0;
875         uint32_t data_size = 0;
876         string argument;
877
878         if ((prop = node.property (X_("ctl"))) != 0) {
879                 ev = MIDI::controller;
880         } else if ((prop = node.property (X_("note"))) != 0) {
881                 ev = MIDI::on;
882         } else if ((prop = node.property (X_("pgm"))) != 0) {
883                 ev = MIDI::program;
884         } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
885
886                 if (prop->name() == X_("sysex")) {
887                         ev = MIDI::sysex;
888                 } else {
889                         ev = MIDI::any;
890                 }
891
892                 int val;
893                 uint32_t cnt;
894
895                 {
896                         cnt = 0;
897                         stringstream ss (prop->value());
898                         ss << hex;
899                         
900                         while (ss >> val) {
901                                 cnt++;
902                         }
903                 }
904
905                 if (cnt == 0) {
906                         return 0;
907                 }
908
909                 data = new MIDI::byte[cnt];
910                 data_size = cnt;
911                 
912                 {
913                         stringstream ss (prop->value());
914                         ss << hex;
915                         cnt = 0;
916                         
917                         while (ss >> val) {
918                                 data[cnt++] = (MIDI::byte) val;
919                         }
920                 }
921
922         } else {
923                 warning << "Binding ignored - unknown type" << endmsg;
924                 return 0;
925         }
926
927         if (data_size == 0) {
928                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
929                         return 0;
930                 }
931                 
932                 detail = (MIDI::byte) intval;
933
934                 if ((prop = node.property (X_("channel"))) == 0) {
935                         return 0;
936                 }
937         
938                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
939                         return 0;
940                 }
941                 channel = (MIDI::channel_t) intval;
942                 /* adjust channel to zero-based counting */
943                 if (channel > 0) {
944                         channel -= 1;
945                 }
946         }
947
948         if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
949                 argument = prop->value ();
950         }
951
952         prop = node.property (X_("function"));
953         
954         MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
955         
956         if (mf->setup (*this, prop->value(), argument, data, data_size)) {
957                 delete mf;
958                 return 0;
959         }
960
961         mf->bind_midi (channel, ev, detail);
962
963         return mf;
964 }
965
966 MIDIAction*
967 GenericMidiControlProtocol::create_action (const XMLNode& node)
968 {
969         const XMLProperty* prop;
970         int intval;
971         MIDI::byte detail = 0;
972         MIDI::channel_t channel = 0;
973         string uri;
974         MIDI::eventType ev;
975         MIDI::byte* data = 0;
976         uint32_t data_size = 0;
977
978         if ((prop = node.property (X_("ctl"))) != 0) {
979                 ev = MIDI::controller;
980         } else if ((prop = node.property (X_("note"))) != 0) {
981                 ev = MIDI::on;
982         } else if ((prop = node.property (X_("pgm"))) != 0) {
983                 ev = MIDI::program;
984         } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
985
986                 if (prop->name() == X_("sysex")) {
987                         ev = MIDI::sysex;
988                 } else {
989                         ev = MIDI::any;
990                 }
991
992                 int val;
993                 uint32_t cnt;
994
995                 {
996                         cnt = 0;
997                         stringstream ss (prop->value());
998                         ss << hex;
999                         
1000                         while (ss >> val) {
1001                                 cnt++;
1002                         }
1003                 }
1004
1005                 if (cnt == 0) {
1006                         return 0;
1007                 }
1008
1009                 data = new MIDI::byte[cnt];
1010                 data_size = cnt;
1011                 
1012                 {
1013                         stringstream ss (prop->value());
1014                         ss << hex;
1015                         cnt = 0;
1016                         
1017                         while (ss >> val) {
1018                                 data[cnt++] = (MIDI::byte) val;
1019                         }
1020                 }
1021
1022         } else {
1023                 warning << "Binding ignored - unknown type" << endmsg;
1024                 return 0;
1025         }
1026
1027         if (data_size == 0) {
1028                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
1029                         return 0;
1030                 }
1031                 
1032                 detail = (MIDI::byte) intval;
1033
1034                 if ((prop = node.property (X_("channel"))) == 0) {
1035                         return 0;
1036                 }
1037         
1038                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
1039                         return 0;
1040                 }
1041                 channel = (MIDI::channel_t) intval;
1042                 /* adjust channel to zero-based counting */
1043                 if (channel > 0) {
1044                         channel -= 1;
1045                 }
1046         }
1047
1048         prop = node.property (X_("action"));
1049         
1050         MIDIAction* ma = new MIDIAction (*_input_port->parser());
1051         
1052         if (ma->init (*this, prop->value(), data, data_size)) {
1053                 delete ma;
1054                 return 0;
1055         }
1056
1057         ma->bind_midi (channel, ev, detail);
1058
1059         return ma;
1060 }
1061
1062 void
1063 GenericMidiControlProtocol::set_current_bank (uint32_t b)
1064 {
1065         _current_bank = b;
1066         reset_controllables ();
1067 }
1068
1069 void
1070 GenericMidiControlProtocol::next_bank ()
1071 {
1072         _current_bank++;
1073         reset_controllables ();
1074 }
1075
1076 void
1077 GenericMidiControlProtocol::prev_bank()
1078 {
1079         if (_current_bank) {
1080                 _current_bank--;
1081                 reset_controllables ();
1082         }
1083 }
1084
1085 void
1086 GenericMidiControlProtocol::set_motorised (bool m)
1087 {
1088         _motorised = m;
1089 }
1090
1091 void
1092 GenericMidiControlProtocol::set_threshold (int t)
1093 {
1094         _threshold = t;
1095 }