mirror of
				https://github.com/encounter/SDL.git
				synced 2025-10-25 19:20:25 +00:00 
			
		
		
		
	jack: Initial shot at a JACK audio target.
http://jackaudio.org/ Fixes Bugzilla #2163. (with several more commits following to improve this code.)
This commit is contained in:
		
							parent
							
								
									cb591ee611
								
							
						
					
					
						commit
						d9039f2396
					
				| @ -279,6 +279,8 @@ set_option(SDL_DLOPEN          "Use dlopen for shared object loading" ${SDL_DLOP | |||||||
| set_option(OSS                 "Support the OSS audio API" ${UNIX_SYS}) | set_option(OSS                 "Support the OSS audio API" ${UNIX_SYS}) | ||||||
| set_option(ALSA                "Support the ALSA audio API" ${UNIX_SYS}) | set_option(ALSA                "Support the ALSA audio API" ${UNIX_SYS}) | ||||||
| dep_option(ALSA_SHARED         "Dynamically load ALSA audio support" ON "ALSA" OFF) | dep_option(ALSA_SHARED         "Dynamically load ALSA audio support" ON "ALSA" OFF) | ||||||
|  | set_option(JACK                "Support the JACK audio API" ${UNIX_SYS}) | ||||||
|  | dep_option(JACK_SHARED         "Dynamically load JACK audio support" ON "JACK" OFF) | ||||||
| set_option(ESD                 "Support the Enlightened Sound Daemon" ${UNIX_SYS}) | set_option(ESD                 "Support the Enlightened Sound Daemon" ${UNIX_SYS}) | ||||||
| dep_option(ESD_SHARED          "Dynamically load ESD audio support" ON "ESD" OFF) | dep_option(ESD_SHARED          "Dynamically load ESD audio support" ON "ESD" OFF) | ||||||
| set_option(PULSEAUDIO          "Use PulseAudio" ${UNIX_SYS}) | set_option(PULSEAUDIO          "Use PulseAudio" ${UNIX_SYS}) | ||||||
| @ -895,6 +897,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID) | |||||||
|     endif() |     endif() | ||||||
|     CheckOSS() |     CheckOSS() | ||||||
|     CheckALSA() |     CheckALSA() | ||||||
|  |     CheckJACK() | ||||||
|     CheckPulseAudio() |     CheckPulseAudio() | ||||||
|     CheckESD() |     CheckESD() | ||||||
|     CheckARTS() |     CheckARTS() | ||||||
|  | |||||||
| @ -158,6 +158,36 @@ macro(CheckPulseAudio) | |||||||
|   endif() |   endif() | ||||||
| endmacro() | endmacro() | ||||||
| 
 | 
 | ||||||
|  | # Requires: | ||||||
|  | # - PkgCheckModules | ||||||
|  | # Optional: | ||||||
|  | # - JACK_SHARED opt | ||||||
|  | # - HAVE_DLOPEN opt | ||||||
|  | macro(CheckJACK) | ||||||
|  |   if(JACK) | ||||||
|  |     pkg_check_modules(PKG_JACK jack) | ||||||
|  |     if(PKG_JACK_FOUND) | ||||||
|  |       set(HAVE_JACK TRUE) | ||||||
|  |       file(GLOB JACK_SOURCES ${SDL2_SOURCE_DIR}/src/audio/jack/*.c) | ||||||
|  |       set(SOURCE_FILES ${SOURCE_FILES} ${JACK_SOURCES}) | ||||||
|  |       set(SDL_AUDIO_DRIVER_JACK 1) | ||||||
|  |       list(APPEND EXTRA_CFLAGS ${PKG_JACK_CFLAGS}) | ||||||
|  |       if(JACK_SHARED) | ||||||
|  |         if(NOT HAVE_DLOPEN) | ||||||
|  |           message_warn("You must have SDL_LoadObject() support for dynamic JACK audio loading") | ||||||
|  |         else() | ||||||
|  |           FindLibraryAndSONAME("jack") | ||||||
|  |           set(SDL_AUDIO_DRIVER_JACK_DYNAMIC "\"${JACK_LIB_SONAME}\"") | ||||||
|  |           set(HAVE_JACK_SHARED TRUE) | ||||||
|  |         endif() | ||||||
|  |       else() | ||||||
|  |         list(APPEND EXTRA_LDFLAGS ${PKG_JACK_LDFLAGS}) | ||||||
|  |       endif() | ||||||
|  |       set(HAVE_SDL_AUDIO TRUE) | ||||||
|  |     endif() | ||||||
|  |   endif() | ||||||
|  | endmacro() | ||||||
|  | 
 | ||||||
| # Requires: | # Requires: | ||||||
| # - PkgCheckModules | # - PkgCheckModules | ||||||
| # Optional: | # Optional: | ||||||
|  | |||||||
							
								
								
									
										120
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										120
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @ -658,10 +658,10 @@ X_PRE_LIBS | |||||||
| X_CFLAGS | X_CFLAGS | ||||||
| XMKMF | XMKMF | ||||||
| ARTSCONFIG | ARTSCONFIG | ||||||
| PKG_CONFIG |  | ||||||
| ESD_LIBS | ESD_LIBS | ||||||
| ESD_CFLAGS | ESD_CFLAGS | ||||||
| ESD_CONFIG | ESD_CONFIG | ||||||
|  | PKG_CONFIG | ||||||
| ALSA_LIBS | ALSA_LIBS | ||||||
| ALSA_CFLAGS | ALSA_CFLAGS | ||||||
| POW_LIB | POW_LIB | ||||||
| @ -806,6 +806,8 @@ with_alsa_prefix | |||||||
| with_alsa_inc_prefix | with_alsa_inc_prefix | ||||||
| enable_alsatest | enable_alsatest | ||||||
| enable_alsa_shared | enable_alsa_shared | ||||||
|  | enable_jack | ||||||
|  | enable_jack_shared | ||||||
| enable_esd | enable_esd | ||||||
| with_esd_prefix | with_esd_prefix | ||||||
| with_esd_exec_prefix | with_esd_exec_prefix | ||||||
| @ -1535,6 +1537,8 @@ Optional Features: | |||||||
|   --enable-alsa           support the ALSA audio API [[default=yes]] |   --enable-alsa           support the ALSA audio API [[default=yes]] | ||||||
|   --disable-alsatest      Do not try to compile and run a test Alsa program |   --disable-alsatest      Do not try to compile and run a test Alsa program | ||||||
|   --enable-alsa-shared    dynamically load ALSA audio support [[default=yes]] |   --enable-alsa-shared    dynamically load ALSA audio support [[default=yes]] | ||||||
|  |   --enable-jack           use JACK audio [[default=yes]] | ||||||
|  |   --enable-jack-shared    dynamically load JACK audio support [[default=yes]] | ||||||
|   --enable-esd            support the Enlightened Sound Daemon [[default=yes]] |   --enable-esd            support the Enlightened Sound Daemon [[default=yes]] | ||||||
|   --disable-esdtest       Do not try to compile and run a test ESD program |   --disable-esdtest       Do not try to compile and run a test ESD program | ||||||
|   --enable-esd-shared     dynamically load ESD audio support [[default=yes]] |   --enable-esd-shared     dynamically load ESD audio support [[default=yes]] | ||||||
| @ -17870,6 +17874,119 @@ _ACEOF | |||||||
|     fi |     fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | CheckJACK() | ||||||
|  | { | ||||||
|  |     # Check whether --enable-jack was given. | ||||||
|  | if test "${enable_jack+set}" = set; then : | ||||||
|  |   enableval=$enable_jack; | ||||||
|  | else | ||||||
|  |   enable_jack=yes | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  |     if test x$enable_audio = xyes -a x$enable_jack = xyes; then | ||||||
|  |         audio_jack=no | ||||||
|  | 
 | ||||||
|  |         JACK_REQUIRED_VERSION=0.125 | ||||||
|  | 
 | ||||||
|  |         # Extract the first word of "pkg-config", so it can be a program name with args. | ||||||
|  | set dummy pkg-config; ac_word=$2 | ||||||
|  | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 | ||||||
|  | $as_echo_n "checking for $ac_word... " >&6; } | ||||||
|  | if ${ac_cv_path_PKG_CONFIG+:} false; then : | ||||||
|  |   $as_echo_n "(cached) " >&6 | ||||||
|  | else | ||||||
|  |   case $PKG_CONFIG in | ||||||
|  |   [\\/]* | ?:[\\/]*) | ||||||
|  |   ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. | ||||||
|  |   ;; | ||||||
|  |   *) | ||||||
|  |   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | ||||||
|  | for as_dir in $PATH | ||||||
|  | do | ||||||
|  |   IFS=$as_save_IFS | ||||||
|  |   test -z "$as_dir" && as_dir=. | ||||||
|  |     for ac_exec_ext in '' $ac_executable_extensions; do | ||||||
|  |   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then | ||||||
|  |     ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" | ||||||
|  |     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 | ||||||
|  |     break 2 | ||||||
|  |   fi | ||||||
|  | done | ||||||
|  |   done | ||||||
|  | IFS=$as_save_IFS | ||||||
|  | 
 | ||||||
|  |   test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" | ||||||
|  |   ;; | ||||||
|  | esac | ||||||
|  | fi | ||||||
|  | PKG_CONFIG=$ac_cv_path_PKG_CONFIG | ||||||
|  | if test -n "$PKG_CONFIG"; then | ||||||
|  |   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 | ||||||
|  | $as_echo "$PKG_CONFIG" >&6; } | ||||||
|  | else | ||||||
|  |   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | ||||||
|  | $as_echo "no" >&6; } | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JACK $JACK_REQUIRED_VERSION support" >&5 | ||||||
|  | $as_echo_n "checking for JACK $JACK_REQUIRED_VERSION support... " >&6; } | ||||||
|  |         if test x$PKG_CONFIG != xno; then | ||||||
|  |         if $PKG_CONFIG --atleast-pkgconfig-version 0.7 && $PKG_CONFIG --atleast-version $JACK_REQUIRED_VERSION jack; then | ||||||
|  |                 JACK_CFLAGS=`$PKG_CONFIG --cflags jack` | ||||||
|  |                 JACK_LIBS=`$PKG_CONFIG --libs jack` | ||||||
|  |                 audio_jack=yes | ||||||
|  |             fi | ||||||
|  |         fi | ||||||
|  |         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $audio_jack" >&5 | ||||||
|  | $as_echo "$audio_jack" >&6; } | ||||||
|  | 
 | ||||||
|  |         if test x$audio_jack = xyes; then | ||||||
|  |             # Check whether --enable-jack-shared was given. | ||||||
|  | if test "${enable_jack_shared+set}" = set; then : | ||||||
|  |   enableval=$enable_jack_shared; | ||||||
|  | else | ||||||
|  |   enable_jack_shared=yes | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  |             jack_lib=`find_lib "libjack.so.*" "$JACK_LIBS" | sed 's/.*\/\(.*\)/\1/; q'` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | $as_echo "#define SDL_AUDIO_DRIVER_JACK 1" >>confdefs.h | ||||||
|  | 
 | ||||||
|  |             SOURCES="$SOURCES $srcdir/src/audio/jack/*.c" | ||||||
|  |             EXTRA_CFLAGS="$EXTRA_CFLAGS $JACK_CFLAGS" | ||||||
|  |             if test x$have_loadso != xyes && \ | ||||||
|  |                test x$enable_jack_shared = xyes; then | ||||||
|  |                 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You must have SDL_LoadObject() support for dynamic JACK audio loading" >&5 | ||||||
|  | $as_echo "$as_me: WARNING: You must have SDL_LoadObject() support for dynamic JACK audio loading" >&2;} | ||||||
|  |             fi | ||||||
|  |             if test x$have_loadso = xyes && \ | ||||||
|  |                test x$enable_jack_shared = xyes && test x$jack_lib != x; then | ||||||
|  |                 echo "-- dynamic libjack -> $jack_lib" | ||||||
|  | 
 | ||||||
|  | cat >>confdefs.h <<_ACEOF | ||||||
|  | #define SDL_AUDIO_DRIVER_JACK_DYNAMIC "$jack_lib" | ||||||
|  | _ACEOF | ||||||
|  | 
 | ||||||
|  |                 SUMMARY_audio="${SUMMARY_audio} jack(dynamic)" | ||||||
|  | 
 | ||||||
|  |                 case "$host" in | ||||||
|  |                     # On Solaris, jack must be linked deferred explicitly | ||||||
|  |                     # to prevent undefined symbol failures. | ||||||
|  |                     *-*-solaris*) | ||||||
|  |                         JACK_LIBS=`echo $JACK_LIBS | sed 's/\-l/-Wl,-l/g'` | ||||||
|  |                         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-zdeferred $JACK_LIBS -Wl,-znodeferred" | ||||||
|  |                 esac | ||||||
|  |             else | ||||||
|  |                 EXTRA_LDFLAGS="$EXTRA_LDFLAGS $JACK_LIBS" | ||||||
|  |                 SUMMARY_audio="${SUMMARY_audio} jack" | ||||||
|  |             fi | ||||||
|  |             have_audio=yes | ||||||
|  |         fi | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
| CheckESD() | CheckESD() | ||||||
| { | { | ||||||
|     # Check whether --enable-esd was given. |     # Check whether --enable-esd was given. | ||||||
| @ -23264,6 +23381,7 @@ case "$host" in | |||||||
|         CheckOSS |         CheckOSS | ||||||
|         CheckALSA |         CheckALSA | ||||||
|         CheckPulseAudio |         CheckPulseAudio | ||||||
|  |         CheckJACK | ||||||
|         CheckARTSC |         CheckARTSC | ||||||
|         CheckESD |         CheckESD | ||||||
|         CheckNAS |         CheckNAS | ||||||
|  | |||||||
							
								
								
									
										58
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								configure.in
									
									
									
									
									
								
							| @ -839,6 +839,63 @@ AC_HELP_STRING([--enable-alsa-shared], [dynamically load ALSA audio support [[de | |||||||
|     fi |     fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | dnl Find JACK Audio | ||||||
|  | CheckJACK() | ||||||
|  | { | ||||||
|  |     AC_ARG_ENABLE(jack, | ||||||
|  | AC_HELP_STRING([--enable-jack], [use JACK audio [[default=yes]]]), | ||||||
|  |                   , enable_jack=yes) | ||||||
|  |     if test x$enable_audio = xyes -a x$enable_jack = xyes; then | ||||||
|  |         audio_jack=no | ||||||
|  | 
 | ||||||
|  |         JACK_REQUIRED_VERSION=0.125 | ||||||
|  | 
 | ||||||
|  |         AC_PATH_PROG(PKG_CONFIG, pkg-config, no) | ||||||
|  |         AC_MSG_CHECKING(for JACK $JACK_REQUIRED_VERSION support) | ||||||
|  |         if test x$PKG_CONFIG != xno; then | ||||||
|  |         if $PKG_CONFIG --atleast-pkgconfig-version 0.7 && $PKG_CONFIG --atleast-version $JACK_REQUIRED_VERSION jack; then | ||||||
|  |                 JACK_CFLAGS=`$PKG_CONFIG --cflags jack` | ||||||
|  |                 JACK_LIBS=`$PKG_CONFIG --libs jack` | ||||||
|  |                 audio_jack=yes | ||||||
|  |             fi | ||||||
|  |         fi | ||||||
|  |         AC_MSG_RESULT($audio_jack) | ||||||
|  | 
 | ||||||
|  |         if test x$audio_jack = xyes; then | ||||||
|  |             AC_ARG_ENABLE(jack-shared, | ||||||
|  | AC_HELP_STRING([--enable-jack-shared], [dynamically load JACK audio support [[default=yes]]]), | ||||||
|  |                           , enable_jack_shared=yes) | ||||||
|  |             jack_lib=[`find_lib "libjack.so.*" "$JACK_LIBS" | sed 's/.*\/\(.*\)/\1/; q'`] | ||||||
|  | 
 | ||||||
|  |             AC_DEFINE(SDL_AUDIO_DRIVER_JACK, 1, [ ]) | ||||||
|  |             SOURCES="$SOURCES $srcdir/src/audio/jack/*.c" | ||||||
|  |             EXTRA_CFLAGS="$EXTRA_CFLAGS $JACK_CFLAGS" | ||||||
|  |             if test x$have_loadso != xyes && \ | ||||||
|  |                test x$enable_jack_shared = xyes; then | ||||||
|  |                 AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic JACK audio loading]) | ||||||
|  |             fi | ||||||
|  |             if test x$have_loadso = xyes && \ | ||||||
|  |                test x$enable_jack_shared = xyes && test x$jack_lib != x; then | ||||||
|  |                 echo "-- dynamic libjack -> $jack_lib" | ||||||
|  |                 AC_DEFINE_UNQUOTED(SDL_AUDIO_DRIVER_JACK_DYNAMIC, "$jack_lib", [ ]) | ||||||
|  |                 SUMMARY_audio="${SUMMARY_audio} jack(dynamic)" | ||||||
|  | 
 | ||||||
|  |                 case "$host" in | ||||||
|  |                     # On Solaris, jack must be linked deferred explicitly | ||||||
|  |                     # to prevent undefined symbol failures. | ||||||
|  |                     *-*-solaris*) | ||||||
|  |                         JACK_LIBS=`echo $JACK_LIBS | sed 's/\-l/-Wl,-l/g'` | ||||||
|  |                         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-zdeferred $JACK_LIBS -Wl,-znodeferred" | ||||||
|  |                 esac | ||||||
|  |             else | ||||||
|  |                 EXTRA_LDFLAGS="$EXTRA_LDFLAGS $JACK_LIBS" | ||||||
|  |                 SUMMARY_audio="${SUMMARY_audio} jack" | ||||||
|  |             fi | ||||||
|  |             have_audio=yes | ||||||
|  |         fi | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
| dnl Find the ESD includes and libraries | dnl Find the ESD includes and libraries | ||||||
| CheckESD() | CheckESD() | ||||||
| { | { | ||||||
| @ -3035,6 +3092,7 @@ case "$host" in | |||||||
|         CheckOSS |         CheckOSS | ||||||
|         CheckALSA |         CheckALSA | ||||||
|         CheckPulseAudio |         CheckPulseAudio | ||||||
|  |         CheckJACK | ||||||
|         CheckARTSC |         CheckARTSC | ||||||
|         CheckESD |         CheckESD | ||||||
|         CheckNAS |         CheckNAS | ||||||
|  | |||||||
| @ -205,6 +205,8 @@ | |||||||
| #cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@ | #cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@ | ||||||
| #cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@ | #cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@ | ||||||
| #cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@ | #cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@ | ||||||
|  | #cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@ | ||||||
|  | #cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@ | ||||||
| #cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@ | #cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@ | ||||||
| #cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@ | #cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@ | ||||||
| #cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@ | #cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@ | ||||||
|  | |||||||
| @ -204,6 +204,8 @@ | |||||||
| /* Enable various audio drivers */ | /* Enable various audio drivers */ | ||||||
| #undef SDL_AUDIO_DRIVER_ALSA | #undef SDL_AUDIO_DRIVER_ALSA | ||||||
| #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC | #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC | ||||||
|  | #undef SDL_AUDIO_DRIVER_JACK | ||||||
|  | #undef SDL_AUDIO_DRIVER_JACK_DYNAMIC | ||||||
| #undef SDL_AUDIO_DRIVER_ARTS | #undef SDL_AUDIO_DRIVER_ARTS | ||||||
| #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC | #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC | ||||||
| #undef SDL_AUDIO_DRIVER_PULSEAUDIO | #undef SDL_AUDIO_DRIVER_PULSEAUDIO | ||||||
|  | |||||||
| @ -101,6 +101,9 @@ static const AudioBootStrap *const bootstrap[] = { | |||||||
| #if SDL_AUDIO_DRIVER_EMSCRIPTEN | #if SDL_AUDIO_DRIVER_EMSCRIPTEN | ||||||
|     &EMSCRIPTENAUDIO_bootstrap, |     &EMSCRIPTENAUDIO_bootstrap, | ||||||
| #endif | #endif | ||||||
|  | #if SDL_AUDIO_DRIVER_JACK | ||||||
|  |     &JACK_bootstrap, | ||||||
|  | #endif | ||||||
| #if SDL_AUDIO_DRIVER_DISK | #if SDL_AUDIO_DRIVER_DISK | ||||||
|     &DISKAUDIO_bootstrap, |     &DISKAUDIO_bootstrap, | ||||||
| #endif | #endif | ||||||
| @ -723,6 +726,7 @@ SDL_RunAudio(void *devicep) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* !!! FIXME: this needs to deal with device spec changes. */ | ||||||
| /* The general capture thread function */ | /* The general capture thread function */ | ||||||
| static int SDLCALL | static int SDLCALL | ||||||
| SDL_CaptureAudio(void *devicep) | SDL_CaptureAudio(void *devicep) | ||||||
|  | |||||||
| @ -182,6 +182,7 @@ typedef struct AudioBootStrap | |||||||
| /* Not all of these are available in a given build. Use #ifdefs, etc. */ | /* Not all of these are available in a given build. Use #ifdefs, etc. */ | ||||||
| extern AudioBootStrap PULSEAUDIO_bootstrap; | extern AudioBootStrap PULSEAUDIO_bootstrap; | ||||||
| extern AudioBootStrap ALSA_bootstrap; | extern AudioBootStrap ALSA_bootstrap; | ||||||
|  | extern AudioBootStrap JACK_bootstrap; | ||||||
| extern AudioBootStrap SNDIO_bootstrap; | extern AudioBootStrap SNDIO_bootstrap; | ||||||
| extern AudioBootStrap NETBSDAUDIO_bootstrap; | extern AudioBootStrap NETBSDAUDIO_bootstrap; | ||||||
| extern AudioBootStrap DSP_bootstrap; | extern AudioBootStrap DSP_bootstrap; | ||||||
|  | |||||||
							
								
								
									
										503
									
								
								src/audio/jack/SDL_jackaudio.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										503
									
								
								src/audio/jack/SDL_jackaudio.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,503 @@ | |||||||
|  | /*
 | ||||||
|  |   Simple DirectMedia Layer | ||||||
|  |   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> | ||||||
|  | 
 | ||||||
|  |   This software is provided 'as-is', without any express or implied | ||||||
|  |   warranty.  In no event will the authors be held liable for any damages | ||||||
|  |   arising from the use of this software. | ||||||
|  | 
 | ||||||
|  |   Permission is granted to anyone to use this software for any purpose, | ||||||
|  |   including commercial applications, and to alter it and redistribute it | ||||||
|  |   freely, subject to the following restrictions: | ||||||
|  | 
 | ||||||
|  |   1. The origin of this software must not be misrepresented; you must not | ||||||
|  |      claim that you wrote the original software. If you use this software | ||||||
|  |      in a product, an acknowledgment in the product documentation would be | ||||||
|  |      appreciated but is not required. | ||||||
|  |   2. Altered source versions must be plainly marked as such, and must not be | ||||||
|  |      misrepresented as being the original software. | ||||||
|  |   3. This notice may not be removed or altered from any source distribution. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "../../SDL_internal.h" | ||||||
|  | 
 | ||||||
|  | #if SDL_AUDIO_DRIVER_JACK | ||||||
|  | 
 | ||||||
|  | #include "SDL_assert.h" | ||||||
|  | #include "SDL_timer.h" | ||||||
|  | #include "SDL_audio.h" | ||||||
|  | #include "../SDL_audio_c.h" | ||||||
|  | #include "SDL_jackaudio.h" | ||||||
|  | #include "SDL_loadso.h" | ||||||
|  | #include "../../thread/SDL_systhread.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* !!! FIXME: my understanding is each JACK port is a _channel_ (like: stereo, mono...)
 | ||||||
|  |    !!! FIXME:  and not a logical device. So we'll have to figure out: | ||||||
|  |    !!! FIXME:   a) Can there be more than one device? | ||||||
|  |    !!! FIXME:   b) If so, how do you decide what port goes to what? | ||||||
|  |    !!! FIXME: (code in BROKEN_MULTI_DEVICE blocks was written when I assumed | ||||||
|  |    !!! FIXME:  enumerating ports meant listing separate devices. As such, it's | ||||||
|  |    !!! FIXME:  incomplete, as I discovered this as I went along writing. | ||||||
|  | */ | ||||||
|  | #define BROKEN_MULTI_DEVICE 0  /* !!! FIXME */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static jack_client_t * (*JACK_jack_client_open) (const char *, jack_options_t, jack_status_t *, ...); | ||||||
|  | static int (*JACK_jack_client_close) (jack_client_t *); | ||||||
|  | static void (*JACK_jack_on_shutdown) (jack_client_t *, JackShutdownCallback, void *); | ||||||
|  | static int (*JACK_jack_activate) (jack_client_t *); | ||||||
|  | static void * (*JACK_jack_port_get_buffer) (jack_port_t *, jack_nframes_t); | ||||||
|  | static int (*JACK_jack_port_unregister) (jack_client_t *, jack_port_t *); | ||||||
|  | static void (*JACK_jack_free) (void *); | ||||||
|  | static const char ** (*JACK_jack_get_ports) (jack_client_t *, const char *, const char *, unsigned long); | ||||||
|  | static jack_nframes_t (*JACK_jack_get_sample_rate) (jack_client_t *); | ||||||
|  | static jack_nframes_t (*JACK_jack_get_buffer_size) (jack_client_t *); | ||||||
|  | static jack_port_t * (*JACK_jack_port_register) (jack_client_t *, const char *, const char *, unsigned long, unsigned long); | ||||||
|  | static const char * (*JACK_jack_port_name) (const jack_port_t *); | ||||||
|  | static int (*JACK_jack_connect) (jack_client_t *, const char *, const char *); | ||||||
|  | static int (*JACK_jack_set_process_callback) (jack_client_t *, JackProcessCallback, void *); | ||||||
|  | 
 | ||||||
|  | static int load_jack_syms(void); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef SDL_AUDIO_DRIVER_JACK_DYNAMIC | ||||||
|  | 
 | ||||||
|  | static const char *jack_library = SDL_AUDIO_DRIVER_JACK_DYNAMIC; | ||||||
|  | static void *jack_handle = NULL; | ||||||
|  | 
 | ||||||
|  | /* !!! FIXME: this is copy/pasted in several places now */ | ||||||
|  | static int | ||||||
|  | load_jack_sym(const char *fn, void **addr) | ||||||
|  | { | ||||||
|  |     *addr = SDL_LoadFunction(jack_handle, fn); | ||||||
|  |     if (*addr == NULL) { | ||||||
|  |         /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* cast funcs to char* first, to please GCC's strict aliasing rules. */ | ||||||
|  | #define SDL_JACK_SYM(x) \ | ||||||
|  |     if (!load_jack_sym(#x, (void **) (char *) &JACK_##x)) return -1 | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | UnloadJackLibrary(void) | ||||||
|  | { | ||||||
|  |     if (jack_handle != NULL) { | ||||||
|  |         SDL_UnloadObject(jack_handle); | ||||||
|  |         jack_handle = NULL; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | LoadJackLibrary(void) | ||||||
|  | { | ||||||
|  |     int retval = 0; | ||||||
|  |     if (jack_handle == NULL) { | ||||||
|  |         jack_handle = SDL_LoadObject(jack_library); | ||||||
|  |         if (jack_handle == NULL) { | ||||||
|  |             retval = -1; | ||||||
|  |             /* Don't call SDL_SetError(): SDL_LoadObject already did. */ | ||||||
|  |         } else { | ||||||
|  |             retval = load_jack_syms(); | ||||||
|  |             if (retval < 0) { | ||||||
|  |                 UnloadJackLibrary(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return retval; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | #define SDL_JACK_SYM(x) JACK_##x = x | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | UnloadJackLibrary(void) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | LoadJackLibrary(void) | ||||||
|  | { | ||||||
|  |     load_jack_syms(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* SDL_AUDIO_DRIVER_JACK_DYNAMIC */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | load_jack_syms(void) | ||||||
|  | { | ||||||
|  |     SDL_JACK_SYM(jack_client_open); | ||||||
|  |     SDL_JACK_SYM(jack_client_close); | ||||||
|  |     SDL_JACK_SYM(jack_on_shutdown); | ||||||
|  |     SDL_JACK_SYM(jack_activate); | ||||||
|  |     SDL_JACK_SYM(jack_port_get_buffer); | ||||||
|  |     SDL_JACK_SYM(jack_port_unregister); | ||||||
|  |     SDL_JACK_SYM(jack_free); | ||||||
|  |     SDL_JACK_SYM(jack_get_ports); | ||||||
|  |     SDL_JACK_SYM(jack_get_sample_rate); | ||||||
|  |     SDL_JACK_SYM(jack_get_buffer_size); | ||||||
|  |     SDL_JACK_SYM(jack_port_register); | ||||||
|  |     SDL_JACK_SYM(jack_port_name); | ||||||
|  |     SDL_JACK_SYM(jack_connect); | ||||||
|  |     SDL_JACK_SYM(jack_set_process_callback); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static jack_client_t *JACK_client = NULL; | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | DisconnectFromJackServer(void) | ||||||
|  | { | ||||||
|  |     if (JACK_client) { | ||||||
|  |         JACK_jack_client_close(JACK_client); | ||||||
|  |         JACK_client = NULL; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | jackShutdownCallback(void *arg) | ||||||
|  | { | ||||||
|  |     /* !!! FIXME: alert SDL that _every_ open device is lost here */ | ||||||
|  |     fprintf(stderr, "SDL JACK FIXME: shutdown callback fired! All audio devices are lost!\n"); | ||||||
|  |     fflush(stderr); | ||||||
|  | // !!! FIXME: need to put the client (and callback) in the SDL device    SDL_SemPost(this->hidden->iosem);  /* unblock the SDL thread. */
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | ConnectToJackServer(void) | ||||||
|  | { | ||||||
|  |     /* !!! FIXME: we _still_ need an API to specify an app name */ | ||||||
|  |     jack_status_t status; | ||||||
|  |     JACK_client = JACK_jack_client_open("SDL", JackNoStartServer, &status, NULL); | ||||||
|  |     if (JACK_client == NULL) { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     JACK_jack_on_shutdown(JACK_client, jackShutdownCallback, NULL); | ||||||
|  | 
 | ||||||
|  | #if 0  // !!! FIXME: we need to move JACK_client into the SDL audio device.
 | ||||||
|  |     if (JACK_jack_activate(JACK_client) != 0) { | ||||||
|  |         DisconnectFromJackServer(); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // !!! FIXME: implement and register these!
 | ||||||
|  | //typedef int(* JackSampleRateCallback)(jack_nframes_t nframes, void *arg)
 | ||||||
|  | //typedef int(* JackBufferSizeCallback)(jack_nframes_t nframes, void *arg)
 | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg) | ||||||
|  | { | ||||||
|  |     SDL_AudioDevice *this = (SDL_AudioDevice *) arg; | ||||||
|  |     jack_port_t **ports = this->hidden->sdlports; | ||||||
|  |     const int total_channels = this->spec.channels; | ||||||
|  |     const int total_frames = this->spec.samples; | ||||||
|  |     int channelsi; | ||||||
|  | 
 | ||||||
|  |     if (!SDL_AtomicGet(&this->enabled)) { | ||||||
|  |         /* silence the buffer to avoid repeats and corruption. */ | ||||||
|  |         SDL_memset(this->hidden->iobuffer, '\0', this->spec.size); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (channelsi = 0; channelsi < total_channels; channelsi++) { | ||||||
|  |         float *dst = (float *) JACK_jack_port_get_buffer(ports[channelsi], nframes); | ||||||
|  |         if (dst) { | ||||||
|  |             const float *src = ((float *) this->hidden->iobuffer) + channelsi; | ||||||
|  |             int framesi; | ||||||
|  |             for (framesi = 0; framesi < total_frames; framesi++) { | ||||||
|  |                 *(dst++) = *src; | ||||||
|  |                 src += total_channels; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SDL_SemPost(this->hidden->iosem);  /* tell SDL thread we're done; refill the buffer. */ | ||||||
|  |     return 0;  /* success */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* This function waits until it is possible to write a full sound buffer */ | ||||||
|  | static void | ||||||
|  | JACK_WaitDevice(_THIS) | ||||||
|  | { | ||||||
|  |     if (SDL_AtomicGet(&this->enabled)) { | ||||||
|  |         if (SDL_SemWait(this->hidden->iosem) == -1) { | ||||||
|  |             SDL_OpenedAudioDeviceDisconnected(this); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static Uint8 * | ||||||
|  | JACK_GetDeviceBuf(_THIS) | ||||||
|  | { | ||||||
|  |     return (Uint8 *) this->hidden->iobuffer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #if 0 // !!! FIXME
 | ||||||
|  | /* JACK thread calls this. */ | ||||||
|  | static int | ||||||
|  | jackProcessCaptureCallback(jack_nframes_t nframes, void *arg) | ||||||
|  | { | ||||||
|  |     jack_port_get_buffer( | ||||||
|  | asdasd | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* SDL thread calls this. */ | ||||||
|  | static int | ||||||
|  | JACK_CaptureFromDevice(_THIS, void *buffer, int buflen) | ||||||
|  | { | ||||||
|  |     return SDL_SemWait(this->hidden->iosem) == 0) ? buflen : -1; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | JACK_CloseDevice(_THIS) | ||||||
|  | { | ||||||
|  |     if (this->hidden->sdlports) { | ||||||
|  |         const int channels = this->spec.channels; | ||||||
|  |         int i; | ||||||
|  |         for (i = 0; i < channels; i++) { | ||||||
|  |             JACK_jack_port_unregister(JACK_client, this->hidden->sdlports[i]); | ||||||
|  |         } | ||||||
|  |         SDL_free(this->hidden->sdlports); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (this->hidden->iosem) { | ||||||
|  |         SDL_DestroySemaphore(this->hidden->iosem); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (this->hidden->devports) { | ||||||
|  |         JACK_jack_free(this->hidden->devports); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SDL_free(this->hidden->iobuffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) | ||||||
|  | { | ||||||
|  |     /* Note that JACK uses "output" for capture devices (they output audio
 | ||||||
|  |         data to us) and "input" for playback (we input audio data to them). | ||||||
|  |         Likewise, SDL's playback port will be "output" (we write data out) | ||||||
|  |         and capture will be "input" (we read data in). */ | ||||||
|  |     const unsigned long sysportflags = iscapture ? JackPortIsOutput : JackPortIsInput; | ||||||
|  |     const unsigned long sdlportflags = iscapture ? JackPortIsInput : JackPortIsOutput; | ||||||
|  |     const char *sdlportstr = iscapture ? "input" : "output"; | ||||||
|  |     const char **devports = NULL; | ||||||
|  |     int channels = 0; | ||||||
|  |     int i; | ||||||
|  | 
 | ||||||
|  |     /* Initialize all variables that we clean on shutdown */ | ||||||
|  |     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof (*this->hidden)); | ||||||
|  |     if (this->hidden == NULL) { | ||||||
|  |         return SDL_OutOfMemory(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     devports = JACK_jack_get_ports(JACK_client, NULL, NULL, JackPortIsPhysical | sysportflags); | ||||||
|  |     this->hidden->devports = devports; | ||||||
|  |     if (!devports || !devports[0]) { | ||||||
|  |         return SDL_SetError("No physical JACK ports available"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     while (devports[++channels]) { | ||||||
|  |         /* spin to count devports */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */ | ||||||
|  | 
 | ||||||
|  |     /* Jack pretty much demands what it wants. */ | ||||||
|  |     this->spec.format = AUDIO_F32SYS; | ||||||
|  |     this->spec.freq = JACK_jack_get_sample_rate(JACK_client); | ||||||
|  |     this->spec.channels = channels; | ||||||
|  |     this->spec.samples = JACK_jack_get_buffer_size(JACK_client); | ||||||
|  | 
 | ||||||
|  |     SDL_CalculateAudioSpec(&this->spec); | ||||||
|  | 
 | ||||||
|  |     this->hidden->iosem = SDL_CreateSemaphore(0); | ||||||
|  |     if (!this->hidden->iosem) { | ||||||
|  |         return -1;  /* error was set by SDL_CreateSemaphore */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this->hidden->iobuffer = (float *) SDL_calloc(1, this->spec.size); | ||||||
|  |     if (!this->hidden->iobuffer) { | ||||||
|  |         return SDL_OutOfMemory(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Build SDL's ports, which we will connect to the device ports. */ | ||||||
|  |     this->hidden->sdlports = (jack_port_t **) SDL_calloc(channels, sizeof (jack_port_t *)); | ||||||
|  |     if (this->hidden->sdlports == NULL) { | ||||||
|  |         return SDL_OutOfMemory(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (JACK_jack_set_process_callback(JACK_client, jackProcessPlaybackCallback, this) != 0) { | ||||||
|  |         return SDL_SetError("JACK: Couldn't set process callback"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < channels; i++) { | ||||||
|  |         char portname[32]; | ||||||
|  |         SDL_snprintf(portname, sizeof (portname), "sdl_jack_%s_%d", sdlportstr, i); | ||||||
|  |         this->hidden->sdlports[i] = JACK_jack_port_register(JACK_client, portname, JACK_DEFAULT_AUDIO_TYPE, sdlportflags, 0); | ||||||
|  |         if (this->hidden->sdlports[i] == NULL) { | ||||||
|  |             return SDL_SetError("jack_port_register failed"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (JACK_jack_activate(JACK_client) != 0) { | ||||||
|  |         return SDL_SetError("jack_activate failed"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* once activated, we can connect all the ports. */ | ||||||
|  |     for (i = 0; i < channels; i++) { | ||||||
|  |         char portname[32]; | ||||||
|  |         SDL_snprintf(portname, sizeof (portname), "sdl_jack_%s_%d", sdlportstr, i); | ||||||
|  |         const char *sdlport = JACK_jack_port_name(this->hidden->sdlports[i]); | ||||||
|  |         const char *srcport = iscapture ? devports[i] : sdlport; | ||||||
|  |         const char *dstport = iscapture ? sdlport : devports[i]; | ||||||
|  |         if (JACK_jack_connect(JACK_client, srcport, dstport) != 0) { | ||||||
|  |             return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* don't need these anymore. */ | ||||||
|  |     this->hidden->devports = NULL; | ||||||
|  |     JACK_jack_free(devports); | ||||||
|  | 
 | ||||||
|  |     /* We're ready to rock and roll. :-) */ | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #if BROKEN_MULTI_DEVICE  /* !!! FIXME */ | ||||||
|  | static void | ||||||
|  | JackHotplugCallback(jack_port_id_t port_id, int register, void *arg) | ||||||
|  | { | ||||||
|  |     JackPortFlags flags; | ||||||
|  |     jack_port_t *port = JACK_jack_port_by_id(JACK_client, port_id); | ||||||
|  |     SDL_bool iscapture; | ||||||
|  |     const char *name; | ||||||
|  | 
 | ||||||
|  |     if (!port) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     name = JACK_jack_port_name(port); | ||||||
|  |     if (!name) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     flags = JACK_jack_port_flags(port); | ||||||
|  |     if ((flags & JackPortIsPhysical) == 0) { | ||||||
|  |         return;  /* not a physical device, don't care. */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     if ((flags & JackPortIsInput|JackPortIsOutput) == 0) { | ||||||
|  |         return;  /* no input OR output? Don't care...? */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* make sure it's not both, I guess. */ | ||||||
|  |     SDL_assert((flags & JackPortIsInput|JackPortIsOutput) != (JackPortIsInput|JackPortIsOutput)); | ||||||
|  | 
 | ||||||
|  |     /* JACK uses "output" for capture devices (they output audio data to us)
 | ||||||
|  |         and "input" for playback (we input audio data to them) */ | ||||||
|  |     iscapture = ((flags & JackPortIsOutput) != 0); | ||||||
|  |     if (register) { | ||||||
|  |         SDL_AddAudioDevice(iscapture, name, port); | ||||||
|  |     } else { | ||||||
|  |         SDL_RemoveAudioDevice(iscapture, port); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | JackEnumerateDevices(const SDL_bool iscapture) | ||||||
|  | { | ||||||
|  |     const JackPortFlags flags = (iscapture ? JackPortIsOutput : JackPortIsInput); | ||||||
|  |     const char **ports = JACK_jack_get_ports(JACK_client, NULL, NULL, | ||||||
|  |                                         JackPortIsPhysical | flags); | ||||||
|  |     const char **i; | ||||||
|  | 
 | ||||||
|  |     if (!ports) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (i = ports; *i != NULL; i++) { | ||||||
|  |         jack_port_t *port = JACK_jack_port_by_name(JACK_client, *i); | ||||||
|  |         if (port != NULL) { | ||||||
|  |             SDL_AddAudioDevice(iscapture, *i, port); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     JACK_jack_free(ports); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | JACK_DetectDevices() | ||||||
|  | { | ||||||
|  |     JackEnumerateDevices(SDL_FALSE); | ||||||
|  |     JackEnumerateDevices(SDL_TRUE); | ||||||
|  | 
 | ||||||
|  |     /* make JACK fire this callback automatically from now on. */ | ||||||
|  |     JACK_jack_set_port_registration_callback(JACK_client, JackHotplugCallback, NULL); | ||||||
|  | } | ||||||
|  | #endif  /* BROKEN_MULTI_DEVICE */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | JACK_Deinitialize(void) | ||||||
|  | { | ||||||
|  |     DisconnectFromJackServer(); | ||||||
|  |     UnloadJackLibrary(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | JACK_Init(SDL_AudioDriverImpl * impl) | ||||||
|  | { | ||||||
|  |     if (LoadJackLibrary() < 0) { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (ConnectToJackServer() < 0) { | ||||||
|  |         UnloadJackLibrary(); | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Set the function pointers */ | ||||||
|  | 
 | ||||||
|  |     #if BROKEN_MULTI_DEVICE  /* !!! FIXME */ | ||||||
|  |     impl->DetectDevices = JACK_DetectDevices; | ||||||
|  |     #else | ||||||
|  |     impl->OnlyHasDefaultOutputDevice = SDL_TRUE; | ||||||
|  |     // !!! FIXME impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
 | ||||||
|  |     #endif | ||||||
|  | 
 | ||||||
|  |     impl->OpenDevice = JACK_OpenDevice; | ||||||
|  |     impl->WaitDevice = JACK_WaitDevice; | ||||||
|  |     impl->GetDeviceBuf = JACK_GetDeviceBuf; | ||||||
|  |     impl->CloseDevice = JACK_CloseDevice; | ||||||
|  |     impl->Deinitialize = JACK_Deinitialize; | ||||||
|  |     // !!! FIXME impl->CaptureFromDevice = JACK_CaptureFromDevice;
 | ||||||
|  |     // !!! FIXME impl->HasCaptureSupport = SDL_TRUE;
 | ||||||
|  | 
 | ||||||
|  |     return 1;   /* this audio target is available. */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AudioBootStrap JACK_bootstrap = { | ||||||
|  |     "jack", "JACK Audio Connection Kit", JACK_Init, 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif /* SDL_AUDIO_DRIVER_JACK */ | ||||||
|  | 
 | ||||||
|  | /* vi: set ts=4 sw=4 expandtab: */ | ||||||
							
								
								
									
										41
									
								
								src/audio/jack/SDL_jackaudio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/audio/jack/SDL_jackaudio.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | /*
 | ||||||
|  |   Simple DirectMedia Layer | ||||||
|  |   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> | ||||||
|  | 
 | ||||||
|  |   This software is provided 'as-is', without any express or implied | ||||||
|  |   warranty.  In no event will the authors be held liable for any damages | ||||||
|  |   arising from the use of this software. | ||||||
|  | 
 | ||||||
|  |   Permission is granted to anyone to use this software for any purpose, | ||||||
|  |   including commercial applications, and to alter it and redistribute it | ||||||
|  |   freely, subject to the following restrictions: | ||||||
|  | 
 | ||||||
|  |   1. The origin of this software must not be misrepresented; you must not | ||||||
|  |      claim that you wrote the original software. If you use this software | ||||||
|  |      in a product, an acknowledgment in the product documentation would be | ||||||
|  |      appreciated but is not required. | ||||||
|  |   2. Altered source versions must be plainly marked as such, and must not be | ||||||
|  |      misrepresented as being the original software. | ||||||
|  |   3. This notice may not be removed or altered from any source distribution. | ||||||
|  | */ | ||||||
|  | #ifndef _SDL_jackaudio_h | ||||||
|  | #define _SDL_jackaudio_h | ||||||
|  | 
 | ||||||
|  | #include <jack/jack.h> | ||||||
|  | 
 | ||||||
|  | #include "../SDL_sysaudio.h" | ||||||
|  | 
 | ||||||
|  | /* Hidden "this" pointer for the audio functions */ | ||||||
|  | #define _THIS SDL_AudioDevice *this | ||||||
|  | 
 | ||||||
|  | struct SDL_PrivateAudioData | ||||||
|  | { | ||||||
|  |     SDL_sem *iosem; | ||||||
|  |     float *iobuffer; | ||||||
|  |     const char **devports; | ||||||
|  |     jack_port_t **sdlports; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif /* _SDL_jackaudio_h */ | ||||||
|  | 
 | ||||||
|  | /* vi: set ts=4 sw=4 expandtab: */ | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user