From patchwork Wed Dec 17 17:27:47 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Cussins X-Patchwork-Id: 5508561 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 5D68F9F1CD for ; Wed, 17 Dec 2014 17:33:12 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 54BC1209D3 for ; Wed, 17 Dec 2014 17:33:11 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id EC6E1209DC for ; Wed, 17 Dec 2014 17:33:09 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id EDD9E260A5B; Wed, 17 Dec 2014 18:33:08 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, FREEMAIL_FROM,NO_DNS_FOR_FROM,SUBJ_OBFU_PUNCT_MANY,T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id EE015261299; Wed, 17 Dec 2014 18:32:37 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 5386B261299; Wed, 17 Dec 2014 18:32:37 +0100 (CET) Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by alsa0.perex.cz (Postfix) with ESMTP id 874002612D7 for ; Wed, 17 Dec 2014 18:31:28 +0100 (CET) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 0064720F00 for ; Wed, 17 Dec 2014 12:31:27 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute1.internal (MEProxy); Wed, 17 Dec 2014 12:31:27 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=eml.cc; h= x-sasl-enc:from:to:cc:subject:date:message-id; s=mesmtp; bh=X6cV shHFmnJFVeEWcTRtsSwNuoA=; b=MabtnJj9GlgsQ3xiSWgQV6eV+OS0rQuJn1DS hBwg97kd+VTVCurD+STpiS4OiYiSnUPJd/gO89VENUwJm12BEQT0HJEisTifBBYC R29db1cFvnYt9/JVkMX8qjovbMbsV7W4I0411KQwt/5M9NUwMw5GNzcp8smUaKad anqPkII= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=x-sasl-enc:from:to:cc:subject:date :message-id; s=smtpout; bh=X6cVshHFmnJFVeEWcTRtsSwNuoA=; b=Z3iz6 Xuj+3Eij4xTjQ2riD6UfcMHpTb2T5bLi9njzI7HJRDgqWX39jEJwiWESpMA8iq8X 1m8En9crr0Odr+pV/sn9tZuIzKMeCdEWIpTNrTmpAIoaadQHfKn1AtTE9w78gZar bHolFVZZmgtyQCf5OFyH9TuLhJDuBcdYeLIvsM= X-Sasl-enc: DAjfeJAb9NUJrOMXlxqUWtpH7CoAd08c1Tcz6rAn32ee 1418837487 Received: from pc695.lan (unknown [217.169.4.223]) by mail.messagingengine.com (Postfix) with ESMTPA id EABF1C00284; Wed, 17 Dec 2014 12:31:26 -0500 (EST) From: Tim Cussins To: alsa-devel@alsa-project.org Date: Wed, 17 Dec 2014 17:27:47 +0000 Message-Id: <1418837267-10896-1-git-send-email-timcussins@eml.cc> X-Mailer: git-send-email 1.7.10.4 Cc: tiwai@suse.de, nstoughton@aether.com, Tim Cussins , pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH v2 1/1] alsa-lib: Add snd_pcm_start_at. X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Add notion of TSTAMP_CLASS (SYSTEM/AUDIO) as per Pierre's suggestion. Add snd_pcm_start_at() Signed-off-by: Tim Cussins diff --git a/include/pcm.h b/include/pcm.h index 0655e7f..c57edca 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -323,13 +323,25 @@ typedef enum _snd_pcm_tstamp { SND_PCM_TSTAMP_LAST = SND_PCM_TSTAMP_ENABLE } snd_pcm_tstamp_t; +typedef enum _snd_pcm_tstamp_class { + SND_PCM_TSTAMP_CLASS_SYSTEM = 0, + SND_PCM_TSTAMP_CLASS_AUDIO, + SND_PCM_TSTAMP_CLASS_LAST = SND_PCM_TSTAMP_CLASS_AUDIO, +} snd_pcm_tstamp_class_t; + typedef enum _snd_pcm_tstamp_type { SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /** gettimeofday equivalent */ - SND_PCM_TSTAMP_TYPE_MONOTONIC, /** posix_clock_monotonic equivalent */ + SND_PCM_TSTAMP_TYPE_MONOTONIC, /** posix_clock_monotonic equivalent */ SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /** monotonic_raw (no NTP) */ SND_PCM_TSTAMP_TYPE_LAST = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW, } snd_pcm_tstamp_type_t; +typedef enum _snd_pcm_audio_tstamp_type { + SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 0, + SND_PCM_AUDIO_TSTAMP_TYPE_LINK, + SND_PCM_AUDIO_TSTAMP_TYPE_LAST = SND_PCM_AUDIO_TSTAMP_TYPE_LINK, +} snd_pcm_audio_tstamp_t; + /** Unsigned frames quantity */ typedef unsigned long snd_pcm_uframes_t; /** Signed frames quantity */ @@ -478,6 +490,7 @@ int snd_pcm_prepare(snd_pcm_t *pcm); int snd_pcm_reset(snd_pcm_t *pcm); int snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status); int snd_pcm_start(snd_pcm_t *pcm); +int snd_pcm_start_at(snd_pcm_t *pcm, snd_pcm_tstamp_class_t tstamp_class, int tstamp_type, const snd_htimestamp_t* start_time); int snd_pcm_drop(snd_pcm_t *pcm); int snd_pcm_drain(snd_pcm_t *pcm); int snd_pcm_pause(snd_pcm_t *pcm, int enable); diff --git a/include/sound/asound.h b/include/sound/asound.h index 1f23cd6..1592160 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -466,12 +466,30 @@ struct snd_xfern { }; enum { + SNDRV_PCM_TSTAMP_CLASS_SYSTEM = 0, + SNDRV_PCM_TSTAMP_CLASS_AUDIO, + SNDRV_PCM_TSTAMP_CLASS_LAST = SNDRV_PCM_TSTAMP_CLASS_AUDIO, +}; + +enum { SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ - SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ + SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, }; +enum { + SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 0, + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK, + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK, +}; + +struct snd_start_at { + int tstamp_class; + int tstamp_type; + struct timespec start_time; +}; + /* channel positions */ enum { SNDRV_CHMAP_UNKNOWN = 0, @@ -550,6 +568,8 @@ enum { #define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern) #define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) #define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) +#define SNDRV_PCM_IOCTL_START_AT _IOW('A', 0x62, struct snd_start_at) + /***************************************************************************** * * diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index baa47c7..40a4689 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -1085,6 +1085,37 @@ int snd_pcm_start(snd_pcm_t *pcm) } /** + * \brief Start a PCM at a specified point in the future + * \param pcm PCM handle + * \param tstamp_class specifies the class of tstamp_type + * \param tstamp_type specifies the clock with which to interpret \p start_time + * \param start_time Absolute time at which to start the stream + * \return 0 on success otherwise a negative error code + * \retval -ENOSYS operation not supported for the current timestamp type + * \retval -EINVAL timespec, tstamp_class or tstamp_type is invalid + * \retval -ETIME requested start_time cannot be satisfied + * + * This method is non-blocking: It establishes an appropriate timer in the kernel + * that will start the stream on expiry. + * + * The timer is unconditionally cancelled upon any \a attempt to change the stream + * state e.g. drop, drain, start, start_at. + */ +int snd_pcm_start_at(snd_pcm_t *pcm, snd_pcm_tstamp_class_t tstamp_class, int tstamp_type, const snd_htimestamp_t *start_time) +{ + assert(pcm); + assert(start_time); + if (CHECK_SANITY(! pcm->setup)) { + SNDMSG("PCM not set up"); + return -EIO; + } + if (pcm->fast_ops->start_at) { + return pcm->fast_ops->start_at(pcm->fast_op_arg, tstamp_class, tstamp_type, start_time); + } + return -EINVAL; +} + +/** * \brief Stop a PCM dropping pending frames * \param pcm PCM handle * \return 0 on success otherwise a negative error code diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index c34b766..0190787 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -620,6 +620,26 @@ static int snd_pcm_hw_start(snd_pcm_t *pcm) return 0; } +static int snd_pcm_hw_start_at(snd_pcm_t *pcm, snd_pcm_tstamp_class_t tstamp_class, int tstamp_type, const snd_htimestamp_t *start_time) +{ + snd_pcm_hw_t *hw = pcm->private_data; + int err; + + struct snd_start_at start_at = { + .tstamp_class = tstamp_class, + .tstamp_type = tstamp_type, + .start_time = *start_time + }; + + sync_ptr(hw, 0); + if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START_AT, &start_at) < 0) { + err = -errno; + SYSMSG("SNDRV_PCM_IOCTL_START_AT failed (%i)", err); + return err; + } + return 0; +} + static int snd_pcm_hw_drop(snd_pcm_t *pcm) { snd_pcm_hw_t *hw = pcm->private_data; @@ -1336,6 +1356,7 @@ static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { .prepare = snd_pcm_hw_prepare, .reset = snd_pcm_hw_reset, .start = snd_pcm_hw_start, + .start_at = snd_pcm_hw_start_at, .drop = snd_pcm_hw_drop, .drain = snd_pcm_hw_drain, .pause = snd_pcm_hw_pause, diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 394505f..5cdfd3a 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -154,6 +154,7 @@ typedef struct { int (*prepare)(snd_pcm_t *pcm); int (*reset)(snd_pcm_t *pcm); int (*start)(snd_pcm_t *pcm); + int (*start_at)(snd_pcm_t *pcm, snd_pcm_tstamp_class_t tstamp_class, int tstamp_type, const snd_htimestamp_t *start_time); int (*drop)(snd_pcm_t *pcm); int (*drain)(snd_pcm_t *pcm); int (*pause)(snd_pcm_t *pcm, int enable);