From 3f1420880befbdb2a9b40b0d6733a7bf533f6ed9 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 14 Apr 2022 13:24:03 +0200 Subject: [PATCH] Implement IOPlug processing using the Process Graph --- libs/ardour/ardour/session.h | 4 ++ libs/ardour/session.cc | 84 +++++++++++++++++++++++++++++++--- libs/ardour/session_process.cc | 14 ++++++ 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 005353cd5b..c27b135c98 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -2278,9 +2278,13 @@ private: friend class IOPlug; boost::shared_ptr _process_graph; boost::shared_ptr _graph_chain; + boost::shared_ptr _io_graph_chain[2]; void resort_routes_using (boost::shared_ptr); + void resort_io_plugs (); + bool rechain_process_graph (GraphNodeList&); + bool rechain_ioplug_graph (bool); void ensure_route_presentation_info_gap (PresentationInfo::order_t, uint32_t gap_size); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index cb3fe254b1..749144b169 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -485,6 +485,8 @@ Session::Session (AudioEngine &eng, Location::cue_change.connect_same_thread (*this, boost::bind (&Session::cue_marker_change, this, _1)); + IOPluginsChanged.connect_same_thread (*this, boost::bind (&Session::resort_io_plugs, this)); + emit_thread_start (); auto_connect_thread_start (); @@ -675,6 +677,8 @@ Session::destroy () /* drop GraphNode references */ _graph_chain.reset (); + _io_graph_chain[0].reset (); + _io_graph_chain[1].reset (); _butler->drop_references (); delete _butler; @@ -2201,11 +2205,35 @@ Session::resort_routes_using (boost::shared_ptr r) gnl.push_back (rt); } + bool ok = true; + if (rechain_process_graph (gnl)) { r->clear (); for (auto const& nd : gnl) { r->push_back (boost::dynamic_pointer_cast (nd)); } + } else { + ok = false; + } + + /* now create IOPlugs graph-chains */ + boost::shared_ptr io_plugins (_io_plugins.reader ()); + GraphNodeList gnl_pre; + GraphNodeList gnl_post; + for (auto const& p : *io_plugins) { + if (p->is_pre ()) { + gnl_pre.push_back (p); + } else { + gnl_post.push_back (p); + } + } + + if (!rechain_ioplug_graph (true)) { + ok = false; + } + + if (!rechain_ioplug_graph (false)) { + ok = false; } #ifndef NDEBUG @@ -2214,6 +2242,30 @@ Session::resort_routes_using (boost::shared_ptr r) DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 (presentation order %2)\n", i->name(), i->presentation_info().order())); } #endif + + if (ok) { + SuccessfulGraphSort (); /* EMIT SIGNAL */ + return; + } + + /* The topological sort failed, so we have a problem. Tell everyone + * and stick to the old graph; this will continue to be processed, so + * until the feedback is fixed, what is played back will not quite + * reflect what is actually connected. + */ + + FeedbackDetected (); /* EMIT SIGNAL */ +} + +void +Session::resort_io_plugs () +{ + bool ok_pre = rechain_ioplug_graph (true); + bool ok_post = rechain_ioplug_graph (false); + + if (!ok_pre || !ok_post) { + FeedbackDetected (); /* EMIT SIGNAL */ + } } bool @@ -2249,17 +2301,35 @@ Session::rechain_process_graph (GraphNodeList& g) _current_route_graph = edges; - SuccessfulGraphSort (); /* EMIT SIGNAL */ return true; } - /* The topological sort failed, so we have a problem. Tell everyone - * and stick to the old graph; this will continue to be processed, so - * until the feedback is fixed, what is played back will not quite - * reflect what is actually connected. - */ + return false; +} - FeedbackDetected (); /* EMIT SIGNAL */ +bool +Session::rechain_ioplug_graph (bool pre) +{ + boost::shared_ptr io_plugins (_io_plugins.reader ()); + + if (io_plugins->empty ()) { + _io_graph_chain[pre ? 0 : 1].reset (); + return true; + } + + GraphNodeList gnl; + for (auto const& p : *io_plugins) { + if (p->is_pre () == pre) { + gnl.push_back (p); + } + } + + GraphEdges edges; + + if (topological_sort (gnl, edges)) { + _io_graph_chain[pre ? 0 : 1] = boost::shared_ptr (new GraphChain (gnl, edges), boost::bind (&rt_safe_delete, this, _1)); + return true; + } return false; } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 3c287543b5..0e0e90be7b 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -44,8 +44,10 @@ #include "ardour/debug.h" #include "ardour/disk_reader.h" #include "ardour/graph.h" +#include "ardour/io_plug.h" #include "ardour/port.h" #include "ardour/process_thread.h" +#include "ardour/rt_tasklist.h" #include "ardour/scene_changer.h" #include "ardour/session.h" #include "ardour/transport_fsm.h" @@ -108,8 +110,20 @@ Session::process (pframes_t nframes) _engine.main_thread()->get_buffers (); + boost::shared_ptr io_graph_chain = _io_graph_chain[0]; + if (io_graph_chain) { + _process_graph->process_io_plugs (io_graph_chain, nframes, 0); + io_graph_chain.reset (); /* drop reference */ + } + (this->*process_function) (nframes); + io_graph_chain = _io_graph_chain[1]; + if (io_graph_chain) { + _process_graph->process_io_plugs (io_graph_chain, nframes, 0); + io_graph_chain.reset (); /* drop reference */ + } + /* realtime-safe meter-position and processor-order changes * * ideally this would be done in