Commit d29ead01 authored by Laurent Aimar's avatar Laurent Aimar

Split out aout_mixer_t from aout_instance_t.

It will allow to sanetize aout_instance_t.
parent 8d6e134e
...@@ -174,25 +174,6 @@ typedef struct aout_alloc_t ...@@ -174,25 +174,6 @@ typedef struct aout_alloc_t
#define AOUT_ALLOC_STACK 1 #define AOUT_ALLOC_STACK 1
#define AOUT_ALLOC_HEAP 2 #define AOUT_ALLOC_HEAP 2
/** audio output mixer */
typedef struct aout_mixer_t
{
audio_sample_format_t mixer;
aout_alloc_t output_alloc;
module_t * p_module;
struct aout_mixer_sys_t * p_sys;
void (* pf_do_work)( struct aout_instance_t *,
struct aout_buffer_t * );
/** If b_error == 1, there is no mixer. */
bool b_error;
/** Multiplier used to raise or lower the volume of the sound in
* software. Beware, this creates sound distortion and should be avoided
* as much as possible. This isn't available for non-float32 mixer. */
float f_multiplier;
} aout_mixer_t;
/** audio output buffer FIFO */ /** audio output buffer FIFO */
struct aout_fifo_t struct aout_fifo_t
{ {
...@@ -201,6 +182,9 @@ struct aout_fifo_t ...@@ -201,6 +182,9 @@ struct aout_fifo_t
date_t end_date; date_t end_date;
}; };
/* FIXME to remove once aout.h is cleaned a bit more */
#include <vlc_aout_mixer.h>
/* */ /* */
typedef struct typedef struct
{ {
...@@ -266,12 +250,8 @@ struct aout_input_t ...@@ -266,12 +250,8 @@ struct aout_input_t
mtime_t i_resamp_start_date; mtime_t i_resamp_start_date;
int i_resamp_start_drift; int i_resamp_start_drift;
aout_fifo_t fifo;
/* Mixer information */ /* Mixer information */
uint8_t * p_first_byte_to_mix;
audio_replay_gain_t replay_gain; audio_replay_gain_t replay_gain;
float f_multiplier;
/* If b_restart == 1, the input pipeline will be re-created. */ /* If b_restart == 1, the input pipeline will be re-created. */
bool b_restart; bool b_restart;
...@@ -295,6 +275,9 @@ struct aout_input_t ...@@ -295,6 +275,9 @@ struct aout_input_t
/* */ /* */
bool b_recycle_vout; bool b_recycle_vout;
aout_request_vout_t request_vout; aout_request_vout_t request_vout;
/* */
aout_mixer_input_t mixer;
}; };
/** an output stream for the audio output */ /** an output stream for the audio output */
...@@ -351,7 +334,10 @@ struct aout_instance_t ...@@ -351,7 +334,10 @@ struct aout_instance_t
int i_nb_inputs; int i_nb_inputs;
/* Mixer */ /* Mixer */
aout_mixer_t mixer; audio_sample_format_t mixer_format;
aout_alloc_t mixer_allocation;
float mixer_multiplier;
aout_mixer_t *p_mixer;
/* Output plug-in */ /* Output plug-in */
aout_output_t output; aout_output_t output;
......
/*****************************************************************************
* vlc_aout_mixer.h : audio output mixer interface
*****************************************************************************
* Copyright (C) 2002-2009 the VideoLAN team
* $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_AOUT_MIXER_H
#define VLC_AOUT_MIXER_H 1
/**
* \file
* This file defines functions, structures and macros for audio output mixer object
*/
#ifdef __cplusplus
extern "C" {
#endif
//#include <vlc_aout.h>
/* */
typedef struct aout_mixer_sys_t aout_mixer_sys_t;
typedef struct aout_mixer_t aout_mixer_t;
typedef struct {
/* Is the input to be ignored while mixing */
bool is_invalid;
/* */
aout_fifo_t fifo;
/* Pointer on the first byte of data to mix.
*
* It points in the first buffer of fifo
*/
uint8_t *begin;
/* Software multiplier */
float multiplier;
} aout_mixer_input_t;
/**
* audio output mixer
*/
struct aout_mixer_t {
VLC_COMMON_MEMBERS
/* Module */
module_t *module;
/* Mixer format.
*
* You cannot modify it.
*/
audio_sample_format_t fmt;
/* Mixer output buffer allocation method.
*
* You can override it in the open function only.
*/
aout_alloc_t allocation;
/* Multiplier used to raise or lower the volume of the sound in
* software.
*/
float multiplier;
/* Array of mixer inputs */
unsigned input_count;
aout_mixer_input_t **input;
/* Mix input into the given buffer (mandatory) */
void (*mix)(aout_mixer_t *, struct aout_buffer_t *);
/* Private place holder for the aout_mixer_t module (optional)
*
* A module is free to use it as it wishes.
*/
aout_mixer_sys_t *sys;
};
#ifdef __cplusplus
}
#endif
#endif
...@@ -46,6 +46,7 @@ pluginsinclude_HEADERS = \ ...@@ -46,6 +46,7 @@ pluginsinclude_HEADERS = \
../include/vlc_access.h \ ../include/vlc_access.h \
../include/vlc_acl.h \ ../include/vlc_acl.h \
../include/vlc_aout.h \ ../include/vlc_aout.h \
../include/vlc_aout_mixer.h \
../include/vlc_arrays.h \ ../include/vlc_arrays.h \
../include/vlc_avcodec.h \ ../include/vlc_avcodec.h \
../include/vlc_bits.h \ ../include/vlc_bits.h \
......
...@@ -43,6 +43,9 @@ ...@@ -43,6 +43,9 @@
static inline void aout_assert_fifo_locked( aout_instance_t * p_aout, aout_fifo_t * p_fifo ) static inline void aout_assert_fifo_locked( aout_instance_t * p_aout, aout_fifo_t * p_fifo )
{ {
#ifndef NDEBUG #ifndef NDEBUG
if( !p_aout )
return;
if( p_fifo == &p_aout->output.fifo ) if( p_fifo == &p_aout->output.fifo )
vlc_assert_locked( &p_aout->output_fifo_lock ); vlc_assert_locked( &p_aout->output_fifo_lock );
else else
...@@ -50,7 +53,7 @@ static inline void aout_assert_fifo_locked( aout_instance_t * p_aout, aout_fifo_ ...@@ -50,7 +53,7 @@ static inline void aout_assert_fifo_locked( aout_instance_t * p_aout, aout_fifo_
int i; int i;
for( i = 0; i < p_aout->i_nb_inputs; i++ ) for( i = 0; i < p_aout->i_nb_inputs; i++ )
{ {
if( p_fifo == &p_aout->pp_inputs[i]->fifo) if( p_fifo == &p_aout->pp_inputs[i]->mixer.fifo)
{ {
vlc_assert_locked( &p_aout->input_fifos_lock ); vlc_assert_locked( &p_aout->input_fifos_lock );
break; break;
...@@ -88,8 +91,8 @@ aout_instance_t * __aout_New( vlc_object_t * p_parent ) ...@@ -88,8 +91,8 @@ aout_instance_t * __aout_New( vlc_object_t * p_parent )
vlc_mutex_init( &p_aout->mixer_lock ); vlc_mutex_init( &p_aout->mixer_lock );
vlc_mutex_init( &p_aout->output_fifo_lock ); vlc_mutex_init( &p_aout->output_fifo_lock );
p_aout->i_nb_inputs = 0; p_aout->i_nb_inputs = 0;
p_aout->mixer.f_multiplier = 1.0; p_aout->mixer_multiplier = 1.0;
p_aout->mixer.b_error = 1; p_aout->p_mixer = NULL;
p_aout->output.b_error = 1; p_aout->output.b_error = 1;
p_aout->output.b_starving = 1; p_aout->output.b_starving = 1;
......
...@@ -112,7 +112,7 @@ static aout_input_t * DecNew( aout_instance_t * p_aout, ...@@ -112,7 +112,7 @@ static aout_input_t * DecNew( aout_instance_t * p_aout,
p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input; p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input;
p_aout->i_nb_inputs++; p_aout->i_nb_inputs++;
if ( p_aout->mixer.b_error ) if ( !p_aout->p_mixer )
{ {
int i; int i;
...@@ -379,7 +379,7 @@ void aout_DecChangePause( aout_instance_t *p_aout, aout_input_t *p_input, bool b ...@@ -379,7 +379,7 @@ void aout_DecChangePause( aout_instance_t *p_aout, aout_input_t *p_input, bool b
if( i_duration != 0 ) if( i_duration != 0 )
{ {
aout_lock_mixer( p_aout ); aout_lock_mixer( p_aout );
for( aout_buffer_t *p = p_input->fifo.p_first; p != NULL; p = p->p_next ) for( aout_buffer_t *p = p_input->mixer.fifo.p_first; p != NULL; p = p->p_next )
{ {
p->start_date += i_duration; p->start_date += i_duration;
p->end_date += i_duration; p->end_date += i_duration;
...@@ -392,8 +392,8 @@ void aout_DecFlush( aout_instance_t *p_aout, aout_input_t *p_input ) ...@@ -392,8 +392,8 @@ void aout_DecFlush( aout_instance_t *p_aout, aout_input_t *p_input )
{ {
aout_lock_input_fifos( p_aout ); aout_lock_input_fifos( p_aout );
aout_FifoSet( p_aout, &p_input->fifo, 0 ); aout_FifoSet( p_aout, &p_input->mixer.fifo, 0 );
p_input->p_first_byte_to_mix = NULL; p_input->mixer.begin = NULL;
aout_unlock_input_fifos( p_aout ); aout_unlock_input_fifos( p_aout );
} }
......
...@@ -83,8 +83,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ ...@@ -83,8 +83,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_
p_input->i_nb_resamplers = p_input->i_nb_filters = 0; p_input->i_nb_resamplers = p_input->i_nb_filters = 0;
/* Prepare FIFO. */ /* Prepare FIFO. */
aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate ); aout_FifoInit( p_aout, &p_input->mixer.fifo, p_aout->p_mixer->fmt.i_rate );
p_input->p_first_byte_to_mix = NULL; p_input->mixer.begin = NULL;
/* */ /* */
if( p_request_vout ) if( p_request_vout )
...@@ -98,10 +98,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ ...@@ -98,10 +98,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_
} }
/* Prepare format structure */ /* Prepare format structure */
memcpy( &chain_input_format, &p_input->input, chain_input_format = p_input->input;
sizeof(audio_sample_format_t) ); chain_output_format = p_aout->p_mixer->fmt;
memcpy( &chain_output_format, &p_aout->mixer.mixer,
sizeof(audio_sample_format_t) );
chain_output_format.i_rate = p_input->input.i_rate; chain_output_format.i_rate = p_input->input.i_rate;
aout_FormatPrepare( &chain_output_format ); aout_FormatPrepare( &chain_output_format );
...@@ -419,12 +417,12 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ ...@@ -419,12 +417,12 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_
p_input->input_alloc.i_bytes_per_sec = -1; p_input->input_alloc.i_bytes_per_sec = -1;
/* Create resamplers. */ /* Create resamplers. */
if ( !AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) ) if ( !AOUT_FMT_NON_LINEAR( &p_aout->p_mixer->fmt ) )
{ {
chain_output_format.i_rate = (__MAX(p_input->input.i_rate, chain_output_format.i_rate = (__MAX(p_input->input.i_rate,
p_aout->mixer.mixer.i_rate) p_aout->p_mixer->fmt.i_rate)
* (100 + AOUT_MAX_RESAMPLING)) / 100; * (100 + AOUT_MAX_RESAMPLING)) / 100;
if ( chain_output_format.i_rate == p_aout->mixer.mixer.i_rate ) if ( chain_output_format.i_rate == p_aout->p_mixer->fmt.i_rate )
{ {
/* Just in case... */ /* Just in case... */
chain_output_format.i_rate++; chain_output_format.i_rate++;
...@@ -432,7 +430,7 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ ...@@ -432,7 +430,7 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_
if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers, if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers,
&p_input->i_nb_resamplers, &p_input->i_nb_resamplers,
&chain_output_format, &chain_output_format,
&p_aout->mixer.mixer ) < 0 ) &p_aout->p_mixer->fmt ) < 0 )
{ {
inputFailure( p_aout, p_input, "couldn't set a resampler pipeline"); inputFailure( p_aout, p_input, "couldn't set a resampler pipeline");
return -1; return -1;
...@@ -500,7 +498,7 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ) ...@@ -500,7 +498,7 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers,
p_input->i_nb_resamplers ); p_input->i_nb_resamplers );
p_input->i_nb_resamplers = 0; p_input->i_nb_resamplers = 0;
aout_FifoDestroy( p_aout, &p_input->fifo ); aout_FifoDestroy( p_aout, &p_input->mixer.fifo );
return 0; return 0;
} }
...@@ -530,18 +528,18 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -530,18 +528,18 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
/* A little trick to avoid loosing our input fifo and properties */ /* A little trick to avoid loosing our input fifo and properties */
p_first_byte_to_mix = p_input->p_first_byte_to_mix; p_first_byte_to_mix = p_input->mixer.begin;
fifo = p_input->fifo; fifo = p_input->mixer.fifo;
b_paused = p_input->b_paused; b_paused = p_input->b_paused;
i_pause_date = p_input->i_pause_date; i_pause_date = p_input->i_pause_date;
aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate ); aout_FifoInit( p_aout, &p_input->mixer.fifo, p_aout->p_mixer->fmt.i_rate );
aout_InputDelete( p_aout, p_input ); aout_InputDelete( p_aout, p_input );
aout_InputNew( p_aout, p_input, &p_input->request_vout ); aout_InputNew( p_aout, p_input, &p_input->request_vout );
p_input->p_first_byte_to_mix = p_first_byte_to_mix; p_input->mixer.begin = p_first_byte_to_mix;
p_input->fifo = fifo; p_input->mixer.fifo = fifo;
p_input->b_paused = b_paused; p_input->b_paused = b_paused;
p_input->i_pause_date = i_pause_date; p_input->i_pause_date = i_pause_date;
...@@ -591,7 +589,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -591,7 +589,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
* this. We'll deal with that when pushing the buffer, and compensate * this. We'll deal with that when pushing the buffer, and compensate
* with the next incoming buffer. */ * with the next incoming buffer. */
aout_lock_input_fifos( p_aout ); aout_lock_input_fifos( p_aout );
start_date = aout_FifoNextStart( p_aout, &p_input->fifo ); start_date = aout_FifoNextStart( p_aout, &p_input->mixer.fifo );
aout_unlock_input_fifos( p_aout ); aout_unlock_input_fifos( p_aout );
if ( start_date != 0 && start_date < mdate() ) if ( start_date != 0 && start_date < mdate() )
...@@ -602,8 +600,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -602,8 +600,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
msg_Warn( p_aout, "computed PTS is out of range (%"PRId64"), " msg_Warn( p_aout, "computed PTS is out of range (%"PRId64"), "
"clearing out", mdate() - start_date ); "clearing out", mdate() - start_date );
aout_lock_input_fifos( p_aout ); aout_lock_input_fifos( p_aout );
aout_FifoSet( p_aout, &p_input->fifo, 0 ); aout_FifoSet( p_aout, &p_input->mixer.fifo, 0 );
p_input->p_first_byte_to_mix = NULL; p_input->mixer.begin = NULL;
aout_unlock_input_fifos( p_aout ); aout_unlock_input_fifos( p_aout );
if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
msg_Warn( p_aout, "timing screwed, stopping resampling" ); msg_Warn( p_aout, "timing screwed, stopping resampling" );
...@@ -632,8 +630,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -632,8 +630,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
msg_Warn( p_aout, "audio drift is too big (%"PRId64"), clearing out", msg_Warn( p_aout, "audio drift is too big (%"PRId64"), clearing out",
start_date - p_buffer->start_date ); start_date - p_buffer->start_date );
aout_lock_input_fifos( p_aout ); aout_lock_input_fifos( p_aout );
aout_FifoSet( p_aout, &p_input->fifo, 0 ); aout_FifoSet( p_aout, &p_input->mixer.fifo, 0 );
p_input->p_first_byte_to_mix = NULL; p_input->mixer.begin = NULL;
aout_unlock_input_fifos( p_aout ); aout_unlock_input_fifos( p_aout );
if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
msg_Warn( p_aout, "timing screwed, stopping resampling" ); msg_Warn( p_aout, "timing screwed, stopping resampling" );
...@@ -760,7 +758,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -760,7 +758,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
p_buffer->start_date = start_date; p_buffer->start_date = start_date;
aout_lock_input_fifos( p_aout ); aout_lock_input_fifos( p_aout );
aout_FifoPush( p_aout, &p_input->fifo, p_buffer ); aout_FifoPush( p_aout, &p_input->mixer.fifo, p_buffer );
aout_unlock_input_fifos( p_aout ); aout_unlock_input_fifos( p_aout );
return 0; return 0;
} }
...@@ -780,7 +778,7 @@ static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -780,7 +778,7 @@ static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input,
p_input->i_nb_filters ); p_input->i_nb_filters );
aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers,
p_input->i_nb_resamplers ); p_input->i_nb_resamplers );
aout_FifoDestroy( p_aout, &p_input->fifo ); aout_FifoDestroy( p_aout, &p_input->mixer.fifo );
var_Destroy( p_aout, "visual" ); var_Destroy( p_aout, "visual" );
var_Destroy( p_aout, "equalizer" ); var_Destroy( p_aout, "equalizer" );
var_Destroy( p_aout, "audio-filter" ); var_Destroy( p_aout, "audio-filter" );
...@@ -934,7 +932,8 @@ static int ReplayGainCallback( vlc_object_t *p_this, char const *psz_cmd, ...@@ -934,7 +932,8 @@ static int ReplayGainCallback( vlc_object_t *p_this, char const *psz_cmd,
ReplayGainSelect( p_aout, p_aout->pp_inputs[i] ); ReplayGainSelect( p_aout, p_aout->pp_inputs[i] );
/* Restart the mixer (a trivial mixer may be in use) */ /* Restart the mixer (a trivial mixer may be in use) */
aout_MixerMultiplierSet( p_aout, p_aout->mixer.f_multiplier ); if( p_aout->p_mixer )
aout_MixerMultiplierSet( p_aout, p_aout->mixer_multiplier );
aout_unlock_mixer( p_aout ); aout_unlock_mixer( p_aout );
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -948,7 +947,7 @@ static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input ) ...@@ -948,7 +947,7 @@ static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input )
int i_use; int i_use;
float f_gain; float f_gain;
p_input->f_multiplier = 1.0; p_input->mixer.multiplier = 1.0;
if( !psz_replay_gain ) if( !psz_replay_gain )
return; return;
...@@ -979,14 +978,14 @@ static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input ) ...@@ -979,14 +978,14 @@ static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input )
f_gain = var_GetFloat( p_aout, "audio-replay-gain-default" ); f_gain = var_GetFloat( p_aout, "audio-replay-gain-default" );
else else
f_gain = 0.0; f_gain = 0.0;
p_input->f_multiplier = pow( 10.0, f_gain / 20.0 ); p_input->mixer.multiplier = pow( 10.0, f_gain / 20.0 );
/* */ /* */
if( p_input->replay_gain.pb_peak[i_use] && if( p_input->replay_gain.pb_peak[i_use] &&
var_GetBool( p_aout, "audio-replay-gain-peak-protection" ) && var_GetBool( p_aout, "audio-replay-gain-peak-protection" ) &&
p_input->replay_gain.pf_peak[i_use] * p_input->f_multiplier > 1.0 ) p_input->replay_gain.pf_peak[i_use] * p_input->mixer.multiplier > 1.0 )
{ {
p_input->f_multiplier = 1.0f / p_input->replay_gain.pf_peak[i_use]; p_input->mixer.multiplier = 1.0f / p_input->replay_gain.pf_peak[i_use];
} }
free( psz_replay_gain ); free( psz_replay_gain );
......
...@@ -79,7 +79,7 @@ int __aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume ) ...@@ -79,7 +79,7 @@ int __aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume )
} }
aout_lock_mixer( p_aout ); aout_lock_mixer( p_aout );
if ( !p_aout->mixer.b_error ) if ( p_aout->p_mixer )
{ {
i_result = p_aout->output.pf_volume_get( p_aout, pi_volume ); i_result = p_aout->output.pf_volume_get( p_aout, pi_volume );
} }
...@@ -110,11 +110,12 @@ int __aout_VolumeSet( vlc_object_t * p_object, audio_volume_t i_volume ) ...@@ -110,11 +110,12 @@ int __aout_VolumeSet( vlc_object_t * p_object, audio_volume_t i_volume )
return VLC_SUCCESS; return VLC_SUCCESS;
int i_result = VLC_SUCCESS; int i_result = VLC_SUCCESS;
aout_lock_mixer( p_aout );
if ( !p_aout->mixer.b_error ) aout_lock_mixer( p_aout );
aout_lock_input_fifos( p_aout );
if ( p_aout->p_mixer )
i_result = p_aout->output.pf_volume_set( p_aout, i_volume ); i_result = p_aout->output.pf_volume_set( p_aout, i_volume );
aout_unlock_input_fifos( p_aout );
aout_unlock_mixer( p_aout ); aout_unlock_mixer( p_aout );
var_SetBool( p_aout, "intf-change", true ); var_SetBool( p_aout, "intf-change", true );
......
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
#include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <libvlc.h>
#ifdef HAVE_ALLOCA_H #ifdef HAVE_ALLOCA_H
# include <alloca.h> # include <alloca.h>
...@@ -43,14 +45,38 @@ ...@@ -43,14 +45,38 @@
*****************************************************************************/ *****************************************************************************/
int aout_MixerNew( aout_instance_t * p_aout ) int aout_MixerNew( aout_instance_t * p_aout )
{ {
p_aout->mixer.p_module = module_need( p_aout, "audio mixer", NULL, false ); assert( !p_aout->p_mixer );
if ( p_aout->mixer.p_module == NULL ) vlc_assert_locked( &p_aout->input_fifos_lock );
aout_mixer_t *p_mixer = vlc_object_create( p_aout, sizeof(*p_mixer) );
if( !p_mixer )
return VLC_EGENERIC;
p_mixer->fmt = p_aout->mixer_format;
p_mixer->allocation = p_aout->mixer_allocation;
p_mixer->multiplier = p_aout->mixer_multiplier;
p_mixer->input_count = p_aout->i_nb_inputs;
p_mixer->input = calloc( p_mixer->input_count, sizeof(*p_mixer->input) );
for( int i = 0; i < p_aout->i_nb_inputs; i++ )
p_mixer->input[i] = &p_aout->pp_inputs[i]->mixer;
p_mixer->mix = NULL;
p_mixer->sys = NULL;
vlc_object_attach( p_mixer, p_aout );
p_mixer->module = module_need( p_mixer, "audio mixer", NULL, false );
if( !p_mixer->module )
{ {
msg_Err( p_aout, "no suitable audio mixer" ); msg_Err( p_aout, "no suitable audio mixer" );
return -1; vlc_object_detach( p_mixer );
free( p_mixer->input );
vlc_object_release( p_mixer );
return VLC_EGENERIC;
} }
p_aout->mixer.b_error = 0;
return 0; /* */
p_aout->p_mixer = p_mixer;
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
...@@ -60,9 +86,17 @@ int aout_MixerNew( aout_instance_t * p_aout ) ...@@ -60,9 +86,17 @@ int aout_MixerNew( aout_instance_t * p_aout )
*****************************************************************************/ *****************************************************************************/
void aout_MixerDelete( aout_instance_t * p_aout ) void aout_MixerDelete( aout_instance_t * p_aout )
{ {
if ( p_aout->mixer.b_error ) return; if( !p_aout->p_mixer )
module_unneed( p_aout, p_aout->mixer.p_module );