From 725e106d5dab631d5032b47cab33827f211f9d14 Mon Sep 17 00:00:00 2001 From: carlh Date: Thu, 27 May 2010 17:10:08 +0000 Subject: [PATCH] Take route's processor lock for things called by the process thread. Prevents problems when processors are being reconfigured and a process callback occurs. git-svn-id: svn+ssh://ardour.org/ardour2/branches/3.0@7183 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/route.h | 3 +- libs/ardour/audio_track.cc | 14 +++--- libs/ardour/midi_track.cc | 14 +++--- libs/ardour/route.cc | 103 +++++++++++++++++++++++---------------------- libs/ardour/track.cc | 10 +++++ 5 files changed, 77 insertions(+), 67 deletions(-) diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 44ee0478..95d60e1a 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -440,7 +440,8 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void passthru_silence (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, int declick); - void silence (nframes_t nframes); + void silence (nframes_t); + void silence_unlocked (nframes_t); ChanCount processor_max_streams; uint32_t _remote_control_id; diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index e90c5697..fcd21137 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -351,20 +351,18 @@ int AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick, bool can_record, bool rec_monitors_input, bool& need_butler) { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; + } + int dret; Sample* b; Sample* tmpb; nframes_t transport_frame; boost::shared_ptr diskstream = audio_diskstream(); - { - Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); - if (lm.locked()) { - // automation snapshot can also be called from the non-rt context - // and it uses the redirect list, so we take the lock out here - automation_snapshot (start_frame, false); - } - } + automation_snapshot (start_frame, false); if (n_outputs().n_total() == 0 && _processors.empty()) { return 0; diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 745fa756..fbd1f542 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -280,17 +280,15 @@ int MidiTrack::roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool can_record, bool rec_monitors_input, bool& needs_butler) { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; + } + int dret; boost::shared_ptr diskstream = midi_diskstream(); - { - Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); - if (lm.locked()) { - // automation snapshot can also be called from the non-rt context - // and it uses the redirect list, so we take the lock out here - automation_snapshot (start_frame); - } - } + automation_snapshot (start_frame); if (n_outputs().n_total() == 0 && _processors.empty()) { return 0; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 8ca10387..a2988670 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -448,22 +448,17 @@ Route::process_output_buffers (BufferSet& bufs, and go .... ----------------------------------------------------------------------------------------- */ - Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK); - - if (rm.locked()) { - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - - if (bufs.count() != (*i)->input_streams()) { - cerr << _name << " bufs = " << bufs.count() - << " input for " << (*i)->name() << " = " << (*i)->input_streams() - << endl; - } - assert (bufs.count() == (*i)->input_streams()); + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - (*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back()); - bufs.set_count ((*i)->output_streams()); + if (bufs.count() != (*i)->input_streams()) { + cerr << _name << " bufs = " << bufs.count() + << " input for " << (*i)->name() << " = " << (*i)->input_streams() + << endl; } + assert (bufs.count() == (*i)->input_streams()); + + (*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back()); + bufs.set_count ((*i)->output_streams()); } } @@ -483,7 +478,7 @@ Route::passthru (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, assert (bufs.available() >= input_streams()); if (_input->n_ports() == ChanCount::ZERO) { - silence (nframes); + silence_unlocked (nframes); } bufs.set_count (input_streams()); @@ -1457,18 +1452,16 @@ Route::configure_processors_unlocked (ProcessorStreams* err) uint32_t index = 0; DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configure processors\n", _name)); -#ifndef NDEBUG DEBUG_TRACE (DEBUG::Processors, "{\n"); for (list >::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)); + DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 in = %2 out = %3\n",(*p)->name(), in, out)); configuration.push_back(make_pair(in, out)); in = out; } else { @@ -1501,6 +1494,8 @@ Route::configure_processors_unlocked (ProcessorStreams* err) _session.ensure_buffers (n_process_buffers ()); } + DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configuration complete\n", _name)); + _in_configure_processors = false; return 0; } @@ -2323,31 +2318,37 @@ Route::curve_reallocate () void Route::silence (nframes_t nframes) { - if (!_silent) { - - _output->silence (nframes); - - { - Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return; + } - if (lm.locked()) { - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - boost::shared_ptr pi; + silence_unlocked (nframes); +} - if (!_active && (pi = boost::dynamic_pointer_cast (*i)) != 0) { - // skip plugins, they don't need anything when we're not active - continue; - } +void +Route::silence_unlocked (nframes_t nframes) +{ + /* Must be called with the processor lock held */ + + if (!_silent) { - (*i)->silence (nframes); - } + _output->silence (nframes); - if (nframes == _session.get_block_size()) { - // _silent = true; - } + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + boost::shared_ptr pi; + + if (!_active && (pi = boost::dynamic_pointer_cast (*i)) != 0) { + // skip plugins, they don't need anything when we're not active + continue; } + + (*i)->silence (nframes); + } + + if (nframes == _session.get_block_size()) { + // _silent = true; } - } } @@ -2643,12 +2644,17 @@ int Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, bool session_state_changing, bool /*can_record*/, bool /*rec_monitors_input*/) { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; + } + if (n_outputs().n_total() == 0) { return 0; } if (!_active || n_inputs() == ChanCount::ZERO) { - silence (nframes); + silence_unlocked (nframes); return 0; } if (session_state_changing) { @@ -2658,7 +2664,7 @@ Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, XXX note the absurdity of ::no_roll() being called when we ARE rolling! */ - silence (nframes); + silence_unlocked (nframes); return 0; } /* we're really not rolling, so we're either delivery silence or actually @@ -2678,14 +2684,14 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame) if (_roll_delay > nframes) { _roll_delay -= nframes; - silence (nframes); + silence_unlocked (nframes); /* transport frame is not legal for caller to use */ return 0; } else if (_roll_delay > 0) { nframes -= _roll_delay; - silence (_roll_delay); + silence_unlocked (_roll_delay); /* we've written _roll_delay of samples into the output ports, so make a note of that for future reference. @@ -2703,22 +2709,19 @@ int Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick, bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */) { - { - // automation snapshot can also be called from the non-rt context - // and it uses the processor list, so we try to acquire the lock here - Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); - - if (lm.locked()) { - automation_snapshot (_session.transport_frame(), false); - } + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; } + + automation_snapshot (_session.transport_frame(), false); if (n_outputs().n_total() == 0) { return 0; } if (!_active || n_inputs().n_total() == 0) { - silence (nframes); + silence_unlocked (nframes); return 0; } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index a7325189..870936ad 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -237,6 +237,11 @@ int Track::no_roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing, bool can_record, bool /*rec_monitors_input*/) { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; + } + if (n_outputs().n_total() == 0) { return 0; } @@ -332,6 +337,11 @@ int Track::silent_roll (nframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/, bool can_record, bool rec_monitors_input, bool& need_butler) { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked()) { + return 0; + } + if (n_outputs().n_total() == 0 && _processors.empty()) { return 0; } -- 2.11.4.GIT