From fbce2d73a8a0bc5c415268ab0c1a868d7b9ac577 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 6 Mar 2022 17:12:23 +0100 Subject: [PATCH] Retain sidechain ports into unknown processors This fixes an issue when loading sessions in "safe mode". Internal side-chain sends are removed if the target port does not exist. Also other port connections are lost if the target port does not exist. --- libs/ardour/ardour/unknown_processor.h | 16 ++++--- libs/ardour/route.cc | 6 +-- libs/ardour/unknown_processor.cc | 58 +++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/libs/ardour/ardour/unknown_processor.h b/libs/ardour/ardour/unknown_processor.h index 31e7399fa1..8dbaf5d2c3 100644 --- a/libs/ardour/ardour/unknown_processor.h +++ b/libs/ardour/ardour/unknown_processor.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2010 Carl Hetherington * Copyright (C) 2013-2017 Paul Davis - * Copyright (C) 2013-2017 Robin Gareus + * Copyright (C) 2013-2022 Robin Gareus * * 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 @@ -21,9 +21,11 @@ #ifndef __ardour_unknown_processor_h__ #define __ardour_unknown_processor_h__ +#include "ardour/libardour_visibility.h" #include "ardour/processor.h" namespace ARDOUR { + class SideChain; /** A stub Processor that can be used in place of a `real' one that cannot be * created for some reason; usually because it requires a plugin which is not @@ -43,7 +45,7 @@ namespace ARDOUR { class LIBARDOUR_API UnknownProcessor : public Processor { public: - UnknownProcessor (Session &, XMLNode const &); + UnknownProcessor (Session&, XMLNode const&, SessionObject*); virtual ~UnknownProcessor (); bool can_support_io_configuration (const ChanCount &, ChanCount &); @@ -54,9 +56,13 @@ protected: private: XMLNode _state; - bool have_ioconfig; - ChanCount *saved_input; - ChanCount *saved_output; + + bool have_ioconfig; + ChanCount* saved_input; + ChanCount* saved_output; + + void add_sidechain_from_xml (const XMLNode& node, int version); + boost::shared_ptr _sidechain; }; } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 7eeb4322d5..4f3ac8bfb4 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -946,7 +946,7 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version) prop->value() == "audiounit") { if (_session.get_disable_all_loaded_plugins ()) { - processor.reset (new UnknownProcessor (_session, node)); + processor.reset (new UnknownProcessor (_session, node, this)); } else { processor.reset (new PluginInsert (_session, time_domain())); processor->set_owner (this); @@ -3262,7 +3262,7 @@ Route::set_processor_state (XMLNode const& node, int version, XMLProperty const* prop->value() == "audiounit") { if (_session.get_disable_all_loaded_plugins ()) { - processor.reset (new UnknownProcessor (_session, node)); + processor.reset (new UnknownProcessor (_session, node, this)); } else { processor.reset (new PluginInsert (_session, time_domain())); processor->set_owner (this); @@ -3287,7 +3287,7 @@ Route::set_processor_state (XMLNode const& node, int version, XMLProperty const* if (processor->set_state (node, version) != 0) { /* This processor could not be configured. Turn it into a UnknownProcessor */ - processor.reset (new UnknownProcessor (_session, node)); + processor.reset (new UnknownProcessor (_session, node, this)); } /* set strict I/O only after loading plugin state, because diff --git a/libs/ardour/unknown_processor.cc b/libs/ardour/unknown_processor.cc index eddc8ef5f6..0dfeaf02ba 100644 --- a/libs/ardour/unknown_processor.cc +++ b/libs/ardour/unknown_processor.cc @@ -1,6 +1,6 @@ /* * Copyright (C) 2010-2011 Carl Hetherington - * Copyright (C) 2013-2017 Robin Gareus + * Copyright (C) 2013-2022 Robin Gareus * Copyright (C) 2016-2017 Paul Davis * * This program is free software; you can redistribute it and/or modify @@ -18,7 +18,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "pbd/types_convert.h" +#include "pbd/xml++.h" + #include "ardour/audio_buffer.h" +#include "ardour/sidechain.h" +#include "ardour/io.h" +#include "ardour/types_convert.h" #include "ardour/unknown_processor.h" #include "pbd/i18n.h" @@ -51,13 +57,15 @@ proc_type_map (std::string const& str) } } -UnknownProcessor::UnknownProcessor (Session& s, XMLNode const & state) +UnknownProcessor::UnknownProcessor (Session&s, XMLNode const &state, SessionObject* o) : Processor (s, "", Temporal::AudioTime) , _state (state) , have_ioconfig (false) , saved_input (0) , saved_output (0) { + set_owner (o); + XMLProperty const* pname = state.property (X_("name")); if (pname) { XMLProperty const* ptype = state.property (X_("type")); @@ -80,6 +88,13 @@ UnknownProcessor::UnknownProcessor (Session& s, XMLNode const & state) have_io |= 2; saved_output = new ChanCount(**i); } + + /* sidechain is a Processor (IO) + * add a SC port to retain connections + */ + if ((*i)->name () == Processor::state_node_name) { + add_sidechain_from_xml (**i, Stateful::loading_state_version); + } } have_ioconfig = (have_io == 3); } @@ -152,3 +167,42 @@ UnknownProcessor::run (BufferSet& bufs, samplepos_t /*start_sample*/, samplepos_ bufs.get_audio (i).silence (nframes); } } + +void +UnknownProcessor::add_sidechain_from_xml (const XMLNode& node, int version) +{ + if (version < 3000) { + return; + } + + XMLNodeList nlist = node.children(); + + if (nlist.size() == 0) { + return; + } + + uint32_t n_audio = 0; + uint32_t n_midi = 0; + + XMLNodeConstIterator it = nlist.front()->children().begin(); + for ( ; it != nlist.front()->children().end(); ++ it) { + if ((*it)->name() == "Port") { + DataType type (DataType::NIL); + (*it)->get_property ("type", type); + if (type == DataType::AUDIO) { + ++n_audio; + } else if (type == DataType::MIDI) { + ++n_midi; + } + } + } + + _sidechain.reset (new SideChain (_session, "toBeRenamed")); + for (uint32_t n = 0; n < n_audio; ++n) { + _sidechain->input()->add_port ("", owner(), DataType::AUDIO); // add a port, don't connect. + } + for (uint32_t n = 0; n < n_midi; ++n) { + _sidechain->input()->add_port ("", owner(), DataType::MIDI); // add a port, don't connect. + } + _sidechain->set_state (node, version); +}