X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=c1f7d97d5cc87d4281413bf3dbec18fe446ecdc7;hb=9f4c7a9e9edd260a72f040b036982d4c5da89292;hp=452d611d87628c9bd064ffb5cfd94b2055f67f47;hpb=6f14394c958409a8a4153b5ab929670cc1970937;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 452d611d87..c1f7d97d5c 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -22,35 +22,36 @@ #include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "pbd/xml++.h" +#include "pbd/enumwriter.h" +#include "pbd/stacktrace.h" +#include "pbd/memento_command.h" + +#include "evoral/Curve.hpp" + +#include "ardour/timestamps.h" +#include "ardour/audioengine.h" +#include "ardour/route.h" +#include "ardour/buffer.h" +#include "ardour/processor.h" +#include "ardour/plugin_insert.h" +#include "ardour/port_insert.h" +#include "ardour/send.h" +#include "ardour/session.h" +#include "ardour/utils.h" +#include "ardour/configuration.h" +#include "ardour/cycle_timer.h" +#include "ardour/route_group.h" +#include "ardour/port.h" +#include "ardour/audio_port.h" +#include "ardour/ladspa_plugin.h" +#include "ardour/panner.h" +#include "ardour/dB.h" +#include "ardour/amp.h" +#include "ardour/meter.h" +#include "ardour/buffer_set.h" +#include "ardour/mix.h" +#include "ardour/profile.h" #include "i18n.h" @@ -61,19 +62,21 @@ using namespace PBD; uint32_t Route::order_key_cnt = 0; sigc::signal Route::SyncOrderKeys; -Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type) - : IO (sess, name, input_min, input_max, output_min, output_max, default_type), - _flags (flg), - _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)), - _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl)) +Route::Route (Session& sess, string name, + int in_min, int in_max, int out_min, int out_max, + Flag flg, DataType default_type) + : IO (sess, name, in_min, in_max, out_min, out_max, default_type) + , _flags (flg) + , _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)) + , _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl)) { init (); } Route::Route (Session& sess, const XMLNode& node, DataType default_type) - : IO (sess, *node.child ("IO"), default_type), - _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)), - _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl)) + : IO (sess, *node.child ("IO"), default_type) + , _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)) + , _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl)) { init (); _set_state (node, false); @@ -187,16 +190,12 @@ Route::sync_order_keys (const char* base) uint32_t key; if ((i = order_keys.find (base)) == order_keys.end()) { - /* key doesn't exist, use the first existing - key (this is done during session initialization) - */ + /* key doesn't exist, use the first existing key (during session initialization) */ i = order_keys.begin(); key = i->second; ++i; } else { - /* key exists - use it and reset all others - (actually, itself included) - */ + /* key exists - use it and reset all others (actually, itself included) */ i = order_keys.begin(); key = i->second; } @@ -211,8 +210,7 @@ Route::ensure_track_or_route_name(string name, Session &session) { string newname = name; - while (session.route_by_name (newname)!=NULL) - { + while (session.route_by_name (newname) != NULL) { newname = bump_name_once (newname); } @@ -294,9 +292,8 @@ Route::set_gain (gain_t val, void *src) */ void Route::process_output_buffers (BufferSet& bufs, - nframes_t start_frame, nframes_t end_frame, - nframes_t nframes, nframes_t offset, bool with_processors, int declick, - bool meter) + nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset, + bool with_processors, int declick, bool meter) { // This is definitely very audio-only for now assert(_default_type == DataType::AUDIO); @@ -346,9 +343,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- GLOBAL DECLICK (for transport changes etc.) - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (declick > 0) { Amp::run_in_place (bufs, nframes, 0.0, 1.0, false); @@ -367,9 +364,9 @@ Route::process_output_buffers (BufferSet& bufs, } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- INPUT METERING & MONITORING - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (meter && (_meter_point == MeterInput)) { _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset); @@ -398,7 +395,8 @@ Route::process_output_buffers (BufferSet& bufs, // TODO: this is probably wrong - (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) + ( no_monitor && record_enabled() + && (!Config->get_auto_input() || _session.actively_recording()) ) ) { @@ -411,9 +409,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ----------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- DENORMAL CONTROL - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (_denormal_protection || Config->get_denormal_protection()) { @@ -426,9 +424,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- PRE-FADER REDIRECTS - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (with_processors) { Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK); @@ -460,7 +458,7 @@ Route::process_output_buffers (BufferSet& bufs, } /* When we entered this method, the number of bufs was set by n_process_buffers(), so - * it may be larger than required. Consider, for example, a mono track with two redirects A and B. + * it may be larger than required. Consider e.g a mono track with two redirects A and B. * If A has one input and three outputs, and B three inputs and one output, n_process_buffers() * will be 3. In this case, now we've done pre-fader redirects, we can reset the number of bufs. */ @@ -472,9 +470,9 @@ Route::process_output_buffers (BufferSet& bufs, mute_declick_applied = true; } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- PRE-FADER METERING & MONITORING - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (meter && (_meter_point == MeterPreFader)) { _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset); @@ -496,7 +494,8 @@ Route::process_output_buffers (BufferSet& bufs, // rec-enabled but not s/w monitoring - (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) + ( no_monitor && record_enabled() + && (!Config->get_auto_input() || _session.actively_recording()) ) ) { @@ -508,9 +507,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- GAIN STAGE - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ /* if not recording or recording and requiring any monitor signal, then apply gain */ @@ -518,9 +517,9 @@ Route::process_output_buffers (BufferSet& bufs, !(record_enabled() && _session.actively_recording()) || - // OR recording + // OR recording - // AND software monitoring required + // AND software monitoring required Config->get_monitoring_model() == SoftwareMonitoring) { @@ -591,11 +590,13 @@ Route::process_output_buffers (BufferSet& bufs, } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- POST-FADER REDIRECTS - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ - /* note that post_fader_work cannot be true unless with_processors was also true, so don't test both */ + /* note that post_fader_work cannot be true unless with_processors was also true, + so don't test both + */ if (post_fader_work) { @@ -631,9 +632,9 @@ Route::process_output_buffers (BufferSet& bufs, mute_declick_applied = true; } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- CONTROL OUTPUT STAGE - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if ((_meter_point == MeterPostFader) && co) { @@ -642,19 +643,20 @@ Route::process_output_buffers (BufferSet& bufs, if ( // silent anyway - (_gain == 0 && !apply_gain_automation) || - - // muted by solo of another track + (_gain == 0 && !apply_gain_automation) || + + // muted by solo of another track !solo_audible || - - // muted by mute of this track + + // muted by mute of this track !mute_audible || - // recording but not s/w monitoring + // recording but not s/w monitoring - (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) + ( no_monitor && record_enabled() + && (!Config->get_auto_input() || _session.actively_recording()) ) ) { @@ -666,9 +668,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- GLOBAL MUTE - ----------------------------------------------------------------------*/ + ----------------------------------------------------------------------------------------- */ if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) { Amp::run_in_place (bufs, nframes, mute_gain, dmg, false); @@ -676,9 +678,9 @@ Route::process_output_buffers (BufferSet& bufs, mute_declick_applied = true; } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- MAIN OUTPUT STAGE - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ solo_audible = dsg > 0; mute_audible = dmg > 0 || !_mute_affects_main_outs; @@ -687,7 +689,8 @@ Route::process_output_buffers (BufferSet& bufs, /* relax */ - } else if (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) { + } else if (no_monitor && record_enabled() + && (!Config->get_auto_input() || _session.actively_recording())) { IO::silence (nframes, offset); @@ -695,15 +698,15 @@ Route::process_output_buffers (BufferSet& bufs, if ( // silent anyway - (_gain == 0 && !apply_gain_automation) || - - // muted by solo of another track, but not using control outs for solo + (_gain == 0 && !apply_gain_automation) || + + // muted by solo of another track, but not using control outs for solo - (!solo_audible && (Config->get_solo_model() != SoloBus)) || - - // muted by mute of this track + (!solo_audible && (Config->get_solo_model() != SoloBus)) || + + // muted by mute of this track - !mute_audible + !mute_audible ) { @@ -725,9 +728,9 @@ Route::process_output_buffers (BufferSet& bufs, } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- POST-FADER METERING - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (meter && (_meter_point == MeterPostFader)) { if ((_gain == 0 && !apply_gain_automation) || dmg == 0) { @@ -752,9 +755,8 @@ Route::process_output_buffers (BufferSet& bufs, */ void Route::process_output_buffers (BufferSet& bufs, - nframes_t start_frame, nframes_t end_frame, - nframes_t nframes, nframes_t offset, bool with_processors, int declick, - bool meter) + nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset, + bool with_processors, int declick, bool meter) { // This is definitely very audio-only for now assert(_default_type == DataType::AUDIO); @@ -804,7 +806,7 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- GLOBAL DECLICK (for transport changes etc.) input metering & monitoring (control outs) denormal control @@ -815,7 +817,7 @@ Route::process_output_buffers (BufferSet& bufs, global mute main output post-fader metering & monitoring (control outs) - */ + ----------------------------------------------------------------------------------------- */ { Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK); @@ -824,9 +826,10 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + + /* ------------------------------------------------------------------------------------------- INPUT METERING & MONITORING - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if (meter && (_meter_point == MeterInput)) { _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset); @@ -838,9 +841,9 @@ Route::process_output_buffers (BufferSet& bufs, mute_declick_applied = true; } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- PRE-FADER REDIRECTS - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ // This really should already be true... bufs.set_count(pre_fader_streams()); @@ -861,7 +864,8 @@ Route::process_output_buffers (BufferSet& bufs, // rec-enabled but not s/w monitoring - (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) + ( no_monitor && record_enabled() + && (!Config->get_auto_input() || _session.actively_recording()) ) ) { @@ -873,9 +877,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- GAIN STAGE - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ /* if not recording or recording and requiring any monitor signal, then apply gain */ @@ -883,9 +887,9 @@ Route::process_output_buffers (BufferSet& bufs, !(record_enabled() && _session.actively_recording()) || - // OR recording + // OR recording - // AND software monitoring required + // AND software monitoring required Config->get_monitoring_model() == SoftwareMonitoring) { @@ -956,10 +960,9 @@ Route::process_output_buffers (BufferSet& bufs, } - - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- CONTROL OUTPUT STAGE - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ if ((_meter_point == MeterPostFader) && co) { @@ -969,17 +972,17 @@ Route::process_output_buffers (BufferSet& bufs, if ( // silent anyway (_gain == 0 && !apply_gain_automation) || - - // muted by solo of another track + + // muted by solo of another track !solo_audible || - - // muted by mute of this track + + // muted by mute of this track !mute_audible || - // recording but not s/w monitoring - + // recording but not s/w monitoring + (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) ) { @@ -992,9 +995,9 @@ Route::process_output_buffers (BufferSet& bufs, } } - /* ---------------------------------------------------------------------------------------------------- + /* ------------------------------------------------------------------------------------------- MAIN OUTPUT STAGE - -------------------------------------------------------------------------------------------------- */ + ----------------------------------------------------------------------------------------- */ solo_audible = dsg > 0; mute_audible = dmg > 0 || !_mute_affects_main_outs; @@ -1003,7 +1006,8 @@ Route::process_output_buffers (BufferSet& bufs, /* relax */ - } else if (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) { + } else if (no_monitor && record_enabled() + && (!Config->get_auto_input() || _session.actively_recording())) { IO::silence (nframes, offset); @@ -1011,22 +1015,22 @@ Route::process_output_buffers (BufferSet& bufs, if ( // silent anyway - (_gain == 0 && !apply_gain_automation) || - - // muted by solo of another track, but not using control outs for solo + (_gain == 0 && !apply_gain_automation) || - (!solo_audible && (Config->get_solo_model() != SoloBus)) || - - // muted by mute of this track + // muted by solo of another track, but not using control outs for solo - !mute_audible + (!solo_audible && (Config->get_solo_model() != SoloBus)) || + + // muted by mute of this track + + !mute_audible ) { /* don't use Route::silence() here, because that causes all outputs (sends, port processors, etc. to be silent). */ - + if (_meter_point == MeterPostFader) { peak_meter().reset(); } @@ -1290,7 +1294,6 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err) /** Turn off all processors with a given placement * @param p Placement of processors to disable */ - void Route::disable_processors (Placement p) { @@ -1307,7 +1310,6 @@ Route::disable_processors (Placement p) /** Turn off all redirects */ - void Route::disable_processors () { @@ -1323,7 +1325,6 @@ Route::disable_processors () /** Turn off all redirects with a given placement * @param p Placement of redirects to disable */ - void Route::disable_plugins (Placement p) { @@ -1340,7 +1341,6 @@ Route::disable_plugins (Placement p) /** Turn off all plugins */ - void Route::disable_plugins () { @@ -1608,8 +1608,6 @@ Route::_reset_processor_counts (ProcessorStreams* err) } else if (boost::dynamic_pointer_cast (*r) != 0) { ++send_cnt; - } else if (boost::dynamic_pointer_cast (*r) != 0) { - ++send_cnt; } } @@ -1673,7 +1671,6 @@ Route::_reset_processor_counts (ProcessorStreams* err) for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) { boost::shared_ptr s; - boost::shared_ptr is; if ((s = boost::dynamic_pointer_cast (*r)) != 0) { @@ -1687,16 +1684,6 @@ Route::_reset_processor_counts (ProcessorStreams* err) s->expect_inputs ((*prev)->output_streams()); } - } else if ((is = boost::dynamic_pointer_cast (*r)) != 0) { - - /* XXX ditto, but clean this inheritance pattern up someday soon */ - - if (r == _processors.begin()) { - is->expect_inputs (n_inputs()); - } else { - is->expect_inputs ((*prev)->output_streams()); - } - } else { max_audio = max ((*r)->output_streams ().n_audio(), max_audio); @@ -1776,87 +1763,6 @@ Route::check_some_processor_counts (list& iclist, ChanCount requ return false; } -int -Route::copy_processors (const Route& other, Placement placement, ProcessorStreams* err) -{ - ChanCount old_pmo = processor_max_outs; - - ProcessorList to_be_deleted; - - { - Glib::RWLock::WriterLock lm (_processor_lock); - ProcessorList::iterator tmp; - ProcessorList the_copy; - - the_copy = _processors; - - /* remove all relevant processors */ - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ) { - tmp = i; - ++tmp; - - if ((*i)->placement() == placement) { - to_be_deleted.push_back (*i); - _processors.erase (i); - } - - i = tmp; - } - - /* now copy the relevant ones from "other" */ - - for (ProcessorList::const_iterator i = other._processors.begin(); i != other._processors.end(); ++i) { - if ((*i)->placement() == placement) { - _processors.push_back (IOProcessor::clone (*i)); - } - } - - /* reset plugin stream handling */ - - if (_reset_processor_counts (err)) { - - /* FAILED COPY ATTEMPT: we have to restore order */ - - /* delete all cloned processors */ - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ) { - - tmp = i; - ++tmp; - - if ((*i)->placement() == placement) { - _processors.erase (i); - } - - i = tmp; - } - - /* restore the natural order */ - - _processors = the_copy; - processor_max_outs = old_pmo; - - /* we failed, even though things are OK again */ - - return -1; - - } else { - - /* SUCCESSFUL COPY ATTEMPT: delete the processors we removed pre-copy */ - to_be_deleted.clear (); - _user_latency = 0; - } - } - - if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) { - reset_panner (); - } - - processors_changed (); /* EMIT SIGNAL */ - return 0; -} - void Route::all_processors_flip () { @@ -2004,7 +1910,7 @@ Route::state(bool full_state) node->add_child_nocopy (_solo_control->get_state ()); node->add_child_nocopy (_mute_control->get_state ()); - XMLNode* remote_control_node = new XMLNode (X_("remote_control")); + XMLNode* remote_control_node = new XMLNode (X_("RemoteControl")); snprintf (buf, sizeof (buf), "%d", _remote_control_id); remote_control_node->add_property (X_("id"), buf); node->add_child_nocopy (*remote_control_node); @@ -2365,22 +2271,21 @@ Route::_set_state (const XMLNode& node, bool call_base) XMLNode *cmt = *(child->children().begin()); _comment = cmt->content(); - } else if (child->name() == X_("extra")) { + } else if (child->name() == X_("Extra")) { _extra_xml = new XMLNode (*child); - } else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) { + } 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 (prop->value() == "mute") { + } else if (prop->value() == "mute") { _mute_control->set_state (*child); _session.add_controllable (_mute_control); } } - else if (child->name() == X_("remote_control")) { + else if (child->name() == X_("RemoteControl")) { if ((prop = child->property (X_("id"))) != 0) { int32_t x; sscanf (prop->value().c_str(), "%d", &x); @@ -3194,3 +3099,16 @@ Route::shift (nframes64_t pos, nframes64_t frames) #endif } + + +int +Route::save_as_template (const string& path, const string& name) +{ + XMLNode& node (state (false)); + XMLTree tree; + + IO::set_name_in_state (*node.children().front(), name); + + tree.set_root (&node); + return tree.write (path.c_str()); +}