Commit ac93bd6e authored by Ryan C. Gordon's avatar Ryan C. Gordon

Reworked Windows DirectSound code.

Now supports multiple devices, and uses DirectSound 8 instead of 5. Changed
name to "directsound" and renamed source directory.

--HG--
rename : src/audio/windx5/SDL_dx5audio.c => src/audio/directsound/SDL_directsound.c
rename : src/audio/windx5/SDL_dx5audio.h => src/audio/directsound/SDL_directsound.h
rename : src/audio/windx5/directx.h => src/audio/directsound/directx.h
parent 55419dbf
......@@ -580,7 +580,7 @@
>
</File>
<File
RelativePath="..\..\src\audio\windx5\directx.h"
RelativePath="..\..\src\audio\directsound\directx.h"
>
</File>
<File
......@@ -840,11 +840,11 @@
>
</File>
<File
RelativePath="..\..\src\audio\windx5\SDL_dx5audio.c"
RelativePath="..\..\src\audio\directsound\SDL_directsound.c"
>
</File>
<File
RelativePath="..\..\src\audio\windx5\SDL_dx5audio.h"
RelativePath="..\..\src\audio\directsound\SDL_directsound.h"
>
</File>
<File
......
......@@ -569,7 +569,7 @@
>
</File>
<File
RelativePath="..\..\src\audio\windx5\directx.h"
RelativePath="..\..\src\audio\directsound\directx.h"
>
</File>
<File
......@@ -829,11 +829,11 @@
>
</File>
<File
RelativePath="..\..\src\audio\windx5\SDL_dx5audio.c"
RelativePath="..\..\src\audio\directsound\SDL_directsound.c"
>
</File>
<File
RelativePath="..\..\src\audio\windx5\SDL_dx5audio.h"
RelativePath="..\..\src\audio\directsound\SDL_directsound.h"
>
</File>
<File
......
......@@ -250,7 +250,7 @@
<ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
<ClInclude Include="..\..\src\events\blank_cursor.h" />
<ClInclude Include="..\..\src\events\default_cursor.h" />
<ClInclude Include="..\..\src\audio\windx5\directx.h" />
<ClInclude Include="..\..\src\audio\directsound\directx.h" />
<ClInclude Include="..\..\src\events\SDL_clipboardevents_c.h" />
<ClInclude Include="..\..\src\events\SDL_gesture_c.h" />
<ClInclude Include="..\..\src\events\SDL_touch_c.h" />
......@@ -279,7 +279,7 @@
<ClInclude Include="..\..\src\audio\windib\SDL_dibaudio.h" />
<ClInclude Include="..\..\src\audio\disk\SDL_diskaudio.h" />
<ClInclude Include="..\..\src\audio\dummy\SDL_dummyaudio.h" />
<ClInclude Include="..\..\src\audio\windx5\SDL_dx5audio.h" />
<ClInclude Include="..\..\src\audio\directsound\SDL_directsound.h" />
<ClInclude Include="..\..\src\SDL_error_c.h" />
<ClInclude Include="..\..\src\SDL_hints_c.h" />
<ClInclude Include="..\..\src\events\SDL_events_c.h" />
......@@ -380,7 +380,7 @@
<ClCompile Include="..\..\src\audio\windib\SDL_dibaudio.c" />
<ClCompile Include="..\..\src\audio\disk\SDL_diskaudio.c" />
<ClCompile Include="..\..\src\audio\dummy\SDL_dummyaudio.c" />
<ClCompile Include="..\..\src\audio\windx5\SDL_dx5audio.c" />
<ClCompile Include="..\..\src\audio\directsound\SDL_directsound.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dxjoystick.c" />
<ClCompile Include="..\..\src\SDL_error.c" />
<ClCompile Include="..\..\src\events\SDL_events.c" />
......
......@@ -2061,7 +2061,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
SOURCES="$SOURCES $srcdir/src/audio/windib/*.c"
if test x$have_dsound = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_DSOUND, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/windx5/*.c"
SOURCES="$SOURCES $srcdir/src/audio/directsound/*.c"
fi
have_audio=yes
fi
......@@ -2148,7 +2148,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
SOURCES="$SOURCES $srcdir/src/audio/windib/*.c"
if test x$have_dsound = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_DSOUND, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/windx5/*.c"
SOURCES="$SOURCES $srcdir/src/audio/directsound/*.c"
fi
have_audio=yes
fi
......
......@@ -26,26 +26,23 @@
#include "SDL_loadso.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_dx5audio.h"
/* !!! FIXME: move this somewhere that other drivers can use it... */
#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
#include "SDL_directsound.h"
/* DirectX function pointers for audio */
static void* DSoundDLL = NULL;
static HRESULT(WINAPI * DSoundCreate) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN) =
NULL;
typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
typedef HRESULT(WINAPI*fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
typedef HRESULT(WINAPI*fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
static void
DSOUND_Unload(void)
{
DSoundCreate = NULL;
pDirectSoundCreate8 = NULL;
pDirectSoundEnumerateW = NULL;
pDirectSoundCaptureEnumerateW = NULL;
if (DSoundDLL != NULL) {
SDL_UnloadObject(DSoundDLL);
......@@ -65,18 +62,19 @@ DSOUND_Load(void)
if (DSoundDLL == NULL) {
SDL_SetError("DirectSound: failed to load DSOUND.DLL");
} else {
/* Now make sure we have DirectX 5 or better... */
/* (DirectSoundCaptureCreate was added in DX5) */
if (!SDL_LoadFunction(DSoundDLL, "DirectSoundCaptureCreate")) {
SDL_SetError("DirectSound: System doesn't appear to have DX5.");
} else {
DSoundCreate = SDL_LoadFunction(DSoundDLL, "DirectSoundCreate");
/* Now make sure we have DirectX 8 or better... */
#define DSOUNDLOAD(f) { \
p##f = (fn##f) SDL_LoadFunction(DSoundDLL, #f); \
if (!p##f) loaded = 0; \
}
loaded = 1; /* will reset if necessary. */
DSOUNDLOAD(DirectSoundCreate8);
DSOUNDLOAD(DirectSoundEnumerateW);
DSOUNDLOAD(DirectSoundCaptureEnumerateW);
#undef DSOUNDLOAD
if (!DSoundCreate) {
SDL_SetError("DirectSound: Failed to find DirectSoundCreate");
} else {
loaded = 1;
if (!loaded) {
SDL_SetError("DirectSound: System doesn't appear to have DX8.");
}
}
......@@ -87,6 +85,13 @@ DSOUND_Load(void)
return loaded;
}
static __inline__ char *
utf16_to_utf8(const WCHAR *S)
{
/* !!! FIXME: this should be UTF-16, not UCS-2! */
return SDL_iconv_string("UTF-8", "UCS-2", (char *)(S),
(SDL_wcslen(S)+1)*sizeof(WCHAR));
}
static void
SetDSerror(const char *function, int code)
......@@ -97,7 +102,7 @@ SetDSerror(const char *function, int code)
errbuf[0] = 0;
switch (code) {
case E_NOINTERFACE:
error = "Unsupported interface -- Is DirectX 5.0 or later installed?";
error = "Unsupported interface -- Is DirectX 8.0 or later installed?";
break;
case DSERR_ALLOCATED:
error = "Audio device in use";
......@@ -142,23 +147,100 @@ SetDSerror(const char *function, int code)
return;
}
/* DirectSound needs to be associated with a window */
static HWND mainwin = NULL;
/* */
void
DSOUND_SoundFocus(HWND hwnd)
/* !!! 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
FreeDSoundAudioDevices(char ***devices, int *devCount)
{
/* !!! FIXME: probably broken with multi-window support in SDL 1.3 ... */
mainwin = hwnd;
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 void
DSOUND_ThreadInit(_THIS)
typedef struct FindAllDevsData
{
const char **devs;
unsigned int devcount;
} FindAllDevsData;
static BOOL CALLBACK
FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
{
FindAllDevsData *data = (FindAllDevsData *) _data;
void *ptr;
char *name;
if (guid == NULL)
return TRUE; /* skip default device, go to the next one. */
ptr = SDL_realloc(data->devs, ((data->devcount) + 1) * sizeof(char *));
if (ptr == NULL)
return TRUE; /* oh well. */
data->devs = (const char **) ptr;
name = utf16_to_utf8(desc);
if (name != NULL)
data->devs[data->devcount++] = name;
return TRUE; /* keep enumerating. */
}
static char **outputDevices = NULL;
static int outputDeviceCount = 0;
static char **inputDevices = NULL;
static int inputDeviceCount = 0;
static int
DSOUND_DetectDevices(int iscapture)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
FindAllDevsData data;
data.devs = NULL;
data.devcount = 0;
if (iscapture) {
FreeDSoundAudioDevices(&inputDevices, &inputDeviceCount);
pDirectSoundCaptureEnumerateW(FindAllDevs, &devs);
inputDevices = data.devs;
inputDeviceCount = data.devcount;
} else {
FreeDSoundAudioDevices(&outputDevices, &outputDeviceCount);
pDirectSoundEnumerateW(FindAllDevs, &devs);
outputDevices = data.devs;
outputDeviceCount = data.devcount;
}
return data.devcount;
}
static const char *
DSOUND_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
DSOUND_WaitDevice(_THIS)
{
......@@ -393,6 +475,30 @@ CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
return (numchunks);
}
typedef struct FindDevGUIDData
{
const char *devname;
GUID guid;
int found;
} FindDevGUIDData;
static BOOL CALLBACK
FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
{
if (guid != NULL) { /* skip the default device. */
FindDevGUIDData *data = (FindDevGUIDData *) _data;
char *str = utf16_to_utf8(desc);
const int match = (SDL_strcmp(str, data->devname) == 0);
SDL_free(str);
if (match) {
data->found = 1;
SDL_memcpy(&data->guid, guid, sizeof (data->guid));
return FALSE; /* found it! stop enumerating. */
}
}
return TRUE; /* keep enumerating. */
}
static int
DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
{
......@@ -400,9 +506,23 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
WAVEFORMATEX waveformat;
int valid_format = 0;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
/* !!! FIXME: handle devname */
/* !!! FIXME: handle iscapture */
FindDevGUIDData devguid;
LPGUID guid = NULL;
if (devname != NULL) {
devguid.found = 0;
devguid.devname = devname;
if (iscapture)
pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
else
pDirectSoundEnumerateW(FindDevGUID, &devguid);
if (!devguid.found) {
SDL_SetError("DirectSound: Requested device not found");
return 0;
}
guid = &devguid.guid;
}
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
......@@ -445,7 +565,7 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
SDL_CalculateAudioSpec(&this->spec);
/* Open the audio device */
result = DSoundCreate(NULL, &this->hidden->sound, NULL);
result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
if (result != DS_OK) {
DSOUND_CloseDevice(this);
SetDSerror("DirectSoundCreate", result);
......@@ -469,6 +589,8 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
static void
DSOUND_Deinitialize(void)
{
FreeDSoundAudioDevices(&inputDevices, &inputDeviceCount);
FreeDSoundAudioDevices(&outputDevices, &outputDeviceCount);
DSOUND_Unload();
}
......@@ -476,42 +598,26 @@ DSOUND_Deinitialize(void)
static int
DSOUND_Init(SDL_AudioDriverImpl * impl)
{
OSVERSIONINFO ver;
/*
* Unfortunately, the sound drivers on NT have higher latencies than the
* audio buffers used by many SDL applications, so there are gaps in the
* audio - it sounds terrible. Punt for now.
*/
SDL_memset(&ver, '\0', sizeof(OSVERSIONINFO));
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&ver);
if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (ver.dwMajorVersion <= 4) {
return 0; /* NT4.0 or earlier. Disable dsound support. */
}
}
if (!DSOUND_Load()) {
return 0;
}
/* Set the function pointers */
impl->DetectDevices = DSOUND_DetectDevices;
impl->GetDeviceName = DSOUND_GetDeviceName;
impl->OpenDevice = DSOUND_OpenDevice;
impl->PlayDevice = DSOUND_PlayDevice;
impl->WaitDevice = DSOUND_WaitDevice;
impl->WaitDone = DSOUND_WaitDone;
impl->ThreadInit = DSOUND_ThreadInit;
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
impl->CloseDevice = DSOUND_CloseDevice;
impl->Deinitialize = DSOUND_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME */
return 1; /* this audio target is available. */
}
AudioBootStrap DSOUND_bootstrap = {
"dsound", WINDOWS_OS_NAME "DirectSound", DSOUND_Init, 0
"directsound", "DirectSound", DSOUND_Init, 0
};
/* vi: set ts=4 sw=4 expandtab: */
......@@ -20,8 +20,8 @@
*/
#include "SDL_config.h"
#ifndef _SDL_dx5audio_h
#define _SDL_dx5audio_h
#ifndef _SDL_directsound_h
#define _SDL_directsound_h
#include "directx.h"
......@@ -41,6 +41,6 @@ struct SDL_PrivateAudioData
Uint8 *locked_buf;
};
#endif /* _SDL_dx5audio_h */
#endif /* _SDL_directsound_h */
/* vi: set ts=4 sw=4 expandtab: */
......@@ -2,7 +2,7 @@
#ifndef _directx_h
#define _directx_h
/* Include all of the DirectX 5.0 headers and adds any necessary tweaks */
/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */
#include "../../core/windows/SDL_windows.h"
#include <mmsystem.h>
......@@ -70,7 +70,7 @@
*/
/* We need these defines to mark what version of DirectX API we use */
#define DIRECTDRAW_VERSION 0x0700
#define DIRECTSOUND_VERSION 0x0500
#define DIRECTSOUND_VERSION 0x0800
#define DIRECTINPUT_VERSION 0x0500
#include <ddraw.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment