X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faudio_output%2Fsdl.c;h=ca62dfbc978f5145f586b86c2c0b8e598f04efcb;hb=13ae40b0efc4f1b1ce205d9a057537047fcab3f4;hp=e332ea5cc0699632247420b297a57fcdfcb1bdcf;hpb=711160b2a2a3c716670d6f4c0f74a7545db8bddc;p=vlc diff --git a/modules/audio_output/sdl.c b/modules/audio_output/sdl.c index e332ea5cc0..ca62dfbc97 100644 --- a/modules/audio_output/sdl.c +++ b/modules/audio_output/sdl.c @@ -1,18 +1,19 @@ /***************************************************************************** * sdl.c : SDL audio output plugin for vlc ***************************************************************************** - * Copyright (C) 2000-2002 VideoLAN - * $Id: sdl.c,v 1.5 2002/08/24 10:19:42 sam Exp $ + * Copyright (C) 2000-2002 the VideoLAN team + * $Id$ * * Authors: Michel Kaempf - * Samuel Hocevar + * Sam Hocevar * Pierre Baillet - * + * Christophe Massiot + * * 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 @@ -20,43 +21,56 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* ENOMEM */ -#include /* open(), O_WRONLY */ -#include /* strerror() */ #include /* write(), close() */ -#include /* calloc(), malloc(), free() */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include -#include -#include "aout_internal.h" +#include +#include #include SDL_INCLUDE_FILE -#define FRAME_SIZE 2048*2 +#define FRAME_SIZE 2048 + +/***************************************************************************** + * aout_sys_t: SDL audio output method descriptor + ***************************************************************************** + * This structure is part of the audio output thread descriptor. + * It describes the specific properties of an audio device. + *****************************************************************************/ +struct aout_sys_t +{ + mtime_t next_date; + mtime_t buffer_time; +}; /***************************************************************************** * Local prototypes *****************************************************************************/ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); - -static int SetFormat ( aout_instance_t * ); static void Play ( aout_instance_t * ); - -static void SDLCallback ( void *, Uint8 *, int ); +static void SDLCallback ( void *, uint8_t *, int ); /***************************************************************************** * Module descriptor *****************************************************************************/ vlc_module_begin(); - set_description( _("Simple DirectMedia Layer audio module") ); + set_shortname( "SDL" ); + set_description( N_("Simple DirectMedia Layer audio output") ); set_capability( "audio output", 40 ); + set_category( CAT_AUDIO ); + set_subcategory( SUBCAT_AUDIO_AOUT ); + add_shortcut( "sdl" ); set_callbacks( Open, Close ); vlc_module_end(); @@ -66,22 +80,22 @@ vlc_module_end(); static int Open ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; + SDL_AudioSpec desired, obtained; + int i_nb_channels; + vlc_value_t val, text; - Uint32 i_flags = SDL_INIT_AUDIO; - + /* Check that no one uses the DSP. */ + uint32_t i_flags = SDL_INIT_AUDIO; if( SDL_WasInit( i_flags ) ) { - return 1; + return VLC_EGENERIC; } - p_aout->output.pf_setformat = SetFormat; - p_aout->output.pf_play = Play; - #ifndef WIN32 - /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/ + /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet */ i_flags |= SDL_INIT_EVENTTHREAD; #endif -#ifdef DEBUG +#ifndef NDEBUG /* In debug mode you may want vlc to dump a core instead of staying * stuck */ i_flags |= SDL_INIT_NOPARACHUTE; @@ -91,39 +105,124 @@ static int Open ( vlc_object_t *p_this ) if( SDL_Init( i_flags ) < 0 ) { msg_Err( p_aout, "cannot initialize SDL (%s)", SDL_GetError() ); - return 1; + return VLC_EGENERIC; } - return 0; -} - -/***************************************************************************** - * SetFormat: reset the audio device and sets its format - *****************************************************************************/ -static int SetFormat( aout_instance_t *p_aout ) -{ - /* TODO: finish and clean this */ - SDL_AudioSpec desired; + if ( var_Type( p_aout, "audio-device" ) != 0 ) + { + /* The user has selected an audio device. */ + vlc_value_t val; + var_Get( p_aout, "audio-device", &val ); + if ( val.i_int == AOUT_VAR_STEREO ) + { + p_aout->output.output.i_physical_channels + = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; + } + else if ( val.i_int == AOUT_VAR_MONO ) + { + p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; + } + } + i_nb_channels = aout_FormatNbChannels( &p_aout->output.output ); + if ( i_nb_channels > 2 ) + { + /* SDL doesn't support more than two channels. */ + i_nb_channels = 2; + p_aout->output.output.i_physical_channels + = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; + } desired.freq = p_aout->output.output.i_rate; desired.format = AUDIO_S16SYS; - desired.channels = p_aout->output.output.i_channels; + desired.channels = i_nb_channels; desired.callback = SDLCallback; desired.userdata = p_aout; desired.samples = FRAME_SIZE; - /* Open the sound device - FIXME : get the "natural" parameters */ - if( SDL_OpenAudio( &desired, NULL ) < 0 ) + /* Open the sound device. */ + if( SDL_OpenAudio( &desired, &obtained ) < 0 ) { - return -1; + return VLC_EGENERIC; } - p_aout->output.output.i_format = AOUT_FMT_S16_NE; - p_aout->output.i_nb_samples = FRAME_SIZE; - SDL_PauseAudio( 0 ); - return 0; + /* Now have a look at what we got. */ + switch ( obtained.format ) + { + case AUDIO_S16LSB: + p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l'); break; + case AUDIO_S16MSB: + p_aout->output.output.i_format = VLC_FOURCC('s','1','6','b'); break; + case AUDIO_U16LSB: + p_aout->output.output.i_format = VLC_FOURCC('u','1','6','l'); break; + case AUDIO_U16MSB: + p_aout->output.output.i_format = VLC_FOURCC('u','1','6','b'); break; + case AUDIO_S8: + p_aout->output.output.i_format = VLC_FOURCC('s','8',' ',' '); break; + case AUDIO_U8: + p_aout->output.output.i_format = VLC_FOURCC('u','8',' ',' '); break; + } + /* Volume is entirely done in software. */ + aout_VolumeSoftInit( p_aout ); + + if ( obtained.channels != i_nb_channels ) + { + p_aout->output.output.i_physical_channels = (obtained.channels == 2 ? + AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT : + AOUT_CHAN_CENTER); + + if ( var_Type( p_aout, "audio-device" ) == 0 ) + { + 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 ); + + val.i_int = (obtained.channels == 2) ? AOUT_VAR_STEREO : + AOUT_VAR_MONO; + text.psz_string = (obtained.channels == 2) ? N_("Stereo") : + N_("Mono"); + var_Change( p_aout, "audio-device", + VLC_VAR_ADDCHOICE, &val, &text ); + var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, + NULL ); + } + } + else if ( var_Type( p_aout, "audio-device" ) == 0 ) + { + /* First launch. */ + 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 ); + + val.i_int = AOUT_VAR_STEREO; + text.psz_string = N_("Stereo"); + var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); + val.i_int = AOUT_VAR_MONO; + text.psz_string = N_("Mono"); + var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); + if ( i_nb_channels == 2 ) + { + val.i_int = AOUT_VAR_STEREO; + } + else + { + val.i_int = AOUT_VAR_MONO; + } + var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL ); + var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); + } + + val.b_bool = true; + var_Set( p_aout, "intf-change", val ); + + p_aout->output.output.i_rate = obtained.freq; + p_aout->output.i_nb_samples = obtained.samples; + p_aout->output.pf_play = Play; + + return VLC_SUCCESS; } /***************************************************************************** @@ -131,6 +230,7 @@ static int SetFormat( aout_instance_t *p_aout ) *****************************************************************************/ static void Play( aout_instance_t * p_aout ) { + VLC_UNUSED(p_aout); } /***************************************************************************** @@ -138,6 +238,7 @@ static void Play( aout_instance_t * p_aout ) *****************************************************************************/ static void Close ( vlc_object_t *p_this ) { + VLC_UNUSED(p_this); SDL_PauseAudio( 1 ); SDL_CloseAudio(); SDL_QuitSubSystem( SDL_INIT_AUDIO ); @@ -146,37 +247,27 @@ static void Close ( vlc_object_t *p_this ) /***************************************************************************** * SDLCallback: what to do once SDL has played sound samples *****************************************************************************/ -static void SDLCallback( void * _p_aout, byte_t * p_stream, int i_len ) +static void SDLCallback( void * _p_aout, uint8_t * p_stream, int i_len ) { aout_instance_t * p_aout = (aout_instance_t *)_p_aout; -//static mtime_t old = 0; -//static mtime_t diff = 0; -//mtime_t foo = mdate(); - aout_buffer_t * p_buffer; -//if(old) diff = (9 * diff + (foo-old))/10; - /* FIXME : take into account SDL latency instead of mdate() */ - p_buffer = aout_OutputNextBuffer( p_aout, mdate(), 0, VLC_TRUE ); - //p_buffer = aout_OutputNextBuffer( p_aout, foo - diff, 0, VLC_TRUE ); -//fprintf(stderr, "foo - old : %lli, diff : %lli\n", foo-old, diff); -//old=foo; - - if ( i_len != FRAME_SIZE * sizeof(s16) - * p_aout->output.output.i_channels ) - { - msg_Err( p_aout, "SDL doesn't know its buffer size (%d)", i_len ); - } + aout_buffer_t * p_buffer; + + /* SDL is unable to call us at regular times, or tell us its current + * hardware latency, or the buffer state. So we just pop data and throw + * it at SDL's face. Nah. */ + + vlc_mutex_lock( &p_aout->output_fifo_lock ); + p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo ); + vlc_mutex_unlock( &p_aout->output_fifo_lock ); if ( p_buffer != NULL ) { -//fprintf(stderr, "got buffer %lli\n", p_buffer->end_date - p_buffer->start_date); - - p_aout->p_vlc->pf_memcpy( p_stream, p_buffer->p_buffer, i_len ); + vlc_memcpy( p_stream, p_buffer->p_buffer, i_len ); aout_BufferFree( p_buffer ); } else { -//fprintf(stderr, "NO BUFFER !\n"); - p_aout->p_vlc->pf_memset( p_stream, 0, i_len ); + vlc_memset( p_stream, 0, i_len ); } }