Load backend libs on-demand
This commit is contained in:
parent
f72b6fe717
commit
8024df2991
224
Alc/alsa.c
224
Alc/alsa.c
@ -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();
|
||||
}
|
||||
|
97
Alc/dsound.c
97
Alc/dsound.c
@ -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();
|
||||
}
|
||||
|
149
Alc/portaudio.c
149
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();
|
||||
}
|
||||
|
227
Alc/pulseaudio.c
227
Alc/pulseaudio.c
@ -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();
|
||||
} //}}}
|
||||
//}}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user