]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm: hw: introduce SNDRV_PCM_HW_PARAMS_DRAIN_SILENCE
authorJaroslav Kysela <perex@perex.cz>
Tue, 2 May 2023 08:34:41 +0000 (10:34 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 3 May 2023 13:58:56 +0000 (15:58 +0200)
The application may not require to touch the playback
sample stream for the drain operation at all. In this case,
the application is responsible to setup a silencing mechanism
for the playback or another graceful stop (like using the
rewind operation).

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
include/pcm.h
include/sound/uapi/asound.h
src/pcm/pcm.c
src/pcm/pcm_hw.c
src/pcm/pcm_local.h

index dd031b6cc8cf1d3ef75747598c2f2f8941844b7c..966d6ffd881f9c8565e27cfc15cc5255400922aa 100644 (file)
@@ -822,6 +822,8 @@ int snd_pcm_hw_params_set_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *par
 int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
 int snd_pcm_hw_params_set_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
 int snd_pcm_hw_params_get_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
+int snd_pcm_hw_params_set_drain_silence(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
+int snd_pcm_hw_params_get_drain_silence(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
 
 int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
 int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
index 0b8834f24dba7d4d4c76f98b5638d146bb858cc0..62a0364fc3cdf0fe7d0083a2b77fec70f00bd964 100644 (file)
@@ -390,6 +390,9 @@ typedef int snd_pcm_hw_param_t;
 #define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
 #define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER      (1<<1)  /* export buffer */
 #define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP   (1<<2)  /* disable period wakeups */
+#define SNDRV_PCM_HW_PARAMS_NO_DRAIN_SILENCE   (1<<3)  /* suppress the silence fill
+                                                        * for draining
+                                                        */
 
 struct snd_interval {
        unsigned int min, max;
index d387da3d83a5767c3f9137d704bc09c049aa225b..997a8a6acddfc0f17117c32593d94ae6b39e2954 100644 (file)
@@ -4958,6 +4958,43 @@ int snd_pcm_hw_params_get_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *par
        return 0;
 }
 
+/**
+ * \brief Restrict a configuration space to fill the end of playback stream with silence when drain() is invoked
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val 0 = disabled, 1 = enabled (default) fill the end of the playback stream with silence when drain() is invoked
+ * \return Zero on success, otherwise a negative error code.
+ *
+ * When disabled, the application should handle the end of stream gracefully
+ * (fill the silent samples to align to the period size plus some extra
+ * samples for hardware / driver without perfect drain). Note that the rewind
+ * may be used for this purpose or the sw_params silencing mechanism.
+ */
+int snd_pcm_hw_params_set_drain_silence(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
+{
+       assert(pcm && params);
+       if (val)
+               params->flags &= ~SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE;
+       else
+               params->flags |= SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE;
+       params->rmask = ~0;
+       return snd_pcm_hw_refine(pcm, params);
+}
+
+/**
+ * \brief Extract drain with the filling of silence samples from a configuration space
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val 0 = disabled, 1 = enabled
+ * \return 0 otherwise a negative error code
+ */
+int snd_pcm_hw_params_get_drain_silence(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
+{
+       assert(pcm && params && val);
+       *val = params->flags & SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE ? 0 : 1;
+       return 0;
+}
+
 /**
  * \brief Extract period time from a configuration space
  * \param params Configuration space
index 37a18b863dee4940e72cef9026bffa3a90bc67cf..180a3e84b7640561e2d1fed055fd56ed2ff18a52 100644 (file)
@@ -399,7 +399,8 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
        params->info &= ~0xf0000000;
        if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY)
                params->info |= SND_PCM_INFO_MONOTONIC;
-       hw->perfect_drain = !!(params->info & SND_PCM_INFO_PERFECT_DRAIN);
+       hw->perfect_drain = !!(params->info & SND_PCM_INFO_PERFECT_DRAIN) ||
+                           !!(params->flags & SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE);
        return query_status_data(hw);
 }
 
index b039dda00717f409ba4d5c54c913683b3302421b..abea6654c3fff3a5eea9af21fa6f6a1cb853e520 100644 (file)
 #define SND_PCM_HW_PARAMS_NORESAMPLE SNDRV_PCM_HW_PARAMS_NORESAMPLE
 #define SND_PCM_HW_PARAMS_EXPORT_BUFFER SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER
 #define SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
+#define SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE SNDRV_PCM_HW_PARAMS_NO_DRAIN_SILENCE
 
 #define SND_PCM_INFO_MONOTONIC 0x80000000