/* FIXME to remove once aout.h is cleaned a bit more */
#include <vlc_block.h>
-struct aout_mixer_t;
-
typedef int (*aout_volume_cb) (audio_output_t *, float, bool);
/** Audio output object */
{
VLC_COMMON_MEMBERS
- /* Lock for volume variables (FIXME: should be in input manager) */
- vlc_mutex_t volume_lock;
vlc_mutex_t lock;
- /* Input streams & pre-filters */
- aout_input_t * p_input;
-
- /* Mixer */
- audio_sample_format_t mixer_format;
- float mixer_multiplier;
- struct audio_mixer *mixer;
-
audio_sample_format_t format; /**< Output format (plugin can modify it
only when succesfully probed and not afterward) */
- /* Indicates whether the audio output is currently starving, to avoid
- * printing a 1,000 "output is starving" messages. */
- bool b_starving;
-
- /* post-filters */
- filter_t * pp_filters[AOUT_MAX_FILTERS];
- int i_nb_filters;
-
aout_fifo_t fifo;
- struct module_t *module; /**< Output plugin */
struct aout_sys_t *sys; /**< Output plugin private data */
void (*pf_play)( audio_output_t * ); /**< Audio buffer callback */
void (* pf_pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume
/* */
aout_fifo_t fifo;
- };
+};
+
+typedef struct
+{
+ module_t *module; /**< Output plugin (or NULL if inactive) */
+ aout_input_t *input;
+
+ struct
+ {
+ vlc_mutex_t lock;
+ float multiplier; /**< Software volume amplification multiplier */
+ struct audio_mixer *mixer; /**< Software volume plugin */
+ } volume; /**< Volume and gain management (FIXME: input manager?) */
+
+ audio_sample_format_t mixer_format;
+
+ /* Filters between mixer and output */
+ filter_t *filters[AOUT_MAX_FILTERS];
+ int nb_filters;
+
+ /* Indicates whether the audio output is currently starving, to avoid
+ * printing a 1,000 "output is starving" messages. */
+ bool b_starving;
+} aout_owner_t;
+
+typedef struct
+{
+ audio_output_t output;
+ aout_owner_t owner;
+} aout_instance_t;
+
+static inline aout_owner_t *aout_owner (audio_output_t *aout)
+{
+ return &((aout_instance_t *)aout)->owner;
+}
/****************************************************************************
* Prototypes
static inline void aout_lock_volume( audio_output_t *p_aout )
{
aout_lock_check( VOLUME_LOCK );
- vlc_mutex_lock( &p_aout->volume_lock );
+ vlc_mutex_lock( &aout_owner(p_aout)->volume.lock );
}
static inline void aout_unlock_volume( audio_output_t *p_aout )
{
aout_unlock_check( VOLUME_LOCK );
- vlc_mutex_unlock( &p_aout->volume_lock );
+ vlc_mutex_unlock( &aout_owner(p_aout)->volume.lock );
}
/* Helpers */
static inline void AoutInputsMarkToRestart( audio_output_t *p_aout )
{
aout_lock( p_aout );
- if( p_aout->p_input != NULL )
- p_aout->p_input->b_restart = true;
+ if( aout_owner(p_aout)->input != NULL )
+ aout_owner(p_aout)->input->b_restart = true;
aout_unlock( p_aout );
}
*****************************************************************************/
audio_output_t *aout_New( vlc_object_t * p_parent )
{
- audio_output_t * p_aout;
-
- /* Allocate descriptor. */
- p_aout = vlc_custom_create( p_parent, sizeof( *p_aout ), "audio output" );
- if( p_aout == NULL )
- {
+ audio_output_t *aout = vlc_custom_create (p_parent,
+ sizeof (aout_instance_t),
+ "audio output");
+ if (unlikely(aout == NULL))
return NULL;
- }
- /* Initialize members. */
- vlc_mutex_init( &p_aout->volume_lock );
- vlc_mutex_init( &p_aout->lock );
- p_aout->p_input = NULL;
- p_aout->mixer_multiplier = 1.0;
- p_aout->mixer = NULL;
- p_aout->b_starving = true;
- p_aout->module = NULL;
- aout_VolumeNoneInit( p_aout );
+ aout_owner_t *owner = aout_owner (aout);
- var_Create( p_aout, "intf-change", VLC_VAR_VOID );
+ owner->module = NULL;
+ owner->input = NULL;
+ vlc_mutex_init (&owner->volume.lock);
+ owner->volume.multiplier = 1.0;
+ owner->volume.mixer = NULL;
+ owner->b_starving = true;
- vlc_object_set_destructor( p_aout, aout_Destructor );
+ vlc_mutex_init (&aout->lock);
- return p_aout;
+ aout_VolumeNoneInit (aout);
+ vlc_object_set_destructor (aout, aout_Destructor);
+ var_Create (aout, "intf-change", VLC_VAR_VOID);
+
+ return aout;
}
/*****************************************************************************
* aout_Destructor: destroy aout structure
*****************************************************************************/
-static void aout_Destructor( vlc_object_t * p_this )
+static void aout_Destructor (vlc_object_t *obj)
{
- audio_output_t * p_aout = (audio_output_t *)p_this;
- vlc_mutex_destroy( &p_aout->volume_lock );
- vlc_mutex_destroy( &p_aout->lock );
+ audio_output_t *aout = (audio_output_t *)obj;
+ aout_owner_t *owner = aout_owner (aout);
+
+ vlc_mutex_destroy (&owner->volume.lock);
+ vlc_mutex_destroy (&aout->lock);
}
#ifdef AOUT_DEBUG
/* We can only be called by the decoder, so no need to lock
* p_input->lock. */
+ aout_owner_t *owner = aout_owner(p_aout);
aout_lock( p_aout );
- assert( p_aout->p_input == NULL );
- p_aout->p_input = p_input;
+ assert (owner->input == NULL);
+ owner->input = p_input;
var_Destroy( p_aout, "audio-device" );
var_Destroy( p_aout, "audio-channels" );
#warning Input without output and mixer = bad idea.
goto out;
- assert( p_aout->mixer == NULL );
- p_aout->mixer = aout_MixerNew( p_aout, &p_aout->mixer_format );
- if( p_aout->mixer == NULL )
+ assert (owner->volume.mixer == NULL);
+ owner->volume.mixer = aout_MixerNew (p_aout, &owner->mixer_format);
+ if (owner->volume.mixer == NULL)
{
aout_OutputDelete( p_aout );
#warning Memory leak.
*****************************************************************************/
void aout_DecDelete( audio_output_t * p_aout, aout_input_t * p_input )
{
+ aout_owner_t *owner = aout_owner (p_aout);
+ struct audio_mixer *mixer;
+
aout_lock( p_aout );
/* Remove the input. */
- assert( p_input == p_aout->p_input ); /* buggy decoder? */
- p_aout->p_input = NULL;
+ assert (owner->input == p_input); /* buggy decoder? */
+ owner->input = NULL;
aout_InputDelete( p_aout, p_input );
aout_OutputDelete( p_aout );
- aout_MixerDelete( p_aout->mixer );
- p_aout->mixer = NULL;
+ mixer = owner->volume.mixer;
+ owner->volume.mixer = NULL;
var_Destroy( p_aout, "audio-device" );
var_Destroy( p_aout, "audio-channels" );
aout_unlock( p_aout );
+
+ aout_MixerDelete (mixer);
free( p_input );
}
int aout_DecPlay( audio_output_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer, int i_input_rate )
{
+ aout_owner_t *owner = aout_owner (p_aout);
assert( i_input_rate >= INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE &&
i_input_rate <= INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE );
assert( p_buffer->i_pts > 0 );
if( p_buffer != NULL )
{
/* Mixer */
- float amp = p_aout->mixer_multiplier * p_input->multiplier;
- aout_MixerRun( p_aout->mixer, p_buffer, amp );
+ float amp = owner->volume.multiplier * p_input->multiplier;
+ aout_MixerRun (owner->volume.mixer, p_buffer, amp);
/* Output */
aout_OutputPlay( p_aout, p_buffer );
void aout_DecChangePause( audio_output_t *p_aout, aout_input_t *p_input, bool b_paused, mtime_t i_date )
{
+ aout_owner_t *owner = aout_owner (p_aout);
+
aout_lock( p_aout );
- assert( p_aout->p_input == p_input );
+ assert (owner->input == p_input);
aout_OutputPause( p_aout, b_paused, i_date );
*****************************************************************************/
int aout_InputNew( audio_output_t * p_aout, aout_input_t * p_input, const aout_request_vout_t *p_request_vout )
{
+ aout_owner_t *owner = aout_owner (p_aout);
audio_sample_format_t chain_input_format;
audio_sample_format_t chain_output_format;
vlc_value_t val, text;
p_input->i_nb_resamplers = p_input->i_nb_filters = 0;
/* Prepare FIFO. */
- aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer_format.i_rate );
+ aout_FifoInit (p_aout, &p_input->fifo, owner->mixer_format.i_rate);
/* */
if( p_request_vout )
/* Prepare format structure */
chain_input_format = p_input->input;
- chain_output_format = p_aout->mixer_format;
+ chain_output_format = owner->mixer_format;
chain_output_format.i_rate = p_input->input.i_rate;
aout_FormatPrepare( &chain_output_format );
}
/* Create resamplers. */
- if ( !AOUT_FMT_NON_LINEAR( &p_aout->mixer_format ) )
+ if (!AOUT_FMT_NON_LINEAR(&owner->mixer_format))
{
chain_output_format.i_rate = (__MAX(p_input->input.i_rate,
- p_aout->mixer_format.i_rate)
+ owner->mixer_format.i_rate)
* (100 + AOUT_MAX_RESAMPLING)) / 100;
- if ( chain_output_format.i_rate == p_aout->mixer_format.i_rate )
+ if ( chain_output_format.i_rate == owner->mixer_format.i_rate )
{
/* Just in case... */
chain_output_format.i_rate++;
}
- if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers,
- &p_input->i_nb_resamplers,
- &chain_output_format,
- &p_aout->mixer_format ) < 0 )
+ if (aout_FiltersCreatePipeline (p_aout, p_input->pp_resamplers,
+ &p_input->i_nb_resamplers,
+ &chain_output_format,
+ &owner->mixer_format) < 0)
{
inputFailure( p_aout, p_input, "couldn't set a resampler pipeline");
return -1;
*****************************************************************************/
void aout_InputCheckAndRestart( audio_output_t * p_aout, aout_input_t * p_input )
{
+ aout_owner_t *owner = aout_owner (p_aout);
AOUT_ASSERT_LOCKED;
if( !p_input->b_restart )
aout_fifo_t fifo = p_input->fifo;
mtime_t i_pause_date = p_input->i_pause_date;
- aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer_format.i_rate );
+ aout_FifoInit (p_aout, &p_input->fifo, owner->mixer_format.i_rate);
aout_InputDelete( p_aout, p_input );
{
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
VLC_UNUSED(newval); VLC_UNUSED(p_data);
- audio_output_t *p_aout = (audio_output_t *)p_this;
+ audio_output_t *aout = (audio_output_t *)p_this;
+ aout_owner_t *owner = aout_owner (aout);
- aout_lock( p_aout );
- if( p_aout->p_input != NULL )
- ReplayGainSelect( p_aout, p_aout->p_input );
- aout_unlock( p_aout );
+ aout_lock (aout);
+ if (owner->input != NULL)
+ ReplayGainSelect (aout, owner->input);
+ aout_unlock (aout);
return VLC_SUCCESS;
}
if (aout != NULL)
{
+ aout_owner_t *owner = aout_owner (aout);
float vol = volume / (float)AOUT_VOLUME_DEFAULT;
aout_lock (aout);
#warning FIXME: wrong test. Need to check that aout_output is ready.
- if (aout->mixer != NULL)
+ if (owner->volume.mixer != NULL)
ret = aout->pf_volume_set (aout, vol, mute);
aout_unlock (aout);
static int aout_Restart( audio_output_t * p_aout )
{
aout_input_t *p_input;
+ aout_owner_t *owner = aout_owner (p_aout);
aout_lock( p_aout );
- p_input = p_aout->p_input;
+ p_input = owner->input;
if( p_input == NULL )
{
aout_unlock( p_aout );
/* Reinitializes the output */
aout_InputDelete( p_aout, p_input );
- aout_MixerDelete( p_aout->mixer );
- p_aout->mixer = NULL;
+ aout_MixerDelete (owner->volume.mixer);
+ owner->volume.mixer = NULL;
aout_OutputDelete( p_aout );
/* FIXME: This function is notoriously dangerous/unsafe.
return -1;
}
- p_aout->mixer = aout_MixerNew( p_aout, &p_aout->mixer_format );
- if( p_aout->mixer == NULL )
+ owner->volume.mixer = aout_MixerNew (p_aout, &owner->mixer_format);
+ if (owner->volume.mixer == NULL)
{
aout_OutputDelete( p_aout );
aout_unlock( p_aout );
*****************************************************************************
* This function is entered with the mixer lock.
*****************************************************************************/
-int aout_OutputNew( audio_output_t * p_aout,
+int aout_OutputNew( audio_output_t *p_aout,
const audio_sample_format_t * p_format )
{
+ aout_owner_t *owner = aout_owner (p_aout);
+
vlc_assert_locked( &p_aout->lock );
p_aout->format = *p_format;
aout_FormatPrepare( &p_aout->format );
/* Find the best output plug-in. */
- p_aout->module = module_need( p_aout, "audio output", "$aout", false );
- if ( p_aout->module == NULL )
+ owner->module = module_need (p_aout, "audio output", "$aout", false);
+ if (owner->module == NULL)
{
msg_Err( p_aout, "no suitable audio output module" );
return -1;
aout_FormatPrint( p_aout, "output", &p_aout->format );
/* Choose the mixer format. */
- p_aout->mixer_format = p_aout->format;
- if ( AOUT_FMT_NON_LINEAR(&p_aout->format) )
- p_aout->mixer_format.i_format = p_format->i_format;
+ owner->mixer_format = p_aout->format;
+ if (AOUT_FMT_NON_LINEAR(&p_aout->format))
+ owner->mixer_format.i_format = p_format->i_format;
else
/* Most audio filters can only deal with single-precision,
* so lets always use that when hardware supports floating point. */
if( HAVE_FPU )
- p_aout->mixer_format.i_format = VLC_CODEC_FL32;
+ owner->mixer_format.i_format = VLC_CODEC_FL32;
else
/* Otherwise, audio filters will not work. Use fixed-point if the input has
* more than 16-bits depth. */
if( p_format->i_bitspersample > 16 )
- p_aout->mixer_format.i_format = VLC_CODEC_FI32;
+ owner->mixer_format.i_format = VLC_CODEC_FI32;
else
/* Fallback to 16-bits. This avoids pointless conversion to and from
* 32-bits samples for the sole purpose of software mixing. */
- p_aout->mixer_format.i_format = VLC_CODEC_S16N;
+ owner->mixer_format.i_format = VLC_CODEC_S16N;
- aout_FormatPrepare( &p_aout->mixer_format );
- aout_FormatPrint( p_aout, "mixer", &p_aout->mixer_format );
+ aout_FormatPrepare (&owner->mixer_format);
+ aout_FormatPrint (p_aout, "mixer", &owner->mixer_format);
/* Create filters. */
- p_aout->i_nb_filters = 0;
- if ( aout_FiltersCreatePipeline( p_aout, p_aout->pp_filters,
- &p_aout->i_nb_filters,
- &p_aout->mixer_format,
- &p_aout->format ) < 0 )
+ owner->nb_filters = 0;
+ if (aout_FiltersCreatePipeline (p_aout, owner->filters,
+ &owner->nb_filters, &owner->mixer_format,
+ &p_aout->format) < 0)
{
msg_Err( p_aout, "couldn't create audio output pipeline" );
- module_unneed( p_aout, p_aout->module );
- p_aout->module = NULL;
+ module_unneed (p_aout, owner->module);
+ owner->module = NULL;
return -1;
}
return 0;
*****************************************************************************/
void aout_OutputDelete( audio_output_t * p_aout )
{
+ aout_owner_t *owner = aout_owner (p_aout);
+
vlc_assert_locked( &p_aout->lock );
- if( p_aout->module == NULL )
+ if (owner->module == NULL)
return;
- module_unneed( p_aout, p_aout->module );
+ module_unneed (p_aout, owner->module);
aout_VolumeNoneInit( p_aout ); /* clear volume callback */
- p_aout->module = NULL;
- aout_FiltersDestroyPipeline( p_aout->pp_filters, p_aout->i_nb_filters );
+ owner->module = NULL;
+ aout_FiltersDestroyPipeline (owner->filters, owner->nb_filters);
aout_FifoDestroy( &p_aout->fifo );
}
*****************************************************************************/
void aout_OutputPlay( audio_output_t * p_aout, aout_buffer_t * p_buffer )
{
+ aout_owner_t *owner = aout_owner (p_aout);
+
vlc_assert_locked( &p_aout->lock );
- aout_FiltersPlay( p_aout->pp_filters, p_aout->i_nb_filters, &p_buffer );
+ aout_FiltersPlay (owner->filters, owner->nb_filters, &p_buffer);
if( !p_buffer )
return;
if( p_buffer->i_buffer == 0 )
return;
}
- aout_fifo_t *fifo = &p_aout->p_input->fifo;
+ aout_fifo_t *fifo = &owner->input->fifo;
/* XXX: cleanup */
aout_FifoPush( fifo, p_buffer );
*/
void aout_OutputPause( audio_output_t *aout, bool pause, mtime_t date )
{
+ aout_owner_t *owner = aout_owner (aout);
+
vlc_assert_locked( &aout->lock );
if( aout->pf_pause != NULL )
aout->pf_pause( aout, pause, date );
if( !pause )
{
- mtime_t duration = date - aout->p_input->i_pause_date;
+ mtime_t duration = date - owner->input->i_pause_date;
/* XXX: ^ onk onk! gruik! ^ */
aout_FifoMoveDates( &aout->fifo, duration );
}
*/
static int aout_VolumeSoftSet (audio_output_t *aout, float volume, bool mute)
{
+ aout_owner_t *owner = aout_owner (aout);
+
vlc_assert_locked (&aout->lock);
/* Cubic mapping from software volume to amplification factor.
else
volume = 0.;
- aout->mixer_multiplier = volume;
+ owner->volume.multiplier = volume;
return 0;
}
mtime_t start_date,
bool b_can_sleek )
{
+ aout_owner_t *owner = aout_owner (p_aout);
aout_fifo_t *p_fifo = &p_aout->fifo;
aout_buffer_t * p_buffer;
mtime_t now = mdate();
*/
if ( 0 > delta + p_buffer->i_length )
{
- if ( !p_aout->b_starving )
+ if (!owner->b_starving)
msg_Dbg( p_aout, "audio output is starving (%"PRId64"), "
"playing silence", -delta );
- p_aout->b_starving = true;
+ owner->b_starving = true;
p_buffer = NULL;
goto out;
}
- p_aout->b_starving = false;
+ owner->b_starving = false;
p_buffer = aout_FifoPop( p_fifo );
if( !b_can_sleek
msg_Warn( p_aout, "output date isn't PTS date, requesting "
"resampling (%"PRId64")", delta );
- aout_FifoMoveDates( &p_aout->p_input->fifo, delta );
+ aout_FifoMoveDates (&owner->input->fifo, delta);
aout_FifoMoveDates( p_fifo, delta );
}
out: