mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[DSOUND]
* Revert r60474 until Johannes has time to look into it. svn path=/trunk/; revision=61851
This commit is contained in:
parent
9ebfde575a
commit
0f2f7f1c78
7 changed files with 119 additions and 99 deletions
|
@ -5,6 +5,7 @@ add_definitions(
|
|||
-D__WINESRC__)
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
||||
|
||||
spec2def(dsound.dll dsound.spec ADD_IMPORTLIB)
|
||||
|
||||
add_library(dsound SHARED
|
||||
|
@ -24,5 +25,5 @@ add_library(dsound SHARED
|
|||
|
||||
set_module_type(dsound win32dll)
|
||||
target_link_libraries(dsound dxguid uuid wine)
|
||||
add_importlibs(dsound ole32 advapi32 user32 msvcrt kernel32 ntdll)
|
||||
add_importlibs(dsound winmm ole32 advapi32 user32 msvcrt kernel32 ntdll)
|
||||
add_cd_file(TARGET dsound DESTINATION reactos/system32 FOR all)
|
||||
|
|
|
@ -43,8 +43,6 @@ typedef struct IDirectSoundCaptureBufferImpl
|
|||
/* IDirectSoundNotify fields */
|
||||
DSBPOSITIONNOTIFY *notifies;
|
||||
int nrofnotifies;
|
||||
HANDLE thread;
|
||||
HANDLE sleepev;
|
||||
} IDirectSoundCaptureBufferImpl;
|
||||
|
||||
/* DirectSoundCaptureDevice implementation structure */
|
||||
|
@ -58,6 +56,7 @@ struct DirectSoundCaptureDevice
|
|||
WAVEFORMATEX *pwfx;
|
||||
IDirectSoundCaptureBufferImpl *capture_buffer;
|
||||
DWORD state;
|
||||
UINT timerID;
|
||||
CRITICAL_SECTION lock;
|
||||
IMMDevice *mmdevice;
|
||||
IAudioClient *client;
|
||||
|
@ -65,20 +64,12 @@ struct DirectSoundCaptureDevice
|
|||
struct list entry;
|
||||
};
|
||||
|
||||
static DWORD WINAPI DSOUND_capture_thread(void *user);
|
||||
|
||||
static void capturebuffer_destroy(IDirectSoundCaptureBufferImpl *This)
|
||||
{
|
||||
if (This->device->state == STATE_CAPTURING)
|
||||
This->device->state = STATE_STOPPING;
|
||||
|
||||
if(This->thread){
|
||||
SetEvent(This->sleepev);
|
||||
WaitForSingleObject(This->thread, INFINITE);
|
||||
CloseHandle(This->thread);
|
||||
}
|
||||
CloseHandle(This->sleepev);
|
||||
|
||||
HeapFree(GetProcessHeap(),0, This->pdscbd);
|
||||
|
||||
if (This->device->client) {
|
||||
|
@ -732,8 +723,8 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
|
|||
}
|
||||
|
||||
err = IAudioClient_Initialize(device->client,
|
||||
AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||
200 * 100000, 0, device->pwfx, NULL);
|
||||
AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST,
|
||||
200 * 100000, 50000, device->pwfx, NULL);
|
||||
if(FAILED(err)){
|
||||
WARN("Initialize failed: %08x\n", err);
|
||||
IAudioClient_Release(device->client);
|
||||
|
@ -746,27 +737,12 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
|
|||
return err;
|
||||
}
|
||||
|
||||
This->sleepev = CreateEventW(NULL, 0, 0, NULL);
|
||||
|
||||
err = IAudioClient_SetEventHandle(device->client, This->sleepev);
|
||||
if(FAILED(err)){
|
||||
WARN("SetEventHandle failed: %08x\n", err);
|
||||
IAudioClient_Release(device->client);
|
||||
device->client = NULL;
|
||||
CloseHandle(This->sleepev);
|
||||
HeapFree(GetProcessHeap(), 0, This->pdscbd);
|
||||
This->device->capture_buffer = 0;
|
||||
HeapFree( GetProcessHeap(), 0, This );
|
||||
return err;
|
||||
}
|
||||
|
||||
err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient,
|
||||
(void**)&device->capture);
|
||||
if(FAILED(err)){
|
||||
WARN("GetService failed: %08x\n", err);
|
||||
IAudioClient_Release(device->client);
|
||||
device->client = NULL;
|
||||
CloseHandle(This->sleepev);
|
||||
HeapFree(GetProcessHeap(), 0, This->pdscbd);
|
||||
This->device->capture_buffer = 0;
|
||||
HeapFree( GetProcessHeap(), 0, This );
|
||||
|
@ -784,7 +760,6 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
|
|||
device->client = NULL;
|
||||
IAudioCaptureClient_Release(device->capture);
|
||||
device->capture = NULL;
|
||||
CloseHandle(This->sleepev);
|
||||
HeapFree(GetProcessHeap(), 0, This->pdscbd);
|
||||
This->device->capture_buffer = 0;
|
||||
HeapFree( GetProcessHeap(), 0, This );
|
||||
|
@ -792,7 +767,6 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
|
|||
}
|
||||
device->buffer = newbuf;
|
||||
device->buflen = buflen;
|
||||
This->thread = CreateThread(NULL, 0, DSOUND_capture_thread, This, 0, NULL);
|
||||
}
|
||||
|
||||
IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface);
|
||||
|
@ -840,6 +814,9 @@ static ULONG DirectSoundCaptureDevice_Release(
|
|||
if (!ref) {
|
||||
TRACE("deleting object\n");
|
||||
|
||||
timeKillEvent(device->timerID);
|
||||
timeEndPeriod(DS_TIME_RES);
|
||||
|
||||
EnterCriticalSection(&DSOUND_capturers_lock);
|
||||
list_remove(&device->entry);
|
||||
LeaveCriticalSection(&DSOUND_capturers_lock);
|
||||
|
@ -858,19 +835,29 @@ static ULONG DirectSoundCaptureDevice_Release(
|
|||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device)
|
||||
static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user,
|
||||
DWORD_PTR dw1, DWORD_PTR dw2)
|
||||
{
|
||||
HRESULT hr;
|
||||
UINT32 packet_frames, packet_bytes, avail_bytes, skip_bytes = 0;
|
||||
DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user;
|
||||
UINT32 packet_frames, packet_bytes, avail_bytes;
|
||||
DWORD flags;
|
||||
BYTE *buf;
|
||||
HRESULT hr;
|
||||
|
||||
if(!device->capture_buffer || device->state == STATE_STOPPED)
|
||||
return S_FALSE;
|
||||
if(!device->ref)
|
||||
return;
|
||||
|
||||
EnterCriticalSection(&device->lock);
|
||||
|
||||
if(!device->capture_buffer || device->state == STATE_STOPPED){
|
||||
LeaveCriticalSection(&device->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(device->state == STATE_STOPPING){
|
||||
device->state = STATE_STOPPED;
|
||||
return S_FALSE;
|
||||
LeaveCriticalSection(&device->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(device->state == STATE_STARTING)
|
||||
|
@ -879,28 +866,24 @@ static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device)
|
|||
hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames,
|
||||
&flags, NULL, NULL);
|
||||
if(FAILED(hr)){
|
||||
LeaveCriticalSection(&device->lock);
|
||||
WARN("GetBuffer failed: %08x\n", hr);
|
||||
return hr;
|
||||
return;
|
||||
}
|
||||
|
||||
packet_bytes = packet_frames * device->pwfx->nBlockAlign;
|
||||
if(packet_bytes > device->buflen){
|
||||
TRACE("audio glitch: dsound buffer too small for data\n");
|
||||
skip_bytes = packet_bytes - device->buflen;
|
||||
packet_bytes = device->buflen;
|
||||
}
|
||||
|
||||
avail_bytes = device->buflen - device->write_pos_bytes;
|
||||
if(avail_bytes > packet_bytes)
|
||||
avail_bytes = packet_bytes;
|
||||
|
||||
memcpy(device->buffer + device->write_pos_bytes, buf + skip_bytes, avail_bytes);
|
||||
memcpy(device->buffer + device->write_pos_bytes, buf, avail_bytes);
|
||||
capture_CheckNotify(device->capture_buffer, device->write_pos_bytes, avail_bytes);
|
||||
|
||||
packet_bytes -= avail_bytes;
|
||||
if(packet_bytes > 0){
|
||||
if(device->capture_buffer->flags & DSCBSTART_LOOPING){
|
||||
memcpy(device->buffer, buf + skip_bytes + avail_bytes, packet_bytes);
|
||||
memcpy(device->buffer, buf + avail_bytes, packet_bytes);
|
||||
capture_CheckNotify(device->capture_buffer, 0, packet_bytes);
|
||||
}else{
|
||||
device->state = STATE_STOPPED;
|
||||
|
@ -913,44 +896,12 @@ static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device)
|
|||
|
||||
hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames);
|
||||
if(FAILED(hr)){
|
||||
LeaveCriticalSection(&device->lock);
|
||||
WARN("ReleaseBuffer failed: %08x\n", hr);
|
||||
return hr;
|
||||
return;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static DWORD WINAPI DSOUND_capture_thread(void *user)
|
||||
{
|
||||
IDirectSoundCaptureBufferImpl *buffer = user;
|
||||
HRESULT hr;
|
||||
DWORD ret, wait_ms;
|
||||
REFERENCE_TIME period;
|
||||
|
||||
hr = IAudioClient_GetDevicePeriod(buffer->device->client, &period, NULL);
|
||||
if(FAILED(hr)){
|
||||
WARN("GetDevicePeriod failed: %08x\n", hr);
|
||||
wait_ms = 5;
|
||||
}else
|
||||
wait_ms = MulDiv(5, period, 10000);
|
||||
|
||||
while(buffer->ref){
|
||||
ret = WaitForSingleObject(buffer->sleepev, wait_ms);
|
||||
|
||||
if(!buffer->device->ref)
|
||||
break;
|
||||
|
||||
if(ret == WAIT_OBJECT_0){
|
||||
EnterCriticalSection(&buffer->device->lock);
|
||||
|
||||
DSOUND_capture_data(buffer->device);
|
||||
|
||||
LeaveCriticalSection(&buffer->device->lock);
|
||||
}else if(ret != WAIT_TIMEOUT)
|
||||
WARN("WaitForSingleObject failed: %u\n", GetLastError());
|
||||
}
|
||||
|
||||
return 0;
|
||||
LeaveCriticalSection(&device->lock);
|
||||
}
|
||||
|
||||
static struct _TestFormat {
|
||||
|
@ -1014,6 +965,14 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
|
|||
|
||||
EnterCriticalSection(&DSOUND_capturers_lock);
|
||||
|
||||
LIST_FOR_EACH_ENTRY(device, &DSOUND_capturers, DirectSoundCaptureDevice, entry){
|
||||
if(IsEqualGUID(&device->guid, &devGUID)){
|
||||
IMMDevice_Release(mmdevice);
|
||||
LeaveCriticalSection(&DSOUND_capturers_lock);
|
||||
return DSERR_ALLOCATED;
|
||||
}
|
||||
}
|
||||
|
||||
hr = DirectSoundCaptureDevice_Create(&device);
|
||||
if (hr != DS_OK) {
|
||||
WARN("DirectSoundCaptureDevice_Create failed\n");
|
||||
|
@ -1048,6 +1007,8 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
|
|||
}
|
||||
IAudioClient_Release(client);
|
||||
|
||||
device->timerID = DSOUND_create_timer(DSOUND_capture_timer, (DWORD_PTR)device);
|
||||
|
||||
list_add_tail(&DSOUND_capturers, &device->entry);
|
||||
|
||||
*ppDevice = device;
|
||||
|
|
|
@ -715,6 +715,30 @@ BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
|
|||
return hr == S_OK;
|
||||
}
|
||||
|
||||
UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user)
|
||||
{
|
||||
UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
|
||||
TIMECAPS time;
|
||||
|
||||
timeGetDevCaps(&time, sizeof(TIMECAPS));
|
||||
TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
|
||||
if (triggertime < time.wPeriodMin)
|
||||
triggertime = time.wPeriodMin;
|
||||
if (res < time.wPeriodMin)
|
||||
res = time.wPeriodMin;
|
||||
if (timeBeginPeriod(res) == TIMERR_NOCANDO)
|
||||
WARN("Could not set minimum resolution, don't expect sound\n");
|
||||
id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
|
||||
if (!id)
|
||||
{
|
||||
WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
|
||||
id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC);
|
||||
if (!id)
|
||||
ERR("Could not create timer, sound playback will not occur\n");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
|
||||
{
|
||||
HRESULT hr = DS_OK;
|
||||
|
|
|
@ -768,16 +768,20 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
TRACE("DLL_PROCESS_ATTACH\n");
|
||||
instance = hInstDLL;
|
||||
DisableThreadLibraryCalls(hInstDLL);
|
||||
/* Increase refcount on dsound by 1 */
|
||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)hInstDLL, &hInstDLL);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
if (lpvReserved) break;
|
||||
TRACE("DLL_PROCESS_DETACH\n");
|
||||
DeleteCriticalSection(&DSOUND_renderers_lock);
|
||||
DeleteCriticalSection(&DSOUND_capturers_lock);
|
||||
break;
|
||||
default:
|
||||
TRACE("UNKNOWN REASON\n");
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -287,5 +287,6 @@ HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device) DECLSP
|
|||
|
||||
BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
|
||||
DWORD depth, WORD channels) DECLSPEC_HIDDEN;
|
||||
UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user) DECLSPEC_HIDDEN;
|
||||
HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
|
||||
LPDSENUMCALLBACKW cb, void *user) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -425,24 +425,35 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP
|
|||
return DS_OK;
|
||||
}
|
||||
|
||||
WAVEFORMATEX *DSOUND_CopyFormat(const WAVEFORMATEX *wfex)
|
||||
static DWORD DSOUND_GetFormatSize(LPCWAVEFORMATEX wfex)
|
||||
{
|
||||
WAVEFORMATEX *pwfx;
|
||||
if(wfex->wFormatTag == WAVE_FORMAT_PCM){
|
||||
pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX));
|
||||
CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
|
||||
pwfx->cbSize = 0;
|
||||
}else{
|
||||
pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX) + wfex->cbSize);
|
||||
CopyMemory(pwfx, wfex, sizeof(WAVEFORMATEX) + wfex->cbSize);
|
||||
}
|
||||
if (wfex->wFormatTag == WAVE_FORMAT_PCM)
|
||||
return sizeof(WAVEFORMATEX);
|
||||
else
|
||||
return sizeof(WAVEFORMATEX) + wfex->cbSize;
|
||||
}
|
||||
|
||||
if(pwfx->wFormatTag == WAVE_FORMAT_PCM ||
|
||||
(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
|
||||
IsEqualGUID(&((const WAVEFORMATEXTENSIBLE*)pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)))
|
||||
pwfx->nBlockAlign = (pwfx->nChannels * pwfx->wBitsPerSample) / 8;
|
||||
|
||||
return pwfx;
|
||||
LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
|
||||
{
|
||||
DWORD size = DSOUND_GetFormatSize(wfex);
|
||||
LPWAVEFORMATEX pwfx = HeapAlloc(GetProcessHeap(),0,size);
|
||||
if (pwfx == NULL) {
|
||||
WARN("out of memory\n");
|
||||
} else if (wfex->wFormatTag != WAVE_FORMAT_PCM) {
|
||||
CopyMemory(pwfx, wfex, size);
|
||||
} else {
|
||||
CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
|
||||
pwfx->cbSize=0;
|
||||
if (pwfx->nBlockAlign != pwfx->nChannels * pwfx->wBitsPerSample/8) {
|
||||
WARN("Fixing bad nBlockAlign (%u)\n", pwfx->nBlockAlign);
|
||||
pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8;
|
||||
}
|
||||
if (pwfx->nAvgBytesPerSec != pwfx->nSamplesPerSec * pwfx->nBlockAlign) {
|
||||
WARN("Fixing bad nAvgBytesPerSec (%u)\n", pwfx->nAvgBytesPerSec);
|
||||
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
|
||||
}
|
||||
}
|
||||
return pwfx;
|
||||
}
|
||||
|
||||
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
|
||||
|
@ -519,9 +530,27 @@ done:
|
|||
device->primary_pwfx = old_fmt;
|
||||
else
|
||||
HeapFree(GetProcessHeap(), 0, old_fmt);
|
||||
} else if (passed_fmt->wFormatTag == WAVE_FORMAT_PCM ||
|
||||
passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
|
||||
/* Fill in "real" values to primary_pwfx */
|
||||
WAVEFORMATEX *fmt = device->primary_pwfx;
|
||||
|
||||
*fmt = *device->pwfx;
|
||||
fmtex = (void*)device->pwfx;
|
||||
|
||||
if (IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
|
||||
passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
|
||||
fmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
} else {
|
||||
fmt->wFormatTag = WAVE_FORMAT_PCM;
|
||||
fmt->wBitsPerSample = 16;
|
||||
}
|
||||
fmt->nBlockAlign = fmt->nChannels * fmt->wBitsPerSample / 8;
|
||||
fmt->nAvgBytesPerSec = fmt->nBlockAlign * fmt->nSamplesPerSec;
|
||||
fmt->cbSize = 0;
|
||||
} else {
|
||||
HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
|
||||
device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
|
||||
device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex));
|
||||
memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex));
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -40,7 +40,7 @@ reactos/dll/directx/wine/dinput8 # Synced to Wine-1.7.1
|
|||
reactos/dll/directx/wine/dmusic # Synced to Wine-1.7.1
|
||||
reactos/dll/directx/wine/dplay # Synced to Wine-1.7.1
|
||||
reactos/dll/directx/wine/dplayx # Synced to Wine-1.7.1
|
||||
reactos/dll/directx/wine/dsound # Synced to Wine-1.7.1
|
||||
reactos/dll/directx/wine/dsound # Synced to Wine-1.5.26
|
||||
reactos/dll/directx/wine/dxdiagn # Synced to Wine-1.7.1
|
||||
reactos/dll/directx/wine/dxgi # Synced to Wine-1.7.1
|
||||
reactos/dll/directx/wine/msdmo # Synced to Wine-1.7.1
|
||||
|
|
Loading…
Reference in a new issue