new PBD::ControllableDescriptor class to encapsulate parsing of binding URIs and...
[ardour.git] / libs / surfaces / generic_midi / midicontrollable.cc
index 9c808af005ea96d482b4bf551522faa70145b2fc..d960140958d7d6939375f73e6acc1cb46d174aec 100644 (file)
 
 */
 
+#define __STDC_FORMAT_MACROS 1
+#include <stdint.h>
+
 #include <cstdio> /* for sprintf, sigh */
 #include <climits>
 
 #include "pbd/error.h"
+#include "pbd/controllable_descriptor.h"
 #include "pbd/xml++.h"
 
 #include "midi++/port.h"
 #include "midi++/channel.h"
 
 #include "ardour/automation_control.h"
+#include "ardour/utils.h"
 
 #include "midicontrollable.h"
 
@@ -35,36 +40,49 @@ using namespace MIDI;
 using namespace PBD;
 using namespace ARDOUR;
 
-MIDIControllable::MIDIControllable (Port& p, const string& c, bool is_bistate)
-       : controllable (0), _current_uri (c), _port (p), bistate (is_bistate)
+MIDIControllable::MIDIControllable (Port& p, bool is_bistate)
+       : controllable (0)
+       , _descriptor (0)
+       , _port (p)
+       , bistate (is_bistate)
 {
-       init ();
+       _learned = false; /* from URI */
+       setting = false;
+       last_value = 0; // got a better idea ?
+       control_type = none;
+       _control_description = "MIDI Control: none";
+       control_additional = (byte) -1;
+       feedback = true; // for now
 }
 
 MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool is_bistate)
-       : controllable (&c), _current_uri (c.uri()), _port (p), bistate (is_bistate)
-{
-       init ();
-}
+       : controllable (&c)
+       , _descriptor (0)
+       , _port (p)
+       , bistate (is_bistate)
 
-MIDIControllable::~MIDIControllable ()
-{
-       drop_external_control ();
-}
-
-void
-MIDIControllable::init ()
 {
+       _learned = true; /* from controllable */
        setting = false;
        last_value = 0; // got a better idea ?
        control_type = none;
        _control_description = "MIDI Control: none";
        control_additional = (byte) -1;
        feedback = true; // for now
+}
 
-       /* use channel 0 ("1") as the initial channel */
+MIDIControllable::~MIDIControllable ()
+{
+       drop_external_control ();
+}
 
-       midi_rebind (0);
+int
+MIDIControllable::init (const std::string& s)
+{
+       _current_uri = s;
+       delete _descriptor;
+       _descriptor = new ControllableDescriptor;
+       return _descriptor->set (s);
 }
 
 void
@@ -82,10 +100,7 @@ MIDIControllable::midi_forget ()
 void
 MIDIControllable::drop_external_control ()
 {
-       midi_sense_connection[0].disconnect ();
-       midi_sense_connection[1].disconnect ();
-       midi_learn_connection.disconnect ();
-
+       midi_forget ();
        control_type = none;
        control_additional = (byte) -1;
 }
@@ -142,15 +157,21 @@ MIDIControllable::midi_to_control(float val)
        float control_min = 0.0f;
        float control_max = 1.0f;
        ARDOUR::AutomationControl* ac = dynamic_cast<ARDOUR::AutomationControl*>(controllable);
+
+       const float midi_range = 127.0f; // TODO: NRPN etc.
+       
        if (ac) {
+
+               if (ac->is_gain_like()) {
+                       return slider_position_to_gain (val/midi_range);
+               }
+               
                control_min = ac->parameter().min();
                control_max = ac->parameter().max();
        }
 
        const float control_range = control_max - control_min;
-       const float midi_range    = 127.0f; // TODO: NRPN etc.
-
-       return val / midi_range * control_range + control_min;
+       return  val / midi_range * control_range + control_min;
 }
 
 void
@@ -410,8 +431,11 @@ MIDIControllable::get_state ()
 
        XMLNode* node = new XMLNode ("MIDIControllable");
 
+       if (!_current_uri.empty()) {
+               node->add_property ("uri", _current_uri);
+       }
+
        if (controllable) {
-               node->add_property ("uri", controllable->uri());
                snprintf (buf, sizeof(buf), "0x%x", (int) control_type);
                node->add_property ("event", buf);
                snprintf (buf, sizeof(buf), "%d", (int) control_channel);