Reworked Windows waveOut code.
Implemented multi-device support, changed name to "winmm".
--- a/VisualC/SDL/SDL_VS2005.vcproj Thu Aug 04 01:26:12 2011 -0400
+++ b/VisualC/SDL/SDL_VS2005.vcproj Thu Aug 04 01:24:22 2011 -0400
@@ -796,11 +796,11 @@
>
</File>
<File
- RelativePath="..\..\src\audio\windib\SDL_dibaudio.c"
+ RelativePath="..\..\src\audio\winmm\SDL_winmm.c"
>
</File>
<File
- RelativePath="..\..\src\audio\windib\SDL_dibaudio.h"
+ RelativePath="..\..\src\audio\winmm\SDL_winmm.h"
>
</File>
<File
--- a/VisualC/SDL/SDL_VS2008.vcproj Thu Aug 04 01:26:12 2011 -0400
+++ b/VisualC/SDL/SDL_VS2008.vcproj Thu Aug 04 01:24:22 2011 -0400
@@ -785,11 +785,11 @@
>
</File>
<File
- RelativePath="..\..\src\audio\windib\SDL_dibaudio.c"
+ RelativePath="..\..\src\audio\winmm\SDL_winmm.c"
>
</File>
<File
- RelativePath="..\..\src\audio\windib\SDL_dibaudio.h"
+ RelativePath="..\..\src\audio\winmm\SDL_winmm.h"
>
</File>
<File
--- a/VisualC/SDL/SDL_VS2010.vcxproj Thu Aug 04 01:26:12 2011 -0400
+++ b/VisualC/SDL/SDL_VS2010.vcxproj Thu Aug 04 01:24:22 2011 -0400
@@ -276,7 +276,7 @@
<ClInclude Include="..\..\src\video\SDL_blit_copy.h" />
<ClInclude Include="..\..\src\video\SDL_blit_slow.h" />
<ClInclude Include="..\..\src\video\SDL_shape_internals.h" />
- <ClInclude Include="..\..\src\audio\windib\SDL_dibaudio.h" />
+ <ClInclude Include="..\..\src\audio\winmm\SDL_winmm.h" />
<ClInclude Include="..\..\src\audio\disk\SDL_diskaudio.h" />
<ClInclude Include="..\..\src\audio\dummy\SDL_dummyaudio.h" />
<ClInclude Include="..\..\src\audio\directsound\SDL_directsound.h" />
@@ -377,7 +377,7 @@
<ClCompile Include="..\..\src\cpuinfo\SDL_cpuinfo.c" />
<ClCompile Include="..\..\src\video\SDL_clipboard.c" />
<ClCompile Include="..\..\src\video\SDL_shape.c" />
- <ClCompile Include="..\..\src\audio\windib\SDL_dibaudio.c" />
+ <ClCompile Include="..\..\src\audio\winmm\SDL_winmm.c" />
<ClCompile Include="..\..\src\audio\disk\SDL_diskaudio.c" />
<ClCompile Include="..\..\src\audio\dummy\SDL_dummyaudio.c" />
<ClCompile Include="..\..\src\audio\directsound\SDL_directsound.c" />
--- a/configure.in Thu Aug 04 01:26:12 2011 -0400
+++ b/configure.in Thu Aug 04 01:24:22 2011 -0400
@@ -2057,8 +2057,8 @@
fi
# Set up files for the audio library
if test x$enable_audio = xyes; then
- AC_DEFINE(SDL_AUDIO_DRIVER_WINWAVEOUT, 1, [ ])
- SOURCES="$SOURCES $srcdir/src/audio/windib/*.c"
+ AC_DEFINE(SDL_AUDIO_DRIVER_WINMM, 1, [ ])
+ SOURCES="$SOURCES $srcdir/src/audio/winmm/*.c"
if test x$have_dsound = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_DSOUND, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/directsound/*.c"
@@ -2144,8 +2144,8 @@
fi
# Set up files for the audio library
if test x$enable_audio = xyes; then
- AC_DEFINE(SDL_AUDIO_DRIVER_WINWAVEOUT, 1, [ ])
- SOURCES="$SOURCES $srcdir/src/audio/windib/*.c"
+ AC_DEFINE(SDL_AUDIO_DRIVER_WINMM, 1, [ ])
+ SOURCES="$SOURCES $srcdir/src/audio/winmm/*.c"
if test x$have_dsound = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_DSOUND, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/directsound/*.c"
--- a/include/SDL_config.h.in Thu Aug 04 01:26:12 2011 -0400
+++ b/include/SDL_config.h.in Thu Aug 04 01:24:22 2011 -0400
@@ -195,7 +195,7 @@
#undef SDL_AUDIO_DRIVER_PAUDIO
#undef SDL_AUDIO_DRIVER_QSA
#undef SDL_AUDIO_DRIVER_SUNAUDIO
-#undef SDL_AUDIO_DRIVER_WINWAVEOUT
+#undef SDL_AUDIO_DRIVER_WINMM
#undef SDL_AUDIO_DRIVER_FUSIONSOUND
#undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
--- a/include/SDL_config_windows.h Thu Aug 04 01:26:12 2011 -0400
+++ b/include/SDL_config_windows.h Thu Aug 04 01:24:22 2011 -0400
@@ -146,7 +146,7 @@
#ifndef _WIN32_WCE
#define SDL_AUDIO_DRIVER_DSOUND 1
#endif
-#define SDL_AUDIO_DRIVER_WINWAVEOUT 1
+#define SDL_AUDIO_DRIVER_WINMM 1
#define SDL_AUDIO_DRIVER_DISK 1
#define SDL_AUDIO_DRIVER_DUMMY 1
--- a/src/audio/SDL_audio.c Thu Aug 04 01:26:12 2011 -0400
+++ b/src/audio/SDL_audio.c Thu Aug 04 01:24:22 2011 -0400
@@ -53,7 +53,7 @@
extern AudioBootStrap ESD_bootstrap;
extern AudioBootStrap NAS_bootstrap;
extern AudioBootStrap DSOUND_bootstrap;
-extern AudioBootStrap WINWAVEOUT_bootstrap;
+extern AudioBootStrap WINMM_bootstrap;
extern AudioBootStrap PAUDIO_bootstrap;
extern AudioBootStrap BEOSAUDIO_bootstrap;
extern AudioBootStrap COREAUDIO_bootstrap;
@@ -100,8 +100,8 @@
#if SDL_AUDIO_DRIVER_DSOUND
&DSOUND_bootstrap,
#endif
-#if SDL_AUDIO_DRIVER_WINWAVEOUT
- &WINWAVEOUT_bootstrap,
+#if SDL_AUDIO_DRIVER_WINMM
+ &WINMM_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_PAUDIO
&PAUDIO_bootstrap,
--- a/src/audio/windib/SDL_dibaudio.c Thu Aug 04 01:26:12 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
-/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_config.h"
-
-/* Allow access to a raw mixing buffer */
-
-#include "../../core/windows/SDL_windows.h"
-#include <mmsystem.h>
-
-#include "SDL_timer.h"
-#include "SDL_audio.h"
-#include "../SDL_audio_c.h"
-#include "SDL_dibaudio.h"
-#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
-#include "win_ce_semaphore.h"
-#endif
-
-#if defined(_WIN32_WCE)
-#define WINDOWS_OS_NAME "Windows CE/PocketPC"
-#elif defined(WIN64)
-#define WINDOWS_OS_NAME "Win64"
-#else
-#define WINDOWS_OS_NAME "Win32"
-#endif
-
-/* The Win32 callback for filling the WAVE device */
-static void CALLBACK
-FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
- DWORD dwParam1, DWORD dwParam2)
-{
- SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
-
- /* Only service "buffer done playing" messages */
- if (uMsg != WOM_DONE)
- return;
-
- /* Signal that we are done playing a buffer */
-#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
- ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
-#else
- ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
-#endif
-}
-
-static void
-SetMMerror(char *function, MMRESULT code)
-{
- size_t len;
- char errbuf[MAXERRORLENGTH];
- wchar_t werrbuf[MAXERRORLENGTH];
-
- SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
- len = SDL_strlen(errbuf);
-
- waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
- WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
- MAXERRORLENGTH - len, NULL, NULL);
-
- SDL_SetError("%s", errbuf);
-}
-
-/* Set high priority for the audio thread */
-static void
-WINWAVEOUT_ThreadInit(_THIS)
-{
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
-}
-
-void
-WINWAVEOUT_WaitDevice(_THIS)
-{
- /* Wait for an audio chunk to finish */
-#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
- WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
-#else
- WaitForSingleObject(this->hidden->audio_sem, INFINITE);
-#endif
-}
-
-Uint8 *
-WINWAVEOUT_GetDeviceBuf(_THIS)
-{
- return (Uint8 *) (this->hidden->
- wavebuf[this->hidden->next_buffer].lpData);
-}
-
-void
-WINWAVEOUT_PlayDevice(_THIS)
-{
- /* Queue it up */
- waveOutWrite(this->hidden->sound,
- &this->hidden->wavebuf[this->hidden->next_buffer],
- sizeof(this->hidden->wavebuf[0]));
- this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
-}
-
-void
-WINWAVEOUT_WaitDone(_THIS)
-{
- int i, left;
-
- do {
- left = NUM_BUFFERS;
- for (i = 0; i < NUM_BUFFERS; ++i) {
- if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
- --left;
- }
- }
- if (left > 0) {
- SDL_Delay(100);
- }
- } while (left > 0);
-}
-
-void
-WINWAVEOUT_CloseDevice(_THIS)
-{
- /* Close up audio */
- if (this->hidden != NULL) {
- int i;
-
- if (this->hidden->audio_sem) {
-#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
- CloseSynchHandle(this->hidden->audio_sem);
-#else
- CloseHandle(this->hidden->audio_sem);
-#endif
- this->hidden->audio_sem = 0;
- }
-
- if (this->hidden->sound) {
- waveOutClose(this->hidden->sound);
- this->hidden->sound = 0;
- }
-
- /* Clean up mixing buffers */
- for (i = 0; i < NUM_BUFFERS; ++i) {
- if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
- waveOutUnprepareHeader(this->hidden->sound,
- &this->hidden->wavebuf[i],
- sizeof(this->hidden->wavebuf[i]));
- this->hidden->wavebuf[i].dwUser = 0xFFFF;
- }
- }
-
- if (this->hidden->mixbuf != NULL) {
- /* Free raw mixing buffer */
- SDL_free(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- }
-
- SDL_free(this->hidden);
- this->hidden = NULL;
- }
-}
-
-int
-WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture)
-{
- SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
- int valid_datatype = 0;
- MMRESULT result;
- WAVEFORMATEX waveformat;
- int i;
-
- /* Initialize all variables that we clean on shutdown */
- this->hidden = (struct SDL_PrivateAudioData *)
- SDL_malloc((sizeof *this->hidden));
- if (this->hidden == NULL) {
- SDL_OutOfMemory();
- return 0;
- }
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
- /* Initialize the wavebuf structures for closing */
- for (i = 0; i < NUM_BUFFERS; ++i)
- this->hidden->wavebuf[i].dwUser = 0xFFFF;
-
- while ((!valid_datatype) && (test_format)) {
- valid_datatype = 1;
- this->spec.format = test_format;
- switch (test_format) {
- case AUDIO_U8:
- case AUDIO_S16:
- case AUDIO_S32:
- break; /* valid. */
-
- default:
- valid_datatype = 0;
- test_format = SDL_NextAudioFormat();
- break;
- }
- }
-
- if (!valid_datatype) {
- WINWAVEOUT_CloseDevice(this);
- SDL_SetError("Unsupported audio format");
- return 0;
- }
-
- /* Set basic WAVE format parameters */
- SDL_memset(&waveformat, '\0', sizeof(waveformat));
- waveformat.wFormatTag = WAVE_FORMAT_PCM;
- waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
-
- if (this->spec.channels > 2)
- this->spec.channels = 2; /* !!! FIXME: is this right? */
-
- waveformat.nChannels = this->spec.channels;
- waveformat.nSamplesPerSec = this->spec.freq;
- waveformat.nBlockAlign =
- waveformat.nChannels * (waveformat.wBitsPerSample / 8);
- waveformat.nAvgBytesPerSec =
- waveformat.nSamplesPerSec * waveformat.nBlockAlign;
-
- /* Check the buffer size -- minimum of 1/4 second (word aligned) */
- if (this->spec.samples < (this->spec.freq / 4))
- this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
-
- /* Update the fragment size as size in bytes */
- SDL_CalculateAudioSpec(&this->spec);
-
- /* Open the audio device */
- result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat,
- (DWORD_PTR) FillSound, (DWORD_PTR) this,
- CALLBACK_FUNCTION);
- if (result != MMSYSERR_NOERROR) {
- WINWAVEOUT_CloseDevice(this);
- SetMMerror("waveOutOpen()", result);
- return 0;
- }
-#ifdef SOUND_DEBUG
- /* Check the sound device we retrieved */
- {
- WAVEOUTCAPS caps;
-
- result = waveOutGetDevCaps((UINT) this->hidden->sound,
- &caps, sizeof(caps));
- if (result != MMSYSERR_NOERROR) {
- WINWAVEOUT_CloseDevice(this);
- SetMMerror("waveOutGetDevCaps()", result);
- return 0;
- }
- printf("Audio device: %s\n", caps.szPname);
- }
-#endif
-
- /* Create the audio buffer semaphore */
- this->hidden->audio_sem =
-#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
- CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
-#else
- CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
-#endif
- if (this->hidden->audio_sem == NULL) {
- WINWAVEOUT_CloseDevice(this);
- SDL_SetError("Couldn't create semaphore");
- return 0;
- }
-
- /* Create the sound buffers */
- this->hidden->mixbuf =
- (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
- if (this->hidden->mixbuf == NULL) {
- WINWAVEOUT_CloseDevice(this);
- SDL_OutOfMemory();
- return 0;
- }
- for (i = 0; i < NUM_BUFFERS; ++i) {
- SDL_memset(&this->hidden->wavebuf[i], '\0',
- sizeof(this->hidden->wavebuf[i]));
- this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
- this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
- this->hidden->wavebuf[i].lpData =
- (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
- result = waveOutPrepareHeader(this->hidden->sound,
- &this->hidden->wavebuf[i],
- sizeof(this->hidden->wavebuf[i]));
- if (result != MMSYSERR_NOERROR) {
- WINWAVEOUT_CloseDevice(this);
- SetMMerror("waveOutPrepareHeader()", result);
- return 0;
- }
- }
-
- return 1; /* Ready to go! */
-}
-
-
-static int
-WINWAVEOUT_Init(SDL_AudioDriverImpl * impl)
-{
- /* Set the function pointers */
- impl->OpenDevice = WINWAVEOUT_OpenDevice;
- impl->ThreadInit = WINWAVEOUT_ThreadInit;
- impl->PlayDevice = WINWAVEOUT_PlayDevice;
- impl->WaitDevice = WINWAVEOUT_WaitDevice;
- impl->WaitDone = WINWAVEOUT_WaitDone;
- impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf;
- impl->CloseDevice = WINWAVEOUT_CloseDevice;
- impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Is this true? */
-
- return 1; /* this audio target is available. */
-}
-
-AudioBootStrap WINWAVEOUT_bootstrap = {
- "waveout", WINDOWS_OS_NAME " WaveOut", WINWAVEOUT_Init, 0
-};
-
-/* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/windib/SDL_dibaudio.h Thu Aug 04 01:26:12 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_config.h"
-
-#ifndef _SDL_dibaudio_h
-#define _SDL_dibaudio_h
-
-#include "../SDL_sysaudio.h"
-
-/* Hidden "this" pointer for the audio functions */
-#define _THIS SDL_AudioDevice *this
-
-#define NUM_BUFFERS 2 /* -- Don't lower this! */
-
-struct SDL_PrivateAudioData
-{
- HWAVEOUT sound;
- HANDLE audio_sem;
- Uint8 *mixbuf; /* The raw allocated mixing buffer */
- WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */
- int next_buffer;
-};
-
-#endif /* _SDL_dibaudio_h */
-
-/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/winmm/SDL_winmm.c Thu Aug 04 01:24:22 2011 -0400
@@ -0,0 +1,466 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+/* Allow access to a raw mixing buffer */
+
+#include "../../core/windows/SDL_windows.h"
+#include <mmsystem.h>
+
+#include "SDL_timer.h"
+#include "SDL_audio.h"
+#include "../SDL_audio_c.h"
+#include "SDL_winmm.h"
+#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
+#include "win_ce_semaphore.h"
+#endif
+
+
+/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(),
+ * !!! FIXME: which is more proof this needs to be managed in SDL_audio.c
+ * !!! FIXME: and not in drivers.
+ */
+static void
+FreeWaveOutAudioDevices(char ***devices, int *devCount)
+{
+ int i = *devCount;
+ if ((i > 0) && (*devices != NULL)) {
+ while (i--) {
+ SDL_free((*devices)[i]);
+ }
+ }
+
+ if (*devices != NULL) {
+ SDL_free(*devices);
+ }
+
+ *devices = NULL;
+ *devCount = 0;
+}
+
+static char **outputDevices = NULL;
+static int outputDeviceCount = 0;
+static char **inputDevices = NULL;
+static int inputDeviceCount = 0;
+
+static int
+DetectWaveOutDevices(void)
+{
+ UINT i;
+ const UINT devcount = waveOutGetNumDevs();
+ WAVEOUTCAPS caps;
+ FreeWaveOutAudioDevices(&outputDevices, &outputDeviceCount);
+ outputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount);
+ for (i = 0; i < devcount; i++) {
+ if (waveOutGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) {
+ outputDevices[outputDeviceCount] = WIN_StringToUTF8(caps.szPname);
+ if (outputDevices[outputDeviceCount] != NULL) {
+ outputDeviceCount++;
+ }
+ }
+ }
+ return outputDeviceCount;
+}
+
+static int
+DetectWaveInDevices(void)
+{
+ UINT i;
+ const UINT devcount = waveInGetNumDevs();
+ WAVEINCAPS caps;
+ FreeWaveInAudioDevices(&inputDevices, &inputDeviceCount);
+ inputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount);
+ for (i = 0; i < devcount; i++) {
+ if (waveInGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) {
+ inputDevices[inputDeviceCount] = WIN_StringToUTF8(caps.szPname);
+ if (inputDevices[inputDeviceCount] != NULL) {
+ inputDeviceCount++;
+ }
+ }
+ }
+ return inputDeviceCount;
+}
+
+static int
+WINMM_DetectDevices(int iscapture)
+{
+ return (iscapture) ? DetectWaveInDevices() : DetectWaveOutDevices();
+}
+
+static const char *
+WINMM_GetDeviceName(int index, int iscapture)
+{
+ if ((iscapture) && (index < inputDeviceCount)) {
+ return inputDevices[index];
+ } else if ((!iscapture) && (index < outputDeviceCount)) {
+ return outputDevices[index];
+ }
+
+ SDL_SetError("No such device");
+ return NULL;
+}
+
+static void CALLBACK
+CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
+ DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+{
+ SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
+
+ /* Only service "buffer is filled" messages */
+ if (uMsg != WIM_DATA)
+ return;
+
+ /* Signal that we have a new buffer of data */
+#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
+ ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
+#else
+ ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
+#endif
+}
+
+
+/* The Win32 callback for filling the WAVE device */
+static void CALLBACK
+FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
+ DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+{
+ SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
+
+ /* Only service "buffer done playing" messages */
+ if (uMsg != WOM_DONE)
+ return;
+
+ /* Signal that we are done playing a buffer */
+#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
+ ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
+#else
+ ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
+#endif
+}
+
+static void
+SetMMerror(char *function, MMRESULT code)
+{
+ size_t len;
+ char errbuf[MAXERRORLENGTH];
+ wchar_t werrbuf[MAXERRORLENGTH];
+
+ SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
+ len = SDL_strlen(errbuf);
+
+ waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
+ WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
+ MAXERRORLENGTH - len, NULL, NULL);
+
+ SDL_SetError("%s", errbuf);
+}
+
+static void
+WINMM_WaitDevice(_THIS)
+{
+ /* Wait for an audio chunk to finish */
+#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
+ WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
+#else
+ WaitForSingleObject(this->hidden->audio_sem, INFINITE);
+#endif
+}
+
+static Uint8 *
+WINMM_GetDeviceBuf(_THIS)
+{
+ return (Uint8 *) (this->hidden->
+ wavebuf[this->hidden->next_buffer].lpData);
+}
+
+static void
+WINMM_PlayDevice(_THIS)
+{
+ /* Queue it up */
+ waveOutWrite(this->hidden->hout,
+ &this->hidden->wavebuf[this->hidden->next_buffer],
+ sizeof(this->hidden->wavebuf[0]));
+ this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
+}
+
+static void
+WINMM_WaitDone(_THIS)
+{
+ int i, left;
+
+ do {
+ left = NUM_BUFFERS;
+ for (i = 0; i < NUM_BUFFERS; ++i) {
+ if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
+ --left;
+ }
+ }
+ if (left > 0) {
+ SDL_Delay(100);
+ }
+ } while (left > 0);
+}
+
+static void
+WINMM_CloseDevice(_THIS)
+{
+ /* Close up audio */
+ if (this->hidden != NULL) {
+ int i;
+
+ if (this->hidden->audio_sem) {
+#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
+ CloseSynchHandle(this->hidden->audio_sem);
+#else
+ CloseHandle(this->hidden->audio_sem);
+#endif
+ this->hidden->audio_sem = 0;
+ }
+
+ if (this->hidden->hin) {
+ waveInClose(this->hidden->hin);
+ this->hidden->hin = 0;
+ }
+
+ if (this->hidden->hout) {
+ waveOutClose(this->hidden->hout);
+ this->hidden->hout = 0;
+ }
+
+ /* Clean up mixing buffers */
+ for (i = 0; i < NUM_BUFFERS; ++i) {
+ if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
+ waveOutUnprepareHeader(this->hidden->hout,
+ &this->hidden->wavebuf[i],
+ sizeof(this->hidden->wavebuf[i]));
+ this->hidden->wavebuf[i].dwUser = 0xFFFF;
+ }
+ }
+
+ if (this->hidden->mixbuf != NULL) {
+ /* Free raw mixing buffer */
+ SDL_free(this->hidden->mixbuf);
+ this->hidden->mixbuf = NULL;
+ }
+
+ SDL_free(this->hidden);
+ this->hidden = NULL;
+ }
+}
+
+static int
+WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
+{
+ SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
+ int valid_datatype = 0;
+ MMRESULT result;
+ WAVEFORMATEX waveformat;
+ UINT_PTR devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
+ char *utf8 = NULL;
+ int i;
+
+ if (devname != NULL) { /* specific device requested? */
+ if (iscapture) {
+ const int devcount = (int) waveInGetNumDevs();
+ WAVEINCAPS caps;
+ for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
+ result = waveInGetDevCaps(i, &caps, sizeof (caps));
+ if (result != MMSYSERR_NOERROR)
+ continue;
+ else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
+ continue;
+ else if (SDL_strcmp(devname, utf8) == 0)
+ devId = (UINT_PTR) i;
+ SDL_free(utf8);
+ }
+ } else {
+ const int devcount = (int) waveOutGetNumDevs();
+ WAVEOUTCAPS caps;
+ for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
+ result = waveOutGetDevCaps(i, &caps, sizeof (caps));
+ if (result != MMSYSERR_NOERROR)
+ continue;
+ else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
+ continue;
+ else if (SDL_strcmp(devname, utf8) == 0)
+ devId = (UINT_PTR) i;
+ SDL_free(utf8);
+ }
+ }
+
+ if (devId == WAVE_MAPPER) {
+ SDL_SetError("Requested device not found");
+ return 0;
+ }
+ }
+
+ /* Initialize all variables that we clean on shutdown */
+ this->hidden = (struct SDL_PrivateAudioData *)
+ SDL_malloc((sizeof *this->hidden));
+ if (this->hidden == NULL) {
+ SDL_OutOfMemory();
+ return 0;
+ }
+ SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+ /* Initialize the wavebuf structures for closing */
+ for (i = 0; i < NUM_BUFFERS; ++i)
+ this->hidden->wavebuf[i].dwUser = 0xFFFF;
+
+ while ((!valid_datatype) && (test_format)) {
+ valid_datatype = 1;
+ this->spec.format = test_format;
+ switch (test_format) {
+ case AUDIO_U8:
+ case AUDIO_S16:
+ case AUDIO_S32:
+ break; /* valid. */
+
+ default:
+ valid_datatype = 0;
+ test_format = SDL_NextAudioFormat();
+ break;
+ }
+ }
+
+ if (!valid_datatype) {
+ WINMM_CloseDevice(this);
+ SDL_SetError("Unsupported audio format");
+ return 0;
+ }
+
+ /* Set basic WAVE format parameters */
+ SDL_memset(&waveformat, '\0', sizeof(waveformat));
+ waveformat.wFormatTag = WAVE_FORMAT_PCM;
+ waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
+
+ if (this->spec.channels > 2)
+ this->spec.channels = 2; /* !!! FIXME: is this right? */
+
+ waveformat.nChannels = this->spec.channels;
+ waveformat.nSamplesPerSec = this->spec.freq;
+ waveformat.nBlockAlign =
+ waveformat.nChannels * (waveformat.wBitsPerSample / 8);
+ waveformat.nAvgBytesPerSec =
+ waveformat.nSamplesPerSec * waveformat.nBlockAlign;
+
+ /* Check the buffer size -- minimum of 1/4 second (word aligned) */
+ if (this->spec.samples < (this->spec.freq / 4))
+ this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
+
+ /* Update the fragment size as size in bytes */
+ SDL_CalculateAudioSpec(&this->spec);
+
+ /* Open the audio device */
+ if (iscapture) {
+ result = waveInOpen(&this->hidden->hin, devId, &waveformat,
+ (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
+ CALLBACK_FUNCTION);
+ } else {
+ result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
+ (DWORD_PTR) FillSound, (DWORD_PTR) this,
+ CALLBACK_FUNCTION);
+ }
+
+ if (result != MMSYSERR_NOERROR) {
+ WINMM_CloseDevice(this);
+ SetMMerror("waveOutOpen()", result);
+ return 0;
+ }
+#ifdef SOUND_DEBUG
+ /* Check the sound device we retrieved */
+ {
+ WAVEOUTCAPS caps;
+
+ result = waveOutGetDevCaps((UINT) this->hidden->hout,
+ &caps, sizeof(caps));
+ if (result != MMSYSERR_NOERROR) {
+ WINMM_CloseDevice(this);
+ SetMMerror("waveOutGetDevCaps()", result);
+ return 0;
+ }
+ printf("Audio device: %s\n", caps.szPname);
+ }
+#endif
+
+ /* Create the audio buffer semaphore */
+ this->hidden->audio_sem =
+#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
+ CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
+#else
+ CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
+#endif
+ if (this->hidden->audio_sem == NULL) {
+ WINMM_CloseDevice(this);
+ SDL_SetError("Couldn't create semaphore");
+ return 0;
+ }
+
+ /* Create the sound buffers */
+ this->hidden->mixbuf =
+ (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
+ if (this->hidden->mixbuf == NULL) {
+ WINMM_CloseDevice(this);
+ SDL_OutOfMemory();
+ return 0;
+ }
+ for (i = 0; i < NUM_BUFFERS; ++i) {
+ SDL_memset(&this->hidden->wavebuf[i], '\0',
+ sizeof(this->hidden->wavebuf[i]));
+ this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
+ this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
+ this->hidden->wavebuf[i].lpData =
+ (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
+ result = waveOutPrepareHeader(this->hidden->hout,
+ &this->hidden->wavebuf[i],
+ sizeof(this->hidden->wavebuf[i]));
+ if (result != MMSYSERR_NOERROR) {
+ WINMM_CloseDevice(this);
+ SetMMerror("waveOutPrepareHeader()", result);
+ return 0;
+ }
+ }
+
+ return 1; /* Ready to go! */
+}
+
+
+static int
+WINMM_Init(SDL_AudioDriverImpl * impl)
+{
+ /* Set the function pointers */
+ impl->DetectDevices = WINMM_DetectDevices;
+ impl->GetDeviceName = WINMM_GetDeviceName;
+ impl->OpenDevice = WINMM_OpenDevice;
+ impl->PlayDevice = WINMM_PlayDevice;
+ impl->WaitDevice = WINMM_WaitDevice;
+ impl->WaitDone = WINMM_WaitDone;
+ impl->GetDeviceBuf = WINMM_GetDeviceBuf;
+ impl->CloseDevice = WINMM_CloseDevice;
+
+ return 1; /* this audio target is available. */
+}
+
+AudioBootStrap WINMM_bootstrap = {
+ "winmm", "Windows Waveform Audio", WINMM_Init, 0
+};
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/winmm/SDL_winmm.h Thu Aug 04 01:24:22 2011 -0400
@@ -0,0 +1,45 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#ifndef _SDL_winmm_h
+#define _SDL_winmm_h
+
+#include "../SDL_sysaudio.h"
+
+/* Hidden "this" pointer for the audio functions */
+#define _THIS SDL_AudioDevice *this
+
+#define NUM_BUFFERS 2 /* -- Don't lower this! */
+
+struct SDL_PrivateAudioData
+{
+ HWAVEOUT hout;
+ HWAVEIN hin;
+ HANDLE audio_sem;
+ Uint8 *mixbuf; /* The raw allocated mixing buffer */
+ WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */
+ int next_buffer;
+};
+
+#endif /* _SDL_winmm_h */
+
+/* vi: set ts=4 sw=4 expandtab: */