diff options
author | Chris Robinson <[email protected]> | 2009-09-27 00:21:40 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2009-09-27 00:21:40 -0700 |
commit | 8024df299121f2d25c4e4b24f8c55ebdac2d9e4c (patch) | |
tree | e3f2ce6634bda5a75521015aaf275fff9ac9c2b4 /Alc/portaudio.c | |
parent | f72b6fe717898172c9915fd70c0710bfcf7d843e (diff) |
Load backend libs on-demand
Diffstat (limited to 'Alc/portaudio.c')
-rw-r--r-- | Alc/portaudio.c | 149 |
1 files changed, 88 insertions, 61 deletions
diff --git a/Alc/portaudio.c b/Alc/portaudio.c index 7ef255f2..5c90f611 100644 --- a/Alc/portaudio.c +++ b/Alc/portaudio.c @@ -47,6 +47,81 @@ MAKE_FUNC(Pa_GetStreamInfo); static const ALCchar pa_device[] = "PortAudio Software"; +static volatile ALuint load_count; + + +void pa_load(void) +{ + const char *str; + PaError err; + + if(load_count == 0) + { +#ifdef HAVE_DLFCN_H +#if defined(__APPLE__) && defined(__MACH__) +# define PALIB "libportaudio.2.dylib" +#else +# define PALIB "libportaudio.so.2" +#endif + pa_handle = dlopen(PALIB, RTLD_NOW); + if(!pa_handle) + return; + dlerror(); + +#define LOAD_FUNC(f) do { \ + p##f = (typeof(f)*)dlsym(pa_handle, #f); \ + if((str=dlerror()) != NULL) \ + { \ + dlclose(pa_handle); \ + pa_handle = NULL; \ + AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \ + return; \ + } \ +} while(0) +#else + str = NULL; + pa_handle = (void*)0xDEADBEEF; +#define LOAD_FUNC(f) p##f = f +#endif + +LOAD_FUNC(Pa_Initialize); +LOAD_FUNC(Pa_Terminate); +LOAD_FUNC(Pa_GetErrorText); +LOAD_FUNC(Pa_StartStream); +LOAD_FUNC(Pa_StopStream); +LOAD_FUNC(Pa_OpenStream); +LOAD_FUNC(Pa_CloseStream); +LOAD_FUNC(Pa_GetDefaultOutputDevice); +LOAD_FUNC(Pa_GetStreamInfo); + +#undef LOAD_FUNC + + if((err=pPa_Initialize()) != paNoError) + { + AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err)); +#ifdef HAVE_DLFCN_H + dlclose(pa_handle); +#endif + pa_handle = NULL; + return; + } + } + + ++load_count; +} + +void pa_unload(void) +{ + if(load_count == 0 || --load_count > 0) + return; + + pPa_Terminate(); +#ifdef HAVE_DLFCN_H + dlclose(pa_handle); +#endif + pa_handle = NULL; +} + typedef struct { PaStream *stream; @@ -75,14 +150,15 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) pa_data *data; PaError err; - if(pa_handle == NULL) - return ALC_FALSE; - if(!deviceName) deviceName = pa_device; else if(strcmp(deviceName, pa_device) != 0) return ALC_FALSE; + pa_load(); + if(pa_handle == NULL) + return ALC_FALSE; + data = (pa_data*)calloc(1, sizeof(pa_data)); device->ExtraData = data; @@ -108,6 +184,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) AL_PRINT("Unknown format: 0x%x\n", device->Format); device->ExtraData = NULL; free(data); + pa_unload(); return ALC_FALSE; } outParams.channelCount = aluChannelsFromFormat(device->Format); @@ -119,6 +196,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err)); device->ExtraData = NULL; free(data); + pa_unload(); return ALC_FALSE; } streamInfo = pPa_GetStreamInfo(data->stream); @@ -130,6 +208,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) pPa_CloseStream(data->stream); device->ExtraData = NULL; free(data); + pa_unload(); return ALC_FALSE; } @@ -153,6 +232,8 @@ static void pa_close_playback(ALCdevice *device) free(data); device->ExtraData = NULL; + + pa_unload(); } static ALCboolean pa_reset_playback(ALCdevice *device) @@ -196,76 +277,22 @@ static const BackendFuncs pa_funcs = { void alc_pa_init(BackendFuncs *func_list) { - const char *str; - PaError err; - - if(func_list) *func_list = pa_funcs; - -#ifdef HAVE_DLFCN_H -#if defined(__APPLE__) && defined(__MACH__) -# define PALIB "libportaudio.2.dylib" -#else -# define PALIB "libportaudio.so.2" -#endif - pa_handle = dlopen(PALIB, RTLD_NOW); - if(!pa_handle) - return; - dlerror(); - -#define LOAD_FUNC(f) do { \ - p##f = (typeof(f)*)dlsym(pa_handle, #f); \ - if((str=dlerror()) != NULL) \ - { \ - dlclose(pa_handle); \ - pa_handle = NULL; \ - AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \ - return; \ - } \ -} while(0) -#else - str = NULL; - pa_handle = (void*)0xDEADBEEF; -#define LOAD_FUNC(f) p##f = f -#endif - - LOAD_FUNC(Pa_Initialize); - LOAD_FUNC(Pa_Terminate); - LOAD_FUNC(Pa_GetErrorText); - LOAD_FUNC(Pa_StartStream); - LOAD_FUNC(Pa_StopStream); - LOAD_FUNC(Pa_OpenStream); - LOAD_FUNC(Pa_CloseStream); - LOAD_FUNC(Pa_GetDefaultOutputDevice); - LOAD_FUNC(Pa_GetStreamInfo); -#undef LOAD_FUNC - - if((err=pPa_Initialize()) != paNoError) - { - AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err)); - alc_pa_deinit(); - return; - } + *func_list = pa_funcs; } void alc_pa_deinit(void) { - if(pa_handle) - { - pPa_Terminate(); -#ifdef HAVE_DLFCN_H - dlclose(pa_handle); - pa_handle = NULL; -#endif - } } void alc_pa_probe(int type) { - if(!pa_handle) alc_pa_init(NULL); + pa_load(); if(!pa_handle) return; if(type == DEVICE_PROBE) AppendDeviceList(pa_device); else if(type == ALL_DEVICE_PROBE) AppendAllDeviceList(pa_device); + + pa_unload(); } |