#include <sigc++/bind.h>
#include "pbd/xml++.h"
#include "pbd/enumwriter.h"
-#include "pbd/stacktrace.h"
#include "pbd/memento_command.h"
#include "evoral/Curve.hpp"
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
#include "ardour/cycle_timer.h"
+#include "ardour/debug.h"
#include "ardour/delivery.h"
#include "ardour/dB.h"
#include "ardour/internal_send.h"
/* add standard processors other than amp (added by ::init()) */
_meter.reset (new PeakMeter (_session));
+ _meter->set_display_to_user (_meter_point == MeterCustom);
add_processor (_meter, PreFader);
if (_flags & ControlOut) {
void
Route::init ()
{
- _solo_level = 0;
+ _self_solo = false;
+ _soloed_by_others = 0;
_solo_isolated = false;
+ _solo_safe = false;
_active = true;
processor_max_streams.reset();
- _solo_safe = false;
_recordable = true;
order_keys[N_("signal")] = order_key_cnt++;
_silent = false;
_pending_declick = true;
_remote_control_id = 0;
_in_configure_processors = false;
+ _mute_points = MuteMaster::AllPoints;
_route_group = 0;
}
}
+void
+Route::set_solo_safe (bool yn, void *src)
+{
+ if (_solo_safe != yn) {
+ _solo_safe = yn;
+ solo_safe_changed (src);
+ }
+}
+
+bool
+Route::solo_safe() const
+{
+ return _solo_safe;
+}
+
void
Route::set_solo (bool yn, void *src)
{
- if (_solo_safe || _solo_isolated) {
+ if (_solo_safe) {
return;
}
return;
}
- if (soloed() != yn) {
- mod_solo_level (yn ? 1 : -1);
+ if (self_soloed() != yn) {
+ set_self_solo (yn);
+ set_delivery_solo ();
solo_changed (src); /* EMIT SIGNAL */
_solo_control->Changed (); /* EMIT SIGNAL */
}
}
void
-Route::mod_solo_level (int32_t delta)
+Route::set_self_solo (bool yn)
+{
+ _self_solo = yn;
+}
+
+void
+Route::mod_solo_by_others (int32_t delta)
{
if (delta < 0) {
- if (_solo_level >= (uint32_t) delta) {
- _solo_level += delta;
+ if (_soloed_by_others >= (uint32_t) delta) {
+ _soloed_by_others += delta;
} else {
- _solo_level = 0;
+ _soloed_by_others = 0;
}
} else {
- _solo_level += delta;
+ _soloed_by_others += delta;
}
- /* tell main outs what the solo situation is
- */
+ set_delivery_solo ();
+}
+
+void
+Route::set_delivery_solo ()
+{
+ /* tell all delivery processors what the solo situation is, so that they keep
+ delivering even though Session::soloing() is true and they were not
+ explicitly soloed.
+ */
- _main_outs->set_solo_level (_solo_level);
- _main_outs->set_solo_isolated (_solo_isolated);
+ Glib::RWLock::ReaderLock rm (_processor_lock);
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ boost::shared_ptr<Delivery> d;
+
+ if ((d = boost::dynamic_pointer_cast<Delivery> (*i)) != 0) {
+ d->set_solo_level (soloed ());
+ d->set_solo_isolated (solo_isolated());
+ }
+ }
}
void
if (yn != _solo_isolated) {
_solo_isolated = yn;
-
- /* tell main outs what the solo situation is
- */
-
- _main_outs->set_solo_level (_solo_level);
- _main_outs->set_solo_isolated (_solo_isolated);
-
+ set_delivery_solo ();
solo_isolated_changed (src);
}
}
return _solo_isolated;
}
+void
+Route::set_mute_points (MuteMaster::MutePoint mp)
+{
+ _mute_points = mp;
+ mute_points_changed (); /* EMIT SIGNAL */
+
+ if (_mute_master->muted()) {
+ _mute_master->mute_at (_mute_points);
+ mute_changed (this); /* EMIT SIGNAL */
+ }
+}
+
void
Route::set_mute (bool yn, void *src)
{
}
if (muted() != yn) {
- _mute_master->mute (yn);
- mute_changed (src);
+ if (yn) {
+ _mute_master->mute_at (_mute_points);
+ } else {
+ _mute_master->clear_mute ();
+ }
+
+ mute_changed (src); /* EMIT SIGNAL */
}
}
}
_meter.reset (new PeakMeter (_session, node));
+ _meter->set_display_to_user (_meter_point == MeterCustom);
processor = _meter;
} else if (prop->value() == "amp") {
return false;
}
- if (iter == _processors.end() && processor->visible() && !_processors.empty()) {
+ if (iter == _processors.end() && processor->display_to_user() && !_processors.empty()) {
/* check for invisible processors stacked at the end and leave them there */
ProcessorList::iterator p;
p = _processors.end();
--p;
- while (!(*p)->visible() && p != _processors.begin()) {
+ while (!(*p)->display_to_user() && p != _processors.begin()) {
--p;
}
++p;
return false;
}
- if (iter == _processors.end() && processor->visible() && !_processors.empty()) {
+ if (iter == _processors.end() && processor->display_to_user() && !_processors.empty()) {
/* check for invisible processors stacked at the end and leave them there */
ProcessorList::iterator p;
p = _processors.end();
--p;
- while (!(*p)->visible() && p != _processors.begin()) {
+ while (!(*p)->display_to_user() && p != _processors.begin()) {
--p;
}
++p;
list< pair<ChanCount,ChanCount> > configuration;
uint32_t index = 0;
+ DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configure processors\n", _name));
+#ifndef NDEBUG
+ DEBUG_TRACE (DEBUG::Processors, "{\n");
+ for (list<boost::shared_ptr<Processor> >::const_iterator p = _processors.begin(); p != _processors.end(); ++p) {
+ DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID = %2\n", (*p)->name(), (*p)->id()));
+ }
+ DEBUG_TRACE (DEBUG::Processors, "}\n");
+#endif
+
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
if ((*p)->can_support_io_configuration(in, out)) {
+ DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1in = %2 out = %3\n",(*p)->name(), in, out));
configuration.push_back(make_pair(in, out));
in = out;
} else {
configuration */
_session.ensure_buffers (n_process_buffers ());
- _session.ensure_buffers (n_process_buffers ());
-
_in_configure_processors = false;
return 0;
}
Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err)
{
/* "new_order" is an ordered list of processors to be positioned according to "placement".
- NOTE: all processors in "new_order" MUST be marked as visible. There maybe additional
+ NOTE: all processors in "new_order" MUST be marked as display_to_user(). There maybe additional
processors in the current actual processor list that are hidden. Any visible processors
in the current list but not in "new_order" will be assumed to be deleted.
*/
} else {
- if (!(*oiter)->visible()) {
+ if (!(*oiter)->display_to_user()) {
as_it_will_be.push_back (*oiter);
order_string += ':';
}
node->add_property ("order-keys", order_string);
+ node->add_property ("self-solo", (_self_solo ? "yes" : "no"));
+ snprintf (buf, sizeof (buf), "%d", _soloed_by_others);
+ node->add_property ("soloed-by-others", buf);
node->add_child_nocopy (_input->state (full_state));
node->add_child_nocopy (_output->state (full_state));
set_processor_state (processor_state);
- if ((prop = node.property ("solo_level")) != 0) {
- _solo_level = 0; // needed for mod_solo_level() to work
- mod_solo_level (atoi (prop->value()));
+ if ((prop = node.property ("self-solo")) != 0) {
+ set_self_solo (string_is_affirmative (prop->value()));
+ }
+
+ if ((prop = node.property ("soloed-by-others")) != 0) {
+ _soloed_by_others = 0; // needed for mod_solo_by_others () to work
+ mod_solo_by_others (atoi (prop->value()));
}
if ((prop = node.property ("solo-isolated")) != 0) {
set_active (yn);
}
- if ((prop = node.property (X_("soloed"))) != 0) {
- bool yn = string_is_affirmative (prop->value());
-
- /* XXX force reset of solo status */
-
- set_solo (yn, this);
- }
-
if ((prop = node.property (X_("meter-point"))) != 0) {
_meter_point = MeterPoint (string_2_enum (prop->value (), _meter_point));
+ if (_meter) {
+ _meter->set_display_to_user (_meter_point == MeterCustom);
+ }
}
if ((prop = node.property (X_("route-group"))) != 0) {
}
bool
-Route::feeds (boost::shared_ptr<Route> other)
+Route::feeds (boost::shared_ptr<Route> other, bool* only_send)
{
- // cerr << _name << endl;
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("Feeds? %1\n", _name));
if (_output->connected_to (other->input())) {
- // cerr << "\tdirect FEEDS " << other->name() << endl;
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\tdirect FEEDS %2\n", other->name()));
+ if (only_send) {
+ *only_send = false;
+ }
+
return true;
}
+
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
boost::shared_ptr<IOProcessor> iop;
if ((iop = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
if (iop->feeds (other)) {
- // cerr << "\tIOP " << iop->name() << " feeds " << other->name() << endl;
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\tIOP %1 does feed %2\n", iop->name(), other->name()));
+ if (only_send) {
+ *only_send = true;
+ }
return true;
} else {
- // cerr << "\tIOP " << iop->name() << " does NOT feeds " << other->name() << endl;
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\tIOP %1 does NOT feed %2\n", iop->name(), other->name()));
}
+ } else {
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\tPROC %1 is not an IOP\n", (*r)->name()));
}
+
}
- // cerr << "\tdoes NOT FEED " << other->name() << endl;
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\tdoes NOT feed %1\n", other->name()));
return false;
}
void
Route::set_meter_point (MeterPoint p, void *src)
{
- if (_meter_point != p) {
- _meter_point = p;
+ if (_meter_point == p) {
+ return;
+ }
- // Move meter in the processors list
- ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), _meter);
- _processors.erase(loc);
- switch (p) {
- case MeterInput:
- loc = _processors.begin();
- break;
- case MeterPreFader:
- loc = find(_processors.begin(), _processors.end(), _amp);
- break;
- case MeterPostFader:
- loc = _processors.end();
+ {
+ Glib::RWLock::WriterLock lm (_processor_lock);
+ ProcessorList as_it_was (_processors);
+
+ if (p != MeterCustom) {
+ // Move meter in the processors list to reflect the new position
+ ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), _meter);
+ _processors.erase(loc);
+ switch (p) {
+ case MeterInput:
+ loc = _processors.begin();
+ break;
+ case MeterPreFader:
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ break;
+ case MeterPostFader:
+ loc = _processors.end();
+ break;
+ default:
break;
- }
- _processors.insert(loc, _meter);
+ }
+
+ _processors.insert(loc, _meter);
+
+ if (configure_processors_unlocked (0)) {
+ _processors = as_it_was;
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
+ return;
+ }
+
+ _meter->set_display_to_user (false);
- meter_change (src); /* EMIT SIGNAL */
- processors_changed (); /* EMIT SIGNAL */
- _session.set_dirty ();
+ } else {
+
+ // just make it visible and let the user move it
+
+ _meter->set_display_to_user (true);
+ }
+
}
+
+ _meter_point = p;
+ meter_change (src); /* EMIT SIGNAL */
+ processors_changed (); /* EMIT SIGNAL */
+ _session.set_dirty ();
}
+
void
Route::put_control_outs_at (Placement p)
{
return;
}
- // Move meter in the processors list
- ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), _control_outs);
- _processors.erase(loc);
+ {
+ Glib::RWLock::WriterLock lm (_processor_lock);
+ ProcessorList as_it_was (_processors);
+ // Move meter in the processors list
+ ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), _control_outs);
+ _processors.erase(loc);
+
+ switch (p) {
+ case PreFader:
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ if (loc != _processors.begin()) {
+ --loc;
+ }
+ break;
+ case PostFader:
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ assert (loc != _processors.end());
+ loc++;
+ break;
+ }
+
+ _processors.insert(loc, _control_outs);
- switch (p) {
- case PreFader:
- loc = find(_processors.begin(), _processors.end(), _amp);
- if (loc != _processors.begin()) {
- --loc;
+ if (configure_processors_unlocked (0)) {
+ _processors = as_it_was;
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
+ return;
}
- break;
- case PostFader:
- loc = find(_processors.begin(), _processors.end(), _amp);
- assert (loc != _processors.end());
- loc++;
- break;
}
- _processors.insert(loc, _control_outs);
-
processors_changed (); /* EMIT SIGNAL */
_session.set_dirty ();
}
}
}
-#undef DEBUG_LATENCY
-#ifdef DEBUG_LATENCY
- cerr << _name << ": internal redirect latency = " << own_latency << endl;
-#endif
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal redirect latency = %2\n", _name, own_latency));
_output->set_port_latency (own_latency);
signal_latency_changed (); /* EMIT SIGNAL */
}
-#ifdef DEBUG_LATENCY
- cerr << _name << ": input latency = " << _input->signal_latency() << " total = "
- << own_latency << endl;
-#endif
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: input latency = %2 total = %3\n", _name, _input->signal_latency(), own_latency));
return _output->effective_latency ();
}
float
Route::SoloControllable::get_value (void) const
{
- return route.soloed() ? 1.0f : 0.0f;
+ return route.self_soloed() ? 1.0f : 0.0f;
}
void