aout: match module life cycle to the object life cycle

In other words, keep the module loaded whenever the aout exists.
This commit is contained in:
Rémi Denis-Courmont 2012-10-31 22:22:14 +02:00
parent ea9c43c2fa
commit 10dd2acc08
3 changed files with 69 additions and 82 deletions

View File

@ -55,6 +55,41 @@ static int var_Copy (vlc_object_t *src, const char *name, vlc_value_t prev,
return var_Set (dst, name, value);
}
/**
* Supply or update the current custom ("hardware") volume.
* @note This only makes sense after calling aout_VolumeHardInit().
* @param volume current custom volume
*
* @warning The caller (i.e. the audio output plug-in) is responsible for
* interlocking and synchronizing call to this function and to the
* audio_output_t.volume_set callback. This ensures that VLC gets correct
* volume information (possibly with a latency).
*/
static void aout_VolumeNotify (audio_output_t *aout, float volume)
{
var_SetFloat (aout, "volume", volume);
}
static void aout_MuteNotify (audio_output_t *aout, bool mute)
{
var_SetBool (aout, "mute", mute);
}
static void aout_PolicyNotify (audio_output_t *aout, bool cork)
{
(cork ? var_IncInteger : var_DecInteger) (aout->p_parent, "corks");
}
static int aout_GainNotify (audio_output_t *aout, float gain)
{
aout_owner_t *owner = aout_owner (aout);
aout_assert_locked (aout);
aout_volume_SetVolume (owner->volume, gain);
/* XXX: ideally, return -1 if format cannot be amplified */
return 0;
}
#undef aout_New
/*****************************************************************************
* aout_New: initialize aout structure
@ -70,12 +105,33 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
aout_owner_t *owner = aout_owner (aout);
vlc_mutex_init (&owner->lock);
owner->module = NULL;
vlc_object_set_destructor (aout, aout_Destructor);
owner->input = NULL;
/* Audio output module callbacks */
var_Create (aout, "volume", VLC_VAR_FLOAT);
var_AddCallback (aout, "volume", var_Copy, p_parent);
var_Create (aout, "mute", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
var_AddCallback (aout, "mute", var_Copy, p_parent);
aout->event.volume_report = aout_VolumeNotify;
aout->event.mute_report = aout_MuteNotify;
aout->event.policy_report = aout_PolicyNotify;
aout->event.gain_request = aout_GainNotify;
/* Audio output module initialization */
aout->start = NULL;
aout->stop = NULL;
aout->volume_set = NULL;
aout->mute_set = NULL;
vlc_object_set_destructor (aout, aout_Destructor);
owner->module = module_need (aout, "audio output", "$aout", false);
if (owner->module == NULL)
{
msg_Err (aout, "no suitable audio output module");
vlc_object_release (aout);
return NULL;
}
/*
* Persistent audio output variables
@ -84,11 +140,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
module_config_t *cfg;
char *str;
var_Create (aout, "volume", VLC_VAR_FLOAT);
var_AddCallback (aout, "volume", var_Copy, p_parent);
var_Create (aout, "mute", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
var_AddCallback (aout, "mute", var_Copy, p_parent);
/* Visualizations */
var_Create (aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE);
text.psz_string = _("Visualizations");
@ -161,7 +212,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
text.psz_string = _("Audio visualizations");
var_Change (aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL);
/* Replay gain */
var_Create (aout, "audio-replay-gain-mode",
VLC_VAR_STRING | VLC_VAR_DOINHERIT );
@ -184,7 +234,12 @@ void aout_Destroy (audio_output_t *aout)
{
aout_owner_t *owner = aout_owner (aout);
assert (owner->module == NULL);
aout_lock (aout);
module_unneed (aout, owner->module);
/* Protect against late call from intf.c */
aout->volume_set = NULL;
aout->mute_set = NULL;
aout_unlock (aout);
var_DelCallback (aout, "mute", var_Copy, aout->p_parent);
var_SetFloat (aout, "volume", -1.f);

View File

@ -71,7 +71,6 @@ int aout_DecNew( audio_output_t *p_aout,
/* TODO: reduce lock scope depending on decoder's real need */
aout_lock( p_aout );
assert (owner->module == NULL);
/* Create the audio output stream */
var_Destroy( p_aout, "audio-device" );
@ -117,11 +116,9 @@ void aout_DecDelete (audio_output_t *p_aout)
aout_InputDelete (p_aout, input);
owner->input = NULL;
if (likely(owner->module != NULL))
{
aout_OutputDelete( p_aout );
aout_volume_Delete (owner->volume);
}
aout_OutputDelete( p_aout );
aout_volume_Delete (owner->volume);
var_Destroy( p_aout, "audio-device" );
var_Destroy( p_aout, "stereo-mode" );

View File

@ -25,52 +25,13 @@
# include "config.h"
#endif
#include <math.h>
#include <vlc_common.h>
#include <vlc_aout.h>
#include <vlc_aout_intf.h>
#include <vlc_cpu.h>
#include <vlc_modules.h>
#include "libvlc.h"
#include "aout_internal.h"
/**
* Supply or update the current custom ("hardware") volume.
* @note This only makes sense after calling aout_VolumeHardInit().
* @param volume current custom volume
*
* @warning The caller (i.e. the audio output plug-in) is responsible for
* interlocking and synchronizing call to this function and to the
* audio_output_t.volume_set callback. This ensures that VLC gets correct
* volume information (possibly with a latency).
*/
static void aout_OutputVolumeReport (audio_output_t *aout, float volume)
{
var_SetFloat (aout, "volume", volume);
}
static void aout_OutputMuteReport (audio_output_t *aout, bool mute)
{
var_SetBool (aout, "mute", mute);
}
static void aout_OutputPolicyReport (audio_output_t *aout, bool cork)
{
(cork ? var_IncInteger : var_DecInteger) (aout->p_parent, "corks");
}
static int aout_OutputGainRequest (audio_output_t *aout, float gain)
{
aout_owner_t *owner = aout_owner (aout);
aout_assert_locked (aout);
aout_volume_SetVolume (owner->volume, gain);
/* XXX: ideally, return -1 if format cannot be amplified */
return 0;
}
/*****************************************************************************
* aout_OutputNew : allocate a new output and rework the filter pipeline
*****************************************************************************
@ -85,24 +46,9 @@ int aout_OutputNew (audio_output_t *aout, const audio_sample_format_t *fmtp)
aout_assert_locked (aout);
aout->event.volume_report = aout_OutputVolumeReport;
aout->event.mute_report = aout_OutputMuteReport;
aout->event.policy_report = aout_OutputPolicyReport;
aout->event.gain_request = aout_OutputGainRequest;
/* Find the best output plug-in. */
owner->module = module_need (aout, "audio output", "$aout", false);
if (owner->module == NULL)
{
msg_Err (aout, "no suitable audio output module");
return -1;
}
if (aout->start (aout, &fmt))
{
msg_Err (aout, "module not functional");
module_unneed (aout, owner->module);
owner->module = NULL;
return -1;
}
@ -195,8 +141,7 @@ int aout_OutputNew (audio_output_t *aout, const audio_sample_format_t *fmtp)
&owner->mixer_format, &fmt) < 0)
{
msg_Err (aout, "couldn't create audio output pipeline");
module_unneed (aout, owner->module);
owner->module = NULL;
aout_OutputDelete (aout);
return -1;
}
return 0;
@ -211,16 +156,9 @@ void aout_OutputDelete (audio_output_t *aout)
aout_assert_locked (aout);
if (owner->module == NULL)
return;
var_DelCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
if (aout->stop != NULL)
aout->stop (aout);
module_unneed (aout, owner->module);
aout->volume_set = NULL;
aout->mute_set = NULL;
owner->module = NULL;
aout_FiltersDestroyPipeline (owner->filters, owner->nb_filters);
}
@ -243,10 +181,7 @@ void aout_OutputPlay (audio_output_t *aout, block_t *block)
return;
}
if (likely(owner->module != NULL))
aout->play (aout, block, &drift);
else
block_Release (block);
aout->play (aout, block, &drift);
/**
* Notifies the audio input of the drift from the requested audio
* playback timestamp (@ref block_t.i_pts) to the anticipated playback time