decouple flash from jack thread with ringbuffer
authorTorben Hohn <torbenh@gmx.de>
Mon, 30 Mar 2009 22:08:56 +0000 (31 00:08 +0200)
committerTorben Hohn <torbenh@gmx.de>
Mon, 30 Mar 2009 22:08:56 +0000 (31 00:08 +0200)
flashsupport.c

index 19fdc83..b6f84e7 100644 (file)
@@ -192,7 +192,9 @@ extern "C" {
 
 #ifdef JACK
 #include <jack/jack.h>
+#include <jack/ringbuffer.h>
 #include <samplerate.h>
+#include <semaphore.h>
 #endif
 
 static struct FPX_Functions fpx_functions;
@@ -1064,11 +1066,32 @@ struct jack_output_data {
        SRC_STATE *src_l;
        SRC_STATE *src_r;
        int src_error;
+       
+       jack_ringbuffer_t *buffer;
+       sem_t semaphore;
+       volatile int quit;
+       pthread_t tid;
 };
 
+static void *jack_flash_thread( void *arg )
+{
+       struct jack_output_data *p = arg;
+       int jack_rate = jack_get_sample_rate( p->client );
+       int flash_frames = jack_get_buffer_size( p->client ) * 44100 / jack_rate;
+       
+       size_t bufsize = 2*flash_frames * sizeof( int16_t );
+       int16_t *buffer = alloca( bufsize );
 
+       while( !p->quit ) {
+               sem_wait( &(p->semaphore) );
+               FPI_SoundOutput_FillBuffer(p, (char*) buffer, bufsize);
+               jack_ringbuffer_write( p->buffer, (char*)buffer, bufsize );
+       }
+       return NULL;
+}
 
-static int jack_process_cb( jack_nframes_t nframes, void *arg ) {
+static int jack_process_cb( jack_nframes_t nframes, void *arg ) 
+{
        struct jack_output_data *p = arg;
        int i;
        int jack_rate = jack_get_sample_rate( p->client );
@@ -1083,8 +1106,19 @@ static int jack_process_cb( jack_nframes_t nframes, void *arg ) {
 
        SRC_DATA sd;
 
+       if( jack_ringbuffer_read_space( p->buffer ) < bufsize ) {
+               // no data to read. fill ports with zero and return.
+               memset( port_l, 0, nframes * sizeof( jack_default_audio_sample_t ) );
+               memset( port_r, 0, nframes * sizeof( jack_default_audio_sample_t ) );
+               return 0;
+       }
 
-        FPI_SoundOutput_FillBuffer(p, (char*) buffer, bufsize);
+        //FPI_SoundOutput_FillBuffer(p, (char*) buffer, bufsize);
+       if( jack_ringbuffer_read( p->buffer, (char *)buffer, bufsize ) != bufsize ) {
+               printf( "Something is pretty wrong :( \n" );
+               return 0;
+       }
+       sem_post( &(p->semaphore) );
 
        for( i=0; i<flash_frames; i++ ) {
                float_buf[i] = (float) (buffer[2*i]) / 32768.0;
@@ -1122,6 +1156,9 @@ static void *FPX_SoundOutput_Open(void) {
 
     struct jack_output_data *p=NULL;
     char namebuf[100];
+    int jack_rate;
+    int flash_frames;
+    size_t bufsize;
 
     /* Unfortunately we cannot report any useful error string back to
      * Flash. It would be highly preferable if Flash supported some
@@ -1136,10 +1173,20 @@ static void *FPX_SoundOutput_Open(void) {
     p->src_l = src_new(SRC_SINC_FASTEST, 1, & (p->src_error));
     p->src_r = src_new(SRC_SINC_FASTEST, 1, & (p->src_error));
 
+
     /* First, let's create the main loop */
     if (!(p->client = jack_client_open( "flash", 0, NULL )))
         goto fail;
 
+    jack_rate = jack_get_sample_rate( p->client );
+    flash_frames = jack_get_buffer_size( p->client ) * 44100 / jack_rate;
+    bufsize = 2*flash_frames * sizeof( int16_t );
+
+    p->buffer = jack_ringbuffer_create( bufsize * 2 );
+    sem_init( &(p->semaphore), 0, 2 );
+
+    pthread_create( &(p->tid), NULL, jack_flash_thread, p );
+
     /* Second, initialize the connection context */
     if (!(p->port_l = jack_port_register( p->client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) )
         goto fail;
@@ -1167,6 +1214,10 @@ static int FPX_SoundOutput_Close(void *ptr) {
     struct jack_output_data *p = ptr;
 
     //assert(p);
+    if( p->tid ) {
+           p->quit = 1;
+           pthread_join( p->tid, NULL );
+    }
 
     if (p->client) {
            jack_deactivate( p->client );