⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oss.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * oss.c : OSS /dev/dsp module for vlc ***************************************************************************** * Copyright (C) 2000-2002 VideoLAN * $Id: oss.c 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Michel Kaempf <maxx@via.ecp.fr> *          Sam Hocevar <sam@zoy.org> *          Christophe Massiot <massiot@via.ecp.fr> * * 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <errno.h>                                                 /* ENOMEM */#include <fcntl.h>                                       /* open(), O_WRONLY */#include <sys/ioctl.h>                                            /* ioctl() */#include <string.h>                                            /* strerror() */#include <unistd.h>                                      /* write(), close() */#include <stdlib.h>                            /* calloc(), malloc(), free() */#include <vlc/vlc.h>#ifdef HAVE_ALLOCA_H#   include <alloca.h>#endif#include <vlc/aout.h>#include "aout_internal.h"/* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT, SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED, * SNDCTL_DSP_GETOSPACE */#ifdef HAVE_SOUNDCARD_H#   include <soundcard.h>#elif defined( HAVE_SYS_SOUNDCARD_H )#   include <sys/soundcard.h>#elif defined( HAVE_MACHINE_SOUNDCARD_H )#   include <machine/soundcard.h>#endif/* Patches for ignorant OSS versions */#ifndef AFMT_AC3#   define AFMT_AC3     0x00000400        /* Dolby Digital AC3 */#endif#ifndef AFMT_S16_NE#   ifdef WORDS_BIGENDIAN#       define AFMT_S16_NE AFMT_S16_BE#   else#       define AFMT_S16_NE AFMT_S16_LE#   endif#endif/***************************************************************************** * aout_sys_t: OSS audio output method descriptor ***************************************************************************** * This structure is part of the audio output thread descriptor. * It describes the DSP specific properties of an audio device. *****************************************************************************/struct aout_sys_t{    int i_fd;    int b_workaround_buggy_driver;    int i_fragstotal;    mtime_t max_buffer_duration;};/* This must be a power of 2. */#define FRAME_SIZE 1024#define FRAME_COUNT 4/***************************************************************************** * Local prototypes *****************************************************************************/static int  Open         ( vlc_object_t * );static void Close        ( vlc_object_t * );static void Play         ( aout_instance_t * );static int  OSSThread    ( aout_instance_t * );static mtime_t BufferDuration( aout_instance_t * p_aout );/***************************************************************************** * Module descriptor *****************************************************************************/#define BUGGY_TEXT N_("Try to work around buggy OSS drivers")#define BUGGY_LONGTEXT N_( \    "Some buggy OSS drivers just don't like when their internal buffers " \    "are completely filled (the sound gets heavily hashed). If you have one " \    "of these drivers, then you need to enable this option." )vlc_module_begin();    set_shortname( "OSS" );    set_description( _("Linux OSS audio output") );    set_category( CAT_AUDIO );    set_subcategory( SUBCAT_AUDIO_AOUT );    add_file( "dspdev", "/dev/dsp", aout_FindAndRestart,              N_("OSS DSP device"), NULL, VLC_FALSE );    add_bool( "oss-buggy", 0, NULL, BUGGY_TEXT, BUGGY_LONGTEXT, VLC_TRUE );    set_capability( "audio output", 100 );    add_shortcut( "oss" );    set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Probe: probe the audio device for available formats and channels *****************************************************************************/static void Probe( aout_instance_t * p_aout ){    struct aout_sys_t * p_sys = p_aout->output.p_sys;    vlc_value_t val, text;    int i_format, i_nb_channels;    var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );    text.psz_string = _("Audio Device");    var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );    /* Test for multi-channel. */#ifdef SNDCTL_DSP_GETCHANNELMASK    if ( aout_FormatNbChannels( &p_aout->output.output ) > 2 )    {        /* Check that the device supports this. */        int i_chanmask;        /* Reset all. */        i_format = AFMT_S16_NE;        if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 ||            ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )        {            msg_Err( p_aout, "cannot reset OSS audio device" );            var_Destroy( p_aout, "audio-device" );            return;        }        if ( ioctl( p_sys->i_fd, SNDCTL_DSP_GETCHANNELMASK,                    &i_chanmask ) == 0 )        {            if ( !(i_chanmask & DSP_BIND_FRONT) )            {                msg_Err( p_aout, "No front channels ! (%x)",                         i_chanmask );                return;            }            if ( (i_chanmask & (DSP_BIND_SURR | DSP_BIND_CENTER_LFE))                  && (p_aout->output.output.i_physical_channels ==                       (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER                         | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT                         | AOUT_CHAN_LFE)) )            {                val.i_int = AOUT_VAR_5_1;                text.psz_string = N_("5.1");                var_Change( p_aout, "audio-device",                            VLC_VAR_ADDCHOICE, &val, &text );            }            if ( (i_chanmask & DSP_BIND_SURR)                  && (p_aout->output.output.i_physical_channels &                       (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT                         | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT)) )            {                val.i_int = AOUT_VAR_2F2R;                text.psz_string = N_("2 Front 2 Rear");                var_Change( p_aout, "audio-device",                            VLC_VAR_ADDCHOICE, &val, &text );            }        }    }#endif    /* Reset all. */    i_format = AFMT_S16_NE;    if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 ||        ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )    {        msg_Err( p_aout, "cannot reset OSS audio device" );        var_Destroy( p_aout, "audio-device" );        return;    }    /* Test for stereo. */    i_nb_channels = 2;    if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) >= 0         && i_nb_channels == 2 )    {        val.i_int = AOUT_VAR_STEREO;        text.psz_string = N_("Stereo");        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );    }    /* Reset all. */    i_format = AFMT_S16_NE;    if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 ||        ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )    {        msg_Err( p_aout, "cannot reset OSS audio device" );        var_Destroy( p_aout, "audio-device" );        return;    }    /* Test for mono. */    i_nb_channels = 1;    if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) >= 0         && i_nb_channels == 1 )    {        val.i_int = AOUT_VAR_MONO;        text.psz_string = N_("Mono");        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );        if ( p_aout->output.output.i_physical_channels == AOUT_CHAN_CENTER )        {            var_Set( p_aout, "audio-device", val );        }    }    if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )    {        msg_Err( p_aout, "cannot reset OSS audio device" );        var_Destroy( p_aout, "audio-device" );        return;    }    /* Test for spdif. */    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )    {        i_format = AFMT_AC3;        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) >= 0             && i_format == AFMT_AC3 )        {            val.i_int = AOUT_VAR_SPDIF;            text.psz_string = N_("A/52 over S/PDIF");            var_Change( p_aout, "audio-device",                        VLC_VAR_ADDCHOICE, &val, &text );            if( config_GetInt( p_aout, "spdif" ) )                var_Set( p_aout, "audio-device", val );        }        else if( config_GetInt( p_aout, "spdif" ) )        {            msg_Warn( p_aout, "s/pdif not supported by card" );        }    }    var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart,                     NULL );}/***************************************************************************** * Open: open the audio device (the digital sound processor) ***************************************************************************** * This function opens the DSP as a usual non-blocking write-only file, and * modifies the p_aout->p_sys->i_fd with the file's descriptor. *****************************************************************************/static int Open( vlc_object_t *p_this ){    aout_instance_t * p_aout = (aout_instance_t *)p_this;    struct aout_sys_t * p_sys;    char * psz_device;    vlc_value_t val;    /* Allocate structure */    p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );    if( p_sys == NULL )    {        msg_Err( p_aout, "out of memory" );        return VLC_ENOMEM;    }    /* Get device name */    if( (psz_device = config_GetPsz( p_aout, "dspdev" )) == NULL )    {        msg_Err( p_aout, "no audio device specified (maybe /dev/dsp?)" );        free( p_sys );        return VLC_EGENERIC;    }    /* Open the sound device in non-blocking mode, because ALSA's OSS     * emulation and some broken OSS drivers would make a blocking call     * wait forever until the device is available. Since this breaks the     * OSS spec, we immediately put it back to blocking mode if the     * operation was successful. */    p_sys->i_fd = open( psz_device, O_WRONLY | O_NDELAY );    if( p_sys->i_fd < 0 )    {        msg_Err( p_aout, "cannot open audio device (%s)", psz_device );        free( p_sys );        return VLC_EGENERIC;    }    /* if the opening was ok, put the device back in blocking mode */    fcntl( p_sys->i_fd, F_SETFL,            fcntl( p_sys->i_fd, F_GETFL ) &~ FNDELAY );    free( psz_device );    p_aout->output.pf_play = Play;    if ( var_Type( p_aout, "audio-device" ) == 0 )    {        Probe( p_aout );    }    if ( var_Get( p_aout, "audio-device", &val ) < 0 )    {        /* Probe() has failed. */        free( p_sys );        return VLC_EGENERIC;    }    if ( val.i_int == AOUT_VAR_SPDIF )    {        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');    }    else if ( val.i_int == AOUT_VAR_5_1 )    {        p_aout->output.output.i_format = AOUT_FMT_S16_NE;        p_aout->output.output.i_physical_channels            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT               | AOUT_CHAN_LFE;    }    else if ( val.i_int == AOUT_VAR_2F2R )    {        p_aout->output.output.i_format = AOUT_FMT_S16_NE;        p_aout->output.output.i_physical_channels            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;    }    else if ( val.i_int == AOUT_VAR_STEREO )    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -