Load backend libs on-demand

This commit is contained in:
Chris Robinson 2009-09-27 00:21:40 -07:00
parent f72b6fe717
commit 8024df2991
4 changed files with 406 additions and 291 deletions

View File

@ -116,6 +116,108 @@ static DevMap *allDevNameMap;
static ALuint numDevNames;
static DevMap *allCaptureDevNameMap;
static ALuint numCaptureDevNames;
static volatile ALuint load_count;
void alsa_load(void)
{
if(load_count == 0)
{
char *str;
#ifdef HAVE_DLFCN_H
alsa_handle = dlopen("libasound.so.2", RTLD_NOW);
if(!alsa_handle)
return;
dlerror();
#define LOAD_FUNC(f) do { \
p##f = dlsym(alsa_handle, #f); \
if((str=dlerror()) != NULL) \
{ \
dlclose(alsa_handle); \
alsa_handle = NULL; \
AL_PRINT("Could not load %s from libasound.so.2: %s\n", #f, str); \
return; \
} \
} while(0)
#else
str = NULL;
alsa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(snd_strerror);
LOAD_FUNC(snd_pcm_open);
LOAD_FUNC(snd_pcm_close);
LOAD_FUNC(snd_pcm_nonblock);
LOAD_FUNC(snd_pcm_frames_to_bytes);
LOAD_FUNC(snd_pcm_hw_params_malloc);
LOAD_FUNC(snd_pcm_hw_params_free);
LOAD_FUNC(snd_pcm_hw_params_any);
LOAD_FUNC(snd_pcm_hw_params_set_access);
LOAD_FUNC(snd_pcm_hw_params_set_format);
LOAD_FUNC(snd_pcm_hw_params_set_channels);
LOAD_FUNC(snd_pcm_hw_params_set_periods_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
LOAD_FUNC(snd_pcm_hw_params_set_period_size_near);
LOAD_FUNC(snd_pcm_hw_params_get_buffer_size);
LOAD_FUNC(snd_pcm_hw_params_get_period_size);
LOAD_FUNC(snd_pcm_hw_params_get_access);
LOAD_FUNC(snd_pcm_hw_params_get_periods);
LOAD_FUNC(snd_pcm_hw_params);
LOAD_FUNC(snd_pcm_sw_params_malloc);
LOAD_FUNC(snd_pcm_sw_params_current);
LOAD_FUNC(snd_pcm_sw_params_set_avail_min);
LOAD_FUNC(snd_pcm_sw_params);
LOAD_FUNC(snd_pcm_sw_params_free);
LOAD_FUNC(snd_pcm_prepare);
LOAD_FUNC(snd_pcm_start);
LOAD_FUNC(snd_pcm_resume);
LOAD_FUNC(snd_pcm_wait);
LOAD_FUNC(snd_pcm_state);
LOAD_FUNC(snd_pcm_avail_update);
LOAD_FUNC(snd_pcm_areas_silence);
LOAD_FUNC(snd_pcm_mmap_begin);
LOAD_FUNC(snd_pcm_mmap_commit);
LOAD_FUNC(snd_pcm_readi);
LOAD_FUNC(snd_pcm_writei);
LOAD_FUNC(snd_pcm_drain);
LOAD_FUNC(snd_pcm_info_malloc);
LOAD_FUNC(snd_pcm_info_free);
LOAD_FUNC(snd_pcm_info_set_device);
LOAD_FUNC(snd_pcm_info_set_subdevice);
LOAD_FUNC(snd_pcm_info_set_stream);
LOAD_FUNC(snd_pcm_info_get_name);
LOAD_FUNC(snd_ctl_pcm_next_device);
LOAD_FUNC(snd_ctl_pcm_info);
LOAD_FUNC(snd_ctl_open);
LOAD_FUNC(snd_ctl_close);
LOAD_FUNC(snd_ctl_card_info_malloc);
LOAD_FUNC(snd_ctl_card_info_free);
LOAD_FUNC(snd_ctl_card_info);
LOAD_FUNC(snd_ctl_card_info_get_name);
LOAD_FUNC(snd_card_next);
#undef LOAD_FUNC
}
++load_count;
}
void alsa_unload(void)
{
if(load_count == 0 || --load_count > 0)
return;
#ifdef HAVE_DLFCN_H
dlclose(alsa_handle);
#endif
alsa_handle = NULL;
}
static int xrun_recovery(snd_pcm_t *handle, int err)
@ -339,9 +441,6 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam
char driver[64];
int i;
if(!alsa_handle)
return ALC_FALSE;
strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(!deviceName)
@ -363,6 +462,10 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
alsa_load();
if(!alsa_handle)
return ALC_FALSE;
open_alsa:
data = (alsa_data*)calloc(1, sizeof(alsa_data));
@ -382,6 +485,7 @@ open_alsa:
{
free(data);
AL_PRINT("Could not open playback device '%s': %s\n", driver, psnd_strerror(i));
alsa_unload();
return ALC_FALSE;
}
@ -397,6 +501,8 @@ static void alsa_close_playback(ALCdevice *device)
psnd_pcm_close(data->pcmHandle);
free(data);
device->ExtraData = NULL;
alsa_unload();
}
static ALCboolean alsa_reset_playback(ALCdevice *device)
@ -565,9 +671,6 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
char *err;
int i;
if(!alsa_handle)
return ALC_FALSE;
strncpy(driver, GetConfigValue("alsa", "capture", "default"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(!deviceName)
@ -590,6 +693,10 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
return ALC_FALSE;
}
alsa_load();
if(!alsa_handle)
return ALC_FALSE;
open_alsa:
data = (alsa_data*)calloc(1, sizeof(alsa_data));
@ -609,6 +716,7 @@ open_alsa:
{
free(data);
AL_PRINT("Could not open capture device '%s': %s\n", driver, psnd_strerror(i));
alsa_unload();
return ALC_FALSE;
}
@ -627,6 +735,7 @@ open_alsa:
AL_PRINT("Unknown format: 0x%x\n", pDevice->Format);
psnd_pcm_close(data->pcmHandle);
free(data);
alsa_unload();
return ALC_FALSE;
}
@ -660,6 +769,7 @@ open_alsa:
psnd_pcm_hw_params_free(p);
psnd_pcm_close(data->pcmHandle);
free(data);
alsa_unload();
return ALC_FALSE;
}
@ -669,6 +779,7 @@ open_alsa:
psnd_pcm_hw_params_free(p);
psnd_pcm_close(data->pcmHandle);
free(data);
alsa_unload();
return ALC_FALSE;
}
@ -683,6 +794,7 @@ open_alsa:
AL_PRINT("ring buffer create failed\n");
psnd_pcm_close(data->pcmHandle);
free(data);
alsa_unload();
return ALC_FALSE;
}
@ -694,6 +806,7 @@ open_alsa:
psnd_pcm_close(data->pcmHandle);
DestroyRingBuffer(data->ring);
free(data);
alsa_unload();
return ALC_FALSE;
}
@ -707,6 +820,7 @@ open_alsa:
pDevice->ExtraData = NULL;
free(data->buffer);
free(data);
alsa_unload();
return ALC_FALSE;
}
@ -727,6 +841,8 @@ static void alsa_close_capture(ALCdevice *pDevice)
free(data->buffer);
free(data);
pDevice->ExtraData = NULL;
alsa_unload();
}
static void alsa_start_capture(ALCdevice *pDevice)
@ -773,89 +889,7 @@ BackendFuncs alsa_funcs = {
void alc_alsa_init(BackendFuncs *func_list)
{
char *str;
if(func_list) *func_list = alsa_funcs;
#ifdef HAVE_DLFCN_H
alsa_handle = dlopen("libasound.so.2", RTLD_NOW);
if(!alsa_handle)
return;
dlerror();
#define LOAD_FUNC(f) do { \
p##f = (typeof(f)*)dlsym(alsa_handle, #f); \
if((str=dlerror()) != NULL) \
{ \
dlclose(alsa_handle); \
alsa_handle = NULL; \
AL_PRINT("Could not load %s from libasound.so.2: %s\n", #f, str); \
return; \
} \
} while(0)
#else
str = NULL;
alsa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(snd_strerror);
LOAD_FUNC(snd_pcm_open);
LOAD_FUNC(snd_pcm_close);
LOAD_FUNC(snd_pcm_nonblock);
LOAD_FUNC(snd_pcm_frames_to_bytes);
LOAD_FUNC(snd_pcm_hw_params_malloc);
LOAD_FUNC(snd_pcm_hw_params_free);
LOAD_FUNC(snd_pcm_hw_params_any);
LOAD_FUNC(snd_pcm_hw_params_set_access);
LOAD_FUNC(snd_pcm_hw_params_set_format);
LOAD_FUNC(snd_pcm_hw_params_set_channels);
LOAD_FUNC(snd_pcm_hw_params_set_periods_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
LOAD_FUNC(snd_pcm_hw_params_set_period_size_near);
LOAD_FUNC(snd_pcm_hw_params_get_buffer_size);
LOAD_FUNC(snd_pcm_hw_params_get_period_size);
LOAD_FUNC(snd_pcm_hw_params_get_access);
LOAD_FUNC(snd_pcm_hw_params_get_periods);
LOAD_FUNC(snd_pcm_hw_params);
LOAD_FUNC(snd_pcm_sw_params_malloc);
LOAD_FUNC(snd_pcm_sw_params_current);
LOAD_FUNC(snd_pcm_sw_params_set_avail_min);
LOAD_FUNC(snd_pcm_sw_params);
LOAD_FUNC(snd_pcm_sw_params_free);
LOAD_FUNC(snd_pcm_prepare);
LOAD_FUNC(snd_pcm_start);
LOAD_FUNC(snd_pcm_resume);
LOAD_FUNC(snd_pcm_wait);
LOAD_FUNC(snd_pcm_state);
LOAD_FUNC(snd_pcm_avail_update);
LOAD_FUNC(snd_pcm_areas_silence);
LOAD_FUNC(snd_pcm_mmap_begin);
LOAD_FUNC(snd_pcm_mmap_commit);
LOAD_FUNC(snd_pcm_readi);
LOAD_FUNC(snd_pcm_writei);
LOAD_FUNC(snd_pcm_drain);
LOAD_FUNC(snd_pcm_info_malloc);
LOAD_FUNC(snd_pcm_info_free);
LOAD_FUNC(snd_pcm_info_set_device);
LOAD_FUNC(snd_pcm_info_set_subdevice);
LOAD_FUNC(snd_pcm_info_set_stream);
LOAD_FUNC(snd_pcm_info_get_name);
LOAD_FUNC(snd_ctl_pcm_next_device);
LOAD_FUNC(snd_ctl_pcm_info);
LOAD_FUNC(snd_ctl_open);
LOAD_FUNC(snd_ctl_close);
LOAD_FUNC(snd_ctl_card_info_malloc);
LOAD_FUNC(snd_ctl_card_info_free);
LOAD_FUNC(snd_ctl_card_info);
LOAD_FUNC(snd_ctl_card_info_get_name);
LOAD_FUNC(snd_card_next);
#undef LOAD_FUNC
*func_list = alsa_funcs;
}
void alc_alsa_deinit(void)
@ -873,12 +907,6 @@ void alc_alsa_deinit(void)
free(allCaptureDevNameMap);
allCaptureDevNameMap = NULL;
numCaptureDevNames = 0;
#ifdef HAVE_DLFCN_H
if(alsa_handle)
dlclose(alsa_handle);
#endif
alsa_handle = NULL;
}
void alc_alsa_probe(int type)
@ -891,7 +919,7 @@ void alc_alsa_probe(int type)
char name[128];
ALuint i;
if(!alsa_handle) alc_alsa_init(NULL);
alsa_load();
if(!alsa_handle) return;
psnd_ctl_card_info_malloc(&info);
@ -907,6 +935,7 @@ void alc_alsa_probe(int type)
AL_PRINT("no playback cards found...\n");
psnd_pcm_info_free(pcminfo);
psnd_ctl_card_info_free(info);
alsa_unload();
return;
}
@ -981,6 +1010,7 @@ void alc_alsa_probe(int type)
AL_PRINT("no capture cards found...\n");
psnd_pcm_info_free(pcminfo);
psnd_ctl_card_info_free(info);
alsa_unload();
return;
}
@ -1048,4 +1078,6 @@ void alc_alsa_probe(int type)
psnd_pcm_info_free(pcminfo);
psnd_ctl_card_info_free(info);
alsa_unload();
}

View File

@ -71,6 +71,53 @@ typedef struct {
static const ALCchar dsDevice[] = "DirectSound Software";
static DevMap *DeviceList;
static ALuint NumDevices;
static volatile ALuint load_count;
void DSoundLoad(void)
{
if(load_count == 0)
{
#ifdef _WIN32
ds_handle = LoadLibraryA("dsound.dll");
if(ds_handle == NULL)
{
AL_PRINT("Failed to load dsound.dll\n");
return;
}
#define LOAD_FUNC(f) do { \
p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \
if(p##f == NULL) \
{ \
FreeLibrary(ds_handle); \
ds_handle = NULL; \
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
return; \
} \
} while(0)
#else
ds_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(DirectSoundCreate);
LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
}
++load_count;
}
void DSoundUnload(void)
{
if(load_count == 0 || --load_count > 0)
return;
#ifdef _WIN32
FreeLibrary(ds_handle);
#endif
ds_handle = NULL;
}
static ALuint DSoundProc(ALvoid *ptr)
@ -157,9 +204,6 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
LPGUID guid = NULL;
HRESULT hr;
if(ds_handle == NULL)
return ALC_FALSE;
if(!deviceName)
deviceName = dsDevice;
else if(strcmp(deviceName, dsDevice) != 0)
@ -177,12 +221,17 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
DSoundLoad();
if(ds_handle == NULL)
return ALC_FALSE;
//Initialise requested device
pData = calloc(1, sizeof(DSoundData));
if(!pData)
{
SetALCError(ALC_OUT_OF_MEMORY);
DSoundUnload();
return ALC_FALSE;
}
@ -195,6 +244,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
if(pData->lpDS)
IDirectSound_Release(pData->lpDS);
free(pData);
DSoundUnload();
return ALC_FALSE;
}
@ -210,6 +260,8 @@ static void DSoundClosePlayback(ALCdevice *device)
IDirectSound_Release(pData->lpDS);
free(pData);
device->ExtraData = NULL;
DSoundUnload();
}
static ALCboolean DSoundResetPlayback(ALCdevice *device)
@ -479,34 +531,7 @@ static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname,
void alcDSoundInit(BackendFuncs *FuncList)
{
if(FuncList) *FuncList = DSoundFuncs;
#ifdef _WIN32
ds_handle = LoadLibraryA("dsound.dll");
if(ds_handle == NULL)
{
AL_PRINT("Failed to load dsound.dll\n");
return;
}
#define LOAD_FUNC(f) do { \
p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \
if(p##f == NULL) \
{ \
FreeLibrary(ds_handle); \
ds_handle = NULL; \
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
return; \
} \
} while(0)
#else
ds_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(DirectSoundCreate);
LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
*FuncList = DSoundFuncs;
}
void alcDSoundDeinit(void)
@ -518,17 +543,11 @@ void alcDSoundDeinit(void)
free(DeviceList);
DeviceList = NULL;
NumDevices = 0;
#ifdef _WIN32
if(ds_handle)
FreeLibrary(ds_handle);
#endif
ds_handle = NULL;
}
void alcDSoundProbe(int type)
{
if(!ds_handle) alcDSoundInit(NULL);
DSoundLoad();
if(!ds_handle) return;
if(type == DEVICE_PROBE)
@ -548,4 +567,6 @@ void alcDSoundProbe(int type)
if(FAILED(hr))
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
}
DSoundUnload();
}

View File

@ -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();
}

View File

@ -109,6 +109,108 @@ typedef struct {
static const ALCchar pulse_device[] = "PulseAudio Software";
static const ALCchar pulse_capture_device[] = "PulseAudio Capture";
static volatile ALuint load_count;
void pulse_load(void) //{{{
{
if(load_count == 0)
{
#ifdef _WIN32
pa_handle = LoadLibrary("libpulse-0.dll");
#define LOAD_FUNC(x) do { \
p##x = GetProcAddress(pa_handle, #x); \
if(!(p##x)) { \
AL_PRINT("Could not load %s from libpulse-0.dll\n", #x); \
FreeLibrary(pa_handle); \
pa_handle = NULL; \
return; \
} \
} while(0)
#elif defined (HAVE_DLFCN_H)
const char *err;
#if defined(__APPLE__) && defined(__MACH__)
pa_handle = dlopen("libpulse.0.dylib", RTLD_NOW);
#else
pa_handle = dlopen("libpulse.so.0", RTLD_NOW);
#endif
dlerror();
#define LOAD_FUNC(x) do { \
p##x = dlsym(pa_handle, #x); \
if((err=dlerror() != NULL) { \
AL_PRINT("Could not load %s from libpulse: %s\n", #x, err); \
dlclose(pa_handle); \
pa_handle = NULL; \
return; \
} \
} while(0)
#else
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(x) p##x = (x)
#endif
if(!pa_handle)
return;
LOAD_FUNC(pa_context_unref);
LOAD_FUNC(pa_sample_spec_valid);
LOAD_FUNC(pa_stream_drop);
LOAD_FUNC(pa_strerror);
LOAD_FUNC(pa_context_get_state);
LOAD_FUNC(pa_stream_get_state);
LOAD_FUNC(pa_threaded_mainloop_signal);
LOAD_FUNC(pa_stream_peek);
LOAD_FUNC(pa_threaded_mainloop_wait);
LOAD_FUNC(pa_threaded_mainloop_unlock);
LOAD_FUNC(pa_context_new);
LOAD_FUNC(pa_threaded_mainloop_stop);
LOAD_FUNC(pa_context_disconnect);
LOAD_FUNC(pa_threaded_mainloop_start);
LOAD_FUNC(pa_threaded_mainloop_get_api);
LOAD_FUNC(pa_context_set_state_callback);
LOAD_FUNC(pa_stream_write);
LOAD_FUNC(pa_xfree);
LOAD_FUNC(pa_stream_connect_record);
LOAD_FUNC(pa_stream_connect_playback);
LOAD_FUNC(pa_path_get_filename);
LOAD_FUNC(pa_get_binary_name);
LOAD_FUNC(pa_threaded_mainloop_free);
LOAD_FUNC(pa_context_errno);
LOAD_FUNC(pa_xmalloc0);
LOAD_FUNC(pa_stream_unref);
LOAD_FUNC(pa_threaded_mainloop_accept);
LOAD_FUNC(pa_stream_set_write_callback);
LOAD_FUNC(pa_threaded_mainloop_new);
LOAD_FUNC(pa_context_connect);
LOAD_FUNC(pa_stream_get_buffer_attr);
LOAD_FUNC(pa_stream_set_read_callback);
LOAD_FUNC(pa_stream_set_state_callback);
LOAD_FUNC(pa_stream_new);
LOAD_FUNC(pa_stream_disconnect);
LOAD_FUNC(pa_threaded_mainloop_lock);
#undef LOAD_FUNC
}
++load_count;
} //}}}
void pulse_unload(void) //{{{
{
if(load_count == 0 || --load_count > 0)
return;
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined (HAVE_DLFCN_H)
dlclose(pa_handle);
#endif
pa_handle = NULL;
} //}}}
// PulseAudio I/O Callbacks //{{{
@ -265,20 +367,26 @@ static void pulse_close(ALCdevice *device) //{{{
// OpenAL {{{
static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_name) //{{{
{
if(!pa_handle)
return ALC_FALSE;
if(!device_name)
device_name = pulse_device;
else if(strcmp(device_name, pulse_device) != 0)
return ALC_FALSE;
return pulse_open(device, device_name);
pulse_load();
if(!pa_handle)
return ALC_FALSE;
if(pulse_open(device, device_name) != ALC_FALSE)
return ALC_TRUE;
pulse_unload();
return ALC_FALSE;
} //}}}
static void pulse_close_playback(ALCdevice *device) //{{{
{
pulse_close(device);
pulse_unload();
} //}}}
static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
@ -399,17 +507,21 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
pulse_data *data;
pa_stream_state_t state;
if(!pa_handle)
return ALC_FALSE;
if(!device_name)
device_name = pulse_capture_device;
else if(strcmp(device_name, pulse_capture_device) != 0)
return ALC_FALSE;
if(pulse_open(device, device_name) == ALC_FALSE)
pulse_load();
if(!pa_handle)
return ALC_FALSE;
if(pulse_open(device, device_name) == ALC_FALSE)
{
pulse_unload();
return ALC_FALSE;
}
data = device->ExtraData;
ppa_threaded_mainloop_lock(data->loop);
@ -421,6 +533,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
{
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
@ -449,6 +562,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
AL_PRINT("Unknown format: 0x%x\n", device->Format);
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
@ -457,6 +571,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
AL_PRINT("Invalid sample format\n");
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
@ -468,6 +583,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
@ -481,6 +597,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
data->stream = NULL;
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
@ -496,6 +613,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
data->stream = NULL;
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
@ -511,6 +629,7 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
static void pulse_close_capture(ALCdevice *device) //{{{
{
pulse_close(device);
pulse_unload();
} //}}}
static void pulse_start_capture(ALCdevice *device) //{{{
@ -563,102 +682,16 @@ BackendFuncs pulse_funcs = { //{{{
void alc_pulse_init(BackendFuncs *func_list) //{{{
{
if(func_list) *func_list = pulse_funcs;
#ifdef _WIN32
pa_handle = LoadLibrary("libpulse-0.dll");
#define LOAD_FUNC(x) do { \
p##x = GetProcAddress(pa_handle, #x); \
if(!(p##x)) { \
AL_PRINT("Could not load %s from libpulse-0.dll\n", #x); \
FreeLibrary(pa_handle); \
pa_handle = NULL; \
return; \
} \
} while(0)
#elif defined (HAVE_DLFCN_H)
#if defined(__APPLE__) && defined(__MACH__)
pa_handle = dlopen("libpulse.0.dylib", RTLD_NOW);
#else
pa_handle = dlopen("libpulse.so.0", RTLD_NOW);
#endif
#define LOAD_FUNC(x) do { \
p##x = dlsym(pa_handle, #x); \
if(!(p##x)) { \
AL_PRINT("Could not load %s from libpulse\n", #x); \
dlclose(pa_handle); \
pa_handle = NULL; \
return; \
} \
} while(0)
#else
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(x) p##x = (x)
#endif
if(!pa_handle)
return;
LOAD_FUNC(pa_context_unref);
LOAD_FUNC(pa_sample_spec_valid);
LOAD_FUNC(pa_stream_drop);
LOAD_FUNC(pa_strerror);
LOAD_FUNC(pa_context_get_state);
LOAD_FUNC(pa_stream_get_state);
LOAD_FUNC(pa_threaded_mainloop_signal);
LOAD_FUNC(pa_stream_peek);
LOAD_FUNC(pa_threaded_mainloop_wait);
LOAD_FUNC(pa_threaded_mainloop_unlock);
LOAD_FUNC(pa_context_new);
LOAD_FUNC(pa_threaded_mainloop_stop);
LOAD_FUNC(pa_context_disconnect);
LOAD_FUNC(pa_threaded_mainloop_start);
LOAD_FUNC(pa_threaded_mainloop_get_api);
LOAD_FUNC(pa_context_set_state_callback);
LOAD_FUNC(pa_stream_write);
LOAD_FUNC(pa_xfree);
LOAD_FUNC(pa_stream_connect_record);
LOAD_FUNC(pa_stream_connect_playback);
LOAD_FUNC(pa_path_get_filename);
LOAD_FUNC(pa_get_binary_name);
LOAD_FUNC(pa_threaded_mainloop_free);
LOAD_FUNC(pa_context_errno);
LOAD_FUNC(pa_xmalloc0);
LOAD_FUNC(pa_stream_unref);
LOAD_FUNC(pa_threaded_mainloop_accept);
LOAD_FUNC(pa_stream_set_write_callback);
LOAD_FUNC(pa_threaded_mainloop_new);
LOAD_FUNC(pa_context_connect);
LOAD_FUNC(pa_stream_get_buffer_attr);
LOAD_FUNC(pa_stream_set_read_callback);
LOAD_FUNC(pa_stream_set_state_callback);
LOAD_FUNC(pa_stream_new);
LOAD_FUNC(pa_stream_disconnect);
LOAD_FUNC(pa_threaded_mainloop_lock);
#undef LOAD_FUNC
*func_list = pulse_funcs;
} //}}}
void alc_pulse_deinit(void) //{{{
{
if(pa_handle)
{
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined (HAVE_DLFCN_H)
dlclose(pa_handle);
#endif
}
pa_handle = NULL;
} //}}}
void alc_pulse_probe(int type) //{{{
{
if(!pa_handle) alc_pulse_init(NULL);
pulse_load();
if(!pa_handle) return;
if(type == DEVICE_PROBE)
@ -667,5 +700,7 @@ void alc_pulse_probe(int type) //{{{
AppendAllDeviceList(pulse_device);
else if(type == CAPTURE_DEVICE_PROBE)
AppendCaptureDeviceList(pulse_capture_device);
pulse_unload();
} //}}}
//}}}