, _in_configure_processors (false)
, _initial_io_setup (false)
, _custom_meter_position_noted (false)
- , _last_custom_meter_was_at_end (false)
{
if (is_master()) {
_meter_type = MeterK20;
/* now that we have _meter, its safe to connect to this */
- Metering::Meter.connect_same_thread (*this, (boost::bind (&Route::meter, this)));
-
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
configure_processors (0);
framecnt_t latency = 0;
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
if (meter_already_run && boost::dynamic_pointer_cast<PeakMeter> (*i)) {
/* don't ::run() the meter, otherwise it will have its previous peak corrupted */
if (_meter) {
- _meter->reset_max_channels (processor_max_streams);
+ _meter->set_max_channels (processor_max_streams);
}
/* make sure we have sufficient scratch buffers to cope with the new processor
after->id().print (buf, sizeof (buf));
node->add_property (X_("processor-after-last-custom-meter"), buf);
}
-
- node->add_property (X_("last-custom-meter-was-at-end"), _last_custom_meter_was_at_end ? "yes" : "no");
}
return *node;
}
}
- if ((prop = node.property (X_("last-custom-meter-was-at-end"))) != 0) {
- _last_custom_meter_was_at_end = string_is_affirmative (prop->value ());
- }
-
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
#ifdef __clang__
__attribute__((annotate("realtime")))
#endif
-void
+bool
Route::apply_processor_changes_rt ()
{
+ int emissions = EmitNone;
+
if (_pending_meter_point != _meter_point) {
Glib::Threads::RWLock::WriterLock pwl (_processor_lock, Glib::Threads::TRY_LOCK);
if (pwl.locked()) {
/* meters always have buffers for 'processor_max_streams'
* they can be re-positioned without re-allocation */
- set_meter_point_unlocked();
+ if (set_meter_point_unlocked()) {
+ emissions |= EmitMeterChanged | EmitMeterVisibilityChange;;
+ } else {
+ emissions |= EmitMeterChanged;
+ }
}
}
if (pwl.locked()) {
apply_processor_order (_pending_processor_order);
setup_invisible_processors ();
-
changed = true;
g_atomic_int_set (&_pending_process_reorder, 0);
+ emissions |= EmitRtProcessorChange;
}
}
if (changed) {
- processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
set_processor_positions ();
}
+ if (emissions != 0) {
+ g_atomic_int_set (&_pending_signals, emissions);
+ return true;
+ }
+ return false;
+}
+
+void
+Route::emit_pending_signals ()
+{
+
+ int sig = g_atomic_int_and (&_pending_signals, 0);
+ if (sig & EmitMeterChanged) {
+ _meter->emit_configuration_changed();
+ meter_change (); /* EMIT SIGNAL */
+ if (sig & EmitMeterVisibilityChange) {
+ processors_changed (RouteProcessorChange (RouteProcessorChange::MeterPointChange, true)); /* EMIT SIGNAL */
+ } else {
+ processors_changed (RouteProcessorChange (RouteProcessorChange::MeterPointChange, false)); /* EMIT SIGNAL */
+ }
+ }
+ if (sig & EmitRtProcessorChange) {
+ processors_changed (RouteProcessorChange (RouteProcessorChange::RealTimeChange)); /* EMIT SIGNAL */
+ }
}
void
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
_pending_meter_point = p;
- set_meter_point_unlocked();
+ _meter->emit_configuration_changed();
+ meter_change (); /* EMIT SIGNAL */
+ if (set_meter_point_unlocked()) {
+ processors_changed (RouteProcessorChange (RouteProcessorChange::MeterPointChange, true)); /* EMIT SIGNAL */
+ } else {
+ processors_changed (RouteProcessorChange (RouteProcessorChange::MeterPointChange, false)); /* EMIT SIGNAL */
+ }
} else {
_pending_meter_point = p;
}
#ifdef __clang__
__attribute__((annotate("realtime")))
#endif
-void
+bool
Route::set_meter_point_unlocked ()
{
#ifndef NDEBUG
bool meter_was_visible_to_user = _meter->display_to_user ();
- maybe_note_meter_position ();
+ if (!_custom_meter_position_noted) {
+ maybe_note_meter_position ();
+ }
if (_meter_point != MeterCustom) {
setup_invisible_processors ();
} else {
-
_meter->set_display_to_user (true);
/* If we have a previous position for the custom meter, try to put it there */
- if (_custom_meter_position_noted) {
- boost::shared_ptr<Processor> after = _processor_after_last_custom_meter.lock ();
-
- if (after) {
- ProcessorList::iterator i = find (_processors.begin(), _processors.end(), after);
- if (i != _processors.end ()) {
- _processors.remove (_meter);
- _processors.insert (i, _meter);
- }
- } else if (_last_custom_meter_was_at_end) {
+ boost::shared_ptr<Processor> after = _processor_after_last_custom_meter.lock ();
+ if (after) {
+ ProcessorList::iterator i = find (_processors.begin(), _processors.end(), after);
+ if (i != _processors.end ()) {
_processors.remove (_meter);
- _processors.push_back (_meter);
+ _processors.insert (i, _meter);
}
+ } else {// at end, right before the mains_out/panner
+ _processors.remove (_meter);
+ ProcessorList::iterator main = _processors.end();
+ _processors.insert (--main, _meter);
}
}
* but all those signals are subscribed to with gui_thread()
* so we're safe.
*/
- meter_change (); /* EMIT SIGNAL */
- bool const meter_visibly_changed = (_meter->display_to_user() != meter_was_visible_to_user);
- processors_changed (RouteProcessorChange (RouteProcessorChange::MeterPointChange, meter_visibly_changed)); /* EMIT SIGNAL */
+ return (_meter->display_to_user() != meter_was_visible_to_user);
}
void
}
}
-void
-Route::meter ()
-{
- Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
-
- assert (_meter);
-
- _meter->meter ();
-
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-
- boost::shared_ptr<Send> s;
- boost::shared_ptr<Return> r;
-
- if ((s = boost::dynamic_pointer_cast<Send> (*i)) != 0) {
- s->meter()->meter();
- } else if ((r = boost::dynamic_pointer_cast<Return> (*i)) != 0) {
- r->meter()->meter ();
- }
- }
-}
-
boost::shared_ptr<Pannable>
Route::pannable() const
{
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
bool had_amp = false;
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
(*i)->set_pre_fader (!had_amp);
if (boost::dynamic_pointer_cast<Amp> (*i)) {
had_amp = true;
}
_custom_meter_position_noted = true;
+ /* custom meter points range from after trim to before panner/main_outs
+ * this is a limitation by the current processor UI
+ */
+ bool seen_trim = false;
+ _processor_after_last_custom_meter.reset();
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ if ((*i) == _trim) {
+ seen_trim = true;
+ }
+ if ((*i) == _main_outs) {
+ _processor_after_last_custom_meter = *i;
+ break;
+ }
if (boost::dynamic_pointer_cast<PeakMeter> (*i)) {
- ProcessorList::iterator j = i;
- ++j;
- if (j != _processors.end ()) {
- _processor_after_last_custom_meter = *j;
- _last_custom_meter_was_at_end = false;
+ if (!seen_trim) {
+ _processor_after_last_custom_meter = _trim;
} else {
- _last_custom_meter_was_at_end = true;
+ ProcessorList::iterator j = i;
+ ++j;
+ assert(j != _processors.end ()); // main_outs should be before
+ _processor_after_last_custom_meter = *j;
}
+ break;
}
}
+ assert(_processor_after_last_custom_meter.lock());
}
boost::shared_ptr<Processor>