[jack] initial jack support.
authorTorben Hohn <torbenh@gmx.de>
Sat, 14 Feb 2009 13:50:45 +0000 (14 14:50 +0100)
committerTorben Hohn <torbenh@gmx.de>
Sat, 14 Feb 2009 13:50:45 +0000 (14 14:50 +0100)
Makefile.am
configure.ac
flashsupport.c

dissimilarity index 61%
index 4850f08..d6351ae 100644 (file)
@@ -1,14 +1,12 @@
-
-EXTRA_DIST=bootstrap.sh
-
-AM_LDFLAGS=-avoid-version -module -export-dynamic
-
-lib_LTLIBRARIES = libflashsupport.la
-
-libflashsupport_la_SOURCES = flashsupport.c
-libflashsupport_la_LIBADD = $(AM_LIBADD) $(PULSE_LIBS) $(LIBSSL_LIBS)
-libflashsupport_la_CFLAGS = $(AM_CFLAGS) $(PULSE_CFLAGS) $(LIBSSL_CFLAGS)
-
-fedora-snapshot: dist
-       cp $(distdir).tar.gz $$HOME/cvs.fedora/pulseaudio/devel/$(distdir).svn`date +%Y%m%d`.tar.gz
-
+
+EXTRA_DIST=bootstrap.sh
+
+AM_LDFLAGS=-avoid-version -module -export-dynamic
+
+lib_LTLIBRARIES = libflashsupport.la
+
+libflashsupport_la_SOURCES = flashsupport.c
+libflashsupport_la_LIBADD = $(AM_LIBADD) $(JACK_LIBS) $(SRC_LIBS) $(LIBSSL_LIBS)
+libflashsupport_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) $(SRC_LIBS) $(LIBSSL_CFLAGS)
+
+
index c5e6cbd..9fd4dd6 100644 (file)
@@ -20,7 +20,7 @@
 
 AC_PREREQ(2.57)
 
-AC_INIT([libflashsupport-pulse], 000, [mzcbylcnhqvb (at) 0pointer (dot) de])
+AC_INIT([libflashsupport-jack], 000, [mzcbylcnhqvb (at) 0pointer (dot) de])
 AC_CONFIG_SRCDIR([flashsupport.c])
 AC_CONFIG_HEADERS([config.h])
 AM_INIT_AUTOMAKE([foreign -Wall])
@@ -45,7 +45,7 @@ if test "x$GCC" = "xyes" ; then
 
     # We use gnu99 instead of c99 because many have interpreted the standard
     # in a way that int64_t isn't defined on non-64 bit platforms.
-    DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math"
+    DESIRED_FLAGS="-pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math"
 
     for flag in $DESIRED_FLAGS ; do
         AC_MSG_CHECKING([whether $CC accepts $flag])
@@ -71,20 +71,16 @@ fi
 
 PKG_PROG_PKG_CONFIG
 
-if test x"$PULSEAUDIO_SOURCES" != x ; then
-   PULSE_CFLAGS="-I${PULSEAUDIO_SOURCES}/src"
-   PULSE_LIBS="-L${PULSEAUDIO_SOURCES}/src/.libs -lpulse"
-   echo "*** Using manually configured PA instance in ${PULSEAUDIO_SOURCES} ***"
-elif test -d ../pulseaudio ; then
-   PULSE_CFLAGS='-I$(top_srcdir)/../pulseaudio/src'
-   PULSE_LIBS='-L$(top_srcdir)/../pulseaudio/src/.libs -lpulse'
-   echo "*** Found pulseaudio in ../pulseaudio, using that version ***"
-else
-   PKG_CHECK_MODULES(PULSE, [ libpulse >= 0.9.5 ])
-fi
+PKG_CHECK_MODULES(JACK, [jack >= 0.100])
+
+AC_SUBST(JACK_LIBS)
+AC_SUBST(JACK_CFLAGS)
+
+PKG_CHECK_MODULES(SRC, [samplerate >= 0.1])
+
+AC_SUBST(SRC_LIBS)
+AC_SUBST(SRC_CFLAGS)
 
-AC_SUBST(PULSE_LIBS)
-AC_SUBST(PULSE_CFLAGS)
 
 PKG_CHECK_MODULES(LIBSSL, [ libssl ])
 
index afb1959..19fdc83 100644 (file)
@@ -54,7 +54,8 @@
 //#define ALSA
 //#define OSS
 #define V4L1
-#define PULSEAUDIO
+//#define PULSEAUDIO
+#define JACK
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 //
@@ -90,7 +91,7 @@ extern "C" {
     typedef void *(*T_FPI_Mem_Alloc)(int size);     // This function is not thread safe
     typedef void (*T_FPI_Mem_Free)(void *ptr); // This function is not thread safe
 
-#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO)
+#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO) || defined(JACK)
     typedef void (*T_FPI_SoundOutput_FillBuffer)(void *ptr, char *buffer, int n_bytes); // This function is thread safe
 #endif // defined(ALSA) || defined(OSS)
 
@@ -117,7 +118,7 @@ extern "C" {
     static int FPX_SSLSocket_Send(void *ptr, const char *buffer, int n_bytes);
 #endif // defined(OPENSSL) || defined(GNUTLS)
 
-#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO)
+#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO) || defined(JACK)
     static void *FPX_SoundOutput_Open(void);
     static int FPX_SoundOutput_Close(void *ptr);
     static int FPX_SoundOutput_Latency(void *ptr);
@@ -189,30 +190,35 @@ extern "C" {
 #include <pulse/pulseaudio.h>
 #endif
 
+#ifdef JACK
+#include <jack/jack.h>
+#include <samplerate.h>
+#endif
 
 static struct FPX_Functions fpx_functions;
 
 static T_FPI_Mem_Alloc FPI_Mem_Alloc = 0;
 static T_FPI_Mem_Free FPI_Mem_Free = 0;
 
-#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO)
+#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO) || defined(JACK)
 static T_FPI_SoundOutput_FillBuffer FPI_SoundOutput_FillBuffer = 0;
 #endif // defined(ALSA) || defined(OSS)
 
 void *FPX_Init(void *ptr)
 {
+    struct FPI_Functions *fpi_functions;
     if ( !ptr ) return 0;
 
     //
     // Setup imported functions
     //
 
-    struct FPI_Functions *fpi_functions = (struct FPI_Functions *)ptr;
+    fpi_functions = (struct FPI_Functions *)ptr;
 
     if ( fpi_functions->fpi_count >= 1 )    FPI_Mem_Alloc           = fpi_functions->fpi_mem_alloc;                                         // 1
     if ( fpi_functions->fpi_count >= 2 )    FPI_Mem_Free            = fpi_functions->fpi_mem_free;                                          // 2
 
-#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO)
+#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO) || defined(JACK)
     if ( fpi_functions->fpi_count >= 3 )    FPI_SoundOutput_FillBuffer= fpi_functions->fpi_soundoutput_fillbuffer;  // 3
 #endif // defined(ALSA) || defined(OSS)
 
@@ -232,7 +238,7 @@ void *FPX_Init(void *ptr)
     fpx_functions.fpx_sslsocket_send                        = FPX_SSLSocket_Send;                   // 6
 #endif // defined(OPENSSL) || defined(GNUTLS)
 
-#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO)
+#if defined(ALSA) || defined(OSS) || defined(PULSEAUDIO) || defined(JACK)
     fpx_functions.fpx_soundoutput_open                      = FPX_SoundOutput_Open;                 // 7
     fpx_functions.fpx_soundoutput_close             = FPX_SoundOutput_Close;                // 8
     fpx_functions.fpx_soundoutput_latency           = FPX_SoundOutput_Latency;              // 9
@@ -1049,6 +1055,134 @@ static int FPX_SoundOutput_Latency(void *ptr) {
 
 #endif
 
+#ifdef JACK
+
+struct jack_output_data {
+       jack_client_t *client;
+       jack_port_t *port_l;
+       jack_port_t *port_r;
+       SRC_STATE *src_l;
+       SRC_STATE *src_r;
+       int src_error;
+};
+
+
+
+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 );
+       int flash_frames = nframes * 44100 / jack_rate;
+       
+       size_t bufsize = 2*flash_frames * sizeof( int16_t );
+       int16_t *buffer = alloca( bufsize );
+       float   *float_buf = alloca( flash_frames * sizeof(float) );
+
+       float *port_l = jack_port_get_buffer( p->port_l, nframes );
+       float *port_r = jack_port_get_buffer( p->port_r, nframes );
+
+       SRC_DATA sd;
+
+
+        FPI_SoundOutput_FillBuffer(p, (char*) buffer, bufsize);
+
+       for( i=0; i<flash_frames; i++ ) {
+               float_buf[i] = (float) (buffer[2*i]) / 32768.0;
+       }
+
+       sd.data_in = float_buf;
+       sd.data_out = port_l;
+       sd.input_frames = flash_frames; 
+       sd.output_frames = nframes; 
+       sd.end_of_input = 0;
+//     sd.src_ratio = (double)flash_frames / (double)nframes;
+       sd.src_ratio = (double)nframes / (double)flash_frames;
+
+       src_process( p->src_l, &sd );
+
+
+       for( i=0; i<flash_frames; i++ ) {
+               float_buf[i] = (float) (buffer[2*i+1]) / 32768.0;
+       }
+
+       sd.data_in = float_buf;
+       sd.data_out = port_r;
+       sd.input_frames = flash_frames; 
+       sd.output_frames = nframes; 
+       sd.end_of_input = 0;
+//     sd.src_ratio = (double)flash_frames / (double)nframes;
+       sd.src_ratio = (double)nframes / (double)flash_frames;
+
+       src_process( p->src_r, &sd );
+
+       return 0;
+}
+
+static void *FPX_SoundOutput_Open(void) {
+
+    struct jack_output_data *p=NULL;
+    char namebuf[100];
+
+    /* Unfortunately we cannot report any useful error string back to
+     * Flash. It would be highly preferable if Flash supported some
+     * way how we could tell the user what the reason is why audio is
+     * not working for him. */
+
+    if (!(p = FPI_Mem_Alloc(sizeof(struct jack_output_data))))
+        goto fail;
+
+    memset(p, 0, sizeof(*p));
+
+    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;
+
+    /* Second, initialize the connection context */
+    if (!(p->port_l = jack_port_register( p->client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) )
+        goto fail;
+    if (!(p->port_r = jack_port_register( p->client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) )
+        goto fail;
+
+    jack_set_process_callback( p->client, jack_process_cb, p );
+    jack_activate( p->client );
+
+    snprintf( namebuf, 99, "%s:out1", jack_get_client_name( p->client ) );
+    jack_connect( p->client, namebuf, "system:playback_1" );
+    snprintf( namebuf, 99, "%s:out2", jack_get_client_name( p->client ) );
+    jack_connect( p->client, namebuf, "system:playback_2" );
+
+    return p;
+
+fail:
+    if (p)
+        FPX_SoundOutput_Close(p);
+
+    return NULL;
+}
+
+static int FPX_SoundOutput_Close(void *ptr) {
+    struct jack_output_data *p = ptr;
+
+    //assert(p);
+
+    if (p->client) {
+           jack_deactivate( p->client );
+           jack_client_close( p->client );
+    }
+
+    return 0;
+}
+
+static int FPX_SoundOutput_Latency(void *ptr) {
+       // heh ? jack has no latency :P
+    return 0;
+}
+#endif
+
+
 #ifdef V4L1
 struct VideoOutput_Instance {
     int                                             v4l_fd;
@@ -1083,6 +1217,7 @@ static void *v4l_thread(void *ptr)
             pthread_exit(0);
         }
     }
+    return NULL;
 }
 
 static void *FPX_VideoInput_Open(void)