@@ -146,10 +146,18 @@ Disk_Stream::shutdown ( void ) | |||||
_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 */ | ||||
int total_ms = 0; | |||||
while ( _terminate ) | while ( _terminate ) | ||||
{ | { | ||||
usleep( 100 ); | |||||
usleep( 1000 * 10 ); | |||||
total_ms += 10; | |||||
block_processed(); | block_processed(); | ||||
if ( total_ms > 100 ) | |||||
{ | |||||
WARNING("Disk_Stream thread has taken longer than %ims to respond to terminate signal.", total_ms ); | |||||
break; | |||||
} | |||||
} | } | ||||
_thread.join(); | _thread.join(); | ||||
@@ -82,25 +82,22 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes ) | |||||
// printf( "IO: attempting to read block @ %lu\n", _frame ); | // printf( "IO: attempting to read block @ %lu\n", _frame ); | ||||
if ( ! sequence() ) | |||||
{ | |||||
/* FIXME: what to do here? */ | |||||
// _frame += _nframes; | |||||
return; | |||||
} | |||||
timeline->rdlock(); | timeline->rdlock(); | ||||
/* FIXME: how does this work if _delay is not a multiple of bufsize? */ | |||||
if ( _frame >= _delay ) | |||||
if ( sequence() ) | |||||
{ | { | ||||
if ( ! sequence()->play( buf, _frame - _delay, nframes, channels() ) ) | |||||
WARNING( "Programming error?" ); | |||||
/* FIXME: how does this work if _delay is not a multiple of bufsize? */ | |||||
if ( _frame >= _delay ) | |||||
{ | |||||
if ( ! sequence()->play( buf, _frame - _delay, nframes, channels() ) ) | |||||
WARNING( "Programming error?" ); | |||||
} | |||||
_frame += nframes; | |||||
} | } | ||||
_frame += nframes; | |||||
timeline->unlock(); | timeline->unlock(); | ||||
} | } | ||||
@@ -58,13 +58,9 @@ Record_DS::write_block ( sample_t *buf, nframes_t nframes ) | |||||
if ( ! ( timeline && sequence() ) ) | if ( ! ( timeline && sequence() ) ) | ||||
return; | return; | ||||
// timeline->wrlock(); | |||||
track()->write( _capture, buf, nframes ); | track()->write( _capture, buf, nframes ); | ||||
_frames_written += nframes; | _frames_written += nframes; | ||||
// timeline->unlock(); | |||||
} | } | ||||
#define AVOID_UNNECESSARY_COPYING 1 | #define AVOID_UNNECESSARY_COPYING 1 | ||||
@@ -150,6 +150,10 @@ Timeline::stop ( void ) | |||||
nframes_t | nframes_t | ||||
Timeline::process ( nframes_t nframes ) | Timeline::process ( nframes_t nframes ) | ||||
{ | { | ||||
/* there is no need to acquire a readlock here because track * | |||||
addition/removal locks process() and track process() calls deal with | |||||
ringbuffers instead of reading the sequence data directly. */ | |||||
for ( int i = tracks->children(); i-- ; ) | for ( int i = tracks->children(); i-- ; ) | ||||
{ | { | ||||
Track *t = (Track*)tracks->child( i ); | Track *t = (Track*)tracks->child( i ); | ||||
@@ -272,8 +272,14 @@ Track::record ( Capture *c, nframes_t frame ) | |||||
/* open it again for reading in the GUI thread */ | /* open it again for reading in the GUI thread */ | ||||
// Audio_File *af = Audio_File::from_file( c->audio_file->name() ); | // Audio_File *af = Audio_File::from_file( c->audio_file->name() ); | ||||
/* must acquire a write lock because the Audio_Region constructor | |||||
* will add the region to the specified sequence */ | |||||
timeline->wrlock(); | |||||
c->region = new Audio_Region( c->audio_file, sequence(), frame ); | c->region = new Audio_Region( c->audio_file, sequence(), frame ); | ||||
timeline->unlock(); | |||||
c->region->prepare(); | c->region->prepare(); | ||||
} | } | ||||
@@ -298,6 +304,8 @@ Track::finalize ( Capture *c, nframes_t frame ) | |||||
/* adjust region start for latency */ | /* adjust region start for latency */ | ||||
/* FIXME: is just looking at the first channel good enough? */ | /* FIXME: is just looking at the first channel good enough? */ | ||||
timeline->wrlock(); | |||||
DMESSAGE( "finalizing audio file" ); | DMESSAGE( "finalizing audio file" ); | ||||
/* must finalize audio before peaks file, otherwise another thread | /* must finalize audio before peaks file, otherwise another thread | ||||
* might think the peaks are out of date and attempt to regenerate | * might think the peaks are out of date and attempt to regenerate | ||||
@@ -323,5 +331,7 @@ Track::finalize ( Capture *c, nframes_t frame ) | |||||
c->region->offset( capture_offset ); | c->region->offset( capture_offset ); | ||||
timeline->unlock(); | |||||
// delete c->audio_file; | // delete c->audio_file; | ||||
} | } |
@@ -154,8 +154,12 @@ Sequence::overlaps ( Sequence_Widget *r ) | |||||
void | void | ||||
Sequence::handle_widget_change ( nframes_t start, nframes_t length ) | Sequence::handle_widget_change ( nframes_t start, nframes_t length ) | ||||
{ | { | ||||
/* this might be invoked from Capture or GUI thread */ | |||||
Fl::lock(); | |||||
sort(); | sort(); | ||||
timeline->damage_sequence(); | timeline->damage_sequence(); | ||||
Fl::unlock(); | |||||
// timeline->update_length( start + length ); | // timeline->update_length( start + length ); | ||||
} | } | ||||
@@ -186,8 +190,11 @@ Sequence::add ( Sequence_Widget *r ) | |||||
if ( r->sequence() ) | if ( r->sequence() ) | ||||
{ | { | ||||
/* This method can be called from the Capture thread as well as the GUI thread, so we must lock FLTK before redraw */ | |||||
Fl::lock(); | |||||
r->redraw(); | r->redraw(); | ||||
r->sequence()->remove( r ); | r->sequence()->remove( r ); | ||||
Fl::unlock(); | |||||
// r->track()->redraw(); | // r->track()->redraw(); | ||||
} | } | ||||
@@ -204,6 +211,7 @@ Sequence::remove ( Sequence_Widget *r ) | |||||
_widgets.remove( r ); | _widgets.remove( r ); | ||||
handle_widget_change( r->start(), r->length() ); | handle_widget_change( r->start(), r->length() ); | ||||
} | } | ||||
static nframes_t | static nframes_t | ||||
@@ -943,6 +943,10 @@ else if ( 0 == p ) | |||||
progress_group->hide(); | progress_group->hide(); | ||||
} | } | ||||
// never allow drawing timeline while loading, as this would cause lock recursion. | |||||
if ( timeline->visible() ) | |||||
return; | |||||
static int oldp; | static int oldp; | ||||
static char pat[10]; | static char pat[10]; | ||||
@@ -1253,6 +1253,8 @@ Timeline::draw ( void ) | |||||
int bdx = 0; | int bdx = 0; | ||||
int bdw = 0; | int bdw = 0; | ||||
rdlock(); | |||||
X = tracks->x() + bdx + 1; | X = tracks->x() + bdx + 1; | ||||
Y = tracks->y(); | Y = tracks->y(); | ||||
W = tracks->w() - bdw - 1; | W = tracks->w() - bdw - 1; | ||||
@@ -1354,6 +1356,8 @@ done: | |||||
_old_xposition = xoffset; | _old_xposition = xoffset; | ||||
_old_yposition = panzoomer->y_value(); | _old_yposition = panzoomer->y_value(); | ||||
unlock(); | |||||
} | } | ||||
void | void | ||||
@@ -63,8 +63,8 @@ public: | |||||
void toggle_record ( void ); | void toggle_record ( void ); | ||||
int handle ( int m ); | int handle ( int m ); | ||||
bool rolling; | |||||
bool recording; | |||||
volatile bool rolling; | |||||
volatile bool recording; | |||||
void poll ( void ); | void poll ( void ); | ||||
void locate ( nframes_t frame ); | void locate ( nframes_t frame ); | ||||
@@ -280,8 +280,9 @@ main ( int argc, char **argv ) | |||||
if ( optind < argc ) | if ( optind < argc ) | ||||
{ | { | ||||
MESSAGE( "Loading \"%s\"", argv[optind] ); | MESSAGE( "Loading \"%s\"", argv[optind] ); | ||||
Fl::lock(); | |||||
tle->open( argv[optind] ); | tle->open( argv[optind] ); | ||||
Fl::unlock(); | |||||
} | } | ||||
} | } | ||||