mmdevapi: Implement ISimpleAudioVolume::{Set, Get}Mute.

oldstable
Andrew Eikum 2011-06-20 09:31:51 -05:00 committed by Alexandre Julliard
parent c6312990ab
commit 0085689f5d
5 changed files with 128 additions and 45 deletions

View File

@ -556,16 +556,16 @@ static void test_simplevolume(void)
mute = TRUE;
hr = ISimpleAudioVolume_GetMute(sav, &mute);
todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
todo_wine ok(mute == FALSE, "Session is already muted\n");
ok(hr == S_OK, "GetMute failed: %08x\n", hr);
ok(mute == FALSE, "Session is already muted\n");
hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
todo_wine ok(hr == S_OK, "SetMute failed: %08x\n", hr);
ok(hr == S_OK, "SetMute failed: %08x\n", hr);
mute = FALSE;
hr = ISimpleAudioVolume_GetMute(sav, &mute);
todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
todo_wine ok(mute == TRUE, "Session should have been muted\n");
ok(hr == S_OK, "GetMute failed: %08x\n", hr);
ok(mute == TRUE, "Session should have been muted\n");
hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
@ -576,11 +576,11 @@ static void test_simplevolume(void)
mute = FALSE;
hr = ISimpleAudioVolume_GetMute(sav, &mute);
todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
todo_wine ok(mute == TRUE, "Session should have been muted\n");
ok(hr == S_OK, "GetMute failed: %08x\n", hr);
ok(mute == TRUE, "Session should have been muted\n");
hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
todo_wine ok(hr == S_OK, "SetMute failed: %08x\n", hr);
ok(hr == S_OK, "SetMute failed: %08x\n", hr);
ISimpleAudioVolume_Release(sav);
IAudioClient_Release(ac);

View File

@ -650,6 +650,7 @@ static void test_clock(void)
CoTaskMemFree(pwfx);
IAudioClock_Release(acl);
IAudioRenderClient_Release(arc);
IAudioClient_Release(ac);
}
@ -1079,16 +1080,16 @@ static void test_simplevolume(void)
mute = TRUE;
hr = ISimpleAudioVolume_GetMute(sav, &mute);
todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
todo_wine ok(mute == FALSE, "Session is already muted\n");
ok(hr == S_OK, "GetMute failed: %08x\n", hr);
ok(mute == FALSE, "Session is already muted\n");
hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
todo_wine ok(hr == S_OK, "SetMute failed: %08x\n", hr);
ok(hr == S_OK, "SetMute failed: %08x\n", hr);
mute = FALSE;
hr = ISimpleAudioVolume_GetMute(sav, &mute);
todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
todo_wine ok(mute == TRUE, "Session should have been muted\n");
ok(hr == S_OK, "GetMute failed: %08x\n", hr);
ok(mute == TRUE, "Session should have been muted\n");
hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
@ -1099,11 +1100,11 @@ static void test_simplevolume(void)
mute = FALSE;
hr = ISimpleAudioVolume_GetMute(sav, &mute);
todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
todo_wine ok(mute == TRUE, "Session should have been muted\n");
ok(hr == S_OK, "GetMute failed: %08x\n", hr);
ok(mute == TRUE, "Session should have been muted\n");
hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
todo_wine ok(hr == S_OK, "SetMute failed: %08x\n", hr);
ok(hr == S_OK, "SetMute failed: %08x\n", hr);
ISimpleAudioVolume_Release(sav);
IAudioClient_Release(ac);

View File

@ -65,6 +65,7 @@ typedef struct _AudioSession {
float master_vol;
UINT32 channel_count;
float *channel_vols;
BOOL mute;
CRITICAL_SECTION lock;
@ -95,6 +96,7 @@ struct ACImpl {
snd_pcm_t *pcm_handle;
snd_pcm_uframes_t period_alsa, bufsize_alsa;
snd_pcm_hw_params_t *hw_params; /* does not hold state between calls */
snd_pcm_format_t alsa_format;
IMMDevice *parent;
@ -739,6 +741,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
goto exit;
}
This->alsa_format = format;
rate = fmt->nSamplesPerSec;
if((err = snd_pcm_hw_params_set_rate_near(This->pcm_handle, This->hw_params,
&rate, NULL)) < 0){
@ -1338,10 +1342,18 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
}
static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
snd_pcm_uframes_t frames)
snd_pcm_uframes_t frames, ACImpl *This)
{
snd_pcm_sframes_t written;
if(This->session->mute){
int err;
if((err = snd_pcm_format_set_silence(This->alsa_format, buf,
frames * This->fmt->nChannels)) < 0)
WARN("Setting buffer to silence failed: %d (%s)\n", err,
snd_strerror(err));
}
written = snd_pcm_writei(handle, buf, frames);
if(written < 0){
int ret;
@ -1377,7 +1389,7 @@ static void alsa_write_data(ACImpl *This)
else
to_write = This->held_frames;
written = alsa_write_best_effort(This->pcm_handle, buf, to_write);
written = alsa_write_best_effort(This->pcm_handle, buf, to_write, This);
if(written < 0){
WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
return;
@ -1395,7 +1407,7 @@ static void alsa_write_data(ACImpl *This)
if(This->held_frames){
/* wrapped and have some data back at the start to write */
written = alsa_write_best_effort(This->pcm_handle, This->local_buffer,
This->held_frames);
This->held_frames, This);
if(written < 0){
WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
return;
@ -1435,6 +1447,15 @@ static void alsa_read_data(ACImpl *This)
}
}
if(This->session->mute){
int err;
if((err = snd_pcm_format_set_silence(This->alsa_format,
This->local_buffer + pos * This->fmt->nBlockAlign,
nread)) < 0)
WARN("Setting buffer to silence failed: %d (%s)\n", err,
snd_strerror(err));
}
This->held_frames += nread;
if(This->held_frames > This->bufsize_frames){
@ -1901,7 +1922,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
snd_pcm_sframes_t written;
written = alsa_write_best_effort(This->pcm_handle, buffer,
written_frames);
written_frames, This);
if(written < 0){
LeaveCriticalSection(&This->lock);
WARN("write failed: %ld (%s)\n", written, snd_strerror(written));
@ -2580,9 +2601,14 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
AudioSession *session = This->session;
FIXME("(%p)->(%u, %p) - stub\n", session, mute, context);
TRACE("(%p)->(%u, %p)\n", session, mute, context);
return E_NOTIMPL;
if(context)
FIXME("Notifications not supported yet\n");
session->mute = mute;
return S_OK;
}
static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
@ -2591,12 +2617,14 @@ static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
AudioSession *session = This->session;
FIXME("(%p)->(%p) - stub\n", session, mute);
TRACE("(%p)->(%p)\n", session, mute);
if(!mute)
return NULL_PTR_ERR;
return E_NOTIMPL;
*mute = session->mute;
return S_OK;
}
static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl =

View File

@ -82,6 +82,7 @@ typedef struct _AudioSession {
float master_vol;
UINT32 channel_count;
float *channel_vols;
BOOL mute;
CRITICAL_SECTION lock;
@ -2314,8 +2315,11 @@ static HRESULT ca_setvol(ACImpl *This, UINT32 index)
return ret;
}
level = This->session->master_vol * This->session->channel_vols[index] *
This->vols[index];
if(This->session->mute)
level = 0;
else
level = This->session->master_vol *
This->session->channel_vols[index] * This->vols[index];
sc = AudioQueueSetParameter(This->aqueue, kAudioQueueParam_Volume, level);
if(sc != noErr){
@ -2422,9 +2426,20 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
AudioSession *session = This->session;
FIXME("(%p)->(%u, %p) - stub\n", session, mute, context);
TRACE("(%p)->(%u, %p)\n", session, mute, context);
return E_NOTIMPL;
if(context)
FIXME("Notifications not supported yet\n");
EnterCriticalSection(&session->lock);
session->mute = mute;
ca_session_setvol(session, -1);
LeaveCriticalSection(&session->lock);
return S_OK;
}
static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
@ -2433,12 +2448,14 @@ static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
AudioSession *session = This->session;
FIXME("(%p)->(%p) - stub\n", session, mute);
TRACE("(%p)->(%p)\n", session, mute);
if(!mute)
return NULL_PTR_ERR;
return E_NOTIMPL;
*mute = session->mute;
return S_OK;
}
static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl =

View File

@ -79,6 +79,7 @@ typedef struct _AudioSession {
float master_vol;
UINT32 channel_count;
float *channel_vols;
BOOL mute;
CRITICAL_SECTION lock;
@ -1105,6 +1106,18 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
return S_OK;
}
static void oss_silence_buffer(ACImpl *This, BYTE *buf, UINT32 frames)
{
WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
(This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
This->fmt->wBitsPerSample == 8)
memset(buf, 128, frames * This->fmt->nBlockAlign);
else
memset(buf, 0, frames * This->fmt->nBlockAlign);
}
static void oss_write_data(ACImpl *This)
{
ssize_t written;
@ -1118,6 +1131,9 @@ static void oss_write_data(ACImpl *This)
else
to_write = This->held_frames;
if(This->session->mute)
oss_silence_buffer(This, buf, to_write);
written = write(This->fd, buf, to_write * This->fmt->nBlockAlign);
if(written < 0){
WARN("write failed: %d (%s)\n", errno, strerror(errno));
@ -1137,6 +1153,10 @@ static void oss_write_data(ACImpl *This)
if(This->held_frames){
/* wrapped and have some data back at the start to write */
if(This->session->mute)
oss_silence_buffer(This, This->local_buffer, This->held_frames);
written = write(This->fd, This->local_buffer,
This->held_frames * This->fmt->nBlockAlign);
if(written < 0){
@ -1192,7 +1212,7 @@ static void CALLBACK oss_period_callback(void *user, BOOLEAN timer)
EnterCriticalSection(&This->lock);
if(This->dataflow == eRender)
if(This->dataflow == eRender && This->held_frames)
oss_write_data(This);
else if(This->dataflow == eCapture)
oss_read_data(This);
@ -1599,16 +1619,8 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
else
buffer = This->tmp_buffer;
if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
(This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
This->fmt->wBitsPerSample == 8)
memset(buffer, 128, written_frames * This->fmt->nBlockAlign);
else
memset(buffer, 0, written_frames * This->fmt->nBlockAlign);
}
if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
oss_silence_buffer(This, buffer, written_frames);
if(This->held_frames){
if(This->buf_state == LOCKED_WRAPPED)
@ -1619,6 +1631,9 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
ssize_t w_bytes;
UINT32 w_frames;
if(This->session->mute)
oss_silence_buffer(This, buffer, written_frames);
w_bytes = write(This->fd, buffer,
written_frames * This->fmt->nBlockAlign);
if(w_bytes < 0){
@ -2369,9 +2384,29 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
AudioSession *session = This->session;
FIXME("(%p)->(%u, %p) - stub\n", session, mute, context);
TRACE("(%p)->(%u, %p)\n", session, mute, context);
return E_NOTIMPL;
EnterCriticalSection(&session->lock);
if(!mute && session->mute){
ACImpl *client;
session->mute = mute;
LIST_FOR_EACH_ENTRY(client, &session->clients, ACImpl, entry){
EnterCriticalSection(&client->lock);
if(ioctl(client->fd, SNDCTL_DSP_SKIP) < 0)
WARN("Error calling DSP_SKIP: %d (%s)\n", errno,
strerror(errno));
oss_write_data(client);
LeaveCriticalSection(&client->lock);
}
}else
session->mute = mute;
LeaveCriticalSection(&session->lock);
return S_OK;
}
static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
@ -2380,12 +2415,14 @@ static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
AudioSession *session = This->session;
FIXME("(%p)->(%p) - stub\n", session, mute);
TRACE("(%p)->(%p)\n", session, mute);
if(!mute)
return NULL_PTR_ERR;
return E_NOTIMPL;
*mute = This->session->mute;
return S_OK;
}
static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl =