Browse Source

Timeline: Fix thread synchronization issues during recording.

tags/non-daw-v1.2.0
Jonathan Moore Liles 13 years ago
parent
commit
1f9c2bbb6a
9 changed files with 66 additions and 17 deletions
  1. +18
    -0
      nonlib/Loggable.C
  2. +7
    -0
      nonlib/Thread.C
  3. +1
    -0
      nonlib/Thread.H
  4. +5
    -7
      timeline/src/Engine/Audio_Region.C
  5. +16
    -5
      timeline/src/Engine/Disk_Stream.C
  6. +2
    -1
      timeline/src/Engine/Disk_Stream.H
  7. +6
    -3
      timeline/src/Engine/Record_DS.C
  8. +11
    -0
      timeline/src/Engine/Timeline.C
  9. +0
    -1
      timeline/src/Engine/Track.C

+ 18
- 0
nonlib/Loggable.C View File

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




+ 7
- 0
nonlib/Thread.C View File

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

+ 1
- 0
nonlib/Thread.H View File

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


}; };

+ 5
- 7
timeline/src/Engine/Audio_Region.C View File

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

+ 16
- 5
timeline/src/Engine/Disk_Stream.C View File

@@ -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 *


+ 2
- 1
timeline/src/Engine/Disk_Stream.H View File

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


+ 6
- 3
timeline/src/Engine/Record_DS.C View File

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


+ 11
- 0
timeline/src/Engine/Timeline.C View File

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


+ 0
- 1
timeline/src/Engine/Track.C View File

@@ -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…
Cancel
Save