From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/stream.c | 52 +++++++++++++++++++++++++++++---- dlls/sapi/tests/stream.c | 62 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 5 deletions(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index c3ecdf42697..ae0e8c048c9 100644 --- a/dlls/sapi/stream.c +++ b/dlls/sapi/stream.c @@ -27,6 +27,7 @@ #include "objbase.h"
#include "sapiddk.h" +#include "sperror.h"
#include "wine/debug.h"
@@ -38,6 +39,10 @@ struct spstream { ISpStream ISpStream_iface; LONG ref; + + IStream *base_stream; + GUID format; + WAVEFORMATEX *wfx; };
static inline struct spstream *impl_from_ISpStream(ISpStream *iface) @@ -87,6 +92,8 @@ static ULONG WINAPI spstream_Release(ISpStream *iface)
if (!ref) { + if (This->base_stream) IStream_Release(This->base_stream); + free(This->wfx); free(This); }
@@ -182,18 +189,49 @@ static HRESULT WINAPI spstream_GetFormat(ISpStream *iface, GUID *format, WAVEFOR }
static HRESULT WINAPI spstream_SetBaseStream(ISpStream *iface, IStream *stream, REFGUID format, - const WAVEFORMATEX *wave) + const WAVEFORMATEX *wfx) { - FIXME("(%p, %p, %s, %p): stub.\n", iface, stream, debugstr_guid(format), wave); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %s, %p).\n", iface, stream, debugstr_guid(format), wfx); + + if (!stream || !format) + return E_INVALIDARG; + + if (This->base_stream) + return SPERR_ALREADY_INITIALIZED; + + This->format = *format; + if (IsEqualGUID(format, &SPDFID_WaveFormatEx)) + { + if (!wfx) + return E_INVALIDARG; + if (!(This->wfx = malloc(sizeof(WAVEFORMATEX) + wfx->cbSize))) + return E_OUTOFMEMORY; + memcpy(This->wfx, wfx, sizeof(WAVEFORMATEX) + wfx->cbSize); + } + + IStream_AddRef(stream); + This->base_stream = stream; + return S_OK; }
static HRESULT WINAPI spstream_GetBaseStream(ISpStream *iface, IStream **stream) { - FIXME("(%p, %p): stub.\n", iface, stream); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p).\n", iface, stream); + + if (!stream) + return E_INVALIDARG; + + if (!This->base_stream) + return SPERR_UNINITIALIZED; + + *stream = This->base_stream; + if (*stream) + IStream_AddRef(*stream); + return S_OK; }
static HRESULT WINAPI spstream_BindToFile(ISpStream *iface, LPCWSTR filename, SPFILEMODE mode, @@ -245,6 +283,10 @@ HRESULT speech_stream_create(IUnknown *outer, REFIID iid, void **obj) This->ISpStream_iface.lpVtbl = &spstream_vtbl; This->ref = 1;
+ This->base_stream = NULL; + This->format = GUID_NULL; + This->wfx = NULL; + hr = ISpStream_QueryInterface(&This->ISpStream_iface, iid, obj);
ISpStream_Release(&This->ISpStream_iface); diff --git a/dlls/sapi/tests/stream.c b/dlls/sapi/tests/stream.c index ee9a7648aa8..6cb21851ee4 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -86,9 +86,71 @@ static void test_interfaces(void) ISpStream_Release(speech_stream); }
+static void test_spstream(void) +{ + ISpStream *stream; + ISpMMSysAudio *mmaudio; + IStream *base_stream, *base_stream2; + GUID fmtid; + WAVEFORMATEX *wfx = NULL; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_SpMMAudioOut, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpMMSysAudio, (void **)&mmaudio); + ok(hr == S_OK, "Failed to create ISpMMSysAudio interface: %#lx.\n", hr); + + hr = ISpMMSysAudio_GetFormat(mmaudio, &fmtid, &wfx); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(IsEqualGUID(&fmtid, &SPDFID_WaveFormatEx), "got %s.\n", wine_dbgstr_guid(&fmtid)); + + hr = ISpMMSysAudio_QueryInterface(mmaudio, &IID_IStream, (void **)&base_stream); + ok(hr == S_OK, "Failed to get IStream interface from mmaudio: %#lx.\n", hr); + + hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpStream, (void **)&stream); + ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, NULL, NULL, NULL); + ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, NULL, NULL); + ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + + hr = ISpStream_GetBaseStream(stream, &base_stream2); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_Text, NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &fmtid, wfx); + ok(hr == SPERR_ALREADY_INITIALIZED, "got %#lx.\n", hr); + + ISpStream_Release(stream); + + hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpStream, (void **)&stream); + ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_WaveFormatEx, NULL); + ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_WaveFormatEx, wfx); + ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_GetBaseStream(stream, &base_stream2); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(base_stream2 == base_stream, "got %p.\n", base_stream2); + IStream_Release(base_stream2); + + ISpStream_Release(stream); + IStream_Release(base_stream); + ISpMMSysAudio_Release(mmaudio); +} + START_TEST(stream) { CoInitialize(NULL); test_interfaces(); + test_spstream(); CoUninitialize(); }