From ffa6e96f8b07ad019fef74784081291de9180d07 Mon Sep 17 00:00:00 2001 From: Torben Hohn Date: Sat, 14 Feb 2009 14:50:45 +0100 Subject: [PATCH] [jack] initial jack support. --- Makefile.am | 26 +++++----- configure.ac | 26 +++++----- flashsupport.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 165 insertions(+), 36 deletions(-) rewrite Makefile.am (61%) diff --git a/Makefile.am b/Makefile.am dissimilarity index 61% index 4850f08..d6351ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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) + + diff --git a/configure.ac b/configure.ac index c5e6cbd..9fd4dd6 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ]) diff --git a/flashsupport.c b/flashsupport.c index afb1959..19fdc83 100644 --- a/flashsupport.c +++ b/flashsupport.c @@ -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 #endif +#ifdef JACK +#include +#include +#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; isrc_l, &sd ); + + + for( i=0; isrc_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) -- 2.11.4.GIT