void
Graph::engine_stopped ()
{
+#ifndef NDEBUG
+ cerr << "Graph::engine_stopped. n_thread: " << AudioEngine::instance()->process_thread_count() << endl;
+#endif
if (AudioEngine::instance()->process_thread_count() != 0) {
drop_threads ();
}
AudioEngine::instance()->join_process_threads ();
+ /* signal main process thread if it's waiting for an already terminated thread */
+ _callback_done_sem.signal ();
_execution_tokens = 0;
+
+ /* reset semaphores.
+ * This is somewhat ugly, yet if a thread is killed (e.g jackd terminates
+ * abnormally), some semaphores are still unlocked.
+ */
+#ifndef NDEBUG
+ int d1 = _execution_sem.reset ();
+ int d2 = _callback_start_sem.reset ();
+ int d3 = _callback_done_sem.reset ();
+ cerr << "Graph::drop_threads() sema-counts: " << d1 << ", " << d2<< ", " << d3 << endl;
+#else
+ _execution_sem.reset ();
+ _callback_start_sem.reset ();
+ _callback_done_sem.reset ();
+#endif
}
void
Graph::restart_cycle()
{
// we are through. wakeup our caller.
+ DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 cycle done.\n", pthread_name()));
again:
_callback_done_sem.signal ();
return;
}
+ DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 prepare new cycle.\n", pthread_name()));
prep ();
if (_graph_empty && _threads_active) {
DEBUG_TRACE(DEBUG::ProcessThreads, "main thread is awake\n");
if (!_threads_active) {
+ pt->drop_buffers();
+ delete (pt);
return;
}
/* This loop will run forever */
while (1) {
- DEBUG_TRACE(DEBUG::ProcessThreads, "main thread runs one graph node\n");
+ DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("main thread (%1) runs one graph node\n", pthread_name ()));
if (run_one()) {
break;
}
}
int
-Graph::silent_process_routes (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool& need_butler)
-{
- if (!_threads_active) return 0;
-
- _process_nframes = nframes;
- _process_start_frame = start_frame;
- _process_end_frame = end_frame;
-
- _process_silent = true;
- _process_noroll = false;
- _process_retval = 0;
- _process_need_butler = false;
-
- if (!_graph_empty) {
- DEBUG_TRACE(DEBUG::ProcessThreads, "wake graph for silent process\n");
- _callback_start_sem.signal ();
- _callback_done_sem.wait ();
- }
-
- need_butler = _process_need_butler;
-
- return _process_retval;
-}
-
-int
-Graph::process_routes (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
+Graph::process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler)
{
- DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("graph execution from %1 to %2 = %3\n", start_frame, end_frame, nframes));
+ DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("graph execution from %1 to %2 = %3\n", start_sample, end_sample, nframes));
if (!_threads_active) return 0;
_process_nframes = nframes;
- _process_start_frame = start_frame;
- _process_end_frame = end_frame;
+ _process_start_sample = start_sample;
+ _process_end_sample = end_sample;
_process_declick = declick;
- _process_silent = false;
_process_noroll = false;
_process_retval = 0;
_process_need_butler = false;
DEBUG_TRACE(DEBUG::ProcessThreads, "wake graph for non-silent process\n");
_callback_start_sem.signal ();
_callback_done_sem.wait ();
-
DEBUG_TRACE (DEBUG::ProcessThreads, "graph execution complete\n");
need_butler = _process_need_butler;
}
int
-Graph::routes_no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
+Graph::routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
bool non_rt_pending, int declick)
{
- DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("no-roll graph execution from %1 to %2 = %3\n", start_frame, end_frame, nframes));
+ DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("no-roll graph execution from %1 to %2 = %3\n", start_sample, end_sample, nframes));
if (!_threads_active) return 0;
_process_nframes = nframes;
- _process_start_frame = start_frame;
- _process_end_frame = end_frame;
+ _process_start_sample = start_sample;
+ _process_end_sample = end_sample;
_process_declick = declick;
_process_non_rt_pending = non_rt_pending;
- _process_silent = false;
_process_noroll = true;
_process_retval = 0;
_process_need_butler = false;
DEBUG_TRACE(DEBUG::ProcessThreads, "wake graph for no-roll process\n");
_callback_start_sem.signal ();
_callback_done_sem.wait ();
+ DEBUG_TRACE (DEBUG::ProcessThreads, "graph execution complete\n");
return _process_retval;
}
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 runs route %2\n", pthread_name(), route->name()));
- if (_process_silent) {
- retval = route->silent_roll (_process_nframes, _process_start_frame, _process_end_frame, need_butler);
- } else if (_process_noroll) {
+ if (_process_noroll) {
route->set_pending_declick (_process_declick);
- retval = route->no_roll (_process_nframes, _process_start_frame, _process_end_frame, _process_non_rt_pending);
+ retval = route->no_roll (_process_nframes, _process_start_sample, _process_end_sample, _process_non_rt_pending);
} else {
route->set_pending_declick (_process_declick);
- retval = route->roll (_process_nframes, _process_start_frame, _process_end_frame, _process_declick, need_butler);
+ retval = route->roll (_process_nframes, _process_start_sample, _process_end_sample, _process_declick, need_butler);
}
if (retval) {