restore excess calls to sync-order stuff (for now); allow MIDI controllers to use...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 30 Dec 2009 16:48:58 +0000 (16:48 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 30 Dec 2009 16:48:58 +0000 (16:48 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@6414 d708f5d6-7413-0410-9779-e7cbd77b26cf

22 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/editor_routes.cc
gtk2_ardour/gain_meter.cc
gtk2_ardour/mixer_ui.cc
gtk2_ardour/utils.h
libs/ardour/ardour/amp.h
libs/ardour/ardour/route.h
libs/ardour/ardour/utils.h
libs/ardour/automation_control.cc
libs/ardour/enums.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/track.cc
libs/pbd/controllable.cc
libs/pbd/enums.cc [new file with mode: 0644]
libs/pbd/enumwriter.cc
libs/pbd/pbd/controllable.h
libs/pbd/pbd/enumwriter.h
libs/pbd/wscript
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
libs/surfaces/generic_midi/midicontrollable.cc
libs/surfaces/generic_midi/midicontrollable.h

index e58e1a2f509cece714484848e233270882e7b875..9b70f266e4a3c1de03fcd734c81489abe6767d01 100644 (file)
@@ -3400,7 +3400,7 @@ ARDOUR_UI::store_clock_modes ()
 
 
 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
-       : Controllable (name,  string() /* missing URI */), ui (u), type(tp)
+       : Controllable (name), ui (u), type(tp)
 {
 
 }
index 1a55d9157396730f30278d75a88f5804e2455214..87d010487fc64f9c6ccd3bce76f8e5fd036a6668 100644 (file)
@@ -892,6 +892,8 @@ EditorRoutes::move_selected_tracks (bool up)
        }
 
        _model->reorder (neworder);
+
+       _session->sync_order_keys (N_ ("editor"));
 }
 
 void
index 961ceb6a4a9c68c6d437a09840e9becff9076343..6c80ae27253a1b18d10f944839a0de536f88e4d0 100644 (file)
@@ -26,6 +26,7 @@
 #include "ardour/session.h"
 #include "ardour/session_route.h"
 #include "ardour/dB.h"
+#include "ardour/utils.h"
 
 #include <gtkmm/style.h>
 #include <gdkmm/color.h>
 
 #include "ardour_ui.h"
 #include "gain_meter.h"
-#include "utils.h"
 #include "logmeter.h"
 #include "gui_thread.h"
 #include "keyboard.h"
 #include "public_editor.h"
+#include "utils.h"
 
 #include "ardour/session.h"
 #include "ardour/route.h"
index 87c48a4348673c0c20f73ae7da5d056a516ea1c5..b750f8a470ed4e7cc0e6e5813b112e7cd243b092 100644 (file)
@@ -689,9 +689,7 @@ void
 Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/)
 {
        strip_redisplay_does_not_sync_order_keys = true;
-       if (!strip_redisplay_does_not_reset_order_keys) {
-               _session->set_remote_control_ids();
-       }
+       _session->set_remote_control_ids();
        redisplay_track_list ();
        strip_redisplay_does_not_sync_order_keys = false;
 }
@@ -701,6 +699,7 @@ Mixer_UI::track_list_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel::
 {
        // never reset order keys because of a property change
        strip_redisplay_does_not_reset_order_keys = true;
+       _session->set_remote_control_ids();
        redisplay_track_list ();
        strip_redisplay_does_not_reset_order_keys = false;
 }
@@ -710,6 +709,7 @@ Mixer_UI::track_list_delete (const Gtk::TreeModel::Path&)
 {
        /* this could require an order sync */
        if (_session && !_session->deletion_in_progress()) {
+               _session->set_remote_control_ids();
                redisplay_track_list ();
        }
 }
index 90a6de9ec4bc7967be80e527e9c78a4cb965d773..e742e89cd51adc34555c6d82e6946a42a994a9f0 100644 (file)
@@ -37,22 +37,6 @@ namespace Gtk {
        class Paned;
 }
 
-static inline double
-gain_to_slider_position (ARDOUR::gain_t g)
-{
-       if (g == 0) return 0;
-       return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
-
-}
-
-static inline ARDOUR::gain_t
-slider_position_to_gain (double pos)
-{
-       /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
-       if (pos == 0.0) return 0;
-       return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
-}
-
 Glib::ustring fit_to_pixels (const Glib::ustring&, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses = false);
 
 std::pair<std::string, double> fit_to_pixels (cairo_t *, std::string, double);
index c237479abd995bf89231691f7bbcaf7138d54da2..54bd9defe240c9a43af4afa94ab72fd4a21f6f6b 100644 (file)
@@ -73,8 +73,9 @@ public:
                GainControl (std::string name, Session& session, Amp* a, const Evoral::Parameter &param,
                                boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
                        : AutomationControl (session, param, al, name)
-                       , _amp (a)
-               {}
+                       , _amp (a) {
+                       set_flags (Controllable::Flag (flags() | Controllable::GainLike));
+               }
 
                void set_value (float val);
                float get_value (void) const;
index bb02396773e116c493170ce98ccb4cea895183b0..ac945703fd3b215fb4a18516c351a8864154051b 100644 (file)
@@ -304,7 +304,7 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou
        void automation_snapshot (nframes_t now, bool force=false);
        void protect_automation ();
 
-       void set_remote_control_id (uint32_t id);
+       void set_remote_control_id (uint32_t id, bool notify_class_listeners = true);
        uint32_t remote_control_id () const;
 
        /* for things concerned about *this* route's RID */
index 6c6f754cf931481c95bda0e99fbd1181dac9d60e..e68f7a01df5bc012bc6f81e1fd661714051f4ad6 100644 (file)
@@ -69,6 +69,22 @@ const char* edit_mode_to_string (ARDOUR::EditMode);
 ARDOUR::EditMode string_to_edit_mode (std::string);
 
 
+static inline double
+gain_to_slider_position (ARDOUR::gain_t g)
+{
+       if (g == 0) return 0;
+       return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
+
+}
+
+static inline ARDOUR::gain_t
+slider_position_to_gain (double pos)
+{
+       /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
+       if (pos == 0.0) return 0;
+       return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
+}
+
 /* I don't really like hard-coding these falloff rates here
  * Probably should use a map of some kind that could be configured
  * These rates are db/sec.
index cad3ef57e88ae0a936e33ccc277cb201a4c1f933..1460c42c7bd75420089b5f37c21657a5cf810e97 100644 (file)
@@ -34,7 +34,7 @@ AutomationControl::AutomationControl(
                const Evoral::Parameter& parameter,
                boost::shared_ptr<ARDOUR::AutomationList> list,
                const string& name)
-       : Controllable((name != "") ? name : EventTypeMap::instance().to_symbol(parameter), string("") /* XXX missing URI */)
+       : Controllable((name != "") ? name : EventTypeMap::instance().to_symbol(parameter))
        , Evoral::Control(parameter, list)
        , _session(session)
 {
index be61b2acb2bbbf33de9e5876067cc583db314f7b..7d07a5a95fefe4f74870ed0087b78a604e01e395 100644 (file)
@@ -48,7 +48,7 @@ namespace ARDOUR {
 void
 setup_enum_writer ()
 {
-       EnumWriter* enum_writer = new EnumWriter();
+       EnumWriter& enum_writer (EnumWriter::instance());
        vector<int> i;
        vector<string> s;
 
@@ -122,8 +122,8 @@ setup_enum_writer ()
        Session::SlaveState _Session_SlaveState;
        MTC_Status _MIDI_MTC_Status;
 
-#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
-#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
+#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
+#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
 #define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
 #define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
 
index 9c08080d2d92de9f5dd3cbac004a0896814e86fb..c5d26f7b7c8e537aac31cedcd7c2c22769542b7d 100644 (file)
@@ -174,12 +174,14 @@ Route::~Route ()
 }
 
 void
-Route::set_remote_control_id (uint32_t id)
+Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
 {
        if (id != _remote_control_id) {
                _remote_control_id = id;
                RemoteControlIDChanged ();
-               RemoteControlIDChange ();
+               if (notify_class_listeners) {
+                       RemoteControlIDChange ();
+               }
        }
 }
 
index 1f61322b4b64e8c6e1492076f42d2d37081eca1b..31693daff39d715ae5384e123f1d7cfcf7f6b3ce 100644 (file)
@@ -1863,20 +1863,27 @@ void
 Session::set_remote_control_ids ()
 {
        RemoteModel m = Config->get_remote_model();
+       bool emit_signal = false;
 
        shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if ( MixerOrdered == m) {
+               if (MixerOrdered == m) {
                        long order = (*i)->order_key(N_("signal"));
-                       (*i)->set_remote_control_id( order+1 );
-               } else if ( EditorOrdered == m) {
+                       (*i)->set_remote_control_id (order+1, false);
+                       emit_signal = true;
+               } else if (EditorOrdered == m) {
                        long order = (*i)->order_key(N_("editor"));
-                       (*i)->set_remote_control_id( order+1 );
-               } else if ( UserOrdered == m) {
+                       (*i)->set_remote_control_id (order+1, false);
+                       emit_signal = true;
+               } else if (UserOrdered == m) {
                        //do nothing ... only changes to remote id's are initiated by user
                }
        }
+
+       if (emit_signal) {
+               Route::RemoteControlIDChange();
+       }
 }
 
 
@@ -2373,6 +2380,8 @@ Session::remove_route (shared_ptr<Route> route)
 
        sync_order_keys (N_("session"));
 
+       Route::RemoteControlIDChange(); /* EMIT SIGNAL */
+
        /* save the new state of the world */
 
        if (save_state (_current_snapshot_name)) {
@@ -4184,9 +4193,11 @@ Session::sync_order_keys (std::string const & base)
        }
 
        Route::SyncOrderKeys (base); // EMIT SIGNAL
-       Route::RemoteControlIDChange (); // EMIT SIGNAL
-}
 
+       /* this might not do anything */
+
+       set_remote_control_ids ();
+}
 
 /** @return true if there is at least one record-enabled diskstream, otherwise false */
 bool
index 7d19d23007d1e1449a59b84343c2958363b0cd42..f286e07c25cd75090c888433cb75a6c9a5a0c133 100644 (file)
@@ -124,7 +124,7 @@ Track::freeze_state() const
 }
 
 Track::RecEnableControllable::RecEnableControllable (Track& s)
-       : Controllable (X_("recenable"), string() /* XXX missing URI */), track (s)
+       : Controllable (X_("recenable")), track (s)
 {
 }
 
index be487a0a87659ae6dffa84c6398f12dfb0185bb5..d5b81a73ed0eeebd13453f60eae65131e84f8253 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "pbd/controllable.h"
+#include "pbd/enumwriter.h"
 #include "pbd/xml++.h"
 #include "pbd/error.h"
 
@@ -34,13 +35,11 @@ PBD::Signal1<void,Controllable*> Controllable::DeleteBinding;
 
 Glib::StaticRWLock Controllable::registry_lock = GLIBMM_STATIC_RW_LOCK_INIT;
 Controllable::Controllables Controllable::registry;
-Controllable::ControllablesByURI Controllable::registry_by_uri;
 PBD::ScopedConnectionList registry_connections;
 
-Controllable::Controllable (const string& name, const string& uri)
+Controllable::Controllable (const string& name, Flag f)
        : _name (name)
-       , _uri (uri)
-       , _touching (false)
+       , _flags (f)
 {
        add (*this);
 }
@@ -53,13 +52,6 @@ Controllable::add (Controllable& ctl)
        Glib::RWLock::WriterLock lm (registry_lock);
        registry.insert (&ctl);
 
-       if (!ctl.uri().empty()) {
-               pair<string,Controllable*> newpair;
-               newpair.first = ctl.uri();
-               newpair.second = &ctl;
-               registry_by_uri.insert (newpair);
-       }
-
        /* Controllable::remove() is static - no need to manage this connection */
 
        ctl.DropReferences.connect_same_thread (registry_connections, boost::bind (&Controllable::remove, &ctl));
@@ -76,35 +68,6 @@ Controllable::remove (Controllable* ctl)
                        break;
                }
        }
-
-       if (!ctl->uri().empty()) {
-               ControllablesByURI::iterator i = registry_by_uri.find (ctl->uri());
-               if (i != registry_by_uri.end()) {
-                       registry_by_uri.erase (i);
-               }
-       }
-}
-
-void
-Controllable::set_uri (const string& new_uri)
-{
-       Glib::RWLock::WriterLock lm (registry_lock);
-
-       if (!_uri.empty()) {
-               ControllablesByURI::iterator i = registry_by_uri.find (_uri);
-               if (i != registry_by_uri.end()) {
-                       registry_by_uri.erase (i);
-               }
-       }
-
-       _uri = new_uri;
-
-       if (!_uri.empty()) {
-               pair<string,Controllable*> newpair;
-               newpair.first = _uri;
-               newpair.second = this;
-               registry_by_uri.insert (newpair);
-       }
 }
 
 Controllable*
@@ -120,18 +83,6 @@ Controllable::by_id (const ID& id)
        return 0;
 }
 
-Controllable*
-Controllable::by_uri (const string& uri)
-{
-       Glib::RWLock::ReaderLock lm (registry_lock);
-       ControllablesByURI::iterator i;
-
-       if ((i = registry_by_uri.find (uri)) != registry_by_uri.end()) {
-               return i->second;
-       }
-       return 0;
-}
-
 Controllable*
 Controllable::by_name (const string& str)
 {
@@ -154,11 +105,8 @@ Controllable::get_state ()
        node->add_property (X_("name"), _name); // not reloaded from XML state, just there to look at
        _id.print (buf, sizeof (buf));
        node->add_property (X_("id"), buf);
+       node->add_property (X_("flags"), enum_2_string (_flags));
 
-       if (!_uri.empty()) {
-               node->add_property (X_("uri"), _uri);
-       }
-               
        return *node;
 }
 
@@ -175,7 +123,13 @@ Controllable::set_state (const XMLNode& node, int /*version*/)
                return -1;
        }
 
-       if ((prop = node.property (X_("uri"))) != 0) {
-               set_uri (prop->value());
+       if ((prop = node.property (X_("flags"))) != 0) {
+               _flags = (Flag) string_2_enum (prop->value(), _flags);
        }
 }
+
+void
+Controllable::set_flags (Flag f)
+{
+       _flags = f;
+}
diff --git a/libs/pbd/enums.cc b/libs/pbd/enums.cc
new file mode 100644 (file)
index 0000000..559af3a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+    Copyright (C) 2009 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "pbd/controllable.h"
+#include "pbd/enumwriter.h"
+
+void setup_libpbd_enums () __attribute__ ((constructor));
+
+using namespace PBD;
+using namespace std;
+
+void
+setup_libpbd_enums () 
+{
+       EnumWriter& enum_writer (EnumWriter::instance());
+       vector<int> i;
+       vector<string> s;
+
+       Controllable::Flag controllable_flags;
+
+#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
+#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
+#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
+#define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
+
+       REGISTER_CLASS_ENUM (Controllable, Toggle);
+       REGISTER_CLASS_ENUM (Controllable, Discrete);
+       REGISTER_CLASS_ENUM (Controllable, GainLike);
+       REGISTER_CLASS_ENUM (Controllable, IntegerOnly);
+       REGISTER (controllable_flags);
+}
index 134a00a20746cb2057c0a60a3329b10d38633a4e..2c6e5c73c82864085dfe340c9b087640802c5013 100644 (file)
@@ -63,11 +63,18 @@ nocase_cmp(const string & s1, const string& s2)
        return (size1 < size2) ? -1 : 1;
 }
 
-EnumWriter::EnumWriter ()
+EnumWriter&
+EnumWriter::instance() 
 {
        if (_instance == 0) {
-               _instance = this;
-       }
+               _instance = new EnumWriter;
+       } 
+
+       return *_instance;
+}
+
+EnumWriter::EnumWriter ()
+{
 }
 
 EnumWriter::~EnumWriter ()
index 28dd4b7a31293d738c55873474569be1aa7535d5..f8d8f828559038fa568b04834055cb4892c47d56 100644 (file)
@@ -35,12 +35,16 @@ namespace PBD {
 
 class Controllable : public PBD::StatefulDestructible {
   public:
-       Controllable (const std::string& name, const std::string& uri);
+       enum Flag {
+               Toggle = 0x1,
+               Discrete = 0x2,
+               GainLike = 0x4,
+               IntegerOnly = 0x8
+       };
+
+       Controllable (const std::string& name, Flag f = Flag (0));
        virtual ~Controllable() { Destroyed (this); }
 
-       void set_uri (const std::string&);
-       const std::string& uri() const { return _uri; }
-
        virtual void set_value (float) = 0;
        virtual float get_value (void) const = 0;
 
@@ -59,27 +63,35 @@ class Controllable : public PBD::StatefulDestructible {
        XMLNode& get_state ();
 
        std::string name()      const { return _name; }
-       bool        touching () const { return _touching; }
-       
+
+       bool touching () const { return _touching; }
        void set_touching (bool yn) { _touching = yn; }
 
+       bool is_toggle() const { return _flags & Toggle; }
+       bool is_discrete() const { return _flags & Discrete; }
+       bool is_gain_like() const { return _flags & GainLike; }
+       bool is_integral_only() const { return _flags & IntegerOnly; }
+
+       Flag flags() const { return _flags; }
+       void set_flags (Flag f);
+
+       virtual uint32_t get_discrete_values (std::list<float>&) { return 0; /* no values returned */ }
+
        static Controllable* by_id (const PBD::ID&);
        static Controllable* by_name (const std::string&);
-       static Controllable* by_uri (const std::string&);
 
   private:
        std::string _name;
-       std::string _uri;
+
+       Flag        _flags;
        bool        _touching;
 
        static void add (Controllable&);
        static void remove (Controllable*);
 
        typedef std::set<PBD::Controllable*> Controllables;
-       typedef std::map<std::string,PBD::Controllable*> ControllablesByURI;
        static Glib::StaticRWLock registry_lock;
        static Controllables registry;
-       static ControllablesByURI registry_by_uri;
 };
 
 /* a utility class for the occasions when you need but do not have
@@ -89,7 +101,7 @@ class Controllable : public PBD::StatefulDestructible {
 class IgnorableControllable : public Controllable 
 {
   public: 
-       IgnorableControllable () : PBD::Controllable ("ignoreMe", std::string()) {}
+       IgnorableControllable () : PBD::Controllable ("ignoreMe") {}
        ~IgnorableControllable () {}
     
        void set_value (float /*v*/) {}
index 63a8ef6f6e326d72b67bea3f6d2b5a0b540a3768..461665d739f0a7b9ad1116bf0677d5354f3bfcd4 100644 (file)
@@ -36,10 +36,7 @@ class unknown_enumeration : public std::exception {
 
 class EnumWriter {
   public:
-       EnumWriter ();
-       ~EnumWriter ();
-
-       static EnumWriter& instance() { return *_instance; }
+       static EnumWriter& instance();
 
        void register_distinct (std::string type, std::vector<int>, std::vector<std::string>);
        void register_bits     (std::string type, std::vector<int>, std::vector<std::string>);
@@ -50,6 +47,9 @@ class EnumWriter {
        void add_to_hack_table (std::string str, std::string hacked_str);
 
   private:
+       EnumWriter ();
+       ~EnumWriter ();
+
        struct EnumRegistration {
            std::vector<int> values;
            std::vector<std::string> names;
index b25d8059ceb8d013e8cf3840a8eed1e596da6ab8..3794a37e81d1998268facfcb0b2bafd31d1cc8e1 100644 (file)
@@ -61,6 +61,7 @@ def build(bld):
                enumwriter.cc
                 event_loop.cc
                dmalloc.cc
+                enums.cc
                error.cc
                filesystem.cc
                filesystem_paths.cc
index 6a29c2768468d3169e3a9857fb9d3be4e4872572..42c53588165454ffcee0b6a82d4613e1ebc17d5a 100644 (file)
@@ -274,7 +274,6 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
                return false;
        }
 
-       Glib::Mutex::Lock lm (pending_lock);
        Glib::Mutex::Lock lm2 (controllables_lock);
 
        MIDIControllables::iterator tmp;
@@ -288,20 +287,23 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
                i = tmp;
        }
 
-       MIDIPendingControllables::iterator ptmp;
-       for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
-               ptmp = i;
-               ++ptmp;
-               if (((*i)->first)->get_controllable() == c) {
-                       (*i)->second.disconnect();
-                       delete (*i)->first;
-                       delete *i;
-                       pending_controllables.erase (i);
+       {
+               Glib::Mutex::Lock lm (pending_lock);
+               
+               MIDIPendingControllables::iterator ptmp;
+               for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
+                       ptmp = i;
+                       ++ptmp;
+                       if (((*i)->first)->get_controllable() == c) {
+                               (*i)->second.disconnect();
+                               delete (*i)->first;
+                               delete *i;
+                               pending_controllables.erase (i);
+                       }
+                       i = ptmp;
                }
-               i = ptmp;
        }
 
-
        MIDIControllable* mc = 0;
 
        for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
@@ -702,6 +704,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
 void
 GenericMidiControlProtocol::reset_controllables ()
 {
+       cerr << "GM::RC\n";
        Glib::Mutex::Lock lm2 (controllables_lock);
        
        for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
index 0cebabd80bce1b858250f3a801579c0d956072dd..5c23628a64e6707e746d1aba0081a4e248509422 100644 (file)
@@ -30,6 +30,7 @@
 #include "midi++/channel.h"
 
 #include "ardour/automation_control.h"
+#include "ardour/utils.h"
 
 #include "midicontrollable.h"
 
@@ -196,10 +197,14 @@ MIDIControllable::midi_to_control(float val)
                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;
+       if (ac->is_gain_like()) {
+               return  slider_position_to_gain (val/midi_range);
+       } 
+
+       const float control_range = control_max - control_min;
+       return  val / midi_range * control_range + control_min;
 }
 
 void
@@ -459,8 +464,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);
index b5aa115feee4e0b9e85561950d93cc93211fb7ac..a635eaea10fb235b3d39200f88c0b612eca5f636 100644 (file)
@@ -91,6 +91,7 @@ class MIDIControllable : public PBD::Stateful
        bool             setting;
        MIDI::byte       last_value;
        bool             bistate;
+       bool            _is_gain_controller;
        bool            _learned;
        int              midi_msg_id;      /* controller ID or note number */
        PBD::ScopedConnection midi_sense_connection[2];