X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faudio_output%2Falsa.c;h=e16a05f78543c0b3397431cfe6be22ec4db28e57;hb=5ad6561ceab66b046b648e7651ed63c071d6012d;hp=a90e2fde0a85a0bba929bc67819793e1e41538fd;hpb=9af57553c9e93a62d2f9b68f78d0420053fbffa2;p=vlc diff --git a/modules/audio_output/alsa.c b/modules/audio_output/alsa.c index a90e2fde0a..e16a05f785 100644 --- a/modules/audio_output/alsa.c +++ b/modules/audio_output/alsa.c @@ -27,7 +27,12 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include #include /* ENOMEM */ #include @@ -40,6 +45,8 @@ #define ALSA_PCM_NEW_SW_PARAMS_API #include +/*#define ALSA_DEBUG*/ + /***************************************************************************** * aout_sys_t: ALSA audio output method descriptor ***************************************************************************** @@ -94,15 +101,15 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, /***************************************************************************** * Module descriptor *****************************************************************************/ -static const char *ppsz_devices[] = { "default" }; -static const char *ppsz_devices_text[] = { N_("Default") }; +static const char *const ppsz_devices[] = { "default" }; +static const char *const ppsz_devices_text[] = { N_("Default") }; vlc_module_begin(); set_shortname( "ALSA" ); - set_description( _("ALSA audio output") ); + set_description( N_("ALSA audio output") ); set_category( CAT_AUDIO ); set_subcategory( SUBCAT_AUDIO_AOUT ); add_string( "alsadev", DEFAULT_ALSA_DEVICE, aout_FindAndRestart, - N_("ALSA Device Name"), NULL, VLC_FALSE ); + N_("ALSA Device Name"), NULL, false ); change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback ); change_action_add( FindDevicesCallback, N_("Refresh list") ); @@ -266,7 +273,7 @@ static void Probe( aout_instance_t * p_aout, /* Add final settings to the variable */ var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); - val.b_bool = VLC_TRUE; + val.b_bool = true; var_Set( p_aout, "intf-change", val ); } @@ -301,25 +308,22 @@ static int Open( vlc_object_t *p_this ) int i_snd_rc = -1; unsigned int i_old_rate; - vlc_bool_t b_retry = VLC_TRUE; + bool b_retry = true; /* Allocate structures */ 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; - } - p_sys->b_playing = VLC_FALSE; + p_sys->b_playing = false; p_sys->start_date = 0; vlc_cond_init( p_aout, &p_sys->wait ); - vlc_mutex_init( p_aout, &p_sys->lock ); + vlc_mutex_init( &p_sys->lock ); /* Get device name */ if( (psz_device = config_GetPsz( p_aout, "alsadev" )) == NULL ) { msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" ); - intf_UserFatal( p_aout, VLC_FALSE, _("No Audio Device"), + intf_UserFatal( p_aout, false, _("No Audio Device"), _("No audio device name was given. You might want to " \ "enter \"default\".") ); free( p_sys ); @@ -427,7 +431,7 @@ static int Open( vlc_object_t *p_this ) { msg_Err( p_aout, "cannot open ALSA device `%s' (%s)", psz_iec_device, snd_strerror( i_snd_rc ) ); - intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"), + intf_UserFatal( p_aout, false, _("Audio output failed"), _("VLC could not open the ALSA device \"%s\" (%s)."), psz_iec_device, snd_strerror( i_snd_rc ) ); free( p_sys ); @@ -466,7 +470,7 @@ static int Open( vlc_object_t *p_this ) { msg_Err( p_aout, "audio device: %s is already in use", psz_device ); - intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"), + intf_UserFatal( p_aout, false, _("Audio output failed"), _("The audio device \"%s\" is already in use."), psz_device ); } @@ -478,7 +482,7 @@ static int Open( vlc_object_t *p_this ) { msg_Err( p_aout, "cannot open ALSA device `%s' (%s)", psz_device, snd_strerror( i_snd_rc ) ); - intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"), + intf_UserFatal( p_aout, false, _("Audio output failed"), _("VLC could not open the ALSA device \"%s\" (%s)."), psz_device, snd_strerror( i_snd_rc ) ); free( p_sys ); @@ -509,7 +513,7 @@ static int Open( vlc_object_t *p_this ) if snd_pcm_hw_params fails in fl32 */ while ( b_retry ) { - b_retry = VLC_FALSE; + b_retry = false; /* Get Initial hardware parameters */ if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 ) @@ -583,42 +587,42 @@ static int Open( vlc_object_t *p_this ) p_aout->output.output.i_rate ); } - /* Set buffer size. */ + /* Set period size. */ #ifdef HAVE_ALSA_NEW_API - if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm, - p_hw, &i_buffer_size ) ) < 0 ) + if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm, + p_hw, &i_period_size, NULL ) ) < 0 ) #else - if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm, - p_hw, i_buffer_size ) ) < 0 ) + if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm, + p_hw, i_period_size, NULL ) ) < 0 ) #endif { - msg_Err( p_aout, "unable to set buffer size (%s)", + msg_Err( p_aout, "unable to set period size (%s)", snd_strerror( i_snd_rc ) ); goto error; } + p_aout->output.i_nb_samples = i_period_size; - /* Set period size. */ +/* Set buffer size. */ #ifdef HAVE_ALSA_NEW_API - if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm, - p_hw, &i_period_size, NULL ) ) < 0 ) + if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm, + p_hw, &i_buffer_size ) ) < 0 ) #else - if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm, - p_hw, i_period_size, NULL ) ) < 0 ) + if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm, + p_hw, i_buffer_size ) ) < 0 ) #endif { - msg_Err( p_aout, "unable to set period size (%s)", + msg_Err( p_aout, "unable to set buffer size (%s)", snd_strerror( i_snd_rc ) ); goto error; } - p_aout->output.i_nb_samples = i_period_size; /* Commit hardware parameters. */ if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 ) { - if ( b_retry == VLC_FALSE && + if ( b_retry == false && i_snd_pcm_format == SND_PCM_FORMAT_FLOAT) { - b_retry = VLC_TRUE; + b_retry = true; i_snd_pcm_format = SND_PCM_FORMAT_S16; p_aout->output.output.i_format = AOUT_FMT_S16_NE; msg_Warn( p_aout, "unable to commit hardware configuration " @@ -680,7 +684,7 @@ static int Open( vlc_object_t *p_this ) /* Create ALSA thread and wait for its readiness. */ if( vlc_thread_create( p_aout, "aout", ALSAThread, - VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) ) + VLC_THREAD_PRIORITY_OUTPUT, false ) ) { msg_Err( p_aout, "cannot create ALSA thread (%m)" ); goto error; @@ -726,14 +730,17 @@ static void Close( vlc_object_t *p_this ) struct aout_sys_t * p_sys = p_aout->output.p_sys; int i_snd_rc; + /* Make sure that the thread will stop once it is waken up */ + vlc_object_kill( p_aout ); + /* make sure the audio output thread is waken up */ vlc_mutex_lock( &p_aout->output.p_sys->lock ); vlc_cond_signal( &p_aout->output.p_sys->wait ); vlc_mutex_unlock( &p_aout->output.p_sys->lock ); - vlc_object_kill( p_aout ); + /* */ vlc_thread_join( p_aout ); - p_aout->b_die = VLC_FALSE; + p_aout->b_die = false; i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm ); @@ -760,17 +767,21 @@ static int ALSAThread( aout_instance_t * p_aout ) /* Wait for the exact time to start playing (avoids resampling) */ vlc_mutex_lock( &p_sys->lock ); - while( !p_sys->start_date ) + while( !p_sys->start_date && vlc_object_alive (p_aout) ) vlc_cond_wait( &p_sys->wait, &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock ); + if( !vlc_object_alive (p_aout) ) + goto cleanup; + mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 ); - while ( !p_aout->b_die ) + while ( vlc_object_alive (p_aout) ) { ALSAFill( p_aout ); } +cleanup: snd_pcm_drop( p_sys->p_snd_pcm ); free( p_aout->output.p_sys->p_status ); return 0; @@ -824,30 +835,30 @@ static void ALSAFill( aout_instance_t * p_aout ) } else { - /* Here the device should be in RUNNING state. - * p_status is valid. */ + /* Here the device should be in RUNNING state, p_status is valid. */ + snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status ); + if( delay == 0 ) /* workaround buggy alsa drivers */ + if( snd_pcm_delay( p_sys->p_snd_pcm, &delay ) < 0 ) + delay = 0; /* FIXME: use a positive minimal delay */ + int i_bytes = snd_pcm_frames_to_bytes( p_sys->p_snd_pcm, delay ); + next_date = mdate() + ( (mtime_t)i_bytes * 1000000 + / p_aout->output.output.i_bytes_per_frame + / p_aout->output.output.i_rate + * p_aout->output.output.i_frame_length ); -#if 0 - /* This apparently does not work correctly in Alsa 1.0.11 */ - snd_pcm_status_get_tstamp( p_status, &ts_next ); - next_date = (mtime_t)ts_next.tv_sec * 1000000 + ts_next.tv_usec; - if( next_date ) - { - next_date += (mtime_t)snd_pcm_status_get_delay(p_status) - * 1000000 / p_aout->output.output.i_rate; - } - else +#ifdef ALSA_DEBUG + snd_pcm_state_t state = snd_pcm_status_get_state( p_status ); + if( state != SND_PCM_STATE_RUNNING ) + msg_Err( p_aout, "pcm status (%d) != RUNNING", state ); + + msg_Dbg( p_aout, "Delay is %ld frames (%d bytes)", delay, i_bytes ); + + msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame ); + msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate ); + msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length ); + + msg_Dbg( p_aout, "Next date is in %d microseconds", (int)(next_date - mdate()) ); #endif - { - /* With screwed ALSA drivers the timestamp is always zero; - * use another method then */ - snd_pcm_sframes_t delay = 0; - - snd_pcm_delay( p_sys->p_snd_pcm, &delay ); - next_date = mdate() + (mtime_t)(delay) * 1000000 - / p_aout->output.output.i_rate - * p_aout->output.output.i_frame_length; - } } p_buffer = aout_OutputNextBuffer( p_aout, next_date, @@ -868,7 +879,7 @@ static void ALSAFill( aout_instance_t * p_aout ) * (stream is suspended and waiting for an application recovery) */ msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." ); - while( !p_aout->b_die && !p_aout->p_libvlc->b_die && + while( vlc_object_alive (p_aout) && vlc_object_alive (p_aout->p_libvlc) && ( i_snd_rc = snd_pcm_resume( p_sys->p_snd_pcm ) ) == -EAGAIN ) { msleep( 1000000 ); @@ -925,7 +936,7 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, GetDevices( p_item ); /* Signal change to the interface */ - p_item->b_dirty = VLC_TRUE; + p_item->b_dirty = true; return VLC_SUCCESS;