#define ALSA_PCM_NEW_SW_PARAMS_API
#include <alsa/asoundlib.h>
+/*#define ALSA_DEBUG*/
+
/*****************************************************************************
* aout_sys_t: ALSA audio output method descriptor
*****************************************************************************
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 )
/* 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 && !p_aout->b_die )
vlc_cond_wait( &p_sys->wait, &p_sys->lock );
vlc_mutex_unlock( &p_sys->lock );
+ if( p_aout->b_die )
+ goto cleanup;
+
mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
while ( !p_aout->b_die )
ALSAFill( p_aout );
}
+cleanup:
snd_pcm_drop( p_sys->p_snd_pcm );
free( p_aout->output.p_sys->p_status );
return 0;
{
/* Here the device should be in RUNNING state.
* p_status is valid. */
+ snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status );
+ 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,