@@ -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(); | |||||
redraw(); | |||||
Fl::awake(); | |||||
Fl::unlock(); | |||||
log_end(); | |||||
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 ) | ||||
{ | { | ||||
_terminate = true; | |||||
/* try to wake the thread so it'll see that it's time to die */ | |||||
block_processed(); | |||||
if ( _thread.running() ) | 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(); | |||||
} | |||||
_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; | ||||