Commit 8928554e authored by Christophe Massiot's avatar Christophe Massiot

Major change of the channels management. p_format->i_channels disappeares

and is replaced by two members : i_physical_channels and i_original_channels.
i_physical_channels describes the channels which are effectively present
in the stream (at the current point of the aout pipeline), whereas
i_original_channels represents the channels we used to constitute the
stream. For instance a mono stream (FRONT_CENTER) may emanate from a
FRONT_LEFT channel of a STEREO stream.

Additionally, this contains hooks to dynamically select the audio device
and the channels configuration. In order to do that, all aout plugins,
and all interface plug-ins need to be adapted. Currently only SDL
(partially OSS) and the rc interface have been adapted, please use them
as a guide. Other aout plug-ins have been temporarily disabled.

IMPORTANT : if you need a working sound output, DO NOT UPDATE YOUR TREE
for several days until we fix that.

* modules/misc/network/ipv4.c: Fixed a long-standing segfault when saving
  preferences and asking for multicast.
parent f5bc3cd8
......@@ -1755,7 +1755,7 @@ if test "x${enable_oss}" != "xno" &&
(test "x${SYS}" != "xmingw32" || test "x${enable_oss}" = "xyes")
then
AC_CHECK_HEADERS(soundcard.h sys/soundcard.h machine/soundcard.h, [
PLUGINS="${PLUGINS} oss"
#PLUGINS="${PLUGINS} oss"
AC_CHECK_LIB(ossaudio,main,LDFLAGS_oss="${LDFLAGS_oss} -lossaudio")
])
fi
......@@ -1770,7 +1770,7 @@ AC_ARG_ENABLE(esd,
AC_PATH_PROG(ESD_CONFIG, esd-config, no)
if test "x${ESD_CONFIG}" != "xno"
then
PLUGINS="${PLUGINS} esd"
#PLUGINS="${PLUGINS} esd"
CFLAGS_esd="${CFLAGS_esd} `${ESD_CONFIG} --cflags`"
LDFLAGS_esd="${LDFLAGS_esd} `${ESD_CONFIG} --libs`"
fi
......@@ -1786,7 +1786,7 @@ AC_ARG_ENABLE(arts,
AC_PATH_PROG(ARTS_CONFIG, artsc-config, no)
if test "x${ARTS_CONFIG}" != "xno"
then
PLUGINS="${PLUGINS} arts"
#PLUGINS="${PLUGINS} arts"
CFLAGS_arts="${CFLAGS_arts} `${ARTS_CONFIG} --cflags`"
LDFLAGS_arts="${LDFLAGS_arts} `${ARTS_CONFIG} --libs `"
fi
......@@ -1802,7 +1802,7 @@ AC_ARG_ENABLE(alsa,
AC_CHECK_HEADER(alsa/asoundlib.h, AC_CHECK_LIB(asound, main, have_alsa="true", have_alsa="false"),have_alsa="false")
if test "x${have_alsa}" = "xtrue"
then
PLUGINS="${PLUGINS} alsa"
#PLUGINS="${PLUGINS} alsa"
LDFLAGS_alsa="${LDFLAGS_alsa} -lasound -lm -ldl"
fi
fi])
......@@ -1814,7 +1814,7 @@ AC_ARG_ENABLE(waveout,
[ --enable-waveout Win32 waveOut module (default enabled on Win32)])
if test "x${enable_waveout}" != "xno"; then
if test "x${SYS}" = "xmingw32" -o "x${SYS}" = "xcygwin"; then
PLUGINS="${PLUGINS} waveout"
#PLUGINS="${PLUGINS} waveout"
LDFLAGS_waveout="-lwinmm"
fi
fi
......
......@@ -2,7 +2,7 @@
* aout_internal.h : internal defines for audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: aout_internal.h,v 1.33 2002/11/13 20:51:04 sam Exp $
* $Id: aout_internal.h,v 1.34 2002/11/14 22:38:46 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -275,10 +275,11 @@ void aout_OutputDelete( aout_instance_t * p_aout );
VLC_EXPORT( aout_buffer_t *, aout_OutputNextBuffer, ( aout_instance_t *, mtime_t, vlc_bool_t ) );
/* From common.c : */
VLC_EXPORT( int, aout_FormatNbChannels, ( audio_sample_format_t * p_format ) );
VLC_EXPORT( int, aout_FormatNbChannels, ( const audio_sample_format_t * p_format ) );
VLC_EXPORT( void, aout_FormatPrepare, ( audio_sample_format_t * p_format ) );
VLC_EXPORT( void, aout_FormatPrint, ( aout_instance_t * p_aout, const char * psz_text, const audio_sample_format_t * p_format ) );
VLC_EXPORT( void, aout_FormatsPrint, ( aout_instance_t * p_aout, const char * psz_text, const audio_sample_format_t * p_format1, const audio_sample_format_t * p_format2 ) );
VLC_EXPORT( const char *, aout_FormatPrintChannels, ( const audio_sample_format_t * ) );
void aout_FifoInit( aout_instance_t *, aout_fifo_t *, uint32_t );
mtime_t aout_FifoNextStart( aout_instance_t *, aout_fifo_t * );
void aout_FifoPush( aout_instance_t *, aout_fifo_t *, aout_buffer_t * );
......
......@@ -2,7 +2,7 @@
* audio_output.h : audio output interface
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: audio_output.h,v 1.70 2002/11/11 14:39:11 sam Exp $
* $Id: audio_output.h,v 1.71 2002/11/14 22:38:46 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -28,12 +28,17 @@
*****************************************************************************/
struct audio_sample_format_t
{
int i_format;
int i_rate;
int i_channels;
vlc_fourcc_t i_format;
unsigned int i_rate;
/* Describes the channels configuration of the samples (ie. number of
* channels which are available in the buffer, and positions). */
u32 i_physical_channels;
/* Describes from which original channels, before downmixing, the
* buffer is derived. */
u32 i_original_channels;
/* Optional - for A52, SPDIF and DTS types */
int i_bytes_per_frame;
int i_frame_length;
unsigned int i_bytes_per_frame;
unsigned int i_frame_length;
/* Please note that it may be completely arbitrary - buffers are not
* obliged to contain a integral number of so-called "frames". It's
* just here for the division :
......@@ -43,14 +48,14 @@ struct audio_sample_format_t
#define AOUT_FMTS_IDENTICAL( p_first, p_second ) ( \
((p_first)->i_format == (p_second)->i_format) \
&& ((p_first)->i_rate == (p_second)->i_rate) \
&& ((p_first)->i_channels == (p_second)->i_channels \
|| (p_first)->i_channels == -1 || (p_second)->i_channels == -1) )
&& ((p_first)->i_physical_channels == (p_second)->i_physical_channels)\
&& ((p_first)->i_original_channels == (p_second)->i_original_channels) )
/* Check if i_rate == i_rate and i_channels == i_channels */
#define AOUT_FMTS_SIMILAR( p_first, p_second ) ( \
((p_first)->i_rate == (p_second)->i_rate) \
&& ((p_first)->i_channels == (p_second)->i_channels \
|| (p_first)->i_channels == -1 || (p_second)->i_channels == -1) )
&& ((p_first)->i_physical_channels == (p_second)->i_physical_channels)\
&& ((p_first)->i_original_channels == (p_second)->i_original_channels) )
#ifdef WORDS_BIGENDIAN
# define AOUT_FMT_S16_NE VLC_FOURCC('s','1','6','b')
......@@ -92,33 +97,24 @@ typedef int32_t vlc_fixed_t;
#define FIXED32_ONE ((vlc_fixed_t) 0x10000000)
/* Dual mono. Two independant mono channels */
#define AOUT_CHAN_CHANNEL 0x0000000B
#define AOUT_CHAN_MONO 0x00000001
#define AOUT_CHAN_STEREO 0x00000002
/* 3 front channels (left, center, right) */
#define AOUT_CHAN_3F 0x00000003
/* 2 front, 1 rear surround channels (L, R, S) */
#define AOUT_CHAN_2F1R 0x00000004
/* 3 front, 1 rear surround channels (L, C, R, S) */
#define AOUT_CHAN_3F1R 0x00000005
/* 2 front, 2 rear surround channels (L, R, LS, RS) */
#define AOUT_CHAN_2F2R 0x00000006
/* 3 front, 2 rear surround channels (L, C, R, LS, RS) */
#define AOUT_CHAN_3F2R 0x00000007
/* First of two mono channels */
#define AOUT_CHAN_CHANNEL1 0x00000008
/* Second of two mono channels */
#define AOUT_CHAN_CHANNEL2 0x00000009
/* Dolby surround compatible stereo */
#define AOUT_CHAN_DOLBY 0x0000000A
#define AOUT_CHAN_MASK 0x0000000F
/* Low frequency effects channel. Normally used to connect a subwoofer.
* Can be combined with any of the above channels. For example :
* AOUT_CHAN_3F2R | AOUT_CHAN_LFE -> 3 front, 2 rear, 1 LFE (5.1) */
#define AOUT_CHAN_LFE 0x00000010
/*
* Channels descriptions
*/
/* Values available for physical and original channels */
#define AOUT_CHAN_CENTER 0x1
#define AOUT_CHAN_LEFT 0x2
#define AOUT_CHAN_RIGHT 0x4
#define AOUT_CHAN_REARCENTER 0x10
#define AOUT_CHAN_REARLEFT 0x20
#define AOUT_CHAN_REARRIGHT 0x40
#define AOUT_CHAN_LFE 0x100
/* Values available for original channels only */
#define AOUT_CHAN_DOLBYSTEREO 0x10000
#define AOUT_CHAN_DUALMONO 0x20000
#define AOUT_CHAN_PHYSMASK 0xFFFF
/*****************************************************************************
......@@ -140,6 +136,9 @@ struct aout_buffer_t
/* Size of a frame for S/PDIF output. */
#define AOUT_SPDIF_SIZE 6144
/* Number of samples in an A/52 frame. */
#define A52_FRAME_NB 1536
/*****************************************************************************
* audio_date_t : date incrementation without long-term rounding errors
*****************************************************************************/
......@@ -179,4 +178,5 @@ VLC_EXPORT( int, aout_VolumeUp, ( aout_instance_t *, int, audio_volume_t * ) );
VLC_EXPORT( int, aout_VolumeDown, ( aout_instance_t *, int, audio_volume_t * ) );
VLC_EXPORT( int, aout_Restart, ( aout_instance_t * p_aout ) );
VLC_EXPORT( void, aout_FindAndRestart, ( vlc_object_t * p_this ) );
VLC_EXPORT( int, aout_ChannelsRestart, ( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ) );
......@@ -2,7 +2,7 @@
* trivial.c : trivial channel mixer plug-in (drops unwanted channels)
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: trivial.c,v 1.5 2002/10/16 23:12:46 massiot Exp $
* $Id: trivial.c,v 1.6 2002/11/14 22:38:46 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -56,7 +56,10 @@ static int Create( vlc_object_t *p_this )
{
aout_filter_t * p_filter = (aout_filter_t *)p_this;
if ( p_filter->input.i_channels == p_filter->output.i_channels
if ( (p_filter->input.i_physical_channels
== p_filter->output.i_physical_channels
&& p_filter->input.i_original_channels
== p_filter->output.i_original_channels)
|| p_filter->input.i_format != p_filter->output.i_format
|| p_filter->input.i_rate != p_filter->output.i_rate
|| (p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
......@@ -66,7 +69,8 @@ static int Create( vlc_object_t *p_this )
}
p_filter->pf_do_work = DoWork;
if ( p_filter->input.i_channels > p_filter->output.i_channels )
if ( aout_FormatNbChannels( &p_filter->input )
> aout_FormatNbChannels( &p_filter->output ) )
{
/* Downmixing */
p_filter->b_in_place = 1;
......@@ -109,11 +113,43 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
int i_output_nb = aout_FormatNbChannels( &p_filter->output );
s32 * p_dest = (s32 *)p_out_buf->p_buffer;
s32 * p_src = (s32 *)p_in_buf->p_buffer;
if ( p_filter->output.i_channels == AOUT_CHAN_CHANNEL2 )
p_src++;
SparseCopy( p_dest, p_src, p_in_buf->i_nb_samples, i_output_nb,
i_input_nb );
if ( p_filter->output.i_original_channels & AOUT_CHAN_DUALMONO )
{
int i;
/* This is a bit special. */
if ( !(p_filter->output.i_original_channels & AOUT_CHAN_LEFT) )
{
p_src++;
}
if ( p_filter->output.i_physical_channels == AOUT_CHAN_CENTER )
{
/* Mono mode */
for ( i = p_in_buf->i_nb_samples; i--; )
{
*p_dest = *p_src;
p_dest++;
p_src += 2;
}
}
else
{
/* Fake-stereo mode */
for ( i = p_in_buf->i_nb_samples; i--; )
{
*p_dest = *p_src;
p_dest++;
*p_dest = *p_src;
p_dest++;
p_src += 2;
}
}
}
else
{
SparseCopy( p_dest, p_src, p_in_buf->i_nb_samples, i_output_nb,
i_input_nb );
}
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * i_output_nb / i_input_nb;
......
......@@ -4,7 +4,7 @@
* (http://liba52.sf.net/).
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: a52tofloat32.c,v 1.5 2002/10/22 23:08:00 massiot Exp $
* $Id: a52tofloat32.c,v 1.6 2002/11/14 22:38:46 massiot Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
* Christophe Massiot <massiot@via.ecp.fr>
......@@ -119,25 +119,78 @@ static int Create( vlc_object_t * _p_filter )
/* We'll do our own downmixing, thanks. */
p_sys->i_nb_channels = aout_FormatNbChannels( &p_filter->output );
switch ( p_filter->output.i_channels & AOUT_CHAN_MASK )
switch ( (p_filter->output.i_physical_channels & AOUT_CHAN_PHYSMASK)
& ~AOUT_CHAN_LFE )
{
case AOUT_CHAN_CHANNEL: p_sys->i_flags = A52_CHANNEL; break;
case AOUT_CHAN_CHANNEL1: p_sys->i_flags = A52_CHANNEL1; break;
case AOUT_CHAN_CHANNEL2: p_sys->i_flags = A52_CHANNEL2; break;
case AOUT_CHAN_MONO: p_sys->i_flags = A52_MONO; break;
case AOUT_CHAN_STEREO: p_sys->i_flags = A52_STEREO; break;
case AOUT_CHAN_DOLBY: p_sys->i_flags = A52_DOLBY; break;
case AOUT_CHAN_3F: p_sys->i_flags = A52_3F; break;
case AOUT_CHAN_2F1R: p_sys->i_flags = A52_2F1R; break;
case AOUT_CHAN_3F1R: p_sys->i_flags = A52_3F1R; break;
case AOUT_CHAN_2F2R: p_sys->i_flags = A52_2F2R; break;
case AOUT_CHAN_3F2R: p_sys->i_flags = A52_3F2R; break;
case AOUT_CHAN_CENTER:
if ( (p_filter->output.i_original_channels & AOUT_CHAN_CENTER)
|| (p_filter->output.i_original_channels
& (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
{
p_sys->i_flags = A52_MONO;
}
else if ( p_filter->output.i_original_channels & AOUT_CHAN_LEFT )
{
p_sys->i_flags = A52_CHANNEL1;
}
else
{
p_sys->i_flags = A52_CHANNEL2;
}
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT:
if ( p_filter->output.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
{
p_sys->i_flags = A52_DOLBY;
}
else if ( p_filter->input.i_original_channels & AOUT_CHAN_DUALMONO )
{
p_sys->i_flags = A52_CHANNEL;
}
else if ( !(p_filter->output.i_original_channels & AOUT_CHAN_RIGHT) )
{
p_sys->i_flags = A52_CHANNEL1;
}
else if ( !(p_filter->output.i_original_channels & AOUT_CHAN_LEFT) )
{
p_sys->i_flags = A52_CHANNEL2;
}
else
{
p_sys->i_flags = A52_STEREO;
}
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER:
p_sys->i_flags = A52_3F;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER:
p_sys->i_flags = A52_2F1R;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARCENTER:
p_sys->i_flags = A52_3F1R;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
p_sys->i_flags = A52_2F2R;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
p_sys->i_flags = A52_3F2R;
break;
default:
msg_Err( p_filter, "unknow sample format !" );
free( p_sys );
return -1;
}
if ( p_filter->output.i_channels & AOUT_CHAN_LFE )
if ( p_filter->output.i_physical_channels & AOUT_CHAN_LFE )
{
p_sys->i_flags |= A52_LFE;
}
......@@ -160,19 +213,34 @@ static int Create( vlc_object_t * _p_filter )
/*****************************************************************************
* Interleave: helper function to interleave channels
*****************************************************************************/
static void Interleave( float * p_out, const float * p_in, int i_channels )
static void Interleave( float * p_out, const float * p_in, int i_nb_channels )
{
int i, j;
for ( j = 0; j < i_channels; j++ )
for ( j = 0; j < i_nb_channels; j++ )
{
for ( i = 0; i < 256; i++ )
{
p_out[i * i_channels + j] = p_in[j * 256 + i];
p_out[i * i_nb_channels + j] = p_in[j * 256 + i];
}
}
}
/*****************************************************************************
* Duplicate: helper function to duplicate a unique channel
*****************************************************************************/
static void Duplicate( float * p_out, const float * p_in )
{
int i;
for ( i = 256; i--; )
{
*p_out++ = *p_in;
*p_out++ = *p_in;
p_in++;
}
}
/*****************************************************************************
* DoWork: decode an ATSC A/52 frame.
*****************************************************************************/
......@@ -221,9 +289,20 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
p_samples = a52_samples( p_sys->p_liba52 );
/* Interleave the *$% samples. */
Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
p_samples, p_sys->i_nb_channels );
if ( ((p_sys->i_flags & A52_CHANNEL1) || (p_sys->i_flags & A52_CHANNEL2)
|| (p_sys->i_flags & A52_MONO))
&& (p_filter->output.i_physical_channels
& (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
{
Duplicate( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
p_samples );
}
else
{
/* Interleave the *$% samples. */
Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
p_samples, p_sys->i_nb_channels );
}
}
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
......
......@@ -2,7 +2,7 @@
* trivial.c : trivial resampler (skips samples or pads with zeroes)
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: trivial.c,v 1.8 2002/11/11 22:27:01 gbazin Exp $
* $Id: trivial.c,v 1.9 2002/11/14 22:38:46 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -58,7 +58,10 @@ static int Create( vlc_object_t *p_this )
if ( p_filter->input.i_rate == p_filter->output.i_rate
|| p_filter->input.i_format != p_filter->output.i_format
|| p_filter->input.i_channels != p_filter->output.i_channels
|| p_filter->input.i_physical_channels
!= p_filter->output.i_physical_channels
|| p_filter->input.i_original_channels
!= p_filter->output.i_original_channels
|| (p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
&& p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) )
{
......
......@@ -2,7 +2,7 @@
* ugly.c : ugly resampler (changes pitch)
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: ugly.c,v 1.5 2002/11/11 22:27:01 gbazin Exp $
* $Id: ugly.c,v 1.6 2002/11/14 22:38:46 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -58,7 +58,10 @@ static int Create( vlc_object_t *p_this )
if ( p_filter->input.i_rate == p_filter->output.i_rate
|| p_filter->input.i_format != p_filter->output.i_format
|| p_filter->input.i_channels != p_filter->output.i_channels
|| p_filter->input.i_physical_channels
!= p_filter->output.i_physical_channels
|| p_filter->input.i_original_channels
!= p_filter->output.i_original_channels
|| (p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
&& p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) )
{
......
......@@ -2,7 +2,7 @@
* float32.c : precise float32 audio mixer implementation
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: float32.c,v 1.6 2002/10/15 23:10:54 massiot Exp $
* $Id: float32.c,v 1.7 2002/11/14 22:38:47 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -49,7 +49,7 @@ vlc_module_begin();
vlc_module_end();
/*****************************************************************************
* Create: allocate trivial mixer
* Create: allocate mixer
*****************************************************************************/
static int Create( vlc_object_t *p_this )
{
......
......@@ -2,7 +2,7 @@
* oss.c : OSS /dev/dsp module for vlc
*****************************************************************************
* Copyright (C) 2000-2002 VideoLAN
* $Id: oss.c,v 1.32 2002/10/25 15:21:42 gbazin Exp $
* $Id: oss.c,v 1.33 2002/11/14 22:38:47 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -70,7 +70,6 @@ struct aout_sys_t
/* This must be a power of 2. */
#define FRAME_SIZE 1024
#define FRAME_COUNT 4
#define A52_FRAME_NB 1536
/*****************************************************************************
* Local prototypes
......@@ -103,6 +102,111 @@ vlc_module_begin();
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;
int i_format, i_nb_channels;
var_Create( p_aout, "audio-device", VLC_VAR_STRING | VLC_VAR_ISLIST );
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;
}
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.psz_string = N_("S/PDIF");
var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
}
}
/* Go to PCM mode. */
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 )
{
return;
}
#ifdef SNDCTL_DSP_GETCHANNELMASK
if ( aout_FormatNbChannels( &p_aout->output.output ) > 2 )
{
/* Check that the device supports this. */
int i_chanmask;
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.psz_string = N_("5.1");
var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
}
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.psz_string = N_("2 Front 2 Rear");
var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
}
}
}
#endif
/* 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.psz_string = N_("Stereo");
var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
}
/* 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.psz_string = N_("Mono");
var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
}
}
/*****************************************************************************
* Open: open the audio device (the digital sound processor)
*****************************************************************************
......@@ -114,6 +218,7 @@ 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 ) );
......@@ -143,6 +248,50 @@ static int Open( vlc_object_t *p_this )
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 ( !strcmp( val.psz_string, N_("S/PDIF") ) )
{
p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
}
else if ( !strcmp( val.psz_string, N_("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_REARLEFT
| AOUT_CHAN_LFE;
}
else if ( !strcmp( val.psz_string, N_("2 Front 2 Rear") ) )
{
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_REARLEFT;
}
else if ( !strcmp( val.psz_string, "Stereo" ) )
{
p_aout->output.output.i_format = AOUT_FMT_S16_NE;
p_aout->output.output.i_physical_channels
= AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
}
else if ( !strcmp( val.psz_string, "Mono" ) )
{
p_aout->output.output.i_format = AOUT_FMT_S16_NE;
p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
}
free( val.psz_string );
/* Reset the DSP device */
if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
{
......@@ -151,7 +300,7 @@ static int Open( vlc_object_t *p_this )
free( p_sys );
return VLC_EGENERIC;
}
/* Set the output format */
if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
{
......@@ -160,17 +309,18 @@ static int Open( vlc_object_t *p_this )
if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
|| i_format != AFMT_AC3 )
{
p_aout->output.output.i_format = AOUT_FMT_S16_NE;
msg_Err( p_aout, "cannot reset OSS audio device" );
close( p_sys->i_fd );
free( p_sys );
return VLC_EGENERIC;
}
else
{
p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
p_aout->output.i_nb_samples = A52_FRAME_NB;
p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->output.output.i_frame_length = A52_FRAME_NB;
aout_VolumeNoneInit( p_aout );
}
p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
p_aout->output.i_nb_samples = A52_FRAME_NB;
p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->output.output.i_frame_length = A52_FRAME_NB;
aout_VolumeNoneInit( p_aout );
}
if ( !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
......@@ -217,100 +367,19 @@ static int Open( vlc_object_t *p_this )
return VLC_EGENERIC;
}