Commit f6d9780e authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: separate volume and mute callbacks

parent c45103a6
......@@ -134,8 +134,6 @@ typedef int32_t vlc_fixed_t;
/* FIXME to remove once aout.h is cleaned a bit more */
#include <vlc_block.h>
typedef int (*aout_volume_cb) (audio_output_t *, float, bool);
/** Audio output object */
struct audio_output
{
......@@ -150,7 +148,8 @@ struct audio_output
callback (optional, may be NULL) */
void (* pf_flush)( audio_output_t *, bool ); /**< Flush/drain callback
(optional, may be NULL) */
aout_volume_cb pf_volume_set; /**< Volume setter (or NULL) */
int (*volume_set)(audio_output_t *, float); /**< Volume setter (or NULL) */
int (*mute_set)(audio_output_t *, bool); /**< Mute setter (or NULL) */
struct {
void (*time_report)(audio_output_t *, mtime_t);
......@@ -224,12 +223,15 @@ VLC_API void aout_FormatPrint(vlc_object_t *, const char *,
VLC_API const char * aout_FormatPrintChannels( const audio_sample_format_t * ) VLC_USED;
VLC_API void aout_VolumeSoftInit( audio_output_t * );
VLC_API void aout_VolumeHardInit( audio_output_t *, aout_volume_cb, bool );
static inline void aout_VolumeHardSet(audio_output_t *aout, float v, bool m)
static inline void aout_VolumeReport(audio_output_t *aout, float volume)
{
aout->event.volume_report(aout, volume);
}
static inline void aout_MuteReport(audio_output_t *aout, bool mute)
{
aout->event.volume_report(aout, v);
aout->event.mute_report(aout, m);
aout->event.mute_report(aout, mute);
}
static inline void aout_TimeReport(audio_output_t *aout, mtime_t date)
......
......@@ -516,7 +516,8 @@ static int Open (vlc_object_t *obj)
{
aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
aout->format.i_frame_length = A52_FRAME_NB;
aout->pf_volume_set = NULL;
aout->volume_set = NULL;
aout->mute_set = NULL;
}
else
{
......
......@@ -62,6 +62,8 @@ struct aout_sys_t
void (*drain) (void *opaque);
int (*set_volume) (void *opaque, float vol, bool mute);
void (*cleanup) (void *opaque);
float volume;
bool mute;
};
static void Play (audio_output_t *aout, block_t *block)
......@@ -91,11 +93,20 @@ static void Flush (audio_output_t *aout, bool wait)
cb (sys->opaque);
}
static int VolumeSet (audio_output_t *aout, float vol, bool mute)
static int VolumeSet (audio_output_t *aout, float vol)
{
aout_sys_t *sys = aout->sys;
return sys->set_volume (sys->opaque, vol, mute) ? -1 : 0;
sys->volume = vol;
return sys->set_volume (sys->opaque, vol, sys->mute) ? -1 : 0;
}
static int MuteSet (audio_output_t *aout, bool mute)
{
aout_sys_t *sys = aout->sys;
sys->mute = mute;
return sys->set_volume (sys->opaque, sys->volume, mute) ? -1 : 0;
}
typedef int (*vlc_audio_format_cb) (void **, char *, unsigned *, unsigned *);
......@@ -116,6 +127,8 @@ static int Open (vlc_object_t *obj)
sys->drain = var_InheritAddress (obj, "amem-drain");
sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
sys->cleanup = NULL; /* defer */
sys->volume = 1.;
sys->mute = false;
if (sys->play == NULL)
goto error;
......@@ -203,7 +216,10 @@ static int Open (vlc_object_t *obj)
aout->pf_pause = Pause;
aout->pf_flush = Flush;
if (sys->set_volume != NULL)
aout->pf_volume_set = VolumeSet;
{
aout->volume_set = VolumeSet;
aout->mute_set = MuteSet;
}
else
aout_VolumeSoftInit (aout);
return VLC_SUCCESS;
......
......@@ -787,7 +787,8 @@ static int OpenSPDIF( audio_output_t * p_aout )
p_aout->format.i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
aout_FormatPrepare( &p_aout->format );
aout_PacketInit( p_aout, &p_sys->packet, A52_FRAME_NB );
p_aout->pf_volume_set = NULL;
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
/* Add IOProc callback */
err = AudioDeviceCreateIOProcID( p_sys->i_selected_dev,
......
......@@ -75,7 +75,12 @@ struct aout_sys_t
LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound
* takes care of mixing all the
* secondary buffers into the primary) */
LONG volume;
struct
{
LONG volume;
LONG mb;
bool mute;
} volume;
notification_thread_t notif; /* DirectSoundThread id */
......@@ -96,7 +101,8 @@ struct aout_sys_t
static int OpenAudio ( vlc_object_t * );
static void CloseAudio ( vlc_object_t * );
static void Play ( audio_output_t *, block_t * );
static int VolumeSet ( audio_output_t *, float, bool );
static int VolumeSet ( audio_output_t *, float );
static int MuteSet ( audio_output_t *, bool );
/* local functions */
static void Probe ( audio_output_t * );
......@@ -232,8 +238,6 @@ static int OpenAudio( vlc_object_t *p_this )
}
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
p_aout->sys->volume = -1;
p_aout->pf_volume_set = NULL;
}
else
{
......@@ -287,9 +291,10 @@ static int OpenAudio( vlc_object_t *p_this )
/* Calculate the frame size in bytes */
aout_FormatPrepare( &p_aout->format );
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
aout_VolumeHardInit( p_aout, VolumeSet, true );
}
p_aout->sys->volume.volume = -1;
/* Now we need to setup our DirectSound play notification structure */
vlc_atomic_set(&p_aout->sys->notif.abort, 0);
p_aout->sys->notif.event = CreateEvent( 0, FALSE, FALSE, 0 );
......@@ -313,6 +318,19 @@ static int OpenAudio( vlc_object_t *p_this )
p_aout->pf_pause = aout_PacketPause;
p_aout->pf_flush = aout_PacketFlush;
/* Volume */
if( val.i_int == AOUT_VAR_SPDIF )
{
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
}
else
{
p_aout->sys->volume.mb = 0;
p_aout->sys->volume.mute = false;
p_aout->volume_set = VolumeSet;
p_aout->mute_set = MuteSet;
}
return VLC_SUCCESS;
error:
......@@ -573,12 +591,10 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
p_aout->pf_play = aout_PacketPlay;
}
/*****************************************************************************
* VolumeSet: change audio device volume
*****************************************************************************/
static int VolumeSet( audio_output_t *p_aout, float vol, bool mute )
static int VolumeSet( audio_output_t *p_aout, float vol )
{
aout_sys_t *sys = p_aout->sys;
int ret = 0;
/* Convert UI volume to linear factor (cube) */
vol = vol * vol * vol;
......@@ -589,15 +605,32 @@ static int VolumeSet( audio_output_t *p_aout, float vol, bool mute )
/* Clamp to allowed DirectSound range */
static_assert( DSBVOLUME_MIN < DSBVOLUME_MAX, "DSBVOLUME_* confused" );
if( mb >= DSBVOLUME_MAX )
{
mb = DSBVOLUME_MAX;
ret = -1;
}
if( mb <= DSBVOLUME_MIN )
mb = DSBVOLUME_MIN;
InterlockedExchange(&sys->volume, mute ? DSBVOLUME_MIN : mb);
sys->volume.mb = mb;
if (!sys->volume.mute)
InterlockedExchange(&sys->volume.volume, mb);
/* Convert back to UI volume */
vol = cbrtf(powf(10.f, ((float)mb) / -2000.f));
aout_VolumeHardSet( p_aout, vol, mute );
aout_VolumeReport( p_aout, vol );
return ret;
}
static int MuteSet( audio_output_t *p_aout, bool mute )
{
aout_sys_t *sys = p_aout->sys;
sys->volume.mute = mute;
InterlockedExchange(&sys->volume.volume,
mute ? DSBVOLUME_MIN : sys->volume.mb);
aout_MuteReport( p_aout, mute );
return 0;
}
......@@ -1064,7 +1097,7 @@ static void* DirectSoundThread( void *data )
int i;
/* Update volume if required */
LONG volume = InterlockedExchange( &p_aout->sys->volume, -1 );
LONG volume = InterlockedExchange( &p_aout->sys->volume.volume, -1 );
if( unlikely(volume != -1) )
IDirectSoundBuffer_SetVolume( p_aout->sys->p_dsbuffer, volume );
......
......@@ -194,7 +194,8 @@ static int Open( vlc_object_t * p_this )
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB;
}
p_aout->pf_volume_set = NULL;
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
/* Channels number */
i_channels = var_CreateGetInteger( p_this, "audiofile-channels" );
......
......@@ -368,7 +368,8 @@ static int Open( vlc_object_t *p_this )
p_aout->format.i_frame_length = A52_FRAME_NB;
aout_PacketInit( p_aout, &p_sys->packet, A52_FRAME_NB );
p_aout->pf_volume_set = NULL;
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
}
else
{
......
......@@ -481,7 +481,8 @@ static void sink_input_info_cb(pa_context *ctx, const pa_sink_input_info *i,
pa_volume_t volume = pa_cvolume_max(&i->volume);
volume = pa_sw_volume_divide(volume, sys->base_volume);
aout_VolumeHardSet(aout, (float)volume / PA_VOLUME_NORM, i->mute);
aout_VolumeReport(aout, (float)volume / PA_VOLUME_NORM);
aout_MuteReport(aout, i->mute);
}
......@@ -601,7 +602,7 @@ static void Flush(audio_output_t *aout, bool wait)
pa_threaded_mainloop_unlock(sys->mainloop);
}
static int VolumeSet(audio_output_t *aout, float vol, bool mute)
static int VolumeSet(audio_output_t *aout, float vol)
{
aout_sys_t *sys = aout->sys;
pa_operation *op;
......@@ -626,6 +627,18 @@ static int VolumeSet(audio_output_t *aout, float vol, bool mute)
op = pa_context_set_sink_input_volume(sys->context, idx, &cvolume, NULL, NULL);
if (likely(op != NULL))
pa_operation_unref(op);
pa_threaded_mainloop_unlock(sys->mainloop);
return 0;
}
static int MuteSet(audio_output_t *aout, bool mute)
{
aout_sys_t *sys = aout->sys;
pa_operation *op;
uint32_t idx = pa_stream_get_index(sys->stream);
pa_threaded_mainloop_lock(sys->mainloop);
op = pa_context_set_sink_input_mute(sys->context, idx, mute, NULL, NULL);
if (likely(op != NULL))
pa_operation_unref(op);
......@@ -946,7 +959,8 @@ static int Open(vlc_object_t *obj)
aout->pf_play = Play;
aout->pf_pause = Pause;
aout->pf_flush = Flush;
aout_VolumeHardInit (aout, VolumeSet, false);
aout->volume_set = VolumeSet;
aout->mute_set = MuteSet;
return VLC_SUCCESS;
fail:
......
......@@ -179,7 +179,7 @@ static void Flush(audio_output_t *aout, bool wait)
Leave();
}
static int SimpleVolumeSet(audio_output_t *aout, float vol, bool mute)
static int SimpleVolumeSet(audio_output_t *aout, float vol)
{
aout_sys_t *sys = aout->sys;
HRESULT hr;
......@@ -188,26 +188,24 @@ static int SimpleVolumeSet(audio_output_t *aout, float vol, bool mute)
vol = 1.;
Enter();
/* NOTE: better change volume while muted (if mute is toggled) */
if (mute)
{
hr = ISimpleAudioVolume_SetMute(sys->volume.simple, true, NULL);
if (FAILED(hr))
msg_Warn(aout, "cannot mute session (error 0x%lx)", hr);
}
hr = ISimpleAudioVolume_SetMasterVolume(sys->volume.simple, vol, NULL);
if (FAILED(hr))
msg_Warn(aout, "cannot set session volume (error 0x%lx)", hr);
Leave();
return FAILED(hr) ? -1 : 0;
}
if (!mute)
{
hr = ISimpleAudioVolume_SetMute(sys->volume.simple, false, NULL);
if (FAILED(hr))
msg_Warn(aout, "cannot unmute session (error 0x%lx)", hr);
}
static int SimpleMuteSet(audio_output_t *aout, bool mute)
{
aout_sys_t *sys = aout->sys;
HRESULT hr;
Enter();
hr = ISimpleAudioVolume_SetMute(sys->volume.simple, mute, NULL);
if (FAILED(hr))
msg_Warn(aout, "cannot mute session (error 0x%lx)", hr);
Leave();
return 0;
return FAILED(hr) ? -1 : 0;
}
static void vlc_ToWave(WAVEFORMATEXTENSIBLE *restrict wf,
......@@ -477,7 +475,10 @@ static int Open(vlc_object_t *obj)
aout->pf_pause = Pause;
aout->pf_flush = Flush;
/*if (AOUT_FMT_LINEAR(&format) && !exclusive)*/
aout_VolumeHardInit(aout, SimpleVolumeSet, false);
{
aout->volume_set = SimpleVolumeSet;
aout->mute_set = SimpleMuteSet;
}
Leave();
return VLC_SUCCESS;
error:
......
......@@ -68,7 +68,8 @@ static int PlayWaveOut ( audio_output_t *, HWAVEOUT, WAVEHDR *,
static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR );
static void* WaveOutThread( void * );
static int VolumeSet( audio_output_t *, float, bool );
static int VolumeSet( audio_output_t *, float );
static int MuteSet( audio_output_t *, bool );
static int WaveOutClearDoneBuffers(aout_sys_t *p_sys);
......@@ -140,6 +141,9 @@ struct aout_sys_t
uint8_t *p_silence_buffer; /* buffer we use to play silence */
float volume;
bool mute;
bool b_chan_reorder; /* do we need channel reordering */
int pi_chan_table[AOUT_CHAN_MAX];
};
......@@ -169,7 +173,6 @@ static int Open( vlc_object_t *p_this )
*/
ReloadWaveoutDevices( p_this, "waveout-audio-device", val, val, NULL);
/*
check for configured audio device!
*/
......@@ -246,7 +249,8 @@ static int Open( vlc_object_t *p_this )
p_aout->format.i_bytes_per_frame;
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
p_aout->pf_volume_set = NULL;
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
}
else
{
......@@ -293,16 +297,22 @@ static int Open( vlc_object_t *p_this )
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
#ifndef UNDER_CE
/* Check for hardware volume support */
if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout,
&wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR
&& (wocaps.dwSupport & WAVECAPS_VOLUME) )
aout_VolumeHardInit( p_aout, VolumeSet, false /* ?? */ );
{
p_aout->volume_set = VolumeSet;
p_aout->mute_set = MuteSet;
p_aout->sys->volume = 0xffff.fp0;
p_aout->sys->mute = false;
}
else
#endif
aout_VolumeSoftInit( p_aout );
}
waveOutReset( p_aout->sys->h_waveout );
/* Allocate silence buffer */
......@@ -992,26 +1002,37 @@ static void* WaveOutThread( void *data )
return NULL;
}
static int VolumeSet( audio_output_t * p_aout, float volume, bool mute )
{
#ifndef UNDER_CE
const HWAVEOUT hwo = p_aout->sys->h_waveout;
#else
const HWAVEOUT hwo = 0;
#endif
static int VolumeSet( audio_output_t *aout, float volume )
{
aout_sys_t *sys = aout->sys;
const HWAVEOUT hwo = sys->h_waveout;
const float full = 0xffff.fp0;
if( mute )
volume = 0.;
volume *= full;
if( volume >= full )
volume = full;
return -1;
sys->volume = volume;
if( sys->mute )
return 0;
uint16_t vol = lroundf(volume);
waveOutSetVolume( hwo, vol | (vol << 16) );
return 0;
}
static int MuteSet( audio_output_t * p_aout, bool mute )
{
aout_sys_t *sys = p_aout->sys;
const HWAVEOUT hwo = sys->h_waveout;
uint16_t vol = mute ? 0 : lroundf(sys->volume);
sys->mute = mute;
waveOutSetVolume( hwo, vol | (vol << 16) );
return 0;
}
#endif
/*
reload the configuration drop down list, of the Audio Devices
......
......@@ -67,7 +67,8 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
owner->volume.mixer = NULL;
aout->pf_play = aout_DecDeleteBuffer;
aout->pf_volume_set = NULL;
aout->volume_set = NULL;
aout->mute_set = NULL;
vlc_object_set_destructor (aout, aout_Destructor);
/*
......
......@@ -90,8 +90,12 @@ static int commitVolume (vlc_object_t *obj, audio_output_t *aout,
{
/* apply volume to the pipeline */
aout_lock (aout);
if (aout->pf_volume_set != NULL)
ret = aout->pf_volume_set (aout, vol, mute);
if (aout->mute_set != NULL)
ret = aout->mute_set (aout, mute);
else
ret = -1;
if (ret == 0 && aout->volume_set != NULL)
ret = aout->volume_set (aout, vol);
aout_unlock (aout);
if (ret == 0)
......
......@@ -277,7 +277,8 @@ void aout_OutputDelete (audio_output_t *aout)
aout->pf_play = aout_DecDeleteBuffer; /* gruik */
aout->pf_pause = NULL;
aout->pf_flush = NULL;
aout->pf_volume_set = NULL;
aout->volume_set = NULL;
aout->mute_set = NULL;
owner->module = NULL;
owner->volume.amp = 1.f;
owner->volume.mute = false;
......@@ -334,15 +335,11 @@ void aout_OutputFlush( audio_output_t *aout, bool wait )
/*** Volume handling ***/
/**
* Volume setter for software volume.
*/
static int aout_VolumeSoftSet (audio_output_t *aout, float volume, bool mute)
static int aout_SoftVolumeSet (audio_output_t *aout, float volume)
{
aout_owner_t *owner = aout_owner (aout);
aout_assert_locked (aout);
/* Cubic mapping from software volume to amplification factor.
* This provides a good tradeoff between low and high volume ranges.
*
......@@ -350,6 +347,14 @@ static int aout_VolumeSoftSet (audio_output_t *aout, float volume, bool mute)
* formula, be sure to update the aout_VolumeHardInit()-based plugins also.
*/
owner->volume.amp = volume * volume * volume;
return 0;
}
static int aout_SoftMuteSet (audio_output_t *aout, bool mute)
{
aout_owner_t *owner = aout_owner (aout);
aout_assert_locked (aout);
owner->volume.mute = mute;
return 0;
}
......@@ -366,26 +371,8 @@ void aout_VolumeSoftInit (audio_output_t *aout)
bool mute = var_GetBool (aout, "mute");
aout_assert_locked (aout);
aout->pf_volume_set = aout_VolumeSoftSet;
aout_VolumeSoftSet (aout, volume / (float)AOUT_VOLUME_DEFAULT, mute);
}
/**
* Configures a custom volume setter. This is used by audio outputs that can
* control the hardware volume directly and/or emulate it internally.
* @param setter volume setter callback
* @param restore apply volume from VLC configuration immediately
*/
void aout_VolumeHardInit (audio_output_t *aout, aout_volume_cb setter,
bool restore)
{
aout_assert_locked (aout);
aout->pf_volume_set = setter;
if (restore)
{
float vol = var_GetInteger (aout, "volume")
/ (float)AOUT_VOLUME_DEFAULT;
setter (aout, vol, var_GetBool (aout, "mute"));
}
aout->volume_set = aout_SoftVolumeSet;
aout->mute_set = aout_SoftMuteSet;
aout_SoftVolumeSet (aout, volume / (float)AOUT_VOLUME_DEFAULT);
aout_SoftMuteSet (aout, mute);
}
......@@ -21,7 +21,6 @@ aout_MuteToggle
aout_MuteSet
aout_MuteGet
aout_VolumeSoftInit
aout_VolumeHardInit
block_Alloc
block_FifoCount
block_FifoEmpty
......
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