intf.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:14k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * intf.c : audio output API towards the interface modules
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2004 VideoLAN
  5.  * $Id: intf.c 8905 2004-10-04 13:34:42Z gbazin $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                            /* calloc(), malloc(), free() */
  27. #include <string.h>
  28. #include <vlc/vlc.h>
  29. #include "audio_output.h"
  30. #include "aout_internal.h"
  31. /*
  32.  * Volume management
  33.  *
  34.  * The hardware volume cannot be set if the output module gets deleted, so
  35.  * we must take the mixer lock. The software volume cannot be set while the
  36.  * mixer is running, so we need the mixer lock (too).
  37.  *
  38.  * Here is a schematic of the i_volume range :
  39.  *
  40.  * |------------------------------+---------------------------------------|
  41.  * 0                           pi_soft                                   1024
  42.  *
  43.  * Between 0 and pi_soft, the volume is done in hardware by the output
  44.  * module. Above, the output module will change p_aout->mixer.i_multiplier
  45.  * (done in software). This scaling may result * in cropping errors and
  46.  * should be avoided as much as possible.
  47.  *
  48.  * It is legal to have *pi_soft == 0, and do everything in software.
  49.  * It is also legal to have *pi_soft == 1024, and completely avoid
  50.  * software scaling. However, some streams (esp. A/52) are encoded with
  51.  * a very low volume and users may complain.
  52.  */
  53. /*****************************************************************************
  54.  * aout_VolumeGet : get the volume of the output device
  55.  *****************************************************************************/
  56. int __aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume )
  57. {
  58.     int i;
  59.     i = config_GetInt( p_object, "volume" );
  60.     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t)i;
  61.     return 0;
  62. }
  63. /*****************************************************************************
  64.  * aout_VolumeSet : set the volume of the output device
  65.  *****************************************************************************/
  66. int __aout_VolumeSet( vlc_object_t * p_object, audio_volume_t i_volume )
  67. {
  68.     vlc_value_t val;
  69.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  70.                                                 FIND_ANYWHERE );
  71.     int i_result = 0;
  72.     config_PutInt( p_object, "volume", i_volume );
  73.     if ( p_aout == NULL ) return 0;
  74.     vlc_mutex_lock( &p_aout->mixer_lock );
  75.     if ( !p_aout->mixer.b_error )
  76.     {
  77.         i_result = p_aout->output.pf_volume_set( p_aout, i_volume );
  78.     }
  79.     vlc_mutex_unlock( &p_aout->mixer_lock );
  80.     vlc_object_release( p_aout );
  81.     val.b_bool = VLC_TRUE;
  82.     var_Set( p_aout, "intf-change", val );
  83.     return i_result;
  84. }
  85. /*****************************************************************************
  86.  * aout_VolumeInfos : get the boundary pi_soft
  87.  *****************************************************************************/
  88. int __aout_VolumeInfos( vlc_object_t * p_object, audio_volume_t * pi_soft )
  89. {
  90.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  91.                                                 FIND_ANYWHERE );
  92.     int i_result;
  93.     if ( p_aout == NULL ) return 0;
  94.     vlc_mutex_lock( &p_aout->mixer_lock );
  95.     if ( p_aout->mixer.b_error )
  96.     {
  97.         /* The output module is destroyed. */
  98.         i_result = -1;
  99.     }
  100.     else
  101.     {
  102.         i_result = p_aout->output.pf_volume_infos( p_aout, pi_soft );
  103.     }
  104.     vlc_mutex_unlock( &p_aout->mixer_lock );
  105.     vlc_object_release( p_aout );
  106.     return i_result;
  107. }
  108. /*****************************************************************************
  109.  * aout_VolumeUp : raise the output volume
  110.  *****************************************************************************
  111.  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
  112.  * function.
  113.  *****************************************************************************/
  114. int __aout_VolumeUp( vlc_object_t * p_object, int i_nb_steps,
  115.                    audio_volume_t * pi_volume )
  116. {
  117.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  118.                                                 FIND_ANYWHERE );
  119.     int i_result = 0, i;
  120.     i = config_GetInt( p_object, "volume" );
  121.     i += AOUT_VOLUME_STEP * i_nb_steps;
  122.     if ( i > AOUT_VOLUME_MAX )
  123.     {
  124.         i = AOUT_VOLUME_MAX;
  125.     }
  126.     config_PutInt( p_object, "volume", i );
  127.     config_PutInt( p_object, "saved-volume", i );
  128.     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t)i;
  129.     if ( p_aout == NULL ) return 0;
  130.     vlc_mutex_lock( &p_aout->mixer_lock );
  131.     if ( !p_aout->mixer.b_error )
  132.     {
  133.         i_result = p_aout->output.pf_volume_set( p_aout, (audio_volume_t)i );
  134.     }
  135.     vlc_mutex_unlock( &p_aout->mixer_lock );
  136.     vlc_object_release( p_aout );
  137.     return i_result;
  138. }
  139. /*****************************************************************************
  140.  * aout_VolumeDown : lower the output volume
  141.  *****************************************************************************
  142.  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
  143.  * function.
  144.  *****************************************************************************/
  145. int __aout_VolumeDown( vlc_object_t * p_object, int i_nb_steps,
  146.                      audio_volume_t * pi_volume )
  147. {
  148.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  149.                                                 FIND_ANYWHERE );
  150.     int i_result = 0, i;
  151.     i = config_GetInt( p_object, "volume" );
  152.     i -= AOUT_VOLUME_STEP * i_nb_steps;
  153.     if ( i < AOUT_VOLUME_MIN )
  154.     {
  155.         i = AOUT_VOLUME_MIN;
  156.     }
  157.     config_PutInt( p_object, "volume", i );
  158.     config_PutInt( p_object, "saved-volume", i );
  159.     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t)i;
  160.     if ( p_aout == NULL ) return 0;
  161.     vlc_mutex_lock( &p_aout->mixer_lock );
  162.     if ( !p_aout->mixer.b_error )
  163.     {
  164.         i_result = p_aout->output.pf_volume_set( p_aout, (audio_volume_t)i );
  165.     }
  166.     vlc_mutex_unlock( &p_aout->mixer_lock );
  167.     vlc_object_release( p_aout );
  168.     return i_result;
  169. }
  170. /*****************************************************************************
  171.  * aout_VolumeMute : Mute/un-mute the output volume
  172.  *****************************************************************************
  173.  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
  174.  * function (muted => 0).
  175.  *****************************************************************************/
  176. int __aout_VolumeMute( vlc_object_t * p_object, audio_volume_t * pi_volume )
  177. {
  178.     int i_result;
  179.     audio_volume_t i_volume;
  180.     i_volume = (audio_volume_t)config_GetInt( p_object, "volume" );
  181.     if ( i_volume != 0 )
  182.     {
  183.         /* Mute */
  184.         i_result = aout_VolumeSet( p_object, AOUT_VOLUME_MIN );
  185.         config_PutInt( p_object, "saved-volume", (int)i_volume );
  186.         if ( pi_volume != NULL ) *pi_volume = AOUT_VOLUME_MIN;
  187.     }
  188.     else
  189.     {
  190.         /* Un-mute */
  191.         i_volume = (audio_volume_t)config_GetInt( p_object, "saved-volume" );
  192.         i_result = aout_VolumeSet( p_object, i_volume );
  193.         if ( pi_volume != NULL ) *pi_volume = i_volume;
  194.     }
  195.     return i_result;
  196. }
  197. /*
  198.  * The next functions are not supposed to be called by the interface, but
  199.  * are placeholders for software-only scaling.
  200.  */
  201. /* Meant to be called by the output plug-in's Open(). */
  202. void aout_VolumeSoftInit( aout_instance_t * p_aout )
  203. {
  204.     int i_volume;
  205.     p_aout->output.pf_volume_infos = aout_VolumeSoftInfos;
  206.     p_aout->output.pf_volume_get = aout_VolumeSoftGet;
  207.     p_aout->output.pf_volume_set = aout_VolumeSoftSet;
  208.     i_volume = config_GetInt( p_aout, "volume" );
  209.     if ( i_volume < AOUT_VOLUME_MIN )
  210.     {
  211.         i_volume = AOUT_VOLUME_DEFAULT;
  212.     }
  213.     else if ( i_volume > AOUT_VOLUME_MAX )
  214.     {
  215.         i_volume = AOUT_VOLUME_MAX;
  216.     }
  217.     aout_VolumeSoftSet( p_aout, (audio_volume_t)i_volume );
  218. }
  219. /* Placeholder for pf_volume_infos(). */
  220. int aout_VolumeSoftInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
  221. {
  222.     *pi_soft = 0;
  223.     return 0;
  224. }
  225. /* Placeholder for pf_volume_get(). */
  226. int aout_VolumeSoftGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
  227. {
  228.     *pi_volume = p_aout->output.i_volume;
  229.     return 0;
  230. }
  231. /* Placeholder for pf_volume_set(). */
  232. int aout_VolumeSoftSet( aout_instance_t * p_aout, audio_volume_t i_volume )
  233. {
  234.     aout_MixerMultiplierSet( p_aout, (float)i_volume / AOUT_VOLUME_DEFAULT );
  235.     p_aout->output.i_volume = i_volume;
  236.     return 0;
  237. }
  238. /*
  239.  * The next functions are not supposed to be called by the interface, but
  240.  * are placeholders for unsupported scaling.
  241.  */
  242. /* Meant to be called by the output plug-in's Open(). */
  243. void aout_VolumeNoneInit( aout_instance_t * p_aout )
  244. {
  245.     p_aout->output.pf_volume_infos = aout_VolumeNoneInfos;
  246.     p_aout->output.pf_volume_get = aout_VolumeNoneGet;
  247.     p_aout->output.pf_volume_set = aout_VolumeNoneSet;
  248. }
  249. /* Placeholder for pf_volume_infos(). */
  250. int aout_VolumeNoneInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
  251. {
  252.     return -1;
  253. }
  254. /* Placeholder for pf_volume_get(). */
  255. int aout_VolumeNoneGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
  256. {
  257.     return -1;
  258. }
  259. /* Placeholder for pf_volume_set(). */
  260. int aout_VolumeNoneSet( aout_instance_t * p_aout, audio_volume_t i_volume )
  261. {
  262.     return -1;
  263. }
  264. /*
  265.  * Pipelines management
  266.  */
  267. /*****************************************************************************
  268.  * aout_Restart : re-open the output device and rebuild the input and output
  269.  *                pipelines
  270.  *****************************************************************************
  271.  * This function is used whenever the parameters of the output plug-in are
  272.  * changed (eg. selecting S/PDIF or PCM).
  273.  *****************************************************************************/
  274. int aout_Restart( aout_instance_t * p_aout )
  275. {
  276.     int i;
  277.     vlc_bool_t b_error = 0;
  278.     vlc_mutex_lock( &p_aout->mixer_lock );
  279.     if ( p_aout->i_nb_inputs == 0 )
  280.     {
  281.         vlc_mutex_unlock( &p_aout->mixer_lock );
  282.         msg_Err( p_aout, "no decoder thread" );
  283.         return -1;
  284.     }
  285.     /* Lock all inputs. */
  286.     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  287.     {
  288.         vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
  289.         aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
  290.     }
  291.     aout_MixerDelete( p_aout );
  292.     /* Re-open the output plug-in. */
  293.     aout_OutputDelete( p_aout );
  294.     if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 )
  295.     {
  296.         /* Release all locks and report the error. */
  297.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  298.         {
  299.             vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
  300.         }
  301.         vlc_mutex_unlock( &p_aout->mixer_lock );
  302.         return -1;
  303.     }
  304.     if ( aout_MixerNew( p_aout ) == -1 )
  305.     {
  306.         aout_OutputDelete( p_aout );
  307.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  308.         {
  309.             vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
  310.         }
  311.         vlc_mutex_unlock( &p_aout->mixer_lock );
  312.         return -1;
  313.     }
  314.     /* Re-open all inputs. */
  315.     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  316.     {
  317.         aout_input_t * p_input = p_aout->pp_inputs[i];
  318.         b_error |= aout_InputNew( p_aout, p_input );
  319.         p_input->b_changed = 1;
  320.         vlc_mutex_unlock( &p_input->lock );
  321.     }
  322.     vlc_mutex_unlock( &p_aout->mixer_lock );
  323.     return b_error;
  324. }
  325. /*****************************************************************************
  326.  * aout_FindAndRestart : find the audio output instance and restart
  327.  *****************************************************************************
  328.  * This is used for callbacks of the configuration variables, and we believe
  329.  * that when those are changed, it is a significant change which implies
  330.  * rebuilding the audio-device and audio-channels variables.
  331.  *****************************************************************************/
  332. int aout_FindAndRestart( vlc_object_t * p_this, const char *psz_name,
  333.                          vlc_value_t oldval, vlc_value_t val, void *p_data )
  334. {
  335.     aout_instance_t * p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT,
  336.                                                 FIND_ANYWHERE );
  337.     if ( p_aout == NULL ) return VLC_SUCCESS;
  338.     if ( var_Type( p_aout, "audio-device" ) != 0 )
  339.     {
  340.         var_Destroy( p_aout, "audio-device" );
  341.     }
  342.     if ( var_Type( p_aout, "audio-channels" ) != 0 )
  343.     {
  344.         var_Destroy( p_aout, "audio-channels" );
  345.     }
  346.     aout_Restart( p_aout );
  347.     vlc_object_release( p_aout );
  348.     return VLC_SUCCESS;
  349. }
  350. /*****************************************************************************
  351.  * aout_ChannelsRestart : change the audio device or channels and restart
  352.  *****************************************************************************/
  353. int aout_ChannelsRestart( vlc_object_t * p_this, const char * psz_variable,
  354.                           vlc_value_t old_value, vlc_value_t new_value,
  355.                           void * unused )
  356. {
  357.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  358.     if ( !strcmp( psz_variable, "audio-device" ) )
  359.     {
  360.         /* This is supposed to be a significant change and supposes
  361.          * rebuilding the channel choices. */
  362.         if ( var_Type( p_aout, "audio-channels" ) >= 0 )
  363.         {
  364.             var_Destroy( p_aout, "audio-channels" );
  365.         }
  366.     }
  367.     aout_Restart( p_aout );
  368.     return 0;
  369. }