From: Paul Davis Date: Sun, 28 Nov 2010 18:31:18 +0000 (+0000) Subject: more or less complete restoration of Controllable::_id from XML, with all that implie... X-Git-Tag: 3.0-alpha5~1191 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=9b7a35cdc0d63d05d91f9deba294bcb7113a9106;p=ardour.git more or less complete restoration of Controllable::_id from XML, with all that implies for MIDI bindings continuing to work across session reloads, and also that the controlled parameter is now set from Controllable::set_value() during session loading, not directly from its "own" XML value; still some funny stuff going on with Panners. This may have broken 2.X session loading in that panners may not be setup correctly git-svn-id: svn://localhost/ardour2/branches/3.0@8117 d708f5d6-7413-0410-9779-e7cbd77b26cf --- diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index 5a4c008c5f..a4b49a9a72 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -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(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 _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(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 pan_control (int id, int chan=0) { + boost::shared_ptr pan_control (int id, uint32_t chan=0) { return automation_control (Evoral::Parameter (PanAutomation, chan, id)); } - boost::shared_ptr pan_control (int id, int chan=0) const { + boost::shared_ptr 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 &); diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index d9b85fe9c9..9b65ba41f5 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -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; diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 554c89df44..ca2291902d 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -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 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 ds (new AudioDiskstream (_session, *child)); - ds->do_refill_with_alloc (); - set_diskstream (ds); - } - } pending_state = const_cast (&node); diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 4de2e89b41..903ae5df75 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -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(this); - if (me) { - control = new Panner::PanControllable(me->session(), X_("panner"), *me, param); + Panner* panner = dynamic_cast(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; } diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index d18a018e26..a1611337fd 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -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); diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index ae70f75941..97d911b93d 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -34,6 +34,7 @@ #include #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 (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::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::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; } diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 6786f7a4f6..b65077e868 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -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::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 c = control (Evoral::Parameter (PluginAutomation, 0, p)); + if (!c) { + continue; + } + boost::shared_ptr ac = boost::dynamic_pointer_cast (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 { diff --git a/libs/ardour/vbap.cc b/libs/ardour/vbap.cc index 75c18cb7de..4e54327acf 100644 --- a/libs/ardour/vbap.cc +++ b/libs/ardour/vbap.cc @@ -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 diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc index b79a523a00..0112ff2b1c 100644 --- a/libs/pbd/controllable.cc +++ b/libs/pbd/controllable.cc @@ -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