mmdevapi: Implement ISimpleAudioVolume::{Set, Get}Mute.
This commit is contained in:
parent
c6312990ab
commit
0085689f5d
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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 =
|
||||
|
|
Loading…
Reference in New Issue