Commit 107d9516 authored by Shaun Ren's avatar Shaun Ren Committed by Alexandre Julliard

sapi: Partially implement ISpMMSysAudio::SetState.

parent 250efdf0
......@@ -53,7 +53,13 @@ struct mmaudio
enum flow_type flow;
ISpObjectToken *token;
UINT device_id;
SPAUDIOSTATE state;
WAVEFORMATEX *wfx;
union
{
HWAVEIN in;
HWAVEOUT out;
} hwave;
CRITICAL_SECTION cs;
};
......@@ -363,6 +369,8 @@ static ULONG WINAPI mmsysaudio_Release(ISpMMSysAudio *iface)
if (!ref)
{
ISpMMSysAudio_SetState(iface, SPAS_CLOSED, 0);
if (This->token) ISpObjectToken_Release(This->token);
heap_free(This->wfx);
DeleteCriticalSection(&This->cs);
......@@ -481,9 +489,45 @@ static HRESULT WINAPI mmsysaudio_GetFormat(ISpMMSysAudio *iface, GUID *format, W
static HRESULT WINAPI mmsysaudio_SetState(ISpMMSysAudio *iface, SPAUDIOSTATE state, ULONGLONG reserved)
{
FIXME("(%p, %u, %s): stub.\n", iface, state, wine_dbgstr_longlong(reserved));
struct mmaudio *This = impl_from_ISpMMSysAudio(iface);
HRESULT hr = S_OK;
return E_NOTIMPL;
TRACE("(%p, %u, %s).\n", iface, state, wine_dbgstr_longlong(reserved));
if (state != SPAS_CLOSED && state != SPAS_RUN)
{
FIXME("state %#x not implemented.\n", state);
return E_NOTIMPL;
}
EnterCriticalSection(&This->cs);
if (This->state == state)
goto done;
if (This->state == SPAS_CLOSED)
{
if (waveOutOpen(&This->hwave.out, This->device_id, This->wfx, 0, 0, 0) != MMSYSERR_NOERROR)
{
hr = SPERR_GENERIC_MMSYS_ERROR;
goto done;
}
}
if (state == SPAS_CLOSED && This->state != SPAS_CLOSED)
{
if (waveOutClose(This->hwave.out) != MMSYSERR_NOERROR)
{
hr = SPERR_GENERIC_MMSYS_ERROR;
goto done;
}
}
This->state = state;
done:
LeaveCriticalSection(&This->cs);
return hr;
}
static HRESULT WINAPI mmsysaudio_SetFormat(ISpMMSysAudio *iface, const GUID *guid, const WAVEFORMATEX *wfx)
......@@ -499,6 +543,18 @@ static HRESULT WINAPI mmsysaudio_SetFormat(ISpMMSysAudio *iface, const GUID *gui
EnterCriticalSection(&This->cs);
if (!memcmp(wfx, This->wfx, sizeof(*wfx)) && !memcmp(wfx + 1, This->wfx + 1, wfx->cbSize))
{
LeaveCriticalSection(&This->cs);
return S_OK;
}
if (This->state != SPAS_CLOSED)
{
LeaveCriticalSection(&This->cs);
return SPERR_DEVICE_BUSY;
}
/* Determine whether the device supports the requested format. */
res = waveOutOpen(NULL, This->device_id, wfx, 0, 0, WAVE_FORMAT_QUERY);
if (res != MMSYSERR_NOERROR)
......@@ -609,7 +665,19 @@ static HRESULT WINAPI mmsysaudio_SetDeviceId(ISpMMSysAudio *iface, UINT id)
return E_INVALIDARG;
EnterCriticalSection(&This->cs);
if (id == This->device_id)
{
LeaveCriticalSection(&This->cs);
return S_OK;
}
if (This->state != SPAS_CLOSED)
{
LeaveCriticalSection(&This->cs);
return SPERR_DEVICE_BUSY;
}
This->device_id = id;
LeaveCriticalSection(&This->cs);
return S_OK;
......@@ -693,6 +761,7 @@ static HRESULT mmaudio_create(IUnknown *outer, REFIID iid, void **obj, enum flow
This->flow = flow;
This->token = NULL;
This->device_id = WAVE_MAPPER;
This->state = SPAS_CLOSED;
if (!(This->wfx = heap_alloc(sizeof(*This->wfx))))
{
......
......@@ -158,11 +158,73 @@ static void test_formats(void)
ISpMMSysAudio_Release(mmaudio);
}
static void test_audio_out(void)
{
ISpMMSysAudio *mmaudio;
GUID fmtid;
WAVEFORMATEX *wfx = NULL;
UINT devid;
HRESULT hr;
if (waveOutGetNumDevs() == 0) {
skip("no wave out devices.\n");
return;
}
hr = CoCreateInstance(&CLSID_SpMMAudioOut, NULL, CLSCTX_INPROC_SERVER,
&IID_ISpMMSysAudio, (void **)&mmaudio);
ok(hr == S_OK, "failed to create SPMMAudioOut instance: %#lx.\n", hr);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_CLOSED, 0);
ok(hr == S_OK, "got %#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));
ok(wfx != NULL, "wfx == NULL.\n");
hr = ISpMMSysAudio_SetFormat(mmaudio, &fmtid, wfx);
ok(hr == S_OK, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetDeviceId(mmaudio, WAVE_MAPPER);
ok(hr == S_OK, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_RUN, 0);
ok(hr == S_OK, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetDeviceId(mmaudio, WAVE_MAPPER);
ok(hr == S_OK, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetDeviceId(mmaudio, 0);
ok(hr == SPERR_DEVICE_BUSY, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetFormat(mmaudio, &fmtid, wfx);
ok(hr == S_OK, "got %#lx.\n", hr);
wfx->nChannels = wfx->nChannels == 1 ? 2 : 1;
wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nChannels * wfx->wBitsPerSample / 8;
wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8;
hr = ISpMMSysAudio_SetFormat(mmaudio, &fmtid, wfx);
ok(hr == SPERR_DEVICE_BUSY, "got %#lx.\n", hr);
devid = 0xdeadbeef;
hr = ISpMMSysAudio_GetDeviceId(mmaudio, &devid);
ok(hr == S_OK, "got %#lx.\n", hr);
ok(devid == WAVE_MAPPER, "got %#x.\n", devid);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_CLOSED, 0);
ok(hr == S_OK, "got %#lx.\n", hr);
CoTaskMemFree(wfx);
ISpMMSysAudio_Release(mmaudio);
}
START_TEST(mmaudio)
{
CoInitialize(NULL);
test_interfaces();
test_device_id();
test_formats();
test_audio_out();
CoUninitialize();
}
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