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