Mark Harmstone : dsound: Implement SetFX.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Mar 10 10:10:04 CDT 2015


Module: wine
Branch: master
Commit: 17056b9f30b61c1b31055135aded1a4ecbea4ea0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=17056b9f30b61c1b31055135aded1a4ecbea4ea0

Author: Mark Harmstone <hellas at burntcomma.com>
Date:   Tue Mar  3 07:47:36 2015 +0000

dsound: Implement SetFX.

---

 dlls/dsound/buffer.c         | 133 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/dsound/dsound_main.c    |   1 +
 dlls/dsound/dsound_private.h |  10 ++++
 3 files changed, 141 insertions(+), 3 deletions(-)

diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 680075e..51796b7 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -21,6 +21,8 @@
 
 #include <stdarg.h>
 
+#define COBJMACROS
+
 #define NONAMELESSSTRUCT
 #define NONAMELESSUNION
 #include "windef.h"
@@ -697,14 +699,129 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, D
 {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
 	DWORD u;
+	DSFilter *filters;
+	HRESULT hr, hr2;
+	DMO_MEDIA_TYPE dmt;
+	WAVEFORMATEX wfx;
 
-	FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
+	TRACE("(%p,%u,%p,%p)\n", This, dwEffectsCount, pDSFXDesc, pdwResultCodes);
 
 	if (pdwResultCodes)
 		for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
 
-	WARN("control unavailable\n");
-	return DSERR_CONTROLUNAVAIL;
+	if ((dwEffectsCount > 0 && !pDSFXDesc) ||
+		(dwEffectsCount == 0 && (pDSFXDesc || pdwResultCodes))
+	)
+		return E_INVALIDARG;
+
+	if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFX)) {
+		WARN("attempted to call SetFX on buffer without DSBCAPS_CTRLFX\n");
+		return DSERR_CONTROLUNAVAIL;
+	}
+
+	if (This->state != STATE_STOPPED)
+		return DSERR_INVALIDCALL;
+
+	if (This->buffer->lockedbytes > 0)
+		return DSERR_INVALIDCALL;
+
+	if (dwEffectsCount == 0) {
+		if (This->num_filters > 0) {
+			for (u = 0; u < This->num_filters; u++) {
+				IMediaObject_Release(This->filters[u].obj);
+			}
+			HeapFree(GetProcessHeap(), 0, This->filters);
+
+			This->filters = NULL;
+			This->num_filters = 0;
+		}
+
+		return DS_OK;
+	}
+
+	filters = HeapAlloc(GetProcessHeap(), 0, dwEffectsCount * sizeof(DSFilter));
+	if (!filters) {
+		WARN("out of memory\n");
+		return DSERR_OUTOFMEMORY;
+	}
+
+	hr = DS_OK;
+
+	wfx.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+	wfx.nChannels = This->pwfx->nChannels;
+	wfx.nSamplesPerSec = This->pwfx->nSamplesPerSec;
+	wfx.wBitsPerSample = sizeof(float) * 8;
+	wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample)/8;
+	wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+	wfx.cbSize = sizeof(wfx);
+
+	dmt.majortype = KSDATAFORMAT_TYPE_AUDIO;
+	dmt.subtype = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+	dmt.bFixedSizeSamples = TRUE;
+	dmt.bTemporalCompression = FALSE;
+	dmt.lSampleSize = sizeof(float) * This->pwfx->nChannels / 8;
+	dmt.formattype = FORMAT_WaveFormatEx;
+	dmt.pUnk = NULL;
+	dmt.cbFormat = sizeof(WAVEFORMATEX);
+	dmt.pbFormat = (BYTE*)&wfx;
+
+	for (u = 0; u < dwEffectsCount; u++) {
+		hr2 = CoCreateInstance(&pDSFXDesc[u].guidDSFXClass, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaObject, (LPVOID*)&filters[u].obj);
+
+		if (SUCCEEDED(hr2)) {
+			hr2 = IMediaObject_SetInputType(filters[u].obj, 0, &dmt, 0);
+			if (FAILED(hr2))
+				WARN("Could not set DMO input type\n");
+		}
+
+		if (SUCCEEDED(hr2)) {
+			hr2 = IMediaObject_SetOutputType(filters[u].obj, 0, &dmt, 0);
+			if (FAILED(hr2))
+				WARN("Could not set DMO output type\n");
+		}
+
+		if (FAILED(hr2)) {
+			if (hr == DS_OK)
+				hr = hr2;
+
+			if (pdwResultCodes)
+				pdwResultCodes[u] = (hr2 == REGDB_E_CLASSNOTREG) ? DSFXR_UNKNOWN : DSFXR_FAILED;
+		} else {
+			if (pdwResultCodes)
+				pdwResultCodes[u] = DSFXR_LOCSOFTWARE;
+		}
+	}
+
+	if (FAILED(hr)) {
+		for (u = 0; u < dwEffectsCount; u++) {
+			if (pdwResultCodes)
+				pdwResultCodes[u] = (pdwResultCodes[u] != DSFXR_UNKNOWN) ? DSFXR_PRESENT : DSFXR_UNKNOWN;
+
+			if (filters[u].obj)
+				IMediaObject_Release(filters[u].obj);
+		}
+
+		HeapFree(GetProcessHeap(), 0, filters);
+	} else {
+		if (This->num_filters > 0) {
+			for (u = 0; u < This->num_filters; u++) {
+				IMediaObject_Release(This->filters[u].obj);
+				if (This->filters[u].inplace) IMediaObjectInPlace_Release(This->filters[u].inplace);
+			}
+			HeapFree(GetProcessHeap(), 0, This->filters);
+		}
+
+		for (u = 0; u < dwEffectsCount; u++) {
+			memcpy(&filters[u].guid, &pDSFXDesc[u].guidDSFXClass, sizeof(GUID));
+			if (FAILED(IMediaObject_QueryInterface(filters[u].obj, &IID_IMediaObjectInPlace, (void*)&filters[u].inplace)))
+				filters[u].inplace = NULL;
+		}
+
+		This->filters = filters;
+		This->num_filters = dwEffectsCount;
+	}
+
+	return hr;
 }
 
 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 *iface,
@@ -1024,6 +1141,16 @@ void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
 
     HeapFree(GetProcessHeap(), 0, This->notifies);
     HeapFree(GetProcessHeap(), 0, This->pwfx);
+
+    if (This->filters) {
+        int i;
+        for (i = 0; i < This->num_filters; i++) {
+            IMediaObject_Release(This->filters[i].obj);
+            if (This->filters[i].inplace) IMediaObjectInPlace_Release(This->filters[i].inplace);
+        }
+        HeapFree(GetProcessHeap(), 0, This->filters);
+    }
+
     HeapFree(GetProcessHeap(), 0, This);
 
     TRACE("(%p) released\n", This);
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
index 0130607..d6be926 100644
--- a/dlls/dsound/dsound_main.c
+++ b/dlls/dsound/dsound_main.c
@@ -55,6 +55,7 @@
 #include "unknwn.h"
 #include "oleidl.h"
 #include "shobjidl.h"
+#include "strmif.h"
 
 #include "initguid.h"
 #include "ksmedia.h"
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 715c5f3..9c58679 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -26,7 +26,9 @@
 #include "wingdi.h"
 #include "mmdeviceapi.h"
 #include "audioclient.h"
+#include "mediaobj.h"
 #include "mmsystem.h"
+#include "uuids.h"
 
 #include "wine/list.h"
 
@@ -57,6 +59,12 @@ typedef struct _DSVOLUMEPAN
     LONG	lPan;
 } DSVOLUMEPAN,*PDSVOLUMEPAN;
 
+typedef struct DSFilter {
+    GUID guid;
+    IMediaObject* obj;
+    IMediaObjectInPlace* inplace;
+} DSFilter;
+
 /*****************************************************************************
  * IDirectSoundDevice implementation structure
  */
@@ -160,6 +168,8 @@ struct IDirectSoundBufferImpl
     int                         mix_channels;
     bitsgetfunc get, get_aux;
     bitsputfunc put, put_aux;
+    int                         num_filters;
+    DSFilter*                   filters;
 
     struct list entry;
 };




More information about the wine-cvs mailing list