MCP: reverse operation of cursor up/down in zoom mode; more tracign for vpot
[ardour.git] / libs / surfaces / generic_midi / generic_midi_control_protocol.cc
index 23072cea37ac46d1ed5be7602172cfc12b3edc1b..bff46462a70fbc5666f2375a1e2cfc9529a6aba8 100644 (file)
@@ -55,9 +55,9 @@ using namespace std;
 
 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
        : ControlProtocol (s, _("Generic MIDI"), midi_ui_context())
+       , _motorised (false)
        , gui (0)
 {
-
        _input_port = MIDI::Manager::instance()->midi_input_port ();
        _output_port = MIDI::Manager::instance()->midi_output_port ();
 
@@ -259,17 +259,18 @@ GenericMidiControlProtocol::_send_feedback ()
        const int32_t bufsize = 16 * 1024; /* XXX too big */
        MIDI::byte buf[bufsize];
        int32_t bsize = bufsize;
-       MIDI::byte* end = buf;
-       
+
+       /* XXX: due to bugs in some ALSA / JACK MIDI bridges, we have to do separate
+          writes for each controllable here; if we send more than one MIDI message
+          in a single jack_midi_event_write then some bridges will only pass the
+          first on to ALSA.
+       */
        for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
-               end = (*r)->write_feedback (end, bsize);
+               MIDI::byte* end = (*r)->write_feedback (buf, bsize);
+               if (end != buf) {
+                       _output_port->write (buf, (int32_t) (end - buf), 0);
+               }
        }
-       
-       if (end == buf) {
-               return;
-       } 
-
-       _output_port->write (buf, (int32_t) (end - buf), 0);
 }
 
 bool
@@ -319,7 +320,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
        }
 
        if (!mc) {
-               mc = new MIDIControllable (*_input_port, *c, false);
+               mc = new MIDIControllable (this, *_input_port, *c, false);
        }
        
        {
@@ -416,7 +417,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
                MIDI::byte value = control_number;
                
                // Create a MIDIControllable
-               MIDIControllable* mc = new MIDIControllable (*_input_port, *control, false);
+               MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
 
                // Remove any old binding for this midi channel/type/value pair
                // Note:  can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
@@ -532,7 +533,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
                                 cerr << "\tresult = " << c << endl;
                                
                                if (c) {
-                                       MIDIControllable* mc = new MIDIControllable (*_input_port, *c, false);
+                                       MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
                                         
                                        if (mc->set_state (**niter, version) == 0) {
                                                controllables.push_back (mc);
@@ -574,9 +575,6 @@ GenericMidiControlProtocol::get_feedback () const
        return do_feedback;
 }
 
-
-
-
 int
 GenericMidiControlProtocol::load_bindings (const string& xmlpath)
 {
@@ -624,6 +622,12 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath)
                                _bank_size = atoi (prop->value());
                                _current_bank = 0;
                        }
+
+                       if ((prop = (*citer)->property ("motorised")) != 0) {
+                               _motorised = string_is_affirmative (prop->value ());
+                       } else {
+                               _motorised = false;
+                       }
                }
 
                if ((*citer)->name() == "Binding") {
@@ -682,6 +686,8 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
                ev = MIDI::on;
        } else if ((prop = node.property (X_("pgm"))) != 0) {
                ev = MIDI::program;
+       } else if ((prop = node.property (X_("pb"))) != 0) {
+               ev = MIDI::pitchbend;
        } else {
                return 0;
        }
@@ -714,7 +720,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
        prop = node.property (X_("uri"));
        uri = prop->value();
 
-       MIDIControllable* mc = new MIDIControllable (*_input_port, momentary);
+       MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
 
        if (mc->init (uri)) {
                delete mc;
@@ -772,6 +778,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
        MIDI::eventType ev;
        MIDI::byte* data = 0;
        uint32_t data_size = 0;
+       string argument;
 
        if ((prop = node.property (X_("ctl"))) != 0) {
                ev = MIDI::controller;
@@ -843,11 +850,15 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
                }
        }
 
+       if ((prop = node.property (X_("arg"))) != 0 || (prop = node.property (X_("argument"))) != 0 || (prop = node.property (X_("arguments"))) != 0) {
+               argument = prop->value ();
+       }
+
        prop = node.property (X_("function"));
        
        MIDIFunction* mf = new MIDIFunction (*_input_port);
        
-       if (mf->init (*this, prop->value(), data, data_size)) {
+       if (mf->setup (*this, prop->value(), argument, data, data_size)) {
                delete mf;
                return 0;
        }
@@ -975,3 +986,9 @@ GenericMidiControlProtocol::prev_bank()
                reset_controllables ();
        }
 }
+
+void
+GenericMidiControlProtocol::set_motorised (bool m)
+{
+       _motorised = m;
+}