Cleanup dynamic loading in the PortAudio backend

This commit is contained in:
Chris Robinson 2011-06-12 04:37:32 -07:00
parent ccf62fc525
commit 6b8209fdc9

View File

@ -26,13 +26,15 @@
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <portaudio.h>
static const ALCchar pa_device[] = "PortAudio Default";
static void *pa_handle;
#ifdef HAVE_DYNLOAD
#define MAKE_FUNC(x) static typeof(x) * p##x
MAKE_FUNC(Pa_Initialize);
MAKE_FUNC(Pa_Terminate);
@ -45,9 +47,15 @@ MAKE_FUNC(Pa_GetDefaultOutputDevice);
MAKE_FUNC(Pa_GetStreamInfo);
#undef MAKE_FUNC
static const ALCchar pa_device[] = "PortAudio Default";
#define Pa_Initialize pPa_Initialize
#define Pa_Terminate pPa_Terminate
#define Pa_GetErrorText pPa_GetErrorText
#define Pa_StartStream pPa_StartStream
#define Pa_StopStream pPa_StopStream
#define Pa_OpenStream pPa_OpenStream
#define Pa_CloseStream pPa_CloseStream
#define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice
#define Pa_GetStreamInfo pPa_GetStreamInfo
void *pa_load(void)
{
@ -56,47 +64,26 @@ void *pa_load(void)
PaError err;
#ifdef _WIN32
pa_handle = LoadLibrary("portaudio.dll");
#define LOAD_FUNC(x) do { \
p##x = (typeof(p##x))GetProcAddress(pa_handle, #x); \
if(!(p##x)) { \
AL_PRINT("Could not load %s from portaudio.dll\n", #x); \
FreeLibrary(pa_handle); \
pa_handle = NULL; \
return NULL; \
} \
} while(0)
#elif defined(HAVE_DLFCN_H)
const char *str;
#if defined(__APPLE__) && defined(__MACH__)
# define PALIB "portaudio.dll"
#elif defined(__APPLE__) && defined(__MACH__)
# define PALIB "libportaudio.2.dylib"
#else
# define PALIB "libportaudio.so.2"
#endif
pa_handle = dlopen(PALIB, RTLD_NOW);
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 NULL; \
} \
} while(0)
#else
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
pa_handle = LoadLib(PALIB);
if(!pa_handle)
return NULL;
#define LOAD_FUNC(f) do { \
p##f = GetSymbol(pa_handle, #f); \
if(p##f == NULL) \
{ \
CloseLib(pa_handle); \
pa_handle = NULL; \
return NULL; \
} \
} while(0)
LOAD_FUNC(Pa_Initialize);
LOAD_FUNC(Pa_Terminate);
LOAD_FUNC(Pa_GetErrorText);
@ -106,23 +93,33 @@ LOAD_FUNC(Pa_OpenStream);
LOAD_FUNC(Pa_CloseStream);
LOAD_FUNC(Pa_GetDefaultOutputDevice);
LOAD_FUNC(Pa_GetStreamInfo);
#undef LOAD_FUNC
if((err=pPa_Initialize()) != paNoError)
if((err=Pa_Initialize()) != paNoError)
{
AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err));
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined(HAVE_DLFCN_H)
dlclose(pa_handle);
#endif
AL_PRINT("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
CloseLib(pa_handle);
pa_handle = NULL;
return NULL;
}
}
return pa_handle;
}
#else
void *pa_load(void)
{
if(!pa_handle)
{
pa_handle = (void*)0xDEADBEEF;
if((err=Pa_Initialize()) != paNoError)
{
AL_PRINT("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
pa_handle = NULL;
}
}
return pa_handle;
}
#endif
typedef struct {
@ -185,7 +182,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
outParams.device = GetConfigValueInt("port", "device", -1);
if(outParams.device < 0)
outParams.device = pPa_GetDefaultOutputDevice();
outParams.device = Pa_GetDefaultOutputDevice();
outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
(float)device->Frequency;
outParams.hostApiSpecificStreamInfo = NULL;
@ -212,16 +209,16 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
SetDefaultChannelOrder(device);
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
err = Pa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
device->UpdateSize, paNoFlag, pa_callback, device);
if(err != paNoError)
{
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
AL_PRINT("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
device->ExtraData = NULL;
free(data);
return ALC_FALSE;
}
streamInfo = pPa_GetStreamInfo(data->stream);
streamInfo = Pa_GetStreamInfo(data->stream);
device->szDeviceName = strdup(deviceName);
device->Frequency = streamInfo->sampleRate;
@ -234,9 +231,9 @@ static void pa_close_playback(ALCdevice *device)
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_CloseStream(data->stream);
err = Pa_CloseStream(data->stream);
if(err != paNoError)
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
AL_PRINT("Error closing stream: %s\n", Pa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
@ -248,7 +245,7 @@ static ALCboolean pa_reset_playback(ALCdevice *device)
const PaStreamInfo *streamInfo;
PaError err;
streamInfo = pPa_GetStreamInfo(data->stream);
streamInfo = Pa_GetStreamInfo(data->stream);
if(device->Frequency != streamInfo->sampleRate)
{
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
@ -258,10 +255,10 @@ static ALCboolean pa_reset_playback(ALCdevice *device)
}
device->UpdateSize = data->update_size;
err = pPa_StartStream(data->stream);
err = Pa_StartStream(data->stream);
if(err != paNoError)
{
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
AL_PRINT("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
return ALC_FALSE;
}
@ -273,9 +270,9 @@ static void pa_stop_playback(ALCdevice *device)
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
err = Pa_StopStream(data->stream);
if(err != paNoError)
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
AL_PRINT("Error stopping stream: %s\n", Pa_GetErrorText(err));
}
@ -311,7 +308,7 @@ static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
inParams.device = GetConfigValueInt("port", "capture", -1);
if(inParams.device < 0)
inParams.device = pPa_GetDefaultOutputDevice();
inParams.device = Pa_GetDefaultOutputDevice();
inParams.suggestedLatency = 0.0f;
inParams.hostApiSpecificStreamInfo = NULL;
@ -335,11 +332,11 @@ static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
}
inParams.channelCount = ChannelsFromDevFmt(device->FmtChans);
err = pPa_OpenStream(&data->stream, &inParams, NULL, device->Frequency,
err = Pa_OpenStream(&data->stream, &inParams, NULL, device->Frequency,
paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
if(err != paNoError)
{
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
AL_PRINT("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
goto error;
}
@ -359,9 +356,9 @@ static void pa_close_capture(ALCdevice *device)
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_CloseStream(data->stream);
err = Pa_CloseStream(data->stream);
if(err != paNoError)
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
AL_PRINT("Error closing stream: %s\n", Pa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
@ -372,9 +369,9 @@ static void pa_start_capture(ALCdevice *device)
pa_data *data = device->ExtraData;
PaError err;
err = pPa_StartStream(data->stream);
err = Pa_StartStream(data->stream);
if(err != paNoError)
AL_PRINT("Error starting stream: %s\n", pPa_GetErrorText(err));
AL_PRINT("Error starting stream: %s\n", Pa_GetErrorText(err));
}
static void pa_stop_capture(ALCdevice *device)
@ -382,9 +379,9 @@ static void pa_stop_capture(ALCdevice *device)
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
err = Pa_StopStream(data->stream);
if(err != paNoError)
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
AL_PRINT("Error stopping stream: %s\n", Pa_GetErrorText(err));
}
static void pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
@ -425,11 +422,9 @@ void alc_pa_deinit(void)
{
if(pa_handle)
{
pPa_Terminate();
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined(HAVE_DLFCN_H)
dlclose(pa_handle);
Pa_Terminate();
#ifdef HAVE_DYNLOAD
CloseLib(pa_handle);
#endif
pa_handle = NULL;
}