get loop recording working when using seam-ed looping

This commit is contained in:
Paul Davis 2015-09-28 17:42:02 -04:00
parent 0613ddd1f9
commit 34f088576c
3 changed files with 89 additions and 45 deletions

View File

@ -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();

View File

@ -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 ()
{

View File

@ -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);
}