add late/lazy binding between generic MIDI bindings and controllable elements in...
[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/pathscanner.h"
32 #include "pbd/xml++.h"
33
34 #include "midi++/port.h"
35 #include "midi++/manager.h"
36
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"
42
43 #include "generic_midi_control_protocol.h"
44 #include "midicontrollable.h"
45 #include "midifunction.h"
46 #include "midiaction.h"
47
48 using namespace ARDOUR;
49 using namespace PBD;
50 using namespace std;
51
52 #include "i18n.h"
53
54 #define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
55
56 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
57         : ControlProtocol (s, _("Generic MIDI"))
58         , _motorised (false)
59         , _threshold (10)
60         , gui (0)
61 {
62         _input_port = MIDI::Manager::instance()->midi_input_port ();
63         _output_port = MIDI::Manager::instance()->midi_output_port ();
64
65         do_feedback = false;
66         _feedback_interval = 10000; // microseconds
67         last_feedback_time = 0;
68
69         _current_bank = 0;
70         _bank_size = 0;
71
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
74          * thread
75          */
76
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));
81
82         Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
83 #if 0
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.
88          */
89
90         Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
91 #endif
92         /* this one is cross-thread */
93
94         Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
95
96         reload_maps ();
97 }
98
99 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
100 {
101         drop_all ();
102         tear_down_gui ();
103 }
104
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";
108
109 static std::string
110 system_midi_map_search_path ()
111 {
112         bool midimap_path_defined = false;
113         std::string spath_env (Glib::getenv (midimap_env_variable_name, midimap_path_defined));
114
115         if (midimap_path_defined) {
116                 return spath_env;
117         }
118
119         SearchPath spath (ardour_data_search_path());
120         spath.add_subdirectory_to_paths(midi_map_dir_name);
121
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)) {
125                         return *i;
126                 }
127         }
128         return std::string();
129 }
130
131 static std::string
132 user_midi_map_directory ()
133 {
134         return Glib::build_filename (user_config_directory(), midi_map_dir_name);
135 }
136
137 static bool
138 midi_map_filter (const string &str, void */*arg*/)
139 {
140         return (str.length() > strlen(midi_map_suffix) &&
141                 str.find (midi_map_suffix) == (str.length() - strlen (midi_map_suffix)));
142 }
143
144 void
145 GenericMidiControlProtocol::reload_maps ()
146 {
147         vector<string *> *midi_maps;
148         PathScanner scanner;
149         SearchPath spath (system_midi_map_search_path());
150         spath += user_midi_map_directory ();
151
152         midi_maps = scanner (spath.to_string(), midi_map_filter, 0, false, true);
153
154         if (!midi_maps) {
155                 cerr << "No MIDI maps found using " << spath.to_string() << endl;
156                 return;
157         }
158
159         for (vector<string*>::iterator i = midi_maps->begin(); i != midi_maps->end(); ++i) {
160                 string fullpath = *(*i);
161
162                 XMLTree tree;
163
164                 if (!tree.read (fullpath.c_str())) {
165                         continue;
166                 }
167
168                 MapInfo mi;
169
170                 XMLProperty* prop = tree.root()->property ("name");
171
172                 if (!prop) {
173                         continue;
174                 }
175
176                 mi.name = prop->value ();
177                 mi.path = fullpath;
178                 
179                 map_info.push_back (mi);
180         }
181
182         delete midi_maps;
183 }
184         
185 void
186 GenericMidiControlProtocol::drop_all ()
187 {
188         Glib::Mutex::Lock lm (pending_lock);
189         Glib::Mutex::Lock lm2 (controllables_lock);
190
191         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
192                 delete *i;
193         }
194         controllables.clear ();
195
196         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
197                 delete *i;
198         }
199         pending_controllables.clear ();
200
201         for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
202                 delete *i;
203         }
204         functions.clear ();
205
206         for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) {
207                 delete *i;
208         }
209         actions.clear ();
210 }
211
212 void
213 GenericMidiControlProtocol::drop_bindings ()
214 {
215         Glib::Mutex::Lock lm2 (controllables_lock);
216
217         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) {
218                 if (!(*i)->learned()) {
219                         delete *i;
220                         i = controllables.erase (i);
221                 } else {
222                         ++i;
223                 }
224         }
225
226         for (MIDIFunctions::iterator i = functions.begin(); i != functions.end(); ++i) {
227                 delete *i;
228         }
229         functions.clear ();
230
231         _current_binding = "";
232         _bank_size = 0;
233         _current_bank = 0;
234 }
235
236 int
237 GenericMidiControlProtocol::set_active (bool /*yn*/)
238 {
239         /* start/stop delivery/outbound thread */
240         return 0;
241 }
242
243 void
244 GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
245 {
246         _feedback_interval = ms;
247 }
248
249 void 
250 GenericMidiControlProtocol::send_feedback ()
251 {
252         /* This is executed in RT "process" context", so no blocking calls
253          */
254
255         if (!do_feedback) {
256                 return;
257         }
258
259         microseconds_t now = get_microseconds ();
260
261         if (last_feedback_time != 0) {
262                 if ((now - last_feedback_time) < _feedback_interval) {
263                         return;
264                 }
265         }
266
267         _send_feedback ();
268         
269         last_feedback_time = now;
270 }
271
272 void 
273 GenericMidiControlProtocol::_send_feedback ()
274 {
275         /* This is executed in RT "process" context", so no blocking calls
276          */
277
278         const int32_t bufsize = 16 * 1024; /* XXX too big */
279         MIDI::byte buf[bufsize];
280         int32_t bsize = bufsize;
281
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
285            first on to ALSA.
286         */
287         for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
288                 MIDI::byte* end = (*r)->write_feedback (buf, bsize);
289                 if (end != buf) {
290                         _output_port->write (buf, (int32_t) (end - buf), 0);
291                 }
292         }
293 }
294
295 bool
296 GenericMidiControlProtocol::start_learning (Controllable* c)
297 {
298         if (c == 0) {
299                 return false;
300         }
301
302         Glib::Mutex::Lock lm2 (controllables_lock);
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::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, *c, false);
343         }
344         
345         {
346                 Glib::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
355         mc->learn_about_external_control ();
356         return true;
357 }
358
359 void
360 GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
361 {
362         Glib::Mutex::Lock lm (pending_lock);
363         Glib::Mutex::Lock lm2 (controllables_lock);
364         
365         MIDIPendingControllables::iterator tmp;
366
367         for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
368                 tmp = i;
369                 ++tmp;
370
371                 if ( (*i)->first == mc) {
372                         (*i)->second.disconnect();
373                         delete *i;
374                         pending_controllables.erase(i);
375                 }
376
377                 i = tmp;
378         }
379
380         controllables.push_back (mc);
381 }
382
383 void
384 GenericMidiControlProtocol::stop_learning (Controllable* c)
385 {
386         Glib::Mutex::Lock lm (pending_lock);
387         Glib::Mutex::Lock lm2 (controllables_lock);
388         MIDIControllable* dptr = 0;
389
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.
392         */
393
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 ();
397                         dptr = (*i)->first;
398                         (*i)->second.disconnect();
399
400                         delete *i;
401                         pending_controllables.erase (i);
402                         break;
403                 }
404         }
405         
406         delete dptr;
407 }
408
409 void
410 GenericMidiControlProtocol::delete_binding (PBD::Controllable* control)
411 {
412         if (control != 0) {
413                 Glib::Mutex::Lock lm2 (controllables_lock);
414                 
415                 for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
416                         MIDIControllable* existingBinding = (*iter);
417                         
418                         if (control == (existingBinding->get_controllable())) {
419                                 delete existingBinding;
420                                 iter = controllables.erase (iter);
421                         } else {
422                                 ++iter;
423                         }
424                         
425                 }
426         }
427 }
428
429 void
430 GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
431 {
432         if (control != NULL) {
433                 Glib::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, *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
462                 controllables.push_back (mc);
463         }
464 }
465
466 XMLNode&
467 GenericMidiControlProtocol::get_state () 
468 {
469         XMLNode* node = new XMLNode ("Protocol"); 
470         char buf[32];
471
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);
476
477         if (!_current_binding.empty()) {
478                 node->add_property ("binding", _current_binding);
479         }
480
481         XMLNode* children = new XMLNode (X_("Controls"));
482
483         node->add_child_nocopy (*children);
484
485         Glib::Mutex::Lock lm2 (controllables_lock);
486         for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
487
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
490                    file.
491                 */
492
493                 if ((*i)->learned()) {
494                         children->add_child_nocopy ((*i)->get_state());
495                 }
496         }
497
498         return *node;
499 }
500
501 int
502 GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
503 {
504         XMLNodeList nlist;
505         XMLNodeConstIterator niter;
506         const XMLProperty* prop;
507
508         if ((prop = node.property ("feedback")) != 0) {
509                 do_feedback = (bool) atoi (prop->value().c_str());
510         } else {
511                 do_feedback = false;
512         }
513
514         if ((prop = node.property ("feedback_interval")) != 0) {
515                 if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) {
516                         _feedback_interval = 10000;
517                 }
518         } else {
519                 _feedback_interval = 10000;
520         }
521
522         boost::shared_ptr<Controllable> c;
523         
524         {
525                 Glib::Mutex::Lock lm (pending_lock);
526                 for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
527                         delete *i;
528                 }
529                 pending_controllables.clear ();
530         }
531
532         {
533                 Glib::Mutex::Lock lm2 (controllables_lock);
534                 controllables.clear ();
535                 nlist = node.children(); // "Controls"
536                 
537                 if (nlist.empty()) {
538                         return 0;
539                 }
540                 
541                 nlist = nlist.front()->children ();
542                 
543                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
544                         
545                         if ((prop = (*niter)->property ("id")) != 0) {
546
547                                 ID id = prop->value ();
548                                 Controllable* c = Controllable::by_id (id);
549
550                                 if (c) {
551                                         MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
552                                         
553                                         if (mc->set_state (**niter, version) == 0) {
554                                                 controllables.push_back (mc);
555                                         }
556                                         
557                                 } else {
558                                         warning << string_compose (
559                                                 _("Generic MIDI control: controllable %1 not found in session (ignored)"),
560                                                 id) << endmsg;
561                                 }
562                         }
563                 }
564
565         }
566
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);
571                                 break;
572                         }
573                 }
574         }
575
576         return 0;
577 }
578
579 int
580 GenericMidiControlProtocol::set_feedback (bool yn)
581 {
582         do_feedback = yn;
583         last_feedback_time = 0;
584         return 0;
585 }
586
587 bool
588 GenericMidiControlProtocol::get_feedback () const
589 {
590         return do_feedback;
591 }
592
593 int
594 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
595 {
596         XMLTree state_tree;
597
598         if (!state_tree.read (xmlpath.c_str())) {
599                 error << string_compose(_("Could not understand MIDI bindings file %1"), xmlpath) << endmsg;
600                 return -1;
601         }
602
603         XMLNode* root = state_tree.root();
604
605         if (root->name() != X_("ArdourMIDIBindings")) {
606                 error << string_compose (_("MIDI Bindings file %1 is not really a MIDI bindings file"), xmlpath) << endmsg;
607                 return -1;
608         }
609
610         const XMLProperty* prop;
611
612         if ((prop = root->property ("version")) == 0) {
613                 return -1;
614         } else {
615                 int major;
616                 int minor;
617                 int micro;
618
619                 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
620                 Stateful::loading_state_version = (major * 1000) + minor;
621         }
622         
623         const XMLNodeList& children (root->children());
624         XMLNodeConstIterator citer;
625         XMLNodeConstIterator gciter;
626
627         MIDIControllable* mc;
628
629         drop_all ();
630
631         for (citer = children.begin(); citer != children.end(); ++citer) {
632                 
633                 if ((*citer)->name() == "DeviceInfo") {
634                         const XMLProperty* prop;
635
636                         if ((prop = (*citer)->property ("bank-size")) != 0) {
637                                 _bank_size = atoi (prop->value());
638                                 _current_bank = 0;
639                         }
640
641                         if ((prop = (*citer)->property ("motorised")) != 0) {
642                                 _motorised = string_is_affirmative (prop->value ());
643                         } else {
644                                 _motorised = false;
645                         }
646
647                         if ((prop = (*citer)->property ("threshold")) != 0) {
648                                 _threshold = atoi (prop->value ());
649                         } else {
650                                 _threshold = 10;
651                         }
652
653                 }
654
655                 if ((*citer)->name() == "Binding") {
656                         const XMLNode* child = *citer;
657
658                         if (child->property ("uri")) {
659                                 /* controllable */
660                                 
661                                 if ((mc = create_binding (*child)) != 0) {
662                                         Glib::Mutex::Lock lm2 (controllables_lock);
663                                         controllables.push_back (mc);
664                                 }
665
666                         } else if (child->property ("function")) {
667
668                                 /* function */
669                                 MIDIFunction* mf;
670
671                                 if ((mf = create_function (*child)) != 0) {
672                                         functions.push_back (mf);
673                                 }
674
675                         } else if (child->property ("action")) {
676                                 MIDIAction* ma;
677
678                                 if ((ma = create_action (*child)) != 0) {
679                                         actions.push_back (ma);
680                                 }
681                         }
682                 }
683         }
684         
685         if ((prop = root->property ("name")) != 0) {
686                 _current_binding = prop->value ();
687         }
688
689         reset_controllables ();
690
691         return 0;
692 }
693
694 MIDIControllable*
695 GenericMidiControlProtocol::create_binding (const XMLNode& node)
696 {
697         const XMLProperty* prop;
698         MIDI::byte detail;
699         MIDI::channel_t channel;
700         string uri;
701         MIDI::eventType ev;
702         int intval;
703         bool momentary;
704
705         if ((prop = node.property (X_("ctl"))) != 0) {
706                 ev = MIDI::controller;
707         } else if ((prop = node.property (X_("note"))) != 0) {
708                 ev = MIDI::on;
709         } else if ((prop = node.property (X_("pgm"))) != 0) {
710                 ev = MIDI::program;
711         } else if ((prop = node.property (X_("pb"))) != 0) {
712                 ev = MIDI::pitchbend;
713         } else {
714                 return 0;
715         }
716         
717         if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
718                 return 0;
719         }
720         
721         detail = (MIDI::byte) intval;
722
723         if ((prop = node.property (X_("channel"))) == 0) {
724                 return 0;
725         }
726         
727         if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
728                 return 0;
729         }
730         channel = (MIDI::channel_t) intval;
731         /* adjust channel to zero-based counting */
732         if (channel > 0) {
733                 channel -= 1;
734         }
735
736         if ((prop = node.property (X_("momentary"))) != 0) {
737                 momentary = string_is_affirmative (prop->value());
738         } else {
739                 momentary = false;
740         }
741         
742         prop = node.property (X_("uri"));
743         uri = prop->value();
744
745         MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
746
747         if (mc->init (uri)) {
748                 delete mc;
749                 return 0;
750         }
751
752         mc->bind_midi (channel, ev, detail);
753
754         return mc;
755 }
756
757 void
758 GenericMidiControlProtocol::reset_controllables ()
759 {
760         Glib::Mutex::Lock lm2 (controllables_lock);
761
762         for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ) {
763                 MIDIControllable* existingBinding = (*iter);
764                 MIDIControllables::iterator next = iter;
765                 ++next;
766
767                 if (!existingBinding->learned()) {
768                         ControllableDescriptor& desc (existingBinding->descriptor());
769
770                         if (desc.banked()) {
771                                 desc.set_bank_offset (_current_bank * _bank_size);
772                         }
773
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.
779                          */
780
781                         boost::shared_ptr<Controllable> c = session->controllable_by_descriptor (desc);
782                         if (c) {
783                                 existingBinding->set_controllable (c.get());
784                         } 
785                 }
786
787                 iter = next;
788         }
789 }
790
791 boost::shared_ptr<Controllable>
792 GenericMidiControlProtocol::lookup_controllable (const ControllableDescriptor& desc) const
793 {
794         return session->controllable_by_descriptor (desc);
795 }
796
797 MIDIFunction*
798 GenericMidiControlProtocol::create_function (const XMLNode& node)
799 {
800         const XMLProperty* prop;
801         int intval;
802         MIDI::byte detail = 0;
803         MIDI::channel_t channel = 0;
804         string uri;
805         MIDI::eventType ev;
806         MIDI::byte* data = 0;
807         uint32_t data_size = 0;
808         string argument;
809
810         if ((prop = node.property (X_("ctl"))) != 0) {
811                 ev = MIDI::controller;
812         } else if ((prop = node.property (X_("note"))) != 0) {
813                 ev = MIDI::on;
814         } else if ((prop = node.property (X_("pgm"))) != 0) {
815                 ev = MIDI::program;
816         } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
817
818                 if (prop->name() == X_("sysex")) {
819                         ev = MIDI::sysex;
820                 } else {
821                         ev = MIDI::any;
822                 }
823
824                 int val;
825                 uint32_t cnt;
826
827                 {
828                         cnt = 0;
829                         stringstream ss (prop->value());
830                         ss << hex;
831                         
832                         while (ss >> val) {
833                                 cnt++;
834                         }
835                 }
836
837                 if (cnt == 0) {
838                         return 0;
839                 }
840
841                 data = new MIDI::byte[cnt];
842                 data_size = cnt;
843                 
844                 {
845                         stringstream ss (prop->value());
846                         ss << hex;
847                         cnt = 0;
848                         
849                         while (ss >> val) {
850                                 data[cnt++] = (MIDI::byte) val;
851                         }
852                 }
853
854         } else {
855                 warning << "Binding ignored - unknown type" << endmsg;
856                 return 0;
857         }
858
859         if (data_size == 0) {
860                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
861                         return 0;
862                 }
863                 
864                 detail = (MIDI::byte) intval;
865
866                 if ((prop = node.property (X_("channel"))) == 0) {
867                         return 0;
868                 }
869         
870                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
871                         return 0;
872                 }
873                 channel = (MIDI::channel_t) intval;
874                 /* adjust channel to zero-based counting */
875                 if (channel > 0) {
876                         channel -= 1;
877                 }
878         }
879
880         if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
881                 argument = prop->value ();
882         }
883
884         prop = node.property (X_("function"));
885         
886         MIDIFunction* mf = new MIDIFunction (*_input_port);
887         
888         if (mf->setup (*this, prop->value(), argument, data, data_size)) {
889                 delete mf;
890                 return 0;
891         }
892
893         mf->bind_midi (channel, ev, detail);
894
895         return mf;
896 }
897
898 MIDIAction*
899 GenericMidiControlProtocol::create_action (const XMLNode& node)
900 {
901         const XMLProperty* prop;
902         int intval;
903         MIDI::byte detail = 0;
904         MIDI::channel_t channel = 0;
905         string uri;
906         MIDI::eventType ev;
907         MIDI::byte* data = 0;
908         uint32_t data_size = 0;
909
910         if ((prop = node.property (X_("ctl"))) != 0) {
911                 ev = MIDI::controller;
912         } else if ((prop = node.property (X_("note"))) != 0) {
913                 ev = MIDI::on;
914         } else if ((prop = node.property (X_("pgm"))) != 0) {
915                 ev = MIDI::program;
916         } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) {
917
918                 if (prop->name() == X_("sysex")) {
919                         ev = MIDI::sysex;
920                 } else {
921                         ev = MIDI::any;
922                 }
923
924                 int val;
925                 uint32_t cnt;
926
927                 {
928                         cnt = 0;
929                         stringstream ss (prop->value());
930                         ss << hex;
931                         
932                         while (ss >> val) {
933                                 cnt++;
934                         }
935                 }
936
937                 if (cnt == 0) {
938                         return 0;
939                 }
940
941                 data = new MIDI::byte[cnt];
942                 data_size = cnt;
943                 
944                 {
945                         stringstream ss (prop->value());
946                         ss << hex;
947                         cnt = 0;
948                         
949                         while (ss >> val) {
950                                 data[cnt++] = (MIDI::byte) val;
951                         }
952                 }
953
954         } else {
955                 warning << "Binding ignored - unknown type" << endmsg;
956                 return 0;
957         }
958
959         if (data_size == 0) {
960                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
961                         return 0;
962                 }
963                 
964                 detail = (MIDI::byte) intval;
965
966                 if ((prop = node.property (X_("channel"))) == 0) {
967                         return 0;
968                 }
969         
970                 if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
971                         return 0;
972                 }
973                 channel = (MIDI::channel_t) intval;
974                 /* adjust channel to zero-based counting */
975                 if (channel > 0) {
976                         channel -= 1;
977                 }
978         }
979
980         prop = node.property (X_("action"));
981         
982         MIDIAction* ma = new MIDIAction (*_input_port);
983         
984         if (ma->init (*this, prop->value(), data, data_size)) {
985                 delete ma;
986                 return 0;
987         }
988
989         ma->bind_midi (channel, ev, detail);
990
991         return ma;
992 }
993
994 void
995 GenericMidiControlProtocol::set_current_bank (uint32_t b)
996 {
997         _current_bank = b;
998         reset_controllables ();
999 }
1000
1001 void
1002 GenericMidiControlProtocol::next_bank ()
1003 {
1004         _current_bank++;
1005         reset_controllables ();
1006 }
1007
1008 void
1009 GenericMidiControlProtocol::prev_bank()
1010 {
1011         if (_current_bank) {
1012                 _current_bank--;
1013                 reset_controllables ();
1014         }
1015 }
1016
1017 void
1018 GenericMidiControlProtocol::set_motorised (bool m)
1019 {
1020         _motorised = m;
1021 }
1022
1023 void
1024 GenericMidiControlProtocol::set_threshold (int t)
1025 {
1026         _threshold = t;
1027 }