diff options
author | Carl Hetherington <carl@carlh.net> | 2009-10-15 00:57:55 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2009-10-15 00:57:55 +0000 |
commit | 79f91c7a205d981d2b8cc15e32a6da02d8423065 (patch) | |
tree | f27dd8319522be8321720ef3560c2207dd56b158 /libs/ardour/route.cc | |
parent | 09efd82c6aea973e3eb9497ef2b09256bf5ddde4 (diff) |
Part 1 of loading 2.X sessions; some things work, some things don't, hacks a-plenty.
LOADING 2.X SESSIONS WITH THIS COMMIT IN PLACE WILL (PROBABLY) CORRUPT THE .ardour FILE,
MAKING THE SESSION UNLOADABLE ON 2.X AND LOSING INFORMATION.
So don't do that unless you make a backup of the session file first.
git-svn-id: svn://localhost/ardour2/branches/3.0@5786 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/route.cc')
-rw-r--r-- | libs/ardour/route.cc | 283 |
1 files changed, 276 insertions, 7 deletions
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 95b651b6ca..7e453653dc 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -96,7 +96,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) _meter_connection = Metering::connect (mem_fun (*this, &Route::meter)); } -Route::Route (Session& sess, const XMLNode& node, DataType default_type) +Route::Route (Session& sess, const XMLNode& node, int version, DataType default_type) : SessionObject (sess, "toBeReset") , AutomatableControls (sess) , _solo_control (new SoloControllable (X_("solo"), *this)) @@ -105,7 +105,7 @@ Route::Route (Session& sess, const XMLNode& node, DataType default_type) { init (); - _set_state (node, false); + _set_state (node, version, false); /* now that we have _meter, its safe to connect to this */ @@ -684,7 +684,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite // Set up processor list channels. This will set processor->[input|output]_streams(), // configure redirect ports properly, etc. - if (configure_processors_unlocked (err)) { ProcessorList::iterator ploc = loc; --ploc; @@ -831,6 +830,64 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter } } + +bool +Route::add_processor_from_xml_2X (const XMLNode& node, int version, ProcessorList::iterator iter) +{ + const XMLProperty *prop; + + try { + boost::shared_ptr<Processor> processor; + + if (node.name() == "Insert") { + + if ((prop = node.property ("type")) != 0) { + + if (prop->value() == "ladspa" || prop->value() == "Ladspa" || + prop->value() == "lv2" || + prop->value() == "vst" || + prop->value() == "audiounit") { + + processor.reset (new PluginInsert (_session, node, version)); + + } else { + + processor.reset (new PortInsert (_session, _mute_master, node, version)); + } + + } + + } else if (node.name() == "Send") { + + processor.reset (new Send (_session, _mute_master, node, version)); + + } else { + + error << string_compose(_("unknown Processor type \"%1\"; ignored"), node.name()) << endmsg; + return false; + } + + if (iter == _processors.end() && processor->visible() && !_processors.empty()) { + /* check for invisible processors stacked at the end and leave them there */ + ProcessorList::iterator p; + p = _processors.end(); + --p; + while (!(*p)->visible() && p != _processors.begin()) { + --p; + } + ++p; + iter = p; + } + + return (add_processor (processor, iter) == 0); + } + + catch (failed_constructor &err) { + warning << _("processor could not be created. Ignored.") << endmsg; + return false; + } +} + int Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor> before, ProcessorStreams* err) { @@ -1326,6 +1383,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err) uint32_t index = 0; for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) { + if ((*p)->can_support_io_configuration(in, out)) { configuration.push_back(make_pair(in, out)); in = out; @@ -1600,15 +1658,18 @@ Route::state(bool full_state) } int -Route::set_state (const XMLNode& node) +Route::set_state (const XMLNode& node, int version) { - return _set_state (node, true); + return _set_state (node, version, true); } int -Route::_set_state (const XMLNode& node, bool /*call_base*/) +Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) { - + if (version < 3000) { + return _set_state_2X (node, version); + } + XMLNodeList nlist; XMLNodeConstIterator niter; XMLNode *child; @@ -1773,6 +1834,200 @@ Route::_set_state (const XMLNode& node, bool /*call_base*/) return 0; } +int +Route::_set_state_2X (const XMLNode& node, int version) +{ + XMLNodeList nlist; + XMLNodeConstIterator niter; + XMLNode *child; + XMLPropertyList plist; + const XMLProperty *prop; + + /* 2X things which still remain to be handled: + * default-type + * muted + * mute-affects-pre-fader + * mute-affects-post-fader + * mute-affects-control-outs + * mute-affects-main-outs + * automation + * controlouts + */ + + if (node.name() != "Route") { + error << string_compose(_("Bad node sent to Route::set_state() [%1]"), node.name()) << endmsg; + return -1; + } + + if ((prop = node.property (X_("flags"))) != 0) { + _flags = Flag (string_2_enum (prop->value(), _flags)); + } else { + _flags = Flag (0); + } + + /* add standard processors */ + + _meter.reset (new PeakMeter (_session)); + add_processor (_meter, PreFader); + + if (_flags & ControlOut) { + /* where we listen to tracks */ + _intreturn.reset (new InternalReturn (_session)); + add_processor (_intreturn, PreFader); + } + + _main_outs.reset (new Delivery (_session, _output, _mute_master, _name, Delivery::Main)); + add_processor (_main_outs, PostFader); + + /* IOs */ + + nlist = node.children (); + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + + child = *niter; + + if (child->name() == IO::state_node_name) { + _input->set_state_2X (*child, version, true); + _output->set_state_2X (*child, version, false); + + if ((prop = child->property (X_("name"))) != 0) { + set_name (prop->value ()); + } + + if ((prop = child->property (X_("id"))) != 0) { + _id = prop->value (); + } + + if ((prop = child->property (X_("active"))) != 0) { + bool yn = string_is_affirmative (prop->value()); + _active = !yn; // force switch + set_active (yn); + } + } + + /* XXX: panners? */ + } + + if ((prop = node.property (X_("phase-invert"))) != 0) { + set_phase_invert (string_is_affirmative (prop->value())); + } + + if ((prop = node.property (X_("denormal-protection"))) != 0) { + set_denormal_protection (string_is_affirmative (prop->value())); + } + + if ((prop = node.property (X_("soloed"))) != 0) { + bool yn = string_is_affirmative (prop->value()); + + /* XXX force reset of solo status */ + + set_solo (yn, this); + } + + if ((prop = node.property (X_("meter-point"))) != 0) { + _meter_point = MeterPoint (string_2_enum (prop->value (), _meter_point)); + } + + /* XXX: if the route was in both a mix group and an edit group, it'll end up + just in the edit group. */ + + if ((prop = node.property (X_("mix-group"))) != 0) { + RouteGroup* route_group = _session.route_group_by_name(prop->value()); + if (route_group == 0) { + error << string_compose(_("Route %1: unknown route group \"%2 in saved state (ignored)"), _name, prop->value()) << endmsg; + } else { + set_route_group (route_group, this); + } + } + + if ((prop = node.property (X_("edit-group"))) != 0) { + RouteGroup* route_group = _session.route_group_by_name(prop->value()); + if (route_group == 0) { + error << string_compose(_("Route %1: unknown route group \"%2 in saved state (ignored)"), _name, prop->value()) << endmsg; + } else { + set_route_group (route_group, this); + } + } + + if ((prop = node.property (X_("order-keys"))) != 0) { + + long n; + + string::size_type colon, equal; + string remaining = prop->value(); + + while (remaining.length()) { + + if ((equal = remaining.find_first_of ('=')) == string::npos || equal == remaining.length()) { + error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining) + << endmsg; + } else { + if (sscanf (remaining.substr (equal+1).c_str(), "%ld", &n) != 1) { + error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining) + << endmsg; + } else { + set_order_key (remaining.substr (0, equal), n); + } + } + + colon = remaining.find_first_of (':'); + + if (colon != string::npos) { + remaining = remaining.substr (colon+1); + } else { + break; + } + } + } + + XMLNodeList redirect_nodes; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter){ + + child = *niter; + + if (child->name() == X_("Send") || child->name() == X_("Insert")) { + redirect_nodes.push_back(child); + } + + } + + set_processor_state_2X (redirect_nodes, version); + + for (niter = nlist.begin(); niter != nlist.end(); ++niter){ + child = *niter; + + if (child->name() == X_("Comment")) { + + /* XXX this is a terrible API design in libxml++ */ + + XMLNode *cmt = *(child->children().begin()); + _comment = cmt->content(); + + } else if (child->name() == X_("Extra")) { + + _extra_xml = new XMLNode (*child); + + } else if (child->name() == X_("Controllable") && (prop = child->property("name")) != 0) { + + if (prop->value() == "solo") { + _solo_control->set_state (*child); + _session.add_controllable (_solo_control); + } + + } else if (child->name() == X_("RemoteControl")) { + if ((prop = child->property (X_("id"))) != 0) { + int32_t x; + sscanf (prop->value().c_str(), "%d", &x); + set_remote_control_id (x); + } + + } + } + + return 0; +} + XMLNode& Route::get_processor_state () { @@ -1785,6 +2040,20 @@ Route::get_processor_state () } void +Route::set_processor_state_2X (XMLNodeList const & nList, int version) +{ + /* We don't bother removing existing processors not in nList, as this + method will only be called when creating a Route from scratch, not + for undo purposes. Just put processors in at the appropriate place + in the list. + */ + + for (XMLNodeConstIterator i = nList.begin(); i != nList.end(); ++i) { + add_processor_from_xml_2X (**i, version, _processors.begin ()); + } +} + +void Route::set_processor_state (const XMLNode& node) { const XMLNodeList &nlist = node.children(); |