Advertisement
Guest User

Untitled

a guest
Jan 17th, 2009
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 141.34 KB | None | 0 0
  1. diff --git a/dlls/openal32/openal.c b/dlls/openal32/openal.c
  2. new file mode 100644
  3. index 0000000..17efbf8
  4. --- /dev/null
  5. +++ b/dlls/openal32/openal.c
  6. @@ -0,0 +1,461 @@
  7. +#include "config.h"
  8. +
  9. +#include <stdarg.h>
  10. +#include "windef.h"
  11. +#include "winbase.h"
  12. +#include "wine/debug.h"
  13. +
  14. +/* TODO: add alut */
  15. +/* TODO: add other openal extensions */
  16. +
  17. +#if defined(HAVE_OPENAL_AL_H)
  18. + #include <OpenAL/al.h>
  19. + #include <OpenAL/alc.h>
  20. +#elif defined(HAVE_AL_AL_H)
  21. + #include <AL/al.h>
  22. + #include <AL/alc.h>
  23. +#endif
  24. +
  25. +WINE_DEFAULT_DEBUG_CHANNEL(openal);
  26. +
  27. +/* OpenAL exts */
  28. +/* defined as (ext) */
  29. +#define WINE_AL_EXTS(func)\
  30. + func(ALC_1_0)\
  31. + func(AL_1_0)\
  32. + func(ALC_1_1)\
  33. + func(AL_1_1)\
  34. + func(ALC_EXT_MAC_OSX)\
  35. + func(AL_EXT_STATIC_BUFFER)\
  36. + func(ALC_EXT_ASA)\
  37. + func(ALUT)
  38. +
  39. +/* OpenAL ext function groups */
  40. +enum
  41. +{
  42. +#define MAKE_WINE_ENUMS(ext) WINE_##ext,
  43. + WINE_AL_EXTS(MAKE_WINE_ENUMS)
  44. +#undef MAKE_WINE_ENUMS
  45. +};
  46. +
  47. +static const char* wine_al_ext_to_string(const int ext)
  48. +{
  49. + switch(ext)
  50. + {
  51. +#define WINE_AL_EXT_TO_STRING_HELPER(ext) case WINE_##ext: return "WINE_" #ext;
  52. + WINE_AL_EXTS(WINE_AL_EXT_TO_STRING_HELPER)
  53. +#undef WINE_AL_EXT_TO_STRING_HELPER
  54. + }
  55. + return "ERROR";
  56. +}
  57. +
  58. +/* OpenAL 1.0 functions */
  59. +/* defined as (ext, return_type, func_name, params, args) */
  60. +/* used to define func ptrs, get proc address, etc... */
  61. +#define WINE_ALC_1_0_FUNCS(func)\
  62. + func(WINE_ALC_1_0, ALCcontext * , alcCreateContext, ( ALCdevice *device, const ALCint* attrlist ), ( device, attrlist ))\
  63. + func(WINE_ALC_1_0, ALCboolean , alcMakeContextCurrent, ( ALCcontext *context ), ( context ))\
  64. + func(WINE_ALC_1_0, void , alcProcessContext, ( ALCcontext *context ), ( context ))\
  65. + func(WINE_ALC_1_0, void , alcSuspendContext, ( ALCcontext *context ), ( context ))\
  66. + func(WINE_ALC_1_0, void , alcDestroyContext, ( ALCcontext *context ), ( context ))\
  67. + func(WINE_ALC_1_0, ALCcontext * , alcGetCurrentContext, ( ALCvoid ), ( ))\
  68. + func(WINE_ALC_1_0, ALCdevice * , alcGetContextsDevice, ( ALCcontext *context ), ( context ))\
  69. + func(WINE_ALC_1_0, ALCdevice * , alcOpenDevice, ( const ALCchar *devicename ), ( devicename ))\
  70. + func(WINE_ALC_1_0, ALCboolean , alcCloseDevice, ( ALCdevice *device ), ( device ))\
  71. + func(WINE_ALC_1_0, ALCenum , alcGetError, ( ALCdevice *device ), ( device ))\
  72. + func(WINE_ALC_1_0, ALCboolean , alcIsExtensionPresent, ( ALCdevice *device, const ALCchar *extname ), ( device, extname ))\
  73. +/* must be handled differently */\
  74. + /*func(WINE_ALC_1_0, void * , alcGetProcAddress, ( ALCdevice *device, const ALCchar *funcname ), ( device, funcname ))*/\
  75. + func(WINE_ALC_1_0, ALCenum , alcGetEnumValue, ( ALCdevice *device, const ALCchar *enumname ), ( device, enumname ))\
  76. + func(WINE_ALC_1_0, const ALCchar* , alcGetString, ( ALCdevice *device, ALCenum param ), ( device, param ))\
  77. + func(WINE_ALC_1_0, void , alcGetIntegerv, ( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ), ( device, param, size, dest ))
  78. +
  79. +#define WINE_AL_1_0_FUNCS(func)\
  80. + func(WINE_AL_1_0, void , alEnable, ( ALenum capability ), ( capability ))\
  81. + func(WINE_AL_1_0, void , alDisable, ( ALenum capability ), ( capability ))\
  82. + func(WINE_AL_1_0, ALboolean , alIsEnabled, ( ALenum capability ), ( capability ))\
  83. + func(WINE_AL_1_0, const ALchar* , alGetString, ( ALenum param ), ( param ))\
  84. + func(WINE_AL_1_0, void , alGetBooleanv, ( ALenum param, ALboolean* data ), ( param, data ))\
  85. + func(WINE_AL_1_0, void , alGetIntegerv, ( ALenum param, ALint* data ), ( param, data ))\
  86. + func(WINE_AL_1_0, void , alGetFloatv, ( ALenum param, ALfloat* data ), ( param, data ))\
  87. + func(WINE_AL_1_0, void , alGetDoublev, ( ALenum param, ALdouble* data ), ( param, data ))\
  88. + func(WINE_AL_1_0, ALboolean , alGetBoolean, ( ALenum param ), ( param ))\
  89. + func(WINE_AL_1_0, ALint , alGetInteger, ( ALenum param ), ( param ))\
  90. + func(WINE_AL_1_0, ALfloat , alGetFloat, ( ALenum param ), ( param ))\
  91. + func(WINE_AL_1_0, ALdouble , alGetDouble, ( ALenum param ), ( param ))\
  92. + func(WINE_AL_1_0, ALenum , alGetError, ( void ), ( ))\
  93. + func(WINE_AL_1_0, ALboolean , alIsExtensionPresent, (const ALchar* extname ), (extname ))\
  94. +/* must be handled differently */\
  95. + /*func(WINE_AL_1_0, void* , alGetProcAddress, ( const ALchar* fname ), ( fname ))*/\
  96. + func(WINE_AL_1_0, ALenum , alGetEnumValue, ( const ALchar* ename ), ( ename ))\
  97. + func(WINE_AL_1_0, void , alListenerf, ( ALenum param, ALfloat value ), ( param, value ))\
  98. + func(WINE_AL_1_0, void , alListener3f, ( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( param, value1, value2, value3 ))\
  99. + func(WINE_AL_1_0, void , alListenerfv, ( ALenum param, const ALfloat* values ), ( param, values ))\
  100. + func(WINE_AL_1_0, void , alListeneri, ( ALenum param, ALint value ), ( param, value ))\
  101. + func(WINE_AL_1_0, void , alGetListenerf, ( ALenum param, ALfloat* value ), ( param, value ))\
  102. + func(WINE_AL_1_0, void , alGetListener3f, ( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ), ( param, value1, value2, value3 ))\
  103. + func(WINE_AL_1_0, void , alGetListenerfv, ( ALenum param, ALfloat* values ), ( param, values ))\
  104. + func(WINE_AL_1_0, void , alGetListeneri, ( ALenum param, ALint* value ), ( param, value ))\
  105. + func(WINE_AL_1_0, void , alGetListeneriv, ( ALenum param, ALint* values ), ( param, values ))\
  106. + func(WINE_AL_1_0, void , alGenSources, ( ALsizei n, ALuint* sources ), ( n, sources ))\
  107. + func(WINE_AL_1_0, void , alDeleteSources, ( ALsizei n, const ALuint* sources ), ( n, sources ))\
  108. + func(WINE_AL_1_0, ALboolean , alIsSource, ( ALuint sid ), ( sid ))\
  109. + func(WINE_AL_1_0, void , alSourcef, ( ALuint sid, ALenum param, ALfloat value), ( sid, param, value))\
  110. + func(WINE_AL_1_0, void , alSource3f, ( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( sid, param, value1, value2, value3 ))\
  111. + func(WINE_AL_1_0, void , alSourcefv, ( ALuint sid, ALenum param, const ALfloat* values ), ( sid, param, values ))\
  112. + func(WINE_AL_1_0, void , alSourcei, ( ALuint sid, ALenum param, ALint value), ( sid, param, value))\
  113. + func(WINE_AL_1_0, void , alGetSourcef, ( ALuint sid, ALenum param, ALfloat* value ), ( sid, param, value ))\
  114. + func(WINE_AL_1_0, void , alGetSource3f, ( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3), ( sid, param, value1, value2, value3))\
  115. + func(WINE_AL_1_0, void , alGetSourcefv, ( ALuint sid, ALenum param, ALfloat* values ), ( sid, param, values ))\
  116. + func(WINE_AL_1_0, void , alGetSourcei, ( ALuint sid, ALenum param, ALint* value ), ( sid, param, value ))\
  117. + func(WINE_AL_1_0, void , alGetSourceiv, ( ALuint sid, ALenum param, ALint* values ), ( sid, param, values ))\
  118. + func(WINE_AL_1_0, void , alSourcePlayv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
  119. + func(WINE_AL_1_0, void , alSourceStopv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
  120. + func(WINE_AL_1_0, void , alSourceRewindv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
  121. + func(WINE_AL_1_0, void , alSourcePausev, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))\
  122. + func(WINE_AL_1_0, void , alSourcePlay, ( ALuint sid ), ( sid ))\
  123. + func(WINE_AL_1_0, void , alSourceStop, ( ALuint sid ), ( sid ))\
  124. + func(WINE_AL_1_0, void , alSourceRewind, ( ALuint sid ), ( sid ))\
  125. + func(WINE_AL_1_0, void , alSourcePause, ( ALuint sid ), ( sid ))\
  126. + func(WINE_AL_1_0, void , alSourceQueueBuffers, ( ALuint sid, ALsizei numEntries, const ALuint *bids ), ( sid, numEntries, bids ))\
  127. + func(WINE_AL_1_0, void , alSourceUnqueueBuffers, ( ALuint sid, ALsizei numEntries, ALuint *bids ), ( sid, numEntries, bids ))\
  128. + func(WINE_AL_1_0, void , alGenBuffers, ( ALsizei n, ALuint* buffers ), ( n, buffers ))\
  129. + func(WINE_AL_1_0, void , alDeleteBuffers, ( ALsizei n, const ALuint* buffers ), ( n, buffers ))\
  130. + func(WINE_AL_1_0, ALboolean , alIsBuffer, ( ALuint bid ), ( bid ))\
  131. + func(WINE_AL_1_0, void , alBufferData, ( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ), ( bid, format, data, size, freq ))\
  132. + func(WINE_AL_1_0, void , alGetBufferf, ( ALuint bid, ALenum param, ALfloat* value ), ( bid, param, value ))\
  133. + func(WINE_AL_1_0, void , alGetBufferfv, ( ALuint bid, ALenum param, ALfloat* values ), ( bid, param, values ))\
  134. + func(WINE_AL_1_0, void , alGetBufferi, ( ALuint bid, ALenum param, ALint* value ), ( bid, param, value ))\
  135. + func(WINE_AL_1_0, void , alGetBufferiv, ( ALuint bid, ALenum param, ALint* values ), ( bid, param, values ))\
  136. + func(WINE_AL_1_0, void , alDopplerFactor, ( ALfloat value ), ( value ))\
  137. + func(WINE_AL_1_0, void , alDopplerVelocity, ( ALfloat value ), ( value ))\
  138. + func(WINE_AL_1_0, void , alDistanceModel, ( ALenum distanceModel ), ( distanceModel ))
  139. +
  140. +/*
  141. + func(WINE_ALC_1_1, ALCdevice*, alcCaptureOpenDevice, (const ALCbyte *deviceName, ALCuint freq, ALCenum fmt, ALCsizei bufsize), (deviceName, freq, fmt, bufsize))\
  142. + func(WINE_ALC_1_1, ALCboolean, alcCaptureCloseDevice, (ALCdevice *device), (device))\
  143. + func(WINE_ALC_1_1, ALCvoid, alcCaptureStart, (ALCdevice *device), (device))\
  144. + func(WINE_ALC_1_1, ALCvoid, alcCaptureStop, (ALCdevice *device), (device))\
  145. + func(WINE_ALC_1_1, ALCvoid, alcCaptureSamples, (ALCdevice *device, ALCvoid *buf, ALCsizei samps), (device, buf, samps))
  146. +*/
  147. +/*
  148. + func(WINE_AL_1_1, ALvoid, alListener3i, (ALenum param, ALint v1, ALint v2, ALint v3), (param, v1, v2, v3))\
  149. + func(WINE_AL_1_1, ALvoid, alListeneriv, (ALenum param, ALint *values), (param, values))\
  150. + func(WINE_AL_1_1, ALvoid, alGetListener3i, (ALenum param, ALint *v1, ALint *v2, ALint *v3), (param, v1, v2, v3))\
  151. + func(WINE_AL_1_1, ALvoid, alSource3i, (ALuint source, ALenum param, ALint v1, ALint v2, ALint v3), (source, param, v1, v2, v3))\
  152. + func(WINE_AL_1_1, ALvoid, alSourceiv, (ALuint source, ALenum param, ALint *values), (source, param, values))\
  153. + func(WINE_AL_1_1, ALvoid, alGetSource3i, (ALuint source, ALenum param, ALint *v1, ALint *v2, ALint *v3), (source, param, v1, v2, v3))\
  154. + func(WINE_AL_1_1, ALvoid, alBufferf, (ALuint buffer, ALenum param, ALfloat value), (buffer, param, value))\
  155. + func(WINE_AL_1_1, ALvoid, alBuffer3f, (ALuint buffer, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3), (buffer, param, v1, v2, v3))\
  156. + func(WINE_AL_1_1, ALvoid, alBufferfv, (ALuint buffer, ALenum param, ALfloat *values), (buffer, param, values))\
  157. + func(WINE_AL_1_1, ALvoid, alBufferi, (ALuint buffer, ALenum param, ALint value), (buffer, param, value))\
  158. + func(WINE_AL_1_1, ALvoid, alBuffer3i, (ALuint buffer, ALenum param, ALint v1, ALint v2, ALint v3), (buffer, param, v1, v2, v3))\
  159. + func(WINE_AL_1_1, ALvoid, alBufferiv, (ALuint buffer, ALenum param, ALint *values), (buffer, param, values))\
  160. + func(WINE_AL_1_1, ALvoid, alGetBuffer3f, (ALuint buffer, ALenum pname, ALfloat *v1, ALfloat *v2, ALfloat *v3), (buffer, pname, v1, v2, v3))\
  161. + func(WINE_AL_1_1, ALvoid, alGetBuffer3i, (ALuint buffer, ALenum pname, ALint *v1, ALint *v2, ALint *v3), (buffer, pname, v1, v2, v3))\
  162. + func(WINE_AL_1_1, ALvoid, alSpeedOfSound, (ALfloat value), (value))
  163. +*/
  164. +
  165. +/* OpenAL 1.1 functions */
  166. +#define WINE_ALC_1_1_FUNCS(func)\
  167. + func(WINE_ALC_1_1, ALCdevice * , alcCaptureOpenDevice, ( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ), ( devicename, frequency, format, buffersize ))\
  168. + func(WINE_ALC_1_1, ALCboolean , alcCaptureCloseDevice, ( ALCdevice *device ), ( device ))\
  169. + func(WINE_ALC_1_1, void , alcCaptureStart, ( ALCdevice *device ), ( device ))\
  170. + func(WINE_ALC_1_1, void , alcCaptureStop, ( ALCdevice *device ), ( device ))\
  171. + func(WINE_ALC_1_1, void , alcCaptureSamples, ( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ), ( device, buffer, samples ))
  172. +
  173. +#define WINE_AL_1_1_FUNCS(func)\
  174. + func(WINE_AL_1_1, void , alListener3i, ( ALenum param, ALint value1, ALint value2, ALint value3 ), ( param, value1, value2, value3 ))\
  175. + func(WINE_AL_1_1, void , alListeneriv, ( ALenum param, const ALint* values ), ( param, values ))\
  176. + func(WINE_AL_1_1, void , alGetListener3i, ( ALenum param, ALint *value1, ALint *value2, ALint *value3 ), ( param, value1, value2, value3 ))\
  177. + func(WINE_AL_1_1, void , alSource3i, ( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ), ( sid, param, value1, value2, value3 ))\
  178. + func(WINE_AL_1_1, void , alSourceiv, ( ALuint sid, ALenum param, const ALint* values ), ( sid, param, values ))\
  179. + func(WINE_AL_1_1, void , alGetSource3i, ( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3), ( sid, param, value1, value2, value3))\
  180. + func(WINE_AL_1_1, void , alBufferf, ( ALuint bid, ALenum param, ALfloat value), ( bid, param, value))\
  181. + func(WINE_AL_1_1, void , alBuffer3f, ( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( bid, param, value1, value2, value3 ))\
  182. + func(WINE_AL_1_1, void , alBufferfv, ( ALuint bid, ALenum param, const ALfloat* values ), ( bid, param, values ))\
  183. + func(WINE_AL_1_1, void , alBufferi, ( ALuint bid, ALenum param, ALint value), ( bid, param, value))\
  184. + func(WINE_AL_1_1, void , alBuffer3i, ( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ), ( bid, param, value1, value2, value3 ))\
  185. + func(WINE_AL_1_1, void , alBufferiv, ( ALuint bid, ALenum param, const ALint* values ), ( bid, param, values ))\
  186. + func(WINE_AL_1_1, void , alGetBuffer3f, ( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3), ( bid, param, value1, value2, value3))\
  187. + func(WINE_AL_1_1, void , alGetBuffer3i, ( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3), ( bid, param, value1, value2, value3))\
  188. + func(WINE_AL_1_1, void , alSpeedOfSound, ( ALfloat value ), ( value ))
  189. +
  190. +/* OpenAL extension functions */
  191. +#define WINE_ALC_EXT_FUNCS(func)\
  192. + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alcMacOSXRenderingQualityProcPtr, (const ALint value), (value))\
  193. + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alMacOSXRenderChannelCountProcPtr, (const ALint value), (value))\
  194. + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alcMacOSXMixerMaxiumumBussesProcPtr, (const ALint value), (value))\
  195. + func(WINE_ALC_EXT_MAC_OSX, ALvoid, alcMacOSXMixerOutputRateProcPtr, (const ALdouble value), (value))\
  196. + func(WINE_ALC_EXT_MAC_OSX, ALint, alcMacOSXGetRenderingQualityProcPtr, (), ())\
  197. + func(WINE_ALC_EXT_MAC_OSX, ALint, alMacOSXGetRenderChannelCountProcPtr, (), ())\
  198. + func(WINE_ALC_EXT_MAC_OSX, ALint, alcMacOSXGetMixerMaxiumumBussesProcPtr, (), ())\
  199. + func(WINE_ALC_EXT_MAC_OSX, ALdouble, alcMacOSXGetMixerOutputRateProcPtr, (), ())\
  200. + func(WINE_ALC_EXT_ASA, ALenum, alcASAGetSourceProcPtr, (const ALuint property, ALuint source, ALvoid *data, ALuint* dataSize), (property, source, data, dataSize))\
  201. + func(WINE_ALC_EXT_ASA, ALenum, alcASASetSourceProcPtr, (const ALuint property, ALuint source, ALvoid *data, ALuint dataSize), (property, source, data, dataSize))\
  202. + func(WINE_ALC_EXT_ASA, ALenum, alcASAGetListenerProcPtr, (const ALuint property, ALvoid *data, ALuint* dataSize), (property, data, dataSize))\
  203. + func(WINE_ALC_EXT_ASA, ALenum, alcASASetListenerProcPtr, (const ALuint property, ALvoid *data, ALuint dataSize), (property, data, dataSize))
  204. +
  205. +#define WINE_AL_EXT_FUNCS(func)\
  206. + func(WINE_AL_EXT_STATIC_BUFFER, ALvoid, alBufferDataStatic, (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq), (bid, format, data, size, freq))
  207. +
  208. +#define WINE_ALUT_FUNCS(func)\
  209. + func(WINE_ALUT, ALvoid , alutInit , (ALint *argcp, ALbyte **argv), (argcp, argv))\
  210. + func(WINE_ALUT, ALvoid , alutExit , (ALvoid), ())\
  211. +/* Nasty Compatibility stuff, WARNING: THESE FUNCTIONS ARE STRONGLY DEPRECATED */\
  212. +/* handled differently */\
  213. +/* func(WINE_ALUT, ALvoid , alutLoadWAVFile , (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency), (fileName, format, data, size, frequency))*/\
  214. +/* func(WINE_ALUT, ALvoid , alutLoadWAVMemory , (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency), (buffer, format, data, size, frequency))*/\
  215. + func(WINE_ALUT, ALvoid , alutUnloadWAV , (ALenum format, ALvoid *data, ALsizei size, ALsizei frequency), (format, data, size, frequency))
  216. +
  217. +/*
  218. + func(WINE_ALUT, ALboolean , alutInit , (int *argcp, char **argv), (argcp, argv))\
  219. + func(WINE_ALUT, ALboolean , alutExit , (void), ())\
  220. + func(WINE_ALUT, ALboolean , alutInitWithoutContext , (int *argcp, char **argv), (argcp, argv))\
  221. + func(WINE_ALUT, ALenum , alutGetError , (void), ())\
  222. + func(WINE_ALUT, const char *, alutGetErrorString , (ALenum error), (error))\
  223. + func(WINE_ALUT, ALuint , alutCreateBufferFromFile , (const char *fileName), (fileName))\
  224. + func(WINE_ALUT, ALuint , alutCreateBufferFromFileImage , (const ALvoid *data, ALsizei length), (data, length))\
  225. + func(WINE_ALUT, ALuint , alutCreateBufferHelloWorld , (void), ())\
  226. + func(WINE_ALUT, ALuint , alutCreateBufferWaveform , (ALenum waveshape, ALfloat frequency, ALfloat phase, ALfloat duration), (waveshape, frequency, phase, duration))\
  227. + func(WINE_ALUT, ALvoid *, alutLoadMemoryFromFile , (const char *fileName, ALenum *format, ALsizei *size, ALfloat *frequency), (fileName, format, size, frequency))\
  228. + func(WINE_ALUT, ALvoid *, alutLoadMemoryFromFileImage , (const ALvoid *data, ALsizei length, ALenum *format, ALsizei *size, ALfloat *frequency), (data, length, format, size, frequency))\
  229. + func(WINE_ALUT, ALvoid *, alutLoadMemoryHelloWorld , (ALenum *format, ALsizei *size, ALfloat *frequency), (format, size, frequency))\
  230. + 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))\
  231. + func(WINE_ALUT, const char *, alutGetMIMETypes , (ALenum loader), (loader))\
  232. + func(WINE_ALUT, ALint , alutGetMajorVersion , (void), ())\
  233. + func(WINE_ALUT, ALint , alutGetMinorVersion , (void), ())\
  234. + func(WINE_ALUT, ALboolean , alutSleep , (ALfloat duration), (duration))
  235. +*/
  236. +
  237. +#if defined(__APPLE__)
  238. + /* Incorrectly defined in Mac OSX */
  239. + #define WINE_ALUT_BAD_FUNCS(func)
  240. +#else
  241. + #define WINE_ALUT_BAD_FUNCS(func)\
  242. + func(WINE_ALUT, ALvoid , alutLoadWAVFile , (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop), (fileName, format, data, size, frequency, loop))\
  243. + func(WINE_ALUT, ALvoid , alutLoadWAVMemory , (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop), (buffer, format, data, size, frequency, loop))
  244. +#endif
  245. +
  246. +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
  247. +
  248. +/* OpenAL error checking (should be able to turn this off for release builds) */
  249. +#define CHECK_ALC_ERROR(al_device)\
  250. +{\
  251. + ALenum error;\
  252. + if(al_device)\
  253. + {\
  254. + error = alcGetError(al_device);\
  255. + if(error)\
  256. + {\
  257. + ERR("ALC ERROR: %s at %s:%d\n", alcGetString(al_device, error), __FILE__, __LINE__);\
  258. + }\
  259. + }\
  260. + else\
  261. + {\
  262. + ERR("Invalid al device at %s:%d\n", __FILE__, __LINE__);\
  263. + }\
  264. +}
  265. +
  266. +#define CHECK_AL_ERROR()\
  267. +{\
  268. + ALenum error;\
  269. + error = alGetError();\
  270. + if(error)\
  271. + {\
  272. + ERR("AL ERROR: %s at %s:%d\n", alGetString(error), __FILE__, __LINE__);\
  273. + }\
  274. +}
  275. +
  276. +static HMODULE openal32_handle;
  277. +
  278. +/* Make the thunking functions */
  279. +
  280. +#define MAKE_WINE_ALC_FUNCS(ext, ret, name, params, args)\
  281. + ret CDECL wine_##name params\
  282. + {\
  283. + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
  284. + return name args;\
  285. + }
  286. +
  287. +#define MAKE_WINE_AL_FUNCS(ext, ret, name, params, args)\
  288. + ret CDECL wine_##name params\
  289. + {\
  290. + /*CHECK_AL_ERROR();*/\
  291. + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
  292. + return name args;\
  293. + }
  294. +
  295. +#define MAKE_WINE_ALC_EXT_FUNCS(ext, ret, name, params, args)\
  296. + typedef ret (*t##name) params;\
  297. + static t##name p_##name = NULL;\
  298. + ret CDECL wine_##name params\
  299. + {\
  300. + /* should these functions be cached? */\
  301. + p_##name = (t##name)alcGetProcAddress(NULL, #name);\
  302. + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
  303. + return p_##name args;\
  304. + }
  305. +
  306. +#define MAKE_WINE_AL_EXT_FUNCS(ext, ret, name, params, args)\
  307. + typedef ret (*t##name) params;\
  308. + static t##name p_##name = NULL;\
  309. + ret CDECL wine_##name params\
  310. + {\
  311. + /*CHECK_AL_ERROR();*/\
  312. + /* should these functions be cached? */\
  313. + p_##name = (t##name)alGetProcAddress(#name);\
  314. + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
  315. + return p_##name args;\
  316. + }
  317. +
  318. +#define MAKE_WINE_ALUT_FUNCS(ext, ret, name, params, args)\
  319. + extern ret name params;\
  320. + ret CDECL wine_##name params\
  321. + {\
  322. + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
  323. + return name args;\
  324. + }
  325. +
  326. + WINE_ALC_1_0_FUNCS(MAKE_WINE_ALC_FUNCS)
  327. + WINE_AL_1_0_FUNCS(MAKE_WINE_AL_FUNCS)
  328. + WINE_ALC_1_1_FUNCS(MAKE_WINE_ALC_EXT_FUNCS)
  329. + WINE_AL_1_1_FUNCS(MAKE_WINE_AL_EXT_FUNCS)
  330. + WINE_ALC_EXT_FUNCS(MAKE_WINE_ALC_EXT_FUNCS)
  331. + WINE_AL_EXT_FUNCS(MAKE_WINE_AL_EXT_FUNCS)
  332. + WINE_ALUT_FUNCS(MAKE_WINE_ALUT_FUNCS)
  333. + WINE_ALUT_BAD_FUNCS(MAKE_WINE_ALUT_FUNCS)
  334. +
  335. +#undef MAKE_WINE_ALC_FUNCS
  336. +#undef MAKE_WINE_AL_FUNCS
  337. +#undef MAKE_WINE_ALC_EXT_FUNCS
  338. +#undef MAKE_WINE_AL_EXT_FUNCS
  339. +#undef MAKE_WINE_ALUT_FUNCS
  340. +
  341. +
  342. +void* CDECL wine_alcGetProcAddress(ALCdevice *device, const ALCchar *funcname)
  343. +{
  344. + void* ret = NULL;
  345. + TRACE("funcname == %s, ext == %s\n", funcname, wine_al_ext_to_string(WINE_ALC_1_0));
  346. + /* TODO: maybe check an ext registry/versions? */
  347. + /*
  348. + Checks similar to the following could be done...
  349. + alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE");
  350. + alcIsExtensionPresent(NULL, "AL_EXT_STATIC_BUFFER");
  351. + */
  352. + /* be consistent with the underlying impl */
  353. + if (alcGetProcAddress(device, funcname))
  354. + {
  355. + ret = GetProcAddress(openal32_handle, funcname);
  356. + }
  357. + TRACE("funcname == %s, ret == %p\n", funcname, ret);
  358. + return ret;
  359. +}
  360. +
  361. +void* CDECL wine_alGetProcAddress(const ALchar* fname)
  362. +{
  363. + void* ret = NULL;
  364. + TRACE("fname == %s, ext == %s\n", fname, wine_al_ext_to_string(WINE_AL_1_0));
  365. + /* TODO: maybe check an ext registry/versions? */
  366. + /*
  367. + Checks similar to the following could be done...
  368. + alIsExtensionPresent("ALC_EXT_CAPTURE");
  369. + alIsExtensionPresent("AL_EXT_STATIC_BUFFER");
  370. + */
  371. + /* be consistent with the underlying impl */
  372. + if (alGetProcAddress(fname))
  373. + {
  374. + ret = GetProcAddress(openal32_handle, fname);
  375. + }
  376. + TRACE("fname == %s, ret == %p\n", fname, ret);
  377. + return ret;
  378. +}
  379. +
  380. +#if defined(__APPLE__)
  381. + /* Incorrectly defined in Mac OSX */
  382. + extern ALvoid alutLoadWAVFile (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency);
  383. + ALvoid CDECL wine_alutLoadWAVFile (ALbyte *fileName, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop)
  384. + {
  385. + /* do what with loop? */
  386. + TRACE("ext == %s\n", wine_al_ext_to_string(WINE_ALUT));
  387. + return alutLoadWAVFile (fileName, format, data, size, frequency);
  388. + }
  389. +
  390. + extern ALvoid alutLoadWAVMemory (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency);
  391. + ALvoid CDECL wine_alutLoadWAVMemory (ALbyte *buffer, ALenum *format, ALvoid **data, ALsizei *size, ALsizei *frequency, ALboolean *loop)
  392. + {
  393. + /* do what with loop? */
  394. + TRACE("ext == %s\n", wine_al_ext_to_string(WINE_ALUT));
  395. + return alutLoadWAVMemory (buffer, format, data, size, frequency);
  396. + }
  397. +#endif
  398. +
  399. +
  400. +/***********************************************************************
  401. + * OpenAL initialisation routine
  402. + */
  403. +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
  404. +{
  405. + switch(reason)
  406. + {
  407. + case DLL_PROCESS_ATTACH:
  408. + openal32_handle = hinst;
  409. + /*DisableThreadLibraryCalls(hinst);*/
  410. + break;
  411. + case DLL_PROCESS_DETACH:
  412. + /*process_detach();*/
  413. + break;
  414. + }
  415. + return TRUE;
  416. +}
  417. +
  418. +
  419. +#else /* !defined(HAVE_OPENAL_AL_H) && !defined(HAVE_AL_AL_H) */
  420. +
  421. +#define MAKE_FAKE_WINE_FUNCS(ext, ret, name, params, args)\
  422. + void CDECL wine_##name ()\
  423. + {\
  424. + TRACE("ext == %s\n", wine_al_ext_to_string(ext));\
  425. + FIXME("OpenAL not supported on this system\n");\
  426. + }
  427. + WINE_ALC_1_0_FUNCS(MAKE_FAKE_WINE_FUNCS)
  428. + WINE_AL_1_0_FUNCS(MAKE_FAKE_WINE_FUNCS)
  429. + WINE_ALUT_FUNCS(MAKE_FAKE_WINE_FUNCS)
  430. + WINE_ALUT_BAD_FUNCS(MAKE_FAKE_WINE_FUNCS)
  431. +#undef MAKE_WINE_FUNCS
  432. +
  433. +
  434. +void CDECL wine_alcGetProcAddress()
  435. +{
  436. + FIXME("OpenAL not supported on this system\n");
  437. +}
  438. +
  439. +void CDECL wine_alGetProcAddress()
  440. +{
  441. + FIXME("OpenAL not supported on this system\n");
  442. +}
  443. +
  444. +#if defined(__APPLE__)
  445. + /* Incorrectly defined in Mac OSX */
  446. + void CDECL wine_alutLoadWAVFile ()
  447. + {
  448. + FIXME("OpenAL not supported on this system\n");
  449. + }
  450. +
  451. + void CDECL wine_alutLoadWAVMemory ()
  452. + {
  453. + FIXME("OpenAL not supported on this system\n");
  454. + }
  455. +#endif
  456. +
  457. +
  458. +/***********************************************************************
  459. + * OpenAL initialisation routine
  460. + */
  461. +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
  462. +{
  463. + FIXME("OpenAL not supported on this system\n");
  464. + return TRUE;
  465. +}
  466. +
  467. +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
  468. \ No newline at end of file
  469. diff --git a/dlls/openal32/openal32.spec b/dlls/openal32/openal32.spec
  470. new file mode 100644
  471. index 0000000..395e660
  472. --- /dev/null
  473. +++ b/dlls/openal32/openal32.spec
  474. @@ -0,0 +1,133 @@
  475. +#OpenAL ALC_1_0
  476. +@ cdecl alcCreateContext(ptr ptr ) wine_alcCreateContext
  477. +@ cdecl alcMakeContextCurrent(ptr) wine_alcMakeContextCurrent
  478. +@ cdecl alcProcessContext(ptr) wine_alcProcessContext
  479. +@ cdecl alcSuspendContext(ptr) wine_alcSuspendContext
  480. +@ cdecl alcDestroyContext(ptr) wine_alcDestroyContext
  481. +@ cdecl alcGetCurrentContext( ) wine_alcGetCurrentContext
  482. +@ cdecl alcGetContextsDevice(ptr) wine_alcGetContextsDevice
  483. +@ cdecl alcOpenDevice(str) wine_alcOpenDevice
  484. +@ cdecl alcCloseDevice(ptr) wine_alcCloseDevice
  485. +@ cdecl alcGetError(ptr) wine_alcGetError
  486. +@ cdecl alcIsExtensionPresent(ptr str) wine_alcIsExtensionPresent
  487. +@ cdecl alcGetProcAddress(ptr str) wine_alcGetProcAddress
  488. +@ cdecl alcGetEnumValue(ptr str) wine_alcGetEnumValue
  489. +@ cdecl alcGetString(ptr long ) wine_alcGetString
  490. +@ cdecl alcGetIntegerv(ptr long long ptr) wine_alcGetIntegerv
  491. +#OpenAL AL_1_0
  492. +@ cdecl alEnable(long ) wine_alEnable
  493. +@ cdecl alDisable(long ) wine_alDisable
  494. +@ cdecl alIsEnabled(long ) wine_alIsEnabled
  495. +@ cdecl alGetString(long ) wine_alGetString
  496. +@ cdecl alGetBooleanv(long ptr ) wine_alGetBooleanv
  497. +@ cdecl alGetIntegerv(long ptr ) wine_alGetIntegerv
  498. +@ cdecl alGetFloatv(long ptr ) wine_alGetFloatv
  499. +@ cdecl alGetDoublev(long ptr ) wine_alGetDoublev
  500. +@ cdecl alGetBoolean(long ) wine_alGetBoolean
  501. +@ cdecl alGetInteger(long ) wine_alGetInteger
  502. +@ cdecl alGetFloat(long ) wine_alGetFloat
  503. +@ cdecl alGetDouble(long ) wine_alGetDouble
  504. +@ cdecl alGetError( ) wine_alGetError
  505. +@ cdecl alIsExtensionPresent(str ) wine_alIsExtensionPresent
  506. +@ cdecl alGetProcAddress(str ) wine_alGetProcAddress
  507. +@ cdecl alGetEnumValue(str ) wine_alGetEnumValue
  508. +@ cdecl alListenerf(long long ) wine_alListenerf
  509. +@ cdecl alListener3f(long long long long ) wine_alListener3f
  510. +@ cdecl alListenerfv(long ptr ) wine_alListenerfv
  511. +@ cdecl alListeneri(long long ) wine_alListeneri
  512. +@ cdecl alGetListenerf(long ptr ) wine_alGetListenerf
  513. +@ cdecl alGetListener3f(long ptr ptr ptr) wine_alGetListener3f
  514. +@ cdecl alGetListenerfv(long ptr ) wine_alGetListenerfv
  515. +@ cdecl alGetListeneri(long ptr ) wine_alGetListeneri
  516. +@ cdecl alGetListeneriv(long ptr ) wine_alGetListeneriv
  517. +@ cdecl alGenSources(long ptr ) wine_alGenSources
  518. +@ cdecl alDeleteSources(long ptr ) wine_alDeleteSources
  519. +@ cdecl alIsSource(long ) wine_alIsSource
  520. +@ cdecl alSourcef(long long long ) wine_alSourcef
  521. +@ cdecl alSource3f(long long long long long ) wine_alSource3f
  522. +@ cdecl alSourcefv(long long ptr ) wine_alSourcefv
  523. +@ cdecl alSourcei(long long long ) wine_alSourcei
  524. +@ cdecl alGetSourcef(long long ptr ) wine_alGetSourcef
  525. +@ cdecl alGetSource3f(long long ptr ptr ptr ) wine_alGetSource3f
  526. +@ cdecl alGetSourcefv(long long ptr ) wine_alGetSourcefv
  527. +@ cdecl alGetSourcei(long long ptr ) wine_alGetSourcei
  528. +@ cdecl alGetSourceiv(long long ptr ) wine_alGetSourceiv
  529. +@ cdecl alSourcePlayv(long ptr) wine_alSourcePlayv
  530. +@ cdecl alSourceStopv(long ptr) wine_alSourceStopv
  531. +@ cdecl alSourceRewindv(long ptr) wine_alSourceRewindv
  532. +@ cdecl alSourcePausev(long ptr) wine_alSourcePausev
  533. +@ cdecl alSourcePlay(long ) wine_alSourcePlay
  534. +@ cdecl alSourceStop(long ) wine_alSourceStop
  535. +@ cdecl alSourceRewind(long ) wine_alSourceRewind
  536. +@ cdecl alSourcePause(long ) wine_alSourcePause
  537. +@ cdecl alSourceQueueBuffers(long long ptr) wine_alSourceQueueBuffers
  538. +@ cdecl alSourceUnqueueBuffers(long long ptr) wine_alSourceUnqueueBuffers
  539. +@ cdecl alGenBuffers(long ptr ) wine_alGenBuffers
  540. +@ cdecl alDeleteBuffers(long ptr ) wine_alDeleteBuffers
  541. +@ cdecl alIsBuffer(long ) wine_alIsBuffer
  542. +@ cdecl alBufferData(long long ptr long long ) wine_alBufferData
  543. +@ cdecl alGetBufferf(long long ptr ) wine_alGetBufferf
  544. +@ cdecl alGetBufferfv(long long ptr ) wine_alGetBufferfv
  545. +@ cdecl alGetBufferi(long long ptr ) wine_alGetBufferi
  546. +@ cdecl alGetBufferiv(long long ptr ) wine_alGetBufferiv
  547. +@ cdecl alDopplerFactor(long ) wine_alDopplerFactor
  548. +@ cdecl alDopplerVelocity(long ) wine_alDopplerVelocity
  549. +@ cdecl alDistanceModel(long ) wine_alDistanceModel
  550. +#OpenAL ALC_1_1
  551. +#@ cdecl alcCaptureOpenDevice(str long long long ) wine_alcCaptureOpenDevice
  552. +#@ cdecl alcCaptureCloseDevice(ptr) wine_alcCaptureCloseDevice
  553. +#@ cdecl alcCaptureStart(ptr) wine_alcCaptureStart
  554. +#@ cdecl alcCaptureStop(ptr) wine_alcCaptureStop
  555. +#@ cdecl alcCaptureSamples(ptr ptr long ) wine_alcCaptureSamples
  556. +#OpenAL AL_1_1
  557. +#@ cdecl alListener3i(long long long long ) wine_alListener3i
  558. +#@ cdecl alListeneriv(long ptr ) wine_alListeneriv
  559. +#@ cdecl alGetListener3i(long ptr ptr ptr) wine_alGetListener3i
  560. +#@ cdecl alSource3i(long long long long long ) wine_alSource3i
  561. +#@ cdecl alSourceiv(long long ptr ) wine_alSourceiv
  562. +#@ cdecl alGetSource3i(long long ptr ptr ptr ) wine_alGetSource3i
  563. +#@ cdecl alBufferf(long long long ) wine_alBufferf
  564. +#@ cdecl alBuffer3f(long long long long long ) wine_alBuffer3f
  565. +#@ cdecl alBufferfv(long long ptr ) wine_alBufferfv
  566. +#@ cdecl alBufferi(long long long ) wine_alBufferi
  567. +#@ cdecl alBuffer3i(long long long long long ) wine_alBuffer3i
  568. +#@ cdecl alBufferiv(long long ptr ) wine_alBufferiv
  569. +#@ cdecl alGetBuffer3f(long long ptr ptr ptr ) wine_alGetBuffer3f
  570. +#@ cdecl alGetBuffer3i(long long ptr ptr ptr ) wine_alGetBuffer3i
  571. +#@ cdecl alSpeedOfSound(long ) wine_alSpeedOfSound
  572. +#OpenAL extensions
  573. +#@ cdecl alcMacOSXRenderingQualityProcPtr(long ) wine_alcMacOSXRenderingQualityProcPtr
  574. +#@ cdecl alMacOSXRenderChannelCountProcPtr(long ) wine_alMacOSXRenderChannelCountProcPtr
  575. +#@ cdecl alcMacOSXMixerMaxiumumBussesProcPtr(long ) wine_alcMacOSXMixerMaxiumumBussesProcPtr
  576. +#@ cdecl alcMacOSXMixerOutputRateProcPtr(double ) wine_alcMacOSXMixerOutputRateProcPtr
  577. +#@ cdecl alcMacOSXGetRenderingQualityProcPtr() wine_alcMacOSXGetRenderingQualityProcPtr
  578. +#@ cdecl alMacOSXGetRenderChannelCountProcPtr() wine_alMacOSXGetRenderChannelCountProcPtr
  579. +#@ cdecl alcMacOSXGetMixerMaxiumumBussesProcPtr() wine_alcMacOSXGetMixerMaxiumumBussesProcPtr
  580. +#@ cdecl alcMacOSXGetMixerOutputRateProcPtr() wine_alcMacOSXGetMixerOutputRateProcPtr
  581. +#@ cdecl alBufferDataStatic(long long ptr long long ) wine_alBufferDataStatic
  582. +#@ cdecl alcASAGetSourceProcPtr(long long ptr ptr ) wine_alcASAGetSourceProcPtr
  583. +#@ cdecl alcASASetSourceProcPtr(long long ptr long ) wine_alcASASetSourceProcPtr
  584. +#@ cdecl alcASAGetListenerProcPtr(long ptr ptr ) wine_alcASAGetListenerProcPtr
  585. +#@ cdecl alcASASetListenerProcPtr(long ptr long ) wine_alcASASetListenerProcPtr
  586. +#OpenAL ALUT -- now part of freealut -- but binary compat requires this section
  587. +@ cdecl alutInit ( ptr ptr) wine_alutInit
  588. +@ cdecl alutExit () wine_alutExit
  589. +@ cdecl alutLoadWAVFile ( ptr ptr ptr ptr ptr ptr) wine_alutLoadWAVFile
  590. +@ cdecl alutLoadWAVMemory ( ptr ptr ptr ptr ptr ptr) wine_alutLoadWAVMemory
  591. +@ cdecl alutUnloadWAV ( long ptr long long) wine_alutUnloadWAV
  592. +#OpenAL ALUT new
  593. +#@ cdecl alutInitWithoutContext ( ptr ptr) wine_alutInitWithoutContext
  594. +#@ cdecl alutGetError () wine_alutGetError
  595. +#@ cdecl alutGetErrorString ( long) wine_alutGetErrorString
  596. +#@ cdecl alutCreateBufferFromFile ( ptr) wine_alutCreateBufferFromFile
  597. +#@ cdecl alutCreateBufferFromFileImage ( ptr long) wine_alutCreateBufferFromFileImage
  598. +#@ cdecl alutCreateBufferHelloWorld () wine_alutCreateBufferHelloWorld
  599. +#@ cdecl alutCreateBufferWaveform ( long long long long) wine_alutCreateBufferWaveform
  600. +#@ cdecl alutLoadMemoryFromFile ( ptr ptr ptr ptr) wine_alutLoadMemoryFromFile
  601. +#@ cdecl alutLoadMemoryFromFileImage ( ptr long ptr ptr ptr) wine_alutLoadMemoryFromFileImage
  602. +#@ cdecl alutLoadMemoryHelloWorld ( ptr ptr ptr) wine_alutLoadMemoryHelloWorld
  603. +#@ cdecl alutLoadMemoryWaveform ( long long long long ptr ptr ptr) wine_alutLoadMemoryWaveform
  604. +#@ cdecl alutGetMIMETypes ( long) wine_alutGetMIMETypes
  605. +#@ cdecl alutGetMajorVersion () wine_alutGetMajorVersion
  606. +#@ cdecl alutGetMinorVersion () wine_alutGetMinorVersion
  607. +#@ cdecl alutSleep ( long) wine_alutSleep
  608. diff --git a/dlls/wineopenal.drv/Makefile.in b/dlls/wineopenal.drv/Makefile.in
  609. new file mode 100644
  610. index 0000000..0b24659
  611. --- /dev/null
  612. +++ b/dlls/wineopenal.drv/Makefile.in
  613. @@ -0,0 +1,15 @@
  614. +TOPSRCDIR = @top_srcdir@
  615. +TOPOBJDIR = ../../..
  616. +SRCDIR = @srcdir@
  617. +VPATH = @srcdir@
  618. +MODULE = wineopenal.drv
  619. +IMPORTS = winmm user32 kernel32
  620. +EXTRALIBS = $(LIBUUID) @OPENAL@
  621. +
  622. +C_SRCS = \
  623. + audio.c \
  624. + openal.c
  625. +
  626. +@MAKE_DLL_RULES@
  627. +
  628. +### Dependencies:
  629. diff --git a/dlls/wineopenal.drv/audio.c b/dlls/wineopenal.drv/audio.c
  630. new file mode 100644
  631. index 0000000..0d13394
  632. --- /dev/null
  633. +++ b/dlls/wineopenal.drv/audio.c
  634. @@ -0,0 +1,2638 @@
  635. +/*
  636. + * Wine Driver for OpenAL
  637. + * http://www.openal.org
  638. + *
  639. + * Copyright 1994 Martin Ayotte
  640. + * 1999 Eric Pouech (async playing in waveOut/waveIn)
  641. + * 2000 Eric Pouech (loops in waveOut)
  642. + * 2004 Zhangrong Huang (EsounD version of this file)
  643. + * 2006 Nick Burns (OpenAL version of this file)
  644. + *
  645. + * This library is free software; you can redistribute it and/or
  646. + * modify it under the terms of the GNU Lesser General Public
  647. + * License as published by the Free Software Foundation; either
  648. + * version 2.1 of the License, or (at your option) any later version.
  649. + *
  650. + * This library is distributed in the hope that it will be useful,
  651. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  652. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  653. + * Lesser General Public License for more details.
  654. + *
  655. + * You should have received a copy of the GNU Lesser General Public
  656. + * License along with this library; if not, write to the Free Software
  657. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  658. + */
  659. +
  660. +/*
  661. + * NOTE: Any problems the ESD driver has this will most likely have.
  662. + */
  663. +
  664. +/*
  665. + * TODO: Use AL_EXT_STATIC_BUFFER to cut down on mem copies
  666. + */
  667. +
  668. +/*
  669. + * TODO: Query max number of buffers -- never exceed that max
  670. + * (PARTIAL FIX): OPENAL_MAX_BUFFERS should be set to the smallest max
  671. + */
  672. +
  673. +/*
  674. + * (FIXED): There is a problem here in sndrec32.exe
  675. + * If you play a file and totally keep seeking while its playing
  676. + * It will keep creating buffers as it thinks many are still in use
  677. + * However they should not be inuse...
  678. + *
  679. + * Note: The above issue is mostly fixed by removing the stop/pause parts from wodReset
  680. + * -- and limiting the max buffers to OPENAL_MAX_BUFFERS
  681. + */
  682. +
  683. +/*
  684. + * (FIXED): Determine why sometimes invalid enums and values spew from wodQueueBuffer
  685. + * This happened because we have run out of buffers .: OPENAL_MAX_BUFFERS
  686. + */
  687. +
  688. +/*
  689. + * (FIXED): Determine why sometimes invalid device spews from OpenAL_WaveClose
  690. + * This happened because we just closed the device we were checking errors on
  691. + */
  692. +
  693. +/*
  694. + * TODO: Test this driver with something other than Mac OSX
  695. + */
  696. +
  697. +/*
  698. + * TODO: Sleep for a more accurate amount of time if past OPENAL_MAX_BUFFERS
  699. + * Know which buffer is being processed and wait exactly for it to be finished
  700. + * Must be able to get current position and track buffers... (maybe timestamps)
  701. + */
  702. +
  703. +#include "config.h"
  704. +
  705. +#include <errno.h>
  706. +#include <math.h>
  707. +#include <stdlib.h>
  708. +#include <stdarg.h>
  709. +#include <stdio.h>
  710. +#include <string.h>
  711. +#ifdef HAVE_UNISTD_H
  712. +# include <unistd.h>
  713. +#endif
  714. +#include <fcntl.h>
  715. +#ifdef HAVE_POLL_H
  716. +#include <poll.h>
  717. +#endif
  718. +#ifdef HAVE_SYS_POLL_H
  719. +# include <sys/poll.h>
  720. +#endif
  721. +
  722. +#include "windef.h"
  723. +#include "winbase.h"
  724. +#include "wingdi.h"
  725. +#include "winerror.h"
  726. +#include "wine/winuser16.h"
  727. +#include "mmddk.h"
  728. +#include "mmreg.h"
  729. +#include "dsound.h"
  730. +#include "dsdriver.h"
  731. +#include "ks.h"
  732. +#include "ksguid.h"
  733. +#include "ksmedia.h"
  734. +#include "wine/debug.h"
  735. +
  736. +#if defined(HAVE_OPENAL_AL_H)
  737. + #include <OpenAL/al.h>
  738. + #include <OpenAL/alc.h>
  739. +#elif defined(HAVE_AL_AL_H)
  740. + #include <AL/al.h>
  741. + #include <AL/alc.h>
  742. +#endif
  743. +
  744. +WINE_DEFAULT_DEBUG_CHANNEL(wave);
  745. +
  746. +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
  747. +
  748. +/* OpenAL 1.1 functions */
  749. +/* defined as return_type, func_name, params */
  750. +/* used to define func ptrs, get proc address, etc... */
  751. +#define OPENAL_1_1_ALC_FUNCS(func)\
  752. + func(ALCdevice*, alcCaptureOpenDevice, (const ALCbyte *deviceName, ALCuint freq, ALCenum fmt, ALCsizei bufsize))\
  753. + func(ALCboolean, alcCaptureCloseDevice, (ALCdevice *device))\
  754. + func(ALCvoid, alcCaptureStart, (ALCdevice *device))\
  755. + func(ALCvoid, alcCaptureStop, (ALCdevice *device))\
  756. + func(ALCvoid, alcCaptureSamples, (ALCdevice *device, ALCvoid *buf, ALCsizei samps))
  757. +
  758. +#define OPENAL_1_1_AL_FUNCS(func)\
  759. + func(ALvoid, alListener3i, (ALenum param, ALint v1, ALint v2, ALint v3))\
  760. + func(ALvoid, alListeneriv, (ALenum param, ALint *values))\
  761. + func(ALvoid, alGetListener3i, (ALenum param, ALint *v1, ALint *v2, ALint *v3))\
  762. + func(ALvoid, alSource3i, (ALuint source, ALenum param, ALint v1, ALint v2, ALint v3))\
  763. + func(ALvoid, alSourceiv, (ALuint source, ALenum param, ALint *values))\
  764. + func(ALvoid, alGetSource3i, (ALuint source, ALenum param, ALint *v1, ALint *v2, ALint *v3))\
  765. + func(ALvoid, alBufferf, (ALuint buffer, ALenum param, ALfloat value))\
  766. + func(ALvoid, alBuffer3f, (ALuint buffer, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3))\
  767. + func(ALvoid, alBufferfv, (ALuint buffer, ALenum param, ALfloat *values))\
  768. + func(ALvoid, alBufferi, (ALuint buffer, ALenum param, ALint value))\
  769. + func(ALvoid, alBuffer3i, (ALuint buffer, ALenum param, ALint v1, ALint v2, ALint v3))\
  770. + func(ALvoid, alBufferiv, (ALuint buffer, ALenum param, ALint *values))\
  771. + func(ALvoid, alGetBuffer3f, (ALuint buffer, ALenum pname, ALfloat *v1, ALfloat *v2, ALfloat *v3))\
  772. + func(ALvoid, alGetBuffer3i, (ALuint buffer, ALenum pname, ALint *v1, ALint *v2, ALint *v3))\
  773. + func(ALvoid, alSpeedOfSound, (ALfloat value))
  774. +
  775. +#define OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(func)\
  776. + func(ALvoid, alBufferDataStatic, (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq))
  777. +
  778. +#define MAKE_FUNC_PTR_TYPE(ret, name, params) typedef ret (*t##name) params;
  779. +OPENAL_1_1_ALC_FUNCS(MAKE_FUNC_PTR_TYPE);
  780. +OPENAL_1_1_AL_FUNCS(MAKE_FUNC_PTR_TYPE);
  781. +OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(MAKE_FUNC_PTR_TYPE);
  782. +#undef MAKE_FUNC_PTR_TYPE
  783. +
  784. +#define MAKE_FUNC_PTR(ret, name, params) static t##name p_##name = NULL;
  785. +OPENAL_1_1_ALC_FUNCS(MAKE_FUNC_PTR);
  786. +OPENAL_1_1_AL_FUNCS(MAKE_FUNC_PTR);
  787. +OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(MAKE_FUNC_PTR);
  788. +#undef MAKE_FUNC_PTR
  789. +
  790. +/* OpenAL 1.1 tokens */
  791. +/* I dont know which way is better... */
  792. +/* Since there is a alcGetEnumValue function it seems like thats the best solution */
  793. +#if 0
  794. +#ifndef ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
  795. + #define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
  796. +#endif
  797. +#ifndef ALC_CAPTURE_DEVICE_SPECIFIER
  798. + #define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
  799. +#endif
  800. +#ifndef ALC_CAPTURE_SAMPLES
  801. + #define ALC_CAPTURE_SAMPLES 0x312
  802. +#endif
  803. +#else
  804. +#define OPENAL_1_1_ALC_TOKENS(func)\
  805. + func(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)\
  806. + func(ALC_CAPTURE_DEVICE_SPECIFIER)\
  807. + func(ALC_CAPTURE_SAMPLES)
  808. +
  809. +#define MAKE_TOKENS(name) static ALCenum t_##name = ALC_INVALID;
  810. +OPENAL_1_1_ALC_TOKENS(MAKE_TOKENS);
  811. +#undef MAKE_TOKENS
  812. +#endif
  813. +
  814. +/* Can we cap audio?? */
  815. +static int al_can_capture;
  816. +
  817. +/* Can use static buffers?? */
  818. +static int al_static_buffer;
  819. +
  820. +/* Enable capture at your own peril -- it SHOULD work and does in certain cases (but I cannot force them) */
  821. +#define OPENAL_DISABLE_IN (1)
  822. +#define OPENAL_LIMIT_OUT_44100 (0)
  823. +#define OPENAL_LIMIT_IN_44100 (0)
  824. +#define OPENAL_BUF_SIZE (4 * 1024)
  825. +/* fine tune this for more better goodness */
  826. +/* too many buffers -- laggggggggggg */
  827. +/* too few buffers -- fun crackling */
  828. +/* inf buffers -- not supported but cannot query limits */
  829. +#define OPENAL_MAX_BUFFERS (4)
  830. +
  831. +/* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
  832. +#define USE_PIPE_SYNC
  833. +
  834. +#define BUFFER_REFILL_THRESHOLD 4
  835. +
  836. +#define MAX_WAVEOUTDRV (10)
  837. +#define MAX_WAVEINDRV (10)
  838. +#define MAX_CHANNELS 2
  839. +
  840. +/* state diagram for waveOut writing:
  841. + *
  842. + * +---------+-------------+---------------+---------------------------------+
  843. + * | state | function | event | new state |
  844. + * +---------+-------------+---------------+---------------------------------+
  845. + * | | open() | | STOPPED |
  846. + * | PAUSED | write() | | PAUSED |
  847. + * | STOPPED | write() | <thrd create> | PLAYING |
  848. + * | PLAYING | write() | HEADER | PLAYING |
  849. + * | (other) | write() | <error> | |
  850. + * | (any) | pause() | PAUSING | PAUSED |
  851. + * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
  852. + * | (any) | reset() | RESETTING | STOPPED |
  853. + * | (any) | close() | CLOSING | CLOSED |
  854. + * +---------+-------------+---------------+---------------------------------+
  855. + */
  856. +
  857. +/* states of the playing device */
  858. +#define WINE_WS_PLAYING 0
  859. +#define WINE_WS_PAUSED 1
  860. +#define WINE_WS_STOPPED 2
  861. +#define WINE_WS_CLOSED 3
  862. +
  863. +/* events to be send to device */
  864. +enum win_wm_message {
  865. + WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
  866. + WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING
  867. +};
  868. +
  869. +#ifdef USE_PIPE_SYNC
  870. +#define SIGNAL_OMR(mr) do { int x = 0; write((mr)->msg_pipe[1], &x, sizeof(x)); } while (0)
  871. +#define CLEAR_OMR(mr) do { int x = 0; read((mr)->msg_pipe[0], &x, sizeof(x)); } while (0)
  872. +#define RESET_OMR(mr) do { } while (0)
  873. +#define WAIT_OMR(mr, sleep) \
  874. + do { struct pollfd pfd; pfd.fd = (mr)->msg_pipe[0]; \
  875. + pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
  876. +#else
  877. +#define SIGNAL_OMR(mr) do { SetEvent((mr)->msg_event); } while (0)
  878. +#define CLEAR_OMR(mr) do { } while (0)
  879. +#define RESET_OMR(mr) do { ResetEvent((mr)->msg_event); } while (0)
  880. +#define WAIT_OMR(mr, sleep) \
  881. + do { WaitForSingleObject((mr)->msg_event, sleep); } while (0)
  882. +#endif
  883. +
  884. +typedef struct {
  885. + enum win_wm_message msg; /* message identifier */
  886. + DWORD param; /* parameter for this message */
  887. + HANDLE hEvent; /* if message is synchronous, handle of event for synchro */
  888. +} RING_MSG;
  889. +
  890. +/* implement an in-process message ring for better performance
  891. + * (compared to passing thru the server)
  892. + * this ring will be used by the input (resp output) record (resp playback) routine
  893. + */
  894. +#define ESD_RING_BUFFER_INCREMENT 64
  895. +typedef struct {
  896. + RING_MSG* messages;
  897. + int ring_buffer_size;
  898. + int msg_tosave;
  899. + int msg_toget;
  900. +#ifdef USE_PIPE_SYNC
  901. + int msg_pipe[2];
  902. +#else
  903. + HANDLE msg_event;
  904. +#endif
  905. + CRITICAL_SECTION msg_crst;
  906. +} ESD_MSG_RING;
  907. +
  908. +typedef struct {
  909. + volatile int state; /* one of the WINE_WS_ manifest constants */
  910. + WAVEOPENDESC waveDesc;
  911. + WORD wFlags;
  912. + WAVEFORMATPCMEX waveFormat;
  913. + WAVEOUTCAPSW caps;
  914. + char interface_name[32];
  915. +
  916. + DWORD dwSleepTime; /* Num of milliseconds to sleep between filling the dsp buffers */
  917. +
  918. + /* OpenAL source */
  919. + int live;
  920. + ALuint al_source;
  921. + int num_al_buffers;
  922. + ALuint* al_buffers;
  923. + int num_free_al_buffers;
  924. + ALuint* free_al_buffers;
  925. +
  926. + int bytes_per_frame;
  927. + DWORD dwBufferSize; /* size of whole buffer in bytes */
  928. +
  929. + DWORD volume_left; /* volume control information */
  930. + DWORD volume_right;
  931. +
  932. + LPWAVEHDR lpQueuePtr; /* start of queued WAVEHDRs (waiting to be notified) */
  933. + LPWAVEHDR lpPlayPtr; /* start of not yet fully played buffers */
  934. + DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
  935. +
  936. + LPWAVEHDR lpLoopPtr; /* pointer of first buffer in loop, if any */
  937. + DWORD dwLoops; /* private copy of loop counter */
  938. +
  939. + DWORD dwPlayedTotal; /* number of bytes actually played since opening */
  940. + DWORD dwWrittenTotal; /* number of bytes written to the audio device since opening */
  941. +
  942. + /* synchronization stuff */
  943. + HANDLE hStartUpEvent;
  944. + HANDLE hThread;
  945. + DWORD dwThreadID;
  946. + ESD_MSG_RING msgRing;
  947. +} WINE_WAVEOUT;
  948. +
  949. +typedef struct {
  950. + volatile int state; /* one of the WINE_WS_ manifest constants */
  951. + WAVEOPENDESC waveDesc;
  952. + WORD wFlags;
  953. + WAVEFORMATPCMEX waveFormat;
  954. + WAVEINCAPSW caps;
  955. + char interface_name[32];
  956. +
  957. + /* OpenAL capture device */
  958. + int live;
  959. + ALCdevice* al_device;
  960. +
  961. + int bytes_per_frame;
  962. +
  963. + LPWAVEHDR lpQueuePtr;
  964. + DWORD dwRecordedTotal;
  965. +
  966. + /* synchronization stuff */
  967. + HANDLE hStartUpEvent;
  968. + HANDLE hThread;
  969. + DWORD dwThreadID;
  970. + ESD_MSG_RING msgRing;
  971. +} WINE_WAVEIN;
  972. +
  973. +/* OpenAL context for wave out */
  974. +static ALCdevice* al_device = NULL;
  975. +static ALCcontext* al_context = NULL;
  976. +
  977. +/* OpenAL error checking (should be able to turn this off for release builds) */
  978. +#define CHECK_ALC_ERROR()\
  979. +{\
  980. + ALenum error;\
  981. + if(al_device)\
  982. + {\
  983. + error = alcGetError(al_device);\
  984. + if(error)\
  985. + {\
  986. + ERR("ALC ERROR: %s at %s:%d\n", alcGetString(al_device, error), __FILE__, __LINE__);\
  987. + }\
  988. + }\
  989. + else\
  990. + {\
  991. + ERR("Invalid al device at %s:%d\n", __FILE__, __LINE__);\
  992. + }\
  993. +}
  994. +
  995. +#define CHECK_AL_ERROR()\
  996. +{\
  997. + ALenum error;\
  998. + error = alGetError();\
  999. + if(error)\
  1000. + {\
  1001. + ERR("AL ERROR: %s at %s:%d\n", alGetString(error), __FILE__, __LINE__);\
  1002. + }\
  1003. +}
  1004. +
  1005. +static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
  1006. +static WINE_WAVEIN WInDev [MAX_WAVEINDRV];
  1007. +
  1008. +static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
  1009. +static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
  1010. +
  1011. +static void wodDeleteBuffers(WINE_WAVEOUT* wwo);
  1012. +
  1013. +/* These strings used only for tracing */
  1014. +static const char *wodPlayerCmdString[] = {
  1015. + "WINE_WM_PAUSING",
  1016. + "WINE_WM_RESTARTING",
  1017. + "WINE_WM_RESETTING",
  1018. + "WINE_WM_HEADER",
  1019. + "WINE_WM_UPDATE",
  1020. + "WINE_WM_BREAKLOOP",
  1021. + "WINE_WM_CLOSING",
  1022. + "WINE_WM_STARTING",
  1023. + "WINE_WM_STOPPING",
  1024. +};
  1025. +
  1026. +/*======================================================================*
  1027. + * Low level WAVE implementation *
  1028. + *======================================================================*/
  1029. +
  1030. +ALenum al_format_for_wave_format(WAVEFORMATPCMEX* waveFormat)
  1031. +{
  1032. + /* Start with an invalid enum... */
  1033. + ALenum format = AL_INVALID;
  1034. + switch(waveFormat->Format.wBitsPerSample)
  1035. + {
  1036. + case 8:
  1037. + switch(waveFormat->Format.nChannels)
  1038. + {
  1039. + case 1:
  1040. + format = AL_FORMAT_MONO8;
  1041. + break;
  1042. + case 2:
  1043. + format = AL_FORMAT_STEREO8;
  1044. + break;
  1045. + default:
  1046. + FIXME("unsupported waveFormat->Format.nChannels of %d\n", waveFormat->Format.nChannels);
  1047. + break;
  1048. + }
  1049. + break;
  1050. + case 16:
  1051. + switch(waveFormat->Format.nChannels)
  1052. + {
  1053. + case 1:
  1054. + format = AL_FORMAT_MONO16;
  1055. + break;
  1056. + case 2:
  1057. + format = AL_FORMAT_STEREO16;
  1058. + break;
  1059. + default:
  1060. + FIXME("unsupported waveFormat->Format.nChannels of %d\n", waveFormat->Format.nChannels);
  1061. + break;
  1062. + }
  1063. + break;
  1064. + default:
  1065. + FIXME("unsupported waveFormat->Format.wBitsPerSample of %d\n", waveFormat->Format.wBitsPerSample);
  1066. + break;
  1067. + }
  1068. + return format;
  1069. +}
  1070. +
  1071. +#if 0
  1072. +/* Volume functions derived from Alsaplayer source */
  1073. +/* length is the number of 16 bit samples */
  1074. +void volume_effect16(void *bufin, void* bufout, int length, int left,
  1075. + int right, int nChannels)
  1076. +{
  1077. + short *d_out = (short *)bufout;
  1078. + short *d_in = (short *)bufin;
  1079. + int i, v;
  1080. +
  1081. +/*
  1082. + TRACE("length == %d, nChannels == %d\n", length, nChannels);
  1083. +*/
  1084. +
  1085. + if (right == -1) right = left;
  1086. +
  1087. + for(i = 0; i < length; i+=(nChannels))
  1088. + {
  1089. + v = (int) ((*(d_in++) * left) / 100);
  1090. + *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
  1091. + if(nChannels == 2)
  1092. + {
  1093. + v = (int) ((*(d_in++) * right) / 100);
  1094. + *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
  1095. + }
  1096. + }
  1097. +}
  1098. +
  1099. +/* length is the number of 8 bit samples */
  1100. +void volume_effect8(void *bufin, void* bufout, int length, int left,
  1101. + int right, int nChannels)
  1102. +{
  1103. + BYTE *d_out = (BYTE *)bufout;
  1104. + BYTE *d_in = (BYTE *)bufin;
  1105. + int i, v;
  1106. +
  1107. +/*
  1108. + TRACE("length == %d, nChannels == %d\n", length, nChannels);
  1109. +*/
  1110. +
  1111. + if (right == -1) right = left;
  1112. +
  1113. + for(i = 0; i < length; i+=(nChannels))
  1114. + {
  1115. + v = (BYTE) ((*(d_in++) * left) / 100);
  1116. + *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
  1117. + if(nChannels == 2)
  1118. + {
  1119. + v = (BYTE) ((*(d_in++) * right) / 100);
  1120. + *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
  1121. + }
  1122. + }
  1123. +}
  1124. +#endif
  1125. +
  1126. +static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
  1127. + WAVEFORMATPCMEX* format)
  1128. +{
  1129. + TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
  1130. + lpTime->wType, format->Format.wBitsPerSample, format->Format.nSamplesPerSec,
  1131. + format->Format.nChannels, format->Format.nAvgBytesPerSec);
  1132. + TRACE("Position in bytes=%lu\n", position);
  1133. +
  1134. + switch (lpTime->wType) {
  1135. + case TIME_SAMPLES:
  1136. + lpTime->u.sample = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
  1137. + TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
  1138. + break;
  1139. + case TIME_MS:
  1140. + lpTime->u.ms = 1000.0 * position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels * format->Format.nSamplesPerSec);
  1141. + TRACE("TIME_MS=%lu\n", lpTime->u.ms);
  1142. + break;
  1143. + case TIME_SMPTE:
  1144. + lpTime->u.smpte.fps = 30;
  1145. + position = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
  1146. + position += (format->Format.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
  1147. + lpTime->u.smpte.sec = position / format->Format.nSamplesPerSec;
  1148. + position -= lpTime->u.smpte.sec * format->Format.nSamplesPerSec;
  1149. + lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
  1150. + lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
  1151. + lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
  1152. + lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
  1153. + lpTime->u.smpte.fps = 30;
  1154. + lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->Format.nSamplesPerSec;
  1155. + TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
  1156. + lpTime->u.smpte.hour, lpTime->u.smpte.min,
  1157. + lpTime->u.smpte.sec, lpTime->u.smpte.frame);
  1158. + break;
  1159. + default:
  1160. + WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
  1161. + lpTime->wType = TIME_BYTES;
  1162. + /* fall through */
  1163. + case TIME_BYTES:
  1164. + lpTime->u.cb = position;
  1165. + TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
  1166. + break;
  1167. + }
  1168. + return MMSYSERR_NOERROR;
  1169. +}
  1170. +
  1171. +static BOOL supportedFormat(LPWAVEFORMATEX wf, int input)
  1172. +{
  1173. + TRACE("(%p)\n",wf);
  1174. +
  1175. + /* Force OpenAL to 44100 */
  1176. + if (((OPENAL_LIMIT_IN_44100 && input) || (OPENAL_LIMIT_OUT_44100 && !input)) && wf->nSamplesPerSec != 44100)
  1177. + return FALSE;
  1178. +
  1179. + if (wf->nSamplesPerSec<DSBFREQUENCY_MIN||wf->nSamplesPerSec>DSBFREQUENCY_MAX)
  1180. + return FALSE;
  1181. +
  1182. + if (wf->wFormatTag == WAVE_FORMAT_PCM) {
  1183. + if (wf->nChannels >= 1 && wf->nChannels <= MAX_CHANNELS) {
  1184. + if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
  1185. + return TRUE;
  1186. + }
  1187. + } else if (wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
  1188. + WAVEFORMATEXTENSIBLE * wfex = (WAVEFORMATEXTENSIBLE *)wf;
  1189. +
  1190. + if (wf->cbSize == 22 && IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
  1191. + if (wf->nChannels >=1 && wf->nChannels <= MAX_CHANNELS) {
  1192. + if (wf->wBitsPerSample==wfex->Samples.wValidBitsPerSample) {
  1193. + if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
  1194. + return TRUE;
  1195. + } else
  1196. + WARN("wBitsPerSample != wValidBitsPerSample not supported yet\n");
  1197. + }
  1198. + } else
  1199. + WARN("only KSDATAFORMAT_SUBTYPE_PCM supported\n");
  1200. + } else
  1201. + WARN("only WAVE_FORMAT_PCM and WAVE_FORMAT_EXTENSIBLE supported\n");
  1202. +
  1203. + return FALSE;
  1204. +}
  1205. +
  1206. +void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2)
  1207. +{
  1208. + ZeroMemory(wf2, sizeof(wf2));
  1209. + if (wf1->wFormatTag == WAVE_FORMAT_PCM)
  1210. + memcpy(wf2, wf1, sizeof(PCMWAVEFORMAT));
  1211. + else if (wf1->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
  1212. + memcpy(wf2, wf1, sizeof(WAVEFORMATPCMEX));
  1213. + else
  1214. + memcpy(wf2, wf1, sizeof(WAVEFORMATEX) + wf1->cbSize);
  1215. +}
  1216. +
  1217. +/******************************************************************
  1218. + * OpenAL_CloseWaveOutDevice
  1219. + *
  1220. + */
  1221. +void OpenAL_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
  1222. +{
  1223. + TRACE("wwo=%p\n", wwo);
  1224. +
  1225. + alDeleteSources(1, &wwo->al_source);
  1226. + CHECK_AL_ERROR();
  1227. + wodDeleteBuffers(wwo);
  1228. + wwo->live = 0;
  1229. +}
  1230. +
  1231. +/******************************************************************
  1232. + * OpenAL_CloseWaveInDevice
  1233. + *
  1234. + */
  1235. +void OpenAL_CloseWaveInDevice(WINE_WAVEIN* wwi)
  1236. +{
  1237. + ALCboolean success;
  1238. + TRACE("wwi=%p\n", wwi);
  1239. +
  1240. + /* recording not supported in OpenAL 1.0 */
  1241. + success = p_alcCaptureCloseDevice(wwi->al_device);
  1242. + if(!success)
  1243. + {
  1244. + ERR("ALC ERROR: Unable to close capture device at %s:%d\n", __FILE__, __LINE__);
  1245. + }
  1246. + wwi->live = 0;
  1247. +}
  1248. +
  1249. +/******************************************************************
  1250. + * OpenAL_WaveClose
  1251. + */
  1252. +LONG OpenAL_WaveClose(void)
  1253. +{
  1254. + /* Cannot check for device close failures on OpenAL 1.0... */
  1255. + /* ALCboolean success; */
  1256. + int iDevice;
  1257. +
  1258. + TRACE("called\n");
  1259. + /* close all open devices */
  1260. + for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++)
  1261. + {
  1262. + if(WOutDev[iDevice].live)
  1263. + {
  1264. + OpenAL_CloseWaveOutDevice(&WOutDev[iDevice]);
  1265. + }
  1266. + }
  1267. +
  1268. + for(iDevice = 0; iDevice < MAX_WAVEINDRV; iDevice++)
  1269. + {
  1270. + if(WInDev[iDevice].live)
  1271. + {
  1272. + OpenAL_CloseWaveInDevice(&WInDev[iDevice]);
  1273. + }
  1274. + }
  1275. +
  1276. + alcDestroyContext(al_context);
  1277. + CHECK_ALC_ERROR();
  1278. +
  1279. + /* Cannot check for device close failures on OpenAL 1.0... */
  1280. + alcCloseDevice(al_device);
  1281. + /*success = alcCloseDevice(al_device);
  1282. + if(!success)
  1283. + {
  1284. + ERR("ALC ERROR: Unable to close device at %s:%d\n", __FILE__, __LINE__);
  1285. + }*/
  1286. +
  1287. + return 1;
  1288. +}
  1289. +
  1290. +/******************************************************************
  1291. + * OpenAL_WaveInit
  1292. + *
  1293. + * Initialize internal structures for OpenAL
  1294. + */
  1295. +LONG OpenAL_WaveInit(void)
  1296. +{
  1297. + int i;
  1298. +
  1299. + TRACE("called\n");
  1300. +
  1301. + /* select the "preferred device" */
  1302. + al_device = alcOpenDevice(NULL);
  1303. + TRACE("al_device = %p\n", al_device);
  1304. + CHECK_ALC_ERROR();
  1305. + if(!al_device)
  1306. + {
  1307. + WARN("alcOpenDevice(%p) failed\n", NULL);
  1308. + return -1;
  1309. + }
  1310. + /* Make the best default context */
  1311. + /* TODO: should this use any init params? */
  1312. + al_context = alcCreateContext(al_device, NULL);
  1313. + TRACE("al_context = %p\n", al_context);
  1314. + CHECK_ALC_ERROR();
  1315. + if(!al_context)
  1316. + {
  1317. + return -1;
  1318. + }
  1319. + alcMakeContextCurrent(al_context);
  1320. + CHECK_ALC_ERROR();
  1321. +
  1322. + TRACE("AL_VERSION: %s\n", alGetString(AL_VERSION));
  1323. + /* OpenAL version check */
  1324. + {
  1325. + ALCint major = -1;
  1326. + ALCint minor = -1;
  1327. + alcGetIntegerv(al_device, ALC_MAJOR_VERSION, 1, &major);
  1328. + CHECK_ALC_ERROR();
  1329. + alcGetIntegerv(al_device, ALC_MINOR_VERSION, 1, &minor);
  1330. + CHECK_ALC_ERROR();
  1331. + TRACE("ALC_VERSION: %d.%d\n", major, minor);
  1332. + }
  1333. +
  1334. +/* alcGetProcAddress alGetProcAddress may give warnings about the signedness of the string... this is a bs warning */
  1335. +#define GET_ALC_FUNC_PTR(ret, name, params) p_##name = (t##name)alcGetProcAddress(al_device, #name);
  1336. +#define GET_AL_FUNC_PTR(ret, name, params) p_##name = (t##name)alGetProcAddress(#name);
  1337. + OPENAL_1_1_ALC_FUNCS(GET_ALC_FUNC_PTR);
  1338. + OPENAL_1_1_AL_FUNCS(GET_AL_FUNC_PTR);
  1339. + OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(GET_AL_FUNC_PTR);
  1340. +#undef GET_ALC_FUNC_PTR
  1341. +#undef GET_AL_FUNC_PTR
  1342. +
  1343. +#define GET_TOKENS(name) t_##name = alcGetEnumValue(al_device, #name);
  1344. + OPENAL_1_1_ALC_TOKENS(GET_TOKENS);
  1345. +#undef GET_TOKENS
  1346. +
  1347. +#define HAS_FUNC(ret, name, params) if(p_##name) TRACE("%s is supported\n", #name); else TRACE("%s is not supported\n", #name);
  1348. + OPENAL_1_1_ALC_FUNCS(HAS_FUNC);
  1349. + OPENAL_1_1_AL_FUNCS(HAS_FUNC);
  1350. + OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(HAS_FUNC);
  1351. +#undef HAS_FUNC
  1352. +
  1353. +#define HAS_TOKENS(name) if(t_##name != AL_NONE) TRACE("%s is supported\n", #name); else TRACE("%s is not supported\n", #name);
  1354. + OPENAL_1_1_ALC_TOKENS(HAS_TOKENS);
  1355. +#undef HAS_TOKENS
  1356. +
  1357. + /* creepy yes -- but the 1.1 alc functions are the capture ones... */
  1358. +#define AND_FUNC_PTR(ret, name, params) p_##name &&
  1359. + al_can_capture = OPENAL_1_1_ALC_FUNCS(AND_FUNC_PTR) /* && */ 1;
  1360. + al_static_buffer = OPENAL_AL_EXT_STATIC_BUFFER_FUNCS(AND_FUNC_PTR) /* && */ 1;
  1361. +#undef AND_FUNC_PTR
  1362. + /* still creepy yes -- but the 1.1 alc functions are the capture ones... */
  1363. +#define AND_TOKENS(name) (t_##name != AL_NONE) &&
  1364. + al_can_capture = al_can_capture && OPENAL_1_1_ALC_TOKENS(AND_TOKENS) /* && */ 1;
  1365. +#undef AND_TOKENS
  1366. +
  1367. + /* Why not test the extension as well?? */
  1368. + /* You know its fun... */
  1369. + al_can_capture = al_can_capture && alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE");
  1370. +
  1371. + /* Why not test the extension as well?? */
  1372. + /* We all love extensions... */
  1373. + al_static_buffer = al_static_buffer && alcIsExtensionPresent(NULL, "AL_EXT_STATIC_BUFFER");
  1374. +
  1375. + TRACE("al_can_capture == %d\n", al_can_capture);
  1376. +
  1377. + /* initialize all device handles to -1 */
  1378. + for (i = 0; i < MAX_WAVEOUTDRV; ++i)
  1379. + {
  1380. + static const WCHAR ini[] = {'O','p','e','n','A','L',' ','W','a','v','e','O','u','t','D','r','i','v','e','r',0};
  1381. +
  1382. + WOutDev[i].live = 0;
  1383. + memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps)); /* zero out caps values */
  1384. + WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */
  1385. + WOutDev[i].caps.wPid = 0x0001; /* Product ID */
  1386. + lstrcpyW(WOutDev[i].caps.szPname, ini);
  1387. + snprintf(WOutDev[i].interface_name, sizeof(WOutDev[i].interface_name), "wineopenal: %d", i);
  1388. +
  1389. + WOutDev[i].caps.vDriverVersion = 0x0100;
  1390. + WOutDev[i].caps.dwFormats = 0x00000000;
  1391. + WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME;
  1392. +
  1393. + WOutDev[i].caps.wChannels = 2;
  1394. + /* Gain is supported but how do we get independant l/r volume control? */
  1395. + /* WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME; */
  1396. +
  1397. +#if !OPENAL_LIMIT_OUT_44100
  1398. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96M08;
  1399. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96S08;
  1400. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96S16;
  1401. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_96M16;
  1402. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48M08;
  1403. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48S08;
  1404. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48S16;
  1405. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_48M16;
  1406. +#endif
  1407. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
  1408. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
  1409. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
  1410. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
  1411. +#if !OPENAL_LIMIT_OUT_44100
  1412. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
  1413. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
  1414. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
  1415. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
  1416. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
  1417. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
  1418. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
  1419. + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
  1420. +#endif
  1421. + }
  1422. +
  1423. + for (i = 0; i < MAX_WAVEINDRV; ++i)
  1424. + {
  1425. + static const WCHAR ini[] = {'O','p','e','n','A','L',' ','W','a','v','e','I','n','D','r','i','v','e','r',0};
  1426. +
  1427. + WInDev[i].live = 0;
  1428. + WInDev[i].al_device = NULL;
  1429. + memset(&WInDev[i].caps, 0, sizeof(WInDev[i].caps)); /* zero out caps values */
  1430. + WInDev[i].caps.wMid = 0x00FF;
  1431. + WInDev[i].caps.wPid = 0x0001;
  1432. + lstrcpyW(WInDev[i].caps.szPname, ini);
  1433. + snprintf(WInDev[i].interface_name, sizeof(WInDev[i].interface_name), "wineopenal: %d", i);
  1434. +
  1435. + WInDev[i].caps.vDriverVersion = 0x0100;
  1436. + WInDev[i].caps.dwFormats = 0x00000000;
  1437. +
  1438. + WInDev[i].caps.wChannels = 2;
  1439. +
  1440. +#if !OPENAL_LIMIT_IN_44100
  1441. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96M08;
  1442. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96S08;
  1443. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96S16;
  1444. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_96M16;
  1445. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48M08;
  1446. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48S08;
  1447. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48S16;
  1448. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_48M16;
  1449. +#endif
  1450. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M08;
  1451. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S08;
  1452. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4S16;
  1453. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;
  1454. +#if !OPENAL_LIMIT_IN_44100
  1455. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M08;
  1456. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S08;
  1457. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2M16;
  1458. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;
  1459. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M08;
  1460. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;
  1461. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1M16;
  1462. + WInDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
  1463. +#endif
  1464. +
  1465. + WInDev[i].caps.wReserved1 = 0;
  1466. + }
  1467. + return 0;
  1468. +}
  1469. +
  1470. +/******************************************************************
  1471. + * OpenAL_InitRingMessage
  1472. + *
  1473. + * Initialize the ring of messages for passing between driver's caller and playback/record
  1474. + * thread
  1475. + */
  1476. +static int OpenAL_InitRingMessage(ESD_MSG_RING* mr)
  1477. +{
  1478. + mr->msg_toget = 0;
  1479. + mr->msg_tosave = 0;
  1480. +#ifdef USE_PIPE_SYNC
  1481. + if (pipe(mr->msg_pipe) < 0) {
  1482. + mr->msg_pipe[0] = -1;
  1483. + mr->msg_pipe[1] = -1;
  1484. + ERR("could not create pipe, error=%s\n", strerror(errno));
  1485. + }
  1486. +#else
  1487. + mr->msg_event = CreateEventW(NULL, FALSE, FALSE, NULL);
  1488. +#endif
  1489. + mr->ring_buffer_size = ESD_RING_BUFFER_INCREMENT;
  1490. + mr->messages = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,mr->ring_buffer_size * sizeof(RING_MSG));
  1491. + InitializeCriticalSection(&mr->msg_crst);
  1492. + mr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)"WINEOpenAL_msg_crst";
  1493. + return 0;
  1494. +}
  1495. +
  1496. +/******************************************************************
  1497. + * OpenAL_DestroyRingMessage
  1498. + *
  1499. + */
  1500. +static int OpenAL_DestroyRingMessage(ESD_MSG_RING* mr)
  1501. +{
  1502. + TRACE("mr=%p\n", mr);
  1503. +#ifdef USE_PIPE_SYNC
  1504. + close(mr->msg_pipe[0]);
  1505. + close(mr->msg_pipe[1]);
  1506. +#else
  1507. + CloseHandle(mr->msg_event);
  1508. +#endif
  1509. + HeapFree(GetProcessHeap(),0,mr->messages);
  1510. + mr->messages=NULL;
  1511. + DeleteCriticalSection(&mr->msg_crst);
  1512. + return 0;
  1513. +}
  1514. +
  1515. +/******************************************************************
  1516. + * OpenAL_AddRingMessage
  1517. + *
  1518. + * Inserts a new message into the ring (should be called from DriverProc derivated routines)
  1519. + */
  1520. +static int OpenAL_AddRingMessage(ESD_MSG_RING* mr, enum win_wm_message msg, DWORD param, BOOL wait)
  1521. +{
  1522. + HANDLE hEvent = INVALID_HANDLE_VALUE;
  1523. + TRACE("mr=%p, msg=%d, param=%08X, wait=%d\n", mr, msg, (unsigned int)param, wait);
  1524. +
  1525. + EnterCriticalSection(&mr->msg_crst);
  1526. + if ((mr->msg_toget == ((mr->msg_tosave + 1) % mr->ring_buffer_size)))
  1527. + {
  1528. + int old_ring_buffer_size = mr->ring_buffer_size;
  1529. + mr->ring_buffer_size += ESD_RING_BUFFER_INCREMENT;
  1530. + TRACE("mr->ring_buffer_size=%d\n",mr->ring_buffer_size);
  1531. + mr->messages = HeapReAlloc(GetProcessHeap(),0,mr->messages, mr->ring_buffer_size * sizeof(RING_MSG));
  1532. + /* Now we need to rearrange the ring buffer so that the new
  1533. + buffers just allocated are in between mr->msg_tosave and
  1534. + mr->msg_toget.
  1535. + */
  1536. + if (mr->msg_tosave < mr->msg_toget)
  1537. + {
  1538. + memmove(&(mr->messages[mr->msg_toget + ESD_RING_BUFFER_INCREMENT]),
  1539. + &(mr->messages[mr->msg_toget]),
  1540. + sizeof(RING_MSG)*(old_ring_buffer_size - mr->msg_toget)
  1541. + );
  1542. + mr->msg_toget += ESD_RING_BUFFER_INCREMENT;
  1543. + }
  1544. + }
  1545. + if (wait)
  1546. + {
  1547. + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
  1548. + if (hEvent == INVALID_HANDLE_VALUE)
  1549. + {
  1550. + ERR("can't create event !?\n");
  1551. + LeaveCriticalSection(&mr->msg_crst);
  1552. + return 0;
  1553. + }
  1554. + if (mr->msg_toget != mr->msg_tosave && mr->messages[mr->msg_toget].msg != WINE_WM_HEADER)
  1555. + FIXME("two fast messages in the queue!!!!\n");
  1556. +
  1557. + /* fast messages have to be added at the start of the queue */
  1558. + mr->msg_toget = (mr->msg_toget + mr->ring_buffer_size - 1) % mr->ring_buffer_size;
  1559. +
  1560. + mr->messages[mr->msg_toget].msg = msg;
  1561. + mr->messages[mr->msg_toget].param = param;
  1562. + mr->messages[mr->msg_toget].hEvent = hEvent;
  1563. + }
  1564. + else
  1565. + {
  1566. + mr->messages[mr->msg_tosave].msg = msg;
  1567. + mr->messages[mr->msg_tosave].param = param;
  1568. + mr->messages[mr->msg_tosave].hEvent = INVALID_HANDLE_VALUE;
  1569. + mr->msg_tosave = (mr->msg_tosave + 1) % mr->ring_buffer_size;
  1570. + }
  1571. +
  1572. + LeaveCriticalSection(&mr->msg_crst);
  1573. +
  1574. + /* signal a new message */
  1575. + SIGNAL_OMR(mr);
  1576. + if (wait)
  1577. + {
  1578. + /* wait for playback/record thread to have processed the message */
  1579. + WaitForSingleObject(hEvent, INFINITE);
  1580. + CloseHandle(hEvent);
  1581. + }
  1582. +
  1583. + return 1;
  1584. +}
  1585. +
  1586. +/******************************************************************
  1587. + * OpenAL_RetrieveRingMessage
  1588. + *
  1589. + * Get a message from the ring. Should be called by the playback/record thread.
  1590. + */
  1591. +static int OpenAL_RetrieveRingMessage(ESD_MSG_RING* mr,
  1592. + enum win_wm_message *msg, DWORD *param, HANDLE *hEvent)
  1593. +{
  1594. + EnterCriticalSection(&mr->msg_crst);
  1595. +
  1596. + if (mr->msg_toget == mr->msg_tosave) /* buffer empty ? */
  1597. + {
  1598. + LeaveCriticalSection(&mr->msg_crst);
  1599. + return 0;
  1600. + }
  1601. +
  1602. + *msg = mr->messages[mr->msg_toget].msg;
  1603. + mr->messages[mr->msg_toget].msg = 0;
  1604. + *param = mr->messages[mr->msg_toget].param;
  1605. + *hEvent = mr->messages[mr->msg_toget].hEvent;
  1606. + mr->msg_toget = (mr->msg_toget + 1) % mr->ring_buffer_size;
  1607. + CLEAR_OMR(mr);
  1608. + LeaveCriticalSection(&mr->msg_crst);
  1609. + return 1;
  1610. +}
  1611. +
  1612. +/*======================================================================*
  1613. + * Low level WAVE OUT implementation *
  1614. + *======================================================================*/
  1615. +
  1616. +/**************************************************************************
  1617. + * wodPrintBuffers [internal]
  1618. + */
  1619. +static void wodPrintBuffers(WINE_WAVEOUT* wwo)
  1620. +{
  1621. + int onBuffer;
  1622. +
  1623. + TRACE("-----------\n");
  1624. + TRACE("wwo->num_al_buffers=%d\n", wwo->num_al_buffers);
  1625. + TRACE("wwo->num_free_al_buffers=%d\n", wwo->num_free_al_buffers);
  1626. + for(onBuffer = 0; onBuffer < wwo->num_al_buffers; onBuffer++)
  1627. + {
  1628. + int onFreeBuffer;
  1629. + int free = 0;
  1630. +
  1631. + for(onFreeBuffer = 0; onFreeBuffer < wwo->num_free_al_buffers; onFreeBuffer++)
  1632. + {
  1633. + free = free || (wwo->free_al_buffers[onFreeBuffer] == wwo->al_buffers[onBuffer]);
  1634. + }
  1635. + TRACE("buffer[%d] buf=%d free=%d\n", onBuffer, wwo->al_buffers[onBuffer], free);
  1636. + }
  1637. + TRACE("-----------\n");
  1638. +}
  1639. +
  1640. +/**************************************************************************
  1641. + * wodAddBuffer [internal]
  1642. + */
  1643. +static void wodAddBuffer(WINE_WAVEOUT* wwo)
  1644. +{
  1645. + wwo->num_al_buffers++;
  1646. + /* HeapReAlloc does not work like realloc... realloc on null is a malloc... */
  1647. + /* This starts with 1 entry (an ignored one) */
  1648. + wwo->al_buffers = (ALuint*)HeapReAlloc(GetProcessHeap(), 0, wwo->al_buffers, wwo->num_al_buffers * sizeof(ALuint));
  1649. +
  1650. + alGenBuffers(1, &wwo->al_buffers[wwo->num_al_buffers - 1]);
  1651. + CHECK_AL_ERROR();
  1652. + TRACE("added buffer #%d == %d\n", wwo->num_al_buffers - 1, wwo->al_buffers[wwo->num_al_buffers - 1]);
  1653. +}
  1654. +
  1655. +/**************************************************************************
  1656. + * wodGetFreeBuffer [internal]
  1657. + */
  1658. +static ALuint wodGetFreeBuffer(WINE_WAVEOUT* wwo)
  1659. +{
  1660. + ALint processed;
  1661. + ALuint freeBuffer;
  1662. +
  1663. + int found = 0;
  1664. + while(!found)
  1665. + {
  1666. + if(wwo->num_free_al_buffers)
  1667. + {
  1668. + wwo->num_free_al_buffers--;
  1669. + freeBuffer = wwo->free_al_buffers[wwo->num_free_al_buffers];
  1670. +
  1671. + TRACE("Found free buffer %d\n", freeBuffer);
  1672. + found = 1;
  1673. + }
  1674. + else
  1675. + {
  1676. + alGetSourcei(wwo->al_source, AL_BUFFERS_PROCESSED, &processed);
  1677. + CHECK_AL_ERROR();
  1678. + TRACE("Found %d processed buffers\n", processed);
  1679. +
  1680. + if(processed)
  1681. + {
  1682. + wwo->num_free_al_buffers = processed;
  1683. + /* HeapReAlloc does not work like realloc... realloc on null is a malloc... */
  1684. + /* This starts with 1 entry (an ignored one) */
  1685. + wwo->free_al_buffers = (ALuint*)HeapReAlloc(GetProcessHeap(), 0, wwo->free_al_buffers, wwo->num_free_al_buffers * sizeof(ALuint));
  1686. +
  1687. + alSourceUnqueueBuffers(wwo->al_source, processed, wwo->free_al_buffers);
  1688. + CHECK_AL_ERROR();
  1689. +
  1690. + TRACE("Freed %d buffers\n", processed);
  1691. + }
  1692. + else
  1693. + {
  1694. + if(wwo->num_al_buffers < OPENAL_MAX_BUFFERS)
  1695. + {
  1696. + /* no free buffer -- add one and return that */
  1697. + wodAddBuffer(wwo);
  1698. + freeBuffer = wwo->al_buffers[wwo->num_al_buffers - 1];
  1699. + TRACE("No free buffers\n");
  1700. + TRACE("Made new buffer %d\n", freeBuffer);
  1701. + found = 1;
  1702. + }
  1703. + else
  1704. + {
  1705. + TRACE("No free buffers -- reached max -- waiting\n");
  1706. + /* Sleep for a more valid amount of time? */
  1707. + usleep(1000);
  1708. + }
  1709. + }
  1710. + }
  1711. + }
  1712. + return freeBuffer;
  1713. +}
  1714. +
  1715. +/**************************************************************************
  1716. + * wodQueueBuffer [internal]
  1717. + */
  1718. +static void wodQueueBuffer(WINE_WAVEOUT* wwo, void* data, int toWrite)
  1719. +{
  1720. + ALuint freeBuffer;
  1721. +
  1722. + TRACE("Buffers before queue\n");
  1723. + wodPrintBuffers(wwo);
  1724. +
  1725. + freeBuffer = wodGetFreeBuffer(wwo);
  1726. + TRACE("Found %d free buffer\n", freeBuffer);
  1727. +
  1728. + /* send the audio data to OpenAL for playing */
  1729. + {
  1730. + ALenum format = al_format_for_wave_format(&wwo->waveFormat);
  1731. + ALsizei freq = wwo->waveFormat.Format.nSamplesPerSec;
  1732. +
  1733. + if(al_static_buffer)
  1734. + {
  1735. + p_alBufferDataStatic(freeBuffer, format, data, toWrite, freq);
  1736. + TRACE("alBufferDataStatic(freeBuffer=%d, format=%08x, data=%p, toWrite=%d, freq=%d)\n", freeBuffer, format, data, toWrite, freq);
  1737. + }
  1738. + else
  1739. + {
  1740. + alBufferData(freeBuffer, format, data, toWrite, freq);
  1741. + TRACE("alBufferData(freeBuffer=%d, format=%08x, data=%p, toWrite=%d, freq=%d)\n", freeBuffer, format, data, toWrite, freq);
  1742. + }
  1743. + CHECK_AL_ERROR();
  1744. + }
  1745. +
  1746. + /* Queue up the buffer */
  1747. + alSourceQueueBuffers(wwo->al_source, 1, &freeBuffer);
  1748. + CHECK_AL_ERROR();
  1749. +
  1750. + TRACE("Buffers after queue\n");
  1751. + wodPrintBuffers(wwo);
  1752. +}
  1753. +
  1754. +/**************************************************************************
  1755. + * wodDeleteBuffers [internal]
  1756. + */
  1757. +static void wodDeleteBuffers(WINE_WAVEOUT* wwo)
  1758. +{
  1759. + alDeleteBuffers(wwo->num_al_buffers, wwo->al_buffers);
  1760. + CHECK_AL_ERROR();
  1761. +
  1762. + /* There is always at least 1 of each of these */
  1763. + HeapFree(GetProcessHeap(), 0, wwo->al_buffers);
  1764. + HeapFree(GetProcessHeap(), 0, wwo->free_al_buffers);
  1765. +}
  1766. +
  1767. +/**************************************************************************
  1768. + * wodNotifyClient [internal]
  1769. + */
  1770. +static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
  1771. +{
  1772. + TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
  1773. +
  1774. + switch (wMsg) {
  1775. + case WOM_OPEN:
  1776. + case WOM_CLOSE:
  1777. + case WOM_DONE:
  1778. + if (wwo->wFlags != DCB_NULL &&
  1779. + !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags, (HDRVR)wwo->waveDesc.hWave,
  1780. + wMsg, wwo->waveDesc.dwInstance, dwParam1, dwParam2)) {
  1781. + WARN("can't notify client !\n");
  1782. + return MMSYSERR_ERROR;
  1783. + }
  1784. + break;
  1785. + default:
  1786. + FIXME("Unknown callback message %u\n", wMsg);
  1787. + return MMSYSERR_INVALPARAM;
  1788. + }
  1789. + return MMSYSERR_NOERROR;
  1790. +}
  1791. +
  1792. +/**************************************************************************
  1793. + * wodUpdatePlayedTotal [internal]
  1794. + *
  1795. + */
  1796. +static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo)
  1797. +{
  1798. + /* total played is the bytes written less the bytes to write ;-) */
  1799. + wwo->dwPlayedTotal = wwo->dwWrittenTotal;
  1800. +
  1801. + return TRUE;
  1802. +}
  1803. +
  1804. +/**************************************************************************
  1805. + * wodPlayer_BeginWaveHdr [internal]
  1806. + *
  1807. + * Makes the specified lpWaveHdr the currently playing wave header.
  1808. + * If the specified wave header is a begin loop and we're not already in
  1809. + * a loop, setup the loop.
  1810. + */
  1811. +static void wodPlayer_BeginWaveHdr(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
  1812. +{
  1813. + wwo->lpPlayPtr = lpWaveHdr;
  1814. +
  1815. + if (!lpWaveHdr) return;
  1816. +
  1817. + if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP) {
  1818. + if (wwo->lpLoopPtr) {
  1819. + WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
  1820. + TRACE("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
  1821. + } else {
  1822. + TRACE("Starting loop (%ldx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
  1823. + wwo->lpLoopPtr = lpWaveHdr;
  1824. + /* Windows does not touch WAVEHDR.dwLoops,
  1825. + * so we need to make an internal copy */
  1826. + wwo->dwLoops = lpWaveHdr->dwLoops;
  1827. + }
  1828. + }
  1829. + wwo->dwPartialOffset = 0;
  1830. +}
  1831. +
  1832. +/**************************************************************************
  1833. + * wodPlayer_PlayPtrNext [internal]
  1834. + *
  1835. + * Advance the play pointer to the next waveheader, looping if required.
  1836. + */
  1837. +static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEOUT* wwo)
  1838. +{
  1839. + LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
  1840. +
  1841. + wwo->dwPartialOffset = 0;
  1842. + if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr) {
  1843. + /* We're at the end of a loop, loop if required */
  1844. + if (--wwo->dwLoops > 0) {
  1845. + wwo->lpPlayPtr = wwo->lpLoopPtr;
  1846. + } else {
  1847. + /* Handle overlapping loops correctly */
  1848. + if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
  1849. + FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
  1850. + /* shall we consider the END flag for the closing loop or for
  1851. + * the opening one or for both ???
  1852. + * code assumes for closing loop only
  1853. + */
  1854. + } else {
  1855. + lpWaveHdr = lpWaveHdr->lpNext;
  1856. + }
  1857. + wwo->lpLoopPtr = NULL;
  1858. + wodPlayer_BeginWaveHdr(wwo, lpWaveHdr);
  1859. + }
  1860. + } else {
  1861. + /* We're not in a loop. Advance to the next wave header */
  1862. + wodPlayer_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
  1863. + }
  1864. +
  1865. + return lpWaveHdr;
  1866. +}
  1867. +
  1868. +/**************************************************************************
  1869. + * wodPlayer_NotifyWait [internal]
  1870. + * Returns the number of milliseconds to wait before attempting to notify
  1871. + * completion of the specified wavehdr.
  1872. + * This is based on the number of bytes remaining to be written in the
  1873. + * wave.
  1874. + */
  1875. +static DWORD wodPlayer_NotifyWait(const WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
  1876. +{
  1877. + DWORD dwMillis;
  1878. +
  1879. + if(lpWaveHdr->reserved < wwo->dwPlayedTotal)
  1880. + {
  1881. + dwMillis = 1;
  1882. + }
  1883. + else
  1884. + {
  1885. + dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->waveFormat.Format.nAvgBytesPerSec;
  1886. + if(!dwMillis) dwMillis = 1;
  1887. + }
  1888. +
  1889. + TRACE("dwMillis = %ld\n", dwMillis);
  1890. +
  1891. + return dwMillis;
  1892. +}
  1893. +
  1894. +/**************************************************************************
  1895. + * wodPlayer_WriteMaxFrags [internal]
  1896. + * Writes the maximum number of bytes possible to the DSP and returns
  1897. + * the number of bytes written.
  1898. + */
  1899. +static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
  1900. +{
  1901. + /* Only attempt to write to free bytes */
  1902. + DWORD dwLength = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
  1903. + int toWrite = min(dwLength, *bytes);
  1904. + int written;
  1905. +
  1906. + TRACE("Writing wavehdr %p.%lu[%lu]\n",
  1907. + wwo->lpPlayPtr, wwo->dwPartialOffset, wwo->lpPlayPtr->dwBufferLength);
  1908. +#if 0
  1909. +/* TODO: use the OpenAL buffer for this... */
  1910. + /* see if our buffer isn't large enough for the data we are writing */
  1911. + if(wwo->buffer_size < toWrite)
  1912. + {
  1913. + if(wwo->sound_buffer)
  1914. + {
  1915. + wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, toWrite);
  1916. + wwo->buffer_size = toWrite;
  1917. + }
  1918. + }
  1919. +
  1920. +/* TODO: use the OpenAL buffer for this... */
  1921. + /* if we don't have a buffer then get one */
  1922. + if(!wwo->sound_buffer)
  1923. + {
  1924. + /* allocate some memory for the buffer */
  1925. + wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, toWrite);
  1926. + wwo->buffer_size = toWrite;
  1927. + }
  1928. +
  1929. + /* if we don't have a buffer then error out */
  1930. + if(!wwo->sound_buffer)
  1931. + {
  1932. + ERR("error allocating sound_buffer memory\n");
  1933. + return 0;
  1934. + }
  1935. +
  1936. + TRACE("toWrite == %d\n", toWrite);
  1937. +
  1938. +/* TODO: use OpenAL gain for this... */
  1939. + /* apply volume to the bits */
  1940. + /* for single channel audio streams we only use the LEFT volume */
  1941. + if(wwo->waveFormat.Format.wBitsPerSample == 16)
  1942. + {
  1943. + /* apply volume to the buffer we are about to send */
  1944. + /* divide toWrite(bytes) by 2 as volume processes by 16 bits */
  1945. + volume_effect16(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
  1946. + wwo->sound_buffer, toWrite>>1, wwo->volume_left,
  1947. + wwo->volume_right, wwo->waveFormat.Format.nChannels);
  1948. + } else if(wwo->waveFormat.Format.wBitsPerSample == 8)
  1949. + {
  1950. + /* apply volume to the buffer we are about to send */
  1951. + volume_effect8(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
  1952. + wwo->sound_buffer, toWrite, wwo->volume_left,
  1953. + wwo->volume_right, wwo->waveFormat.Format.nChannels);
  1954. + } else
  1955. + {
  1956. + FIXME("unsupported wwo->format.wBitsPerSample of %d\n",
  1957. + wwo->waveFormat.Format.wBitsPerSample);
  1958. + }
  1959. +
  1960. + 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);
  1961. + /* send the audio data to OpenAL for playing */
  1962. + ALenum format = al_format_for_wave_format(&wwo->waveFormat);
  1963. + ALsizei freq = wwo->waveFormat.Format.nSamplesPerSec;
  1964. +
  1965. + wodQueueBuffer(wwo, wwo->sound_buffer, toWrite);
  1966. +
  1967. + /* Continue playing... */
  1968. + {
  1969. + ALint state;
  1970. + alGetSourcei(wwo->al_source, AL_SOURCE_STATE, &state);
  1971. + CHECK_AL_ERROR();
  1972. + if(state != AL_PLAYING)
  1973. + {
  1974. + alSourcePlay(wwo->al_source);
  1975. + CHECK_AL_ERROR();
  1976. + }
  1977. + }
  1978. + written = toWrite;
  1979. +#else
  1980. + /* Modify the gain... needs fixing (no right/left control) */
  1981. + /* No pain... no gain? */
  1982. + {
  1983. + ALfloat gain = (ALfloat)max(wwo->volume_left, wwo->volume_right) / 100.0f;
  1984. + /* TODO: control the left/right audio separately */
  1985. + alSourcef(wwo->al_source, AL_GAIN, gain);
  1986. + CHECK_AL_ERROR();
  1987. + }
  1988. + TRACE("al_device=%p,wwo->al_buffers=%p,wwo->al_source=%d\n", al_device, wwo->al_buffers, wwo->al_source);
  1989. + /* send the audio data to OpenAL for playing */
  1990. + wodQueueBuffer(wwo, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
  1991. +
  1992. + /* Continue playing... */
  1993. + {
  1994. + ALint state;
  1995. + alGetSourcei(wwo->al_source, AL_SOURCE_STATE, &state);
  1996. + CHECK_AL_ERROR();
  1997. + if(state != AL_PLAYING)
  1998. + {
  1999. + alSourcePlay(wwo->al_source);
  2000. + CHECK_AL_ERROR();
  2001. + }
  2002. + }
  2003. + written = toWrite;
  2004. +#endif
  2005. + TRACE("written = %d\n", written);
  2006. +
  2007. + if (written <= 0)
  2008. + {
  2009. + *bytes = 0; /* REMOVE COMMENT: apparently esd is actually full */
  2010. + return written; /* if we wrote nothing just return */
  2011. + }
  2012. +
  2013. + if (written >= dwLength)
  2014. + wodPlayer_PlayPtrNext(wwo); /* If we wrote all current wavehdr, skip to the next one */
  2015. + else
  2016. + wwo->dwPartialOffset += written; /* Remove the amount written */
  2017. +
  2018. + if (written < toWrite)
  2019. + *bytes = 0;
  2020. + else
  2021. + *bytes -= written;
  2022. +
  2023. + wwo->dwWrittenTotal += written; /* update stats on this wave device */
  2024. +
  2025. + return written; /* return the number of bytes written */
  2026. +}
  2027. +
  2028. +/**************************************************************************
  2029. + * wodPlayer_NotifyCompletions [internal]
  2030. + *
  2031. + * Notifies and remove from queue all wavehdrs which have been played to
  2032. + * the speaker (ie. they have cleared the audio device). If force is true,
  2033. + * we notify all wavehdrs and remove them all from the queue even if they
  2034. + * are unplayed or part of a loop.
  2035. + */
  2036. +static DWORD wodPlayer_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
  2037. +{
  2038. + LPWAVEHDR lpWaveHdr;
  2039. +
  2040. + if (wwo->lpQueuePtr) {
  2041. + TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), reserved=(%ld), dwWrittenTotal=(%ld), force=(%d)\n",
  2042. + wwo->lpQueuePtr,
  2043. + wwo->lpPlayPtr,
  2044. + wwo->lpLoopPtr,
  2045. + wwo->lpQueuePtr->reserved,
  2046. + wwo->dwWrittenTotal,
  2047. + force);
  2048. + } else {
  2049. + TRACE("lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), dwWrittenTotal=(%ld), force=(%d)\n",
  2050. + wwo->lpQueuePtr,
  2051. + wwo->lpPlayPtr,
  2052. + wwo->lpLoopPtr,
  2053. + wwo->dwWrittenTotal,
  2054. + force);
  2055. + }
  2056. +
  2057. + /* Start from lpQueuePtr and keep notifying until:
  2058. + * - we hit an unwritten wavehdr
  2059. + * - we hit the beginning of a running loop
  2060. + * - we hit a wavehdr which hasn't finished playing
  2061. + */
  2062. + while ((lpWaveHdr = wwo->lpQueuePtr) &&
  2063. + (force ||
  2064. + (lpWaveHdr != wwo->lpPlayPtr &&
  2065. + lpWaveHdr != wwo->lpLoopPtr &&
  2066. + lpWaveHdr->reserved <= wwo->dwWrittenTotal))) {
  2067. +
  2068. + wwo->lpQueuePtr = lpWaveHdr->lpNext;
  2069. +
  2070. + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
  2071. + lpWaveHdr->dwFlags |= WHDR_DONE;
  2072. +
  2073. + wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
  2074. + }
  2075. + return (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != wwo->lpLoopPtr) ?
  2076. + wodPlayer_NotifyWait(wwo, lpWaveHdr) : INFINITE;
  2077. +}
  2078. +
  2079. +/**************************************************************************
  2080. + * wodPlayer_Reset [internal]
  2081. + *
  2082. + * wodPlayer helper. Resets current output stream.
  2083. + */
  2084. +static void wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
  2085. +{
  2086. + wodUpdatePlayedTotal(wwo);
  2087. +
  2088. + wodPlayer_NotifyCompletions(wwo, FALSE); /* updates current notify list */
  2089. +
  2090. + /* REMOVE COMMENT: we aren't able to flush any data that has already been written */
  2091. + /* to esd, otherwise we would do the flushing here */
  2092. +
  2093. + if (reset) {
  2094. + enum win_wm_message msg;
  2095. + DWORD param;
  2096. + HANDLE ev;
  2097. +
  2098. + /* stop OpenAL on this wod */
  2099. + /*TRACE("alSourceStop(%d)\n", wwo->al_source);
  2100. + alSourceStop(wwo->al_source);
  2101. + CHECK_AL_ERROR();*/
  2102. +
  2103. + /* remove any buffer */
  2104. + wodPlayer_NotifyCompletions(wwo, TRUE);
  2105. +
  2106. + wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
  2107. + wwo->state = WINE_WS_STOPPED;
  2108. + wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
  2109. +
  2110. + wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
  2111. +
  2112. + /* remove any existing message in the ring */
  2113. + EnterCriticalSection(&wwo->msgRing.msg_crst);
  2114. +
  2115. + /* return all pending headers in queue */
  2116. + while (OpenAL_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev))
  2117. + {
  2118. + TRACE("flushing msg\n");
  2119. + if (msg != WINE_WM_HEADER)
  2120. + {
  2121. + FIXME("shouldn't have headers left\n");
  2122. + SetEvent(ev);
  2123. + continue;
  2124. + }
  2125. + ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
  2126. + ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;
  2127. +
  2128. + wodNotifyClient(wwo, WOM_DONE, param, 0);
  2129. + }
  2130. + RESET_OMR(&wwo->msgRing);
  2131. + LeaveCriticalSection(&wwo->msgRing.msg_crst);
  2132. + } else {
  2133. + /* Not sure about this ones interaction with OpenAL */
  2134. + /* It seems like Pausing causes lots of ... problems */
  2135. +
  2136. + /* pause OpenAL on this wod */
  2137. + /*TRACE("alSourcePause(%d)\n", wwo->al_source);
  2138. + alSourcePause(wwo->al_source);
  2139. + CHECK_AL_ERROR();*/
  2140. +
  2141. + /* stop OpenAL on this wod */
  2142. + /*TRACE("alSourceStop(%d)\n", wwo->al_source);
  2143. + alSourceStop(wwo->al_source);
  2144. + CHECK_AL_ERROR();*/
  2145. +
  2146. + if (wwo->lpLoopPtr) {
  2147. + /* complicated case, not handled yet (could imply modifying the loop counter */
  2148. + FIXME("Pausing while in loop isn't correctly handled yet, except strange results\n");
  2149. + wwo->lpPlayPtr = wwo->lpLoopPtr;
  2150. + wwo->dwPartialOffset = 0;
  2151. + wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
  2152. + } else {
  2153. + /* the data already written is going to be played, so take */
  2154. + /* this fact into account here */
  2155. + wwo->dwPlayedTotal = wwo->dwWrittenTotal;
  2156. + }
  2157. + wwo->state = WINE_WS_PAUSED;
  2158. + }
  2159. +}
  2160. +
  2161. +/**************************************************************************
  2162. + * wodPlayer_ProcessMessages [internal]
  2163. + */
  2164. +static void wodPlayer_ProcessMessages(WINE_WAVEOUT* wwo)
  2165. +{
  2166. + LPWAVEHDR lpWaveHdr;
  2167. + enum win_wm_message msg;
  2168. + DWORD param;
  2169. + HANDLE ev;
  2170. +
  2171. + while (OpenAL_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
  2172. + TRACE("Received %s %lx\n", wodPlayerCmdString[msg - WM_USER - 1], param);
  2173. + switch (msg) {
  2174. + case WINE_WM_PAUSING:
  2175. + wodPlayer_Reset(wwo, FALSE);
  2176. + SetEvent(ev);
  2177. + break;
  2178. + case WINE_WM_RESTARTING:
  2179. + wwo->state = WINE_WS_PLAYING;
  2180. + SetEvent(ev);
  2181. + break;
  2182. + case WINE_WM_HEADER:
  2183. + lpWaveHdr = (LPWAVEHDR)param;
  2184. +
  2185. + /* insert buffer at the end of queue */
  2186. + {
  2187. + LPWAVEHDR* wh;
  2188. + for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
  2189. + *wh = lpWaveHdr;
  2190. + }
  2191. + if (!wwo->lpPlayPtr)
  2192. + wodPlayer_BeginWaveHdr(wwo,lpWaveHdr);
  2193. + if (wwo->state == WINE_WS_STOPPED)
  2194. + wwo->state = WINE_WS_PLAYING;
  2195. + break;
  2196. + case WINE_WM_RESETTING:
  2197. + wodPlayer_Reset(wwo, TRUE);
  2198. + SetEvent(ev);
  2199. + break;
  2200. + case WINE_WM_UPDATE:
  2201. + wodUpdatePlayedTotal(wwo);
  2202. + SetEvent(ev);
  2203. + break;
  2204. + case WINE_WM_BREAKLOOP:
  2205. + if (wwo->state == WINE_WS_PLAYING && wwo->lpLoopPtr != NULL) {
  2206. + /* ensure exit at end of current loop */
  2207. + wwo->dwLoops = 1;
  2208. + }
  2209. + SetEvent(ev);
  2210. + break;
  2211. + case WINE_WM_CLOSING:
  2212. + /* sanity check: this should not happen since the device must have been reset before */
  2213. + if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
  2214. + wwo->hThread = 0;
  2215. + wwo->state = WINE_WS_CLOSED;
  2216. + SetEvent(ev);
  2217. + TRACE("Killing Thread ... how?\n");
  2218. + ExitThread(0);
  2219. + /* shouldn't go here */
  2220. + default:
  2221. + FIXME("unknown message %d\n", msg);
  2222. + break;
  2223. + }
  2224. + }
  2225. +}
  2226. +
  2227. +/**************************************************************************
  2228. + * wodPlayer_FeedDSP [internal]
  2229. + * Feed as much sound data as we can into the DSP and return the number of
  2230. + * milliseconds before it will be necessary to feed the DSP again.
  2231. + */
  2232. +static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
  2233. +{
  2234. + DWORD availInQ;
  2235. +
  2236. + wodUpdatePlayedTotal(wwo);
  2237. + /* better way to set availInQ? */
  2238. + availInQ = OPENAL_BUF_SIZE;
  2239. + TRACE("availInQ = %ld\n", availInQ);
  2240. +
  2241. + /* input queue empty */
  2242. + if (!wwo->lpPlayPtr) {
  2243. + TRACE("Run out of wavehdr:s... flushing\n");
  2244. + return INFINITE;
  2245. + }
  2246. +
  2247. +#if 0
  2248. + /* no more room... no need to try to feed */
  2249. + if(!availInQ)
  2250. + {
  2251. + TRACE("no more room, no need to try to feed\n");
  2252. + return wwo->dwSleepTime;
  2253. + }
  2254. +#endif
  2255. +
  2256. + /* Feed from partial wavehdr */
  2257. + if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0)
  2258. + {
  2259. + TRACE("feeding from partial wavehdr\n");
  2260. + wodPlayer_WriteMaxFrags(wwo, &availInQ);
  2261. + }
  2262. +
  2263. + /* Feed wavehdrs until we run out of wavehdrs or DSP space */
  2264. + if (!wwo->dwPartialOffset)
  2265. + {
  2266. + while(wwo->lpPlayPtr && availInQ)
  2267. + {
  2268. + TRACE("feeding waveheaders until we run out of space\n");
  2269. + /* note the value that dwPlayedTotal will return when this wave finishes playing */
  2270. + wwo->lpPlayPtr->reserved = wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength;
  2271. + TRACE("reserved=(%ld) dwWrittenTotal=(%ld) dwBufferLength=(%ld)\n",
  2272. + wwo->lpPlayPtr->reserved,
  2273. + wwo->dwWrittenTotal,
  2274. + wwo->lpPlayPtr->dwBufferLength
  2275. + );
  2276. + wodPlayer_WriteMaxFrags(wwo, &availInQ);
  2277. + }
  2278. + }
  2279. +
  2280. + if (!wwo->lpPlayPtr) {
  2281. + TRACE("Ran out of wavehdrs\n");
  2282. + return INFINITE;
  2283. + }
  2284. +
  2285. + return wwo->dwSleepTime;
  2286. +}
  2287. +
  2288. +/**************************************************************************
  2289. + * wodPlayer [internal]
  2290. + */
  2291. +static DWORD CALLBACK wodPlayer(LPVOID pmt)
  2292. +{
  2293. + WORD uDevID = (DWORD)pmt;
  2294. + WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)&WOutDev[uDevID];
  2295. + DWORD dwNextFeedTime = INFINITE; /* Time before DSP needs feeding */
  2296. + DWORD dwNextNotifyTime = INFINITE; /* Time before next wave completion */
  2297. + DWORD dwSleepTime;
  2298. +
  2299. + wwo->state = WINE_WS_STOPPED;
  2300. + SetEvent(wwo->hStartUpEvent);
  2301. +
  2302. + for (;;) {
  2303. + /** Wait for the shortest time before an action is required. If there
  2304. + * are no pending actions, wait forever for a command.
  2305. + */
  2306. + dwSleepTime = min(dwNextFeedTime, dwNextNotifyTime);
  2307. + TRACE("waiting %lums (%lu,%lu)\n", dwSleepTime, dwNextFeedTime, dwNextNotifyTime);
  2308. + WAIT_OMR(&wwo->msgRing, dwSleepTime);
  2309. + wodPlayer_ProcessMessages(wwo);
  2310. + if (wwo->state == WINE_WS_PLAYING) {
  2311. + dwNextFeedTime = wodPlayer_FeedDSP(wwo);
  2312. + dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE);
  2313. + } else {
  2314. + dwNextFeedTime = dwNextNotifyTime = INFINITE;
  2315. + }
  2316. + }
  2317. +}
  2318. +
  2319. +/**************************************************************************
  2320. + * wodGetDevCaps [internal]
  2321. + */
  2322. +static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize)
  2323. +{
  2324. + TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
  2325. +
  2326. + if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
  2327. +
  2328. + if (wDevID >= MAX_WAVEOUTDRV) {
  2329. + TRACE("MAX_WAVOUTDRV reached !\n");
  2330. + return MMSYSERR_BADDEVICEID;
  2331. + }
  2332. +
  2333. + memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
  2334. + return MMSYSERR_NOERROR;
  2335. +}
  2336. +
  2337. +/**************************************************************************
  2338. + * wodOpen [internal]
  2339. + */
  2340. +static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
  2341. +{
  2342. + WINE_WAVEOUT* wwo;
  2343. +
  2344. + TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
  2345. + if (lpDesc == NULL) {
  2346. + WARN("Invalid Parameter !\n");
  2347. + return MMSYSERR_INVALPARAM;
  2348. + }
  2349. + if (wDevID >= MAX_WAVEOUTDRV) {
  2350. + TRACE("MAX_WAVOUTDRV reached !\n");
  2351. + return MMSYSERR_BADDEVICEID;
  2352. + }
  2353. +
  2354. + /* if this device is already open tell the app that it is allocated */
  2355. + if(WOutDev[wDevID].live)
  2356. + {
  2357. + TRACE("device already allocated\n");
  2358. + return MMSYSERR_ALLOCATED;
  2359. + }
  2360. +
  2361. + /* only PCM format is supported so far... */
  2362. + if (!supportedFormat(lpDesc->lpFormat, 0)) {
  2363. + WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
  2364. + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
  2365. + lpDesc->lpFormat->nSamplesPerSec);
  2366. + return WAVERR_BADFORMAT;
  2367. + }
  2368. +
  2369. + if (dwFlags & WAVE_FORMAT_QUERY) {
  2370. + TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
  2371. + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
  2372. + lpDesc->lpFormat->nSamplesPerSec);
  2373. + return MMSYSERR_NOERROR;
  2374. + }
  2375. +
  2376. + wwo = &WOutDev[wDevID];
  2377. +
  2378. + /* direct sound not supported, ignore the flag */
  2379. + dwFlags &= ~WAVE_DIRECTSOUND;
  2380. +
  2381. + wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
  2382. +
  2383. + memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
  2384. + copy_format(lpDesc->lpFormat, &wwo->waveFormat);
  2385. +
  2386. + if (wwo->waveFormat.Format.wBitsPerSample == 0) {
  2387. + WARN("Resetting zeroed wBitsPerSample\n");
  2388. + wwo->waveFormat.Format.wBitsPerSample = 8 *
  2389. + (wwo->waveFormat.Format.nAvgBytesPerSec /
  2390. + wwo->waveFormat.Format.nSamplesPerSec) /
  2391. + wwo->waveFormat.Format.nChannels;
  2392. + }
  2393. +
  2394. + wwo->bytes_per_frame = (wwo->waveFormat.Format.wBitsPerSample * wwo->waveFormat.Format.nChannels) / 8;
  2395. +
  2396. + /* output to OpenAL... */
  2397. + wwo->live = 1;
  2398. + alGenSources(1, &wwo->al_source);
  2399. + CHECK_AL_ERROR();
  2400. +
  2401. + wwo->num_al_buffers = 0;
  2402. + wwo->al_buffers = (ALuint*)HeapAlloc(GetProcessHeap(), 0, sizeof(ALuint));
  2403. + wwo->num_free_al_buffers = 0;
  2404. + wwo->free_al_buffers = (ALuint*)HeapAlloc(GetProcessHeap(), 0, sizeof(ALuint));
  2405. +
  2406. + if(!wwo->live) return MMSYSERR_ALLOCATED;
  2407. +
  2408. + wwo->dwBufferSize = OPENAL_BUF_SIZE;
  2409. + TRACE("Buffer size is now (%ld)\n", wwo->dwBufferSize);
  2410. +
  2411. + wwo->dwPlayedTotal = 0;
  2412. + wwo->dwWrittenTotal = 0;
  2413. +
  2414. + wwo->dwSleepTime = (1024 * 1000 * BUFFER_REFILL_THRESHOLD) / wwo->waveFormat.Format.nAvgBytesPerSec;
  2415. +
  2416. + /* Initialize volume to full level */
  2417. + wwo->volume_left = 100;
  2418. + wwo->volume_right = 100;
  2419. +
  2420. + OpenAL_InitRingMessage(&wwo->msgRing);
  2421. +
  2422. + /* create player thread */
  2423. + if (!(dwFlags & WAVE_DIRECTSOUND)) {
  2424. + wwo->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
  2425. + wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD)wDevID, 0, &(wwo->dwThreadID));
  2426. + WaitForSingleObject(wwo->hStartUpEvent, INFINITE);
  2427. + CloseHandle(wwo->hStartUpEvent);
  2428. + } else {
  2429. + wwo->hThread = INVALID_HANDLE_VALUE;
  2430. + wwo->dwThreadID = 0;
  2431. + }
  2432. + wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
  2433. +
  2434. + TRACE("live=0x%lx, dwBufferSize=%ld\n",
  2435. + (long)wwo->live, wwo->dwBufferSize);
  2436. +
  2437. + TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
  2438. + wwo->waveFormat.Format.wBitsPerSample, wwo->waveFormat.Format.nAvgBytesPerSec,
  2439. + wwo->waveFormat.Format.nSamplesPerSec, wwo->waveFormat.Format.nChannels,
  2440. + wwo->waveFormat.Format.nBlockAlign);
  2441. +
  2442. + return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
  2443. +}
  2444. +
  2445. +/**************************************************************************
  2446. + * wodClose [internal]
  2447. + */
  2448. +static DWORD wodClose(WORD wDevID)
  2449. +{
  2450. + DWORD ret = MMSYSERR_NOERROR;
  2451. + WINE_WAVEOUT* wwo;
  2452. +
  2453. + TRACE("(%u);\n", wDevID);
  2454. +
  2455. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2456. + WARN("bad device ID !\n");
  2457. + return MMSYSERR_BADDEVICEID;
  2458. + }
  2459. +
  2460. + wwo = &WOutDev[wDevID];
  2461. + if (wwo->lpQueuePtr) {
  2462. + WARN("buffers still playing !\n");
  2463. + ret = WAVERR_STILLPLAYING;
  2464. + } else {
  2465. + TRACE("imhere[3-close]\n");
  2466. + if (wwo->hThread != INVALID_HANDLE_VALUE) {
  2467. + OpenAL_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);
  2468. + }
  2469. +
  2470. + OpenAL_DestroyRingMessage(&wwo->msgRing);
  2471. +
  2472. + OpenAL_CloseWaveOutDevice(wwo); /* close the stream and clean things up */
  2473. +
  2474. + ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
  2475. + }
  2476. + return ret;
  2477. +}
  2478. +
  2479. +/**************************************************************************
  2480. + * wodWrite [internal]
  2481. + *
  2482. + */
  2483. +static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
  2484. +{
  2485. + TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
  2486. +
  2487. + /* first, do the sanity checks... */
  2488. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2489. + WARN("bad dev ID !\n");
  2490. + return MMSYSERR_BADDEVICEID;
  2491. + }
  2492. +
  2493. + if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
  2494. + {
  2495. + TRACE("unprepared\n");
  2496. + return WAVERR_UNPREPARED;
  2497. + }
  2498. +
  2499. + if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
  2500. + {
  2501. + TRACE("still playing\n");
  2502. + return WAVERR_STILLPLAYING;
  2503. + }
  2504. +
  2505. + lpWaveHdr->dwFlags &= ~WHDR_DONE;
  2506. + lpWaveHdr->dwFlags |= WHDR_INQUEUE;
  2507. + lpWaveHdr->lpNext = 0;
  2508. +
  2509. + TRACE("adding ring message\n");
  2510. + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
  2511. +
  2512. + return MMSYSERR_NOERROR;
  2513. +}
  2514. +
  2515. +/**************************************************************************
  2516. + * wodPause [internal]
  2517. + */
  2518. +static DWORD wodPause(WORD wDevID)
  2519. +{
  2520. + TRACE("(%u);!\n", wDevID);
  2521. +
  2522. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2523. + WARN("bad device ID !\n");
  2524. + return MMSYSERR_BADDEVICEID;
  2525. + }
  2526. +
  2527. + TRACE("imhere[3-PAUSING]\n");
  2528. + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_PAUSING, 0, TRUE);
  2529. +
  2530. + return MMSYSERR_NOERROR;
  2531. +}
  2532. +
  2533. +/**************************************************************************
  2534. + * wodRestart [internal]
  2535. + */
  2536. +static DWORD wodRestart(WORD wDevID)
  2537. +{
  2538. + TRACE("(%u);\n", wDevID);
  2539. +
  2540. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2541. + WARN("bad device ID !\n");
  2542. + return MMSYSERR_BADDEVICEID;
  2543. + }
  2544. +
  2545. + if (WOutDev[wDevID].state == WINE_WS_PAUSED) {
  2546. + TRACE("imhere[3-RESTARTING]\n");
  2547. + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESTARTING, 0, TRUE);
  2548. + }
  2549. +
  2550. + /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
  2551. + /* FIXME: Myst crashes with this ... hmm -MM
  2552. + return wodNotifyClient(wwo, WOM_DONE, 0L, 0L);
  2553. + */
  2554. +
  2555. + return MMSYSERR_NOERROR;
  2556. +}
  2557. +
  2558. +/**************************************************************************
  2559. + * wodReset [internal]
  2560. + */
  2561. +static DWORD wodReset(WORD wDevID)
  2562. +{
  2563. + TRACE("(%u);\n", wDevID);
  2564. +
  2565. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2566. + WARN("bad device ID !\n");
  2567. + return MMSYSERR_BADDEVICEID;
  2568. + }
  2569. +
  2570. + TRACE("imhere[3-RESET]\n");
  2571. + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);
  2572. +
  2573. + return MMSYSERR_NOERROR;
  2574. +}
  2575. +
  2576. +/**************************************************************************
  2577. + * wodGetPosition [internal]
  2578. + */
  2579. +static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
  2580. +{
  2581. + WINE_WAVEOUT* wwo;
  2582. +
  2583. + TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
  2584. +
  2585. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2586. + WARN("bad device ID !\n");
  2587. + return MMSYSERR_BADDEVICEID;
  2588. + }
  2589. +
  2590. + if (lpTime == NULL) {
  2591. + WARN("invalid parameter: lpTime == NULL\n");
  2592. + return MMSYSERR_INVALPARAM;
  2593. + }
  2594. +
  2595. + wwo = &WOutDev[wDevID];
  2596. + OpenAL_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
  2597. +
  2598. + return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->waveFormat);
  2599. +}
  2600. +
  2601. +/**************************************************************************
  2602. + * wodBreakLoop [internal]
  2603. + */
  2604. +static DWORD wodBreakLoop(WORD wDevID)
  2605. +{
  2606. + TRACE("(%u);\n", wDevID);
  2607. +
  2608. + if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].live) {
  2609. + WARN("bad device ID !\n");
  2610. + return MMSYSERR_BADDEVICEID;
  2611. + }
  2612. + OpenAL_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);
  2613. + return MMSYSERR_NOERROR;
  2614. +}
  2615. +
  2616. +/**************************************************************************
  2617. + * wodGetVolume [internal]
  2618. + */
  2619. +static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
  2620. +{
  2621. + DWORD left, right;
  2622. +
  2623. + left = WOutDev[wDevID].volume_left;
  2624. + right = WOutDev[wDevID].volume_right;
  2625. +
  2626. + TRACE("(%u, %p);\n", wDevID, lpdwVol);
  2627. +
  2628. + *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
  2629. + 16);
  2630. +
  2631. + return MMSYSERR_NOERROR;
  2632. +}
  2633. +
  2634. +/**************************************************************************
  2635. + * wodSetVolume [internal]
  2636. + */
  2637. +static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
  2638. +{
  2639. + DWORD left, right;
  2640. +
  2641. + left = (LOWORD(dwParam) * 100) / 0xFFFFl;
  2642. + right = (HIWORD(dwParam) * 100) / 0xFFFFl;
  2643. +
  2644. + TRACE("(%u, %08lX);\n", wDevID, dwParam);
  2645. +
  2646. + WOutDev[wDevID].volume_left = left;
  2647. + WOutDev[wDevID].volume_right = right;
  2648. +
  2649. + return MMSYSERR_NOERROR;
  2650. +}
  2651. +
  2652. +/**************************************************************************
  2653. + * wodGetNumDevs [internal]
  2654. + */
  2655. +static DWORD wodGetNumDevs(void)
  2656. +{
  2657. + return MAX_WAVEOUTDRV;
  2658. +}
  2659. +
  2660. +/**************************************************************************
  2661. + * wodDevInterfaceSize [internal]
  2662. + */
  2663. +static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
  2664. +{
  2665. + TRACE("(%u, %p)\n", wDevID, dwParam1);
  2666. +
  2667. + *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
  2668. + NULL, 0 ) * sizeof(WCHAR);
  2669. + return MMSYSERR_NOERROR;
  2670. +}
  2671. +
  2672. +/**************************************************************************
  2673. + * wodDevInterface [internal]
  2674. + */
  2675. +static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
  2676. +{
  2677. + if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
  2678. + NULL, 0 ) * sizeof(WCHAR))
  2679. + {
  2680. + MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
  2681. + dwParam1, dwParam2 / sizeof(WCHAR));
  2682. + return MMSYSERR_NOERROR;
  2683. + }
  2684. + return MMSYSERR_INVALPARAM;
  2685. +}
  2686. +
  2687. +/**************************************************************************
  2688. + * wodMessage (WINEOPENAL.@)
  2689. + */
  2690. +DWORD WINAPI OpenAL_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
  2691. + DWORD dwParam1, DWORD dwParam2)
  2692. +{
  2693. + TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
  2694. + wDevID, wMsg, dwUser, dwParam1, dwParam2);
  2695. +
  2696. + switch (wMsg) {
  2697. + case DRVM_INIT:
  2698. + case DRVM_EXIT:
  2699. + case DRVM_ENABLE:
  2700. + case DRVM_DISABLE:
  2701. + /* FIXME: Pretend this is supported */
  2702. + return 0;
  2703. + case WODM_OPEN: return wodOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
  2704. + case WODM_CLOSE: return wodClose (wDevID);
  2705. + case WODM_WRITE: return wodWrite (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
  2706. + case WODM_PAUSE: return wodPause (wDevID);
  2707. + case WODM_GETPOS: return wodGetPosition (wDevID, (LPMMTIME)dwParam1, dwParam2);
  2708. + case WODM_BREAKLOOP: return wodBreakLoop (wDevID);
  2709. + case WODM_PREPARE: return MMSYSERR_NOTSUPPORTED;
  2710. + case WODM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
  2711. + case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (LPWAVEOUTCAPSW)dwParam1, dwParam2);
  2712. + case WODM_GETNUMDEVS: return wodGetNumDevs ();
  2713. + case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED;
  2714. + case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED;
  2715. + case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
  2716. + case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED;
  2717. + case WODM_GETVOLUME: return wodGetVolume (wDevID, (LPDWORD)dwParam1);
  2718. + case WODM_SETVOLUME: return wodSetVolume (wDevID, dwParam1);
  2719. + case WODM_RESTART: return wodRestart (wDevID);
  2720. + case WODM_RESET: return wodReset (wDevID);
  2721. +
  2722. + case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
  2723. + case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
  2724. + case DRV_QUERYDSOUNDIFACE: return wodDsCreate (wDevID, (PIDSDRIVER*)dwParam1);
  2725. + case DRV_QUERYDSOUNDDESC: return wodDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
  2726. + default:
  2727. + FIXME("unknown message %d!\n", wMsg);
  2728. + }
  2729. + return MMSYSERR_NOTSUPPORTED;
  2730. +}
  2731. +
  2732. +/*======================================================================*
  2733. + * Low level WAVE IN implementation *
  2734. + *======================================================================*/
  2735. +
  2736. +/**************************************************************************
  2737. + * widGetNumDevs [internal]
  2738. + */
  2739. +static DWORD widGetNumDevs(void)
  2740. +{
  2741. + return (OPENAL_DISABLE_IN || !al_can_capture) ? 0 : MAX_WAVEINDRV;
  2742. +}
  2743. +
  2744. +/**************************************************************************
  2745. + * widDevInterfaceSize [internal]
  2746. + */
  2747. +static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
  2748. +{
  2749. + TRACE("(%u, %p)\n", wDevID, dwParam1);
  2750. +
  2751. + *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
  2752. + NULL, 0 ) * sizeof(WCHAR);
  2753. + return MMSYSERR_NOERROR;
  2754. +}
  2755. +
  2756. +/**************************************************************************
  2757. + * widDevInterface [internal]
  2758. + */
  2759. +static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
  2760. +{
  2761. + if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
  2762. + NULL, 0 ) * sizeof(WCHAR))
  2763. + {
  2764. + MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
  2765. + dwParam1, dwParam2 / sizeof(WCHAR));
  2766. + return MMSYSERR_NOERROR;
  2767. + }
  2768. + return MMSYSERR_INVALPARAM;
  2769. +}
  2770. +
  2771. +/**************************************************************************
  2772. + * widNotifyClient [internal]
  2773. + */
  2774. +static DWORD widNotifyClient(WINE_WAVEIN* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2)
  2775. +{
  2776. + TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
  2777. +
  2778. + switch (wMsg) {
  2779. + case WIM_OPEN:
  2780. + case WIM_CLOSE:
  2781. + case WIM_DATA:
  2782. + if (wwi->wFlags != DCB_NULL &&
  2783. + !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags,
  2784. + (HDRVR)wwi->waveDesc.hWave, wMsg,
  2785. + wwi->waveDesc.dwInstance, dwParam1, dwParam2)) {
  2786. + WARN("can't notify client !\n");
  2787. + return MMSYSERR_ERROR;
  2788. + }
  2789. + break;
  2790. + default:
  2791. + FIXME("Unknown callback message %u\n", wMsg);
  2792. + return MMSYSERR_INVALPARAM;
  2793. + }
  2794. + return MMSYSERR_NOERROR;
  2795. +}
  2796. +
  2797. +/**************************************************************************
  2798. + * widGetDevCaps [internal]
  2799. + */
  2800. +static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize)
  2801. +{
  2802. + TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
  2803. +
  2804. + if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
  2805. +
  2806. + if (wDevID >= MAX_WAVEINDRV) {
  2807. + TRACE("MAX_WAVINDRV reached !\n");
  2808. + return MMSYSERR_BADDEVICEID;
  2809. + }
  2810. +
  2811. + memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
  2812. + return MMSYSERR_NOERROR;
  2813. +}
  2814. +
  2815. +/**************************************************************************
  2816. + * widRecorder [internal]
  2817. + */
  2818. +static DWORD CALLBACK widRecorder(LPVOID pmt)
  2819. +{
  2820. + WORD uDevID = (DWORD)pmt;
  2821. + WINE_WAVEIN* wwi = (WINE_WAVEIN*)&WInDev[uDevID];
  2822. + WAVEHDR* lpWaveHdr;
  2823. + DWORD dwSleepTime;
  2824. + DWORD bytesRead;
  2825. + enum win_wm_message msg;
  2826. + DWORD param;
  2827. + HANDLE ev;
  2828. +
  2829. + SetEvent(wwi->hStartUpEvent);
  2830. +
  2831. + /* make sleep time to be # of ms to record one packet */
  2832. + dwSleepTime = (1024 * 1000) / wwi->waveFormat.Format.nAvgBytesPerSec;
  2833. + TRACE("sleeptime=%ld ms\n", dwSleepTime);
  2834. +
  2835. + for(;;) {
  2836. + TRACE("wwi->lpQueuePtr=(%p), wwi->state=(%d)\n",wwi->lpQueuePtr,wwi->state);
  2837. +
  2838. + /* read data from OpenAL */
  2839. + if ((wwi->lpQueuePtr != NULL) && (wwi->state == WINE_WS_PLAYING))
  2840. + {
  2841. + lpWaveHdr = wwi->lpQueuePtr;
  2842. +
  2843. + TRACE("read as much as we can\n");
  2844. + while(wwi->lpQueuePtr)
  2845. + {
  2846. + ALCint samples = 0;
  2847. +
  2848. + TRACE("attempt to read %ld bytes\n",lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
  2849. +
  2850. + /* Get samples from OpenAL on this wid */
  2851. + alcGetIntegerv(wwi->al_device, t_ALC_CAPTURE_SAMPLES, 1, &samples);
  2852. + CHECK_ALC_ERROR();
  2853. + bytesRead = (wwi->waveFormat.Format.wBitsPerSample * samples) / 8;
  2854. + TRACE("Got %d samples == %ld bytes\n", samples, bytesRead);
  2855. + /* I have no idea if the below is needed... I dont want to just overrun buffers that are not big enough... */
  2856. + /*if(bytesRead > (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded))
  2857. + {
  2858. + FIXME("Buffer overrun detected... cutting back samples -- is this correct?");
  2859. + bytesRead = (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
  2860. + samples = (bytesRead * 8) / wwi->waveFormat.Format.wBitsPerSample;
  2861. + }*/
  2862. + p_alcCaptureSamples(wwi->al_device, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, samples);
  2863. + CHECK_ALC_ERROR();
  2864. +
  2865. + TRACE("bytesRead=%ld\n",bytesRead);
  2866. + if (bytesRead == -1 && errno == EAGAIN)
  2867. + bytesRead = 0;
  2868. + if (bytesRead==0) break; /* So we can stop recording smoothly */
  2869. + if (bytesRead < 0)
  2870. + bytesRead = 0;
  2871. +
  2872. + lpWaveHdr->dwBytesRecorded += bytesRead;
  2873. + wwi->dwRecordedTotal += bytesRead;
  2874. +
  2875. + /* buffer full. notify client */
  2876. + if (lpWaveHdr->dwBytesRecorded >= lpWaveHdr->dwBufferLength)
  2877. + {
  2878. + /* must copy the value of next waveHdr, because we have no idea of what
  2879. + * will be done with the content of lpWaveHdr in callback
  2880. + */
  2881. + LPWAVEHDR lpNext = lpWaveHdr->lpNext;
  2882. +
  2883. + TRACE("waveHdr full.\n");
  2884. +
  2885. + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
  2886. + lpWaveHdr->dwFlags |= WHDR_DONE;
  2887. +
  2888. + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
  2889. + lpWaveHdr = wwi->lpQueuePtr = lpNext;
  2890. + TRACE("wwi->lpQueuePtr=%p\n", wwi->lpQueuePtr);
  2891. + }
  2892. + }
  2893. + }
  2894. +
  2895. + /* wait for dwSleepTime or an event in thread's queue */
  2896. + WAIT_OMR(&wwi->msgRing, dwSleepTime);
  2897. +
  2898. + while (OpenAL_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev))
  2899. + {
  2900. + TRACE("msg=%s param=0x%lx\n",wodPlayerCmdString[msg - WM_USER - 1], param);
  2901. + switch(msg) {
  2902. + case WINE_WM_PAUSING:
  2903. + wwi->state = WINE_WS_PAUSED;
  2904. +
  2905. + /* stop OpenAL on this wid -- correct or no? */
  2906. + p_alcCaptureStop(wwi->al_device);
  2907. + CHECK_ALC_ERROR();
  2908. +
  2909. + SetEvent(ev);
  2910. + break;
  2911. + case WINE_WM_STARTING:
  2912. + wwi->state = WINE_WS_PLAYING;
  2913. +
  2914. + /* start OpenAL on this wid */
  2915. + p_alcCaptureStart(wwi->al_device);
  2916. + CHECK_ALC_ERROR();
  2917. +
  2918. + SetEvent(ev);
  2919. + break;
  2920. + case WINE_WM_HEADER:
  2921. + lpWaveHdr = (LPWAVEHDR)param;
  2922. + /* insert buffer at end of queue */
  2923. + {
  2924. + LPWAVEHDR* wh;
  2925. + int num_headers = 0;
  2926. + for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext))
  2927. + {
  2928. + num_headers++;
  2929. + }
  2930. + *wh=lpWaveHdr;
  2931. + }
  2932. + break;
  2933. + case WINE_WM_STOPPING:
  2934. + if (wwi->state != WINE_WS_STOPPED)
  2935. + {
  2936. + /* stop OpenAL on this wid */
  2937. + p_alcCaptureStop(wwi->al_device);
  2938. + CHECK_ALC_ERROR();
  2939. +
  2940. + /* return current buffer to app */
  2941. + lpWaveHdr = wwi->lpQueuePtr;
  2942. + if (lpWaveHdr)
  2943. + {
  2944. + LPWAVEHDR lpNext = lpWaveHdr->lpNext;
  2945. + TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
  2946. + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
  2947. + lpWaveHdr->dwFlags |= WHDR_DONE;
  2948. + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
  2949. + wwi->lpQueuePtr = lpNext;
  2950. + }
  2951. + }
  2952. + wwi->state = WINE_WS_STOPPED;
  2953. + SetEvent(ev);
  2954. + break;
  2955. + case WINE_WM_RESETTING:
  2956. + wwi->state = WINE_WS_STOPPED;
  2957. + wwi->dwRecordedTotal = 0;
  2958. +
  2959. + /* stop OpenAL on this wid */
  2960. + p_alcCaptureStop(wwi->al_device);
  2961. + CHECK_ALC_ERROR();
  2962. +
  2963. + /* return all buffers to the app */
  2964. + for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) {
  2965. + TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
  2966. + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
  2967. + lpWaveHdr->dwFlags |= WHDR_DONE;
  2968. +
  2969. + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
  2970. + }
  2971. + wwi->lpQueuePtr = NULL;
  2972. + SetEvent(ev);
  2973. + break;
  2974. + case WINE_WM_CLOSING:
  2975. + wwi->hThread = 0;
  2976. + wwi->state = WINE_WS_CLOSED;
  2977. + SetEvent(ev);
  2978. + TRACE("Killing Thread ... how?\n");
  2979. + ExitThread(0);
  2980. + /* shouldn't go here */
  2981. + default:
  2982. + FIXME("unknown message %d\n", msg);
  2983. + break;
  2984. + }
  2985. + }
  2986. + }
  2987. + TRACE("Killing Thread ... how?\n");
  2988. + ExitThread(0);
  2989. + /* just for not generating compilation warnings... should never be executed */
  2990. + return 0;
  2991. +}
  2992. +
  2993. +/**************************************************************************
  2994. + * widOpen [internal]
  2995. + */
  2996. +static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
  2997. +{
  2998. + WINE_WAVEIN* wwi;
  2999. +
  3000. + TRACE("(%u, %p %08lX);\n",wDevID, lpDesc, dwFlags);
  3001. + if (lpDesc == NULL) {
  3002. + WARN("Invalid Parametr (lpDesc == NULL)!\n");
  3003. + return MMSYSERR_INVALPARAM;
  3004. + }
  3005. +
  3006. + if (wDevID >= MAX_WAVEINDRV) {
  3007. + TRACE ("MAX_WAVEINDRV reached !\n");
  3008. + return MMSYSERR_BADDEVICEID;
  3009. + }
  3010. +
  3011. + /* if this device is already open tell the app that it is allocated */
  3012. + if(WInDev[wDevID].live)
  3013. + {
  3014. + TRACE("device already allocated\n");
  3015. + return MMSYSERR_ALLOCATED;
  3016. + }
  3017. +
  3018. + /* only PCM format is support so far... */
  3019. + if (!supportedFormat(lpDesc->lpFormat, 1)) {
  3020. + WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
  3021. + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
  3022. + lpDesc->lpFormat->nSamplesPerSec);
  3023. + return WAVERR_BADFORMAT;
  3024. + }
  3025. +
  3026. + if (dwFlags & WAVE_FORMAT_QUERY) {
  3027. + TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
  3028. + lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
  3029. + lpDesc->lpFormat->nSamplesPerSec);
  3030. + return MMSYSERR_NOERROR;
  3031. + }
  3032. +
  3033. + wwi = &WInDev[wDevID];
  3034. +
  3035. + /* direct sound not supported, ignore the flag */
  3036. + dwFlags &= ~WAVE_DIRECTSOUND;
  3037. +
  3038. + wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
  3039. +
  3040. + memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
  3041. + copy_format(lpDesc->lpFormat, &wwi->waveFormat);
  3042. +
  3043. + if (wwi->waveFormat.Format.wBitsPerSample == 0) {
  3044. + WARN("Resetting zerod wBitsPerSample\n");
  3045. + wwi->waveFormat.Format.wBitsPerSample = 8 *
  3046. + (wwi->waveFormat.Format.nAvgBytesPerSec /
  3047. + wwi->waveFormat.Format.nSamplesPerSec) /
  3048. + wwi->waveFormat.Format.nChannels;
  3049. + }
  3050. +
  3051. + /* input OpenAL... */
  3052. + wwi->bytes_per_frame = (wwi->waveFormat.Format.wBitsPerSample * wwi->waveFormat.Format.nChannels) / 8;
  3053. + {
  3054. + ALenum format = al_format_for_wave_format(&wwi->waveFormat);
  3055. + ALuint freq = wwi->waveFormat.Format.nSamplesPerSec;
  3056. + /* Setup the OpenAL cap device */ /* Be able to hold 4 secs worth of data? */
  3057. + wwi->al_device = p_alcCaptureOpenDevice(NULL, freq, format, 4 * wwi->waveFormat.Format.nSamplesPerSec * wwi->waveFormat.Format.wBitsPerSample / 8);
  3058. +//wwi->al_device = p_alcCaptureOpenDevice(NULL, 44100, format, 4 * wwi->waveFormat.Format.nSamplesPerSec * wwi->waveFormat.Format.wBitsPerSample / 8);
  3059. + TRACE("wwi->al_device = %p\n", wwi->al_device);
  3060. + CHECK_ALC_ERROR();
  3061. + if(!wwi->al_device)
  3062. + {
  3063. + WARN("alcCaptureOpenDevice(%p, %d, %d, %ld) failed\n", NULL, freq, format, 4 * wwi->waveFormat.Format.nSamplesPerSec * wwi->waveFormat.Format.wBitsPerSample / 8);
  3064. + return MMSYSERR_ALLOCATED;
  3065. + }
  3066. + wwi->live = 1;
  3067. + }
  3068. +
  3069. + if(!wwi->live) return MMSYSERR_ALLOCATED;
  3070. +
  3071. + wwi->dwRecordedTotal = 0;
  3072. + wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
  3073. +
  3074. + OpenAL_InitRingMessage(&wwi->msgRing);
  3075. +
  3076. + /* create recorder thread */
  3077. + if (!(dwFlags & WAVE_DIRECTSOUND)) {
  3078. + wwi->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
  3079. + wwi->hThread = CreateThread(NULL, 0, widRecorder, (LPVOID)(DWORD)wDevID, 0, &(wwi->dwThreadID));
  3080. + WaitForSingleObject(wwi->hStartUpEvent, INFINITE);
  3081. + CloseHandle(wwi->hStartUpEvent);
  3082. + } else {
  3083. + wwi->hThread = INVALID_HANDLE_VALUE;
  3084. + wwi->dwThreadID = 0;
  3085. + }
  3086. + wwi->hStartUpEvent = INVALID_HANDLE_VALUE;
  3087. +
  3088. + TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
  3089. + wwi->waveFormat.Format.wBitsPerSample, wwi->waveFormat.Format.nAvgBytesPerSec,
  3090. + wwi->waveFormat.Format.nSamplesPerSec, wwi->waveFormat.Format.nChannels,
  3091. + wwi->waveFormat.Format.nBlockAlign);
  3092. + return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
  3093. +}
  3094. +
  3095. +/**************************************************************************
  3096. + * widClose [internal]
  3097. + */
  3098. +static DWORD widClose(WORD wDevID)
  3099. +{
  3100. + WINE_WAVEIN* wwi;
  3101. +
  3102. + TRACE("(%u);\n", wDevID);
  3103. + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
  3104. + WARN("can't close !\n");
  3105. + return MMSYSERR_INVALHANDLE;
  3106. + }
  3107. +
  3108. + wwi = &WInDev[wDevID];
  3109. +
  3110. + if (wwi->lpQueuePtr != NULL) {
  3111. + WARN("still buffers open !\n");
  3112. + return WAVERR_STILLPLAYING;
  3113. + }
  3114. +
  3115. + OpenAL_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
  3116. + OpenAL_CloseWaveInDevice(wwi);
  3117. + wwi->state = WINE_WS_CLOSED;
  3118. + OpenAL_DestroyRingMessage(&wwi->msgRing);
  3119. + return widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
  3120. +}
  3121. +
  3122. +/**************************************************************************
  3123. + * widAddBuffer [internal]
  3124. + */
  3125. +static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
  3126. +{
  3127. + TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
  3128. +
  3129. + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
  3130. + WARN("can't do it !\n");
  3131. + return MMSYSERR_INVALHANDLE;
  3132. + }
  3133. + if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
  3134. + TRACE("never been prepared !\n");
  3135. + return WAVERR_UNPREPARED;
  3136. + }
  3137. + if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
  3138. + TRACE("header already in use !\n");
  3139. + return WAVERR_STILLPLAYING;
  3140. + }
  3141. +
  3142. + lpWaveHdr->dwFlags |= WHDR_INQUEUE;
  3143. + lpWaveHdr->dwFlags &= ~WHDR_DONE;
  3144. + lpWaveHdr->dwBytesRecorded = 0;
  3145. + lpWaveHdr->lpNext = NULL;
  3146. +
  3147. + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
  3148. + return MMSYSERR_NOERROR;
  3149. +}
  3150. +
  3151. +/**************************************************************************
  3152. + * widStart [internal]
  3153. + */
  3154. +static DWORD widStart(WORD wDevID)
  3155. +{
  3156. + TRACE("(%u);\n", wDevID);
  3157. + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
  3158. + WARN("can't start recording !\n");
  3159. + return MMSYSERR_INVALHANDLE;
  3160. + }
  3161. +
  3162. + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_STARTING, 0, TRUE);
  3163. + return MMSYSERR_NOERROR;
  3164. +}
  3165. +
  3166. +/**************************************************************************
  3167. + * widStop [internal]
  3168. + */
  3169. +static DWORD widStop(WORD wDevID)
  3170. +{
  3171. + TRACE("(%u);\n", wDevID);
  3172. + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
  3173. + WARN("can't stop !\n");
  3174. + return MMSYSERR_INVALHANDLE;
  3175. + }
  3176. +
  3177. + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_STOPPING, 0, TRUE);
  3178. +
  3179. + return MMSYSERR_NOERROR;
  3180. +}
  3181. +
  3182. +/**************************************************************************
  3183. + * widReset [internal]
  3184. + */
  3185. +static DWORD widReset(WORD wDevID)
  3186. +{
  3187. + TRACE("(%u);\n", wDevID);
  3188. + if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
  3189. + WARN("can't reset !\n");
  3190. + return MMSYSERR_INVALHANDLE;
  3191. + }
  3192. + OpenAL_AddRingMessage(&WInDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);
  3193. + return MMSYSERR_NOERROR;
  3194. +}
  3195. +
  3196. +/**************************************************************************
  3197. + * widMessage (WINEOPENAL.6)
  3198. + */
  3199. +DWORD WINAPI OpenAL_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
  3200. + DWORD dwParam1, DWORD dwParam2)
  3201. +{
  3202. + TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
  3203. + wDevID, wMsg, dwUser, dwParam1, dwParam2);
  3204. +
  3205. + switch (wMsg) {
  3206. + case DRVM_INIT:
  3207. + case DRVM_EXIT:
  3208. + case DRVM_ENABLE:
  3209. + case DRVM_DISABLE:
  3210. + /* FIXME: Pretend this is supported */
  3211. + return 0;
  3212. + case WIDM_OPEN: return widOpen (wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
  3213. + case WIDM_CLOSE: return widClose (wDevID);
  3214. + case WIDM_ADDBUFFER: return widAddBuffer (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
  3215. + case WIDM_PREPARE: return MMSYSERR_NOTSUPPORTED;
  3216. + case WIDM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
  3217. + case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSW)dwParam1, dwParam2);
  3218. + case WIDM_GETNUMDEVS: return widGetNumDevs ();
  3219. + case WIDM_RESET: return widReset (wDevID);
  3220. + case WIDM_START: return widStart (wDevID);
  3221. + case WIDM_STOP: return widStop (wDevID);
  3222. + case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
  3223. + case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
  3224. + default:
  3225. + FIXME("unknown message %d!\n", wMsg);
  3226. + }
  3227. + return MMSYSERR_NOTSUPPORTED;
  3228. +}
  3229. +
  3230. +/*======================================================================*
  3231. + * Low level DSOUND implementation *
  3232. + *======================================================================*/
  3233. +static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
  3234. +{
  3235. + /* REMOVE COMMENT: we can't perform memory mapping as we don't have a file stream
  3236. + interface with esd like we do with oss */
  3237. + MESSAGE("This sound card's driver does not support direct access\n");
  3238. + MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
  3239. + return MMSYSERR_NOTSUPPORTED;
  3240. +}
  3241. +
  3242. +static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
  3243. +{
  3244. + memset(desc, 0, sizeof(*desc));
  3245. + strcpy(desc->szDesc, "Wine OpenAL DirectSound Driver");
  3246. + strcpy(desc->szDrvname, "wineopenal.drv");
  3247. + return MMSYSERR_NOERROR;
  3248. +}
  3249. +
  3250. +#else /* !defined(HAVE_OPENAL_AL_H) && !defined(HAVE_AL_AL_H) */
  3251. +
  3252. +/**************************************************************************
  3253. + * wodMessage (WINEOPENAL.@)
  3254. + */
  3255. +DWORD WINAPI OpenAL_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
  3256. + DWORD dwParam1, DWORD dwParam2)
  3257. +{
  3258. + FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
  3259. + return MMSYSERR_NOTENABLED;
  3260. +}
  3261. +
  3262. +/**************************************************************************
  3263. + * widMessage (WINEOPENAL.6)
  3264. + */
  3265. +DWORD WINAPI OpenAL_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
  3266. + DWORD dwParam1, DWORD dwParam2)
  3267. +{
  3268. + FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
  3269. + return MMSYSERR_NOTENABLED;
  3270. +}
  3271. +
  3272. +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
  3273. diff --git a/dlls/wineopenal.drv/openal.c b/dlls/wineopenal.drv/openal.c
  3274. new file mode 100644
  3275. index 0000000..4e0702d
  3276. --- /dev/null
  3277. +++ b/dlls/wineopenal.drv/openal.c
  3278. @@ -0,0 +1,87 @@
  3279. +/*
  3280. + * Wine Driver for OpenAL
  3281. + * http://www.openal.org
  3282. + *
  3283. + * Copyright 2004 Zhangrong Huang <hzhr@users.sourceforge.net>
  3284. + * 2006 Nick Burns <adger44@hotmail.com> (OpenAL version)
  3285. + *
  3286. + * Code massively copied from Eric Pouech's OSS driver
  3287. + * and Chris Morgan aRts driver
  3288. + *
  3289. + * This library is free software; you can redistribute it and/or
  3290. + * modify it under the terms of the GNU Lesser General Public
  3291. + * License as published by the Free Software Foundation; either
  3292. + * version 2.1 of the License, or (at your option) any later version.
  3293. + *
  3294. + * This library is distributed in the hope that it will be useful,
  3295. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3296. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  3297. + * Lesser General Public License for more details.
  3298. + *
  3299. + * You should have received a copy of the GNU Lesser General Public
  3300. + * License along with this library; if not, write to the Free Software
  3301. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  3302. + */
  3303. +
  3304. +#include "config.h"
  3305. +
  3306. +#include <stdarg.h>
  3307. +
  3308. +#include "windef.h"
  3309. +#include "winbase.h"
  3310. +#include "wingdi.h"
  3311. +#include "winuser.h"
  3312. +#include "mmddk.h"
  3313. +#include "openal.h"
  3314. +#include "wine/library.h"
  3315. +#include "wine/debug.h"
  3316. +
  3317. +WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
  3318. +
  3319. +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
  3320. +
  3321. +/**************************************************************************
  3322. + * OpenAL_drvOpen [internal]
  3323. + */
  3324. +static LRESULT OpenAL_drvOpen(LPSTR str)
  3325. +{
  3326. + return 1;
  3327. +}
  3328. +
  3329. +/**************************************************************************
  3330. + * OpenAL_drvClose [internal]
  3331. + */
  3332. +static LRESULT OpenAL_drvClose(DWORD_PTR dwDevID)
  3333. +{
  3334. + return 1;
  3335. +}
  3336. +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
  3337. +
  3338. +
  3339. +/**************************************************************************
  3340. + * DriverProc (WINEOPENAL.@)
  3341. + */
  3342. +LRESULT CALLBACK OpenAL_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
  3343. + LPARAM dwParam1, LPARAM dwParam2)
  3344. +{
  3345. +/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
  3346. +/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
  3347. +
  3348. + switch(wMsg) {
  3349. +#if defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H)
  3350. + case DRV_LOAD: if (OpenAL_WaveInit()<0) return 0;
  3351. + return 1;
  3352. + case DRV_FREE: return OpenAL_WaveClose();
  3353. + case DRV_OPEN: return OpenAL_drvOpen((LPSTR)dwParam1);
  3354. + case DRV_CLOSE: return OpenAL_drvClose(dwDevID);
  3355. + case DRV_ENABLE: return 1;
  3356. + case DRV_DISABLE: return 1;
  3357. + case DRV_QUERYCONFIGURE: return 1;
  3358. + case DRV_CONFIGURE: MessageBoxA(0, "OpenAL MultiMedia Driver!", "OpenAL Driver", MB_OK); return 1;
  3359. + case DRV_INSTALL: return DRVCNF_RESTART;
  3360. + case DRV_REMOVE: return DRVCNF_RESTART;
  3361. +#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
  3362. + default:
  3363. + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
  3364. + }
  3365. +}
  3366. diff --git a/dlls/wineopenal.drv/openal.h b/dlls/wineopenal.drv/openal.h
  3367. new file mode 100644
  3368. index 0000000..3c9aec0
  3369. --- /dev/null
  3370. +++ b/dlls/wineopenal.drv/openal.h
  3371. @@ -0,0 +1,35 @@
  3372. +/* Definition for OpenAL drivers : wine multimedia system
  3373. + *
  3374. + * Copyright 2004 Zhangrong Huang <hzhr@users.sourceforge.net>
  3375. + * 2006 Nick Burns <adger44@hotmail.com> (OpenAL version)
  3376. + *
  3377. + * This library is free software; you can redistribute it and/or
  3378. + * modify it under the terms of the GNU Lesser General Public
  3379. + * License as published by the Free Software Foundation; either
  3380. + * version 2.1 of the License, or (at your option) any later version.
  3381. + *
  3382. + * This library is distributed in the hope that it will be useful,
  3383. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3384. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  3385. + * Lesser General Public License for more details.
  3386. + *
  3387. + * You should have received a copy of the GNU Lesser General Public
  3388. + * License along with this library; if not, write to the Free Software
  3389. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  3390. + */
  3391. +
  3392. +#ifndef __WINE_OPENAL_H
  3393. +#define __WINE_OPENAL_H
  3394. +
  3395. +#ifndef __WINE_CONFIG_H
  3396. +# error You must include config.h to use this header
  3397. +#endif
  3398. +
  3399. +#ifdef HAVE_SYS_ERRNO_H
  3400. +#include <sys/errno.h>
  3401. +#endif
  3402. +
  3403. +extern LONG OpenAL_WaveInit(void);
  3404. +extern LONG OpenAL_WaveClose(void);
  3405. +
  3406. +#endif /* __WINE_OPENAL_H */
  3407. diff --git a/dlls/wineopenal.drv/wineopenal.drv.spec b/dlls/wineopenal.drv/wineopenal.drv.spec
  3408. new file mode 100644
  3409. index 0000000..e08c3d8
  3410. --- /dev/null
  3411. +++ b/dlls/wineopenal.drv/wineopenal.drv.spec
  3412. @@ -0,0 +1,3 @@
  3413. +@ stdcall -private DriverProc(long long long long long) OpenAL_DriverProc
  3414. +@ stdcall -private wodMessage(long long long long long) OpenAL_wodMessage
  3415. +@ stdcall -private widMessage(long long long long long) OpenAL_widMessage
  3416. diff --git a/configure.ac b/configure.ac
  3417. index 72f93b7..18ca664 100644
  3418. --- a/configure.ac
  3419. +++ b/configure.ac
  3420. @@ -247,10 +247,13 @@ AC_CHECK_LIB(pthread,pthread_create,AC_SUBST(LIBPTHREAD,"-lpthread"))
  3421.  
  3422. AC_SUBST(XLIB,"")
  3423. AC_SUBST(OPENGL_LIBS,"")
  3424. +AC_SUBST(OPENAL,"")
  3425.  
  3426. dnl **** Check for header files ****
  3427.  
  3428. AC_CHECK_HEADERS(\
  3429. + OpenAL/al.h \
  3430. + AL/al.h \
  3431. AudioUnit/AudioUnit.h \
  3432. Carbon/Carbon.h \
  3433. CoreAudio/CoreAudio.h \
  3434. @@ -542,6 +545,11 @@ case $host_os in
  3435. dnl CoreServices needed by AudioUnit
  3436. AC_SUBST(COREAUDIO,"-framework CoreAudio -framework AudioUnit -framework CoreServices -framework AudioToolbox -framework CoreMIDI")
  3437. fi
  3438. + if test "$ac_cv_header_OpenAL_al_h" = "yes"
  3439. + then
  3440. + dnl OpenAL framework
  3441. + AC_SUBST(OPENAL,"-framework OpenAL")
  3442. + fi
  3443. case $host_cpu in
  3444. *powerpc*)
  3445. LDDLLFLAGS="$LDDLLFLAGS -read_only_relocs warning" dnl FIXME
  3446. @@ -1264,6 +1272,15 @@ then
  3447. WINE_WARNING([No sound system was found. Windows applications will be silent.])
  3448. fi
  3449.  
  3450. +dnl **** Check for OpenAL support ****
  3451. +dnl **** Mac OSX OpenAL support checked below ****
  3452. +
  3453. +if test "$ac_cv_header_AL_al_h" = "yes"
  3454. + then
  3455. + dnl OpenAL framework
  3456. + AC_SUBST(OPENAL,"-lopenal")
  3457. +fi
  3458. +
  3459. dnl **** Check for gcc specific options ****
  3460.  
  3461. AC_SUBST(EXTRACFLAGS,"")
  3462. @@ -2014,6 +2031,7 @@ WINE_CONFIG_MAKEFILE([dlls/olecli32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_D
  3463. WINE_CONFIG_MAKEFILE([dlls/oledlg/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3464. WINE_CONFIG_MAKEFILE([dlls/olepro32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3465. WINE_CONFIG_MAKEFILE([dlls/olesvr32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3466. +WINE_CONFIG_MAKEFILE([dlls/openal32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3467. WINE_CONFIG_MAKEFILE([dlls/olethk32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3468. WINE_CONFIG_MAKEFILE([dlls/opengl32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3469. WINE_CONFIG_MAKEFILE([dlls/opengl32/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests])
  3470. @@ -2119,6 +2137,7 @@ WINE_CONFIG_MAKEFILE([dlls/winejack.drv/Makefile],[dlls/Makedll.rules],[dlls],[A
  3471. WINE_CONFIG_MAKEFILE([dlls/winejoystick.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3472. WINE_CONFIG_MAKEFILE([dlls/winemp3.acm/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3473. WINE_CONFIG_MAKEFILE([dlls/winenas.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3474. +WINE_CONFIG_MAKEFILE([dlls/wineopenal.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3475. WINE_CONFIG_MAKEFILE([dlls/wineoss.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3476. WINE_CONFIG_MAKEFILE([dlls/wineps.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3477. WINE_CONFIG_MAKEFILE([dlls/winequartz.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
  3478. diff --git a/dlls/Makefile.in b/dlls/Makefile.in
  3479. index 794905a..5a38be5 100644
  3480. --- a/dlls/Makefile.in
  3481. +++ b/dlls/Makefile.in
  3482. @@ -116,6 +116,9 @@ olecli.dll16:
  3483.  
  3484. olesvr.dll16:
  3485. echo "olesvr32.dll" >$@
  3486. +
  3487. +openal.dll16:
  3488. + echo "openal32.dll" >$@
  3489.  
  3490. rasapi16.dll16:
  3491. echo "rasapi32.dll" >$@
  3492. @@ -264,6 +267,7 @@ IMPORT_LIBS = \
  3493. oledlg/liboledlg.$(IMPLIBEXT) \
  3494. olepro32/libolepro32.$(IMPLIBEXT) \
  3495. olesvr32/libolesvr32.$(IMPLIBEXT) \
  3496. + openal32/libopenal32.$(IMPLIBEXT) \
  3497. opengl32/libopengl32.$(IMPLIBEXT) \
  3498. pdh/libpdh.$(IMPLIBEXT) \
  3499. powrprof/libpowrprof.$(IMPLIBEXT) \
  3500. @@ -405,6 +409,7 @@ CROSS_IMPLIBS = \
  3501. oledlg/liboledlg.a \
  3502. olepro32/libolepro32.a \
  3503. olesvr32/libolesvr32.a \
  3504. + openal32/libopenal32.a \
  3505. opengl32/libopengl32.a \
  3506. pdh/libpdh.a \
  3507. powrprof/libpowrprof.a \
  3508. @@ -726,6 +731,9 @@ olepro32/libolepro32.def olepro32/libolepro32.a: olepro32/olepro32.spec $(WINEBU
  3509. olesvr32/libolesvr32.def olesvr32/libolesvr32.a: olesvr32/olesvr32.spec $(WINEBUILD)
  3510. @cd olesvr32 && $(MAKE) `basename $@`
  3511.  
  3512. +openal32/libopenal32.def openal32/libopenal32.a: openal32/openal32.spec $(WINEBUILD)
  3513. + @cd openal32 && $(MAKE) `basename $@`
  3514. +
  3515. opengl32/libopengl32.def opengl32/libopengl32.a: opengl32/opengl32.spec $(WINEBUILD)
  3516. @cd opengl32 && $(MAKE) `basename $@`
  3517.  
  3518. diff --git a/programs/winecfg/En.rc b/programs/winecfg/En.rc
  3519. index 5743ba3..f790f95 100644
  3520. --- a/programs/winecfg/En.rc
  3521. +++ b/programs/winecfg/En.rc
  3522. @@ -277,6 +277,7 @@ BEGIN
  3523. IDS_DRIVER_NAS "NAS Driver"
  3524. IDS_DRIVER_AUDIOIO "Audio IO (Solaris) Driver"
  3525. IDS_DRIVER_COREAUDIO "CoreAudio Driver"
  3526. + IDS_DRIVER_OPENAL "OpenAL Driver"
  3527. IDS_OPEN_DRIVER_ERROR "Couldn't open %s!"
  3528. IDS_SOUNDDRIVERS "Sound Drivers"
  3529. IDS_DEVICES_WAVEOUT "Wave Out Devices"
  3530. diff --git a/programs/winecfg/audio.c b/programs/winecfg/audio.c
  3531. index 8e966a5..75596e4 100644
  3532. --- a/programs/winecfg/audio.c
  3533. +++ b/programs/winecfg/audio.c
  3534. @@ -95,6 +95,7 @@ static const AUDIO_DRIVER sAudioDrivers[] = {
  3535. {IDS_DRIVER_NAS, "nas"},
  3536. {IDS_DRIVER_ESOUND, "esd"},
  3537. {IDS_DRIVER_AUDIOIO, "audioio"},
  3538. + {IDS_DRIVER_OPENAL, "openal"},
  3539. {0, ""}
  3540. };
  3541.  
  3542. diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
  3543. index a18fe76..24b9120 100644
  3544. --- a/programs/winecfg/resource.h
  3545. +++ b/programs/winecfg/resource.h
  3546. @@ -255,3 +255,5 @@
  3547. /* About tab */
  3548. #define IDC_ABT_OWNER 8432
  3549. #define IDC_ABT_ORG 8433
  3550. +
  3551. +#define IDS_DRIVER_OPENAL 8434
  3552.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement