diff options
-rw-r--r-- | include/tinyalsa/pcm.h | 2 | ||||
-rw-r--r-- | include/tinyalsa/plugin.h | 5 | ||||
-rw-r--r-- | src/pcm.c | 16 | ||||
-rw-r--r-- | src/pcm_plugin.c | 13 | ||||
-rw-r--r-- | utils/tinyplay.c | 2 |
5 files changed, 36 insertions, 2 deletions
diff --git a/include/tinyalsa/pcm.h b/include/tinyalsa/pcm.h index 9fca92d..35318a5 100644 --- a/include/tinyalsa/pcm.h +++ b/include/tinyalsa/pcm.h @@ -361,6 +361,8 @@ int pcm_prepare(struct pcm *pcm); int pcm_start(struct pcm *pcm); +int pcm_drain(struct pcm *pcm); + int pcm_stop(struct pcm *pcm); int pcm_wait(struct pcm *pcm, int timeout); diff --git a/include/tinyalsa/plugin.h b/include/tinyalsa/plugin.h index b2f97b9..055734c 100644 --- a/include/tinyalsa/plugin.h +++ b/include/tinyalsa/plugin.h @@ -124,7 +124,10 @@ struct pcm_plugin_ops { int (*prepare) (struct pcm_plugin *plugin); /** Start data transfer from/to the plugin */ int (*start) (struct pcm_plugin *plugin); - /** Drop pcm frames */ + /** Signal the plugin to drain PCM */ + int (*drain) (struct pcm_plugin *plugin); + /** Stop a PCM dropping pending frames if drain() is NOT called. + * Stop a PCM preserving pending frames if drain() is called. */ int (*drop) (struct pcm_plugin *plugin); /** Any custom or alsa specific ioctl implementation */ int (*ioctl) (struct pcm_plugin *plugin, @@ -1218,6 +1218,22 @@ int pcm_start(struct pcm *pcm) return 0; } +/** Drains a PCM. + * @param pcm A PCM handle. + * @return On success, zero; on failure, a negative number. + * @ingroup libtinyalsa-pcm + */ +int pcm_drain(struct pcm *pcm) +{ + if (!pcm_is_ready(pcm)) + return -1; + + if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_DRAIN) < 0) + return oops(pcm, errno, "cannot drain channel"); + + return 0; +} + /** Stops a PCM. * @param pcm A PCM handle. * @return On success, zero; on failure, a negative number. diff --git a/src/pcm_plugin.c b/src/pcm_plugin.c index b6b69aa..4d2651c 100644 --- a/src/pcm_plugin.c +++ b/src/pcm_plugin.c @@ -622,6 +622,16 @@ static int pcm_plug_drop(struct pcm_plug_data *plug_data) return rc; } +static int pcm_plug_drain(struct pcm_plug_data *plug_data) +{ + struct pcm_plugin *plugin = plug_data->plugin; + + if (plugin->state != PCM_PLUG_STATE_RUNNING) + return -EBADFD; + + return plug_data->ops->drain(plugin); +} + static int pcm_plug_ioctl(void *data, unsigned int cmd, ...) { struct pcm_plug_data *plug_data = data; @@ -659,6 +669,9 @@ static int pcm_plug_ioctl(void *data, unsigned int cmd, ...) case SNDRV_PCM_IOCTL_START: ret = pcm_plug_start(plug_data); break; + case SNDRV_PCM_IOCTL_DRAIN: + ret = pcm_plug_drain(plug_data); + break; case SNDRV_PCM_IOCTL_DROP: ret = pcm_plug_drop(plug_data); break; diff --git a/utils/tinyplay.c b/utils/tinyplay.c index 9f72bbb..d617074 100644 --- a/utils/tinyplay.c +++ b/utils/tinyplay.c @@ -112,7 +112,7 @@ static bool is_wave_file(const char *filetype) return filetype != NULL && strcmp(filetype, "wav") == 0; } -static bool signed_pcm_bits_to_format(int bits) +static enum pcm_format signed_pcm_bits_to_format(int bits) { switch (bits) { case 8: |