+/*****************************************************************************
+ * 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 = "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 );
+}
+