more or less complete restoration of Controllable::_id from XML, with all that implie...
authorPaul Davis <paul@linuxaudiosystems.com>
Sun, 28 Nov 2010 18:31:18 +0000 (18:31 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sun, 28 Nov 2010 18:31:18 +0000 (18:31 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@8117 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/panner.h
libs/ardour/ardour/plugin_insert.h
libs/ardour/audio_track.cc
libs/ardour/automatable.cc
libs/ardour/automation_control.cc
libs/ardour/panner.cc
libs/ardour/plugin_insert.cc
libs/ardour/vbap.cc
libs/pbd/controllable.cc

index 5a4c008c5fed8b9cd443271daa2d52d70c6f4e1f..a4b49a9a72c379622e5c13420b1fbd62441c8168 100644 (file)
@@ -87,6 +87,20 @@ class StreamPanner : public PBD::Stateful
        /* old school automation loading */
        virtual int load (std::istream&, std::string path, uint32_t&) = 0;
 
+       struct PanControllable : public AutomationControl {
+               PanControllable (Session& s, std::string name, StreamPanner& p, Evoral::Parameter param)
+                       : AutomationControl (s, param,
+                                             boost::shared_ptr<AutomationList>(new AutomationList(param)), name)
+                       , streampanner (p)
+               { assert(param.type() != NullAutomation); }
+                
+               AutomationList* alist() { return (AutomationList*)_list.get(); }
+               StreamPanner& streampanner;
+
+               void set_value (double);
+               double get_value (void) const;
+       };
+
   protected:
        friend class Panner;
        Panner& parent;
@@ -99,10 +113,10 @@ class StreamPanner : public PBD::Stateful
 
        bool _muted;
        bool _mono;
-
+        
        boost::shared_ptr<AutomationControl> _control;
 
-       void add_state (XMLNode&);
+       XMLNode& get_state ();
 
        /* Update internal parameters based on this.angles */
        virtual void update () = 0;
@@ -257,30 +271,16 @@ public:
 
        int load ();
 
-       struct PanControllable : public AutomationControl {
-               PanControllable (Session& s, std::string name, Panner& p, Evoral::Parameter param)
-                       : AutomationControl (s, param,
-                                       boost::shared_ptr<AutomationList>(new AutomationList(param)), name)
-                       , panner (p)
-               { assert(param.type() != NullAutomation); }
-
-               AutomationList* alist() { return (AutomationList*)_list.get(); }
-               Panner& panner;
-
-               void set_value (double);
-               double get_value (void) const;
-       };
-
-       boost::shared_ptr<AutomationControl> pan_control (int id, int chan=0) {
+       boost::shared_ptr<AutomationControl> pan_control (int id, uint32_t chan=0) {
                return automation_control (Evoral::Parameter (PanAutomation, chan, id));
        }
 
-       boost::shared_ptr<const AutomationControl> pan_control (int id, int chan=0) const {
+       boost::shared_ptr<const AutomationControl> pan_control (int id, uint32_t chan=0) const {
                return automation_control (Evoral::Parameter (PanAutomation, chan, id));
        }
 
        static std::string value_as_string (double);
-
+        
   private:
        /* disallow copy construction */
        Panner (Panner const &);
index d9b85fe9c9fd844c2762788a5d4168375c6beb4c..9b65ba41f5acab25900729c6ff902fd4bab7faed 100644 (file)
@@ -81,7 +81,8 @@ class PluginInsert : public Processor
 
                void set_value (double val);
                double get_value (void) const;
-
+                XMLNode& get_state();
+                
        private:
                PluginInsert* _plugin;
                bool _logarithmic;
@@ -136,6 +137,7 @@ class PluginInsert : public Processor
        void set_automatable ();
        void control_list_automation_state_changed (Evoral::Parameter, AutoState);
        void set_parameter_state_2X (const XMLNode& node, int version);
+        void set_control_ids (const XMLNode&, int version);
 
        int32_t count_for_configuration (ChanCount in, ChanCount out) const;
 
index 554c89df44031c4916b698a6e035970723671146..ca2291902d277a2e179e760e31c8092cdf344e2b 100644 (file)
@@ -209,6 +209,7 @@ AudioTrack::_set_state (const XMLNode& node, int version, bool call_base)
 {
        const XMLProperty *prop;
        XMLNodeConstIterator iter;
+       XMLNode *child;
 
        if (call_base) {
                if (Route::_set_state (node, version, call_base)) {
@@ -222,9 +223,20 @@ AudioTrack::_set_state (const XMLNode& node, int version, bool call_base)
                _mode = Normal;
        }
 
+       if (version >= 3000) {
+               if ((child = find_named_node (node, X_("Diskstream"))) != 0) {
+                       boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, *child));
+                       ds->do_refill_with_alloc ();
+                       set_diskstream (ds);
+               }
+       }
+
+        /* set rec-enable control *AFTER* setting up diskstream, because it may want to operate
+           on the diskstream as it sets its own state
+        */
+
        XMLNodeList nlist;
        XMLNodeConstIterator niter;
-       XMLNode *child;
 
        nlist = node.children();
        for (niter = nlist.begin(); niter != nlist.end(); ++niter){
@@ -237,13 +249,6 @@ AudioTrack::_set_state (const XMLNode& node, int version, bool call_base)
                 }
        }
 
-       if (version >= 3000) {
-               if ((child = find_named_node (node, X_("Diskstream"))) != 0) {
-                       boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, *child));
-                       ds->do_refill_with_alloc ();
-                       set_diskstream (ds);
-               }
-       }
 
        pending_state = const_cast<XMLNode*> (&node);
 
index 4de2e89b412e6c972479012ace282f00459c705b..903ae5df75587baef6380ad9dbbebe379368cd4b 100644 (file)
@@ -456,9 +456,10 @@ Automatable::control_factory(const Evoral::Parameter& param)
                        warning << "GainAutomation for non-Amp" << endl;
                }
        } else if (param.type() == PanAutomation) {
-               Panner* me = dynamic_cast<Panner*>(this);
-               if (me) {
-                       control = new Panner::PanControllable(me->session(), X_("panner"), *me, param);
+               Panner* panner = dynamic_cast<Panner*>(this);
+               if (panner) {
+                        StreamPanner& sp (panner->streampanner (param.channel()));
+                       control = new StreamPanner::PanControllable (_a_session, X_("direction"), sp, param);
                } else {
                        warning << "PanAutomation for non-Panner" << endl;
                }
index d18a018e260dc4b7ff97c656a9a2ebf76835f968..a1611337fd78f07262a7f272080c8b10289845de 100644 (file)
@@ -55,7 +55,7 @@ AutomationControl::set_value(double value)
  
         if (to_list && parameter().toggled()) {
 
-                //store the previous value just before this so any 
+                // store the previous value just before this so any 
                 // interpolation works right
                 
                 _list->add (get_double(), _session.transport_frame()-1);
index ae70f759418f9255ea1a193404c1477745bb425d..97d911b93d2d879dcfe52069b418845c6df834fc 100644 (file)
@@ -34,6 +34,7 @@
 #include <glibmm.h>
 
 #include "pbd/cartesian.h"
+#include "pbd/convert.h"
 #include "pbd/error.h"
 #include "pbd/failed_constructor.h"
 #include "pbd/xml++.h"
@@ -74,14 +75,14 @@ static double direct_control_to_stereo_pan (double fract)
 
 StreamPanner::StreamPanner (Panner& p, Evoral::Parameter param)
        : parent (p)
+        , _control (new PanControllable (parent.session(), _("direction"), *this, param))
 {
        assert (param.type() != NullAutomation);
 
        _muted = false;
        _mono = false;
 
-       /* get our AutomationControl from our parent Panner, creating it if required */
-       _control = boost::dynamic_pointer_cast<AutomationControl> (parent.control (param, true));
+        p.add_control (_control);
 }
 
 StreamPanner::~StreamPanner ()
@@ -98,14 +99,14 @@ StreamPanner::set_mono (bool yn)
 }
 
 void
-Panner::PanControllable::set_value (double val)
+StreamPanner::PanControllable::set_value (double val)
 {
-       panner.streampanner (parameter().id()).set_position (AngularVector (direct_control_to_stereo_pan (val), 0.0));
+       streampanner.set_position (AngularVector (direct_control_to_stereo_pan (val), 0.0));
        AutomationControl::set_value(val);
 }
 
 double
-Panner::PanControllable::get_value (void) const
+StreamPanner::PanControllable::get_value (void) const
 {
        return AutomationControl::get_value();
 }
@@ -135,7 +136,7 @@ StreamPanner::set_position (const AngularVector& av, bool link_call)
 }
 
 int
-StreamPanner::set_state (const XMLNode& node, int /*version*/)
+StreamPanner::set_state (const XMLNode& node, int version)
 {
        const XMLProperty* prop;
        XMLNodeConstIterator iter;
@@ -148,14 +149,25 @@ StreamPanner::set_state (const XMLNode& node, int /*version*/)
                set_mono (string_is_affirmative (prop->value()));
        }
 
+       for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) {              
+                if ((*iter)->name() == Controllable::xml_node_name) {
+                       if ((prop = (*iter)->property ("name")) != 0 && prop->value() == "direction") {
+                               _control->set_state (**iter, version);
+                       } 
+                }
+        }
+
        return 0;
 }
 
-void
-StreamPanner::add_state (XMLNode& node)
+XMLNode&
+StreamPanner::get_state ()
 {
-       node.add_property (X_("muted"), (muted() ? "yes" : "no"));
-       node.add_property (X_("mono"), (_mono ? "yes" : "no"));
+        XMLNode* node = new XMLNode (X_("StreamPanner"));
+       node->add_property (X_("muted"), (muted() ? "yes" : "no"));
+       node->add_property (X_("mono"), (_mono ? "yes" : "no"));
+       node->add_child_nocopy (_control->get_state ());
+        return *node;
 }
 
 void
@@ -498,52 +510,24 @@ EqualPowerStereoPanner::get_state (void)
 XMLNode&
 EqualPowerStereoPanner::state (bool /*full_state*/)
 {
-       XMLNode* root = new XMLNode ("StreamPanner");
-       char buf[64];
-       LocaleGuard lg (X_("POSIX"));
-
-       snprintf (buf, sizeof (buf), "%.12g", _angles.azi);
-       root->add_property (X_("azimuth"), buf);
-       root->add_property (X_("type"), EqualPowerStereoPanner::name);
-
-       // XXX: dont save automation here... its part of the automatable panner now.
-
-       StreamPanner::add_state (*root);
-
-       root->add_child_nocopy (_control->get_state ());
-
-       return *root;
+       XMLNode& root (StreamPanner::get_state ());
+       root.add_property (X_("type"), EqualPowerStereoPanner::name);
+       return root;
 }
 
 int
 EqualPowerStereoPanner::set_state (const XMLNode& node, int version)
 {
-       const XMLProperty* prop;
        LocaleGuard lg (X_("POSIX"));
 
-       if ((prop = node.property (X_("azimuth")))) {
-               AngularVector a (atof (prop->value().c_str()), 0.0);
-               set_position (a, true);
-       } else if ((prop = node.property (X_("x")))) {
-               /* old school cartesian positioning */
-               AngularVector a;
-               a.azi = BaseStereoPanner::lr_fract_to_azimuth (atof (prop->value().c_str()));
-               set_position (a, true);
-       }
-
        StreamPanner::set_state (node, version);
 
        for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) {
 
-               if ((*iter)->name() == Controllable::xml_node_name) {
-                       if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") {
-                               _control->set_state (**iter, version);
-                       }
-
-               } else if ((*iter)->name() == X_("Automation")) {
-
+                if ((*iter)->name() == X_("Automation")) {
+                        
                        _control->alist()->set_state (*((*iter)->children().front()), version);
-
+                        
                        if (_control->alist()->automation_state() != Off) {
                                double degrees = BaseStereoPanner::lr_fract_to_azimuth (_control->list()->eval (parent.session().transport_frame()));
                                set_position (AngularVector (degrees, 0.0));
@@ -556,7 +540,7 @@ EqualPowerStereoPanner::set_state (const XMLNode& node, int version)
 
 Panner::Panner (string name, Session& s)
        : SessionObject (s, name)
-       , Automatable (s)
+        , Automatable (s)
 {
        //set_name_old_auto (name);
        set_name (name);
@@ -916,21 +900,14 @@ Panner::state (bool full)
        node->add_property (X_("linked"), (_linked ? "yes" : "no"));
        node->add_property (X_("link_direction"), enum_2_string (_link_direction));
        node->add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
-
-       for (vector<Panner::Output>::iterator o = outputs.begin(); o != outputs.end(); ++o) {
-               XMLNode* onode = new XMLNode (X_("Output"));
-               snprintf (buf, sizeof (buf), "%.12g", (*o).position.azi);
-               onode->add_property (X_("azimuth"), buf);
-               snprintf (buf, sizeof (buf), "%.12g", (*o).position.ele);
-               onode->add_property (X_("elevation"), buf);
-               node->add_child_nocopy (*onode);
-       }
+        snprintf (buf, sizeof (buf), "%zd", outputs.size());
+        node->add_property (X_("outputs"), buf);
 
        for (vector<StreamPanner*>::const_iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) {
                node->add_child_nocopy ((*i)->state (full));
        }
 
-       node->add_child_nocopy (get_automation_xml_state ());
+        node->add_child_nocopy (get_automation_xml_state ());
 
        return *node;
 }
@@ -938,7 +915,7 @@ Panner::state (bool full)
 int
 Panner::set_state (const XMLNode& node, int version)
 {
-       XMLNodeList nlist;
+       XMLNodeList nlist = node.children ();
        XMLNodeConstIterator niter;
        const XMLProperty *prop;
        uint32_t i;
@@ -967,27 +944,38 @@ Panner::set_state (const XMLNode& node, int version)
                set_link_direction (LinkDirection (string_2_enum (prop->value(), ld)));
        }
 
-       nlist = node.children();
-
-       for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-               if ((*niter)->name() == X_("Output")) {
-
-                       AngularVector a;
-
-                       if ((prop = (*niter)->property (X_("azimuth")))) {
-                               sscanf (prop->value().c_str(), "%lg", &a.azi);
-                       } else if ((prop = (*niter)->property (X_("x")))) {
-                               /* old school cartesian */
-                               a.azi = BaseStereoPanner::lr_fract_to_azimuth (atof (prop->value().c_str()));
-                       }
-
-                       if ((prop = (*niter)->property (X_("elevation")))) {
-                               sscanf (prop->value().c_str(), "%lg", &a.ele);
-                       }
-
-                       outputs.push_back (Output (a));
-               }
-       }
+        if ((prop = node.property (X_("outputs"))) != 0) {
+                uint32_t n = atoi (prop->value());
+
+                while (n--) {
+                        AngularVector a; // value is irrelevant
+                        outputs.push_back (Output (a));
+                }
+
+        } else {
+                
+                /* old school */
+
+                for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+                        if ((*niter)->name() == X_("Output")) {
+                                
+                                AngularVector a;
+                                
+                                if ((prop = (*niter)->property (X_("azimuth")))) {
+                                        sscanf (prop->value().c_str(), "%lg", &a.azi);
+                                } else if ((prop = (*niter)->property (X_("x")))) {
+                                        /* old school cartesian */
+                                        a.azi = BaseStereoPanner::lr_fract_to_azimuth (atof (prop->value().c_str()));
+                                }
+                                
+                                if ((prop = (*niter)->property (X_("elevation")))) {
+                                        sscanf (prop->value().c_str(), "%lg", &a.ele);
+                                }
+                                
+                                outputs.push_back (Output (a));
+                        }
+                }
+        }
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
@@ -1041,11 +1029,13 @@ Panner::set_state (const XMLNode& node, int version)
                automation_path = Glib::build_filename(_session.automation_dir(), prop->value ());
        }
 
+#ifdef MUST_FIX_PANNER_AUTOMATION
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
                if ((*niter)->name() == X_("Automation")) {
                        set_automation_xml_state (**niter, Evoral::Parameter (PanAutomation));
                }
        }
+#endif
        
        return 0;
 }
index 6786f7a4f67aa377badd8b7c957c3796517e4822..b65077e868d94a940120849cb6c29ed928672312 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "pbd/failed_constructor.h"
 #include "pbd/xml++.h"
+#include "pbd/convert.h"
 
 #include "ardour/audio_buffer.h"
 #include "ardour/automation_list.h"
@@ -695,6 +696,31 @@ PluginInsert::state (bool full)
        return node;
 }
 
+void
+PluginInsert::set_control_ids (const XMLNode& node, int version)
+{
+        const XMLNodeList& nlist = node.children();
+        XMLNodeConstIterator iter;
+        set<Evoral::Parameter>::const_iterator p;
+
+        for (iter = nlist.begin(); iter != nlist.end(); ++iter) {
+                if ((*iter)->name() == Controllable::xml_node_name) {
+                        const XMLProperty* prop;
+
+                        if ((prop = (*iter)->property (X_("parameter"))) != 0) {
+                                uint32_t p = atoi (prop->value());
+                                boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p));
+                                if (!c) {
+                                        continue;
+                                }
+                                boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
+                                if (ac) {
+                                        ac->set_state (**iter, version);
+                                }
+                        }
+                }
+        }
+}
 int
 PluginInsert::set_state(const XMLNode& node, int version)
 {
@@ -779,6 +805,7 @@ PluginInsert::set_state(const XMLNode& node, int version)
 
        if (need_automatables) {
                set_automatable ();
+                set_control_ids (node, version);
        }
 
        /* Handle the node list for this Processor (or Insert if an A2 session) */
@@ -962,6 +989,18 @@ PluginInsert::PluginControl::set_value (double val)
        AutomationControl::set_value(val);
 }
 
+XMLNode&
+PluginInsert::PluginControl::get_state ()
+{
+        stringstream ss;
+
+        XMLNode& node (AutomationControl::get_state());
+        ss << parameter().id();
+        node.add_property (X_("parameter"), ss.str());
+
+        return node;
+}
+
 double
 PluginInsert::PluginControl::get_value (void) const
 {
index 75c18cb7de8d9b1bfc70376a516b7e5c2cd00d23..4e54327acfd840c0f79b9812bfc6dc6c81d79361 100644 (file)
@@ -222,8 +222,9 @@ VBAPanner::get_state ()
 XMLNode&
 VBAPanner::state (bool full_state)
 {
-       XMLNode* node = new XMLNode (X_("VBAPanner"));
-       return *node;
+        XMLNode& node (StreamPanner::get_state());
+       node.add_property (X_("type"), VBAPanner::name);
+       return node;
 }
 
 int
index b79a523a0046de5ecff83e7c8d356e52e6ebca2b..0112ff2b1ccabf76200fdcf30a94e24a196eeac9 100644 (file)
@@ -21,6 +21,7 @@
 #include "pbd/enumwriter.h"
 #include "pbd/xml++.h"
 #include "pbd/error.h"
+#include "pbd/locale_guard.h"
 
 #include "i18n.h"
 
@@ -102,6 +103,7 @@ XMLNode&
 Controllable::get_state ()
 {
        XMLNode* node = new XMLNode (xml_node_name);
+       LocaleGuard lg (X_("POSIX"));
        char buf[64];
 
        node->add_property (X_("name"), _name); // not reloaded from XML state, just there to look at
@@ -114,14 +116,15 @@ Controllable::get_state ()
        return *node;
 }
 
+
 int
 Controllable::set_state (const XMLNode& node, int /*version*/)
 {
+       LocaleGuard lg (X_("POSIX"));
        const XMLProperty* prop;
 
        if ((prop = node.property (X_("id"))) != 0) {
                _id = prop->value();
-               return 0;
        } else {
                error << _("Controllable state node has no ID property") << endmsg;
                return -1;
@@ -136,8 +139,10 @@ Controllable::set_state (const XMLNode& node, int /*version*/)
 
                if (sscanf (prop->value().c_str(), "%f", &val) == 1) {
                        set_value (val);
-               }
-       }
+               } 
+        }
+
+        return 0;
 }
 
 void