+ /* Underrun, try to recover as quickly as possible */
+ next_date = mdate();
+ }
+ else
+ {
+ /* 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 );
+
+#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
+ }
+
+ p_buffer = aout_OutputNextBuffer( p_aout, next_date,
+ (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i')) );
+
+ /* Audio output buffer shortage -> stop the fill process and wait */
+ if( p_buffer == NULL )
+ goto error;
+
+ for (;;)
+ {
+ i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,
+ p_buffer->i_nb_samples );
+ if( i_snd_rc != -ESTRPIPE )
+ break;
+
+ /* a suspend event occurred
+ * (stream is suspended and waiting for an application recovery) */
+ msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
+
+ 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 )