示例#1
0
// 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;
    }
}
示例#2
0
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;
}
示例#3
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_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;
}
示例#5
0
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;
}
示例#6
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;
}
示例#7
0
// 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);
}
示例#8
0
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();
}
示例#9
0
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;
}
示例#10
0
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;
}
示例#12
0
文件: alsa.c 项目: pmyadlowsky/qmx
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;
	}
示例#13
0
文件: alsa.c 项目: sailfish009/vlc
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);
}
示例#14
0
/* 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);
}
示例#15
0
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);
}
示例#16
0
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;
}
示例#17
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);
}
示例#18
0
/* 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;
}
示例#19
0
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);
}
示例#20
0
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;
}
示例#21
0
/*----------------------------------------------------------------------
|    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;
}
示例#22
0
/* 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);
}
示例#23
0
文件: ao_alsa.c 项目: C3MA/fc_mplayer
/* 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;
}
示例#24
0
/* 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);
}
示例#25
0
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));
		}
	}
}
示例#26
0
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 );
	}
}
示例#27
0
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;
}
示例#28
0
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)));
}
示例#29
0
文件: pcm_compat.c 项目: 020gzh/linux
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;
}