X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fprocessor.cc;h=39c3d68ad7941d8ac35a852e057cd2f0486521f6;hb=f39bcaa4bfe0a6aed097f669f039ae2efcc2642f;hp=8ea45de4065019a4e7d64e0b3d36f6b1515d0d3b;hpb=ca10cc82a4374a5b413c06ead6cc89c53f8881ee;p=ardour.git diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc index 8ea45de406..39c3d68ad7 100644 --- a/libs/ardour/processor.cc +++ b/libs/ardour/processor.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000 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 @@ -17,29 +17,26 @@ */ -#include +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif -#include +#include -#include "pbd/failed_constructor.h" -#include "pbd/enumwriter.h" #include "pbd/xml++.h" +#include "pbd/types_convert.h" +#include "ardour/automatable.h" +#include "ardour/chan_count.h" +#include "ardour/debug.h" #include "ardour/processor.h" -#include "ardour/plugin.h" -#include "ardour/port.h" -#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" +#include "ardour/types.h" + +#ifdef WINDOWS_VST_SUPPORT +#include "ardour/windows_vst_plugin.h" #endif -#ifdef HAVE_AUDIOUNITS +#ifdef AUDIOUNIT_SUPPORT #include "ardour/audio_unit.h" #endif @@ -47,51 +44,74 @@ #include "ardour/session.h" #include "ardour/types.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; using namespace PBD; -sigc::signal Processor::ProcessorCreated; +namespace ARDOUR { class Session; } // Always saved as Processor, but may be IOProcessor or Send in legacy sessions const string Processor::state_node_name = "Processor"; -Processor::Processor(Session& session, const string& name, Placement p) +Processor::Processor(Session& session, const string& name) : SessionObject(session, name) - , AutomatableControls(session) + , Automatable (session) + , _pending_active(false) , _active(false) , _next_ab_is_active(false) , _configured(false) - , _placement(p) - , _gui(0) + , _display_to_user (true) + , _pre_fader (false) + , _ui_pointer (0) + , _window_proxy (0) + , _pinmgr_proxy (0) + , _owner (0) + , _input_latency (0) + , _output_latency (0) + , _capture_offset (0) + , _playback_offset (0) + , _loop_location (0) { } -void -Processor::set_sort_key (uint32_t key) +Processor::Processor (const Processor& other) + : Evoral::ControlSet (other) + , SessionObject (other.session(), other.name()) + , Automatable (other.session()) + , Latent (other) + , _pending_active(other._pending_active) + , _active(other._active) + , _next_ab_is_active(false) + , _configured(false) + , _display_to_user (true) + , _pre_fader (false) + , _ui_pointer (0) + , _window_proxy (0) + , _pinmgr_proxy (0) + , _owner (0) + , _input_latency (0) + , _output_latency (0) + , _capture_offset (0) + , _playback_offset (0) + , _loop_location (other._loop_location) { - _sort_key = key; } - -void -Processor::set_placement (Placement p) + +Processor::~Processor () { - if (_placement != p) { - _placement = p; - PlacementChanged (); /* EMIT SIGNAL */ - } + DEBUG_TRACE (DEBUG::Destruction, string_compose ("processor %1 destructor\n", _name)); } XMLNode& Processor::get_state (void) { - return state (true); + return state (); } -/* NODE STRUCTURE - +/* NODE STRUCTURE + @@ -105,105 +125,116 @@ Processor::get_state (void) */ XMLNode& -Processor::state (bool full_state) +Processor::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)); + node->set_property("id", id()); + node->set_property("name", name()); + node->set_property("active", active()); if (_extra_xml){ node->add_child_copy (*_extra_xml); } - - if (full_state) { - - XMLNode& automation = Automatable::get_automation_state(); - - for (set::iterator x = _visible_controls.begin(); x != _visible_controls.end(); ++x) { - if (x != _visible_controls.begin()) { - sstr << ' '; - } - sstr << *x; + + if (!skip_saving_automation) { + XMLNode& automation = Automatable::get_automation_xml_state(); + if (!automation.children().empty() || !automation.properties().empty()) { + node->add_child_nocopy (automation); + } else { + delete &automation; } + } + + node->set_property("user-latency", _user_latency); + + return *node; +} + +int +Processor::set_state_2X (const XMLNode & node, int /*version*/) +{ + XMLProperty const * prop; + + XMLNodeList children = node.children (); - automation.add_property ("visible", sstr.str()); + for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) { + + if ((*i)->name() == X_("IO")) { + + if ((prop = (*i)->property ("name")) != 0) { + set_name (prop->value ()); + } + + set_id (**i); + + //note: in A2, active state was stored in the Redirect node, not the child IO node + /* + * if ((prop = (*i)->property ("active")) != 0) { + bool const a = string_is_affirmative (prop->value ()); + if (_active != a) { + if (a) { + activate (); + } else { + deactivate (); + } + } + }*/ - node->add_child_nocopy (automation); + } } - return *node; + return 0; } int -Processor::set_state (const XMLNode& node) +Processor::set_state (const XMLNode& node, int version) { - const XMLProperty *prop; - const XMLProperty *legacy_active = 0; - const XMLProperty *legacy_placement = 0; + if (version < 3000) { + return set_state_2X (node, version); + } - // may not exist for legacy sessions - if ((prop = node.property ("name")) != 0) { - set_name(prop->value()); + bool ignore_name; + // Only testing for the presence of the property not value + if (!node.get_property("ignore-name", ignore_name)) { + string name; + // may not exist for legacy 3.0 sessions + if (node.get_property ("name", name)) { + /* don't let derived classes have a crack at set_name, + as some (like Send) will screw with the one we suggest. + */ + Processor::set_name (name); + } + + set_id (node); } XMLNodeList nlist = node.children(); XMLNodeIterator niter; + Stateful::save_extra_xml (node); + + XMLProperty const * prop = 0; + XMLProperty const * legacy_active = 0; + 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 { - set_automation_state (*(*niter), Evoral::Parameter(PluginAutomation)); + set_automation_xml_state (*(*niter), Evoral::Parameter(PluginAutomation)); } - if ((prop = (*niter)->property ("visible")) != 0) { - uint32_t what; - stringstream sstr; - - _visible_controls.clear (); - - sstr << prop->value(); - while (1) { - sstr >> what; - if (sstr.fail()) { - break; - } - // FIXME: other automation types? - mark_automation_visible (Evoral::Parameter(PluginAutomation, 0, what), true); - } - } - - } else if ((*niter)->name() == "Extra") { - _extra_xml = new XMLNode (*(*niter)); } else if ((*niter)->name() == "Redirect") { if ( !(legacy_active = (*niter)->property("active"))) { error << string_compose(_("No %1 property flag in element %2"), "active", (*niter)->name()) << endl; } - if ( !(legacy_placement = (*niter)->property("placement"))) { - error << string_compose(_("No %1 property flag in element %2"), "placement", (*niter)->name()) << endl; - } } } if ((prop = node.property ("active")) == 0) { - warning << _("XML node describing a processor is missing the `active' field, trying legacy active flag from child node") << endmsg; if (legacy_active) { prop = legacy_active; } else { @@ -212,49 +243,86 @@ Processor::set_state (const XMLNode& node) } } - if (_active != (prop->value() == "yes")) { - _active = !_active; - ActiveChanged (); /* EMIT_SIGNAL */ - } - - if ((prop = node.property ("placement")) == 0) { - warning << _("XML node describing a processor is missing the `placement' field, trying legacy placement flag from child node") << endmsg; - if (legacy_placement) { - prop = legacy_placement; + bool const a = string_to (prop->value ()) && !_session.get_bypass_all_loaded_plugins(); + if (_active != a) { + if (a) { + activate (); } else { - error << _("No child node with placement property") << endmsg; - return -1; + deactivate (); } } - /* 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); + node.get_property ("user-latency", _user_latency); return 0; } +/** @pre Caller must hold process lock */ bool Processor::configure_io (ChanCount in, ChanCount out) { /* This class assumes 1:1 input:output.static output stream count. Derived classes must override and set _configured_output appropriately - if this is not the case */ + if this is not the case + */ - _configured_input = in; - _configured_output = out; + _configured_input = in; + _configured_output = out; _configured = true; + ConfigurationChanged (in, out); /* EMIT SIGNAL */ + return true; } + +bool +Processor::map_loop_range (samplepos_t& start, samplepos_t& end) const +{ + if (!_loop_location) { + return false; + } + if (start >= end) { + /* no backwards looping */ + return false; + } + + const samplepos_t loop_end = _loop_location->end (); + if (start < loop_end) { + return false; + } + + const samplepos_t loop_start = _loop_location->start (); + const samplecnt_t looplen = loop_end - loop_start; + const sampleoffset_t start_off = (start - loop_start) % looplen; + const samplepos_t start_pos = loop_start + start_off; + + assert (start >= start_pos); + end -= start - start_pos; + start = start_pos; + assert (end > start); + return true; +} + +void +Processor::set_display_to_user (bool yn) +{ + _display_to_user = yn; +} + +void +Processor::set_pre_fader (bool p) +{ + _pre_fader = p; +} + +void +Processor::set_owner (SessionObject* o) +{ + _owner = o; +} + +SessionObject* +Processor::owner() const +{ + return _owner; +}