Reworked Windows waveOut code.
Implemented multi-device support, changed name to "winmm".
1.1 --- a/VisualC/SDL/SDL_VS2005.vcproj Thu Aug 04 01:26:12 2011 -0400
1.2 +++ b/VisualC/SDL/SDL_VS2005.vcproj Thu Aug 04 01:24:22 2011 -0400
1.3 @@ -796,11 +796,11 @@
1.4 >
1.5 </File>
1.6 <File
1.7 - RelativePath="..\..\src\audio\windib\SDL_dibaudio.c"
1.8 + RelativePath="..\..\src\audio\winmm\SDL_winmm.c"
1.9 >
1.10 </File>
1.11 <File
1.12 - RelativePath="..\..\src\audio\windib\SDL_dibaudio.h"
1.13 + RelativePath="..\..\src\audio\winmm\SDL_winmm.h"
1.14 >
1.15 </File>
1.16 <File
2.1 --- a/VisualC/SDL/SDL_VS2008.vcproj Thu Aug 04 01:26:12 2011 -0400
2.2 +++ b/VisualC/SDL/SDL_VS2008.vcproj Thu Aug 04 01:24:22 2011 -0400
2.3 @@ -785,11 +785,11 @@
2.4 >
2.5 </File>
2.6 <File
2.7 - RelativePath="..\..\src\audio\windib\SDL_dibaudio.c"
2.8 + RelativePath="..\..\src\audio\winmm\SDL_winmm.c"
2.9 >
2.10 </File>
2.11 <File
2.12 - RelativePath="..\..\src\audio\windib\SDL_dibaudio.h"
2.13 + RelativePath="..\..\src\audio\winmm\SDL_winmm.h"
2.14 >
2.15 </File>
2.16 <File
3.1 --- a/VisualC/SDL/SDL_VS2010.vcxproj Thu Aug 04 01:26:12 2011 -0400
3.2 +++ b/VisualC/SDL/SDL_VS2010.vcxproj Thu Aug 04 01:24:22 2011 -0400
3.3 @@ -276,7 +276,7 @@
3.4 <ClInclude Include="..\..\src\video\SDL_blit_copy.h" />
3.5 <ClInclude Include="..\..\src\video\SDL_blit_slow.h" />
3.6 <ClInclude Include="..\..\src\video\SDL_shape_internals.h" />
3.7 - <ClInclude Include="..\..\src\audio\windib\SDL_dibaudio.h" />
3.8 + <ClInclude Include="..\..\src\audio\winmm\SDL_winmm.h" />
3.9 <ClInclude Include="..\..\src\audio\disk\SDL_diskaudio.h" />
3.10 <ClInclude Include="..\..\src\audio\dummy\SDL_dummyaudio.h" />
3.11 <ClInclude Include="..\..\src\audio\directsound\SDL_directsound.h" />
3.12 @@ -377,7 +377,7 @@
3.13 <ClCompile Include="..\..\src\cpuinfo\SDL_cpuinfo.c" />
3.14 <ClCompile Include="..\..\src\video\SDL_clipboard.c" />
3.15 <ClCompile Include="..\..\src\video\SDL_shape.c" />
3.16 - <ClCompile Include="..\..\src\audio\windib\SDL_dibaudio.c" />
3.17 + <ClCompile Include="..\..\src\audio\winmm\SDL_winmm.c" />
3.18 <ClCompile Include="..\..\src\audio\disk\SDL_diskaudio.c" />
3.19 <ClCompile Include="..\..\src\audio\dummy\SDL_dummyaudio.c" />
3.20 <ClCompile Include="..\..\src\audio\directsound\SDL_directsound.c" />
4.1 --- a/configure.in Thu Aug 04 01:26:12 2011 -0400
4.2 +++ b/configure.in Thu Aug 04 01:24:22 2011 -0400
4.3 @@ -2057,8 +2057,8 @@
4.4 fi
4.5 # Set up files for the audio library
4.6 if test x$enable_audio = xyes; then
4.7 - AC_DEFINE(SDL_AUDIO_DRIVER_WINWAVEOUT, 1, [ ])
4.8 - SOURCES="$SOURCES $srcdir/src/audio/windib/*.c"
4.9 + AC_DEFINE(SDL_AUDIO_DRIVER_WINMM, 1, [ ])
4.10 + SOURCES="$SOURCES $srcdir/src/audio/winmm/*.c"
4.11 if test x$have_dsound = xyes; then
4.12 AC_DEFINE(SDL_AUDIO_DRIVER_DSOUND, 1, [ ])
4.13 SOURCES="$SOURCES $srcdir/src/audio/directsound/*.c"
4.14 @@ -2144,8 +2144,8 @@
4.15 fi
4.16 # Set up files for the audio library
4.17 if test x$enable_audio = xyes; then
4.18 - AC_DEFINE(SDL_AUDIO_DRIVER_WINWAVEOUT, 1, [ ])
4.19 - SOURCES="$SOURCES $srcdir/src/audio/windib/*.c"
4.20 + AC_DEFINE(SDL_AUDIO_DRIVER_WINMM, 1, [ ])
4.21 + SOURCES="$SOURCES $srcdir/src/audio/winmm/*.c"
4.22 if test x$have_dsound = xyes; then
4.23 AC_DEFINE(SDL_AUDIO_DRIVER_DSOUND, 1, [ ])
4.24 SOURCES="$SOURCES $srcdir/src/audio/directsound/*.c"
5.1 --- a/include/SDL_config.h.in Thu Aug 04 01:26:12 2011 -0400
5.2 +++ b/include/SDL_config.h.in Thu Aug 04 01:24:22 2011 -0400
5.3 @@ -195,7 +195,7 @@
5.4 #undef SDL_AUDIO_DRIVER_PAUDIO
5.5 #undef SDL_AUDIO_DRIVER_QSA
5.6 #undef SDL_AUDIO_DRIVER_SUNAUDIO
5.7 -#undef SDL_AUDIO_DRIVER_WINWAVEOUT
5.8 +#undef SDL_AUDIO_DRIVER_WINMM
5.9 #undef SDL_AUDIO_DRIVER_FUSIONSOUND
5.10 #undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
5.11
6.1 --- a/include/SDL_config_windows.h Thu Aug 04 01:26:12 2011 -0400
6.2 +++ b/include/SDL_config_windows.h Thu Aug 04 01:24:22 2011 -0400
6.3 @@ -146,7 +146,7 @@
6.4 #ifndef _WIN32_WCE
6.5 #define SDL_AUDIO_DRIVER_DSOUND 1
6.6 #endif
6.7 -#define SDL_AUDIO_DRIVER_WINWAVEOUT 1
6.8 +#define SDL_AUDIO_DRIVER_WINMM 1
6.9 #define SDL_AUDIO_DRIVER_DISK 1
6.10 #define SDL_AUDIO_DRIVER_DUMMY 1
6.11
7.1 --- a/src/audio/SDL_audio.c Thu Aug 04 01:26:12 2011 -0400
7.2 +++ b/src/audio/SDL_audio.c Thu Aug 04 01:24:22 2011 -0400
7.3 @@ -53,7 +53,7 @@
7.4 extern AudioBootStrap ESD_bootstrap;
7.5 extern AudioBootStrap NAS_bootstrap;
7.6 extern AudioBootStrap DSOUND_bootstrap;
7.7 -extern AudioBootStrap WINWAVEOUT_bootstrap;
7.8 +extern AudioBootStrap WINMM_bootstrap;
7.9 extern AudioBootStrap PAUDIO_bootstrap;
7.10 extern AudioBootStrap BEOSAUDIO_bootstrap;
7.11 extern AudioBootStrap COREAUDIO_bootstrap;
7.12 @@ -100,8 +100,8 @@
7.13 #if SDL_AUDIO_DRIVER_DSOUND
7.14 &DSOUND_bootstrap,
7.15 #endif
7.16 -#if SDL_AUDIO_DRIVER_WINWAVEOUT
7.17 - &WINWAVEOUT_bootstrap,
7.18 +#if SDL_AUDIO_DRIVER_WINMM
7.19 + &WINMM_bootstrap,
7.20 #endif
7.21 #if SDL_AUDIO_DRIVER_PAUDIO
7.22 &PAUDIO_bootstrap,
8.1 --- a/src/audio/windib/SDL_dibaudio.c Thu Aug 04 01:26:12 2011 -0400
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,328 +0,0 @@
8.4 -/*
8.5 - Simple DirectMedia Layer
8.6 - Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
8.7 -
8.8 - This software is provided 'as-is', without any express or implied
8.9 - warranty. In no event will the authors be held liable for any damages
8.10 - arising from the use of this software.
8.11 -
8.12 - Permission is granted to anyone to use this software for any purpose,
8.13 - including commercial applications, and to alter it and redistribute it
8.14 - freely, subject to the following restrictions:
8.15 -
8.16 - 1. The origin of this software must not be misrepresented; you must not
8.17 - claim that you wrote the original software. If you use this software
8.18 - in a product, an acknowledgment in the product documentation would be
8.19 - appreciated but is not required.
8.20 - 2. Altered source versions must be plainly marked as such, and must not be
8.21 - misrepresented as being the original software.
8.22 - 3. This notice may not be removed or altered from any source distribution.
8.23 -*/
8.24 -#include "SDL_config.h"
8.25 -
8.26 -/* Allow access to a raw mixing buffer */
8.27 -
8.28 -#include "../../core/windows/SDL_windows.h"
8.29 -#include <mmsystem.h>
8.30 -
8.31 -#include "SDL_timer.h"
8.32 -#include "SDL_audio.h"
8.33 -#include "../SDL_audio_c.h"
8.34 -#include "SDL_dibaudio.h"
8.35 -#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
8.36 -#include "win_ce_semaphore.h"
8.37 -#endif
8.38 -
8.39 -#if defined(_WIN32_WCE)
8.40 -#define WINDOWS_OS_NAME "Windows CE/PocketPC"
8.41 -#elif defined(WIN64)
8.42 -#define WINDOWS_OS_NAME "Win64"
8.43 -#else
8.44 -#define WINDOWS_OS_NAME "Win32"
8.45 -#endif
8.46 -
8.47 -/* The Win32 callback for filling the WAVE device */
8.48 -static void CALLBACK
8.49 -FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
8.50 - DWORD dwParam1, DWORD dwParam2)
8.51 -{
8.52 - SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
8.53 -
8.54 - /* Only service "buffer done playing" messages */
8.55 - if (uMsg != WOM_DONE)
8.56 - return;
8.57 -
8.58 - /* Signal that we are done playing a buffer */
8.59 -#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
8.60 - ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
8.61 -#else
8.62 - ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
8.63 -#endif
8.64 -}
8.65 -
8.66 -static void
8.67 -SetMMerror(char *function, MMRESULT code)
8.68 -{
8.69 - size_t len;
8.70 - char errbuf[MAXERRORLENGTH];
8.71 - wchar_t werrbuf[MAXERRORLENGTH];
8.72 -
8.73 - SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
8.74 - len = SDL_strlen(errbuf);
8.75 -
8.76 - waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
8.77 - WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
8.78 - MAXERRORLENGTH - len, NULL, NULL);
8.79 -
8.80 - SDL_SetError("%s", errbuf);
8.81 -}
8.82 -
8.83 -/* Set high priority for the audio thread */
8.84 -static void
8.85 -WINWAVEOUT_ThreadInit(_THIS)
8.86 -{
8.87 - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
8.88 -}
8.89 -
8.90 -void
8.91 -WINWAVEOUT_WaitDevice(_THIS)
8.92 -{
8.93 - /* Wait for an audio chunk to finish */
8.94 -#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
8.95 - WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
8.96 -#else
8.97 - WaitForSingleObject(this->hidden->audio_sem, INFINITE);
8.98 -#endif
8.99 -}
8.100 -
8.101 -Uint8 *
8.102 -WINWAVEOUT_GetDeviceBuf(_THIS)
8.103 -{
8.104 - return (Uint8 *) (this->hidden->
8.105 - wavebuf[this->hidden->next_buffer].lpData);
8.106 -}
8.107 -
8.108 -void
8.109 -WINWAVEOUT_PlayDevice(_THIS)
8.110 -{
8.111 - /* Queue it up */
8.112 - waveOutWrite(this->hidden->sound,
8.113 - &this->hidden->wavebuf[this->hidden->next_buffer],
8.114 - sizeof(this->hidden->wavebuf[0]));
8.115 - this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
8.116 -}
8.117 -
8.118 -void
8.119 -WINWAVEOUT_WaitDone(_THIS)
8.120 -{
8.121 - int i, left;
8.122 -
8.123 - do {
8.124 - left = NUM_BUFFERS;
8.125 - for (i = 0; i < NUM_BUFFERS; ++i) {
8.126 - if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
8.127 - --left;
8.128 - }
8.129 - }
8.130 - if (left > 0) {
8.131 - SDL_Delay(100);
8.132 - }
8.133 - } while (left > 0);
8.134 -}
8.135 -
8.136 -void
8.137 -WINWAVEOUT_CloseDevice(_THIS)
8.138 -{
8.139 - /* Close up audio */
8.140 - if (this->hidden != NULL) {
8.141 - int i;
8.142 -
8.143 - if (this->hidden->audio_sem) {
8.144 -#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
8.145 - CloseSynchHandle(this->hidden->audio_sem);
8.146 -#else
8.147 - CloseHandle(this->hidden->audio_sem);
8.148 -#endif
8.149 - this->hidden->audio_sem = 0;
8.150 - }
8.151 -
8.152 - if (this->hidden->sound) {
8.153 - waveOutClose(this->hidden->sound);
8.154 - this->hidden->sound = 0;
8.155 - }
8.156 -
8.157 - /* Clean up mixing buffers */
8.158 - for (i = 0; i < NUM_BUFFERS; ++i) {
8.159 - if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
8.160 - waveOutUnprepareHeader(this->hidden->sound,
8.161 - &this->hidden->wavebuf[i],
8.162 - sizeof(this->hidden->wavebuf[i]));
8.163 - this->hidden->wavebuf[i].dwUser = 0xFFFF;
8.164 - }
8.165 - }
8.166 -
8.167 - if (this->hidden->mixbuf != NULL) {
8.168 - /* Free raw mixing buffer */
8.169 - SDL_free(this->hidden->mixbuf);
8.170 - this->hidden->mixbuf = NULL;
8.171 - }
8.172 -
8.173 - SDL_free(this->hidden);
8.174 - this->hidden = NULL;
8.175 - }
8.176 -}
8.177 -
8.178 -int
8.179 -WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture)
8.180 -{
8.181 - SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
8.182 - int valid_datatype = 0;
8.183 - MMRESULT result;
8.184 - WAVEFORMATEX waveformat;
8.185 - int i;
8.186 -
8.187 - /* Initialize all variables that we clean on shutdown */
8.188 - this->hidden = (struct SDL_PrivateAudioData *)
8.189 - SDL_malloc((sizeof *this->hidden));
8.190 - if (this->hidden == NULL) {
8.191 - SDL_OutOfMemory();
8.192 - return 0;
8.193 - }
8.194 - SDL_memset(this->hidden, 0, (sizeof *this->hidden));
8.195 -
8.196 - /* Initialize the wavebuf structures for closing */
8.197 - for (i = 0; i < NUM_BUFFERS; ++i)
8.198 - this->hidden->wavebuf[i].dwUser = 0xFFFF;
8.199 -
8.200 - while ((!valid_datatype) && (test_format)) {
8.201 - valid_datatype = 1;
8.202 - this->spec.format = test_format;
8.203 - switch (test_format) {
8.204 - case AUDIO_U8:
8.205 - case AUDIO_S16:
8.206 - case AUDIO_S32:
8.207 - break; /* valid. */
8.208 -
8.209 - default:
8.210 - valid_datatype = 0;
8.211 - test_format = SDL_NextAudioFormat();
8.212 - break;
8.213 - }
8.214 - }
8.215 -
8.216 - if (!valid_datatype) {
8.217 - WINWAVEOUT_CloseDevice(this);
8.218 - SDL_SetError("Unsupported audio format");
8.219 - return 0;
8.220 - }
8.221 -
8.222 - /* Set basic WAVE format parameters */
8.223 - SDL_memset(&waveformat, '\0', sizeof(waveformat));
8.224 - waveformat.wFormatTag = WAVE_FORMAT_PCM;
8.225 - waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
8.226 -
8.227 - if (this->spec.channels > 2)
8.228 - this->spec.channels = 2; /* !!! FIXME: is this right? */
8.229 -
8.230 - waveformat.nChannels = this->spec.channels;
8.231 - waveformat.nSamplesPerSec = this->spec.freq;
8.232 - waveformat.nBlockAlign =
8.233 - waveformat.nChannels * (waveformat.wBitsPerSample / 8);
8.234 - waveformat.nAvgBytesPerSec =
8.235 - waveformat.nSamplesPerSec * waveformat.nBlockAlign;
8.236 -
8.237 - /* Check the buffer size -- minimum of 1/4 second (word aligned) */
8.238 - if (this->spec.samples < (this->spec.freq / 4))
8.239 - this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
8.240 -
8.241 - /* Update the fragment size as size in bytes */
8.242 - SDL_CalculateAudioSpec(&this->spec);
8.243 -
8.244 - /* Open the audio device */
8.245 - result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat,
8.246 - (DWORD_PTR) FillSound, (DWORD_PTR) this,
8.247 - CALLBACK_FUNCTION);
8.248 - if (result != MMSYSERR_NOERROR) {
8.249 - WINWAVEOUT_CloseDevice(this);
8.250 - SetMMerror("waveOutOpen()", result);
8.251 - return 0;
8.252 - }
8.253 -#ifdef SOUND_DEBUG
8.254 - /* Check the sound device we retrieved */
8.255 - {
8.256 - WAVEOUTCAPS caps;
8.257 -
8.258 - result = waveOutGetDevCaps((UINT) this->hidden->sound,
8.259 - &caps, sizeof(caps));
8.260 - if (result != MMSYSERR_NOERROR) {
8.261 - WINWAVEOUT_CloseDevice(this);
8.262 - SetMMerror("waveOutGetDevCaps()", result);
8.263 - return 0;
8.264 - }
8.265 - printf("Audio device: %s\n", caps.szPname);
8.266 - }
8.267 -#endif
8.268 -
8.269 - /* Create the audio buffer semaphore */
8.270 - this->hidden->audio_sem =
8.271 -#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
8.272 - CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
8.273 -#else
8.274 - CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
8.275 -#endif
8.276 - if (this->hidden->audio_sem == NULL) {
8.277 - WINWAVEOUT_CloseDevice(this);
8.278 - SDL_SetError("Couldn't create semaphore");
8.279 - return 0;
8.280 - }
8.281 -
8.282 - /* Create the sound buffers */
8.283 - this->hidden->mixbuf =
8.284 - (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
8.285 - if (this->hidden->mixbuf == NULL) {
8.286 - WINWAVEOUT_CloseDevice(this);
8.287 - SDL_OutOfMemory();
8.288 - return 0;
8.289 - }
8.290 - for (i = 0; i < NUM_BUFFERS; ++i) {
8.291 - SDL_memset(&this->hidden->wavebuf[i], '\0',
8.292 - sizeof(this->hidden->wavebuf[i]));
8.293 - this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
8.294 - this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
8.295 - this->hidden->wavebuf[i].lpData =
8.296 - (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
8.297 - result = waveOutPrepareHeader(this->hidden->sound,
8.298 - &this->hidden->wavebuf[i],
8.299 - sizeof(this->hidden->wavebuf[i]));
8.300 - if (result != MMSYSERR_NOERROR) {
8.301 - WINWAVEOUT_CloseDevice(this);
8.302 - SetMMerror("waveOutPrepareHeader()", result);
8.303 - return 0;
8.304 - }
8.305 - }
8.306 -
8.307 - return 1; /* Ready to go! */
8.308 -}
8.309 -
8.310 -
8.311 -static int
8.312 -WINWAVEOUT_Init(SDL_AudioDriverImpl * impl)
8.313 -{
8.314 - /* Set the function pointers */
8.315 - impl->OpenDevice = WINWAVEOUT_OpenDevice;
8.316 - impl->ThreadInit = WINWAVEOUT_ThreadInit;
8.317 - impl->PlayDevice = WINWAVEOUT_PlayDevice;
8.318 - impl->WaitDevice = WINWAVEOUT_WaitDevice;
8.319 - impl->WaitDone = WINWAVEOUT_WaitDone;
8.320 - impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf;
8.321 - impl->CloseDevice = WINWAVEOUT_CloseDevice;
8.322 - impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Is this true? */
8.323 -
8.324 - return 1; /* this audio target is available. */
8.325 -}
8.326 -
8.327 -AudioBootStrap WINWAVEOUT_bootstrap = {
8.328 - "waveout", WINDOWS_OS_NAME " WaveOut", WINWAVEOUT_Init, 0
8.329 -};
8.330 -
8.331 -/* vi: set ts=4 sw=4 expandtab: */
9.1 --- a/src/audio/windib/SDL_dibaudio.h Thu Aug 04 01:26:12 2011 -0400
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,44 +0,0 @@
9.4 -/*
9.5 - Simple DirectMedia Layer
9.6 - Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
9.7 -
9.8 - This software is provided 'as-is', without any express or implied
9.9 - warranty. In no event will the authors be held liable for any damages
9.10 - arising from the use of this software.
9.11 -
9.12 - Permission is granted to anyone to use this software for any purpose,
9.13 - including commercial applications, and to alter it and redistribute it
9.14 - freely, subject to the following restrictions:
9.15 -
9.16 - 1. The origin of this software must not be misrepresented; you must not
9.17 - claim that you wrote the original software. If you use this software
9.18 - in a product, an acknowledgment in the product documentation would be
9.19 - appreciated but is not required.
9.20 - 2. Altered source versions must be plainly marked as such, and must not be
9.21 - misrepresented as being the original software.
9.22 - 3. This notice may not be removed or altered from any source distribution.
9.23 -*/
9.24 -#include "SDL_config.h"
9.25 -
9.26 -#ifndef _SDL_dibaudio_h
9.27 -#define _SDL_dibaudio_h
9.28 -
9.29 -#include "../SDL_sysaudio.h"
9.30 -
9.31 -/* Hidden "this" pointer for the audio functions */
9.32 -#define _THIS SDL_AudioDevice *this
9.33 -
9.34 -#define NUM_BUFFERS 2 /* -- Don't lower this! */
9.35 -
9.36 -struct SDL_PrivateAudioData
9.37 -{
9.38 - HWAVEOUT sound;
9.39 - HANDLE audio_sem;
9.40 - Uint8 *mixbuf; /* The raw allocated mixing buffer */
9.41 - WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */
9.42 - int next_buffer;
9.43 -};
9.44 -
9.45 -#endif /* _SDL_dibaudio_h */
9.46 -
9.47 -/* vi: set ts=4 sw=4 expandtab: */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/src/audio/winmm/SDL_winmm.c Thu Aug 04 01:24:22 2011 -0400
10.3 @@ -0,0 +1,466 @@
10.4 +/*
10.5 + Simple DirectMedia Layer
10.6 + Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
10.7 +
10.8 + This software is provided 'as-is', without any express or implied
10.9 + warranty. In no event will the authors be held liable for any damages
10.10 + arising from the use of this software.
10.11 +
10.12 + Permission is granted to anyone to use this software for any purpose,
10.13 + including commercial applications, and to alter it and redistribute it
10.14 + freely, subject to the following restrictions:
10.15 +
10.16 + 1. The origin of this software must not be misrepresented; you must not
10.17 + claim that you wrote the original software. If you use this software
10.18 + in a product, an acknowledgment in the product documentation would be
10.19 + appreciated but is not required.
10.20 + 2. Altered source versions must be plainly marked as such, and must not be
10.21 + misrepresented as being the original software.
10.22 + 3. This notice may not be removed or altered from any source distribution.
10.23 +*/
10.24 +#include "SDL_config.h"
10.25 +
10.26 +/* Allow access to a raw mixing buffer */
10.27 +
10.28 +#include "../../core/windows/SDL_windows.h"
10.29 +#include <mmsystem.h>
10.30 +
10.31 +#include "SDL_timer.h"
10.32 +#include "SDL_audio.h"
10.33 +#include "../SDL_audio_c.h"
10.34 +#include "SDL_winmm.h"
10.35 +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
10.36 +#include "win_ce_semaphore.h"
10.37 +#endif
10.38 +
10.39 +
10.40 +/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(),
10.41 + * !!! FIXME: which is more proof this needs to be managed in SDL_audio.c
10.42 + * !!! FIXME: and not in drivers.
10.43 + */
10.44 +static void
10.45 +FreeWaveOutAudioDevices(char ***devices, int *devCount)
10.46 +{
10.47 + int i = *devCount;
10.48 + if ((i > 0) && (*devices != NULL)) {
10.49 + while (i--) {
10.50 + SDL_free((*devices)[i]);
10.51 + }
10.52 + }
10.53 +
10.54 + if (*devices != NULL) {
10.55 + SDL_free(*devices);
10.56 + }
10.57 +
10.58 + *devices = NULL;
10.59 + *devCount = 0;
10.60 +}
10.61 +
10.62 +static char **outputDevices = NULL;
10.63 +static int outputDeviceCount = 0;
10.64 +static char **inputDevices = NULL;
10.65 +static int inputDeviceCount = 0;
10.66 +
10.67 +static int
10.68 +DetectWaveOutDevices(void)
10.69 +{
10.70 + UINT i;
10.71 + const UINT devcount = waveOutGetNumDevs();
10.72 + WAVEOUTCAPS caps;
10.73 + FreeWaveOutAudioDevices(&outputDevices, &outputDeviceCount);
10.74 + outputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount);
10.75 + for (i = 0; i < devcount; i++) {
10.76 + if (waveOutGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) {
10.77 + outputDevices[outputDeviceCount] = WIN_StringToUTF8(caps.szPname);
10.78 + if (outputDevices[outputDeviceCount] != NULL) {
10.79 + outputDeviceCount++;
10.80 + }
10.81 + }
10.82 + }
10.83 + return outputDeviceCount;
10.84 +}
10.85 +
10.86 +static int
10.87 +DetectWaveInDevices(void)
10.88 +{
10.89 + UINT i;
10.90 + const UINT devcount = waveInGetNumDevs();
10.91 + WAVEINCAPS caps;
10.92 + FreeWaveInAudioDevices(&inputDevices, &inputDeviceCount);
10.93 + inputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount);
10.94 + for (i = 0; i < devcount; i++) {
10.95 + if (waveInGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) {
10.96 + inputDevices[inputDeviceCount] = WIN_StringToUTF8(caps.szPname);
10.97 + if (inputDevices[inputDeviceCount] != NULL) {
10.98 + inputDeviceCount++;
10.99 + }
10.100 + }
10.101 + }
10.102 + return inputDeviceCount;
10.103 +}
10.104 +
10.105 +static int
10.106 +WINMM_DetectDevices(int iscapture)
10.107 +{
10.108 + return (iscapture) ? DetectWaveInDevices() : DetectWaveOutDevices();
10.109 +}
10.110 +
10.111 +static const char *
10.112 +WINMM_GetDeviceName(int index, int iscapture)
10.113 +{
10.114 + if ((iscapture) && (index < inputDeviceCount)) {
10.115 + return inputDevices[index];
10.116 + } else if ((!iscapture) && (index < outputDeviceCount)) {
10.117 + return outputDevices[index];
10.118 + }
10.119 +
10.120 + SDL_SetError("No such device");
10.121 + return NULL;
10.122 +}
10.123 +
10.124 +static void CALLBACK
10.125 +CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
10.126 + DWORD_PTR dwParam1, DWORD_PTR dwParam2)
10.127 +{
10.128 + SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
10.129 +
10.130 + /* Only service "buffer is filled" messages */
10.131 + if (uMsg != WIM_DATA)
10.132 + return;
10.133 +
10.134 + /* Signal that we have a new buffer of data */
10.135 +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
10.136 + ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
10.137 +#else
10.138 + ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
10.139 +#endif
10.140 +}
10.141 +
10.142 +
10.143 +/* The Win32 callback for filling the WAVE device */
10.144 +static void CALLBACK
10.145 +FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
10.146 + DWORD_PTR dwParam1, DWORD_PTR dwParam2)
10.147 +{
10.148 + SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
10.149 +
10.150 + /* Only service "buffer done playing" messages */
10.151 + if (uMsg != WOM_DONE)
10.152 + return;
10.153 +
10.154 + /* Signal that we are done playing a buffer */
10.155 +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
10.156 + ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
10.157 +#else
10.158 + ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
10.159 +#endif
10.160 +}
10.161 +
10.162 +static void
10.163 +SetMMerror(char *function, MMRESULT code)
10.164 +{
10.165 + size_t len;
10.166 + char errbuf[MAXERRORLENGTH];
10.167 + wchar_t werrbuf[MAXERRORLENGTH];
10.168 +
10.169 + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
10.170 + len = SDL_strlen(errbuf);
10.171 +
10.172 + waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
10.173 + WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
10.174 + MAXERRORLENGTH - len, NULL, NULL);
10.175 +
10.176 + SDL_SetError("%s", errbuf);
10.177 +}
10.178 +
10.179 +static void
10.180 +WINMM_WaitDevice(_THIS)
10.181 +{
10.182 + /* Wait for an audio chunk to finish */
10.183 +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
10.184 + WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
10.185 +#else
10.186 + WaitForSingleObject(this->hidden->audio_sem, INFINITE);
10.187 +#endif
10.188 +}
10.189 +
10.190 +static Uint8 *
10.191 +WINMM_GetDeviceBuf(_THIS)
10.192 +{
10.193 + return (Uint8 *) (this->hidden->
10.194 + wavebuf[this->hidden->next_buffer].lpData);
10.195 +}
10.196 +
10.197 +static void
10.198 +WINMM_PlayDevice(_THIS)
10.199 +{
10.200 + /* Queue it up */
10.201 + waveOutWrite(this->hidden->hout,
10.202 + &this->hidden->wavebuf[this->hidden->next_buffer],
10.203 + sizeof(this->hidden->wavebuf[0]));
10.204 + this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
10.205 +}
10.206 +
10.207 +static void
10.208 +WINMM_WaitDone(_THIS)
10.209 +{
10.210 + int i, left;
10.211 +
10.212 + do {
10.213 + left = NUM_BUFFERS;
10.214 + for (i = 0; i < NUM_BUFFERS; ++i) {
10.215 + if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
10.216 + --left;
10.217 + }
10.218 + }
10.219 + if (left > 0) {
10.220 + SDL_Delay(100);
10.221 + }
10.222 + } while (left > 0);
10.223 +}
10.224 +
10.225 +static void
10.226 +WINMM_CloseDevice(_THIS)
10.227 +{
10.228 + /* Close up audio */
10.229 + if (this->hidden != NULL) {
10.230 + int i;
10.231 +
10.232 + if (this->hidden->audio_sem) {
10.233 +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
10.234 + CloseSynchHandle(this->hidden->audio_sem);
10.235 +#else
10.236 + CloseHandle(this->hidden->audio_sem);
10.237 +#endif
10.238 + this->hidden->audio_sem = 0;
10.239 + }
10.240 +
10.241 + if (this->hidden->hin) {
10.242 + waveInClose(this->hidden->hin);
10.243 + this->hidden->hin = 0;
10.244 + }
10.245 +
10.246 + if (this->hidden->hout) {
10.247 + waveOutClose(this->hidden->hout);
10.248 + this->hidden->hout = 0;
10.249 + }
10.250 +
10.251 + /* Clean up mixing buffers */
10.252 + for (i = 0; i < NUM_BUFFERS; ++i) {
10.253 + if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
10.254 + waveOutUnprepareHeader(this->hidden->hout,
10.255 + &this->hidden->wavebuf[i],
10.256 + sizeof(this->hidden->wavebuf[i]));
10.257 + this->hidden->wavebuf[i].dwUser = 0xFFFF;
10.258 + }
10.259 + }
10.260 +
10.261 + if (this->hidden->mixbuf != NULL) {
10.262 + /* Free raw mixing buffer */
10.263 + SDL_free(this->hidden->mixbuf);
10.264 + this->hidden->mixbuf = NULL;
10.265 + }
10.266 +
10.267 + SDL_free(this->hidden);
10.268 + this->hidden = NULL;
10.269 + }
10.270 +}
10.271 +
10.272 +static int
10.273 +WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
10.274 +{
10.275 + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
10.276 + int valid_datatype = 0;
10.277 + MMRESULT result;
10.278 + WAVEFORMATEX waveformat;
10.279 + UINT_PTR devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
10.280 + char *utf8 = NULL;
10.281 + int i;
10.282 +
10.283 + if (devname != NULL) { /* specific device requested? */
10.284 + if (iscapture) {
10.285 + const int devcount = (int) waveInGetNumDevs();
10.286 + WAVEINCAPS caps;
10.287 + for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
10.288 + result = waveInGetDevCaps(i, &caps, sizeof (caps));
10.289 + if (result != MMSYSERR_NOERROR)
10.290 + continue;
10.291 + else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
10.292 + continue;
10.293 + else if (SDL_strcmp(devname, utf8) == 0)
10.294 + devId = (UINT_PTR) i;
10.295 + SDL_free(utf8);
10.296 + }
10.297 + } else {
10.298 + const int devcount = (int) waveOutGetNumDevs();
10.299 + WAVEOUTCAPS caps;
10.300 + for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
10.301 + result = waveOutGetDevCaps(i, &caps, sizeof (caps));
10.302 + if (result != MMSYSERR_NOERROR)
10.303 + continue;
10.304 + else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
10.305 + continue;
10.306 + else if (SDL_strcmp(devname, utf8) == 0)
10.307 + devId = (UINT_PTR) i;
10.308 + SDL_free(utf8);
10.309 + }
10.310 + }
10.311 +
10.312 + if (devId == WAVE_MAPPER) {
10.313 + SDL_SetError("Requested device not found");
10.314 + return 0;
10.315 + }
10.316 + }
10.317 +
10.318 + /* Initialize all variables that we clean on shutdown */
10.319 + this->hidden = (struct SDL_PrivateAudioData *)
10.320 + SDL_malloc((sizeof *this->hidden));
10.321 + if (this->hidden == NULL) {
10.322 + SDL_OutOfMemory();
10.323 + return 0;
10.324 + }
10.325 + SDL_memset(this->hidden, 0, (sizeof *this->hidden));
10.326 +
10.327 + /* Initialize the wavebuf structures for closing */
10.328 + for (i = 0; i < NUM_BUFFERS; ++i)
10.329 + this->hidden->wavebuf[i].dwUser = 0xFFFF;
10.330 +
10.331 + while ((!valid_datatype) && (test_format)) {
10.332 + valid_datatype = 1;
10.333 + this->spec.format = test_format;
10.334 + switch (test_format) {
10.335 + case AUDIO_U8:
10.336 + case AUDIO_S16:
10.337 + case AUDIO_S32:
10.338 + break; /* valid. */
10.339 +
10.340 + default:
10.341 + valid_datatype = 0;
10.342 + test_format = SDL_NextAudioFormat();
10.343 + break;
10.344 + }
10.345 + }
10.346 +
10.347 + if (!valid_datatype) {
10.348 + WINMM_CloseDevice(this);
10.349 + SDL_SetError("Unsupported audio format");
10.350 + return 0;
10.351 + }
10.352 +
10.353 + /* Set basic WAVE format parameters */
10.354 + SDL_memset(&waveformat, '\0', sizeof(waveformat));
10.355 + waveformat.wFormatTag = WAVE_FORMAT_PCM;
10.356 + waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
10.357 +
10.358 + if (this->spec.channels > 2)
10.359 + this->spec.channels = 2; /* !!! FIXME: is this right? */
10.360 +
10.361 + waveformat.nChannels = this->spec.channels;
10.362 + waveformat.nSamplesPerSec = this->spec.freq;
10.363 + waveformat.nBlockAlign =
10.364 + waveformat.nChannels * (waveformat.wBitsPerSample / 8);
10.365 + waveformat.nAvgBytesPerSec =
10.366 + waveformat.nSamplesPerSec * waveformat.nBlockAlign;
10.367 +
10.368 + /* Check the buffer size -- minimum of 1/4 second (word aligned) */
10.369 + if (this->spec.samples < (this->spec.freq / 4))
10.370 + this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
10.371 +
10.372 + /* Update the fragment size as size in bytes */
10.373 + SDL_CalculateAudioSpec(&this->spec);
10.374 +
10.375 + /* Open the audio device */
10.376 + if (iscapture) {
10.377 + result = waveInOpen(&this->hidden->hin, devId, &waveformat,
10.378 + (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
10.379 + CALLBACK_FUNCTION);
10.380 + } else {
10.381 + result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
10.382 + (DWORD_PTR) FillSound, (DWORD_PTR) this,
10.383 + CALLBACK_FUNCTION);
10.384 + }
10.385 +
10.386 + if (result != MMSYSERR_NOERROR) {
10.387 + WINMM_CloseDevice(this);
10.388 + SetMMerror("waveOutOpen()", result);
10.389 + return 0;
10.390 + }
10.391 +#ifdef SOUND_DEBUG
10.392 + /* Check the sound device we retrieved */
10.393 + {
10.394 + WAVEOUTCAPS caps;
10.395 +
10.396 + result = waveOutGetDevCaps((UINT) this->hidden->hout,
10.397 + &caps, sizeof(caps));
10.398 + if (result != MMSYSERR_NOERROR) {
10.399 + WINMM_CloseDevice(this);
10.400 + SetMMerror("waveOutGetDevCaps()", result);
10.401 + return 0;
10.402 + }
10.403 + printf("Audio device: %s\n", caps.szPname);
10.404 + }
10.405 +#endif
10.406 +
10.407 + /* Create the audio buffer semaphore */
10.408 + this->hidden->audio_sem =
10.409 +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
10.410 + CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
10.411 +#else
10.412 + CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
10.413 +#endif
10.414 + if (this->hidden->audio_sem == NULL) {
10.415 + WINMM_CloseDevice(this);
10.416 + SDL_SetError("Couldn't create semaphore");
10.417 + return 0;
10.418 + }
10.419 +
10.420 + /* Create the sound buffers */
10.421 + this->hidden->mixbuf =
10.422 + (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
10.423 + if (this->hidden->mixbuf == NULL) {
10.424 + WINMM_CloseDevice(this);
10.425 + SDL_OutOfMemory();
10.426 + return 0;
10.427 + }
10.428 + for (i = 0; i < NUM_BUFFERS; ++i) {
10.429 + SDL_memset(&this->hidden->wavebuf[i], '\0',
10.430 + sizeof(this->hidden->wavebuf[i]));
10.431 + this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
10.432 + this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
10.433 + this->hidden->wavebuf[i].lpData =
10.434 + (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
10.435 + result = waveOutPrepareHeader(this->hidden->hout,
10.436 + &this->hidden->wavebuf[i],
10.437 + sizeof(this->hidden->wavebuf[i]));
10.438 + if (result != MMSYSERR_NOERROR) {
10.439 + WINMM_CloseDevice(this);
10.440 + SetMMerror("waveOutPrepareHeader()", result);
10.441 + return 0;
10.442 + }
10.443 + }
10.444 +
10.445 + return 1; /* Ready to go! */
10.446 +}
10.447 +
10.448 +
10.449 +static int
10.450 +WINMM_Init(SDL_AudioDriverImpl * impl)
10.451 +{
10.452 + /* Set the function pointers */
10.453 + impl->DetectDevices = WINMM_DetectDevices;
10.454 + impl->GetDeviceName = WINMM_GetDeviceName;
10.455 + impl->OpenDevice = WINMM_OpenDevice;
10.456 + impl->PlayDevice = WINMM_PlayDevice;
10.457 + impl->WaitDevice = WINMM_WaitDevice;
10.458 + impl->WaitDone = WINMM_WaitDone;
10.459 + impl->GetDeviceBuf = WINMM_GetDeviceBuf;
10.460 + impl->CloseDevice = WINMM_CloseDevice;
10.461 +
10.462 + return 1; /* this audio target is available. */
10.463 +}
10.464 +
10.465 +AudioBootStrap WINMM_bootstrap = {
10.466 + "winmm", "Windows Waveform Audio", WINMM_Init, 0
10.467 +};
10.468 +
10.469 +/* vi: set ts=4 sw=4 expandtab: */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/src/audio/winmm/SDL_winmm.h Thu Aug 04 01:24:22 2011 -0400
11.3 @@ -0,0 +1,45 @@
11.4 +/*
11.5 + Simple DirectMedia Layer
11.6 + Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
11.7 +
11.8 + This software is provided 'as-is', without any express or implied
11.9 + warranty. In no event will the authors be held liable for any damages
11.10 + arising from the use of this software.
11.11 +
11.12 + Permission is granted to anyone to use this software for any purpose,
11.13 + including commercial applications, and to alter it and redistribute it
11.14 + freely, subject to the following restrictions:
11.15 +
11.16 + 1. The origin of this software must not be misrepresented; you must not
11.17 + claim that you wrote the original software. If you use this software
11.18 + in a product, an acknowledgment in the product documentation would be
11.19 + appreciated but is not required.
11.20 + 2. Altered source versions must be plainly marked as such, and must not be
11.21 + misrepresented as being the original software.
11.22 + 3. This notice may not be removed or altered from any source distribution.
11.23 +*/
11.24 +#include "SDL_config.h"
11.25 +
11.26 +#ifndef _SDL_winmm_h
11.27 +#define _SDL_winmm_h
11.28 +
11.29 +#include "../SDL_sysaudio.h"
11.30 +
11.31 +/* Hidden "this" pointer for the audio functions */
11.32 +#define _THIS SDL_AudioDevice *this
11.33 +
11.34 +#define NUM_BUFFERS 2 /* -- Don't lower this! */
11.35 +
11.36 +struct SDL_PrivateAudioData
11.37 +{
11.38 + HWAVEOUT hout;
11.39 + HWAVEIN hin;
11.40 + HANDLE audio_sem;
11.41 + Uint8 *mixbuf; /* The raw allocated mixing buffer */
11.42 + WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */
11.43 + int next_buffer;
11.44 +};
11.45 +
11.46 +#endif /* _SDL_winmm_h */
11.47 +
11.48 +/* vi: set ts=4 sw=4 expandtab: */