Timeline: Fix thread synchronization issues during recording.
This commit is contained in:
parent
ab8f23f15d
commit
1f9c2bbb6a
|
@ -36,6 +36,8 @@
|
||||||
// #include "const.h"
|
// #include "const.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "Mutex.H"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
@ -64,8 +66,11 @@ void *Loggable::_dirty_callback_arg = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Mutex _lock;
|
||||||
|
|
||||||
Loggable::~Loggable ( )
|
Loggable::~Loggable ( )
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
_loggables[ _id ].loggable = NULL;
|
_loggables[ _id ].loggable = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,12 +79,15 @@ Loggable::~Loggable ( )
|
||||||
void
|
void
|
||||||
Loggable::block_start ( void )
|
Loggable::block_start ( void )
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
++Loggable::_level;
|
++Loggable::_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Loggable::block_end ( void )
|
Loggable::block_end ( void )
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
|
|
||||||
--Loggable::_level;
|
--Loggable::_level;
|
||||||
|
|
||||||
ASSERT( Loggable::_level >= 0, "Programming error" );
|
ASSERT( Loggable::_level >= 0, "Programming error" );
|
||||||
|
@ -559,6 +567,8 @@ Loggable::compact ( void )
|
||||||
void
|
void
|
||||||
Loggable::log ( const char *fmt, ... )
|
Loggable::log ( const char *fmt, ... )
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );
|
||||||
|
|
||||||
static char * buf = NULL;
|
static char * buf = NULL;
|
||||||
static size_t i = 0;
|
static size_t i = 0;
|
||||||
static size_t buf_size = 0;
|
static size_t buf_size = 0;
|
||||||
|
@ -689,6 +699,8 @@ Loggable::log_print( const Log_Entry *o, const Log_Entry *n ) const
|
||||||
void
|
void
|
||||||
Loggable::log_start ( void )
|
Loggable::log_start ( void )
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
|
|
||||||
if ( ! _old_state )
|
if ( ! _old_state )
|
||||||
{
|
{
|
||||||
_old_state = new Log_Entry;
|
_old_state = new Log_Entry;
|
||||||
|
@ -702,6 +714,8 @@ Loggable::log_start ( void )
|
||||||
void
|
void
|
||||||
Loggable::log_end ( void )
|
Loggable::log_end ( void )
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
|
|
||||||
ASSERT( _old_state, "Programming error: log_end() called before log_start()" );
|
ASSERT( _old_state, "Programming error: log_end() called before log_start()" );
|
||||||
|
|
||||||
if ( --_nest > 0 )
|
if ( --_nest > 0 )
|
||||||
|
@ -737,6 +751,8 @@ Loggable::log_end ( void )
|
||||||
void
|
void
|
||||||
Loggable::log_create ( void ) const
|
Loggable::log_create ( void ) const
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
|
|
||||||
set_dirty();
|
set_dirty();
|
||||||
|
|
||||||
if ( ! _fp )
|
if ( ! _fp )
|
||||||
|
@ -786,6 +802,8 @@ Loggable::record_unjournaled ( void ) const
|
||||||
void
|
void
|
||||||
Loggable::log_destroy ( void ) const
|
Loggable::log_destroy ( void ) const
|
||||||
{
|
{
|
||||||
|
Locker lock( _lock );;
|
||||||
|
|
||||||
/* the unjournaled state may have changed: make a note of it. */
|
/* the unjournaled state may have changed: make a note of it. */
|
||||||
record_unjournaled();
|
record_unjournaled();
|
||||||
|
|
||||||
|
|
|
@ -116,3 +116,10 @@ Thread::join ( void )
|
||||||
pthread_join( _thread, NULL );
|
pthread_join( _thread, NULL );
|
||||||
_thread = 0;
|
_thread = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread::exit ( void *retval )
|
||||||
|
{
|
||||||
|
pthread_exit( retval );
|
||||||
|
_thread = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -52,5 +52,6 @@ public:
|
||||||
bool clone ( void *(*entry_point)(void *), void *arg );
|
bool clone ( void *(*entry_point)(void *), void *arg );
|
||||||
void detach ( void );
|
void detach ( void );
|
||||||
void join ( void );
|
void join ( void );
|
||||||
|
void exit ( void *retval = 0 );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -175,11 +175,14 @@ Audio_Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channe
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** prepare for capturing */
|
/** prepare for capturing */
|
||||||
void
|
void
|
||||||
Audio_Region::prepare ( void )
|
Audio_Region::prepare ( void )
|
||||||
{
|
{
|
||||||
|
THREAD_ASSERT( Capture );
|
||||||
|
|
||||||
|
DMESSAGE( "Preparing capture region" );
|
||||||
|
|
||||||
log_start();
|
log_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,15 +221,10 @@ Audio_Region::finalize ( nframes_t frame )
|
||||||
|
|
||||||
_range.length = frame - _range.start;
|
_range.length = frame - _range.start;
|
||||||
|
|
||||||
log_end();
|
|
||||||
|
|
||||||
_clip->close();
|
_clip->close();
|
||||||
_clip->open();
|
_clip->open();
|
||||||
|
|
||||||
Fl::lock();
|
log_end();
|
||||||
redraw();
|
|
||||||
Fl::awake();
|
|
||||||
Fl::unlock();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ class Audio_Sequence;
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,13 +141,23 @@ Disk_Stream::detach ( void )
|
||||||
void
|
void
|
||||||
Disk_Stream::shutdown ( void )
|
Disk_Stream::shutdown ( void )
|
||||||
{
|
{
|
||||||
|
if ( _thread.running() )
|
||||||
|
{
|
||||||
_terminate = true;
|
_terminate = true;
|
||||||
|
|
||||||
/* try to wake the thread so it'll see that it's time to die */
|
/* try to wake the thread so it'll see that it's time to die */
|
||||||
|
while ( _terminate )
|
||||||
|
{
|
||||||
|
usleep( 100 );
|
||||||
block_processed();
|
block_processed();
|
||||||
|
}
|
||||||
|
|
||||||
if ( _thread.running() )
|
|
||||||
_thread.join();
|
_thread.join();
|
||||||
|
|
||||||
|
sem_destroy( &_blocks );
|
||||||
|
|
||||||
|
sem_init( &_blocks, 0, 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Track *
|
Track *
|
||||||
|
|
|
@ -94,11 +94,12 @@ protected:
|
||||||
virtual void flush ( void ) = 0;
|
virtual void flush ( void ) = 0;
|
||||||
|
|
||||||
void run ( void );
|
void run ( void );
|
||||||
void shutdown ( void );
|
|
||||||
void detach ( void );
|
void detach ( void );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
void shutdown ( void );
|
||||||
|
|
||||||
/* must be set before any Disk_Streams are created */
|
/* must be set before any Disk_Streams are created */
|
||||||
static float seconds_to_buffer;
|
static float seconds_to_buffer;
|
||||||
static size_t disk_io_kbytes;
|
static size_t disk_io_kbytes;
|
||||||
|
|
|
@ -74,10 +74,10 @@ Record_DS::disk_thread ( void )
|
||||||
{
|
{
|
||||||
_thread.name( "Capture" );
|
_thread.name( "Capture" );
|
||||||
|
|
||||||
track()->record( _capture, _frame );
|
|
||||||
|
|
||||||
DMESSAGE( "capture thread running..." );
|
DMESSAGE( "capture thread running..." );
|
||||||
|
|
||||||
|
track()->record( _capture, _frame );
|
||||||
|
|
||||||
const nframes_t nframes = _nframes * _disk_io_blocks;
|
const nframes_t nframes = _nframes * _disk_io_blocks;
|
||||||
|
|
||||||
/* buffer to hold the interleaved data returned by the track reader */
|
/* buffer to hold the interleaved data returned by the track reader */
|
||||||
|
@ -211,7 +211,10 @@ Record_DS::disk_thread ( void )
|
||||||
delete c;
|
delete c;
|
||||||
|
|
||||||
_terminate = false;
|
_terminate = false;
|
||||||
|
|
||||||
DMESSAGE( "capture thread gone" );
|
DMESSAGE( "capture thread gone" );
|
||||||
|
|
||||||
|
_thread.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -258,7 +261,7 @@ Record_DS::stop ( nframes_t frame )
|
||||||
|
|
||||||
_stop_frame = frame;
|
_stop_frame = frame;
|
||||||
|
|
||||||
detach();
|
// detach();
|
||||||
|
|
||||||
DMESSAGE( "recording finished" );
|
DMESSAGE( "recording finished" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,17 @@ Timeline::stop ( void )
|
||||||
t->record_ds->stop( frame );
|
t->record_ds->stop( frame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wait until finalization is complete before continuing */
|
||||||
|
|
||||||
|
DMESSAGE( "Waiting for record threads to shutdown" );
|
||||||
|
for ( int i = tracks->children(); i-- ; )
|
||||||
|
{
|
||||||
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
|
||||||
|
if ( t->armed() && t->record_ds )
|
||||||
|
t->record_ds->shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
Loggable::block_end();
|
Loggable::block_end();
|
||||||
|
|
||||||
activate();
|
activate();
|
||||||
|
|
|
@ -304,7 +304,6 @@ Track::finalize ( Capture *c, nframes_t frame )
|
||||||
* them */
|
* them */
|
||||||
c->audio_file->finalize();
|
c->audio_file->finalize();
|
||||||
|
|
||||||
/* peaks get finalized here */
|
|
||||||
c->region->finalize( frame );
|
c->region->finalize( frame );
|
||||||
|
|
||||||
nframes_t capture_offset = 0;
|
nframes_t capture_offset = 0;
|
||||||
|
|
Loading…
Reference in New Issue