summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/export_handler.h2
-rw-r--r--libs/ardour/export_graph_builder.cc10
-rw-r--r--libs/ardour/export_handler.cc28
-rw-r--r--libs/ardour/session_export.cc25
4 files changed, 58 insertions, 7 deletions
diff --git a/libs/ardour/ardour/export_handler.h b/libs/ardour/ardour/export_handler.h
index 1178eb9e79..d270f4d82d 100644
--- a/libs/ardour/ardour/export_handler.h
+++ b/libs/ardour/ardour/export_handler.h
@@ -146,6 +146,8 @@ class LIBARDOUR_API ExportHandler : public ExportElementFactory, public sigc::tr
/* Timespan management */
+ static void* start_timespan_bg (void*);
+
void start_timespan ();
int process_timespan (samplecnt_t samples);
int post_process ();
diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc
index 2a2eb63671..f4d6d21f2d 100644
--- a/libs/ardour/export_graph_builder.cc
+++ b/libs/ardour/export_graph_builder.cc
@@ -25,6 +25,7 @@
#include <vector>
#include <glibmm/miscutils.h>
+#include <glibmm/timer.h>
#include "pbd/uuid.h"
#include "pbd/file_utils.h"
@@ -655,10 +656,17 @@ ExportGraphBuilder::Intermediate::prepare_post_processing()
void
ExportGraphBuilder::Intermediate::start_post_processing()
{
- // called in disk-thread (when exporting in realtime)
+ /* called in disk-thread (when exporting in realtime) */
tmp_file->seek (0, SEEK_SET);
+ /* RT Stem export has multiple TmpFileRt threads,
+ * prevent concurrent calls to enable freewheel ()
+ */
+ Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
if (!AudioEngine::instance()->freewheeling ()) {
AudioEngine::instance()->freewheel (true);
+ while (!AudioEngine::instance()->freewheeling ()) {
+ Glib::usleep (AudioEngine::instance()->usecs_per_cycle ());
+ }
}
}
diff --git a/libs/ardour/export_handler.cc b/libs/ardour/export_handler.cc
index 4aed0ee97e..76869c7a79 100644
--- a/libs/ardour/export_handler.cc
+++ b/libs/ardour/export_handler.cc
@@ -172,6 +172,14 @@ ExportHandler::start_timespan ()
{
export_status->timespan++;
+ /* stop freewheeling and wait for latency callbacks */
+ if (AudioEngine::instance()->freewheeling ()) {
+ AudioEngine::instance()->freewheel (false);
+ do {
+ Glib::usleep (AudioEngine::instance()->usecs_per_cycle ());
+ } while (AudioEngine::instance()->freewheeling ());
+ }
+
if (config_map.empty()) {
// freewheeling has to be stopped from outside the process cycle
export_status->set_running (false);
@@ -266,10 +274,11 @@ ExportHandler::process (samplecnt_t samples)
// wait until we're freewheeling
return 0;
}
- } else {
+ } else if (samples > 0) {
Glib::Threads::Mutex::Lock l (export_status->lock());
return process_timespan (samples);
}
+ return 0;
}
int
@@ -338,6 +347,16 @@ ExportHandler::command_output(std::string output, size_t size)
info << output << endmsg;
}
+void*
+ExportHandler::start_timespan_bg (void* eh)
+{
+ ExportHandler* self = static_cast<ExportHandler*> (eh);
+ self->process_connection.disconnect ();
+ Glib::Threads::Mutex::Lock l (self->export_status->lock());
+ self->start_timespan ();
+ return 0;
+}
+
void
ExportHandler::finish_timespan ()
{
@@ -474,7 +493,12 @@ ExportHandler::finish_timespan ()
config_map.erase (config_map.begin());
}
- start_timespan ();
+ /* finish timespan is called in freewheeling rt-context,
+ * we cannot start a new export from here */
+ assert (AudioEngine::instance()->freewheeling ());
+ pthread_t tid;
+ pthread_create (&tid, NULL, ExportHandler::start_timespan_bg, this);
+ pthread_detach (tid);
}
void
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index c4ef004550..93ca0d5afe 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -111,9 +111,10 @@ Session::start_audio_export (samplepos_t position, bool realtime, bool region_ex
{
if (!_exporting) {
pre_export ();
+ } else {
+ realtime_stop (true, true);
}
- _realtime_export = realtime;
_region_export = region_export;
if (region_export) {
@@ -165,7 +166,6 @@ Session::start_audio_export (samplepos_t position, bool realtime, bool region_ex
} else {
_remaining_latency_preroll = 0;
}
- export_status->stop = false;
/* get transport ready. note how this is calling butler functions
from a non-butler thread. we waited for the butler to stop
@@ -179,15 +179,27 @@ Session::start_audio_export (samplepos_t position, bool realtime, bool region_ex
return -1;
}
- _engine.Freewheel.connect_same_thread (export_freewheel_connection, boost::bind (&Session::process_export_fw, this, _1));
+ assert (!_engine.freewheeling ());
+ assert (!_engine.in_process_thread ());
- if (_realtime_export) {
+ if (realtime) {
Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
_export_rolling = true;
+ _realtime_export = true;
+ export_status->stop = false;
process_function = &Session::process_export_fw;
+ /* this is required for ExportGraphBuilder::Intermediate::start_post_processing */
+ _engine.Freewheel.connect_same_thread (export_freewheel_connection, boost::bind (&Session::process_export_fw, this, _1));
return 0;
} else {
+ if (_realtime_export) {
+ Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ process_function = &Session::process_with_events;
+ }
+ _realtime_export = false;
_export_rolling = true;
+ export_status->stop = false;
+ _engine.Freewheel.connect_same_thread (export_freewheel_connection, boost::bind (&Session::process_export_fw, this, _1));
return _engine.freewheel (true);
}
}
@@ -235,6 +247,11 @@ Session::process_export (pframes_t nframes)
void
Session::process_export_fw (pframes_t nframes)
{
+ if (!_export_rolling) {
+ ProcessExport (0);
+ return;
+ }
+
const bool need_buffers = _engine.freewheeling ();
if (_export_preroll > 0) {