Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

intf.c

00001 /*****************************************************************************
00002  * intf.c : audio output API towards the interface modules
00003  *****************************************************************************
00004  * Copyright (C) 2002-2004 the VideoLAN team
00005  * $Id: intf.c 13250 2005-11-14 21:17:45Z jpsaman $
00006  *
00007  * Authors: Christophe Massiot <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <stdlib.h>                            /* calloc(), malloc(), free() */
00028 #include <string.h>
00029 
00030 #include <vlc/vlc.h>
00031 
00032 #include "audio_output.h"
00033 #include "aout_internal.h"
00034 
00035 
00036 /*
00037  * Volume management
00038  *
00039  * The hardware volume cannot be set if the output module gets deleted, so
00040  * we must take the mixer lock. The software volume cannot be set while the
00041  * mixer is running, so we need the mixer lock (too).
00042  *
00043  * Here is a schematic of the i_volume range :
00044  *
00045  * |------------------------------+---------------------------------------|
00046  * 0                           pi_soft                                   1024
00047  *
00048  * Between 0 and pi_soft, the volume is done in hardware by the output
00049  * module. Above, the output module will change p_aout->mixer.i_multiplier
00050  * (done in software). This scaling may result * in cropping errors and
00051  * should be avoided as much as possible.
00052  *
00053  * It is legal to have *pi_soft == 0, and do everything in software.
00054  * It is also legal to have *pi_soft == 1024, and completely avoid
00055  * software scaling. However, some streams (esp. A/52) are encoded with
00056  * a very low volume and users may complain.
00057  */
00058 
00059 /*****************************************************************************
00060  * aout_VolumeGet : get the volume of the output device
00061  *****************************************************************************/
00062 int __aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume )
00063 {
00064     int i_volume, i_result = 0;
00065     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
00066                                                 FIND_ANYWHERE );
00067 
00068     i_volume = config_GetInt( p_object, "volume" );
00069     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t)i_volume;
00070 
00071     if ( p_aout == NULL ) return 0;
00072 
00073     vlc_mutex_lock( &p_aout->mixer_lock );
00074     if ( !p_aout->mixer.b_error )
00075     {
00076         i_result = p_aout->output.pf_volume_get( p_aout, pi_volume );
00077     }
00078     vlc_mutex_unlock( &p_aout->mixer_lock );
00079 
00080     vlc_object_release( p_aout );
00081     return i_result;
00082 }
00083 
00084 /*****************************************************************************
00085  * aout_VolumeSet : set the volume of the output device
00086  *****************************************************************************/
00087 int __aout_VolumeSet( vlc_object_t * p_object, audio_volume_t i_volume )
00088 {
00089     vlc_value_t val;
00090     aout_instance_t *p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT, FIND_ANYWHERE );
00091     int i_result = 0;
00092 
00093     config_PutInt( p_object, "volume", i_volume );
00094 
00095     val.b_bool = VLC_TRUE;
00096     var_Set( p_object->p_vlc, "volume-change", val );
00097 
00098     if ( p_aout == NULL ) return 0;
00099 
00100     vlc_mutex_lock( &p_aout->mixer_lock );
00101     if ( !p_aout->mixer.b_error )
00102     {
00103         i_result = p_aout->output.pf_volume_set( p_aout, i_volume );
00104     }
00105     vlc_mutex_unlock( &p_aout->mixer_lock );
00106 
00107     var_Set( p_aout, "intf-change", val );
00108     vlc_object_release( p_aout );
00109     return i_result;
00110 }
00111 
00112 /*****************************************************************************
00113  * aout_VolumeInfos : get the boundary pi_soft
00114  *****************************************************************************/
00115 int __aout_VolumeInfos( vlc_object_t * p_object, audio_volume_t * pi_soft )
00116 {
00117     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
00118                                                 FIND_ANYWHERE );
00119     int i_result;
00120 
00121     if ( p_aout == NULL ) return 0;
00122 
00123     vlc_mutex_lock( &p_aout->mixer_lock );
00124     if ( p_aout->mixer.b_error )
00125     {
00126         /* The output module is destroyed. */
00127         i_result = -1;
00128     }
00129     else
00130     {
00131         i_result = p_aout->output.pf_volume_infos( p_aout, pi_soft );
00132     }
00133     vlc_mutex_unlock( &p_aout->mixer_lock );
00134 
00135     vlc_object_release( p_aout );
00136     return i_result;
00137 }
00138 
00139 /*****************************************************************************
00140  * aout_VolumeUp : raise the output volume
00141  *****************************************************************************
00142  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
00143  * function.
00144  *****************************************************************************/
00145 int __aout_VolumeUp( vlc_object_t * p_object, int i_nb_steps,
00146                    audio_volume_t * pi_volume )
00147 {
00148     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
00149                                                 FIND_ANYWHERE );
00150     int i_result = 0, i_volume = 0, i_volume_step = 0;
00151 
00152     i_volume_step = config_GetInt( p_object->p_vlc, "volume-step" );
00153     i_volume = config_GetInt( p_object, "volume" );
00154     i_volume += i_volume_step * i_nb_steps;
00155     if ( i_volume > AOUT_VOLUME_MAX )
00156     {
00157         i_volume = AOUT_VOLUME_MAX;
00158     }
00159     config_PutInt( p_object, "volume", i_volume );
00160     var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
00161     var_SetInteger( p_object->p_libvlc, "saved-volume" , (audio_volume_t) i_volume );
00162     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t) i_volume;
00163 
00164     if ( p_aout == NULL ) return 0;
00165 
00166     vlc_mutex_lock( &p_aout->mixer_lock );
00167     if ( !p_aout->mixer.b_error )
00168     {
00169         i_result = p_aout->output.pf_volume_set( p_aout, (audio_volume_t) i_volume );
00170     }
00171     vlc_mutex_unlock( &p_aout->mixer_lock );
00172 
00173     vlc_object_release( p_aout );
00174     return i_result;
00175 }
00176 
00177 /*****************************************************************************
00178  * aout_VolumeDown : lower the output volume
00179  *****************************************************************************
00180  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
00181  * function.
00182  *****************************************************************************/
00183 int __aout_VolumeDown( vlc_object_t * p_object, int i_nb_steps,
00184                      audio_volume_t * pi_volume )
00185 {
00186     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
00187                                                 FIND_ANYWHERE );
00188     int i_result = 0, i_volume = 0, i_volume_step = 0;
00189 
00190     i_volume_step = config_GetInt( p_object->p_vlc, "volume-step" );
00191     i_volume = config_GetInt( p_object, "volume" );
00192     i_volume -= i_volume_step * i_nb_steps;
00193     if ( i_volume < AOUT_VOLUME_MIN )
00194     {
00195         i_volume = AOUT_VOLUME_MIN;
00196     }
00197     config_PutInt( p_object, "volume", i_volume );
00198     var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
00199     var_SetInteger( p_object->p_libvlc, "saved-volume", (audio_volume_t) i_volume );
00200     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t) i_volume;
00201 
00202     if ( p_aout == NULL ) return 0;
00203 
00204     vlc_mutex_lock( &p_aout->mixer_lock );
00205     if ( !p_aout->mixer.b_error )
00206     {
00207         i_result = p_aout->output.pf_volume_set( p_aout, (audio_volume_t) i_volume );
00208     }
00209     vlc_mutex_unlock( &p_aout->mixer_lock );
00210 
00211     vlc_object_release( p_aout );
00212     return i_result;
00213 }
00214 
00215 /*****************************************************************************
00216  * aout_VolumeMute : Mute/un-mute the output volume
00217  *****************************************************************************
00218  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
00219  * function (muted => 0).
00220  *****************************************************************************/
00221 int __aout_VolumeMute( vlc_object_t * p_object, audio_volume_t * pi_volume )
00222 {
00223     int i_result;
00224     audio_volume_t i_volume;
00225 
00226     i_volume = (audio_volume_t)config_GetInt( p_object, "volume" );
00227     if ( i_volume != 0 )
00228     {
00229         /* Mute */
00230         i_result = aout_VolumeSet( p_object, AOUT_VOLUME_MIN );
00231         var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
00232         var_SetInteger( p_object->p_libvlc, "saved-volume", (int)i_volume );
00233         if ( pi_volume != NULL ) *pi_volume = AOUT_VOLUME_MIN;
00234     }
00235     else
00236     {
00237         /* Un-mute */
00238         var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
00239         i_volume = (audio_volume_t)var_GetInteger( p_object->p_libvlc,
00240                                                    "saved-volume" );
00241         i_result = aout_VolumeSet( p_object, i_volume );
00242         if ( pi_volume != NULL ) *pi_volume = i_volume;
00243     }
00244 
00245     return i_result;
00246 }
00247 
00248 /*
00249  * The next functions are not supposed to be called by the interface, but
00250  * are placeholders for software-only scaling.
00251  */
00252 
00253 /* Meant to be called by the output plug-in's Open(). */
00254 void aout_VolumeSoftInit( aout_instance_t * p_aout )
00255 {
00256     int i_volume;
00257 
00258     p_aout->output.pf_volume_infos = aout_VolumeSoftInfos;
00259     p_aout->output.pf_volume_get = aout_VolumeSoftGet;
00260     p_aout->output.pf_volume_set = aout_VolumeSoftSet;
00261 
00262     i_volume = config_GetInt( p_aout, "volume" );
00263     if ( i_volume < AOUT_VOLUME_MIN )
00264     {
00265         i_volume = AOUT_VOLUME_DEFAULT;
00266     }
00267     else if ( i_volume > AOUT_VOLUME_MAX )
00268     {
00269         i_volume = AOUT_VOLUME_MAX;
00270     }
00271 
00272     aout_VolumeSoftSet( p_aout, (audio_volume_t)i_volume );
00273 }
00274 
00275 /* Placeholder for pf_volume_infos(). */
00276 int aout_VolumeSoftInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
00277 {
00278     *pi_soft = 0;
00279     return 0;
00280 }
00281 
00282 /* Placeholder for pf_volume_get(). */
00283 int aout_VolumeSoftGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
00284 {
00285     *pi_volume = p_aout->output.i_volume;
00286     return 0;
00287 }
00288 
00289 
00290 /* Placeholder for pf_volume_set(). */
00291 int aout_VolumeSoftSet( aout_instance_t * p_aout, audio_volume_t i_volume )
00292 {
00293     aout_MixerMultiplierSet( p_aout, (float)i_volume / AOUT_VOLUME_DEFAULT );
00294     p_aout->output.i_volume = i_volume;
00295     return 0;
00296 }
00297 
00298 /*
00299  * The next functions are not supposed to be called by the interface, but
00300  * are placeholders for unsupported scaling.
00301  */
00302 
00303 /* Meant to be called by the output plug-in's Open(). */
00304 void aout_VolumeNoneInit( aout_instance_t * p_aout )
00305 {
00306     p_aout->output.pf_volume_infos = aout_VolumeNoneInfos;
00307     p_aout->output.pf_volume_get = aout_VolumeNoneGet;
00308     p_aout->output.pf_volume_set = aout_VolumeNoneSet;
00309 }
00310 
00311 /* Placeholder for pf_volume_infos(). */
00312 int aout_VolumeNoneInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
00313 {
00314     return -1;
00315 }
00316 
00317 /* Placeholder for pf_volume_get(). */
00318 int aout_VolumeNoneGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
00319 {
00320     return -1;
00321 }
00322 
00323 /* Placeholder for pf_volume_set(). */
00324 int aout_VolumeNoneSet( aout_instance_t * p_aout, audio_volume_t i_volume )
00325 {
00326     return -1;
00327 }
00328 
00329 
00330 /*
00331  * Pipelines management
00332  */
00333 
00334 /*****************************************************************************
00335  * aout_Restart : re-open the output device and rebuild the input and output
00336  *                pipelines
00337  *****************************************************************************
00338  * This function is used whenever the parameters of the output plug-in are
00339  * changed (eg. selecting S/PDIF or PCM).
00340  *****************************************************************************/
00341 int aout_Restart( aout_instance_t * p_aout )
00342 {
00343     int i;
00344     vlc_bool_t b_error = 0;
00345 
00346     vlc_mutex_lock( &p_aout->mixer_lock );
00347 
00348     if ( p_aout->i_nb_inputs == 0 )
00349     {
00350         vlc_mutex_unlock( &p_aout->mixer_lock );
00351         msg_Err( p_aout, "no decoder thread" );
00352         return -1;
00353     }
00354 
00355     /* Lock all inputs. */
00356     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
00357     {
00358         vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
00359         aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
00360     }
00361 
00362     aout_MixerDelete( p_aout );
00363 
00364     /* Re-open the output plug-in. */
00365     aout_OutputDelete( p_aout );
00366 
00367     if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 )
00368     {
00369         /* Release all locks and report the error. */
00370         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
00371         {
00372             vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
00373         }
00374         vlc_mutex_unlock( &p_aout->mixer_lock );
00375         return -1;
00376     }
00377 
00378     if ( aout_MixerNew( p_aout ) == -1 )
00379     {
00380         aout_OutputDelete( p_aout );
00381         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
00382         {
00383             vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
00384         }
00385         vlc_mutex_unlock( &p_aout->mixer_lock );
00386         return -1;
00387     }
00388 
00389     /* Re-open all inputs. */
00390     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
00391     {
00392         aout_input_t * p_input = p_aout->pp_inputs[i];
00393 
00394         b_error |= aout_InputNew( p_aout, p_input );
00395         p_input->b_changed = 1;
00396         vlc_mutex_unlock( &p_input->lock );
00397     }
00398 
00399     vlc_mutex_unlock( &p_aout->mixer_lock );
00400 
00401     return b_error;
00402 }
00403 
00404 /*****************************************************************************
00405  * aout_FindAndRestart : find the audio output instance and restart
00406  *****************************************************************************
00407  * This is used for callbacks of the configuration variables, and we believe
00408  * that when those are changed, it is a significant change which implies
00409  * rebuilding the audio-device and audio-channels variables.
00410  *****************************************************************************/
00411 int aout_FindAndRestart( vlc_object_t * p_this, const char *psz_name,
00412                          vlc_value_t oldval, vlc_value_t val, void *p_data )
00413 {
00414     aout_instance_t * p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT,
00415                                                 FIND_ANYWHERE );
00416 
00417     if ( p_aout == NULL ) return VLC_SUCCESS;
00418 
00419     if ( var_Type( p_aout, "audio-device" ) != 0 )
00420     {
00421         var_Destroy( p_aout, "audio-device" );
00422     }
00423     if ( var_Type( p_aout, "audio-channels" ) != 0 )
00424     {
00425         var_Destroy( p_aout, "audio-channels" );
00426     }
00427 
00428     aout_Restart( p_aout );
00429     vlc_object_release( p_aout );
00430 
00431     return VLC_SUCCESS;
00432 }
00433 
00434 /*****************************************************************************
00435  * aout_ChannelsRestart : change the audio device or channels and restart
00436  *****************************************************************************/
00437 int aout_ChannelsRestart( vlc_object_t * p_this, const char * psz_variable,
00438                           vlc_value_t old_value, vlc_value_t new_value,
00439                           void * unused )
00440 {
00441     aout_instance_t * p_aout = (aout_instance_t *)p_this;
00442 
00443     if ( !strcmp( psz_variable, "audio-device" ) )
00444     {
00445         /* This is supposed to be a significant change and supposes
00446          * rebuilding the channel choices. */
00447         if ( var_Type( p_aout, "audio-channels" ) >= 0 )
00448         {
00449             var_Destroy( p_aout, "audio-channels" );
00450         }
00451     }
00452     aout_Restart( p_aout );
00453     return 0;
00454 }

Generated on Tue Dec 20 10:14:27 2005 for vlc-0.8.4a by  doxygen 1.4.2