intf.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:17k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * intf.c : audio output API towards the interface modules
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2007 the VideoLAN team
  5.  * $Id: 3f517d787738c9fa8190c6fd348fc4d3eb2f29d7 $
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>                            /* calloc(), malloc(), free() */
  32. #include <string.h>
  33. #include <vlc_aout.h>
  34. #include "aout_internal.h"
  35. /*
  36.  * Volume management
  37.  *
  38.  * The hardware volume cannot be set if the output module gets deleted, so
  39.  * we must take the mixer lock. The software volume cannot be set while the
  40.  * mixer is running, so we need the mixer lock (too).
  41.  *
  42.  * Here is a schematic of the i_volume range :
  43.  *
  44.  * |------------------------------+---------------------------------------|
  45.  * 0                           pi_soft                                   1024
  46.  *
  47.  * Between 0 and pi_soft, the volume is done in hardware by the output
  48.  * module. Above, the output module will change p_aout->mixer.i_multiplier
  49.  * (done in software). This scaling may result * in cropping errors and
  50.  * should be avoided as much as possible.
  51.  *
  52.  * It is legal to have *pi_soft == 0, and do everything in software.
  53.  * It is also legal to have *pi_soft == 1024, and completely avoid
  54.  * software scaling. However, some streams (esp. A/52) are encoded with
  55.  * a very low volume and users may complain.
  56.  */
  57. /*****************************************************************************
  58.  * aout_VolumeGet : get the volume of the output device
  59.  *****************************************************************************/
  60. int __aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume )
  61. {
  62.     int i_result = 0;
  63.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  64.                                                 FIND_ANYWHERE );
  65.     if ( pi_volume == NULL ) return -1;
  66.     if ( p_aout == NULL )
  67.     {
  68.         *pi_volume = (audio_volume_t)config_GetInt( p_object, "volume" );
  69.         return 0;
  70.     }
  71.     aout_lock_mixer( p_aout );
  72.     if ( !p_aout->mixer.b_error )
  73.     {
  74.         i_result = p_aout->output.pf_volume_get( p_aout, pi_volume );
  75.     }
  76.     else
  77.     {
  78.         *pi_volume = (audio_volume_t)config_GetInt( p_object, "volume" );
  79.     }
  80.     aout_unlock_mixer( p_aout );
  81.     vlc_object_release( p_aout );
  82.     return i_result;
  83. }
  84. /*****************************************************************************
  85.  * aout_VolumeSet : set the volume of the output device
  86.  *****************************************************************************/
  87. int __aout_VolumeSet( vlc_object_t * p_object, audio_volume_t i_volume )
  88. {
  89.     aout_instance_t *p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT, FIND_ANYWHERE );
  90.     int i_result = 0;
  91.     config_PutInt( p_object, "volume", i_volume );
  92.     var_SetBool( p_object->p_libvlc, "volume-change", true );
  93.     if ( p_aout == NULL ) return 0;
  94.     aout_lock_mixer( p_aout );
  95.     if ( !p_aout->mixer.b_error )
  96.     {
  97.         i_result = p_aout->output.pf_volume_set( p_aout, i_volume );
  98.     }
  99.     aout_unlock_mixer( p_aout );
  100.     var_SetBool( p_aout, "intf-change", true );
  101.     vlc_object_release( p_aout );
  102.     return i_result;
  103. }
  104. /*****************************************************************************
  105.  * aout_VolumeInfos : get the boundary pi_soft
  106.  *****************************************************************************/
  107. int __aout_VolumeInfos( vlc_object_t * p_object, audio_volume_t * pi_soft )
  108. {
  109.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  110.                                                 FIND_ANYWHERE );
  111.     int i_result;
  112.     if ( p_aout == NULL ) return 0;
  113.     aout_lock_mixer( p_aout );
  114.     if ( p_aout->mixer.b_error )
  115.     {
  116.         /* The output module is destroyed. */
  117.         i_result = -1;
  118.     }
  119.     else
  120.     {
  121.         i_result = p_aout->output.pf_volume_infos( p_aout, pi_soft );
  122.     }
  123.     aout_unlock_mixer( p_aout );
  124.     vlc_object_release( p_aout );
  125.     return i_result;
  126. }
  127. /*****************************************************************************
  128.  * aout_VolumeUp : raise the output volume
  129.  *****************************************************************************
  130.  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
  131.  * function.
  132.  *****************************************************************************/
  133. int __aout_VolumeUp( vlc_object_t * p_object, int i_nb_steps,
  134.                    audio_volume_t * pi_volume )
  135. {
  136.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  137.                                                 FIND_ANYWHERE );
  138.     int i_result = 0, i_volume = 0, i_volume_step = 0;
  139.     i_volume_step = config_GetInt( p_object->p_libvlc, "volume-step" );
  140.     i_volume = config_GetInt( p_object, "volume" );
  141.     i_volume += i_volume_step * i_nb_steps;
  142.     if ( i_volume > AOUT_VOLUME_MAX )
  143.     {
  144.         i_volume = AOUT_VOLUME_MAX;
  145.     }
  146.     config_PutInt( p_object, "volume", i_volume );
  147.     var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
  148.     var_SetInteger( p_object->p_libvlc, "saved-volume" ,
  149.                     (audio_volume_t) i_volume );
  150.     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t) i_volume;
  151.     var_SetBool( p_object->p_libvlc, "volume-change", true );
  152.     if ( p_aout == NULL ) return 0;
  153.     aout_lock_mixer( p_aout );
  154.     if ( !p_aout->mixer.b_error )
  155.     {
  156.         i_result = p_aout->output.pf_volume_set( p_aout,
  157.                                                 (audio_volume_t) i_volume );
  158.     }
  159.     aout_unlock_mixer( p_aout );
  160.     vlc_object_release( p_aout );
  161.     return i_result;
  162. }
  163. /*****************************************************************************
  164.  * aout_VolumeDown : lower the output volume
  165.  *****************************************************************************
  166.  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
  167.  * function.
  168.  *****************************************************************************/
  169. int __aout_VolumeDown( vlc_object_t * p_object, int i_nb_steps,
  170.                      audio_volume_t * pi_volume )
  171. {
  172.     aout_instance_t * p_aout = vlc_object_find( p_object, VLC_OBJECT_AOUT,
  173.                                                 FIND_ANYWHERE );
  174.     int i_result = 0, i_volume = 0, i_volume_step = 0;
  175.     i_volume_step = config_GetInt( p_object->p_libvlc, "volume-step" );
  176.     i_volume = config_GetInt( p_object, "volume" );
  177.     i_volume -= i_volume_step * i_nb_steps;
  178.     if ( i_volume < AOUT_VOLUME_MIN )
  179.     {
  180.         i_volume = AOUT_VOLUME_MIN;
  181.     }
  182.     config_PutInt( p_object, "volume", i_volume );
  183.     var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
  184.     var_SetInteger( p_object->p_libvlc, "saved-volume", (audio_volume_t) i_volume );
  185.     if ( pi_volume != NULL ) *pi_volume = (audio_volume_t) i_volume;
  186.     var_SetBool( p_object->p_libvlc, "volume-change", true );
  187.     if ( p_aout == NULL ) return 0;
  188.     aout_lock_mixer( p_aout );
  189.     if ( !p_aout->mixer.b_error )
  190.     {
  191.         i_result = p_aout->output.pf_volume_set( p_aout, (audio_volume_t) i_volume );
  192.     }
  193.     aout_unlock_mixer( p_aout );
  194.     vlc_object_release( p_aout );
  195.     return i_result;
  196. }
  197. /*****************************************************************************
  198.  * aout_VolumeMute : Mute/un-mute the output volume
  199.  *****************************************************************************
  200.  * If pi_volume != NULL, *pi_volume will contain the volume at the end of the
  201.  * function (muted => 0).
  202.  *****************************************************************************/
  203. int __aout_VolumeMute( vlc_object_t * p_object, audio_volume_t * pi_volume )
  204. {
  205.     int i_result;
  206.     audio_volume_t i_volume;
  207.     i_volume = (audio_volume_t)config_GetInt( p_object, "volume" );
  208.     if ( i_volume != 0 )
  209.     {
  210.         /* Mute */
  211.         i_result = aout_VolumeSet( p_object, AOUT_VOLUME_MIN );
  212.         var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
  213.         var_SetInteger( p_object->p_libvlc, "saved-volume", (int)i_volume );
  214.         if ( pi_volume != NULL ) *pi_volume = AOUT_VOLUME_MIN;
  215.     }
  216.     else
  217.     {
  218.         /* Un-mute */
  219.         var_Create( p_object->p_libvlc, "saved-volume", VLC_VAR_INTEGER );
  220.         i_volume = (audio_volume_t)var_GetInteger( p_object->p_libvlc,
  221.                                                    "saved-volume" );
  222.         i_result = aout_VolumeSet( p_object, i_volume );
  223.         if ( pi_volume != NULL ) *pi_volume = i_volume;
  224.     }
  225.     return i_result;
  226. }
  227. /*
  228.  * The next functions are not supposed to be called by the interface, but
  229.  * are placeholders for software-only scaling.
  230.  */
  231. /* Meant to be called by the output plug-in's Open(). */
  232. void aout_VolumeSoftInit( aout_instance_t * p_aout )
  233. {
  234.     int i_volume;
  235.     p_aout->output.pf_volume_infos = aout_VolumeSoftInfos;
  236.     p_aout->output.pf_volume_get = aout_VolumeSoftGet;
  237.     p_aout->output.pf_volume_set = aout_VolumeSoftSet;
  238.     i_volume = config_GetInt( p_aout, "volume" );
  239.     if ( i_volume < AOUT_VOLUME_MIN )
  240.     {
  241.         i_volume = AOUT_VOLUME_DEFAULT;
  242.     }
  243.     else if ( i_volume > AOUT_VOLUME_MAX )
  244.     {
  245.         i_volume = AOUT_VOLUME_MAX;
  246.     }
  247.     aout_VolumeSoftSet( p_aout, (audio_volume_t)i_volume );
  248. }
  249. /* Placeholder for pf_volume_infos(). */
  250. int aout_VolumeSoftInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
  251. {
  252.     (void)p_aout;
  253.     *pi_soft = 0;
  254.     return 0;
  255. }
  256. /* Placeholder for pf_volume_get(). */
  257. int aout_VolumeSoftGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
  258. {
  259.     *pi_volume = p_aout->output.i_volume;
  260.     return 0;
  261. }
  262. /* Placeholder for pf_volume_set(). */
  263. int aout_VolumeSoftSet( aout_instance_t * p_aout, audio_volume_t i_volume )
  264. {
  265.     aout_MixerMultiplierSet( p_aout, (float)i_volume / AOUT_VOLUME_DEFAULT );
  266.     p_aout->output.i_volume = i_volume;
  267.     return 0;
  268. }
  269. /*
  270.  * The next functions are not supposed to be called by the interface, but
  271.  * are placeholders for unsupported scaling.
  272.  */
  273. /* Meant to be called by the output plug-in's Open(). */
  274. void aout_VolumeNoneInit( aout_instance_t * p_aout )
  275. {
  276.     p_aout->output.pf_volume_infos = aout_VolumeNoneInfos;
  277.     p_aout->output.pf_volume_get = aout_VolumeNoneGet;
  278.     p_aout->output.pf_volume_set = aout_VolumeNoneSet;
  279. }
  280. /* Placeholder for pf_volume_infos(). */
  281. int aout_VolumeNoneInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
  282. {
  283.     (void)p_aout; (void)pi_soft;
  284.     return -1;
  285. }
  286. /* Placeholder for pf_volume_get(). */
  287. int aout_VolumeNoneGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
  288. {
  289.     (void)p_aout; (void)pi_volume;
  290.     return -1;
  291. }
  292. /* Placeholder for pf_volume_set(). */
  293. int aout_VolumeNoneSet( aout_instance_t * p_aout, audio_volume_t i_volume )
  294. {
  295.     (void)p_aout; (void)i_volume;
  296.     return -1;
  297. }
  298. /*
  299.  * Pipelines management
  300.  */
  301. /*****************************************************************************
  302.  * aout_Restart : re-open the output device and rebuild the input and output
  303.  *                pipelines
  304.  *****************************************************************************
  305.  * This function is used whenever the parameters of the output plug-in are
  306.  * changed (eg. selecting S/PDIF or PCM).
  307.  *****************************************************************************/
  308. static int aout_Restart( aout_instance_t * p_aout )
  309. {
  310.     int i;
  311.     bool b_error = 0;
  312.     aout_lock_mixer( p_aout );
  313.     if ( p_aout->i_nb_inputs == 0 )
  314.     {
  315.         aout_unlock_mixer( p_aout );
  316.         msg_Err( p_aout, "no decoder thread" );
  317.         return -1;
  318.     }
  319.     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  320.     {
  321.         aout_lock_input( p_aout, p_aout->pp_inputs[i] );
  322.         aout_lock_input_fifos( p_aout );
  323.         aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
  324.         aout_unlock_input_fifos( p_aout );
  325.     }
  326.     /* Lock all inputs. */
  327.     aout_lock_input_fifos( p_aout );
  328.     aout_MixerDelete( p_aout );
  329.     /* Re-open the output plug-in. */
  330.     aout_OutputDelete( p_aout );
  331.     if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 )
  332.     {
  333.         /* Release all locks and report the error. */
  334.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  335.         {
  336.             vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
  337.         }
  338.         aout_unlock_input_fifos( p_aout );
  339.         aout_unlock_mixer( p_aout );
  340.         return -1;
  341.     }
  342.     if ( aout_MixerNew( p_aout ) == -1 )
  343.     {
  344.         aout_OutputDelete( p_aout );
  345.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  346.         {
  347.             vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
  348.         }
  349.         aout_unlock_input_fifos( p_aout );
  350.         aout_unlock_mixer( p_aout );
  351.         return -1;
  352.     }
  353.     /* Re-open all inputs. */
  354.     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  355.     {
  356.         aout_input_t * p_input = p_aout->pp_inputs[i];
  357.         b_error |= aout_InputNew( p_aout, p_input, &p_input->request_vout );
  358.         p_input->b_changed = 1;
  359.         aout_unlock_input( p_aout, p_input );
  360.     }
  361.     aout_unlock_input_fifos( p_aout );
  362.     aout_unlock_mixer( p_aout );
  363.     return b_error;
  364. }
  365. /*****************************************************************************
  366.  * aout_FindAndRestart : find the audio output instance and restart
  367.  *****************************************************************************
  368.  * This is used for callbacks of the configuration variables, and we believe
  369.  * that when those are changed, it is a significant change which implies
  370.  * rebuilding the audio-device and audio-channels variables.
  371.  *****************************************************************************/
  372. int aout_FindAndRestart( vlc_object_t * p_this, const char *psz_name,
  373.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  374. {
  375.     aout_instance_t * p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT,
  376.                                                 FIND_ANYWHERE );
  377.     (void)psz_name; (void)oldval; (void)newval; (void)p_data;
  378.     if ( p_aout == NULL ) return VLC_SUCCESS;
  379.     if ( var_Type( p_aout, "audio-device" ) != 0 )
  380.     {
  381.         var_Destroy( p_aout, "audio-device" );
  382.     }
  383.     if ( var_Type( p_aout, "audio-channels" ) != 0 )
  384.     {
  385.         var_Destroy( p_aout, "audio-channels" );
  386.     }
  387.     aout_Restart( p_aout );
  388.     vlc_object_release( p_aout );
  389.     return VLC_SUCCESS;
  390. }
  391. /*****************************************************************************
  392.  * aout_ChannelsRestart : change the audio device or channels and restart
  393.  *****************************************************************************/
  394. int aout_ChannelsRestart( vlc_object_t * p_this, const char * psz_variable,
  395.                           vlc_value_t oldval, vlc_value_t newval,
  396.                           void *p_data )
  397. {
  398.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  399.     (void)oldval; (void)newval; (void)p_data;
  400.     if ( !strcmp( psz_variable, "audio-device" ) )
  401.     {
  402.         /* This is supposed to be a significant change and supposes
  403.          * rebuilding the channel choices. */
  404.         if ( var_Type( p_aout, "audio-channels" ) >= 0 )
  405.         {
  406.             var_Destroy( p_aout, "audio-channels" );
  407.         }
  408.     }
  409.     aout_Restart( p_aout );
  410.     return 0;
  411. }
  412. /** Enable or disable an audio filter
  413.  * param p_this a vlc object
  414.  * param psz_name name of the filter
  415.  * param b_add are we adding or removing the filter ?
  416.  */
  417. void aout_EnableFilter( vlc_object_t *p_this, const char *psz_name,
  418.                         bool b_add )
  419. {
  420.     aout_instance_t *p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT,
  421.                                                FIND_ANYWHERE );
  422.     if( AoutChangeFilterString( p_this, p_aout, "audio-filter", psz_name, b_add ) )
  423.     {
  424.         if( p_aout )
  425.             AoutInputsMarkToRestart( p_aout );
  426.     }
  427.     if( p_aout )
  428.         vlc_object_release( p_aout );
  429. }
  430. /**
  431.  * Change audio visualization
  432.  * -1 goes backwards, +1 goes forward
  433.  */
  434. char *aout_VisualChange( vlc_object_t *p_this, int i_skip )
  435. {
  436.     (void)p_this; (void)i_skip;
  437.     msg_Err( p_this, "FIXME: %s (%s %d) isn't implemented.", __func__,
  438.              __FILE__, __LINE__ );
  439.     return strdup("foobar");
  440. }