#include <cassert>
#include <sigc++/bind.h>
-#include <pbd/xml++.h>
-#include <pbd/enumwriter.h>
-#include <pbd/stacktrace.h>
-#include <pbd/memento_command.h>
-
-#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/internal_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 "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"
uint32_t Route::order_key_cnt = 0;
sigc::signal<void,const char*> 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);
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;
}
{
string newname = name;
- while (session.route_by_name (newname)!=NULL)
- {
+ while (session.route_by_name (newname) != NULL) {
newname = bump_name_once (newname);
}
*/
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);
}
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (declick > 0) {
Amp::run_in_place (bufs, nframes, 0.0, 1.0, false);
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
INPUT METERING & MONITORING
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (meter && (_meter_point == MeterInput)) {
_meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
// 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()) )
) {
}
}
- /* -----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
DENORMAL CONTROL
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (_denormal_protection || Config->get_denormal_protection()) {
}
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
PRE-FADER REDIRECTS
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (with_processors) {
Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
}
/* 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.
*/
mute_declick_applied = true;
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
PRE-FADER METERING & MONITORING
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (meter && (_meter_point == MeterPreFader)) {
_meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
// 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()) )
) {
}
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
GAIN STAGE
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
/* if not recording or recording and requiring any monitor signal, then apply gain */
!(record_enabled() && _session.actively_recording()) ||
- // OR recording
+ // OR recording
- // AND software monitoring required
+ // AND software monitoring required
Config->get_monitoring_model() == SoftwareMonitoring) {
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
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) {
mute_declick_applied = true;
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
CONTROL OUTPUT STAGE
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if ((_meter_point == MeterPostFader) && co) {
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()) )
) {
}
}
- /* ----------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
GLOBAL MUTE
- ----------------------------------------------------------------------*/
+ ----------------------------------------------------------------------------------------- */
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
mute_declick_applied = true;
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
MAIN OUTPUT STAGE
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
solo_audible = dsg > 0;
mute_audible = dmg > 0 || !_mute_affects_main_outs;
/* 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);
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
) {
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
POST-FADER METERING
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (meter && (_meter_point == MeterPostFader)) {
if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
*/
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);
}
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
input metering & monitoring (control outs)
denormal control
global mute
main output
post-fader metering & monitoring (control outs)
- */
+ ----------------------------------------------------------------------------------------- */
{
Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
}
}
- /* ----------------------------------------------------------------------------------------------------
+
+ /* -------------------------------------------------------------------------------------------
INPUT METERING & MONITORING
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if (meter && (_meter_point == MeterInput)) {
_meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
mute_declick_applied = true;
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
PRE-FADER REDIRECTS
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
// This really should already be true...
bufs.set_count(pre_fader_streams());
// 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()) )
) {
}
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
GAIN STAGE
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
/* if not recording or recording and requiring any monitor signal, then apply gain */
!(record_enabled() && _session.actively_recording()) ||
- // OR recording
+ // OR recording
- // AND software monitoring required
+ // AND software monitoring required
Config->get_monitoring_model() == SoftwareMonitoring) {
}
-
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
CONTROL OUTPUT STAGE
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
if ((_meter_point == MeterPostFader) && co) {
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()))
) {
}
}
- /* ----------------------------------------------------------------------------------------------------
+ /* -------------------------------------------------------------------------------------------
MAIN OUTPUT STAGE
- -------------------------------------------------------------------------------------------------- */
+ ----------------------------------------------------------------------------------------- */
solo_audible = dsg > 0;
mute_audible = dmg > 0 || !_mute_affects_main_outs;
/* 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);
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();
}
/** Turn off all processors with a given placement
* @param p Placement of processors to disable
*/
-
void
Route::disable_processors (Placement p)
{
/** Turn off all redirects
*/
-
void
Route::disable_processors ()
{
/** Turn off all redirects with a given placement
* @param p Placement of redirects to disable
*/
-
void
Route::disable_plugins (Placement p)
{
/** Turn off all plugins
*/
-
void
Route::disable_plugins ()
{
} else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
++send_cnt;
- } else if (boost::dynamic_pointer_cast<InternalSend> (*r) != 0) {
- ++send_cnt;
}
}
for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
boost::shared_ptr<Send> s;
- boost::shared_ptr<InternalSend> is;
if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
s->expect_inputs ((*prev)->output_streams());
}
- } else if ((is = boost::dynamic_pointer_cast<InternalSend> (*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);
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 ()
{
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);
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);
#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());
+}