// TODO first frame causes broken pipe (underrun) because not enough data is sent // we should wait until the handle is ready void AlsaLayer::write(SFLAudioSample* buffer, int frames, snd_pcm_t * handle) { // Skip empty buffers if (!frames) return; int err = snd_pcm_writei(handle, (const void*)buffer, frames); if (err < 0) snd_pcm_recover(handle, err, 0); if (err >= 0) return; switch (err) { case -EPIPE: case -ESTRPIPE: case -EIO: { snd_pcm_status_t* status; snd_pcm_status_alloca(&status); if (ALSA_CALL(snd_pcm_status(handle, status), "Cannot get playback handle status") >= 0) if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { stopPlaybackStream(); preparePlaybackStream(); startPlaybackStream(); } ALSA_CALL(snd_pcm_writei(handle, (const void*)buffer, frames), "XRUN handling failed"); break; } case -EBADFD: { snd_pcm_status_t* status; snd_pcm_status_alloca(&status); if (ALSA_CALL(snd_pcm_status(handle, status), "Cannot get playback handle status") >= 0) { if (snd_pcm_status_get_state(status) == SND_PCM_STATE_SETUP) { ERROR("Writing in state SND_PCM_STATE_SETUP, should be " "SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING"); int error = snd_pcm_prepare(handle); if (error < 0) { ERROR("Failed to prepare handle: %s", snd_strerror(error)); stopPlaybackStream(); } } } break; } default: ERROR("Unknown write error, dropping frames: %s", snd_strerror(err)); stopPlaybackStream(); break; } }
static GstClockTime gst_alsasrc_get_timestamp (GstAlsaSrc * asrc) { snd_pcm_status_t *status; snd_htimestamp_t tstamp; GstClockTime timestamp; snd_pcm_uframes_t avail; gint err = -EPIPE; if (G_UNLIKELY (!asrc)) { GST_ERROR_OBJECT (asrc, "No alsa handle created yet !"); return GST_CLOCK_TIME_NONE; } if (G_UNLIKELY (snd_pcm_status_malloc (&status) != 0)) { GST_ERROR_OBJECT (asrc, "snd_pcm_status_malloc failed"); return GST_CLOCK_TIME_NONE; } if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) { GST_ERROR_OBJECT (asrc, "snd_pcm_status failed"); return GST_CLOCK_TIME_NONE; } /* in case an xrun condition has occured we need to handle this */ if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING) { if (xrun_recovery (asrc, asrc->handle, err) < 0) { GST_WARNING_OBJECT (asrc, "Could not recover from xrun condition !"); } /* reload the status alsa status object, since recovery made it invalid */ if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) { GST_ERROR_OBJECT (asrc, "snd_pcm_status failed"); } } /* get high resolution time stamp from driver */ snd_pcm_status_get_htstamp (status, &tstamp); timestamp = GST_TIMESPEC_TO_TIME (tstamp); /* max available frames sets the depth of the buffer */ avail = snd_pcm_status_get_avail (status); /* calculate the timestamp of the next sample to be read */ timestamp -= gst_util_uint64_scale_int (avail, GST_SECOND, asrc->rate); /* compensate for the fact that we really need the timestamp of the * previously read data segment */ timestamp -= asrc->period_time * 1000; snd_pcm_status_free (status); GST_LOG_OBJECT (asrc, "ALSA timestamp : %" GST_TIME_FORMAT ", delay %lu", GST_TIME_ARGS (timestamp), avail); return timestamp; }
int ai_alsa_xrun(audio_in_t *ai) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(ai->alsa.handle, status))<0) { mp_tmsg(MSGT_TV, MSGL_ERR, "ALSA status error: %s", snd_strerror(res)); return -1; } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { struct timeval now, diff, tstamp; gettimeofday(&now, 0); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); mp_tmsg(MSGT_TV, MSGL_ERR, "ALSA xrun!!! (at least %.3f ms long)\n", diff.tv_sec * 1000 + diff.tv_usec / 1000.0); if (mp_msg_test(MSGT_TV, MSGL_V)) { mp_tmsg(MSGT_TV, MSGL_ERR, "ALSA Status:\n"); snd_pcm_status_dump(status, ai->alsa.log); } if ((res = snd_pcm_prepare(ai->alsa.handle))<0) { mp_tmsg(MSGT_TV, MSGL_ERR, "ALSA xrun: prepare error: %s", snd_strerror(res)); return -1; } return 0; /* ok, data should be accepted again */ } mp_tmsg(MSGT_TV, MSGL_ERR, "ALSA read/write error"); return -1; }
static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, struct snd_pcm_status32 __user *src) { struct snd_pcm_status status; int err; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (put_user(status.state, &src->state) || put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) || put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) || put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state)) return -EFAULT; return err; }
static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) { snd_pcm_direct_t *dmix = pcm->private_data; memset(status, 0, sizeof(*status)); snd_pcm_status(dmix->spcm, status); switch (dmix->state) { case SNDRV_PCM_STATE_DRAINING: case SNDRV_PCM_STATE_RUNNING: snd_pcm_dmix_sync_ptr0(pcm, status->hw_ptr); status->delay += snd_pcm_mmap_playback_delay(pcm) + status->avail - dmix->spcm->buffer_size; break; default: break; } status->state = snd_pcm_dmix_state(pcm); status->trigger_tstamp = dmix->trigger_tstamp; status->avail = snd_pcm_mmap_playback_avail(pcm); status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max; dmix->avail_max = 0; return 0; }
int ai_alsa_xrun(audio_in_t *ai) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(ai->alsa.handle, status))<0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatusError, snd_strerror(res)); return -1; } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { struct timeval now, diff, tstamp; gettimeofday(&now, 0); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUN, diff.tv_sec * 1000 + diff.tv_usec / 1000.0); if (mp_msg_test(MSGT_TV, MSGL_V)) { mp_msg(MSGT_TV, MSGL_ERR, "ALSA Status:\n"); snd_pcm_status_dump(status, ai->alsa.log); } if ((res = snd_pcm_prepare(ai->alsa.handle))<0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError, snd_strerror(res)); return -1; } return 0; /* ok, data should be accepted again */ } mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError); return -1; }
// I/O error handler static void xrun(void) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(handle, status))<0) { error(_("status error: %s"), snd_strerror(res)); exit(EXIT_FAILURE); } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { struct timeval now, diff, tstamp; gettimeofday(&now, 0); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"), stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"), diff.tv_sec * 1000 + diff.tv_usec / 1000.0); if ((res = snd_pcm_prepare(handle))<0) { error(_("xrun: prepare error: %s"), snd_strerror(res)); exit(EXIT_FAILURE); } return; // ok, data should be accepted again } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_DRAINING) { } error(_("read/write error, state = %s"), snd_pcm_state_name(snd_pcm_status_get_state(status))); exit(EXIT_FAILURE); }
uint32_t AudioStreamOutALSA::latency() const { int err; int t; snd_pcm_status_t *status; snd_pcm_status_alloca(&status); if(mHandle->handle == NULL) { LOGV("handle is null, error !"); return 0; } if ((err = snd_pcm_status(mHandle->handle, status)) < 0) { LOGV("stream status error :%s\n", snd_strerror(err)); return USEC_TO_MSEC (mHandle->latency); } t = snd_pcm_status_get_delay(status); LOGV("snd_pcm_status_get_delay = %d", t); LOGV("AudioStreamOutALSA::latency = %d, sampleRate = %d", (t * 1000) / sampleRate(), sampleRate()); return (t * 1000) / sampleRate(); }
static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, struct snd_pcm_status32 __user *src) { struct snd_pcm_status status; int err; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (clear_user(src, sizeof(*src))) return -EFAULT; if (put_user(status.state, &src->state) || compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state) || compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp)) return -EFAULT; return err; }
static void xrun(void) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(AHandle, status)) < 0) { fprintf(stderr, "status error: %s", snd_strerror(res)); exit(EXIT_FAILURE); } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { struct timeval now, diff, tstamp; gettimeofday(&now, 0); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); fprintf(stderr, "Underrun!!! (at least %.3f ms long)\n", diff.tv_sec * 1000 + diff.tv_usec / 1000.0); if ((res = snd_pcm_prepare(AHandle)) < 0) { fprintf(stderr, "xrun: prepare error: %s", snd_strerror(res)); exit(EXIT_FAILURE); } return; // ok, data should be accepted // again } fprintf(stderr, "read/write error, state = %s", snd_pcm_state_name(snd_pcm_status_get_state(status))); exit(EXIT_FAILURE); }
qint64 QAudioOutputPrivate::elapsedUSecs() const { if(!handle) return 0; if (deviceState == QAudio::StoppedState) return 0; #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) snd_pcm_status_t* status; snd_pcm_status_alloca(&status); snd_timestamp_t t1,t2; if( snd_pcm_status(handle, status) >= 0) { snd_pcm_status_get_tstamp(status,&t1); snd_pcm_status_get_trigger_tstamp(status,&t2); t1.tv_sec-=t2.tv_sec; signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec; if(l < 0) { t1.tv_sec--; l = -l; l %= 1000000; } return ((t1.tv_sec * 1000000)+l); } else return 0; #else return clockStamp.elapsed()*1000; #endif return 0; }
static int log_state(ALSA_CARD *card) { // log card state snd_pcm_status_t *status; snd_pcm_state_t state; const char *state_str; snd_pcm_status_alloca(&status); snd_pcm_status(card->handle, status); state = snd_pcm_status_get_state(status); switch (state) { case SND_PCM_STATE_RUNNING: state_str = "running"; break; case SND_PCM_STATE_XRUN: state_str = "overrun"; break; case SND_PCM_STATE_DRAINING: state_str = "draining"; break; case SND_PCM_STATE_PAUSED: state_str = "paused"; break; case SND_PCM_STATE_SUSPENDED: state_str = "suspended"; break; case SND_PCM_STATE_DISCONNECTED: state_str = "disconnected"; break; default: state_str = "other"; } log_msg("ALSA: state: %s [%d]\n", state_str, (int)state); return state; }
static void DumpDeviceStatus (vlc_object_t *obj, snd_pcm_t *pcm) { snd_pcm_status_t *status; snd_pcm_status_alloca (&status); snd_pcm_status (pcm, status); Dump (obj, "current status:\n", snd_pcm_status_dump, status); }
/* stolen from devposs */ static uint32_t gettimer(void) { long tmp=playpos; int odelay; if (busy++) { odelay=kernlen; } else { int err; #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_status(alsa_pcm, alsa_pcm_status) = "); #endif if ((err=snd_pcm_status(alsa_pcm, alsa_pcm_status))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_status() failed: %s\n", snd_strerror(-err)); odelay=kernlen; } else { #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "snd_pcm_status_get_delay(alsa_pcm_status) = "); #endif odelay=snd_pcm_status_get_delay(alsa_pcm_status); #ifdef ALSA_DEBUG fprintf(stderr, "%i\n", odelay); #endif if (odelay<0) /* we ignore buffer-underruns */ odelay=0; else if (odelay==0) { /* ALSA sometimes (atlast on Stians Ubuntu laptop) gives odelay==0 always */ odelay = snd_pcm_status_get_avail_max(alsa_pcm_status) - snd_pcm_status_get_avail(alsa_pcm_status); if (odelay<0) odelay=0; } odelay<<=(bit16+stereo); if (odelay>kernlen) { odelay=kernlen; } else if ((odelay<kernlen)) { kernlen=odelay; kernpos=(cachepos-kernlen+buflen)%buflen; } } } tmp-=odelay; busy--; return imuldiv(tmp, 65536>>(stereo+bit16), plrRate); }
void gettimestamp(snd_pcm_t *handle, snd_timestamp_t *timestamp) { int err; snd_pcm_status_t *status; snd_pcm_status_alloca(&status); if ((err = snd_pcm_status(handle, status)) < 0) { printf("Stream status error: %s\n", snd_strerror(err)); exit(0); } snd_pcm_status_get_trigger_tstamp(status, timestamp); }
static int alsa_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch) { decoder_t *d = (decoder_t *)ad; media_pipe_t *mp = ad->ad_mp; int c; retry: c = snd_pcm_wait(d->h, 100); if(c >= 0) { c = snd_pcm_avail_update(d->h); } if(c == -EPIPE) { snd_pcm_prepare(d->h); usleep(100000); TRACE(TRACE_DEBUG, "ALSA", "Audio underrun"); d->samples = 0; goto retry; } c = MIN(d->max_frames_per_write, c); uint8_t *planes[8] = {0}; planes[0] = d->tmp; c = avresample_read(ad->ad_avr, planes, c); snd_pcm_status_t *status; int err; snd_pcm_status_alloca(&status); if ((err = snd_pcm_status(d->h, status)) >= 0) { if(pts != AV_NOPTS_VALUE) { snd_htimestamp_t hts; snd_pcm_status_get_trigger_htstamp(status, &hts); int64_t ts = hts.tv_sec * 1000000LL + hts.tv_nsec / 1000; ts += d->samples * 1000000LL / ad->ad_out_sample_rate; hts_mutex_lock(&mp->mp_clock_mutex); mp->mp_audio_clock_avtime = ts; mp->mp_audio_clock = pts; mp->mp_audio_clock_epoch = epoch; hts_mutex_unlock(&mp->mp_clock_mutex); } } snd_pcm_sframes_t fr; if(!snd_pcm_delay(d->h, &fr)) ad->ad_delay = 1000000L * fr / ad->ad_out_sample_rate; c = snd_pcm_writei(d->h, d->tmp, c); d->samples += c; return 0; }
void showstat(snd_pcm_t *handle, size_t frames) { int err; snd_pcm_status_t *status; snd_pcm_status_alloca(&status); if ((err = snd_pcm_status(handle, status)) < 0) { printf("Stream status error: %s\n", snd_strerror(err)); exit(0); } printf("*** frames = %li ***\n", (long)frames); snd_pcm_status_dump(status, output); }
/* more or less stolen from devposs */ static int getplaypos(void) { int retval; if (busy++) { } else { snd_pcm_sframes_t tmp; int err; #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_status(alsa_pcm, alsa_pcm_status) = "); #endif if ((err=snd_pcm_status(alsa_pcm, alsa_pcm_status))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_status() failed: %s\n", snd_strerror(-err)); } else { #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_pcm_status_get_delay(alsa_pcm_status = "); #endif tmp=snd_pcm_status_get_delay(alsa_pcm_status); #ifdef ALSA_DEBUG fprintf(stderr, "%ld\n", tmp); #endif tmp<<=(bit16+stereo); if (tmp<0) /* we ignore buffer-underruns */ tmp=0; else if (tmp==0) { /* ALSA sometimes (atlast on Stians Ubuntu laptop) gives odelay==0 always */ tmp = snd_pcm_status_get_avail_max(alsa_pcm_status) - snd_pcm_status_get_avail(alsa_pcm_status); if (tmp<0) tmp=0; } if (tmp>kernlen) { } else { kernlen=tmp; } kernpos=(cachepos-kernlen+buflen)%buflen; } } retval=kernpos; busy--; return retval; }
void alsamm_showstat(snd_pcm_t *handle) { int err; snd_pcm_status_t *status; snd_output_t *output = NULL; snd_pcm_status_alloca(&status); if ((err = snd_pcm_status(handle, status)) < 0) { check_error(err, "Get Stream status error"); return; } snd_pcm_status_dump(status, alsa_stdout); }
static void *peeper(void *data) { int thread_no = (long)data; snd_pcm_sframes_t val; snd_pcm_status_t *stat; snd_htimestamp_t tstamp; int mode = running_mode, err; snd_pcm_status_alloca(&stat); while (running) { if (running_mode == MODE_RANDOM) mode = rand() % MODE_RANDOM; switch (mode) { case MODE_AVAIL_UPDATE: val = snd_pcm_avail_update(pcm); err = 0; break; case MODE_STATUS: err = snd_pcm_status(pcm, stat); val = snd_pcm_status_get_avail(stat); break; case MODE_HWSYNC: err = snd_pcm_hwsync(pcm); break; case MODE_TIMESTAMP: err = snd_pcm_htimestamp(pcm, (snd_pcm_uframes_t *)&val, &tstamp); break; default: err = snd_pcm_delay(pcm, &val); break; } if (quiet) continue; if (running_mode == MODE_RANDOM) { fprintf(stderr, "%d%c%s", thread_no, mode_suffix[mode], err ? "!" : ""); } else { if (show_value && mode != MODE_HWSYNC) fprintf(stderr, "\r%d ", (int)val); else fprintf(stderr, "%d%s", thread_no, err ? "!" : ""); } } return NULL; }
/*---------------------------------------------------------------------- | AlsaOutput_GetStatus +---------------------------------------------------------------------*/ BLT_METHOD AlsaOutput_GetStatus(BLT_OutputNode* _self, BLT_OutputNodeStatus* status) { AlsaOutput* self = ATX_SELF(AlsaOutput, BLT_OutputNode); snd_pcm_status_t* pcm_status; snd_pcm_sframes_t delay = 0; int io_result; /* default values */ status->media_time.seconds = 0; status->media_time.nanoseconds = 0; status->flags = 0; /* get the driver status */ snd_pcm_status_alloca_no_assert(&pcm_status); io_result = snd_pcm_status(self->device_handle, pcm_status); if (io_result != 0) { return BLT_FAILURE; } delay = snd_pcm_status_get_delay(pcm_status); if (delay == 0) { /* workaround buggy alsa drivers */ io_result = snd_pcm_delay(self->device_handle, &delay); if (io_result != 0) { return BLT_FAILURE; } } if (delay > 0 && self->media_type.sample_rate) { ATX_UInt64 media_time_samples = (self->next_media_time * (ATX_UInt64)self->media_type.sample_rate)/ (ATX_UInt64)1000000000; ATX_UInt64 media_time_ns; if (delay <= (snd_pcm_sframes_t)media_time_samples) { media_time_samples -= delay; } else { media_time_samples = 0; } media_time_ns = (media_time_samples*(ATX_UInt64)1000000000)/self->media_type.sample_rate; status->media_time = BLT_TimeStamp_FromNanos(media_time_ns); } else { status->media_time = BLT_TimeStamp_FromNanos(self->next_media_time); } /* return the computed media time */ ATX_LOG_FINEST_3("delay = %lld samples, input port time = %lld, media time = %lld", (ATX_UInt64)delay, self->next_media_time, BLT_TimeStamp_ToNanos(status->media_time)); return BLT_SUCCESS; }
/* I/O error handler */ static void xrun(void) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(handle, status))<0) { error("status error: %s", snd_strerror(res)); exit(EXIT_FAILURE); } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { struct timeval now, diff, tstamp; gettimeofday(&now, 0); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); fprintf(stderr, "%s!!! (at least %.3f ms long)\n", stream == SND_PCM_STREAM_PLAYBACK ? "underrun" : "overrun", diff.tv_sec * 1000 + diff.tv_usec / 1000.0); if (verbose) { fprintf(stderr, "Status:\n"); snd_pcm_status_dump(status, log); } if ((res = snd_pcm_prepare(handle))<0) { error("xrun: prepare error: %s", snd_strerror(res)); exit(EXIT_FAILURE); } return; /* ok, data should be accepted again */ } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_DRAINING) { if (verbose) { fprintf(stderr, "Status(DRAINING):\n"); snd_pcm_status_dump(status, log); } if (stream == SND_PCM_STREAM_CAPTURE) { fprintf(stderr, "capture stream format change? attempting recover...\n"); if ((res = snd_pcm_prepare(handle))<0) { error("xrun(DRAINING): prepare error: %s", snd_strerror(res)); exit(EXIT_FAILURE); } return; } } if (verbose) { fprintf(stderr, "Status(R/W):\n"); snd_pcm_status_dump(status, log); } error("read/write error, state = %s", snd_pcm_state_name(snd_pcm_status_get_state(status))); exit(EXIT_FAILURE); }
/* how many byes are free in the buffer */ static int get_space(void) { snd_pcm_status_t *status; int ret; snd_pcm_status_alloca(&status); if ((ret = snd_pcm_status(alsa_handler, status)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_CannotGetPcmStatus, snd_strerror(ret)); return 0; } ret = snd_pcm_status_get_avail(status) * bytes_per_sample; if (ret > ao_data.buffersize) // Buffer underrun? ret = ao_data.buffersize; return ret; }
/* how many byes are free in the buffer */ static int get_space(void) { snd_pcm_status_t *status; int ret; snd_pcm_status_alloca(&status); if ((ret = snd_pcm_status(alsa_handler, status)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_CannotGetPcmStatus, snd_strerror(ret)); return(0); } ret = snd_pcm_status_get_avail(status) * bytes_per_sample; if (ret > MAX_OUTBURST) ret = MAX_OUTBURST; return(ret); }
static void alsa_resume(snd_pcm_t *handle){ int err; snd_pcm_status_t *status=NULL; snd_pcm_status_alloca(&status); if ((err=snd_pcm_status(handle,status))!=0){ ms_warning("snd_pcm_status() failed: %s",snd_strerror(err)); return; } if (snd_pcm_status_get_state(status)==SND_PCM_STATE_SUSPENDED){ ms_warning("Maybe suspended, trying resume"); if ((err=snd_pcm_resume(handle))!=0){ if (err!=EWOULDBLOCK) ms_warning("snd_pcm_resume() failed: %s",snd_strerror(err)); } } }
static void alsa_prefill( void ) { snd_pcm_status_t *status; char buf[512]; int frames, cnt; snd_pcm_status_malloc( &status ); snd_pcm_status( alsa.pcm, status ); frames = snd_pcm_status_get_avail(status); snd_pcm_status_free( status ); memset( buf, 0, sizeof(buf) ); cnt = sizeof(buf)/alsa.bpf; for( ; frames > 0; frames -= cnt ) { if( cnt > frames ) cnt = frames; snd_pcm_writei( alsa.pcm, buf, sizeof(buf)/alsa.bpf ); } }
static int ao_alsa_space(alsa_ctx_t *ctx) { snd_pcm_t *alsa_handle = (snd_pcm_t *) ctx->handle; int ret; snd_pcm_status_t *status; int bytes_per_sample = ctx->bps * ctx->channels / 8; snd_pcm_status_alloca(&status); if ((ret = snd_pcm_status(alsa_handle, status)) < 0) { dt_info("%s,%d: %s\n", __FUNCTION__, __LINE__, snd_strerror(ret)); return 0; } ret = snd_pcm_status_get_avail(status) * bytes_per_sample; if (ret > ctx->buf_size) { ret = ctx->buf_size; } return ret; }
static void xrun(void) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(AHandle, status))<0) { fprintf(stderr, "status error: %s", snd_strerror(res)); return; } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { if (monotonic) { #ifdef HAVE_CLOCK_GETTIME struct timespec now, diff, tstamp; clock_gettime(CLOCK_MONOTONIC, &now); snd_pcm_status_get_trigger_htstamp(status, &tstamp); timermsub(&now, &tstamp, &diff); fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"), stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"), diff.tv_sec * 1000 + diff.tv_nsec / 10000000.0); #else fprintf(stderr, "%s !!!\n", "underrun"); #endif } else { struct timeval now, diff, tstamp; gettimeofday(&now, 0); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); fprintf(stderr, "%s!!! (at least %.3f ms long)\n", "Underrun", diff.tv_sec * 1000 + diff.tv_usec / 1000.0); } if ((res = snd_pcm_prepare(AHandle))<0) { fprintf(stderr, "xrun: prepare error: %s", snd_strerror(res)); /* we should probably die here */ return; } return; /* ok, data should be accepted again */ } fprintf(stderr, "read/write error, state = %s", snd_pcm_state_name(snd_pcm_status_get_state(status))); }
static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream, struct snd_pcm_status_x32 __user *src, bool ext) { struct snd_pcm_status status; int err; memset(&status, 0, sizeof(status)); /* * with extension, parameters are read/write, * get audio_tstamp_data from user, * ignore rest of status structure */ if (ext && get_user(status.audio_tstamp_data, (u32 __user *)(&src->audio_tstamp_data))) return -EFAULT; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (clear_user(src, sizeof(*src))) return -EFAULT; if (put_user(status.state, &src->state) || put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state) || put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || put_timespec(&status.audio_tstamp, &src->audio_tstamp) || put_timespec(&status.driver_tstamp, &src->driver_tstamp) || put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) return -EFAULT; return err; }
INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) { AlsaPcmInfo* info = (AlsaPcmInfo*) id; int ret; INT64 result = javaBytePos; snd_pcm_state_t state; state = snd_pcm_state(info->handle); if (state != SND_PCM_STATE_XRUN) { #ifdef GET_POSITION_METHOD2 snd_timestamp_t* ts; snd_pcm_uframes_t framesAvail; // note: slight race condition if this is called simultaneously from 2 threads ret = snd_pcm_status(info->handle, info->positionStatus); if (ret != 0) { ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret)); result = javaBytePos; } else { // calculate from time value, or from available bytes framesAvail = snd_pcm_status_get_avail(info->positionStatus); result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize); } #endif #ifdef GET_POSITION_METHOD3 snd_pcm_uframes_t framesAvail; ret = snd_pcm_avail(info->handle, &framesAvail); if (ret != 0) { ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret)); result = javaBytePos; } else { result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize); } #endif #ifdef GET_POSITION_METHOD1 result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource)); #endif } //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result); return result; }