Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/dlls/openal32/openal.c b/dlls/openal32/openal.c
- new file mode 100644
- index 0000000..17efbf8
- --- /dev/null
- +++ b/dlls/openal32/openal.c
- @@ -0,0 +1,461 @@
- +#include "config.h"
- +
- +#include <stdarg.h>
- +#include "windef.h"
- +#include "winbase.h"
- +#include "wine/debug.h"
- +
- +/* TODO: add alut */
- +/* TODO: add other openal extensions */
- +
- +#if defined(HAVE_OPENAL_AL_H)
- + #include <OpenAL/al.h>
- + #include <OpenAL/alc.h>
- +#elif defined(HAVE_AL_AL_H)
- + #include <AL/al.h>
- + #include <AL/alc.h>
- +#endif
- +
- +WINE_DEFAULT_DEBUG_CHANNEL(openal);
- +
- +/* OpenAL exts */
- +/* defined as (ext) */
- +#define WINE_AL_EXTS(func)\
- + func(ALC_1_0)\
- + func(AL_1_0)\
- + func(ALC_1_1)\
- + func(AL_1_1)\
- + func(ALC_EXT_MAC_OSX)\
- + func(AL_EXT_STATIC_BUFFER)\
- + func(ALC_EXT_ASA)\
- + func(ALUT)
- +
- +/* OpenAL ext function groups */
- +enum
- +{
- +#define MAKE_WINE_ENUMS(ext) WINE_##ext,
- + WINE_AL_EXTS(MAKE_WINE_ENUMS)
- +#undef MAKE_WINE_ENUMS
- +};
- +
- +static const char* wine_al_ext_to_string(const int ext)
- +{
- + switch(ext)
- + {
- +#define WINE_AL_EXT_TO_STRING_HELPER(ext) case WINE_##ext: return "WINE_" #ext;
- + WINE_AL_EXTS(WINE_AL_EXT_TO_STRING_HELPER)
- +#undef WINE_AL_EXT_TO_STRING_HELPER
- + }
- + return "ERROR";
- +}
- +
- +/* OpenAL 1.0 functions */
- +/* defined as (ext, return_type, func_name, params, args) */
- +/* used to define func ptrs, get proc address, etc... */
- +#define WINE_ALC_1_0_FUNCS(func)\
- + func(WINE_ALC_1_0, ALCcontext * , alcCreateContext, ( ALCdevice *device, const ALCint* attrlist ), ( device, attrlist ))\
- + func(WINE_ALC_1_0, ALCboolean , alcMakeContextCurrent, ( ALCcontext *context ), ( context ))\
- + func(WINE_ALC_1_0, void , alcProcessContext, ( ALCcontext *context ), ( context ))\
- + func(WINE_ALC_1_0, void , alcSuspendContext, ( ALCcontext *context ), ( context ))\
- + func(WINE_ALC_1_0, void , alcDestroyContext, ( ALCcontext *context ), ( context ))\
- + func(WINE_ALC_1_0, ALCcontext * , alcGetCurrentContext, ( ALCvoid ), ( ))\
- + func(WINE_ALC_1_0, ALCdevice * , alcGetContextsDevice, ( ALCcontext *context ), ( context ))\
- + func(WINE_ALC_1_0, ALCdevice * , alcOpenDevice, ( const ALCchar *devicename ), ( devicename ))\
- + func(WINE_ALC_1_0, ALCboolean , alcCloseDevice, ( ALCdevice *device ), ( device ))\
- + func(WINE_ALC_1_0, ALCenum , alcGetError, ( ALCdevice *device ), ( device ))\
- + func(WINE_ALC_1_0, ALCboolean , alcIsExtensionPresent, ( ALCdevice *device, const ALCchar *extname ), ( device, extname ))\
- +/* must be handled differently */\
- + /*func(WINE_ALC_1_0, void * , alcGetProcAddress, ( ALCdevice *device, const ALCchar *funcname ), ( device, funcname ))*/\
- + func(WINE_ALC_1_0, ALCenum , alcGetEnumValue, ( ALCdevice *device, const ALCchar *enumname ), ( device, enumname ))\
- + func(WINE_ALC_1_0, const ALCchar* , alcGetString, ( ALCdevice *device, ALCenum param ), ( device, param ))\
- + func(WINE_ALC_1_0, void , alcGetIntegerv, ( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ), ( device, param, size, dest ))
- +
- +#define WINE_AL_1_0_FUNCS(func)\
- + func(WINE_AL_1_0, void , alEnable, ( ALenum capability ), ( capability ))\
- + func(WINE_AL_1_0, void , alDisable, ( ALenum capability ), ( capability ))\
- + func(WINE_AL_1_0, ALboolean , alIsEnabled, ( ALenum capability ), ( capability ))\
- + func(WINE_AL_1_0, const ALchar* , alGetString, ( ALenum param ), ( param ))\
- + func(WINE_AL_1_0, void , alGetBooleanv, ( ALenum param, ALboolean* data ), ( param, data ))\
- + func(WINE_AL_1_0, void , alGetIntegerv, ( ALenum param, ALint* data ), ( param, data ))\
- + func(WINE_AL_1_0, void , alGetFloatv, ( ALenum param, ALfloat* data ), ( param, data ))\
- + func(WINE_AL_1_0, void , alGetDoublev, ( ALenum param, ALdouble* data ), ( param, data ))\
- + func(WINE_AL_1_0, ALboolean , alGetBoolean, ( ALenum param ), ( param ))\
- + func(WINE_AL_1_0, ALint , alGetInteger, ( ALenum param ), ( param ))\
- + func(WINE_AL_1_0, ALfloat , alGetFloat, ( ALenum param ), ( param ))\
- + func(WINE_AL_1_0, ALdouble , alGetDouble, ( ALenum param ), ( param ))\
- + func(WINE_AL_1_0, ALenum , alGetError, ( void ), ( ))\
- + func(WINE_AL_1_0, ALboolean , alIsExtensionPresent, (const ALchar* extname ), (extname ))\
- +/* must be handled differently */\
- + /*func(WINE_AL_1_0, void* , alGetProcAddress, ( const ALchar* fname ), ( fname ))*/\
- + func(WINE_AL_1_0, ALenum , alGetEnumValue, ( const ALchar* ename ), ( ename ))\
- + func(WINE_AL_1_0, void , alListenerf, ( ALenum param, ALfloat value ), ( param, value ))\
- + func(WINE_AL_1_0, void , alListener3f, ( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( param, value1, value2, value3 ))\
- + func(WINE_AL_1_0, void , alListenerfv, ( ALenum param, const ALfloat* values ), ( param, values ))\
- + func(WINE_AL_1_0, void , alListeneri, ( ALenum param, ALint value ), ( param, value ))\
- + func(WINE_AL_1_0, void , alGetListenerf, ( ALenum param, ALfloat* value ), ( param, value ))\
- + func(WINE_AL_1_0, void , alGetListener3f, ( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ), ( param, value1, value2, value3 ))\
- + func(WINE_AL_1_0, void , alGetListenerfv, ( ALenum param, ALfloat* values ), ( param, values ))\
- + func(WINE_AL_1_0, void , alGetListeneri, ( ALenum param, ALint* value ), ( param, value ))\
- + func(WINE_AL_1_0, void , alGetListeneriv, ( ALenum param, ALint* values ), ( param, values ))\
- + func(WINE_AL_1_0, void , alGenSources, ( ALsizei n, ALuint* sources ), ( n, sources ))\
- + func(WINE_AL_1_0, void , alDeleteSources, ( ALsizei n, const ALuint* sources ), ( n, sources ))\
- + func(WINE_AL_1_0, ALboolean , alIsSource, ( ALuint sid ), ( sid ))\
- + func(WINE_AL_1_0, void , alSourcef, ( ALuint sid, ALenum param, ALfloat value), ( sid, param, value))\
- + func(WINE_AL_1_0, void , alSource3f, ( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( sid, param, value1, value2, value3 ))\
- + func(WINE_AL_1_0, void , alSourcefv, ( ALuint sid, ALenum param, const ALfloat* values ), ( sid, param, values ))\
- + func(WINE_AL_1_0, void , alSourcei, ( ALuint sid, ALenum param, ALint value), ( sid, param, value))\
- + func(WINE_AL_1_0, void , alGetSourcef, ( ALuint sid, ALenum param, ALfloat* value ), ( sid, param, value ))\
- + func(WINE_AL_1_0, void , alGetSource3f, ( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3), ( sid, param, value1, value2, value3))\
- + func(WINE_AL_1_0, void , alGetSourcefv, ( ALuint sid, ALenum param, ALfloat* values ), ( sid, param, values ))\
- + func(WINE_AL_1_0, void , alGetSourcei, ( ALuint sid, ALenum param, ALint* value ), ( sid, param, value ))\
- + func(WINE_AL_1_0, void , alGetSourceiv, ( ALuint sid, ALenum param, ALint* values ), ( sid, param, values ))\
- + func(WINE_AL_1_0, void , alSourcePlayv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
- + func(WINE_AL_1_0, void , alSourceStopv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
- + func(WINE_AL_1_0, void , alSourceRewindv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
- + func(WINE_AL_1_0, void , alSourcePausev, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
- + func(WINE_AL_1_0, void , alSourcePlay, ( ALuint sid ), ( sid ))\
- + func(WINE_AL_1_0, void , alSourceStop, ( ALuint sid ), ( sid ))\
- + func(WINE_AL_1_0, void , alSourceRewind, ( ALuint sid ), ( sid ))\
- + func(WINE_AL_1_0, void , alSourcePause, ( ALuint sid ), ( sid ))\
- + func(WINE_AL_1_0, void , alSourceQueueBuffers, ( ALuint sid, ALsizei numEntries, const ALuint *bids ), ( sid, numEntries, bids ))\
- + func(WINE_AL_1_0, void , alSourceUnqueueBuffers, ( ALuint sid, ALsizei numEntries, ALuint *bids ), ( sid, numEntries, bids ))\
- + func(WINE_AL_1_0, void , alGenBuffers, ( ALsizei n, ALuint* buffers ), ( n, buffers ))\
- + func(WINE_AL_1_0, void , alDeleteBuffers, ( ALsizei n, const ALuint* buffers ), ( n, buffers ))\
- + func(WINE_AL_1_0, ALboolean , alIsBuffer, ( ALuint bid ), ( bid ))\
- + func(WINE_AL_1_0, void , alBufferData, ( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ), ( bid, format, data, size, freq ))\
- + func(WINE_AL_1_0, void , alGetBufferf, ( ALuint bid, ALenum param, ALfloat* value ), ( bid, param, value ))\
- + func(WINE_AL_1_0, void , alGetBufferfv, ( ALuint bid, ALenum param, ALfloat* values ), ( bid, param, values ))\
- + func(WINE_AL_1_0, void , alGetBufferi, ( ALuint bid, ALenum param, ALint* value ), ( bid, param, value ))\
- + func(WINE_AL_1_0, void , alGetBufferiv, ( ALuint bid, ALenum param, ALint* values ), ( bid, param, values ))\
- + func(WINE_AL_1_0, void , alDopplerFactor, ( ALfloat value ), ( value ))\
- + func(WINE_AL_1_0, void , alDopplerVelocity, ( ALfloat value ), ( value ))\
- + func(WINE_AL_1_0, void , alDistanceModel, ( ALenum distanceModel ), ( distanceModel ))
- +
- +/*
- + func(WINE_ALC_1_1, ALCdevice*, alcCaptureOpenDevice, (const ALCbyte *deviceName, ALCuint freq, ALCenum fmt, ALCsizei bufsize), (deviceName, freq, fmt, bufsize))\
- + func(WINE_ALC_1_1, ALCboolean, alcCaptureCloseDevice, (ALCdevice *device), (device))\
- + func(WINE_ALC_1_1, ALCvoid, alcCaptureStart, (ALCdevice *device), (device))\
- + func(WINE_ALC_1_1, ALCvoid, alcCaptureStop, (ALCdevice *device), (device))\
- + func(WINE_ALC_1_1, ALCvoid, alcCaptureSamples, (ALCdevice *device, ALCvoid *buf, ALCsizei samps), (device, buf, samps))
- +*/
- +/*
- + func(WINE_AL_1_1, ALvoid, alListener3i, (ALenum param, ALint v1, ALint v2, ALint v3), (param, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alListeneriv, (ALenum param, ALint *values), (param, values))\
- + func(WINE_AL_1_1, ALvoid, alGetListener3i, (ALenum param, ALint *v1, ALint *v2, ALint *v3), (param, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alSource3i, (ALuint source, ALenum param, ALint v1, ALint v2, ALint v3), (source, param, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alSourceiv, (ALuint source, ALenum param, ALint *values), (source, param, values))\
- + func(WINE_AL_1_1, ALvoid, alGetSource3i, (ALuint source, ALenum param, ALint *v1, ALint *v2, ALint *v3), (source, param, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alBufferf, (ALuint buffer, ALenum param, ALfloat value), (buffer, param, value))\
- + func(WINE_AL_1_1, ALvoid, alBuffer3f, (ALuint buffer, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3), (buffer, param, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alBufferfv, (ALuint buffer, ALenum param, ALfloat *values), (buffer, param, values))\
- + func(WINE_AL_1_1, ALvoid, alBufferi, (ALuint buffer, ALenum param, ALint value), (buffer, param, value))\
- + func(WINE_AL_1_1, ALvoid, alBuffer3i, (ALuint buffer, ALenum param, ALint v1, ALint v2, ALint v3), (buffer, param, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alBufferiv, (ALuint buffer, ALenum param, ALint *values), (buffer, param, values))\
- + func(WINE_AL_1_1, ALvoid, alGetBuffer3f, (ALuint buffer, ALenum pname, ALfloat *v1, ALfloat *v2, ALfloat *v3), (buffer, pname, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alGetBuffer3i, (ALuint buffer, ALenum pname, ALint *v1, ALint *v2, ALint *v3), (buffer, pname, v1, v2, v3))\
- + func(WINE_AL_1_1, ALvoid, alSpeedOfSound, (ALfloat value), (value))
- +*/
- +
- +/* OpenAL 1.1 functions */
- +#define WINE_ALC_1_1_FUNCS(func)\
- + func(WINE_ALC_1_1, ALCdevice * , alcCaptureOpenDevice, ( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ), ( devicename, frequency, format, buffersize ))\
- + func(WINE_ALC_1_1, ALCboolean , alcCaptureCloseDevice, ( ALCdevice *device ), ( device ))\
- + func(WINE_ALC_1_1, void , alcCaptureStart, ( ALCdevice *device ), ( device ))\
- + func(WINE_ALC_1_1, void , alcCaptureStop, ( ALCdevice *device ), ( device ))\
- + func(WINE_ALC_1_1, void , alcCaptureSamples, ( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ), ( device, buffer, samples ))
- +
- +#define WINE_AL_1_1_FUNCS(func)\
- + func(WINE_AL_1_1, void , alListener3i, ( ALenum param, ALint value1, ALint value2, ALint value3 ), ( param, value1, value2, value3 ))\
- + func(WINE_AL_1_1, void , alListeneriv, ( ALenum param, const ALint* values ), ( param, values ))\
- + func(WINE_AL_1_1, void , alGetListener3i, ( ALenum param, ALint *value1, ALint *value2, ALint *value3 ), ( param, value1, value2, value3 ))\
- + func(WINE_AL_1_1, void , alSource3i, ( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ), ( sid, param, value1, value2, value3 ))\
- + func(WINE_AL_1_1, void , alSourceiv, ( ALuint sid, ALenum param, const ALint* values ), ( sid, param, values ))\
- + func(WINE_AL_1_1, void , alGetSource3i, ( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3), ( sid, param, value1, value2, value3))\
- + func(WINE_AL_1_1, void , alBufferf, ( ALuint bid, ALenum param, ALfloat value), ( bid, param, value))\
- + func(WINE_AL_1_1, void , alBuffer3f, ( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( bid, param, value1, value2, value3 ))\
- + func(WINE_AL_1_1, void , alBufferfv, ( ALuint bid, ALenum param, const ALfloat* values ), ( bid, param, values ))\
- + func(WINE_AL_1_1, void , alBufferi, ( ALuint bid, ALenum param, ALint value), ( bid, param, value))\
- + func(WINE_AL_1_1, void , alBuffer3i, ( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ), ( bid, param, value1, value2, value3 ))\
- + func(WINE_AL_1_1, void , alBufferiv, ( ALuint bid, ALenum param, const ALint* values ), ( bid, param, values ))\
- + func(WINE_AL_1_1, void , alGetBuffer3f, ( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3), ( bid, param, value1, value2, value3))\
- + func(WINE_AL_1_1, void , alGetBuffer3i, ( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3), ( bid, param, value1, value2, value3))\
- + func(WINE_AL_1_1, void , alSpeedOfSound, ( ALfloat value ), ( value ))
- +
- +/* OpenAL extension functions */
- +#define WINE_ALC_EXT_FUNCS(func)\
- + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alcMacOSXRenderingQualityProcPtr, (const ALint value), (value))\
- + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alMacOSXRenderChannelCountProcPtr, (const ALint value), (value))\
- + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alcMacOSXMixerMaxiumumBussesProcPtr, (const ALint value), (value))\
- + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alcMacOSXMixerOutputRateProcPtr, (const ALdouble value), (value))\
- + func(WINE_ALC_EXT_MAC_OSX, ALint, alcMacOSXGetRenderingQualityProcPtr, (), ())\
- + func(WINE_ALC_EXT_MAC_OSX, ALint, alMacOSXGetRenderChannelCountProcPtr, (), ())\
- + func(WINE_ALC_EXT_MAC_OSX, ALint, alcMacOSXGetMixerMaxiumumBussesProcPtr, (), ())\
- + func(WINE_ALC_EXT_MAC_OSX, ALdouble, alcMacOSXGetMixerOutputRateProcPtr, (), ())\
- + func(WINE_ALC_EXT_ASA, ALenum, alcASAGetSourceProcPtr, (const ALuint property, ALuint source, ALvoid *data, ALuint* dataSize), (property, source, data, dataSize))\
- + func(WINE_ALC_EXT_ASA, ALenum, alcASASetSourceProcPtr, (const ALuint property, ALuint source, ALvoid *data, ALuint dataSize), (property, source, data, dataSize))\
- + func(WINE_ALC_EXT_ASA, ALenum, alcASAGetListenerProcPtr, (const ALuint property, ALvoid *data, ALuint* dataSize), (property, data, dataSize))\
- + func(WINE_ALC_EXT_ASA, ALenum, alcASASetListenerProcPtr, (const ALuint property, ALvoid *data, ALuint dataSize), (property, data, dataSize))
- +
- +#define WINE_AL_EXT_FUNCS(func)\
- + func(WINE_AL_EXT_STATIC_BUFFER, ALvoid, alBufferDataStatic, (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq), (bid, format, data, size, freq))
- +
- +#define WINE_ALUT_FUNCS(func)\
- + func(WINE_ALUT, ALvoid , alutInit , (ALint *argcp, ALbyte **argv), (argcp, argv))\
- + func(WINE_ALUT, ALvoid , alutExit , (ALvoid), ())\
- +/* Nasty Compatibility stuff, WARNING: THESE FUNCTIONS ARE STRONGLY DEPRECATED */\
- +/* handled differently */\
- +/* func(WINE_ALUT, ALvoid , alutLoadWAVFile , (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency), (fileName, format, data, size, frequency))*/\
- +/* func(WINE_ALUT, ALvoid , alutLoadWAVMemory , (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency), (buffer, format, data, size, frequency))*/\
- + func(WINE_ALUT, ALvoid , alutUnloadWAV , (ALenum format, ALvoid *data, ALsizei size, ALsizei frequency), (format, data, size, frequency))
- +
- +/*
- + func(WINE_ALUT, ALboolean , alutInit , (int *argcp, char **argv), (argcp, argv))\
- + func(WINE_ALUT, ALboolean , alutExit , (void), ())\
- + func(WINE_ALUT, ALboolean , alutInitWithoutContext , (int *argcp, char **argv), (argcp, argv))\
- + func(WINE_ALUT, ALenum , alutGetError , (void), ())\
- + func(WINE_ALUT, const char *, alutGetErrorString , (ALenum error), (error))\
- + func(WINE_ALUT, ALuint , alutCreateBufferFromFile , (const char *fileName), (fileName))\
- + func(WINE_ALUT, ALuint , alutCreateBufferFromFileImage , (const ALvoid *data, ALsizei length), (data, length))\
- + func(WINE_ALUT, ALuint , alutCreateBufferHelloWorld , (void), ())\
- + func(WINE_ALUT, ALuint , alutCreateBufferWaveform , (ALenum waveshape, ALfloat frequency, ALfloat phase, ALfloat duration), (waveshape, frequency, phase, duration))\
- + func(WINE_ALUT, ALvoid *, alutLoadMemoryFromFile , (const char *fileName, ALenum *format, ALsizei *size, ALfloat *frequency), (fileName, format, size, frequency))\
- + func(WINE_ALUT, ALvoid *, alutLoadMemoryFromFileImage , (const ALvoid *data, ALsizei length, ALenum *format, ALsizei *size, ALfloat *frequency), (data, length, format, size, frequency))\
- + func(WINE_ALUT, ALvoid *, alutLoadMemoryHelloWorld , (ALenum *format, ALsizei *size, ALfloat *frequency), (format, size, frequency))\
- + func(WINE_ALUT, ALvoid *, alutLoadMemoryWaveform , (ALenum waveshape, ALfloat frequency, ALfloat phase, ALfloat duration, ALenum *format, ALsizei *size, ALfloat *freq), (waveshape, frequency, phase, duration, format, size, freq))\
- + func(WINE_ALUT, const char *, alutGetMIMETypes , (ALenum loader), (loader))\
- + func(WINE_ALUT, ALint , alutGetMajorVersion , (void), ())\
- + func(WINE_ALUT, ALint , alutGetMinorVersion , (void), ())\
- + func(WINE_ALUT, ALboolean , alutSleep , (ALfloat duration), (duration))
- +*/
- +
- +#if defined(__APPLE__)
- + /* Incorrectly defined in Mac OSX */
- + #define WINE_ALUT_BAD_FUNCS(func)
- +#else
- + #define WINE_ALUT_BAD_FUNCS(func)\
- + func(WINE_ALUT, ALvoid , alutLoadWAVFile , (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop), (fileName, format, data, size, frequency, loop))\
- + func(WINE_ALUT, ALvoid , alutLoadWAVMemory , (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop), (buffer, format, data, size, frequency, loop))
- +#endif
- +
- +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
- +
- +/* OpenAL error checking (should be able to turn this off for release builds) */
- +#define CHECK_ALC_ERROR(al_device)\
- +{\
- + ALenum error;\
- + if(al_device)\
- + {\
- + error = alcGetError(al_device);\
- + if(error)\
- + {\
- + ERR("ALC ERROR: %s at %s:%d\n", alcGetString(al_device, error), __FILE__, __LINE__);\
- + }\
- + }\
- + else\
- + {\
- + ERR("Invalid al device at %s:%d\n", __FILE__, __LINE__);\
- + }\
- +}
- +
- +#define CHECK_AL_ERROR()\
- +{\
- + ALenum error;\
- + error = alGetError();\
- + if(error)\
- + {\
- + ERR("AL ERROR: %s at %s:%d\n", alGetString(error), __FILE__, __LINE__);\
- + }\
- +}
- +
- +static HMODULE openal32_handle;
- +
- +/* Make the thunking functions */
- +
- +#define MAKE_WINE_ALC_FUNCS(ext, ret, name, params, args)\
- + ret CDECL wine_##name params\
- + {\
- + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
- + return name args;\
- + }
- +
- +#define MAKE_WINE_AL_FUNCS(ext, ret, name, params, args)\
- + ret CDECL wine_##name params\
- + {\
- + /*CHECK_AL_ERROR();*/\
- + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
- + return name args;\
- + }
- +
- +#define MAKE_WINE_ALC_EXT_FUNCS(ext, ret, name, params, args)\
- + typedef ret (*t##name) params;\
- + static t##name p_##name = NULL;\
- + ret CDECL wine_##name params\
- + {\
- + /* should these functions be cached? */\
- + p_##name = (t##name)alcGetProcAddress(NULL, #name);\
- + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
- + return p_##name args;\
- + }
- +
- +#define MAKE_WINE_AL_EXT_FUNCS(ext, ret, name, params, args)\
- + typedef ret (*t##name) params;\
- + static t##name p_##name = NULL;\
- + ret CDECL wine_##name params\
- + {\
- + /*CHECK_AL_ERROR();*/\
- + /* should these functions be cached? */\
- + p_##name = (t##name)alGetProcAddress(#name);\
- + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
- + return p_##name args;\
- + }
- +
- +#define MAKE_WINE_ALUT_FUNCS(ext, ret, name, params, args)\
- + extern ret name params;\
- + ret CDECL wine_##name params\
- + {\
- + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
- + return name args;\
- + }
- +
- + WINE_ALC_1_0_FUNCS(MAKE_WINE_ALC_FUNCS)
- + WINE_AL_1_0_FUNCS(MAKE_WINE_AL_FUNCS)
- + WINE_ALC_1_1_FUNCS(MAKE_WINE_ALC_EXT_FUNCS)
- + WINE_AL_1_1_FUNCS(MAKE_WINE_AL_EXT_FUNCS)
- + WINE_ALC_EXT_FUNCS(MAKE_WINE_ALC_EXT_FUNCS)
- + WINE_AL_EXT_FUNCS(MAKE_WINE_AL_EXT_FUNCS)
- + WINE_ALUT_FUNCS(MAKE_WINE_ALUT_FUNCS)
- + WINE_ALUT_BAD_FUNCS(MAKE_WINE_ALUT_FUNCS)
- +
- +#undef MAKE_WINE_ALC_FUNCS
- +#undef MAKE_WINE_AL_FUNCS
- +#undef MAKE_WINE_ALC_EXT_FUNCS
- +#undef MAKE_WINE_AL_EXT_FUNCS
- +#undef MAKE_WINE_ALUT_FUNCS
- +
- +
- +void* CDECL wine_alcGetProcAddress(ALCdevice *device, const ALCchar *funcname)
- +{
- + void* ret = NULL;
- + TRACE("funcname == %s, ext == %s\n", funcname, wine_al_ext_to_string(WINE_ALC_1_0));
- + /* TODO: maybe check an ext registry/versions? */
- + /*
- + Checks similar to the following could be done...
- + alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE");
- + alcIsExtensionPresent(NULL, "AL_EXT_STATIC_BUFFER");
- + */
- + /* be consistent with the underlying impl */
- + if (alcGetProcAddress(device, funcname))
- + {
- + ret = GetProcAddress(openal32_handle, funcname);
- + }
- + TRACE("funcname == %s, ret == %p\n", funcname, ret);
- + return ret;
- +}
- +
- +void* CDECL wine_alGetProcAddress(const ALchar* fname)
- +{
- + void* ret = NULL;
- + TRACE("fname == %s, ext == %s\n", fname, wine_al_ext_to_string(WINE_AL_1_0));
- + /* TODO: maybe check an ext registry/versions? */
- + /*
- + Checks similar to the following could be done...
- + alIsExtensionPresent("ALC_EXT_CAPTURE");
- + alIsExtensionPresent("AL_EXT_STATIC_BUFFER");
- + */
- + /* be consistent with the underlying impl */
- + if (alGetProcAddress(fname))
- + {
- + ret = GetProcAddress(openal32_handle, fname);
- + }
- + TRACE("fname == %s, ret == %p\n", fname, ret);
- + return ret;
- +}
- +
- +#if defined(__APPLE__)
- + /* Incorrectly defined in Mac OSX */
- + extern ALvoid alutLoadWAVFile (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency);
- + ALvoid CDECL wine_alutLoadWAVFile (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop)
- + {
- + /* do what with loop? */
- + TRACE("ext == %s\n", wine_al_ext_to_string(WINE_ALUT));
- + return alutLoadWAVFile (fileName, format, data, size, frequency);
- + }
- +
- + extern ALvoid alutLoadWAVMemory (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency);
- + ALvoid CDECL wine_alutLoadWAVMemory (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop)
- + {
- + /* do what with loop? */
- + TRACE("ext == %s\n", wine_al_ext_to_string(WINE_ALUT));
- + return alutLoadWAVMemory (buffer, format, data, size, frequency);
- + }
- +#endif
- +
- +
- +/***********************************************************************
- + * OpenAL initialisation routine
- + */
- +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
- +{
- + switch(reason)
- + {
- + case DLL_PROCESS_ATTACH:
- + openal32_handle = hinst;
- + /*DisableThreadLibraryCalls(hinst);*/
- + break;
- + case DLL_PROCESS_DETACH:
- + /*process_detach();*/
- + break;
- + }
- + return TRUE;
- +}
- +
- +
- +#else /* !defined(HAVE_OPENAL_AL_H) && !defined(HAVE_AL_AL_H) */
- +
- +#define MAKE_FAKE_WINE_FUNCS(ext, ret, name, params, args)\
- + void CDECL wine_##name ()\
- + {\
- + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
- + FIXME("OpenAL not supported on this system\n");\
- + }
- + WINE_ALC_1_0_FUNCS(MAKE_FAKE_WINE_FUNCS)
- + WINE_AL_1_0_FUNCS(MAKE_FAKE_WINE_FUNCS)
- + WINE_ALUT_FUNCS(MAKE_FAKE_WINE_FUNCS)
- + WINE_ALUT_BAD_FUNCS(MAKE_FAKE_WINE_FUNCS)
- +#undef MAKE_WINE_FUNCS
- +
- +
- +void CDECL wine_alcGetProcAddress()
- +{
- + FIXME("OpenAL not supported on this system\n");
- +}
- +
- +void CDECL wine_alGetProcAddress()
- +{
- + FIXME("OpenAL not supported on this system\n");
- +}
- +
- +#if defined(__APPLE__)
- + /* Incorrectly defined in Mac OSX */
- + void CDECL wine_alutLoadWAVFile ()
- + {
- + FIXME("OpenAL not supported on this system\n");
- + }
- +
- + void CDECL wine_alutLoadWAVMemory ()
- + {
- + FIXME("OpenAL not supported on this system\n");
- + }
- +#endif
- +
- +
- +/***********************************************************************
- + * OpenAL initialisation routine
- + */
- +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
- +{
- + FIXME("OpenAL not supported on this system\n");
- + return TRUE;
- +}
- +
- +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
- \ No newline at end of file
- diff --git a/dlls/openal32/openal32.spec b/dlls/openal32/openal32.spec
- new file mode 100644
- index 0000000..395e660
- --- /dev/null
- +++ b/dlls/openal32/openal32.spec
- @@ -0,0 +1,133 @@
- +#OpenAL ALC_1_0
- +@ cdecl alcCreateContext(ptr ptr ) wine_alcCreateContext
- +@ cdecl alcMakeContextCurrent(ptr) wine_alcMakeContextCurrent
- +@ cdecl alcProcessContext(ptr) wine_alcProcessContext
- +@ cdecl alcSuspendContext(ptr) wine_alcSuspendContext
- +@ cdecl alcDestroyContext(ptr) wine_alcDestroyContext
- +@ cdecl alcGetCurrentContext( ) wine_alcGetCurrentContext
- +@ cdecl alcGetContextsDevice(ptr) wine_alcGetContextsDevice
- +@ cdecl alcOpenDevice(str) wine_alcOpenDevice
- +@ cdecl alcCloseDevice(ptr) wine_alcCloseDevice
- +@ cdecl alcGetError(ptr) wine_alcGetError
- +@ cdecl alcIsExtensionPresent(ptr str) wine_alcIsExtensionPresent
- +@ cdecl alcGetProcAddress(ptr str) wine_alcGetProcAddress
- +@ cdecl alcGetEnumValue(ptr str) wine_alcGetEnumValue
- +@ cdecl alcGetString(ptr long ) wine_alcGetString
- +@ cdecl alcGetIntegerv(ptr long long ptr) wine_alcGetIntegerv
- +#OpenAL AL_1_0
- +@ cdecl alEnable(long ) wine_alEnable
- +@ cdecl alDisable(long ) wine_alDisable
- +@ cdecl alIsEnabled(long ) wine_alIsEnabled
- +@ cdecl alGetString(long ) wine_alGetString
- +@ cdecl alGetBooleanv(long ptr ) wine_alGetBooleanv
- +@ cdecl alGetIntegerv(long ptr ) wine_alGetIntegerv
- +@ cdecl alGetFloatv(long ptr ) wine_alGetFloatv
- +@ cdecl alGetDoublev(long ptr ) wine_alGetDoublev
- +@ cdecl alGetBoolean(long ) wine_alGetBoolean
- +@ cdecl alGetInteger(long ) wine_alGetInteger
- +@ cdecl alGetFloat(long ) wine_alGetFloat
- +@ cdecl alGetDouble(long ) wine_alGetDouble
- +@ cdecl alGetError( ) wine_alGetError
- +@ cdecl alIsExtensionPresent(str ) wine_alIsExtensionPresent
- +@ cdecl alGetProcAddress(str ) wine_alGetProcAddress
- +@ cdecl alGetEnumValue(str ) wine_alGetEnumValue
- +@ cdecl alListenerf(long long ) wine_alListenerf
- +@ cdecl alListener3f(long long long long ) wine_alListener3f
- +@ cdecl alListenerfv(long ptr ) wine_alListenerfv
- +@ cdecl alListeneri(long long ) wine_alListeneri
- +@ cdecl alGetListenerf(long ptr ) wine_alGetListenerf
- +@ cdecl alGetListener3f(long ptr ptr ptr) wine_alGetListener3f
- +@ cdecl alGetListenerfv(long ptr ) wine_alGetListenerfv
- +@ cdecl alGetListeneri(long ptr ) wine_alGetListeneri
- +@ cdecl alGetListeneriv(long ptr ) wine_alGetListeneriv
- +@ cdecl alGenSources(long ptr ) wine_alGenSources
- +@ cdecl alDeleteSources(long ptr ) wine_alDeleteSources
- +@ cdecl alIsSource(long ) wine_alIsSource
- +@ cdecl alSourcef(long long long ) wine_alSourcef
- +@ cdecl alSource3f(long long long long long ) wine_alSource3f
- +@ cdecl alSourcefv(long long ptr ) wine_alSourcefv
- +@ cdecl alSourcei(long long long ) wine_alSourcei
- +@ cdecl alGetSourcef(long long ptr ) wine_alGetSourcef
- +@ cdecl alGetSource3f(long long ptr ptr ptr ) wine_alGetSource3f
- +@ cdecl alGetSourcefv(long long ptr ) wine_alGetSourcefv
- +@ cdecl alGetSourcei(long long ptr ) wine_alGetSourcei
- +@ cdecl alGetSourceiv(long long ptr ) wine_alGetSourceiv
- +@ cdecl alSourcePlayv(long ptr) wine_alSourcePlayv
- +@ cdecl alSourceStopv(long ptr) wine_alSourceStopv
- +@ cdecl alSourceRewindv(long ptr) wine_alSourceRewindv
- +@ cdecl alSourcePausev(long ptr) wine_alSourcePausev
- +@ cdecl alSourcePlay(long ) wine_alSourcePlay
- +@ cdecl alSourceStop(long ) wine_alSourceStop
- +@ cdecl alSourceRewind(long ) wine_alSourceRewind
- +@ cdecl alSourcePause(long ) wine_alSourcePause
- +@ cdecl alSourceQueueBuffers(long long ptr) wine_alSourceQueueBuffers
- +@ cdecl alSourceUnqueueBuffers(long long ptr) wine_alSourceUnqueueBuffers
- +@ cdecl alGenBuffers(long ptr ) wine_alGenBuffers
- +@ cdecl alDeleteBuffers(long ptr ) wine_alDeleteBuffers
- +@ cdecl alIsBuffer(long ) wine_alIsBuffer
- +@ cdecl alBufferData(long long ptr long long ) wine_alBufferData
- +@ cdecl alGetBufferf(long long ptr ) wine_alGetBufferf
- +@ cdecl alGetBufferfv(long long ptr ) wine_alGetBufferfv
- +@ cdecl alGetBufferi(long long ptr ) wine_alGetBufferi
- +@ cdecl alGetBufferiv(long long ptr ) wine_alGetBufferiv
- +@ cdecl alDopplerFactor(long ) wine_alDopplerFactor
- +@ cdecl alDopplerVelocity(long ) wine_alDopplerVelocity
- +@ cdecl alDistanceModel(long ) wine_alDistanceModel
- +#OpenAL ALC_1_1
- +#@ cdecl alcCaptureOpenDevice(str long long long ) wine_alcCaptureOpenDevice
- +#@ cdecl alcCaptureCloseDevice(ptr) wine_alcCaptureCloseDevice
- +#@ cdecl alcCaptureStart(ptr) wine_alcCaptureStart
- +#@ cdecl alcCaptureStop(ptr) wine_alcCaptureStop
- +#@ cdecl alcCaptureSamples(ptr ptr long ) wine_alcCaptureSamples
- +#OpenAL AL_1_1
- +#@ cdecl alListener3i(long long long long ) wine_alListener3i
- +#@ cdecl alListeneriv(long ptr ) wine_alListeneriv
- +#@ cdecl alGetListener3i(long ptr ptr ptr) wine_alGetListener3i
- +#@ cdecl alSource3i(long long long long long ) wine_alSource3i
- +#@ cdecl alSourceiv(long long ptr ) wine_alSourceiv
- +#@ cdecl alGetSource3i(long long ptr ptr ptr ) wine_alGetSource3i
- +#@ cdecl alBufferf(long long long ) wine_alBufferf
- +#@ cdecl alBuffer3f(long long long long long ) wine_alBuffer3f
- +#@ cdecl alBufferfv(long long ptr ) wine_alBufferfv
- +#@ cdecl alBufferi(long long long ) wine_alBufferi
- +#@ cdecl alBuffer3i(long long long long long ) wine_alBuffer3i
- +#@ cdecl alBufferiv(long long ptr ) wine_alBufferiv
- +#@ cdecl alGetBuffer3f(long long ptr ptr ptr ) wine_alGetBuffer3f
- +#@ cdecl alGetBuffer3i(long long ptr ptr ptr ) wine_alGetBuffer3i
- +#@ cdecl alSpeedOfSound(long ) wine_alSpeedOfSound
- +#OpenAL extensions
- +#@ cdecl alcMacOSXRenderingQualityProcPtr(long ) wine_alcMacOSXRenderingQualityProcPtr
- +#@ cdecl alMacOSXRenderChannelCountProcPtr(long ) wine_alMacOSXRenderChannelCountProcPtr
- +#@ cdecl alcMacOSXMixerMaxiumumBussesProcPtr(long ) wine_alcMacOSXMixerMaxiumumBussesProcPtr
- +#@ cdecl alcMacOSXMixerOutputRateProcPtr(double ) wine_alcMacOSXMixerOutputRateProcPtr
- +#@ cdecl alcMacOSXGetRenderingQualityProcPtr() wine_alcMacOSXGetRenderingQualityProcPtr
- +#@ cdecl alMacOSXGetRenderChannelCountProcPtr() wine_alMacOSXGetRenderChannelCountProcPtr
- +#@ cdecl alcMacOSXGetMixerMaxiumumBussesProcPtr() wine_alcMacOSXGetMixerMaxiumumBussesProcPtr
- +#@ cdecl alcMacOSXGetMixerOutputRateProcPtr() wine_alcMacOSXGetMixerOutputRateProcPtr
- +#@ cdecl alBufferDataStatic(long long ptr long long ) wine_alBufferDataStatic
- +#@ cdecl alcASAGetSourceProcPtr(long long ptr ptr ) wine_alcASAGetSourceProcPtr
- +#@ cdecl alcASASetSourceProcPtr(long long ptr long ) wine_alcASASetSourceProcPtr
- +#@ cdecl alcASAGetListenerProcPtr(long ptr ptr ) wine_alcASAGetListenerProcPtr
- +#@ cdecl alcASASetListenerProcPtr(long ptr long ) wine_alcASASetListenerProcPtr
- +#OpenAL ALUT -- now part of freealut -- but binary compat requires this section
- +@ cdecl alutInit ( ptr ptr) wine_alutInit
- +@ cdecl alutExit () wine_alutExit
- +@ cdecl alutLoadWAVFile ( ptr ptr ptr ptr ptr ptr) wine_alutLoadWAVFile
- +@ cdecl alutLoadWAVMemory ( ptr ptr ptr ptr ptr ptr) wine_alutLoadWAVMemory
- +@ cdecl alutUnloadWAV ( long ptr long long) wine_alutUnloadWAV
- +#OpenAL ALUT new
- +#@ cdecl alutInitWithoutContext ( ptr ptr) wine_alutInitWithoutContext
- +#@ cdecl alutGetError () wine_alutGetError
- +#@ cdecl alutGetErrorString ( long) wine_alutGetErrorString
- +#@ cdecl alutCreateBufferFromFile ( ptr) wine_alutCreateBufferFromFile
- +#@ cdecl alutCreateBufferFromFileImage ( ptr long) wine_alutCreateBufferFromFileImage
- +#@ cdecl alutCreateBufferHelloWorld () wine_alutCreateBufferHelloWorld
- +#@ cdecl alutCreateBufferWaveform ( long long long long) wine_alutCreateBufferWaveform
- +#@ cdecl alutLoadMemoryFromFile ( ptr ptr ptr ptr) wine_alutLoadMemoryFromFile
- +#@ cdecl alutLoadMemoryFromFileImage ( ptr long ptr ptr ptr) wine_alutLoadMemoryFromFileImage
- +#@ cdecl alutLoadMemoryHelloWorld ( ptr ptr ptr) wine_alutLoadMemoryHelloWorld
- +#@ cdecl alutLoadMemoryWaveform ( long long long long ptr ptr ptr) wine_alutLoadMemoryWaveform
- +#@ cdecl alutGetMIMETypes ( long) wine_alutGetMIMETypes
- +#@ cdecl alutGetMajorVersion () wine_alutGetMajorVersion
- +#@ cdecl alutGetMinorVersion () wine_alutGetMinorVersion
- +#@ cdecl alutSleep ( long) wine_alutSleep
- diff --git a/dlls/wineopenal.drv/Makefile.in b/dlls/wineopenal.drv/Makefile.in
- new file mode 100644
- index 0000000..0b24659
- --- /dev/null
- +++ b/dlls/wineopenal.drv/Makefile.in
- @@ -0,0 +1,15 @@
- +TOPSRCDIR = @top_srcdir@
- +TOPOBJDIR = ../../..
- +SRCDIR = @srcdir@
- +VPATH = @srcdir@
- +MODULE = wineopenal.drv
- +IMPORTS = winmm user32 kernel32
- +EXTRALIBS = $(LIBUUID) @OPENAL@
- +
- +C_SRCS = \
- + audio.c \
- + openal.c
- +
- +@MAKE_DLL_RULES@
- +
- +### Dependencies:
- diff --git a/dlls/wineopenal.drv/audio.c b/dlls/wineopenal.drv/audio.c
- new file mode 100644
- index 0000000..0d13394
- --- /dev/null
- +++ b/dlls/wineopenal.drv/audio.c
- @@ -0,0 +1,2638 @@
- +/*
- + * Wine Driver for OpenAL
- + * http://www.openal.org
- + *
- + * Copyright 1994 Martin Ayotte
- + * 1999 Eric Pouech (async playing in waveOut/waveIn)
- + * 2000 Eric Pouech (loops in waveOut)
- + * 2004 Zhangrong Huang (EsounD version of this file)
- + * 2006 Nick Burns (OpenAL version of this file)
- + *
- + * This library is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * This library is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with this library; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- + */
- +
- +/*
- + * NOTE: Any problems the ESD driver has this will most likely have.
- + */
- +
- +/*
- + * TODO: Use AL_EXT_STATIC_BUFFER to cut down on mem copies
- + */
- +
- +/*
- + * TODO: Query max number of buffers -- never exceed that max
- + * (PARTIAL FIX): OPENAL_MAX_BUFFERS should be set to the smallest max
- + */
- +
- +/*
- + * (FIXED): There is a problem here in sndrec32.exe
- + * If you play a file and totally keep seeking while its playing
- + * It will keep creating buffers as it thinks many are still in use
- + * However they should not be inuse...
- + *
- + * Note: The above issue is mostly fixed by removing the stop/pause parts from wodReset
- + * -- and limiting the max buffers to OPENAL_MAX_BUFFERS
- + */
- +
- +/*
- + * (FIXED): Determine why sometimes invalid enums and values spew from wodQueueBuffer
- + * This happened because we have run out of buffers .: OPENAL_MAX_BUFFERS
- + */
- +
- +/*
- + * (FIXED): Determine why sometimes invalid device spews from OpenAL_WaveClose
- + * This happened because we just closed the device we were checking errors on
- + */
- +
- +/*
- + * TODO: Test this driver with something other than Mac OSX
- + */
- +
- +/*
- + * TODO: Sleep for a more accurate amount of time if past OPENAL_MAX_BUFFERS
- + * Know which buffer is being processed and wait exactly for it to be finished
- + * Must be able to get current position and track buffers... (maybe timestamps)
- + */
- +
- +#include "config.h"
- +
- +#include <errno.h>
- +#include <math.h>
- +#include <stdlib.h>
- +#include <stdarg.h>
- +#include <stdio.h>
- +#include <string.h>
- +#ifdef HAVE_UNISTD_H
- +# include <unistd.h>
- +#endif
- +#include <fcntl.h>
- +#ifdef HAVE_POLL_H
- +#include <poll.h>
- +#endif
- +#ifdef HAVE_SYS_POLL_H
- +# include <sys/poll.h>
- +#endif
- +
- +#include "windef.h"
- +#include "winbase.h"
- +#include "wingdi.h"
- +#include "winerror.h"
- +#include "wine/winuser16.h"
- +#include "mmddk.h"
- +#include "mmreg.h"
- +#include "dsound.h"
- +#include "dsdriver.h"
- +#include "ks.h"
- +#include "ksguid.h"
- +#include "ksmedia.h"
- +#include "wine/debug.h"
- +
- +#if defined(HAVE_OPENAL_AL_H)
- + #include <OpenAL/al.h>
- + #include <OpenAL/alc.h>
- +#elif defined(HAVE_AL_AL_H)
- + #include <AL/al.h>
- + #include <AL/alc.h>
- +#endif
- +
- +WINE_DEFAULT_DEBUG_CHANNEL(wave);
- +
- +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
- +
- +/* OpenAL 1.1 functions */
- +/* defined as return_type, func_name, params */
- +/* used to define func ptrs, get proc address, etc... */
- +#define OPENAL_1_1_ALC_FUNCS(func)\
- + func(ALCdevice*, alcCaptureOpenDevice, (const ALCbyte *deviceName, ALCuint freq, ALCenum fmt, ALCsizei bufsize))\
- + func(ALCboolean, alcCaptureCloseDevice, (ALCdevice *device))\
- + func(ALCvoid, alcCaptureStart, (ALCdevice *device))\
- + func(ALCvoid, alcCaptureStop, (ALCdevice *device))\
- + func(ALCvoid, alcCaptureSamples, (ALCdevice *device, ALCvoid *buf, ALCsizei samps))
- +
- +#define OPENAL_1_1_AL_FUNCS(func)\
- + func(ALvoid, alListener3i, (ALenum param, ALint v1, ALint v2, ALint v3))\
- + func(ALvoid, alListeneriv, (ALenum param, ALint *values))\
- + func(ALvoid, alGetListener3i, (ALenum param, ALint *v1, ALint *v2, ALint *v3))\
- + func(ALvoid, alSource3i, (ALuint source, ALenum param, ALint v1, ALint v2, ALint v3))\
- + func(ALvoid, alSourceiv, (ALuint source, ALenum param, ALint *values))\
- + func(ALvoid, alGetSource3i, (ALuint source, ALenum param, ALint *v1, ALint *v2, ALint *v3))\
- + func(ALvoid, alBufferf, (ALuint buffer, ALenum param, ALfloat value))\
- + func(ALvoid, alBuffer3f, (ALuint buffer, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3))\
- + func(ALvoid, alBufferfv, (ALuint buffer, ALenum param, ALfloat *values))\
- + func(ALvoid, alBufferi, (ALuint buffer, ALenum param, ALint value))\
- + func(ALvoid, alBuffer3i, (ALuint buffer, ALenum param, ALint v1, ALint v2, ALint v3))\
- + func(ALvoid, alBufferiv, (ALuint buffer, ALenum param, ALint *values))\
- + func(ALvoid, alGetBuffer3f, (ALuint buffer, ALenum pname, ALfloat *v1, ALfloat *v2, ALfloat *v3))\
- + func(ALvoid, alGetBuffer3i, (ALuint buffer, ALenum pname, ALint *v1, ALint *v2, ALint *v3))\
- + func(ALvoid, alSpeedOfSound, (ALfloat value))
- +
- +#define OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(func)\
- + func(ALvoid, alBufferDataStatic, (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq))
- +
- +#define MAKE_FUNC_PTR_TYPE(ret, name, params) typedef ret (*t##name) params;
- +OPENAL_1_1_ALC_FUNCS(MAKE_FUNC_PTR_TYPE);
- +OPENAL_1_1_AL_FUNCS(MAKE_FUNC_PTR_TYPE);
- +OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(MAKE_FUNC_PTR_TYPE);
- +#undef MAKE_FUNC_PTR_TYPE
- +
- +#define MAKE_FUNC_PTR(ret, name, params) static t##name p_##name = NULL;
- +OPENAL_1_1_ALC_FUNCS(MAKE_FUNC_PTR);
- +OPENAL_1_1_AL_FUNCS(MAKE_FUNC_PTR);
- +OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(MAKE_FUNC_PTR);
- +#undef MAKE_FUNC_PTR
- +
- +/* OpenAL 1.1 tokens */
- +/* I dont know which way is better... */
- +/* Since there is a alcGetEnumValue function it seems like thats the best solution */
- +#if 0
- +#ifndef ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
- + #define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
- +#endif
- +#ifndef ALC_CAPTURE_DEVICE_SPECIFIER
- + #define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
- +#endif
- +#ifndef ALC_CAPTURE_SAMPLES
- + #define ALC_CAPTURE_SAMPLES 0x312
- +#endif
- +#else
- +#define OPENAL_1_1_ALC_TOKENS(func)\
- + func(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)\
- + func(ALC_CAPTURE_DEVICE_SPECIFIER)\
- + func(ALC_CAPTURE_SAMPLES)
- +
- +#define MAKE_TOKENS(name) static ALCenum t_##name = ALC_INVALID;
- +OPENAL_1_1_ALC_TOKENS(MAKE_TOKENS);
- +#undef MAKE_TOKENS
- +#endif
- +
- +/* Can we cap audio?? */
- +static int al_can_capture;
- +
- +/* Can use static buffers?? */
- +static int al_static_buffer;
- +
- +/* Enable capture at your own peril -- it SHOULD work and does in certain cases (but I cannot force them) */
- +#define OPENAL_DISABLE_IN (1)
- +#define OPENAL_LIMIT_OUT_44100 (0)
- +#define OPENAL_LIMIT_IN_44100 (0)
- +#define OPENAL_BUF_SIZE (4 * 1024)
- +/* fine tune this for more better goodness */
- +/* too many buffers -- laggggggggggg */
- +/* too few buffers -- fun crackling */
- +/* inf buffers -- not supported but cannot query limits */
- +#define OPENAL_MAX_BUFFERS (4)
- +
- +/* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
- +#define USE_PIPE_SYNC
- +
- +#define BUFFER_REFILL_THRESHOLD 4
- +
- +#define MAX_WAVEOUTDRV (10)
- +#define MAX_WAVEINDRV (10)
- +#define MAX_CHANNELS 2
- +
- +/* state diagram for waveOut writing:
- + *
- + * +---------+-------------+---------------+---------------------------------+
- + * | state | function | event | new state |
- + * +---------+-------------+---------------+---------------------------------+
- + * | | open() | | STOPPED |
- + * | PAUSED | write() | | PAUSED |
- + * | STOPPED | write() | <thrd create> | PLAYING |
- + * | PLAYING | write() | HEADER | PLAYING |
- + * | (other) | write() | <error> | |
- + * | (any) | pause() | PAUSING | PAUSED |
- + * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
- + * | (any) | reset() | RESETTING | STOPPED |
- + * | (any) | close() | CLOSING | CLOSED |
- + * +---------+-------------+---------------+---------------------------------+
- + */
- +
- +/* states of the playing device */
- +#define WINE_WS_PLAYING 0
- +#define WINE_WS_PAUSED 1
- +#define WINE_WS_STOPPED 2
- +#define WINE_WS_CLOSED 3
- +
- +/* events to be send to device */
- +enum win_wm_message {
- + WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
- + WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING
- +};
- +
- +#ifdef USE_PIPE_SYNC
- +#define SIGNAL_OMR(mr) do { int x = 0; write((mr)->msg_pipe[1], &x, sizeof(x)); } while (0)
- +#define CLEAR_OMR(mr) do { int x = 0; read((mr)->msg_pipe[0], &x, sizeof(x)); } while (0)
- +#define RESET_OMR(mr) do { } while (0)
- +#define WAIT_OMR(mr, sleep) \
- + do { struct pollfd pfd; pfd.fd = (mr)->msg_pipe[0]; \
- + pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
- +#else
- +#define SIGNAL_OMR(mr) do { SetEvent((mr)->msg_event); } while (0)
- +#define CLEAR_OMR(mr) do { } while (0)
- +#define RESET_OMR(mr) do { ResetEvent((mr)->msg_event); } while (0)
- +#define WAIT_OMR(mr, sleep) \
- + do { WaitForSingleObject((mr)->msg_event, sleep); } while (0)
- +#endif
- +
- +typedef struct {
- + enum win_wm_message msg; /* message identifier */
- + DWORD param; /* parameter for this message */
- + HANDLE hEvent; /* if message is synchronous, handle of event for synchro */
- +} RING_MSG;
- +
- +/* implement an in-process message ring for better performance
- + * (compared to passing thru the server)
- + * this ring will be used by the input (resp output) record (resp playback) routine
- + */
- +#define ESD_RING_BUFFER_INCREMENT 64
- +typedef struct {
- + RING_MSG* messages;
- + int ring_buffer_size;
- + int msg_tosave;
- + int msg_toget;
- +#ifdef USE_PIPE_SYNC
- + int msg_pipe[2];
- +#else
- + HANDLE msg_event;
- +#endif
- + CRITICAL_SECTION msg_crst;
- +} ESD_MSG_RING;
- +
- +typedef struct {
- + volatile int state; /* one of the WINE_WS_ manifest constants */
- + WAVEOPENDESC waveDesc;
- + WORD wFlags;
- + WAVEFORMATPCMEX waveFormat;
- + WAVEOUTCAPSW caps;
- + char interface_name[32];
- +
- + DWORD dwSleepTime; /* Num of milliseconds to sleep between filling the dsp buffers */
- +
- + /* OpenAL source */
- + int live;
- + ALuint al_source;
- + int num_al_buffers;
- + ALuint* al_buffers;
- + int num_free_al_buffers;
- + ALuint* free_al_buffers;
- +
- + int bytes_per_frame;
- + DWORD dwBufferSize; /* size of whole buffer in bytes */
- +
- + DWORD volume_left; /* volume control information */
- + DWORD volume_right;
- +
- + LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
- + LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
- + DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
- +
- + LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
- + DWORD dwLoops; /* private copy of loop counter */
- +
- + DWORD dwPlayedTotal; /* number of bytes actually played since opening */
- + DWORD dwWrittenTotal; /* number of bytes written to the audio device since opening */
- +
- + /* synchronization stuff */
- + HANDLE hStartUpEvent;
- + HANDLE hThread;
- + DWORD dwThreadID;
- + ESD_MSG_RING msgRing;
- +} WINE_WAVEOUT;
- +
- +typedef struct {
- + volatile int state; /* one of the WINE_WS_ manifest constants */
- + WAVEOPENDESC waveDesc;
- + WORD wFlags;
- + WAVEFORMATPCMEX waveFormat;
- + WAVEINCAPSW caps;
- + char interface_name[32];
- +
- + /* OpenAL capture device */
- + int live;
- + ALCdevice* al_device;
- +
- + int bytes_per_frame;
- +
- + LPWAVEHDR lpQueuePtr;
- + DWORD dwRecordedTotal;
- +
- + /* synchronization stuff */
- + HANDLE hStartUpEvent;
- + HANDLE hThread;
- + DWORD dwThreadID;
- + ESD_MSG_RING msgRing;
- +} WINE_WAVEIN;
- +
- +/* OpenAL context for wave out */
- +static ALCdevice* al_device = NULL;
- +static ALCcontext* al_context = NULL;
- +
- +/* OpenAL error checking (should be able to turn this off for release builds) */
- +#define CHECK_ALC_ERROR()\
- +{\
- + ALenum error;\
- + if(al_device)\
- + {\
- + error = alcGetError(al_device);\
- + if(error)\
- + {\
- + ERR("ALC ERROR: %s at %s:%d\n", alcGetString(al_device, error), __FILE__, __LINE__);\
- + }\
- + }\
- + else\
- + {\
- + ERR("Invalid al device at %s:%d\n", __FILE__, __LINE__);\
- + }\
- +}
- +
- +#define CHECK_AL_ERROR()\
- +{\
- + ALenum error;\
- + error = alGetError();\
- + if(error)\
- + {\
- + ERR("AL ERROR: %s at %s:%d\n", alGetString(error), __FILE__, __LINE__);\
- + }\
- +}
- +
- +static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
- +static WINE_WAVEIN WInDev [MAX_WAVEINDRV];
- +
- +static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
- +static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
- +
- +static void wodDeleteBuffers(WINE_WAVEOUT* wwo);
- +
- +/* These strings used only for tracing */
- +static const char *wodPlayerCmdString[] = {
- + "WINE_WM_PAUSING",
- + "WINE_WM_RESTARTING",
- + "WINE_WM_RESETTING",
- + "WINE_WM_HEADER",
- + "WINE_WM_UPDATE",
- + "WINE_WM_BREAKLOOP",
- + "WINE_WM_CLOSING",
- + "WINE_WM_STARTING",
- + "WINE_WM_STOPPING",
- +};
- +
- +/*======================================================================*
- + * Low level WAVE implementation *
- + *======================================================================*/
- +
- +ALenum al_format_for_wave_format(WAVEFORMATPCMEX* waveFormat)
- +{
- + /* Start with an invalid enum... */
- + ALenum format = AL_INVALID;
- + switch(waveFormat->Format.wBitsPerSample)
- + {
- + case 8:
- + switch(waveFormat->Format.nChannels)
- + {
- + case 1:
- + format = AL_FORMAT_MONO8;
- + break;
- + case 2:
- + format = AL_FORMAT_STEREO8;
- + break;
- + default:
- + FIXME("unsupported waveFormat->Format.nChannels of %d\n", waveFormat->Format.nChannels);
- + break;
- + }
- + break;
- + case 16:
- + switch(waveFormat->Format.nChannels)
- + {
- + case 1:
- + format = AL_FORMAT_MONO16;
- + break;
- + case 2:
- + format = AL_FORMAT_STEREO16;
- + break;
- + default:
- + FIXME("unsupported waveFormat->Format.nChannels of %d\n", waveFormat->Format.nChannels);
- + break;
- + }
- + break;
- + default:
- + FIXME("unsupported waveFormat->Format.wBitsPerSample of %d\n", waveFormat->Format.wBitsPerSample);
- + break;
- + }
- + return format;
- +}
- +
- +#if 0
- +/* Volume functions derived from Alsaplayer source */
- +/* length is the number of 16 bit samples */
- +void volume_effect16(void *bufin, void* bufout, int length, int left,
- + int right, int nChannels)
- +{
- + short *d_out = (short *)bufout;
- + short *d_in = (short *)bufin;
- + int i, v;
- +
- +/*
- + TRACE("length == %d, nChannels == %d\n", length, nChannels);
- +*/
- +
- + if (right == -1) right = left;
- +
- + for(i = 0; i < length; i+=(nChannels))
- + {
- + v = (int) ((*(d_in++) * left) / 100);
- + *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
- + if(nChannels == 2)
- + {
- + v = (int) ((*(d_in++) * right) / 100);
- + *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
- + }
- + }
- +}
- +
- +/* length is the number of 8 bit samples */
- +void volume_effect8(void *bufin, void* bufout, int length, int left,
- + int right, int nChannels)
- +{
- + BYTE *d_out = (BYTE *)bufout;
- + BYTE *d_in = (BYTE *)bufin;
- + int i, v;
- +
- +/*
- + TRACE("length == %d, nChannels == %d\n", length, nChannels);
- +*/
- +
- + if (right == -1) right = left;
- +
- + for(i = 0; i < length; i+=(nChannels))
- + {
- + v = (BYTE) ((*(d_in++) * left) / 100);
- + *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
- + if(nChannels == 2)
- + {
- + v = (BYTE) ((*(d_in++) * right) / 100);
- + *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
- + }
- + }
- +}
- +#endif
- +
- +static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
- + WAVEFORMATPCMEX* format)
- +{
- + TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- + lpTime->wType, format->Format.wBitsPerSample, format->Format.nSamplesPerSec,
- + format->Format.nChannels, format->Format.nAvgBytesPerSec);
- + TRACE("Position in bytes=%lu\n", position);
- +
- + switch (lpTime->wType) {
- + case TIME_SAMPLES:
- + lpTime->u.sample = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
- + TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- + break;
- + case TIME_MS:
- + lpTime->u.ms = 1000.0 * position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels * format->Format.nSamplesPerSec);
- + TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- + break;
- + case TIME_SMPTE:
- + lpTime->u.smpte.fps = 30;
- + position = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
- + position += (format->Format.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
- + lpTime->u.smpte.sec = position / format->Format.nSamplesPerSec;
- + position -= lpTime->u.smpte.sec * format->Format.nSamplesPerSec;
- + lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
- + lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
- + lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
- + lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
- + lpTime->u.smpte.fps = 30;
- + lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->Format.nSamplesPerSec;
- + TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- + lpTime->u.smpte.hour, lpTime->u.smpte.min,
- + lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- + break;
- + default:
- + WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
- + lpTime->wType = TIME_BYTES;
- + /* fall through */
- + case TIME_BYTES:
- + lpTime->u.cb = position;
- + TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- + break;
- + }
- + return MMSYSERR_NOERROR;
- +}
- +
- +static BOOL supportedFormat(LPWAVEFORMATEX wf, int input)
- +{
- + TRACE("(%p)\n",wf);
- +
- + /* Force OpenAL to 44100 */
- + if (((OPENAL_LIMIT_IN_44100 && input) || (OPENAL_LIMIT_OUT_44100 && !input)) && wf->nSamplesPerSec != 44100)
- + return FALSE;
- +
- + if (wf->nSamplesPerSec<DSBFREQUENCY_MIN||wf->nSamplesPerSec>DSBFREQUENCY_MAX)
- + return FALSE;
- +
- + if (wf->wFormatTag == WAVE_FORMAT_PCM) {
- + if (wf->nChannels >= 1 && wf->nChannels <= MAX_CHANNELS) {
- + if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
- + return TRUE;
- + }
- + } else if (wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
- + WAVEFORMATEXTENSIBLE * wfex = (WAVEFORMATEXTENSIBLE *)wf;
- +
- + if (wf->cbSize == 22 && IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
- + if (wf->nChannels >=1 && wf->nChannels <= MAX_CHANNELS) {
- + if (wf->wBitsPerSample==wfex->Samples.wValidBitsPerSample) {
- + if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
- + return TRUE;
- + } else
- + WARN("wBitsPerSample != wValidBitsPerSample not supported yet\n");
- + }
- + } else
- + WARN("only KSDATAFORMAT_SUBTYPE_PCM supported\n");
- + } else
- + WARN("only WAVE_FORMAT_PCM and WAVE_FORMAT_EXTENSIBLE supported\n");
- +
- + return FALSE;
- +}
- +
- +void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2)
- +{
- + ZeroMemory(wf2, sizeof(wf2));
- + if (wf1->wFormatTag == WAVE_FORMAT_PCM)
- + memcpy(wf2, wf1, sizeof(PCMWAVEFORMAT));
- + else if (wf1->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
- + memcpy(wf2, wf1, sizeof(WAVEFORMATPCMEX));
- + else
- + memcpy(wf2, wf1, sizeof(WAVEFORMATEX) + wf1->cbSize);
- +}
- +
- +/******************************************************************
- + * OpenAL_CloseWaveOutDevice
- + *
- + */
- +void OpenAL_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
- +{
- + TRACE("wwo=%p\n", wwo);
- +
- + alDeleteSources(1, &wwo->al_source);
- + CHECK_AL_ERROR();
- + wodDeleteBuffers(wwo);
- + wwo->live = 0;
- +}
- +
- +/******************************************************************
- + * OpenAL_CloseWaveInDevice
- + *
- + */
- +void OpenAL_CloseWaveInDevice(WINE_WAVEIN* wwi)
- +{
- + ALCboolean success;
- + TRACE("wwi=%p\n", wwi);
- +
- + /* recording not supported in OpenAL 1.0 */
- + success = p_alcCaptureCloseDevice(wwi->al_device);
- + if(!success)
- + {
- + ERR("ALC ERROR: Unable to close capture device at %s:%d\n", __FILE__, __LINE__);
- + }
- + wwi->live = 0;
- +}
- +
- +/******************************************************************
- + * OpenAL_WaveClose
- + */
- +LONG OpenAL_WaveClose(void)
- +{
- + /* Cannot check for device close failures on OpenAL 1.0... */
- + /* ALCboolean success; */
- + int iDevice;
- +
- + TRACE("called\n");
- + /* close all open devices */
- + for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
- + {
- + if(WOutDev[iDevice].live)
- + {
- + OpenAL_CloseWaveOutDevice(&WOutDev[iDevice]);
- + }
- + }
- +
- + for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
- + {
- + if(WInDev[iDevice].live)
- + {
- + OpenAL_CloseWaveInDevice(&WInDev[iDevice]);
- + }
- + }
- +
- + alcDestroyContext(al_context);
- + CHECK_ALC_ERROR();
- +
- + /* Cannot check for device close failures on OpenAL 1.0... */
- + alcCloseDevice(al_device);
- + /*success = alcCloseDevice(al_device);
- + if(!success)
- + {
- + ERR("ALC ERROR: Unable to close device at %s:%d\n", __FILE__, __LINE__);
- + }*/
- +
- + return 1;
- +}
- +
- +/******************************************************************
- + * OpenAL_WaveInit
- + *
- + * Initialize internal structures for OpenAL
- + */
- +LONG OpenAL_WaveInit(void)
- +{
- + int i;
- +
- + TRACE("called\n");
- +
- + /* select the "preferred device" */
- + al_device = alcOpenDevice(NULL);
- + TRACE("al_device = %p\n", al_device);
- + CHECK_ALC_ERROR();
- + if(!al_device)
- + {
- + WARN("alcOpenDevice(%p) failed\n", NULL);
- + return -1;
- + }
- + /* Make the best default context */
- + /* TODO: should this use any init params? */
- + al_context = alcCreateContext(al_device, NULL);
- + TRACE("al_context = %p\n", al_context);
- + CHECK_ALC_ERROR();
- + if(!al_context)
- + {
- + return -1;
- + }
- + alcMakeContextCurrent(al_context);
- + CHECK_ALC_ERROR();
- +
- + TRACE("AL_VERSION: %s\n", alGetString(AL_VERSION));
- + /* OpenAL version check */
- + {
- + ALCint major = -1;
- + ALCint minor = -1;
- + alcGetIntegerv(al_device, ALC_MAJOR_VERSION, 1, &major);
- + CHECK_ALC_ERROR();
- + alcGetIntegerv(al_device, ALC_MINOR_VERSION, 1, &minor);
- + CHECK_ALC_ERROR();
- + TRACE("ALC_VERSION: %d.%d\n", major, minor);
- + }
- +
- +/* alcGetProcAddress alGetProcAddress may give warnings about the signedness of the string... this is a bs warning */
- +#define GET_ALC_FUNC_PTR(ret, name, params) p_##name = (t##name)alcGetProcAddress(al_device, #name);
- +#define GET_AL_FUNC_PTR(ret, name, params) p_##name = (t##name)alGetProcAddress(#name);
- + OPENAL_1_1_ALC_FUNCS(GET_ALC_FUNC_PTR);
- + OPENAL_1_1_AL_FUNCS(GET_AL_FUNC_PTR);
- + OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(GET_AL_FUNC_PTR);
- +#undef GET_ALC_FUNC_PTR
- +#undef GET_AL_FUNC_PTR
- +
- +#define GET_TOKENS(name) t_##name = alcGetEnumValue(al_device, #name);
- + OPENAL_1_1_ALC_TOKENS(GET_TOKENS);
- +#undef GET_TOKENS
- +
- +#define HAS_FUNC(ret, name, params) if(p_##name) TRACE("%s is supported\n", #name); else TRACE("%s is not supported\n", #name);
- + OPENAL_1_1_ALC_FUNCS(HAS_FUNC);
- + OPENAL_1_1_AL_FUNCS(HAS_FUNC);
- + OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(HAS_FUNC);
- +#undef HAS_FUNC
- +
- +#define HAS_TOKENS(name) if(t_##name != AL_NONE) TRACE("%s is supported\n", #name); else TRACE("%s is not supported\n", #name);
- + OPENAL_1_1_ALC_TOKENS(HAS_TOKENS);
- +#undef HAS_TOKENS
- +
- + /* creepy yes -- but the 1.1 alc functions are the capture ones... */
- +#define AND_FUNC_PTR(ret, name, params) p_##name &&
- + al_can_capture = OPENAL_1_1_ALC_FUNCS(AND_FUNC_PTR) /* && */ 1;
- + al_static_buffer = OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(AND_FUNC_PTR) /* && */ 1;
- +#undef AND_FUNC_PTR
- + /* still creepy yes -- but the 1.1 alc functions are the capture ones... */
- +#define AND_TOKENS(name) (t_##name != AL_NONE) &&
- + al_can_capture = al_can_capture && OPENAL_1_1_ALC_TOKENS(AND_TOKENS) /* && */ 1;
- +#undef AND_TOKENS
- +
- + /* Why not test the extension as well?? */
- + /* You know its fun... */
- + al_can_capture = al_can_capture && alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE");
- +
- + /* Why not test the extension as well?? */
- + /* We all love extensions... */
- + al_static_buffer = al_static_buffer && alcIsExtensionPresent(NULL, "AL_EXT_STATIC_BUFFER");
- +
- + TRACE("al_can_capture == %d\n", al_can_capture);
- +
- + /* initialize all device handles to -1 */
- + for (i = 0; i < MAX_WAVEOUTDRV; ++i)
- + {
- + static const WCHAR ini[] = {'O','p','e','n','A','L',' ','W','a','v','e','O','u','t','D','r','i','v','e','r',0};
- +
- + WOutDev[i].live = 0;
- + memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps)); /* zero out caps values */
- + WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
- + WOutDev[i].caps.wPid = 0x0001; /* Product ID */
- + lstrcpyW(WOutDev[i].caps.szPname, ini);
- + snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "wineopenal: %d", i);
- +
- + WOutDev[i].caps.vDriverVersion = 0x0100;
- + WOutDev[i].caps.dwFormats = 0x00000000;
- + WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
- +
- + WOutDev[i].caps.wChannels = 2;
- + /* Gain is supported but how do we get independant l/r volume control? */
- + /* WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME; */
- +
- +#if !OPENAL_LIMIT_OUT_44100
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96M08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96S08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96S16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96M16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48M08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48S08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48S16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48M16;
- +#endif
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
- +#if !OPENAL_LIMIT_OUT_44100
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
- + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
- +#endif
- + }
- +
- + for (i = 0; i < MAX_WAVEINDRV; ++i)
- + {
- + static const WCHAR ini[] = {'O','p','e','n','A','L',' ','W','a','v','e','I','n','D','r','i','v','e','r',0};
- +
- + WInDev[i].live = 0;
- + WInDev[i].al_device = NULL;
- + memset(&WInDev[i].caps, 0, sizeof(WInDev[i].caps)); /* zero out caps values */
- + WInDev[i].caps.wMid = 0x00FF;
- + WInDev[i].caps.wPid = 0x0001;
- + lstrcpyW(WInDev[i].caps.szPname, ini);
- + snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "wineopenal: %d", i);
- +
- + WInDev[i].caps.vDriverVersion = 0x0100;
- + WInDev[i].caps.dwFormats = 0x00000000;
- +
- + WInDev[i].caps.wChannels = 2;
- +
- +#if !OPENAL_LIMIT_IN_44100
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96M08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96S08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96S16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96M16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48M08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48S08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48S16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48M16;
- +#endif
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
- +#if !OPENAL_LIMIT_IN_44100
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
- + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
- +#endif
- +
- + WInDev[i].caps.wReserved1 = 0;
- + }
- + return 0;
- +}
- +
- +/******************************************************************
- + * OpenAL_InitRingMessage
- + *
- + * Initialize the ring of messages for passing between driver's caller and playback/record
- + * thread
- + */
- +static int OpenAL_InitRingMessage(ESD_MSG_RING* mr)
- +{
- + mr->msg_toget = 0;
- + mr->msg_tosave = 0;
- +#ifdef USE_PIPE_SYNC
- + if (pipe(mr->msg_pipe) < 0) {
- + mr->msg_pipe[0] = -1;
- + mr->msg_pipe[1] = -1;
- + ERR("could not create pipe, error=%s\n", strerror(errno));
- + }
- +#else
- + mr->msg_event = CreateEventW(NULL, FALSE, FALSE, NULL);
- +#endif
- + mr->ring_buffer_size = ESD_RING_BUFFER_INCREMENT;
- + mr->messages = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,mr->ring_buffer_size * sizeof(RING_MSG));
- + InitializeCriticalSection(&mr->msg_crst);
- + mr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)"WINEOpenAL_msg_crst";
- + return 0;
- +}
- +
- +/******************************************************************
- + * OpenAL_DestroyRingMessage
- + *
- + */
- +static int OpenAL_DestroyRingMessage(ESD_MSG_RING* mr)
- +{
- + TRACE("mr=%p\n", mr);
- +#ifdef USE_PIPE_SYNC
- + close(mr->msg_pipe[0]);
- + close(mr->msg_pipe[1]);
- +#else
- + CloseHandle(mr->msg_event);
- +#endif
- + HeapFree(GetProcessHeap(),0,mr->messages);
- + mr->messages=NULL;
- + DeleteCriticalSection(&mr->msg_crst);
- + return 0;
- +}
- +
- +/******************************************************************
- + * OpenAL_AddRingMessage
- + *
- + * Inserts a new message into the ring (should be called from DriverProc derivated routines)
- + */
- +static int OpenAL_AddRingMessage(ESD_MSG_RING* mr, enum win_wm_message msg, DWORD param, BOOL wait)
- +{
- + HANDLE hEvent = INVALID_HANDLE_VALUE;
- + TRACE("mr=%p, msg=%d, param=%08X, wait=%d\n", mr, msg, (unsigned int)param, wait);
- +
- + EnterCriticalSection(&mr->msg_crst);
- + if ((mr->msg_toget == ((mr->msg_tosave + 1) % mr->ring_buffer_size)))
- + {
- + int old_ring_buffer_size = mr->ring_buffer_size;
- + mr->ring_buffer_size += ESD_RING_BUFFER_INCREMENT;
- + TRACE("mr->ring_buffer_size=%d\n",mr->ring_buffer_size);
- + mr->messages = HeapReAlloc(GetProcessHeap(),0,mr->messages, mr->ring_buffer_size * sizeof(RING_MSG));
- + /* Now we need to rearrange the ring buffer so that the new
- + buffers just allocated are in between mr->msg_tosave and
- + mr->msg_toget.
- + */
- + if (mr->msg_tosave < mr->msg_toget)
- + {
- + memmove(&(mr->messages[mr->msg_toget + ESD_RING_BUFFER_INCREMENT]),
- + &(mr->messages[mr->msg_toget]),
- + sizeof(RING_MSG)*(old_ring_buffer_size - mr->msg_toget)
- + );
- + mr->msg_toget += ESD_RING_BUFFER_INCREMENT;
- + }
- + }
- + if (wait)
- + {
- + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- + if (hEvent == INVALID_HANDLE_VALUE)
- + {
- + ERR("can't create event !?\n");
- + LeaveCriticalSection(&mr->msg_crst);
- + return 0;
- + }
- + if (mr->msg_toget != mr->msg_tosave && mr->messages[mr->msg_toget].msg != WINE_WM_HEADER)
- + FIXME("two fast messages in the queue!!!!\n");
- +
- + /* fast messages have to be added at the start of the queue */
- + mr->msg_toget = (mr->msg_toget + mr->ring_buffer_size - 1) % mr->ring_buffer_size;
- +
- + mr->messages[mr->msg_toget].msg = msg;
- + mr->messages[mr->msg_toget].param = param;
- + mr->messages[mr->msg_toget].hEvent = hEvent;
- + }
- + else
- + {
- + mr->messages[mr->msg_tosave].msg = msg;
- + mr->messages[mr->msg_tosave].param = param;
- + mr->messages[mr->msg_tosave].hEvent = INVALID_HANDLE_VALUE;
- + mr->msg_tosave = (mr->msg_tosave + 1) % mr->ring_buffer_size;
- + }
- +
- + LeaveCriticalSection(&mr->msg_crst);
- +
- + /* signal a new message */
- + SIGNAL_OMR(mr);
- + if (wait)
- + {
- + /* wait for playback/record thread to have processed the message */
- + WaitForSingleObject(hEvent, INFINITE);
- + CloseHandle(hEvent);
- + }
- +
- + return 1;
- +}
- +
- +/******************************************************************
- + * OpenAL_RetrieveRingMessage
- + *
- + * Get a message from the ring. Should be called by the playback/record thread.
- + */
- +static int OpenAL_RetrieveRingMessage(ESD_MSG_RING* mr,
- + enum win_wm_message *msg, DWORD *param, HANDLE *hEvent)
- +{
- + EnterCriticalSection(&mr->msg_crst);
- +
- + if (mr->msg_toget == mr->msg_tosave) /* buffer empty ? */
- + {
- + LeaveCriticalSection(&mr->msg_crst);
- + return 0;
- + }
- +
- + *msg = mr->messages[mr->msg_toget].msg;
- + mr->messages[mr->msg_toget].msg = 0;
- + *param = mr->messages[mr->msg_toget].param;
- + *hEvent = mr->messages[mr->msg_toget].hEvent;
- + mr->msg_toget = (mr->msg_toget + 1) % mr->ring_buffer_size;
- + CLEAR_OMR(mr);
- + LeaveCriticalSection(&mr->msg_crst);
- + return 1;
- +}
- +
- +/*======================================================================*
- + * Low level WAVE OUT implementation *
- + *======================================================================*/
- +
- +/**************************************************************************
- + * wodPrintBuffers [internal]
- + */
- +static void wodPrintBuffers(WINE_WAVEOUT* wwo)
- +{
- + int onBuffer;
- +
- + TRACE("-----------\n");
- + TRACE("wwo->num_al_buffers=%d\n", wwo->num_al_buffers);
- + TRACE("wwo->num_free_al_buffers=%d\n", wwo->num_free_al_buffers);
- + for(onBuffer = 0; onBuffer < wwo->num_al_buffers; onBuffer++)
- + {
- + int onFreeBuffer;
- + int free = 0;
- +
- + for(onFreeBuffer = 0; onFreeBuffer < wwo->num_free_al_buffers; onFreeBuffer++)
- + {
- + free = free || (wwo->free_al_buffers[onFreeBuffer] == wwo->al_buffers[onBuffer]);
- + }
- + TRACE("buffer[%d] buf=%d free=%d\n", onBuffer, wwo->al_buffers[onBuffer], free);
- + }
- + TRACE("-----------\n");
- +}
- +
- +/**************************************************************************
- + * wodAddBuffer [internal]
- + */
- +static void wodAddBuffer(WINE_WAVEOUT* wwo)
- +{
- + wwo->num_al_buffers++;
- + /* HeapReAlloc does not work like realloc... realloc on null is a malloc... */
- + /* This starts with 1 entry (an ignored one) */
- + wwo->al_buffers = (ALuint*)HeapReAlloc(GetProcessHeap(), 0, wwo->al_buffers, wwo->num_al_buffers * sizeof(ALuint));
- +
- + alGenBuffers(1, &wwo->al_buffers[wwo->num_al_buffers - 1]);
- + CHECK_AL_ERROR();
- + TRACE("added buffer #%d == %d\n", wwo->num_al_buffers - 1, wwo->al_buffers[wwo->num_al_buffers - 1]);
- +}
- +
- +/**************************************************************************
- + * wodGetFreeBuffer [internal]
- + */
- +static ALuint wodGetFreeBuffer(WINE_WAVEOUT* wwo)
- +{
- + ALint processed;
- + ALuint freeBuffer;
- +
- + int found = 0;
- + while(!found)
- + {
- + if(wwo->num_free_al_buffers)
- + {
- + wwo->num_free_al_buffers--;
- + freeBuffer = wwo->free_al_buffers[wwo->num_free_al_buffers];
- +
- + TRACE("Found free buffer %d\n", freeBuffer);
- + found = 1;
- + }
- + else
- + {
- + alGetSourcei(wwo->al_source, AL_BUFFERS_PROCESSED, &processed);
- + CHECK_AL_ERROR();
- + TRACE("Found %d processed buffers\n", processed);
- +
- + if(processed)
- + {
- + wwo->num_free_al_buffers = processed;
- + /* HeapReAlloc does not work like realloc... realloc on null is a malloc... */
- + /* This starts with 1 entry (an ignored one) */
- + wwo->free_al_buffers = (ALuint*)HeapReAlloc(GetProcessHeap(), 0, wwo->free_al_buffers, wwo->num_free_al_buffers * sizeof(ALuint));
- +
- + alSourceUnqueueBuffers(wwo->al_source, processed, wwo->free_al_buffers);
- + CHECK_AL_ERROR();
- +
- + TRACE("Freed %d buffers\n", processed);
- + }
- + else
- + {
- + if(wwo->num_al_buffers < OPENAL_MAX_BUFFERS)
- + {
- + /* no free buffer -- add one and return that */
- + wodAddBuffer(wwo);
- + freeBuffer = wwo->al_buffers[wwo->num_al_buffers - 1];
- + TRACE("No free buffers\n");
- + TRACE("Made new buffer %d\n", freeBuffer);
- + found = 1;
- + }
- + else
- + {
- + TRACE("No free buffers -- reached max -- waiting\n");
- + /* Sleep for a more valid amount of time? */
- + usleep(1000);
- + }
- + }
- + }
- + }
- + return freeBuffer;
- +}
- +
- +/**************************************************************************
- + * wodQueueBuffer [internal]
- + */
- +static void wodQueueBuffer(WINE_WAVEOUT* wwo, void* data, int toWrite)
- +{
- + ALuint freeBuffer;
- +
- + TRACE("Buffers before queue\n");
- + wodPrintBuffers(wwo);
- +
- + freeBuffer = wodGetFreeBuffer(wwo);
- + TRACE("Found %d free buffer\n", freeBuffer);
- +
- + /* send the audio data to OpenAL for playing */
- + {
- + ALenum format = al_format_for_wave_format(&wwo->waveFormat);
- + ALsizei freq = wwo->waveFormat.Format.nSamplesPerSec;
- +
- + if(al_static_buffer)
- + {
- + p_alBufferDataStatic(freeBuffer, format, data, toWrite, freq);
- + TRACE("alBufferDataStatic(freeBuffer=%d, format=%08x, data=%p, toWrite=%d, freq=%d)\n", freeBuffer, format, data, toWrite, freq);
- + }
- + else
- + {
- + alBufferData(freeBuffer, format, data, toWrite, freq);
- + TRACE("alBufferData(freeBuffer=%d, format=%08x, data=%p, toWrite=%d, freq=%d)\n", freeBuffer, format, data, toWrite, freq);
- + }
- + CHECK_AL_ERROR();
- + }
- +
- + /* Queue up the buffer */
- + alSourceQueueBuffers(wwo->al_source, 1, &freeBuffer);
- + CHECK_AL_ERROR();
- +
- + TRACE("Buffers after queue\n");
- + wodPrintBuffers(wwo);
- +}
- +
- +/**************************************************************************
- + * wodDeleteBuffers [internal]
- + */
- +static void wodDeleteBuffers(WINE_WAVEOUT* wwo)
- +{
- + alDeleteBuffers(wwo->num_al_buffers, wwo->al_buffers);
- + CHECK_AL_ERROR();
- +
- + /* There is always at least 1 of each of these */
- + HeapFree(GetProcessHeap(), 0, wwo->al_buffers);
- + HeapFree(GetProcessHeap(), 0, wwo->free_al_buffers);
- +}
- +
- +/**************************************************************************
- + * wodNotifyClient [internal]
- + */
- +static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
- +{
- + TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
- +
- + switch (wMsg) {
- + case WOM_OPEN:
- + case WOM_CLOSE:
- + case WOM_DONE:
- + if (wwo->wFlags != DCB_NULL &&
- + !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags, (HDRVR)wwo->waveDesc.hWave,
- + wMsg, wwo->waveDesc.dwInstance, dwParam1, dwParam2)) {
- + WARN("can't notify client !\n");
- + return MMSYSERR_ERROR;
- + }
- + break;
- + default:
- + FIXME("Unknown callback message %u\n", wMsg);
- + return MMSYSERR_INVALPARAM;
- + }
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodUpdatePlayedTotal [internal]
- + *
- + */
- +static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo)
- +{
- + /* total played is the bytes written less the bytes to write ;-) */
- + wwo->dwPlayedTotal = wwo->dwWrittenTotal;
- +
- + return TRUE;
- +}
- +
- +/**************************************************************************
- + * wodPlayer_BeginWaveHdr [internal]
- + *
- + * Makes the specified lpWaveHdr the currently playing wave header.
- + * If the specified wave header is a begin loop and we're not already in
- + * a loop, setup the loop.
- + */
- +static void wodPlayer_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
- +{
- + wwo->lpPlayPtr = lpWaveHdr;
- +
- + if (!lpWaveHdr) return;
- +
- + if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP) {
- + if (wwo->lpLoopPtr) {
- + WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
- + TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
- + } else {
- + TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
- + wwo->lpLoopPtr = lpWaveHdr;
- + /* Windows does not touch WAVEHDR.dwLoops,
- + * so we need to make an internal copy */
- + wwo->dwLoops = lpWaveHdr->dwLoops;
- + }
- + }
- + wwo->dwPartialOffset = 0;
- +}
- +
- +/**************************************************************************
- + * wodPlayer_PlayPtrNext [internal]
- + *
- + * Advance the play pointer to the next waveheader, looping if required.
- + */
- +static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEOUT* wwo)
- +{
- + LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
- +
- + wwo->dwPartialOffset = 0;
- + if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr) {
- + /* We're at the end of a loop, loop if required */
- + if (--wwo->dwLoops > 0) {
- + wwo->lpPlayPtr = wwo->lpLoopPtr;
- + } else {
- + /* Handle overlapping loops correctly */
- + if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
- + FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
- + /* shall we consider the END flag for the closing loop or for
- + * the opening one or for both ???
- + * code assumes for closing loop only
- + */
- + } else {
- + lpWaveHdr = lpWaveHdr->lpNext;
- + }
- + wwo->lpLoopPtr = NULL;
- + wodPlayer_BeginWaveHdr(wwo, lpWaveHdr);
- + }
- + } else {
- + /* We're not in a loop. Advance to the next wave header */
- + wodPlayer_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
- + }
- +
- + return lpWaveHdr;
- +}
- +
- +/**************************************************************************
- + * wodPlayer_NotifyWait [internal]
- + * Returns the number of milliseconds to wait before attempting to notify
- + * completion of the specified wavehdr.
- + * This is based on the number of bytes remaining to be written in the
- + * wave.
- + */
- +static DWORD wodPlayer_NotifyWait(const WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
- +{
- + DWORD dwMillis;
- +
- + if(lpWaveHdr->reserved < wwo->dwPlayedTotal)
- + {
- + dwMillis = 1;
- + }
- + else
- + {
- + dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->waveFormat.Format.nAvgBytesPerSec;
- + if(!dwMillis) dwMillis = 1;
- + }
- +
- + TRACE("dwMillis = %ld\n", dwMillis);
- +
- + return dwMillis;
- +}
- +
- +/**************************************************************************
- + * wodPlayer_WriteMaxFrags [internal]
- + * Writes the maximum number of bytes possible to the DSP and returns
- + * the number of bytes written.
- + */
- +static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
- +{
- + /* Only attempt to write to free bytes */
- + DWORD dwLength = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
- + int toWrite = min(dwLength, *bytes);
- + int written;
- +
- + TRACE("Writing wavehdr %p.%lu[%lu]\n",
- + wwo->lpPlayPtr, wwo->dwPartialOffset, wwo->lpPlayPtr->dwBufferLength);
- +#if 0
- +/* TODO: use the OpenAL buffer for this... */
- + /* see if our buffer isn't large enough for the data we are writing */
- + if(wwo->buffer_size < toWrite)
- + {
- + if(wwo->sound_buffer)
- + {
- + wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, toWrite);
- + wwo->buffer_size = toWrite;
- + }
- + }
- +
- +/* TODO: use the OpenAL buffer for this... */
- + /* if we don't have a buffer then get one */
- + if(!wwo->sound_buffer)
- + {
- + /* allocate some memory for the buffer */
- + wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, toWrite);
- + wwo->buffer_size = toWrite;
- + }
- +
- + /* if we don't have a buffer then error out */
- + if(!wwo->sound_buffer)
- + {
- + ERR("error allocating sound_buffer memory\n");
- + return 0;
- + }
- +
- + TRACE("toWrite == %d\n", toWrite);
- +
- +/* TODO: use OpenAL gain for this... */
- + /* apply volume to the bits */
- + /* for single channel audio streams we only use the LEFT volume */
- + if(wwo->waveFormat.Format.wBitsPerSample == 16)
- + {
- + /* apply volume to the buffer we are about to send */
- + /* divide toWrite(bytes) by 2 as volume processes by 16 bits */
- + volume_effect16(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
- + wwo->sound_buffer, toWrite>>1, wwo->volume_left,
- + wwo->volume_right, wwo->waveFormat.Format.nChannels);
- + } else if(wwo->waveFormat.Format.wBitsPerSample == 8)
- + {
- + /* apply volume to the buffer we are about to send */
- + volume_effect8(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
- + wwo->sound_buffer, toWrite, wwo->volume_left,
- + wwo->volume_right, wwo->waveFormat.Format.nChannels);
- + } else
- + {
- + FIXME("unsupported wwo->format.wBitsPerSample of %d\n",
- + wwo->waveFormat.Format.wBitsPerSample);
- + }
- +
- + TRACE("al_device=%p,al_context=%p,wwo->al_buffer=%d,wwo->al_source=%d\n", al_device, al_context, wwo->al_buffer, wwo->al_source);
- + /* send the audio data to OpenAL for playing */
- + ALenum format = al_format_for_wave_format(&wwo->waveFormat);
- + ALsizei freq = wwo->waveFormat.Format.nSamplesPerSec;
- +
- + wodQueueBuffer(wwo, wwo->sound_buffer, toWrite);
- +
- + /* Continue playing... */
- + {
- + ALint state;
- + alGetSourcei(wwo->al_source, AL_SOURCE_STATE, &state);
- + CHECK_AL_ERROR();
- + if(state != AL_PLAYING)
- + {
- + alSourcePlay(wwo->al_source);
- + CHECK_AL_ERROR();
- + }
- + }
- + written = toWrite;
- +#else
- + /* Modify the gain... needs fixing (no right/left control) */
- + /* No pain... no gain? */
- + {
- + ALfloat gain = (ALfloat)max(wwo->volume_left, wwo->volume_right) / 100.0f;
- + /* TODO: control the left/right audio separately */
- + alSourcef(wwo->al_source, AL_GAIN, gain);
- + CHECK_AL_ERROR();
- + }
- + TRACE("al_device=%p,wwo->al_buffers=%p,wwo->al_source=%d\n", al_device, wwo->al_buffers, wwo->al_source);
- + /* send the audio data to OpenAL for playing */
- + wodQueueBuffer(wwo, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
- +
- + /* Continue playing... */
- + {
- + ALint state;
- + alGetSourcei(wwo->al_source, AL_SOURCE_STATE, &state);
- + CHECK_AL_ERROR();
- + if(state != AL_PLAYING)
- + {
- + alSourcePlay(wwo->al_source);
- + CHECK_AL_ERROR();
- + }
- + }
- + written = toWrite;
- +#endif
- + TRACE("written = %d\n", written);
- +
- + if (written <= 0)
- + {
- + *bytes = 0; /* REMOVE COMMENT: apparently esd is actually full */
- + return written; /* if we wrote nothing just return */
- + }
- +
- + if (written >= dwLength)
- + wodPlayer_PlayPtrNext(wwo); /* If we wrote all current wavehdr, skip to the next one */
- + else
- + wwo->dwPartialOffset += written; /* Remove the amount written */
- +
- + if (written < toWrite)
- + *bytes = 0;
- + else
- + *bytes -= written;
- +
- + wwo->dwWrittenTotal += written; /* update stats on this wave device */
- +
- + return written; /* return the number of bytes written */
- +}
- +
- +/**************************************************************************
- + * wodPlayer_NotifyCompletions [internal]
- + *
- + * Notifies and remove from queue all wavehdrs which have been played to
- + * the speaker (ie. they have cleared the audio device). If force is true,
- + * we notify all wavehdrs and remove them all from the queue even if they
- + * are unplayed or part of a loop.
- + */
- +static DWORD wodPlayer_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
- +{
- + LPWAVEHDR lpWaveHdr;
- +
- + if (wwo->lpQueuePtr) {
- + TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), reserved=(%ld), dwWrittenTotal=(%ld), force=(%d)\n",
- + wwo->lpQueuePtr,
- + wwo->lpPlayPtr,
- + wwo->lpLoopPtr,
- + wwo->lpQueuePtr->reserved,
- + wwo->dwWrittenTotal,
- + force);
- + } else {
- + TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), dwWrittenTotal=(%ld), force=(%d)\n",
- + wwo->lpQueuePtr,
- + wwo->lpPlayPtr,
- + wwo->lpLoopPtr,
- + wwo->dwWrittenTotal,
- + force);
- + }
- +
- + /* Start from lpQueuePtr and keep notifying until:
- + * - we hit an unwritten wavehdr
- + * - we hit the beginning of a running loop
- + * - we hit a wavehdr which hasn't finished playing
- + */
- + while ((lpWaveHdr = wwo->lpQueuePtr) &&
- + (force ||
- + (lpWaveHdr != wwo->lpPlayPtr &&
- + lpWaveHdr != wwo->lpLoopPtr &&
- + lpWaveHdr->reserved <= wwo->dwWrittenTotal))) {
- +
- + wwo->lpQueuePtr = lpWaveHdr->lpNext;
- +
- + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
- + lpWaveHdr->dwFlags |= WHDR_DONE;
- +
- + wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
- + }
- + return (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != wwo->lpLoopPtr) ?
- + wodPlayer_NotifyWait(wwo, lpWaveHdr) : INFINITE;
- +}
- +
- +/**************************************************************************
- + * wodPlayer_Reset [internal]
- + *
- + * wodPlayer helper. Resets current output stream.
- + */
- +static void wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
- +{
- + wodUpdatePlayedTotal(wwo);
- +
- + wodPlayer_NotifyCompletions(wwo, FALSE); /* updates current notify list */
- +
- + /* REMOVE COMMENT: we aren't able to flush any data that has already been written */
- + /* to esd, otherwise we would do the flushing here */
- +
- + if (reset) {
- + enum win_wm_message msg;
- + DWORD param;
- + HANDLE ev;
- +
- + /* stop OpenAL on this wod */
- + /*TRACE("alSourceStop(%d)\n", wwo->al_source);
- + alSourceStop(wwo->al_source);
- + CHECK_AL_ERROR();*/
- +
- + /* remove any buffer */
- + wodPlayer_NotifyCompletions(wwo, TRUE);
- +
- + wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
- + wwo->state = WINE_WS_STOPPED;
- + wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
- +
- + wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
- +
- + /* remove any existing message in the ring */
- + EnterCriticalSection(&wwo->msgRing.msg_crst);
- +
- + /* return all pending headers in queue */
- + while (OpenAL_RetrieveRingMessage(&wwo->msgRing, &msg, ¶m, &ev))
- + {
- + TRACE("flushing msg\n");
- + if (msg != WINE_WM_HEADER)
- + {
- + FIXME("shouldn't have headers left\n");
- + SetEvent(ev);
- + continue;
- + }
- + ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
- + ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;
- +
- + wodNotifyClient(wwo, WOM_DONE, param, 0);
- + }
- + RESET_OMR(&wwo->msgRing);
- + LeaveCriticalSection(&wwo->msgRing.msg_crst);
- + } else {
- + /* Not sure about this ones interaction with OpenAL */
- + /* It seems like Pausing causes lots of ... problems */
- +
- + /* pause OpenAL on this wod */
- + /*TRACE("alSourcePause(%d)\n", wwo->al_source);
- + alSourcePause(wwo->al_source);
- + CHECK_AL_ERROR();*/
- +
- + /* stop OpenAL on this wod */
- + /*TRACE("alSourceStop(%d)\n", wwo->al_source);
- + alSourceStop(wwo->al_source);
- + CHECK_AL_ERROR();*/
- +
- + if (wwo->lpLoopPtr) {
- + /* complicated case, not handled yet (could imply modifying the loop counter */
- + FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
- + wwo->lpPlayPtr = wwo->lpLoopPtr;
- + wwo->dwPartialOffset = 0;
- + wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
- + } else {
- + /* the data already written is going to be played, so take */
- + /* this fact into account here */
- + wwo->dwPlayedTotal = wwo->dwWrittenTotal;
- + }
- + wwo->state = WINE_WS_PAUSED;
- + }
- +}
- +
- +/**************************************************************************
- + * wodPlayer_ProcessMessages [internal]
- + */
- +static void wodPlayer_ProcessMessages(WINE_WAVEOUT* wwo)
- +{
- + LPWAVEHDR lpWaveHdr;
- + enum win_wm_message msg;
- + DWORD param;
- + HANDLE ev;
- +
- + while (OpenAL_RetrieveRingMessage(&wwo->msgRing, &msg, ¶m, &ev)) {
- + TRACE("Received %s %lx\n", wodPlayerCmdString[msg - WM_USER - 1], param);
- + switch (msg) {
- + case WINE_WM_PAUSING:
- + wodPlayer_Reset(wwo, FALSE);
- + SetEvent(ev);
- + break;
- + case WINE_WM_RESTARTING:
- + wwo->state = WINE_WS_PLAYING;
- + SetEvent(ev);
- + break;
- + case WINE_WM_HEADER:
- + lpWaveHdr = (LPWAVEHDR)param;
- +
- + /* insert buffer at the end of queue */
- + {
- + LPWAVEHDR* wh;
- + for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
- + *wh = lpWaveHdr;
- + }
- + if (!wwo->lpPlayPtr)
- + wodPlayer_BeginWaveHdr(wwo,lpWaveHdr);
- + if (wwo->state == WINE_WS_STOPPED)
- + wwo->state = WINE_WS_PLAYING;
- + break;
- + case WINE_WM_RESETTING:
- + wodPlayer_Reset(wwo, TRUE);
- + SetEvent(ev);
- + break;
- + case WINE_WM_UPDATE:
- + wodUpdatePlayedTotal(wwo);
- + SetEvent(ev);
- + break;
- + case WINE_WM_BREAKLOOP:
- + if (wwo->state == WINE_WS_PLAYING && wwo->lpLoopPtr != NULL) {
- + /* ensure exit at end of current loop */
- + wwo->dwLoops = 1;
- + }
- + SetEvent(ev);
- + break;
- + case WINE_WM_CLOSING:
- + /* sanity check: this should not happen since the device must have been reset before */
- + if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
- + wwo->hThread = 0;
- + wwo->state = WINE_WS_CLOSED;
- + SetEvent(ev);
- + TRACE("Killing Thread ... how?\n");
- + ExitThread(0);
- + /* shouldn't go here */
- + default:
- + FIXME("unknown message %d\n", msg);
- + break;
- + }
- + }
- +}
- +
- +/**************************************************************************
- + * wodPlayer_FeedDSP [internal]
- + * Feed as much sound data as we can into the DSP and return the number of
- + * milliseconds before it will be necessary to feed the DSP again.
- + */
- +static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
- +{
- + DWORD availInQ;
- +
- + wodUpdatePlayedTotal(wwo);
- + /* better way to set availInQ? */
- + availInQ = OPENAL_BUF_SIZE;
- + TRACE("availInQ = %ld\n", availInQ);
- +
- + /* input queue empty */
- + if (!wwo->lpPlayPtr) {
- + TRACE("Run out of wavehdr:s... flushing\n");
- + return INFINITE;
- + }
- +
- +#if 0
- + /* no more room... no need to try to feed */
- + if(!availInQ)
- + {
- + TRACE("no more room, no need to try to feed\n");
- + return wwo->dwSleepTime;
- + }
- +#endif
- +
- + /* Feed from partial wavehdr */
- + if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0)
- + {
- + TRACE("feeding from partial wavehdr\n");
- + wodPlayer_WriteMaxFrags(wwo, &availInQ);
- + }
- +
- + /* Feed wavehdrs until we run out of wavehdrs or DSP space */
- + if (!wwo->dwPartialOffset)
- + {
- + while(wwo->lpPlayPtr && availInQ)
- + {
- + TRACE("feeding waveheaders until we run out of space\n");
- + /* note the value that dwPlayedTotal will return when this wave finishes playing */
- + wwo->lpPlayPtr->reserved = wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength;
- + TRACE("reserved=(%ld) dwWrittenTotal=(%ld) dwBufferLength=(%ld)\n",
- + wwo->lpPlayPtr->reserved,
- + wwo->dwWrittenTotal,
- + wwo->lpPlayPtr->dwBufferLength
- + );
- + wodPlayer_WriteMaxFrags(wwo, &availInQ);
- + }
- + }
- +
- + if (!wwo->lpPlayPtr) {
- + TRACE("Ran out of wavehdrs\n");
- + return INFINITE;
- + }
- +
- + return wwo->dwSleepTime;
- +}
- +
- +/**************************************************************************
- + * wodPlayer [internal]
- + */
- +static DWORD CALLBACK wodPlayer(LPVOID pmt)
- +{
- + WORD uDevID = (DWORD)pmt;
- + WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)&WOutDev[uDevID];
- + DWORD dwNextFeedTime = INFINITE; /* Time before DSP needs feeding */
- + DWORD dwNextNotifyTime = INFINITE; /* Time before next wave completion */
- + DWORD dwSleepTime;
- +
- + wwo->state = WINE_WS_STOPPED;
- + SetEvent(wwo->hStartUpEvent);
- +
- + for (;;) {
- + /** Wait for the shortest time before an action is required. If there
- + * are no pending actions, wait forever for a command.
- + */
- + dwSleepTime = min(dwNextFeedTime, dwNextNotifyTime);
- + TRACE("waiting %lums (%lu,%lu)\n", dwSleepTime, dwNextFeedTime, dwNextNotifyTime);
- + WAIT_OMR(&wwo->msgRing, dwSleepTime);
- + wodPlayer_ProcessMessages(wwo);
- + if (wwo->state == WINE_WS_PLAYING) {
- + dwNextFeedTime = wodPlayer_FeedDSP(wwo);
- + dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE);
- + } else {
- + dwNextFeedTime = dwNextNotifyTime = INFINITE;
- + }
- + }
- +}
- +
- +/**************************************************************************
- + * wodGetDevCaps [internal]
- + */
- +static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize)
- +{
- + TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
- +
- + if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
- +
- + if (wDevID >= MAX_WAVEOUTDRV) {
- + TRACE("MAX_WAVOUTDRV reached !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodOpen [internal]
- + */
- +static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
- +{
- + WINE_WAVEOUT* wwo;
- +
- + TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
- + if (lpDesc == NULL) {
- + WARN("Invalid Parameter !\n");
- + return MMSYSERR_INVALPARAM;
- + }
- + if (wDevID >= MAX_WAVEOUTDRV) {
- + TRACE("MAX_WAVOUTDRV reached !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + /* if this device is already open tell the app that it is allocated */
- + if(WOutDev[wDevID].live)
- + {
- + TRACE("device already allocated\n");
- + return MMSYSERR_ALLOCATED;
- + }
- +
- + /* only PCM format is supported so far... */
- + if (!supportedFormat(lpDesc->lpFormat, 0)) {
- + WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
- + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
- + lpDesc->lpFormat->nSamplesPerSec);
- + return WAVERR_BADFORMAT;
- + }
- +
- + if (dwFlags & WAVE_FORMAT_QUERY) {
- + TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
- + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
- + lpDesc->lpFormat->nSamplesPerSec);
- + return MMSYSERR_NOERROR;
- + }
- +
- + wwo = &WOutDev[wDevID];
- +
- + /* direct sound not supported, ignore the flag */
- + dwFlags &= ~WAVE_DIRECTSOUND;
- +
- + wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- +
- + memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
- + copy_format(lpDesc->lpFormat, &wwo->waveFormat);
- +
- + if (wwo->waveFormat.Format.wBitsPerSample == 0) {
- + WARN("Resetting zeroed wBitsPerSample\n");
- + wwo->waveFormat.Format.wBitsPerSample = 8 *
- + (wwo->waveFormat.Format.nAvgBytesPerSec /
- + wwo->waveFormat.Format.nSamplesPerSec) /
- + wwo->waveFormat.Format.nChannels;
- + }
- +
- + wwo->bytes_per_frame = (wwo->waveFormat.Format.wBitsPerSample * wwo->waveFormat.Format.nChannels) / 8;
- +
- + /* output to OpenAL... */
- + wwo->live = 1;
- + alGenSources(1, &wwo->al_source);
- + CHECK_AL_ERROR();
- +
- + wwo->num_al_buffers = 0;
- + wwo->al_buffers = (ALuint*)HeapAlloc(GetProcessHeap(), 0, sizeof(ALuint));
- + wwo->num_free_al_buffers = 0;
- + wwo->free_al_buffers = (ALuint*)HeapAlloc(GetProcessHeap(), 0, sizeof(ALuint));
- +
- + if(!wwo->live) return MMSYSERR_ALLOCATED;
- +
- + wwo->dwBufferSize = OPENAL_BUF_SIZE;
- + TRACE("Buffer size is now (%ld)\n", wwo->dwBufferSize);
- +
- + wwo->dwPlayedTotal = 0;
- + wwo->dwWrittenTotal = 0;
- +
- + wwo->dwSleepTime = (1024 * 1000 * BUFFER_REFILL_THRESHOLD) / wwo->waveFormat.Format.nAvgBytesPerSec;
- +
- + /* Initialize volume to full level */
- + wwo->volume_left = 100;
- + wwo->volume_right = 100;
- +
- + OpenAL_InitRingMessage(&wwo->msgRing);
- +
- + /* create player thread */
- + if (!(dwFlags & WAVE_DIRECTSOUND)) {
- + wwo->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- + wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD)wDevID, 0, &(wwo->dwThreadID));
- + WaitForSingleObject(wwo->hStartUpEvent, INFINITE);
- + CloseHandle(wwo->hStartUpEvent);
- + } else {
- + wwo->hThread = INVALID_HANDLE_VALUE;
- + wwo->dwThreadID = 0;
- + }
- + wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
- +
- + TRACE("live=0x%lx, dwBufferSize=%ld\n",
- + (long)wwo->live, wwo->dwBufferSize);
- +
- + TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
- + wwo->waveFormat.Format.wBitsPerSample, wwo->waveFormat.Format.nAvgBytesPerSec,
- + wwo->waveFormat.Format.nSamplesPerSec, wwo->waveFormat.Format.nChannels,
- + wwo->waveFormat.Format.nBlockAlign);
- +
- + return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
- +}
- +
- +/**************************************************************************
- + * wodClose [internal]
- + */
- +static DWORD wodClose(WORD wDevID)
- +{
- + DWORD ret = MMSYSERR_NOERROR;
- + WINE_WAVEOUT* wwo;
- +
- + TRACE("(%u);\n", wDevID);
- +
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad device ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + wwo = &WOutDev[wDevID];
- + if (wwo->lpQueuePtr) {
- + WARN("buffers still playing !\n");
- + ret = WAVERR_STILLPLAYING;
- + } else {
- + TRACE("imhere[3-close]\n");
- + if (wwo->hThread != INVALID_HANDLE_VALUE) {
- + OpenAL_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);
- + }
- +
- + OpenAL_DestroyRingMessage(&wwo->msgRing);
- +
- + OpenAL_CloseWaveOutDevice(wwo); /* close the stream and clean things up */
- +
- + ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
- + }
- + return ret;
- +}
- +
- +/**************************************************************************
- + * wodWrite [internal]
- + *
- + */
- +static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
- +{
- + TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
- +
- + /* first, do the sanity checks... */
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad dev ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
- + {
- + TRACE("unprepared\n");
- + return WAVERR_UNPREPARED;
- + }
- +
- + if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
- + {
- + TRACE("still playing\n");
- + return WAVERR_STILLPLAYING;
- + }
- +
- + lpWaveHdr->dwFlags &= ~WHDR_DONE;
- + lpWaveHdr->dwFlags |= WHDR_INQUEUE;
- + lpWaveHdr->lpNext = 0;
- +
- + TRACE("adding ring message\n");
- + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodPause [internal]
- + */
- +static DWORD wodPause(WORD wDevID)
- +{
- + TRACE("(%u);!\n", wDevID);
- +
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad device ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + TRACE("imhere[3-PAUSING]\n");
- + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_PAUSING, 0, TRUE);
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodRestart [internal]
- + */
- +static DWORD wodRestart(WORD wDevID)
- +{
- + TRACE("(%u);\n", wDevID);
- +
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad device ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + if (WOutDev[wDevID].state == WINE_WS_PAUSED) {
- + TRACE("imhere[3-RESTARTING]\n");
- + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESTARTING, 0, TRUE);
- + }
- +
- + /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
- + /* FIXME: Myst crashes with this ... hmm -MM
- + return wodNotifyClient(wwo, WOM_DONE, 0L, 0L);
- + */
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodReset [internal]
- + */
- +static DWORD wodReset(WORD wDevID)
- +{
- + TRACE("(%u);\n", wDevID);
- +
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad device ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + TRACE("imhere[3-RESET]\n");
- + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodGetPosition [internal]
- + */
- +static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
- +{
- + WINE_WAVEOUT* wwo;
- +
- + TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
- +
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad device ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + if (lpTime == NULL) {
- + WARN("invalid parameter: lpTime == NULL\n");
- + return MMSYSERR_INVALPARAM;
- + }
- +
- + wwo = &WOutDev[wDevID];
- + OpenAL_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
- +
- + return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->waveFormat);
- +}
- +
- +/**************************************************************************
- + * wodBreakLoop [internal]
- + */
- +static DWORD wodBreakLoop(WORD wDevID)
- +{
- + TRACE("(%u);\n", wDevID);
- +
- + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
- + WARN("bad device ID !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodGetVolume [internal]
- + */
- +static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
- +{
- + DWORD left, right;
- +
- + left = WOutDev[wDevID].volume_left;
- + right = WOutDev[wDevID].volume_right;
- +
- + TRACE("(%u, %p);\n", wDevID, lpdwVol);
- +
- + *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
- + 16);
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodSetVolume [internal]
- + */
- +static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
- +{
- + DWORD left, right;
- +
- + left = (LOWORD(dwParam) * 100) / 0xFFFFl;
- + right = (HIWORD(dwParam) * 100) / 0xFFFFl;
- +
- + TRACE("(%u, %08lX);\n", wDevID, dwParam);
- +
- + WOutDev[wDevID].volume_left = left;
- + WOutDev[wDevID].volume_right = right;
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodGetNumDevs [internal]
- + */
- +static DWORD wodGetNumDevs(void)
- +{
- + return MAX_WAVEOUTDRV;
- +}
- +
- +/**************************************************************************
- + * wodDevInterfaceSize [internal]
- + */
- +static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
- +{
- + TRACE("(%u, %p)\n", wDevID, dwParam1);
- +
- + *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
- + NULL, 0 ) * sizeof(WCHAR);
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * wodDevInterface [internal]
- + */
- +static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
- +{
- + if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
- + NULL, 0 ) * sizeof(WCHAR))
- + {
- + MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
- + dwParam1, dwParam2 / sizeof(WCHAR));
- + return MMSYSERR_NOERROR;
- + }
- + return MMSYSERR_INVALPARAM;
- +}
- +
- +/**************************************************************************
- + * wodMessage (WINEOPENAL.@)
- + */
- +DWORD WINAPI OpenAL_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
- + DWORD dwParam1, DWORD dwParam2)
- +{
- + TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
- + wDevID, wMsg, dwUser, dwParam1, dwParam2);
- +
- + switch (wMsg) {
- + case DRVM_INIT:
- + case DRVM_EXIT:
- + case DRVM_ENABLE:
- + case DRVM_DISABLE:
- + /* FIXME: Pretend this is supported */
- + return 0;
- + case WODM_OPEN: return wodOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
- + case WODM_CLOSE: return wodClose (wDevID);
- + case WODM_WRITE: return wodWrite (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
- + case WODM_PAUSE: return wodPause (wDevID);
- + case WODM_GETPOS: return wodGetPosition (wDevID, (LPMMTIME)dwParam1, dwParam2);
- + case WODM_BREAKLOOP: return wodBreakLoop (wDevID);
- + case WODM_PREPARE: return MMSYSERR_NOTSUPPORTED;
- + case WODM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
- + case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (LPWAVEOUTCAPSW)dwParam1, dwParam2);
- + case WODM_GETNUMDEVS: return wodGetNumDevs ();
- + case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
- + case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
- + case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
- + case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
- + case WODM_GETVOLUME: return wodGetVolume (wDevID, (LPDWORD)dwParam1);
- + case WODM_SETVOLUME: return wodSetVolume (wDevID, dwParam1);
- + case WODM_RESTART: return wodRestart (wDevID);
- + case WODM_RESET: return wodReset (wDevID);
- +
- + case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
- + case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
- + case DRV_QUERYDSOUNDIFACE: return wodDsCreate (wDevID, (PIDSDRIVER*)dwParam1);
- + case DRV_QUERYDSOUNDDESC: return wodDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
- + default:
- + FIXME("unknown message %d!\n", wMsg);
- + }
- + return MMSYSERR_NOTSUPPORTED;
- +}
- +
- +/*======================================================================*
- + * Low level WAVE IN implementation *
- + *======================================================================*/
- +
- +/**************************************************************************
- + * widGetNumDevs [internal]
- + */
- +static DWORD widGetNumDevs(void)
- +{
- + return (OPENAL_DISABLE_IN || !al_can_capture) ? 0 : MAX_WAVEINDRV;
- +}
- +
- +/**************************************************************************
- + * widDevInterfaceSize [internal]
- + */
- +static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
- +{
- + TRACE("(%u, %p)\n", wDevID, dwParam1);
- +
- + *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
- + NULL, 0 ) * sizeof(WCHAR);
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widDevInterface [internal]
- + */
- +static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
- +{
- + if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
- + NULL, 0 ) * sizeof(WCHAR))
- + {
- + MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
- + dwParam1, dwParam2 / sizeof(WCHAR));
- + return MMSYSERR_NOERROR;
- + }
- + return MMSYSERR_INVALPARAM;
- +}
- +
- +/**************************************************************************
- + * widNotifyClient [internal]
- + */
- +static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
- +{
- + TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
- +
- + switch (wMsg) {
- + case WIM_OPEN:
- + case WIM_CLOSE:
- + case WIM_DATA:
- + if (wwi->wFlags != DCB_NULL &&
- + !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
- + (HDRVR)wwi->waveDesc.hWave, wMsg,
- + wwi->waveDesc.dwInstance, dwParam1, dwParam2)) {
- + WARN("can't notify client !\n");
- + return MMSYSERR_ERROR;
- + }
- + break;
- + default:
- + FIXME("Unknown callback message %u\n", wMsg);
- + return MMSYSERR_INVALPARAM;
- + }
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widGetDevCaps [internal]
- + */
- +static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize)
- +{
- + TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
- +
- + if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
- +
- + if (wDevID >= MAX_WAVEINDRV) {
- + TRACE("MAX_WAVINDRV reached !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widRecorder [internal]
- + */
- +static DWORD CALLBACK widRecorder(LPVOID pmt)
- +{
- + WORD uDevID = (DWORD)pmt;
- + WINE_WAVEIN* wwi = (WINE_WAVEIN*)&WInDev[uDevID];
- + WAVEHDR* lpWaveHdr;
- + DWORD dwSleepTime;
- + DWORD bytesRead;
- + enum win_wm_message msg;
- + DWORD param;
- + HANDLE ev;
- +
- + SetEvent(wwi->hStartUpEvent);
- +
- + /* make sleep time to be # of ms to record one packet */
- + dwSleepTime = (1024 * 1000) / wwi->waveFormat.Format.nAvgBytesPerSec;
- + TRACE("sleeptime=%ld ms\n", dwSleepTime);
- +
- + for(;;) {
- + TRACE("wwi->lpQueuePtr=(%p), wwi->state=(%d)\n",wwi->lpQueuePtr,wwi->state);
- +
- + /* read data from OpenAL */
- + if ((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
- + {
- + lpWaveHdr = wwi->lpQueuePtr;
- +
- + TRACE("read as much as we can\n");
- + while(wwi->lpQueuePtr)
- + {
- + ALCint samples = 0;
- +
- + TRACE("attempt to read %ld bytes\n",lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
- +
- + /* Get samples from OpenAL on this wid */
- + alcGetIntegerv(wwi->al_device, t_ALC_CAPTURE_SAMPLES, 1, &samples);
- + CHECK_ALC_ERROR();
- + bytesRead = (wwi->waveFormat.Format.wBitsPerSample * samples) / 8;
- + TRACE("Got %d samples == %ld bytes\n", samples, bytesRead);
- + /* I have no idea if the below is needed... I dont want to just overrun buffers that are not big enough... */
- + /*if(bytesRead > (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded))
- + {
- + FIXME("Buffer overrun detected... cutting back samples -- is this correct?");
- + bytesRead = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
- + samples = (bytesRead * 8) / wwi->waveFormat.Format.wBitsPerSample;
- + }*/
- + p_alcCaptureSamples(wwi->al_device, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, samples);
- + CHECK_ALC_ERROR();
- +
- + TRACE("bytesRead=%ld\n",bytesRead);
- + if (bytesRead == -1 && errno == EAGAIN)
- + bytesRead = 0;
- + if (bytesRead==0) break; /* So we can stop recording smoothly */
- + if (bytesRead < 0)
- + bytesRead = 0;
- +
- + lpWaveHdr->dwBytesRecorded += bytesRead;
- + wwi->dwRecordedTotal += bytesRead;
- +
- + /* buffer full. notify client */
- + if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
- + {
- + /* must copy the value of next waveHdr, because we have no idea of what
- + * will be done with the content of lpWaveHdr in callback
- + */
- + LPWAVEHDR lpNext = lpWaveHdr->lpNext;
- +
- + TRACE("waveHdr full.\n");
- +
- + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
- + lpWaveHdr->dwFlags |= WHDR_DONE;
- +
- + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
- + lpWaveHdr = wwi->lpQueuePtr = lpNext;
- + TRACE("wwi->lpQueuePtr=%p\n", wwi->lpQueuePtr);
- + }
- + }
- + }
- +
- + /* wait for dwSleepTime or an event in thread's queue */
- + WAIT_OMR(&wwi->msgRing, dwSleepTime);
- +
- + while (OpenAL_RetrieveRingMessage(&wwi->msgRing, &msg, ¶m, &ev))
- + {
- + TRACE("msg=%s param=0x%lx\n",wodPlayerCmdString[msg - WM_USER - 1], param);
- + switch(msg) {
- + case WINE_WM_PAUSING:
- + wwi->state = WINE_WS_PAUSED;
- +
- + /* stop OpenAL on this wid -- correct or no? */
- + p_alcCaptureStop(wwi->al_device);
- + CHECK_ALC_ERROR();
- +
- + SetEvent(ev);
- + break;
- + case WINE_WM_STARTING:
- + wwi->state = WINE_WS_PLAYING;
- +
- + /* start OpenAL on this wid */
- + p_alcCaptureStart(wwi->al_device);
- + CHECK_ALC_ERROR();
- +
- + SetEvent(ev);
- + break;
- + case WINE_WM_HEADER:
- + lpWaveHdr = (LPWAVEHDR)param;
- + /* insert buffer at end of queue */
- + {
- + LPWAVEHDR* wh;
- + int num_headers = 0;
- + for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext))
- + {
- + num_headers++;
- + }
- + *wh=lpWaveHdr;
- + }
- + break;
- + case WINE_WM_STOPPING:
- + if (wwi->state != WINE_WS_STOPPED)
- + {
- + /* stop OpenAL on this wid */
- + p_alcCaptureStop(wwi->al_device);
- + CHECK_ALC_ERROR();
- +
- + /* return current buffer to app */
- + lpWaveHdr = wwi->lpQueuePtr;
- + if (lpWaveHdr)
- + {
- + LPWAVEHDR lpNext = lpWaveHdr->lpNext;
- + TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
- + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
- + lpWaveHdr->dwFlags |= WHDR_DONE;
- + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
- + wwi->lpQueuePtr = lpNext;
- + }
- + }
- + wwi->state = WINE_WS_STOPPED;
- + SetEvent(ev);
- + break;
- + case WINE_WM_RESETTING:
- + wwi->state = WINE_WS_STOPPED;
- + wwi->dwRecordedTotal = 0;
- +
- + /* stop OpenAL on this wid */
- + p_alcCaptureStop(wwi->al_device);
- + CHECK_ALC_ERROR();
- +
- + /* return all buffers to the app */
- + for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
- + TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
- + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
- + lpWaveHdr->dwFlags |= WHDR_DONE;
- +
- + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
- + }
- + wwi->lpQueuePtr = NULL;
- + SetEvent(ev);
- + break;
- + case WINE_WM_CLOSING:
- + wwi->hThread = 0;
- + wwi->state = WINE_WS_CLOSED;
- + SetEvent(ev);
- + TRACE("Killing Thread ... how?\n");
- + ExitThread(0);
- + /* shouldn't go here */
- + default:
- + FIXME("unknown message %d\n", msg);
- + break;
- + }
- + }
- + }
- + TRACE("Killing Thread ... how?\n");
- + ExitThread(0);
- + /* just for not generating compilation warnings... should never be executed */
- + return 0;
- +}
- +
- +/**************************************************************************
- + * widOpen [internal]
- + */
- +static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
- +{
- + WINE_WAVEIN* wwi;
- +
- + TRACE("(%u, %p %08lX);\n",wDevID, lpDesc, dwFlags);
- + if (lpDesc == NULL) {
- + WARN("Invalid Parametr (lpDesc == NULL)!\n");
- + return MMSYSERR_INVALPARAM;
- + }
- +
- + if (wDevID >= MAX_WAVEINDRV) {
- + TRACE ("MAX_WAVEINDRV reached !\n");
- + return MMSYSERR_BADDEVICEID;
- + }
- +
- + /* if this device is already open tell the app that it is allocated */
- + if(WInDev[wDevID].live)
- + {
- + TRACE("device already allocated\n");
- + return MMSYSERR_ALLOCATED;
- + }
- +
- + /* only PCM format is support so far... */
- + if (!supportedFormat(lpDesc->lpFormat, 1)) {
- + WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
- + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
- + lpDesc->lpFormat->nSamplesPerSec);
- + return WAVERR_BADFORMAT;
- + }
- +
- + if (dwFlags & WAVE_FORMAT_QUERY) {
- + TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
- + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
- + lpDesc->lpFormat->nSamplesPerSec);
- + return MMSYSERR_NOERROR;
- + }
- +
- + wwi = &WInDev[wDevID];
- +
- + /* direct sound not supported, ignore the flag */
- + dwFlags &= ~WAVE_DIRECTSOUND;
- +
- + wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- +
- + memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
- + copy_format(lpDesc->lpFormat, &wwi->waveFormat);
- +
- + if (wwi->waveFormat.Format.wBitsPerSample == 0) {
- + WARN("Resetting zerod wBitsPerSample\n");
- + wwi->waveFormat.Format.wBitsPerSample = 8 *
- + (wwi->waveFormat.Format.nAvgBytesPerSec /
- + wwi->waveFormat.Format.nSamplesPerSec) /
- + wwi->waveFormat.Format.nChannels;
- + }
- +
- + /* input OpenAL... */
- + wwi->bytes_per_frame = (wwi->waveFormat.Format.wBitsPerSample * wwi->waveFormat.Format.nChannels) / 8;
- + {
- + ALenum format = al_format_for_wave_format(&wwi->waveFormat);
- + ALuint freq = wwi->waveFormat.Format.nSamplesPerSec;
- + /* Setup the OpenAL cap device */ /* Be able to hold 4 secs worth of data? */
- + wwi->al_device = p_alcCaptureOpenDevice(NULL, freq, format, 4 * wwi->waveFormat.Format.nSamplesPerSec * wwi->waveFormat.Format.wBitsPerSample / 8);
- +//wwi->al_device = p_alcCaptureOpenDevice(NULL, 44100, format, 4 * wwi->waveFormat.Format.nSamplesPerSec * wwi->waveFormat.Format.wBitsPerSample / 8);
- + TRACE("wwi->al_device = %p\n", wwi->al_device);
- + CHECK_ALC_ERROR();
- + if(!wwi->al_device)
- + {
- + WARN("alcCaptureOpenDevice(%p, %d, %d, %ld) failed\n", NULL, freq, format, 4 * wwi->waveFormat.Format.nSamplesPerSec * wwi->waveFormat.Format.wBitsPerSample / 8);
- + return MMSYSERR_ALLOCATED;
- + }
- + wwi->live = 1;
- + }
- +
- + if(!wwi->live) return MMSYSERR_ALLOCATED;
- +
- + wwi->dwRecordedTotal = 0;
- + wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- +
- + OpenAL_InitRingMessage(&wwi->msgRing);
- +
- + /* create recorder thread */
- + if (!(dwFlags & WAVE_DIRECTSOUND)) {
- + wwi->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- + wwi->hThread = CreateThread(NULL, 0, widRecorder, (LPVOID)(DWORD)wDevID, 0, &(wwi->dwThreadID));
- + WaitForSingleObject(wwi->hStartUpEvent, INFINITE);
- + CloseHandle(wwi->hStartUpEvent);
- + } else {
- + wwi->hThread = INVALID_HANDLE_VALUE;
- + wwi->dwThreadID = 0;
- + }
- + wwi->hStartUpEvent = INVALID_HANDLE_VALUE;
- +
- + TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
- + wwi->waveFormat.Format.wBitsPerSample, wwi->waveFormat.Format.nAvgBytesPerSec,
- + wwi->waveFormat.Format.nSamplesPerSec, wwi->waveFormat.Format.nChannels,
- + wwi->waveFormat.Format.nBlockAlign);
- + return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
- +}
- +
- +/**************************************************************************
- + * widClose [internal]
- + */
- +static DWORD widClose(WORD wDevID)
- +{
- + WINE_WAVEIN* wwi;
- +
- + TRACE("(%u);\n", wDevID);
- + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
- + WARN("can't close !\n");
- + return MMSYSERR_INVALHANDLE;
- + }
- +
- + wwi = &WInDev[wDevID];
- +
- + if (wwi->lpQueuePtr != NULL) {
- + WARN("still buffers open !\n");
- + return WAVERR_STILLPLAYING;
- + }
- +
- + OpenAL_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
- + OpenAL_CloseWaveInDevice(wwi);
- + wwi->state = WINE_WS_CLOSED;
- + OpenAL_DestroyRingMessage(&wwi->msgRing);
- + return widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
- +}
- +
- +/**************************************************************************
- + * widAddBuffer [internal]
- + */
- +static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
- +{
- + TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
- +
- + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
- + WARN("can't do it !\n");
- + return MMSYSERR_INVALHANDLE;
- + }
- + if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
- + TRACE("never been prepared !\n");
- + return WAVERR_UNPREPARED;
- + }
- + if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
- + TRACE("header already in use !\n");
- + return WAVERR_STILLPLAYING;
- + }
- +
- + lpWaveHdr->dwFlags |= WHDR_INQUEUE;
- + lpWaveHdr->dwFlags &= ~WHDR_DONE;
- + lpWaveHdr->dwBytesRecorded = 0;
- + lpWaveHdr->lpNext = NULL;
- +
- + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widStart [internal]
- + */
- +static DWORD widStart(WORD wDevID)
- +{
- + TRACE("(%u);\n", wDevID);
- + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
- + WARN("can't start recording !\n");
- + return MMSYSERR_INVALHANDLE;
- + }
- +
- + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_STARTING, 0, TRUE);
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widStop [internal]
- + */
- +static DWORD widStop(WORD wDevID)
- +{
- + TRACE("(%u);\n", wDevID);
- + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
- + WARN("can't stop !\n");
- + return MMSYSERR_INVALHANDLE;
- + }
- +
- + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_STOPPING, 0, TRUE);
- +
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widReset [internal]
- + */
- +static DWORD widReset(WORD wDevID)
- +{
- + TRACE("(%u);\n", wDevID);
- + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
- + WARN("can't reset !\n");
- + return MMSYSERR_INVALHANDLE;
- + }
- + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);
- + return MMSYSERR_NOERROR;
- +}
- +
- +/**************************************************************************
- + * widMessage (WINEOPENAL.6)
- + */
- +DWORD WINAPI OpenAL_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
- + DWORD dwParam1, DWORD dwParam2)
- +{
- + TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
- + wDevID, wMsg, dwUser, dwParam1, dwParam2);
- +
- + switch (wMsg) {
- + case DRVM_INIT:
- + case DRVM_EXIT:
- + case DRVM_ENABLE:
- + case DRVM_DISABLE:
- + /* FIXME: Pretend this is supported */
- + return 0;
- + case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
- + case WIDM_CLOSE: return widClose (wDevID);
- + case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
- + case WIDM_PREPARE: return MMSYSERR_NOTSUPPORTED;
- + case WIDM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
- + case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSW)dwParam1, dwParam2);
- + case WIDM_GETNUMDEVS: return widGetNumDevs ();
- + case WIDM_RESET: return widReset (wDevID);
- + case WIDM_START: return widStart (wDevID);
- + case WIDM_STOP: return widStop (wDevID);
- + case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
- + case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
- + default:
- + FIXME("unknown message %d!\n", wMsg);
- + }
- + return MMSYSERR_NOTSUPPORTED;
- +}
- +
- +/*======================================================================*
- + * Low level DSOUND implementation *
- + *======================================================================*/
- +static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
- +{
- + /* REMOVE COMMENT: we can't perform memory mapping as we don't have a file stream
- + interface with esd like we do with oss */
- + MESSAGE("This sound card's driver does not support direct access\n");
- + MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
- + return MMSYSERR_NOTSUPPORTED;
- +}
- +
- +static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
- +{
- + memset(desc, 0, sizeof(*desc));
- + strcpy(desc->szDesc, "Wine OpenAL DirectSound Driver");
- + strcpy(desc->szDrvname, "wineopenal.drv");
- + return MMSYSERR_NOERROR;
- +}
- +
- +#else /* !defined(HAVE_OPENAL_AL_H) && !defined(HAVE_AL_AL_H) */
- +
- +/**************************************************************************
- + * wodMessage (WINEOPENAL.@)
- + */
- +DWORD WINAPI OpenAL_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
- + DWORD dwParam1, DWORD dwParam2)
- +{
- + FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
- + return MMSYSERR_NOTENABLED;
- +}
- +
- +/**************************************************************************
- + * widMessage (WINEOPENAL.6)
- + */
- +DWORD WINAPI OpenAL_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
- + DWORD dwParam1, DWORD dwParam2)
- +{
- + FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
- + return MMSYSERR_NOTENABLED;
- +}
- +
- +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
- diff --git a/dlls/wineopenal.drv/openal.c b/dlls/wineopenal.drv/openal.c
- new file mode 100644
- index 0000000..4e0702d
- --- /dev/null
- +++ b/dlls/wineopenal.drv/openal.c
- @@ -0,0 +1,87 @@
- +/*
- + * Wine Driver for OpenAL
- + * http://www.openal.org
- + *
- + * Copyright 2004 Zhangrong Huang <hzhr@users.sourceforge.net>
- + * 2006 Nick Burns <adger44@hotmail.com> (OpenAL version)
- + *
- + * Code massively copied from Eric Pouech's OSS driver
- + * and Chris Morgan aRts driver
- + *
- + * This library is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * This library is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with this library; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- + */
- +
- +#include "config.h"
- +
- +#include <stdarg.h>
- +
- +#include "windef.h"
- +#include "winbase.h"
- +#include "wingdi.h"
- +#include "winuser.h"
- +#include "mmddk.h"
- +#include "openal.h"
- +#include "wine/library.h"
- +#include "wine/debug.h"
- +
- +WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
- +
- +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
- +
- +/**************************************************************************
- + * OpenAL_drvOpen [internal]
- + */
- +static LRESULT OpenAL_drvOpen(LPSTR str)
- +{
- + return 1;
- +}
- +
- +/**************************************************************************
- + * OpenAL_drvClose [internal]
- + */
- +static LRESULT OpenAL_drvClose(DWORD_PTR dwDevID)
- +{
- + return 1;
- +}
- +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
- +
- +
- +/**************************************************************************
- + * DriverProc (WINEOPENAL.@)
- + */
- +LRESULT CALLBACK OpenAL_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
- + LPARAM dwParam1, LPARAM dwParam2)
- +{
- +/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
- +/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
- +
- + switch(wMsg) {
- +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
- + case DRV_LOAD: if (OpenAL_WaveInit()<0) return 0;
- + return 1;
- + case DRV_FREE: return OpenAL_WaveClose();
- + case DRV_OPEN: return OpenAL_drvOpen((LPSTR)dwParam1);
- + case DRV_CLOSE: return OpenAL_drvClose(dwDevID);
- + case DRV_ENABLE: return 1;
- + case DRV_DISABLE: return 1;
- + case DRV_QUERYCONFIGURE: return 1;
- + case DRV_CONFIGURE: MessageBoxA(0, "OpenAL MultiMedia Driver!", "OpenAL Driver", MB_OK); return 1;
- + case DRV_INSTALL: return DRVCNF_RESTART;
- + case DRV_REMOVE: return DRVCNF_RESTART;
- +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
- + default:
- + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
- + }
- +}
- diff --git a/dlls/wineopenal.drv/openal.h b/dlls/wineopenal.drv/openal.h
- new file mode 100644
- index 0000000..3c9aec0
- --- /dev/null
- +++ b/dlls/wineopenal.drv/openal.h
- @@ -0,0 +1,35 @@
- +/* Definition for OpenAL drivers : wine multimedia system
- + *
- + * Copyright 2004 Zhangrong Huang <hzhr@users.sourceforge.net>
- + * 2006 Nick Burns <adger44@hotmail.com> (OpenAL version)
- + *
- + * This library is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * This library is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with this library; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- + */
- +
- +#ifndef __WINE_OPENAL_H
- +#define __WINE_OPENAL_H
- +
- +#ifndef __WINE_CONFIG_H
- +# error You must include config.h to use this header
- +#endif
- +
- +#ifdef HAVE_SYS_ERRNO_H
- +#include <sys/errno.h>
- +#endif
- +
- +extern LONG OpenAL_WaveInit(void);
- +extern LONG OpenAL_WaveClose(void);
- +
- +#endif /* __WINE_OPENAL_H */
- diff --git a/dlls/wineopenal.drv/wineopenal.drv.spec b/dlls/wineopenal.drv/wineopenal.drv.spec
- new file mode 100644
- index 0000000..e08c3d8
- --- /dev/null
- +++ b/dlls/wineopenal.drv/wineopenal.drv.spec
- @@ -0,0 +1,3 @@
- +@ stdcall -private DriverProc(long long long long long) OpenAL_DriverProc
- +@ stdcall -private wodMessage(long long long long long) OpenAL_wodMessage
- +@ stdcall -private widMessage(long long long long long) OpenAL_widMessage
- diff --git a/configure.ac b/configure.ac
- index 72f93b7..18ca664 100644
- --- a/configure.ac
- +++ b/configure.ac
- @@ -247,10 +247,13 @@ AC_CHECK_LIB(pthread,pthread_create,AC_SUBST(LIBPTHREAD,"-lpthread"))
- AC_SUBST(XLIB,"")
- AC_SUBST(OPENGL_LIBS,"")
- +AC_SUBST(OPENAL,"")
- dnl **** Check for header files ****
- AC_CHECK_HEADERS(\
- + OpenAL/al.h \
- + AL/al.h \
- AudioUnit/AudioUnit.h \
- Carbon/Carbon.h \
- CoreAudio/CoreAudio.h \
- @@ -542,6 +545,11 @@ case $host_os in
- dnl CoreServices needed by AudioUnit
- AC_SUBST(COREAUDIO,"-framework CoreAudio -framework AudioUnit -framework CoreServices -framework AudioToolbox -framework CoreMIDI")
- fi
- + if test "$ac_cv_header_OpenAL_al_h" = "yes"
- + then
- + dnl OpenAL framework
- + AC_SUBST(OPENAL,"-framework OpenAL")
- + fi
- case $host_cpu in
- *powerpc*)
- LDDLLFLAGS="$LDDLLFLAGS -read_only_relocs warning" dnl FIXME
- @@ -1264,6 +1272,15 @@ then
- WINE_WARNING([No sound system was found. Windows applications will be silent.])
- fi
- +dnl **** Check for OpenAL support ****
- +dnl **** Mac OSX OpenAL support checked below ****
- +
- +if test "$ac_cv_header_AL_al_h" = "yes"
- + then
- + dnl OpenAL framework
- + AC_SUBST(OPENAL,"-lopenal")
- +fi
- +
- dnl **** Check for gcc specific options ****
- AC_SUBST(EXTRACFLAGS,"")
- @@ -2014,6 +2031,7 @@ WINE_CONFIG_MAKEFILE([dlls/olecli32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_D
- WINE_CONFIG_MAKEFILE([dlls/oledlg/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/olepro32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/olesvr32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- +WINE_CONFIG_MAKEFILE([dlls/openal32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/olethk32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/opengl32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/opengl32/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests])
- @@ -2119,6 +2137,7 @@ WINE_CONFIG_MAKEFILE([dlls/winejack.drv/Makefile],[dlls/Makedll.rules],[dlls],[A
- WINE_CONFIG_MAKEFILE([dlls/winejoystick.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/winemp3.acm/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/winenas.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- +WINE_CONFIG_MAKEFILE([dlls/wineopenal.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/wineoss.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/wineps.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- WINE_CONFIG_MAKEFILE([dlls/winequartz.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
- diff --git a/dlls/Makefile.in b/dlls/Makefile.in
- index 794905a..5a38be5 100644
- --- a/dlls/Makefile.in
- +++ b/dlls/Makefile.in
- @@ -116,6 +116,9 @@ olecli.dll16:
- olesvr.dll16:
- echo "olesvr32.dll" >$@
- +
- +openal.dll16:
- + echo "openal32.dll" >$@
- rasapi16.dll16:
- echo "rasapi32.dll" >$@
- @@ -264,6 +267,7 @@ IMPORT_LIBS = \
- oledlg/liboledlg.$(IMPLIBEXT) \
- olepro32/libolepro32.$(IMPLIBEXT) \
- olesvr32/libolesvr32.$(IMPLIBEXT) \
- + openal32/libopenal32.$(IMPLIBEXT) \
- opengl32/libopengl32.$(IMPLIBEXT) \
- pdh/libpdh.$(IMPLIBEXT) \
- powrprof/libpowrprof.$(IMPLIBEXT) \
- @@ -405,6 +409,7 @@ CROSS_IMPLIBS = \
- oledlg/liboledlg.a \
- olepro32/libolepro32.a \
- olesvr32/libolesvr32.a \
- + openal32/libopenal32.a \
- opengl32/libopengl32.a \
- pdh/libpdh.a \
- powrprof/libpowrprof.a \
- @@ -726,6 +731,9 @@ olepro32/libolepro32.def olepro32/libolepro32.a: olepro32/olepro32.spec $(WINEBU
- olesvr32/libolesvr32.def olesvr32/libolesvr32.a: olesvr32/olesvr32.spec $(WINEBUILD)
- @cd olesvr32 && $(MAKE) `basename $@`
- +openal32/libopenal32.def openal32/libopenal32.a: openal32/openal32.spec $(WINEBUILD)
- + @cd openal32 && $(MAKE) `basename $@`
- +
- opengl32/libopengl32.def opengl32/libopengl32.a: opengl32/opengl32.spec $(WINEBUILD)
- @cd opengl32 && $(MAKE) `basename $@`
- diff --git a/programs/winecfg/En.rc b/programs/winecfg/En.rc
- index 5743ba3..f790f95 100644
- --- a/programs/winecfg/En.rc
- +++ b/programs/winecfg/En.rc
- @@ -277,6 +277,7 @@ BEGIN
- IDS_DRIVER_NAS "NAS Driver"
- IDS_DRIVER_AUDIOIO "Audio IO (Solaris) Driver"
- IDS_DRIVER_COREAUDIO "CoreAudio Driver"
- + IDS_DRIVER_OPENAL "OpenAL Driver"
- IDS_OPEN_DRIVER_ERROR "Couldn't open %s!"
- IDS_SOUNDDRIVERS "Sound Drivers"
- IDS_DEVICES_WAVEOUT "Wave Out Devices"
- diff --git a/programs/winecfg/audio.c b/programs/winecfg/audio.c
- index 8e966a5..75596e4 100644
- --- a/programs/winecfg/audio.c
- +++ b/programs/winecfg/audio.c
- @@ -95,6 +95,7 @@ static const AUDIO_DRIVER sAudioDrivers[] = {
- {IDS_DRIVER_NAS, "nas"},
- {IDS_DRIVER_ESOUND, "esd"},
- {IDS_DRIVER_AUDIOIO, "audioio"},
- + {IDS_DRIVER_OPENAL, "openal"},
- {0, ""}
- };
- diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
- index a18fe76..24b9120 100644
- --- a/programs/winecfg/resource.h
- +++ b/programs/winecfg/resource.h
- @@ -255,3 +255,5 @@
- /* About tab */
- #define IDC_ABT_OWNER 8432
- #define IDC_ABT_ORG 8433
- +
- +#define IDS_DRIVER_OPENAL 8434
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement