Compare commits

...

2 Commits

Author SHA1 Message Date
Robin Gareus dc4247f9bb
Consolidate processing prohibited / silent runs
This uses the Process-lock when processing is not prohibited,
removing the special-case when bouncing audio to a more
general case.

One downside is that while bouncing, timecode masters no longer
run and may loose sync-lock.

However transport does not move while Session::write_one_track()
runs, and a resume will need to seek/varispeed to catch up anyway.
2022-02-03 03:27:57 +01:00
Robin Gareus 58d81f0227
Remove Session::process_can_proceed
Auditioning uses dedicated callback method. There is no need to
return early when starting to audition.
butler_completed_transport_work() which handles PostTransportAudition
and switches process-callbacks happens in sync in Session::process().
2022-02-03 03:23:08 +01:00
5 changed files with 23 additions and 58 deletions

View File

@ -1443,7 +1443,6 @@ private:
std::string _missing_file_replacement;
mutable GATOMIC_QUAL gint _processing_prohibited;
mutable GATOMIC_QUAL gint _record_status;
void add_monitor_section ();
@ -1469,10 +1468,6 @@ private:
samplecnt_t calc_preroll_subcycle (samplecnt_t) const;
void block_processing();
void unblock_processing() { g_atomic_int_set (&_processing_prohibited, 0); }
bool processing_blocked() const { return g_atomic_int_get (&_processing_prohibited); }
static const samplecnt_t bounce_chunk_size;
/* Transport master DLL */
@ -1613,8 +1608,6 @@ private:
TransportFSM* _transport_fsm;
static const PostTransportWork ProcessCannotProceedMask = PostTransportWork (PostTransportAudition);
GATOMIC_QUAL gint _post_transport_work; /* accessed only atomic ops */
PostTransportWork post_transport_work() const { return (PostTransportWork) g_atomic_int_get (const_cast<GATOMIC_QUAL gint*> (&_post_transport_work)); }
void set_post_transport_work (PostTransportWork ptw) { g_atomic_int_set (&_post_transport_work, (gint) ptw); }
@ -1836,7 +1829,6 @@ private:
int fail_roll (pframes_t nframes);
bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work()); }
bool process_can_proceed() const { return !(post_transport_work() & ProcessCannotProceedMask); }
MidiControlUI* midi_control_ui;

View File

@ -257,7 +257,7 @@ AudioEngine::process_callback (pframes_t nframes)
if (!tm.locked()) {
/* return having done nothing */
if (_session) {
if (_session && !_session->bounce_processing ()) {
Xrun();
}
/* really only JACK requires this
@ -298,7 +298,7 @@ AudioEngine::process_callback (pframes_t nframes)
*
* Note: this must be done without holding the _process_lock
*/
if (_session && !_session->processing_blocked ()) {
if (_session) {
bool lp = false;
bool lc = false;
if (g_atomic_int_compare_and_exchange (&_pending_playback_latency_callback, 1, 0)) {
@ -308,13 +308,11 @@ AudioEngine::process_callback (pframes_t nframes)
lc = true;
}
if (lp || lc) {
/* synchronize with Session::processing_blocked
* This lock is not contended by this thread, but acts
* as barrier for Session::block_processing (Session::write_one_track).
/* The process-lock needs to be released before calling Session::update_latency,
* However latency callbacks may not happen concurrently.
*/
Glib::Threads::Mutex::Lock ll (_latency_lock, Glib::Threads::TRY_LOCK);
/* re-check after talking latency-lock */
if (!ll.locked () || _session->processing_blocked ()) {
if (!ll.locked ()) {
if (lc) {
queue_latency_update (false);
}
@ -332,7 +330,16 @@ AudioEngine::process_callback (pframes_t nframes)
}
/* release latency lock, **before** reacquiring process-lock */
ll.release ();
tm.acquire ();
tm.try_acquire ();
if (!tm.locked()) {
if (!_session->bounce_processing ()) {
Xrun();
}
PortManager::silence_outputs (nframes);
return 0;
}
}
}
}
@ -1493,7 +1500,7 @@ AudioEngine::latency_callback (bool for_playback)
* All is fine.
*/
Glib::Threads::Mutex::Lock ll (_latency_lock, Glib::Threads::TRY_LOCK);
if (!ll.locked () || _session->processing_blocked ()) {
if (!ll.locked ()) {
/* Except Session::write_one_track() might just have called block_processing() */
queue_latency_update (for_playback);
} else {

View File

@ -327,7 +327,6 @@ Session::Session (AudioEngine &eng,
g_atomic_int_set (&_playback_load, 0);
g_atomic_int_set (&_capture_load, 0);
g_atomic_int_set (&_post_transport_work, 0);
g_atomic_int_set (&_processing_prohibited, Disabled);
g_atomic_int_set (&_record_status, Disabled);
g_atomic_int_set (&_punch_or_loop, NoConstraint);
g_atomic_int_set (&_current_usecs_per_track, 1000);
@ -847,20 +846,6 @@ Session::destroy ()
}
void
Session::block_processing()
{
g_atomic_int_set (&_processing_prohibited, 1);
/* processing_blocked() is only checked at the beginning
* of the next cycle. So wait until any ongoing
* process-callback returns.
*/
Glib::Threads::Mutex::Lock lm (_engine.process_lock());
/* latency callback may be in process, wait until it completed */
Glib::Threads::Mutex::Lock lx (_engine.latency_lock());
}
void
Session::setup_ltc ()
{
@ -5770,10 +5755,14 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
/* block all process callback handling, so that thread-buffers
* are available here.
*/
block_processing ();
Glib::Threads::Mutex::Lock lm (_engine.process_lock());
_bounce_processing_active = true;
/* prevent concurrent latency callbacks, they must not be called
* concurrently with ::run ()
*/
Glib::Threads::Mutex::Lock lx (_engine.latency_lock());
/* call tree *MUST* hold route_lock */
if ((playlist = track.playlist()) == 0) {
@ -6054,8 +6043,6 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
track.set_block_size (get_block_size());
}
unblock_processing ();
return result;
}

View File

@ -85,12 +85,7 @@ Session::process (pframes_t nframes)
{
TimerRAII tr (dsp_stats[OverallProcess]);
if (processing_blocked()) {
_silent = true;
return;
} else {
_silent = false;
}
_silent = false;
samplepos_t transport_at_start = _transport_sample;
@ -490,11 +485,6 @@ Session::process_with_events (pframes_t nframes)
send_full_time_code (_transport_sample, nframes);
}
if (!process_can_proceed()) {
_silent = true;
return;
}
if (events.empty() || next_event == events.end()) {
try_run_lua (nframes); // also during export ?? ->move to process_without_events()
/* lua scripts may inject events */
@ -518,11 +508,6 @@ Session::process_with_events (pframes_t nframes)
SessionEvent* this_event;
Events::iterator the_next_one;
if (!process_can_proceed()) {
_silent = true;
return;
}
if (!_exporting && config.get_external_sync()) {
if (!implement_master_strategy ()) {
no_roll (nframes);
@ -656,11 +641,6 @@ Session::process_without_events (pframes_t nframes)
bool session_needs_butler = false;
samplecnt_t samples_moved;
if (!process_can_proceed()) {
_silent = true;
return;
}
if (!_exporting && config.get_external_sync()) {
if (!implement_master_strategy ()) {
no_roll (nframes);

View File

@ -178,7 +178,6 @@ Session::pre_engine_init (string fullpath)
*/
timerclear (&last_mmc_step);
g_atomic_int_set (&_processing_prohibited, 0);
g_atomic_int_set (&_record_status, Disabled);
g_atomic_int_set (&_playback_load, 100);
g_atomic_int_set (&_capture_load, 100);