summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-09-28 17:42:02 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2015-09-28 17:42:11 -0400
commit34f088576cff12d7bfe1b21a0cebd3e194371a64 (patch)
tree0396021be74291a5483561910e3dd702e21a3c3d
parent0613ddd1f9b3ccd7de086738aab874c4153a20cc (diff)
get loop recording working when using seam-ed looping
-rw-r--r--libs/ardour/ardour/butler.h2
-rw-r--r--libs/ardour/butler.cc94
-rw-r--r--libs/ardour/session_transport.cc38
3 files changed, 89 insertions, 45 deletions
diff --git a/libs/ardour/ardour/butler.h b/libs/ardour/ardour/butler.h
index 7f0847498e..3a2d8090d5 100644
--- a/libs/ardour/ardour/butler.h
+++ b/libs/ardour/ardour/butler.h
@@ -67,6 +67,8 @@ class LIBARDOUR_API Butler : public SessionHandleRef
framecnt_t audio_diskstream_playback_buffer_size() const { return audio_dstream_playback_buffer_size; }
uint32_t midi_diskstream_buffer_size() const { return midi_dstream_buffer_size; }
+ bool flush_tracks_to_disk (boost::shared_ptr<RouteList>, uint32_t& errors, bool force_flush);
+
static void* _thread_work(void *arg);
void* thread_work();
diff --git a/libs/ardour/butler.cc b/libs/ardour/butler.cc
index 95ba2a3ffe..8542f5e0cb 100644
--- a/libs/ardour/butler.cc
+++ b/libs/ardour/butler.cc
@@ -268,44 +268,7 @@ Butler::thread_work ()
goto restart;
}
- for (i = rl->begin(); !transport_work_requested() && should_run && i != rl->end(); ++i) {
- // cerr << "write behind for " << (*i)->name () << endl;
-
- boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-
- if (!tr) {
- continue;
- }
-
- /* note that we still try to flush diskstreams attached to inactive routes
- */
-
- gint64 before, after;
- int ret;
-
- DEBUG_TRACE (DEBUG::Butler, string_compose ("butler flushes track %1 capture load %2\n", tr->name(), tr->capture_buffer_load()));
- before = g_get_monotonic_time ();
- ret = tr->do_flush (ButlerContext);
- after = g_get_monotonic_time ();
- switch (ret) {
- case 0:
- DEBUG_TRACE (DEBUG::Butler, string_compose ("\tflush complete for %1, %2 usecs\n", tr->name(), after - before));
- break;
-
- case 1:
- DEBUG_TRACE (DEBUG::Butler, string_compose ("\tflush not finished for %1, %2 usecs\n", tr->name(), after - before));
- disk_work_outstanding = true;
- break;
-
- default:
- err++;
- error << string_compose(_("Butler write-behind failure on dstream %1"), (*i)->name()) << endmsg;
- std::cerr << string_compose(_("Butler write-behind failure on dstream %1"), (*i)->name()) << std::endl;
- /* don't break - try to flush all streams in case they
- are split across disks.
- */
- }
- }
+ disk_work_outstanding = flush_tracks_to_disk (rl, err, false);
if (err && _session.actively_recording()) {
/* stop the transport and try to catch as much possible
@@ -315,12 +278,6 @@ Butler::thread_work ()
_session.request_stop ();
}
- if (i != rl->begin() && i != rl->end()) {
- /* we didn't get to all the streams */
- DEBUG_TRACE (DEBUG::Butler, "not all tracks processed, will need to go back for more\n");
- disk_work_outstanding = true;
- }
-
if (!err && transport_work_requested()) {
DEBUG_TRACE (DEBUG::Butler, "transport work requested during flush, back to restart\n");
goto restart;
@@ -330,7 +287,6 @@ Butler::thread_work ()
_session.refresh_disk_space ();
}
-
{
Glib::Threads::Mutex::Lock lm (request_lock);
@@ -351,6 +307,54 @@ Butler::thread_work ()
return (0);
}
+bool
+Butler::flush_tracks_to_disk (boost::shared_ptr<RouteList> rl, uint32_t& errors, bool force)
+{
+ bool disk_work_outstanding = false;
+
+ for (RouteList::iterator i = rl->begin(); (force || !transport_work_requested()) && should_run && i != rl->end(); ++i) {
+
+ // cerr << "write behind for " << (*i)->name () << endl;
+
+ boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+
+ if (!tr) {
+ continue;
+ }
+
+ /* note that we still try to flush diskstreams attached to inactive routes
+ */
+
+ gint64 before, after;
+ int ret;
+
+ DEBUG_TRACE (DEBUG::Butler, string_compose ("butler flushes track %1 capture load %2\n", tr->name(), tr->capture_buffer_load()));
+ before = g_get_monotonic_time ();
+ ret = tr->do_flush (ButlerContext, force);
+ after = g_get_monotonic_time ();
+ switch (ret) {
+ case 0:
+ DEBUG_TRACE (DEBUG::Butler, string_compose ("\tflush complete for %1, %2 usecs\n", tr->name(), after - before));
+ break;
+
+ case 1:
+ DEBUG_TRACE (DEBUG::Butler, string_compose ("\tflush not finished for %1, %2 usecs\n", tr->name(), after - before));
+ disk_work_outstanding = true;
+ break;
+
+ default:
+ errors++;
+ error << string_compose(_("Butler write-behind failure on dstream %1"), (*i)->name()) << endmsg;
+ std::cerr << string_compose(_("Butler write-behind failure on dstream %1"), (*i)->name()) << std::endl;
+ /* don't break - try to flush all streams in case they
+ are split across disks.
+ */
+ }
+ }
+
+ return disk_work_outstanding;
+}
+
void
Butler::schedule_transport_work ()
{
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 72ec1ebdd8..3b2060d2ac 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -326,6 +326,37 @@ Session::butler_transport_work ()
DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
+
+ if (ptw & PostTransportLocate) {
+
+ if (get_play_loop() && !Config->get_seamless_loop() && actively_recording()) {
+
+ /* this locate is happening while we are doing loop
+ * recording but with seam-ed (non-seamless) looping.
+ * We must flush any data to disk before resetting
+ * buffers as part of the pending locate (which happens
+ * a little later in this method).
+ */
+
+ bool more_disk_io_to_do = false;
+ uint32_t errors = 0;
+
+ do {
+ more_disk_io_to_do = _butler->flush_tracks_to_disk (r, errors, true);
+
+ if (errors) {
+ break;
+ }
+
+ if (more_disk_io_to_do) {
+ continue;
+ }
+
+ } while (false);
+
+ }
+ }
+
if (ptw & PostTransportAdjustPlaybackBuffering) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
@@ -1067,6 +1098,13 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
+
+ /* already at the desired position. Not forced to locate,
+ the loop isn't changing, so unless we're told to
+ start rolling also, there's nothing to do but
+ tell the world where we are (again).
+ */
+
if (with_roll) {
set_transport_speed (1.0, 0, false);
}