sapi: Implement ISpMMSysAudio::Write.

This commit is contained in:
Shaun Ren 2023-05-30 23:58:32 -04:00 committed by Alexandre Julliard
parent 7bced2878a
commit ef730b6e41
2 changed files with 102 additions and 6 deletions

View file

@ -400,9 +400,58 @@ static HRESULT WINAPI mmsysaudio_Read(ISpMMSysAudio *iface, void *pv, ULONG cb,
static HRESULT WINAPI mmsysaudio_Write(ISpMMSysAudio *iface, const void *pv, ULONG cb, ULONG *cb_written)
{
FIXME("(%p, %p, %lu, %p): stub.\n", iface, pv, cb, cb_written);
struct mmaudio *This = impl_from_ISpMMSysAudio(iface);
HRESULT hr = S_OK;
WAVEHDR *buf;
return E_NOTIMPL;
TRACE("(%p, %p, %lu, %p).\n", iface, pv, cb, cb_written);
if (This->flow != FLOW_OUT)
return STG_E_ACCESSDENIED;
if (cb_written)
*cb_written = 0;
EnterCriticalSection(&This->cs);
if (This->state == SPAS_CLOSED || This->state == SPAS_STOP)
{
LeaveCriticalSection(&This->cs);
return SP_AUDIO_STOPPED;
}
if (!(buf = heap_alloc(sizeof(WAVEHDR) + cb)))
{
LeaveCriticalSection(&This->cs);
return E_OUTOFMEMORY;
}
memcpy((char *)(buf + 1), pv, cb);
buf->lpData = (char *)(buf + 1);
buf->dwBufferLength = cb;
buf->dwFlags = 0;
if (waveOutPrepareHeader(This->hwave.out, buf, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
LeaveCriticalSection(&This->cs);
heap_free(buf);
return E_FAIL;
}
waveOutWrite(This->hwave.out, buf, sizeof(WAVEHDR));
EnterCriticalSection(&This->pending_cs);
++This->pending_buf_count;
TRACE("pending_buf_count = %Iu\n", This->pending_buf_count);
LeaveCriticalSection(&This->pending_cs);
ResetEvent(This->event);
LeaveCriticalSection(&This->cs);
if (cb_written)
*cb_written = cb;
return hr;
}
static HRESULT WINAPI mmsysaudio_Seek(ISpMMSysAudio *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)

View file

@ -163,7 +163,10 @@ static void test_audio_out(void)
ISpMMSysAudio *mmaudio;
GUID fmtid;
WAVEFORMATEX *wfx = NULL;
WAVEFORMATEX wfx2;
UINT devid;
char *buf = NULL;
ULONG written;
HRESULT hr;
if (waveOutGetNumDevs() == 0) {
@ -182,6 +185,8 @@ static void test_audio_out(void)
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");
ok(wfx->wFormatTag == WAVE_FORMAT_PCM, "got %u.\n", wfx->wFormatTag);
ok(wfx->cbSize == 0, "got %u.\n", wfx->cbSize);
hr = ISpMMSysAudio_SetFormat(mmaudio, &fmtid, wfx);
ok(hr == S_OK, "got %#lx.\n", hr);
@ -201,10 +206,12 @@ static void test_audio_out(void)
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);
memcpy(&wfx2, wfx, sizeof(wfx2));
wfx2.nChannels = wfx->nChannels == 1 ? 2 : 1;
wfx2.nAvgBytesPerSec = wfx2.nSamplesPerSec * wfx2.nChannels * wfx2.wBitsPerSample / 8;
wfx2.nBlockAlign = wfx2.nChannels * wfx2.wBitsPerSample / 8;
hr = ISpMMSysAudio_SetFormat(mmaudio, &fmtid, &wfx2);
ok(hr == SPERR_DEVICE_BUSY, "got %#lx.\n", hr);
devid = 0xdeadbeef;
@ -215,7 +222,47 @@ static void test_audio_out(void)
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_CLOSED, 0);
ok(hr == S_OK, "got %#lx.\n", hr);
buf = calloc(1, wfx->nAvgBytesPerSec);
ok(buf != NULL, "failed to allocate buffer.\n");
hr = ISpMMSysAudio_Write(mmaudio, buf, wfx->nAvgBytesPerSec, NULL);
ok(hr == SP_AUDIO_STOPPED, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_STOP, 0);
todo_wine ok(hr == S_OK, "got %#lx.\n", hr);
if (hr == S_OK)
{
hr = ISpMMSysAudio_Write(mmaudio, buf, wfx->nAvgBytesPerSec, NULL);
ok(hr == SP_AUDIO_STOPPED, "got %#lx.\n", hr);
}
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_CLOSED, 0);
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_Write(mmaudio, buf, wfx->nAvgBytesPerSec, NULL);
ok(hr == S_OK, "got %#lx.\n", hr);
Sleep(200);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_CLOSED, 0);
ok(hr == S_OK, "got %#lx.\n", hr);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_RUN, 0);
ok(hr == S_OK, "got %#lx.\n", hr);
written = 0xdeadbeef;
hr = ISpMMSysAudio_Write(mmaudio, buf, wfx->nAvgBytesPerSec * 200 / 1000, &written);
ok(hr == S_OK, "got %#lx.\n", hr);
ok(written == wfx->nAvgBytesPerSec * 200 / 1000, "got %lu.\n", written);
hr = ISpMMSysAudio_SetState(mmaudio, SPAS_CLOSED, 0);
ok(hr == S_OK, "got %#lx.\n", hr);
CoTaskMemFree(wfx);
free(buf);
ISpMMSysAudio_Release(mmaudio);
}