Mercurial > audio-send
diff Alc/backends/dsound.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Alc/backends/dsound.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,614 @@ 1.4 +/** 1.5 + * OpenAL cross platform audio library 1.6 + * Copyright (C) 1999-2007 by authors. 1.7 + * This library is free software; you can redistribute it and/or 1.8 + * modify it under the terms of the GNU Library General Public 1.9 + * License as published by the Free Software Foundation; either 1.10 + * version 2 of the License, or (at your option) any later version. 1.11 + * 1.12 + * This library is distributed in the hope that it will be useful, 1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.15 + * Library General Public License for more details. 1.16 + * 1.17 + * You should have received a copy of the GNU Library General Public 1.18 + * License along with this library; if not, write to the 1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1.20 + * Boston, MA 02111-1307, USA. 1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 1.22 + */ 1.23 + 1.24 +#include "config.h" 1.25 + 1.26 +#define _WIN32_WINNT 0x0500 1.27 +#include <stdlib.h> 1.28 +#include <stdio.h> 1.29 +#include <memory.h> 1.30 + 1.31 +#include <dsound.h> 1.32 +#include <cguid.h> 1.33 +#include <mmreg.h> 1.34 +#ifndef _WAVEFORMATEXTENSIBLE_ 1.35 +#include <ks.h> 1.36 +#include <ksmedia.h> 1.37 +#endif 1.38 + 1.39 +#include "alMain.h" 1.40 +#include "AL/al.h" 1.41 +#include "AL/alc.h" 1.42 + 1.43 +#ifndef DSSPEAKER_5POINT1 1.44 +#define DSSPEAKER_5POINT1 6 1.45 +#endif 1.46 +#ifndef DSSPEAKER_7POINT1 1.47 +#define DSSPEAKER_7POINT1 7 1.48 +#endif 1.49 + 1.50 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 1.51 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 1.52 + 1.53 + 1.54 +static HMODULE ds_handle; 1.55 +static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); 1.56 +static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); 1.57 + 1.58 +#define DirectSoundCreate pDirectSoundCreate 1.59 +#define DirectSoundEnumerateA pDirectSoundEnumerateA 1.60 + 1.61 + 1.62 +typedef struct { 1.63 + // DirectSound Playback Device 1.64 + IDirectSound *lpDS; 1.65 + IDirectSoundBuffer *DSpbuffer; 1.66 + IDirectSoundBuffer *DSsbuffer; 1.67 + IDirectSoundNotify *DSnotify; 1.68 + HANDLE hNotifyEvent; 1.69 + 1.70 + volatile int killNow; 1.71 + ALvoid *thread; 1.72 +} DSoundData; 1.73 + 1.74 + 1.75 +typedef struct { 1.76 + ALCchar *name; 1.77 + GUID guid; 1.78 +} DevMap; 1.79 + 1.80 +static const ALCchar dsDevice[] = "DirectSound Default"; 1.81 +static DevMap *DeviceList; 1.82 +static ALuint NumDevices; 1.83 + 1.84 +#define MAX_UPDATES 128 1.85 + 1.86 +static ALCboolean DSoundLoad(void) 1.87 +{ 1.88 + ALCboolean ok = ALC_TRUE; 1.89 + if(!ds_handle) 1.90 + { 1.91 + ds_handle = LoadLibraryA("dsound.dll"); 1.92 + if(ds_handle == NULL) 1.93 + { 1.94 + ERR("Failed to load dsound.dll\n"); 1.95 + return ALC_FALSE; 1.96 + } 1.97 + 1.98 +#define LOAD_FUNC(x) do { \ 1.99 + if((p##x = (void*)GetProcAddress(ds_handle, #x)) == NULL) { \ 1.100 + ERR("Could not load %s from dsound.dll\n", #x); \ 1.101 + ok = ALC_FALSE; \ 1.102 + } \ 1.103 +} while(0) 1.104 + LOAD_FUNC(DirectSoundCreate); 1.105 + LOAD_FUNC(DirectSoundEnumerateA); 1.106 +#undef LOAD_FUNC 1.107 + 1.108 + if(!ok) 1.109 + { 1.110 + FreeLibrary(ds_handle); 1.111 + ds_handle = NULL; 1.112 + } 1.113 + } 1.114 + return ok; 1.115 +} 1.116 + 1.117 + 1.118 +static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data) 1.119 +{ 1.120 + char str[1024]; 1.121 + void *temp; 1.122 + int count; 1.123 + ALuint i; 1.124 + 1.125 + (void)data; 1.126 + (void)drvname; 1.127 + 1.128 + if(!guid) 1.129 + return TRUE; 1.130 + 1.131 + count = 0; 1.132 + do { 1.133 + if(count == 0) 1.134 + snprintf(str, sizeof(str), "%s", desc); 1.135 + else 1.136 + snprintf(str, sizeof(str), "%s #%d", desc, count+1); 1.137 + count++; 1.138 + 1.139 + for(i = 0;i < NumDevices;i++) 1.140 + { 1.141 + if(strcmp(str, DeviceList[i].name) == 0) 1.142 + break; 1.143 + } 1.144 + } while(i != NumDevices); 1.145 + 1.146 + temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1)); 1.147 + if(temp) 1.148 + { 1.149 + DeviceList = temp; 1.150 + DeviceList[NumDevices].name = strdup(str); 1.151 + DeviceList[NumDevices].guid = *guid; 1.152 + NumDevices++; 1.153 + } 1.154 + 1.155 + return TRUE; 1.156 +} 1.157 + 1.158 + 1.159 +static ALuint DSoundProc(ALvoid *ptr) 1.160 +{ 1.161 + ALCdevice *pDevice = (ALCdevice*)ptr; 1.162 + DSoundData *pData = (DSoundData*)pDevice->ExtraData; 1.163 + DSBCAPS DSBCaps; 1.164 + DWORD LastCursor = 0; 1.165 + DWORD PlayCursor; 1.166 + VOID *WritePtr1, *WritePtr2; 1.167 + DWORD WriteCnt1, WriteCnt2; 1.168 + BOOL Playing = FALSE; 1.169 + DWORD FrameSize; 1.170 + DWORD FragSize; 1.171 + DWORD avail; 1.172 + HRESULT err; 1.173 + 1.174 + SetRTPriority(); 1.175 + 1.176 + memset(&DSBCaps, 0, sizeof(DSBCaps)); 1.177 + DSBCaps.dwSize = sizeof(DSBCaps); 1.178 + err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps); 1.179 + if(FAILED(err)) 1.180 + { 1.181 + ERR("Failed to get buffer caps: 0x%lx\n", err); 1.182 + aluHandleDisconnect(pDevice); 1.183 + return 1; 1.184 + } 1.185 + 1.186 + FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 1.187 + FragSize = pDevice->UpdateSize * FrameSize; 1.188 + 1.189 + IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL); 1.190 + while(!pData->killNow) 1.191 + { 1.192 + // Get current play cursor 1.193 + IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL); 1.194 + avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; 1.195 + 1.196 + if(avail < FragSize) 1.197 + { 1.198 + if(!Playing) 1.199 + { 1.200 + err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING); 1.201 + if(FAILED(err)) 1.202 + { 1.203 + ERR("Failed to play buffer: 0x%lx\n", err); 1.204 + aluHandleDisconnect(pDevice); 1.205 + return 1; 1.206 + } 1.207 + Playing = TRUE; 1.208 + } 1.209 + 1.210 + avail = WaitForSingleObjectEx(pData->hNotifyEvent, 2000, FALSE); 1.211 + if(avail != WAIT_OBJECT_0) 1.212 + ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); 1.213 + continue; 1.214 + } 1.215 + avail -= avail%FragSize; 1.216 + 1.217 + // Lock output buffer 1.218 + WriteCnt1 = 0; 1.219 + WriteCnt2 = 0; 1.220 + err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); 1.221 + 1.222 + // If the buffer is lost, restore it and lock 1.223 + if(err == DSERR_BUFFERLOST) 1.224 + { 1.225 + WARN("Buffer lost, restoring...\n"); 1.226 + err = IDirectSoundBuffer_Restore(pData->DSsbuffer); 1.227 + if(SUCCEEDED(err)) 1.228 + { 1.229 + Playing = FALSE; 1.230 + LastCursor = 0; 1.231 + err = IDirectSoundBuffer_Lock(pData->DSsbuffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); 1.232 + } 1.233 + } 1.234 + 1.235 + // Successfully locked the output buffer 1.236 + if(SUCCEEDED(err)) 1.237 + { 1.238 + // If we have an active context, mix data directly into output buffer otherwise fill with silence 1.239 + aluMixData(pDevice, WritePtr1, WriteCnt1/FrameSize); 1.240 + aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize); 1.241 + 1.242 + // Unlock output buffer only when successfully locked 1.243 + IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); 1.244 + } 1.245 + else 1.246 + { 1.247 + ERR("Buffer lock error: %#lx\n", err); 1.248 + aluHandleDisconnect(pDevice); 1.249 + return 1; 1.250 + } 1.251 + 1.252 + // Update old write cursor location 1.253 + LastCursor += WriteCnt1+WriteCnt2; 1.254 + LastCursor %= DSBCaps.dwBufferBytes; 1.255 + } 1.256 + 1.257 + return 0; 1.258 +} 1.259 + 1.260 +static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) 1.261 +{ 1.262 + DSoundData *pData = NULL; 1.263 + LPGUID guid = NULL; 1.264 + HRESULT hr; 1.265 + 1.266 + if(!deviceName) 1.267 + deviceName = dsDevice; 1.268 + else if(strcmp(deviceName, dsDevice) != 0) 1.269 + { 1.270 + ALuint i; 1.271 + 1.272 + if(!DeviceList) 1.273 + { 1.274 + hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL); 1.275 + if(FAILED(hr)) 1.276 + ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); 1.277 + } 1.278 + 1.279 + for(i = 0;i < NumDevices;i++) 1.280 + { 1.281 + if(strcmp(deviceName, DeviceList[i].name) == 0) 1.282 + { 1.283 + guid = &DeviceList[i].guid; 1.284 + break; 1.285 + } 1.286 + } 1.287 + if(i == NumDevices) 1.288 + return ALC_FALSE; 1.289 + } 1.290 + 1.291 + //Initialise requested device 1.292 + pData = calloc(1, sizeof(DSoundData)); 1.293 + if(!pData) 1.294 + { 1.295 + alcSetError(device, ALC_OUT_OF_MEMORY); 1.296 + return ALC_FALSE; 1.297 + } 1.298 + 1.299 + hr = DS_OK; 1.300 + pData->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 1.301 + if(pData->hNotifyEvent == NULL) 1.302 + hr = E_FAIL; 1.303 + 1.304 + //DirectSound Init code 1.305 + if(SUCCEEDED(hr)) 1.306 + hr = DirectSoundCreate(guid, &pData->lpDS, NULL); 1.307 + if(SUCCEEDED(hr)) 1.308 + hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY); 1.309 + if(FAILED(hr)) 1.310 + { 1.311 + if(pData->lpDS) 1.312 + IDirectSound_Release(pData->lpDS); 1.313 + if(pData->hNotifyEvent) 1.314 + CloseHandle(pData->hNotifyEvent); 1.315 + free(pData); 1.316 + ERR("Device init failed: 0x%08lx\n", hr); 1.317 + return ALC_FALSE; 1.318 + } 1.319 + 1.320 + device->szDeviceName = strdup(deviceName); 1.321 + device->ExtraData = pData; 1.322 + return ALC_TRUE; 1.323 +} 1.324 + 1.325 +static void DSoundClosePlayback(ALCdevice *device) 1.326 +{ 1.327 + DSoundData *pData = device->ExtraData; 1.328 + 1.329 + IDirectSound_Release(pData->lpDS); 1.330 + CloseHandle(pData->hNotifyEvent); 1.331 + free(pData); 1.332 + device->ExtraData = NULL; 1.333 +} 1.334 + 1.335 +static ALCboolean DSoundResetPlayback(ALCdevice *device) 1.336 +{ 1.337 + DSoundData *pData = (DSoundData*)device->ExtraData; 1.338 + DSBUFFERDESC DSBDescription; 1.339 + WAVEFORMATEXTENSIBLE OutputType; 1.340 + DWORD speakers; 1.341 + HRESULT hr; 1.342 + 1.343 + memset(&OutputType, 0, sizeof(OutputType)); 1.344 + 1.345 + switch(device->FmtType) 1.346 + { 1.347 + case DevFmtByte: 1.348 + device->FmtType = DevFmtUByte; 1.349 + break; 1.350 + case DevFmtUShort: 1.351 + device->FmtType = DevFmtShort; 1.352 + break; 1.353 + case DevFmtUByte: 1.354 + case DevFmtShort: 1.355 + case DevFmtFloat: 1.356 + break; 1.357 + } 1.358 + 1.359 + hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); 1.360 + if(SUCCEEDED(hr)) 1.361 + { 1.362 + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) 1.363 + { 1.364 + speakers = DSSPEAKER_CONFIG(speakers); 1.365 + if(speakers == DSSPEAKER_MONO) 1.366 + device->FmtChans = DevFmtMono; 1.367 + else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE) 1.368 + device->FmtChans = DevFmtStereo; 1.369 + else if(speakers == DSSPEAKER_QUAD) 1.370 + device->FmtChans = DevFmtQuad; 1.371 + else if(speakers == DSSPEAKER_5POINT1) 1.372 + device->FmtChans = DevFmtX51; 1.373 + else if(speakers == DSSPEAKER_7POINT1) 1.374 + device->FmtChans = DevFmtX71; 1.375 + else 1.376 + ERR("Unknown system speaker config: 0x%lx\n", speakers); 1.377 + } 1.378 + 1.379 + switch(device->FmtChans) 1.380 + { 1.381 + case DevFmtMono: 1.382 + OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; 1.383 + break; 1.384 + case DevFmtStereo: 1.385 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 1.386 + SPEAKER_FRONT_RIGHT; 1.387 + break; 1.388 + case DevFmtQuad: 1.389 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 1.390 + SPEAKER_FRONT_RIGHT | 1.391 + SPEAKER_BACK_LEFT | 1.392 + SPEAKER_BACK_RIGHT; 1.393 + break; 1.394 + case DevFmtX51: 1.395 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 1.396 + SPEAKER_FRONT_RIGHT | 1.397 + SPEAKER_FRONT_CENTER | 1.398 + SPEAKER_LOW_FREQUENCY | 1.399 + SPEAKER_BACK_LEFT | 1.400 + SPEAKER_BACK_RIGHT; 1.401 + break; 1.402 + case DevFmtX51Side: 1.403 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 1.404 + SPEAKER_FRONT_RIGHT | 1.405 + SPEAKER_FRONT_CENTER | 1.406 + SPEAKER_LOW_FREQUENCY | 1.407 + SPEAKER_SIDE_LEFT | 1.408 + SPEAKER_SIDE_RIGHT; 1.409 + break; 1.410 + case DevFmtX61: 1.411 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 1.412 + SPEAKER_FRONT_RIGHT | 1.413 + SPEAKER_FRONT_CENTER | 1.414 + SPEAKER_LOW_FREQUENCY | 1.415 + SPEAKER_BACK_CENTER | 1.416 + SPEAKER_SIDE_LEFT | 1.417 + SPEAKER_SIDE_RIGHT; 1.418 + break; 1.419 + case DevFmtX71: 1.420 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 1.421 + SPEAKER_FRONT_RIGHT | 1.422 + SPEAKER_FRONT_CENTER | 1.423 + SPEAKER_LOW_FREQUENCY | 1.424 + SPEAKER_BACK_LEFT | 1.425 + SPEAKER_BACK_RIGHT | 1.426 + SPEAKER_SIDE_LEFT | 1.427 + SPEAKER_SIDE_RIGHT; 1.428 + break; 1.429 + } 1.430 + 1.431 + OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; 1.432 + OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); 1.433 + OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; 1.434 + OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; 1.435 + OutputType.Format.nSamplesPerSec = device->Frequency; 1.436 + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; 1.437 + OutputType.Format.cbSize = 0; 1.438 + } 1.439 + 1.440 + if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) 1.441 + { 1.442 + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 1.443 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 1.444 + OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); 1.445 + if(device->FmtType == DevFmtFloat) 1.446 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; 1.447 + else 1.448 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 1.449 + } 1.450 + else 1.451 + { 1.452 + if(SUCCEEDED(hr)) 1.453 + { 1.454 + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); 1.455 + DSBDescription.dwSize=sizeof(DSBUFFERDESC); 1.456 + DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; 1.457 + hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); 1.458 + } 1.459 + if(SUCCEEDED(hr)) 1.460 + hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); 1.461 + } 1.462 + 1.463 + if(SUCCEEDED(hr)) 1.464 + { 1.465 + if(device->NumUpdates > MAX_UPDATES) 1.466 + { 1.467 + device->UpdateSize = (device->UpdateSize*device->NumUpdates + 1.468 + MAX_UPDATES-1) / MAX_UPDATES; 1.469 + device->NumUpdates = MAX_UPDATES; 1.470 + } 1.471 + 1.472 + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); 1.473 + DSBDescription.dwSize=sizeof(DSBUFFERDESC); 1.474 + DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; 1.475 + DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * 1.476 + OutputType.Format.nBlockAlign; 1.477 + DSBDescription.lpwfxFormat=&OutputType.Format; 1.478 + hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); 1.479 + } 1.480 + 1.481 + if(SUCCEEDED(hr)) 1.482 + { 1.483 + hr = IDirectSoundBuffer_QueryInterface(pData->DSsbuffer, &IID_IDirectSoundNotify, (LPVOID *)&pData->DSnotify); 1.484 + if(SUCCEEDED(hr)) 1.485 + { 1.486 + DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; 1.487 + ALuint i; 1.488 + 1.489 + for(i = 0;i < device->NumUpdates;++i) 1.490 + { 1.491 + notifies[i].dwOffset = i * device->UpdateSize * 1.492 + OutputType.Format.nBlockAlign; 1.493 + notifies[i].hEventNotify = pData->hNotifyEvent; 1.494 + } 1.495 + if(IDirectSoundNotify_SetNotificationPositions(pData->DSnotify, device->NumUpdates, notifies) != DS_OK) 1.496 + hr = E_FAIL; 1.497 + } 1.498 + } 1.499 + 1.500 + if(SUCCEEDED(hr)) 1.501 + { 1.502 + ResetEvent(pData->hNotifyEvent); 1.503 + SetDefaultWFXChannelOrder(device); 1.504 + pData->thread = StartThread(DSoundProc, device); 1.505 + if(pData->thread == NULL) 1.506 + hr = E_FAIL; 1.507 + } 1.508 + 1.509 + if(FAILED(hr)) 1.510 + { 1.511 + if(pData->DSnotify != NULL) 1.512 + IDirectSoundNotify_Release(pData->DSnotify); 1.513 + pData->DSnotify = NULL; 1.514 + if(pData->DSsbuffer != NULL) 1.515 + IDirectSoundBuffer_Release(pData->DSsbuffer); 1.516 + pData->DSsbuffer = NULL; 1.517 + if(pData->DSpbuffer != NULL) 1.518 + IDirectSoundBuffer_Release(pData->DSpbuffer); 1.519 + pData->DSpbuffer = NULL; 1.520 + return ALC_FALSE; 1.521 + } 1.522 + 1.523 + return ALC_TRUE; 1.524 +} 1.525 + 1.526 +static void DSoundStopPlayback(ALCdevice *device) 1.527 +{ 1.528 + DSoundData *pData = device->ExtraData; 1.529 + 1.530 + if(!pData->thread) 1.531 + return; 1.532 + 1.533 + pData->killNow = 1; 1.534 + StopThread(pData->thread); 1.535 + pData->thread = NULL; 1.536 + 1.537 + pData->killNow = 0; 1.538 + 1.539 + IDirectSoundNotify_Release(pData->DSnotify); 1.540 + pData->DSnotify = NULL; 1.541 + IDirectSoundBuffer_Release(pData->DSsbuffer); 1.542 + pData->DSsbuffer = NULL; 1.543 + if(pData->DSpbuffer != NULL) 1.544 + IDirectSoundBuffer_Release(pData->DSpbuffer); 1.545 + pData->DSpbuffer = NULL; 1.546 +} 1.547 + 1.548 + 1.549 +static const BackendFuncs DSoundFuncs = { 1.550 + DSoundOpenPlayback, 1.551 + DSoundClosePlayback, 1.552 + DSoundResetPlayback, 1.553 + DSoundStopPlayback, 1.554 + NULL, 1.555 + NULL, 1.556 + NULL, 1.557 + NULL, 1.558 + NULL, 1.559 + NULL 1.560 +}; 1.561 + 1.562 + 1.563 +ALCboolean alcDSoundInit(BackendFuncs *FuncList) 1.564 +{ 1.565 + if(!DSoundLoad()) 1.566 + return ALC_FALSE; 1.567 + *FuncList = DSoundFuncs; 1.568 + return ALC_TRUE; 1.569 +} 1.570 + 1.571 +void alcDSoundDeinit(void) 1.572 +{ 1.573 + ALuint i; 1.574 + 1.575 + for(i = 0;i < NumDevices;++i) 1.576 + free(DeviceList[i].name); 1.577 + free(DeviceList); 1.578 + DeviceList = NULL; 1.579 + NumDevices = 0; 1.580 + 1.581 + if(ds_handle) 1.582 + FreeLibrary(ds_handle); 1.583 + ds_handle = NULL; 1.584 +} 1.585 + 1.586 +void alcDSoundProbe(enum DevProbe type) 1.587 +{ 1.588 + HRESULT hr; 1.589 + ALuint i; 1.590 + 1.591 + switch(type) 1.592 + { 1.593 + case DEVICE_PROBE: 1.594 + AppendDeviceList(dsDevice); 1.595 + break; 1.596 + 1.597 + case ALL_DEVICE_PROBE: 1.598 + for(i = 0;i < NumDevices;++i) 1.599 + free(DeviceList[i].name); 1.600 + free(DeviceList); 1.601 + DeviceList = NULL; 1.602 + NumDevices = 0; 1.603 + 1.604 + hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL); 1.605 + if(FAILED(hr)) 1.606 + ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); 1.607 + else 1.608 + { 1.609 + for(i = 0;i < NumDevices;i++) 1.610 + AppendAllDeviceList(DeviceList[i].name); 1.611 + } 1.612 + break; 1.613 + 1.614 + case CAPTURE_DEVICE_PROBE: 1.615 + break; 1.616 + } 1.617 +}