Respond appropriately to changes in JACK buffer size.

pull/3/head
Jonathan Moore Liles 2008-05-19 23:30:08 -05:00
parent 97f0283780
commit 48d7f61f8a
12 changed files with 101 additions and 26 deletions

View File

@ -52,7 +52,6 @@ size_t Disk_Stream::disk_io_kbytes = 256;
Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track )
{
assert( channels );
_frame = 0;
@ -60,20 +59,9 @@ Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, in
_terminate = false;
_pending_seek = -1;
_xruns = 0;
_frame_rate = frame_rate;
_total_blocks = frame_rate * seconds_to_buffer / nframes;
_nframes = nframes;
size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
if ( disk_io_kbytes )
_disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 );
else
_disk_io_blocks = 1;
for ( int i = channels; i--; )
_rb.push_back( jack_ringbuffer_create( bufsize ) );
_resize_buffers( nframes, channels );
sem_init( &_blocks, 0, _total_blocks );
}
@ -97,14 +85,13 @@ Disk_Stream::~Disk_Stream ( )
/* THREAD: RT */
/** flush buffers and reset. Must only be called from the RT thread. */
void
Disk_Stream::flush ( bool is_output )
Disk_Stream::base_flush ( bool is_output )
{
/* flush buffers */
for ( int i = channels(); i--; )
for ( int i = _rb.size(); i--; )
jack_ringbuffer_read_advance( _rb[ i ], jack_ringbuffer_read_space( _rb[ i ] ) );
/* sem_destroy( &_blocks ); */
/* if ( is_output ) */
@ -114,7 +101,6 @@ Disk_Stream::flush ( bool is_output )
if ( is_output )
{
int n;
sem_getvalue( &_blocks, &n );
@ -145,6 +131,7 @@ Disk_Stream::shutdown ( void )
if ( _thread )
pthread_join( _thread, NULL );
_thread = 0;
_terminate = false;
}
@ -168,12 +155,50 @@ Disk_Stream::run ( void )
FATAL( "Could not create IO thread!" );
}
void
Disk_Stream::_resize_buffers ( nframes_t nframes, int channels )
{
for ( int i = _rb.size(); i--; )
jack_ringbuffer_free( _rb[ i ] );
_rb.clear();
_nframes = nframes;
_total_blocks = _frame_rate * seconds_to_buffer / nframes;
size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
if ( disk_io_kbytes )
_disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 );
else
_disk_io_blocks = 1;
for ( int i = channels; i--; )
_rb.push_back( jack_ringbuffer_create( bufsize ) );
}
/* THREAD: RT (non-RT) */
/* to be called when the JACK buffer size changes. */
void
Disk_Stream::resize ( nframes_t nframes )
Disk_Stream::resize_buffers ( nframes_t nframes )
{
if ( nframes != _nframes )
/* FIXME: to something here! */;
{
DMESSAGE( "resizing buffers" );
const bool was_running = _thread;
if ( was_running )
shutdown();
flush();
_resize_buffers( nframes, channels() );
if ( was_running )
run();
}
}

View File

@ -59,6 +59,9 @@ protected:
int _total_blocks; /* total number of blocks that we can buffer */
int _disk_io_blocks; /* the number of blocks to read/write to/from disk at once */
nframes_t _frame_rate; /* used for buffer size calculations */
volatile nframes_t _pending_seek; /* absolute transport position to seek to */
volatile int _terminate;
@ -71,6 +74,8 @@ protected:
static void *disk_thread ( void *arg );
void _resize_buffers ( nframes_t nframes, int channels );
protected:
void block_processed ( void ) { sem_post( &_blocks ); }
@ -86,7 +91,8 @@ protected:
virtual void disk_thread ( void ) = 0;
void flush ( bool is_output );
void base_flush ( bool is_output );
virtual void flush ( void ) = 0;
public:
@ -100,7 +106,7 @@ public:
virtual ~Disk_Stream ( );
void resize ( nframes_t nframes );
void resize_buffers ( nframes_t nframes );
/* void seek ( nframes_t frame ); */
/* bool seek_pending ( void ); */

View File

@ -70,6 +70,12 @@ Engine::freewheel ( int starting, void *arg )
((Engine*)arg)->freewheel( starting );
}
int
Engine::buffer_size ( nframes_t nframes, void *arg )
{
return ((Engine*)arg)->buffer_size( nframes );
}
void
@ -101,6 +107,16 @@ Engine::freewheel ( bool starting )
DMESSAGE( "leaving freewheeling mode" );
}
/* THREAD: RT (non-RT) */
int
Engine::buffer_size ( nframes_t nframes )
{
/* TODO: inform all disktreams the the buffer size has changed */
timeline->resize_buffers( nframes );
return 0;
}
/* THREAD: RT */
/** This is the jack slow-sync callback. */
int
@ -232,6 +248,7 @@ Engine::init ( void )
set_callback( process );
set_callback( xrun );
set_callback( freewheel );
set_callback( buffer_size );
/* FIXME: should we wait to register this until after the project
has been loaded (and we have disk threads running)? */

View File

@ -55,6 +55,8 @@ class Engine : public Mutex
void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos );
static void freewheel ( int yes, void *arg );
void freewheel ( bool yes );
static int buffer_size ( nframes_t nframes, void *arg );
int buffer_size ( nframes_t nframes );
Engine ( const Engine &rhs );
Engine & operator = ( const Engine &rhs );

View File

@ -54,7 +54,7 @@ Playback_DS::seek ( nframes_t frame )
_pending_seek = frame;
flush( true );
flush();
}
/* THREAD: IO */
@ -93,7 +93,6 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes )
void
Playback_DS::disk_thread ( void )
{
DMESSAGE( "playback thread running" );
/* buffer to hold the interleaved data returned by the track reader */

View File

@ -25,6 +25,8 @@ class Playback_DS : public Disk_Stream
void read_block ( sample_t *buf, nframes_t nframes );
void disk_thread ( void );
void flush ( void ) { base_flush( true ); }
public:
Playback_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) :

View File

@ -199,7 +199,7 @@ Record_DS::start ( nframes_t frame )
}
/* FIXME: safe to do this here? */
flush( false );
flush();
_frame = frame;

View File

@ -43,6 +43,8 @@ class Record_DS : public Disk_Stream
void write_block ( sample_t *buf, nframes_t nframes );
void disk_thread ( void );
void flush ( void ) { base_flush( false ); }
public:
Record_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) :

View File

@ -1233,6 +1233,18 @@ Timeline::seek ( nframes_t frame )
}
}
/* THREAD: RT (non-RT) */
void
Timeline::resize_buffers ( nframes_t nframes )
{
for ( int i = tracks->children(); i-- ; )
{
Track *t = (Track*)tracks->child( i );
t->resize_buffers( nframes );
}
}
/* THREAD: RT */
int
Timeline::seek_pending ( void )

View File

@ -210,6 +210,7 @@ private:
char * get_unique_track_name ( const char *name );
/* Engine */
void resize_buffers ( nframes_t nframes );
nframes_t process ( nframes_t nframes );
void seek ( nframes_t frame );
int seek_pending ( void );

View File

@ -745,7 +745,15 @@ Track::seek ( nframes_t frame )
return playback_ds->seek( frame );
}
/* THREAD: RT (non-RT) */
void
Track::resize_buffers ( nframes_t nframes )
{
if ( record_ds )
record_ds->resize_buffers( nframes );
if ( playback_ds )
playback_ds->resize_buffers( nframes );
}
/* FIXME: what about theading issues with this region/audiofile being
accessible from the UI thread? Need locking? */

View File

@ -265,6 +265,7 @@ public:
const Audio_Region *capture ( void ) const { return _capture; }
/* Engine */
void resize_buffers ( nframes_t nframes );
nframes_t process ( nframes_t nframes );
void seek ( nframes_t frame );
void record ( nframes_t nframes );