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