X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Fintf.c;h=1e0d8b9315f673120112fee83740cc5d035b452a;hb=be5d9107a6ba2160a0baa5ea51fc3c121265d5d2;hp=cc82727057ba2080e18c3b3d9bf98832c067370d;hpb=81442b6bf1af46dbaedc3388ea0b48f55bf13ae1;p=vlc diff --git a/src/audio_output/intf.c b/src/audio_output/intf.c index cc82727057..1e0d8b9315 100644 --- a/src/audio_output/intf.c +++ b/src/audio_output/intf.c @@ -1,8 +1,8 @@ /***************************************************************************** * intf.c : audio output API towards the interface modules ***************************************************************************** - * Copyright (C) 2002 VideoLAN - * $Id: intf.c,v 1.3 2002/09/19 21:56:40 massiot Exp $ + * Copyright (C) 2002-2007 the VideoLAN team + * $Id$ * * Authors: Christophe Massiot * @@ -10,7 +10,7 @@ * 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 @@ -18,18 +18,24 @@ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include #include /* calloc(), malloc(), free() */ #include -#include - -#include "audio_output.h" +#include #include "aout_internal.h" /* @@ -40,7 +46,7 @@ * mixer is running, so we need the mixer lock (too). * * Here is a schematic of the i_volume range : - * + * * |------------------------------+---------------------------------------| * 0 pi_soft 1024 * @@ -58,69 +64,62 @@ /***************************************************************************** * aout_VolumeGet : get the volume of the output device *****************************************************************************/ -int aout_VolumeGet( aout_instance_t * p_aout, audio_volume_t * pi_volume ) +int __aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume ) { - int i_result; + int i_result = 0; + aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT, + FIND_ANYWHERE ); - vlc_mutex_lock( &p_aout->mixer_lock ); + if ( pi_volume == NULL ) return -1; - if ( p_aout->i_nb_inputs == 0 ) + if ( p_aout == NULL ) { - /* The output module is destroyed. */ - vlc_mutex_unlock( &p_aout->mixer_lock ); - msg_Err( p_aout, "VolumeGet called without output module" ); - return -1; + *pi_volume = (audio_volume_t)config_GetInt( p_object, "volume" ); + return 0; } - i_result = p_aout->output.pf_volume_get( p_aout, pi_volume ); - - vlc_mutex_unlock( &p_aout->mixer_lock ); - return i_result; -} - -/***************************************************************************** - * aout_VolumeSet : set the volume of the output device - *****************************************************************************/ -int aout_VolumeSet( aout_instance_t * p_aout, audio_volume_t i_volume ) -{ - int i_result; - - vlc_mutex_lock( &p_aout->mixer_lock ); - - if ( p_aout->i_nb_inputs == 0 ) + aout_lock_mixer( p_aout ); + if ( p_aout->p_mixer ) { - /* The output module is destroyed. */ - vlc_mutex_unlock( &p_aout->mixer_lock ); - msg_Err( p_aout, "VolumeSet called without output module" ); - return -1; + i_result = p_aout->output.pf_volume_get( p_aout, pi_volume ); } + else + { + *pi_volume = (audio_volume_t)config_GetInt( p_object, "volume" ); + } + aout_unlock_mixer( p_aout ); - i_result = p_aout->output.pf_volume_set( p_aout, i_volume ); - - vlc_mutex_unlock( &p_aout->mixer_lock ); + vlc_object_release( p_aout ); return i_result; } /***************************************************************************** - * aout_VolumeInfos : get the boundaries pi_low_soft and pi_high_soft + * aout_VolumeSet : set the volume of the output device *****************************************************************************/ -int aout_VolumeInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft ) +int __aout_VolumeSet( vlc_object_t * p_object, audio_volume_t i_volume ) { - int i_result; + config_PutInt( p_object, "volume", i_volume ); + var_SetBool( p_object->p_libvlc, "volume-change", true ); - vlc_mutex_lock( &p_aout->mixer_lock ); + var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER ); + var_SetInteger( p_object->p_libvlc, "saved-volume" , i_volume ); - if ( p_aout->i_nb_inputs == 0 ) - { - /* The output module is destroyed. */ - vlc_mutex_unlock( &p_aout->mixer_lock ); - msg_Err( p_aout, "VolumeInfos called without output module" ); - return -1; - } + aout_instance_t *p_aout = vlc_object_find( p_object, + VLC_OBJECT_AOUT, FIND_ANYWHERE ); + if ( p_aout == NULL ) + return VLC_SUCCESS; - i_result = p_aout->output.pf_volume_infos( p_aout, pi_soft ); + int i_result = VLC_SUCCESS; - vlc_mutex_unlock( &p_aout->mixer_lock ); + 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 ); + aout_unlock_input_fifos( p_aout ); + aout_unlock_mixer( p_aout ); + + var_SetBool( p_aout, "intf-change", true ); + vlc_object_release( p_aout ); return i_result; } @@ -130,37 +129,22 @@ int aout_VolumeInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft ) * If pi_volume != NULL, *pi_volume will contain the volume at the end of the * function. *****************************************************************************/ -int aout_VolumeUp( aout_instance_t * p_aout, int i_nb_steps, +int __aout_VolumeUp( vlc_object_t * p_object, int i_nb_steps, audio_volume_t * pi_volume ) { - int i_result; - audio_volume_t i_volume; - vlc_mutex_lock( &p_aout->mixer_lock ); + const int i_volume_step = config_GetInt( p_object->p_libvlc, "volume-step" ); - if ( p_aout->i_nb_inputs == 0 ) - { - /* The output module is destroyed. */ - vlc_mutex_unlock( &p_aout->mixer_lock ); - msg_Err( p_aout, "VolumeUp called without output module" ); - return -1; - } - - if ( p_aout->output.pf_volume_get( p_aout, &i_volume ) ) - { - vlc_mutex_unlock( &p_aout->mixer_lock ); - return -1; - } + int i_volume = config_GetInt( p_object, "volume" ) + + i_volume_step * i_nb_steps; + if ( i_volume > AOUT_VOLUME_MAX ) + i_volume = AOUT_VOLUME_MAX; + else if ( i_volume < AOUT_VOLUME_MIN ) + i_volume = AOUT_VOLUME_MIN; + if ( pi_volume != NULL ) + *pi_volume = i_volume; - i_volume += AOUT_VOLUME_STEP * i_nb_steps; - if ( i_volume > 1024 ) i_volume = 1024; - - i_result = p_aout->output.pf_volume_set( p_aout, i_volume ); - - vlc_mutex_unlock( &p_aout->mixer_lock ); - - if ( pi_volume != NULL ) *pi_volume = i_volume; - return i_result; + return __aout_VolumeSet( p_object, i_volume ); } /***************************************************************************** @@ -169,38 +153,42 @@ int aout_VolumeUp( aout_instance_t * p_aout, int i_nb_steps, * If pi_volume != NULL, *pi_volume will contain the volume at the end of the * function. *****************************************************************************/ -int aout_VolumeDown( aout_instance_t * p_aout, int i_nb_steps, +int __aout_VolumeDown( vlc_object_t * p_object, int i_nb_steps, audio_volume_t * pi_volume ) +{ + return __aout_VolumeUp( p_object, -i_nb_steps, pi_volume ); +} + +/***************************************************************************** + * aout_ToggleMute : Mute/un-mute the output volume + ***************************************************************************** + * If pi_volume != NULL, *pi_volume will contain the volume at the end of the + * function (muted => 0). + *****************************************************************************/ +int __aout_ToggleMute( vlc_object_t * p_object, audio_volume_t * pi_volume ) { int i_result; audio_volume_t i_volume; - vlc_mutex_lock( &p_aout->mixer_lock ); - - if ( p_aout->i_nb_inputs == 0 ) + i_volume = (audio_volume_t)config_GetInt( p_object, "volume" ); + if ( i_volume != 0 ) { - /* The output module is destroyed. */ - vlc_mutex_unlock( &p_aout->mixer_lock ); - msg_Err( p_aout, "VolumeUp called without output module" ); - return -1; + /* Mute */ + i_result = aout_VolumeSet( p_object, AOUT_VOLUME_MIN ); + var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER ); + var_SetInteger( p_object->p_libvlc, "saved-volume", (int)i_volume ); + if ( pi_volume != NULL ) *pi_volume = AOUT_VOLUME_MIN; } - - if ( p_aout->output.pf_volume_get( p_aout, &i_volume ) ) + else { - vlc_mutex_unlock( &p_aout->mixer_lock ); - return -1; + /* Un-mute */ + var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER ); + i_volume = (audio_volume_t)var_GetInteger( p_object->p_libvlc, + "saved-volume" ); + i_result = aout_VolumeSet( p_object, i_volume ); + if ( pi_volume != NULL ) *pi_volume = i_volume; } - if ( i_volume < AOUT_VOLUME_STEP * i_nb_steps ) - i_volume = 0; - else - i_volume -= AOUT_VOLUME_STEP * i_nb_steps; - - i_result = p_aout->output.pf_volume_set( p_aout, i_volume ); - - vlc_mutex_unlock( &p_aout->mixer_lock ); - - if ( pi_volume != NULL ) *pi_volume = i_volume; return i_result; } @@ -214,24 +202,20 @@ void aout_VolumeSoftInit( aout_instance_t * p_aout ) { int i_volume; - p_aout->output.pf_volume_infos = aout_VolumeSoftInfos; p_aout->output.pf_volume_get = aout_VolumeSoftGet; p_aout->output.pf_volume_set = aout_VolumeSoftSet; i_volume = config_GetInt( p_aout, "volume" ); - if ( i_volume == -1 ) + if ( i_volume < AOUT_VOLUME_MIN ) { i_volume = AOUT_VOLUME_DEFAULT; } + else if ( i_volume > AOUT_VOLUME_MAX ) + { + i_volume = AOUT_VOLUME_MAX; + } - aout_VolumeSoftSet( p_aout, i_volume ); -} - -/* Placeholder for pf_volume_infos(). */ -int aout_VolumeSoftInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft ) -{ - *pi_soft = 0; - return 0; + aout_VolumeSoftSet( p_aout, (audio_volume_t)i_volume ); } /* Placeholder for pf_volume_get(). */ @@ -258,27 +242,166 @@ int aout_VolumeSoftSet( aout_instance_t * p_aout, audio_volume_t i_volume ) /* Meant to be called by the output plug-in's Open(). */ void aout_VolumeNoneInit( aout_instance_t * p_aout ) { - p_aout->output.pf_volume_infos = aout_VolumeNoneInfos; p_aout->output.pf_volume_get = aout_VolumeNoneGet; p_aout->output.pf_volume_set = aout_VolumeNoneSet; } -/* Placeholder for pf_volume_infos(). */ -int aout_VolumeNoneInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft ) -{ - return -1; -} - /* Placeholder for pf_volume_get(). */ int aout_VolumeNoneGet( aout_instance_t * p_aout, audio_volume_t * pi_volume ) { + (void)p_aout; (void)pi_volume; return -1; } - /* Placeholder for pf_volume_set(). */ int aout_VolumeNoneSet( aout_instance_t * p_aout, audio_volume_t i_volume ) { + (void)p_aout; (void)i_volume; return -1; } + +/* + * Pipelines management + */ + +/***************************************************************************** + * aout_Restart : re-open the output device and rebuild the input and output + * pipelines + ***************************************************************************** + * This function is used whenever the parameters of the output plug-in are + * changed (eg. selecting S/PDIF or PCM). + *****************************************************************************/ +static int aout_Restart( aout_instance_t * p_aout ) +{ + int i; + bool b_error = 0; + + aout_lock_mixer( p_aout ); + + if ( p_aout->i_nb_inputs == 0 ) + { + aout_unlock_mixer( p_aout ); + msg_Err( p_aout, "no decoder thread" ); + return -1; + } + + /* Lock all inputs. */ + aout_lock_input_fifos( p_aout ); + + for ( i = 0; i < p_aout->i_nb_inputs; i++ ) + { + aout_lock_input( p_aout, p_aout->pp_inputs[i] ); + aout_InputDelete( p_aout, p_aout->pp_inputs[i] ); + } + + aout_MixerDelete( p_aout ); + + /* Re-open the output plug-in. */ + aout_OutputDelete( p_aout ); + + if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 ) + { + /* Release all locks and report the error. */ + for ( i = 0; i < p_aout->i_nb_inputs; i++ ) + { + vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock ); + } + aout_unlock_input_fifos( p_aout ); + aout_unlock_mixer( p_aout ); + return -1; + } + + if ( aout_MixerNew( p_aout ) == -1 ) + { + aout_OutputDelete( p_aout ); + for ( i = 0; i < p_aout->i_nb_inputs; i++ ) + { + vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock ); + } + aout_unlock_input_fifos( p_aout ); + aout_unlock_mixer( p_aout ); + return -1; + } + + /* Re-open all inputs. */ + for ( i = 0; i < p_aout->i_nb_inputs; i++ ) + { + aout_input_t * p_input = p_aout->pp_inputs[i]; + b_error |= aout_InputNew( p_aout, p_input, &p_input->request_vout ); + p_input->b_changed = 1; + aout_unlock_input( p_aout, p_input ); + } + + aout_unlock_input_fifos( p_aout ); + aout_unlock_mixer( p_aout ); + + return b_error; +} + +/***************************************************************************** + * aout_FindAndRestart : find the audio output instance and restart + ***************************************************************************** + * This is used for callbacks of the configuration variables, and we believe + * that when those are changed, it is a significant change which implies + * rebuilding the audio-device and audio-channels variables. + *****************************************************************************/ +int aout_FindAndRestart( vlc_object_t * p_this, const char *psz_name, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + aout_instance_t * p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, + FIND_ANYWHERE ); + + (void)psz_name; (void)oldval; (void)newval; (void)p_data; + if ( p_aout == NULL ) return VLC_SUCCESS; + + var_Destroy( p_aout, "audio-device" ); + var_Destroy( p_aout, "audio-channels" ); + + aout_Restart( p_aout ); + vlc_object_release( p_aout ); + + return VLC_SUCCESS; +} + +/***************************************************************************** + * aout_ChannelsRestart : change the audio device or channels and restart + *****************************************************************************/ +int aout_ChannelsRestart( vlc_object_t * p_this, const char * psz_variable, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ) +{ + aout_instance_t * p_aout = (aout_instance_t *)p_this; + (void)oldval; (void)newval; (void)p_data; + + if ( !strcmp( psz_variable, "audio-device" ) ) + { + /* This is supposed to be a significant change and supposes + * rebuilding the channel choices. */ + var_Destroy( p_aout, "audio-channels" ); + } + aout_Restart( p_aout ); + return 0; +} + +#undef aout_EnableFilter +/** Enable or disable an audio filter + * \param p_this a vlc object + * \param psz_name name of the filter + * \param b_add are we adding or removing the filter ? + */ +void aout_EnableFilter( vlc_object_t *p_this, const char *psz_name, + bool b_add ) +{ + aout_instance_t *p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, + FIND_ANYWHERE ); + + if( AoutChangeFilterString( p_this, p_aout, "audio-filter", psz_name, b_add ) ) + { + if( p_aout ) + AoutInputsMarkToRestart( p_aout ); + } + + if( p_aout ) + vlc_object_release( p_aout ); +}