diff options
Diffstat (limited to 'libs/ardour/insert.cc')
-rw-r--r-- | libs/ardour/insert.cc | 215 |
1 files changed, 208 insertions, 7 deletions
diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index 519bf1ad83..177aa5a98c 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -22,6 +22,7 @@ #include <sigc++/bind.h> #include <pbd/failed_constructor.h> +#include <pbd/enumwriter.h> #include <pbd/xml++.h> #include <ardour/insert.h> @@ -30,6 +31,9 @@ #include <ardour/route.h> #include <ardour/ladspa_plugin.h> #include <ardour/buffer_set.h> +#include <ardour/send.h> +#include <ardour/port_insert.h> +#include <ardour/plugin_insert.h> #ifdef VST_SUPPORT #include <ardour/vst_plugin.h> @@ -49,17 +53,214 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -Insert::Insert(Session& s, string name, Placement p) - : Redirect (s, name, p) +sigc::signal<void,Insert*> Insert::InsertCreated; + +// Always saved as Insert, but may be Redirect in legacy sessions +const string Insert::state_node_name = "Insert"; + +Insert::Insert(Session& session, const string& name, Placement p) + : Automatable(session, name) + , _active(false) + , _next_ab_is_active(false) , _configured(false) + , _placement(p) + , _gui(0) { - // FIXME: default type? } -Insert::Insert(Session& s, string name, Placement p, int imin, int imax, int omin, int omax) - : Redirect (s, name, p, imin, imax, omin, omax) - , _configured(false) +boost::shared_ptr<Insert> +Insert::clone (boost::shared_ptr<const Insert> other) +{ + boost::shared_ptr<const Send> send; + boost::shared_ptr<const PortInsert> port_insert; + boost::shared_ptr<const PluginInsert> plugin_insert; + + if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) { + return boost::shared_ptr<Insert> (new Send (*send)); + } else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) { + return boost::shared_ptr<Insert> (new PortInsert (*port_insert)); + } else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) { + return boost::shared_ptr<Insert> (new PluginInsert (*plugin_insert)); + } else { + fatal << _("programming error: unknown Insert type in Insert::Clone!\n") + << endmsg; + /*NOTREACHED*/ + } + return boost::shared_ptr<Insert>(); +} + +void +Insert::set_sort_key (uint32_t key) +{ + _sort_key = key; +} + +void +Insert::set_placement (Placement p) +{ + if (_placement != p) { + _placement = p; + PlacementChanged (); /* EMIT SIGNAL */ + } +} + +void +Insert::set_active (bool yn) +{ + _active = yn; + ActiveChanged (); +} + +XMLNode& +Insert::get_state (void) +{ + return state (true); +} + +/* NODE STRUCTURE + + <Automation [optionally with visible="...." ]> + <parameter-N> + <AutomationList id=N> + <events> + X1 Y1 + X2 Y2 + .... + </events> + </parameter-N> + <Automation> +*/ + +XMLNode& +Insert::state (bool full_state) +{ + XMLNode* node = new XMLNode (state_node_name); + stringstream sstr; + + // FIXME: This conflicts with "id" used by plugin for name in legacy sessions (ugh). + // Do we need to serialize this? + /* + char buf[64]; + id().print (buf, sizeof (buf)); + node->add_property("id", buf); + */ + + node->add_property("name", _name); + node->add_property("active", active() ? "yes" : "no"); + node->add_property("placement", enum_2_string (_placement)); + + if (_extra_xml){ + node->add_child_copy (*_extra_xml); + } + + if (full_state) { + + XMLNode& automation = Automatable::get_automation_state(); + + for (set<uint32_t>::iterator x = _visible_parameter_automation.begin(); x != _visible_parameter_automation.end(); ++x) { + if (x != _visible_parameter_automation.begin()) { + sstr << ' '; + } + sstr << *x; + } + + automation.add_property ("visible", sstr.str()); + + node->add_child_nocopy (automation); + } + + return *node; +} + +int +Insert::set_state (const XMLNode& node) { - // FIXME: default type? + const XMLProperty *prop; + + if (node.name() != state_node_name) { + error << string_compose(_("incorrect XML node \"%1\" passed to Redirect object"), node.name()) << endmsg; + return -1; + } + + if ((prop = node.property ("name")) == 0) { + warning << _("XML node describing an insert is missing the `name' field") << endmsg; + } else { + set_name(prop->value()); + } + + XMLNodeList nlist = node.children(); + XMLNodeIterator niter; + bool have_io = false; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + + if ((*niter)->name() == X_("Automation")) { + + + XMLProperty *prop; + + if ((prop = (*niter)->property ("path")) != 0) { + old_set_automation_state (*(*niter)); + } else { + Automatable::set_automation_state (*(*niter)); + } + + if ((prop = (*niter)->property ("visible")) != 0) { + uint32_t what; + stringstream sstr; + + _visible_parameter_automation.clear (); + + sstr << prop->value(); + while (1) { + sstr >> what; + if (sstr.fail()) { + break; + } + mark_automation_visible (what, true); + } + } + + } else if ((*niter)->name() == "extra") { + _extra_xml = new XMLNode (*(*niter)); + } + } + + if (!have_io && dynamic_cast<IO*>(this)) { + error << _("XML node describing a redirect is missing an IO node") << endmsg; + return -1; + } + + if ((prop = node.property ("active")) == 0) { + error << _("XML node describing an insert is missing the `active' field") << endmsg; + return -1; + } + + if (_active != (prop->value() == "yes")) { + _active = !_active; + ActiveChanged (); /* EMIT_SIGNAL */ + } + + if ((prop = node.property ("placement")) == 0) { + error << _("XML node describing an insert is missing the `placement' field") << endmsg; + return -1; + } + + /* hack to handle older sessions before we only used EnumWriter */ + + string pstr; + + if (prop->value() == "pre") { + pstr = "PreFader"; + } else if (prop->value() == "post") { + pstr = "PostFader"; + } else { + pstr = prop->value(); + } + + Placement p = Placement (string_2_enum (pstr, p)); + set_placement (p); + + return 0; } |