From 757785fece0be06d3a84b1f05bc6f6c91fb50166 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 6 Feb 2003 19:15:53 +0000 Subject: [PATCH] Added snd_timer_async() function. More updates to pcm_dmix.c . --- src/pcm/pcm_dmix.c | 77 ++++++++++++++++++++++++++++++----------- src/pcm/pcm_null.c | 3 +- src/timer/timer.c | 22 ++++++++++++ src/timer/timer_hw.c | 52 +++++++++++++++++++++++----- src/timer/timer_local.h | 3 ++ 5 files changed, 125 insertions(+), 32 deletions(-) diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index a19b19f1..4ea253f1 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -48,6 +48,12 @@ const char *_snd_module_pcm_dmix = ""; #endif +/* + * + */ + +int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid); + /* * */ @@ -432,24 +438,51 @@ static int client_discard(snd_pcm_dmix_t *dmix) return 0; } +/* + * ring buffer operation + */ + +/* + * synchronize shm ring buffer with hardware + */ +static void snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm, snd_pcm_uframes_t size) +{ + snd_pcm_dmix_t *dmix = pcm->private_data; + snd_pcm_uframes_t appl_ptr; + + /* get the start of update area */ + appl_ptr = dmix->appl_ptr - size; + if (appl_ptr > pcm->boundary) + appl_ptr += pcm->boundary; +} + /* * plugin implementation */ -static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock) +static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock ATTRIBUTE_UNUSED) { + /* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ return 0; } static int snd_pcm_dmix_async(snd_pcm_t *pcm, int sig, pid_t pid) { snd_pcm_dmix_t *dmix = pcm->private_data; - return 0; + return snd_timer_async(dmix->timer, sig, pid); } static int snd_pcm_dmix_info(snd_pcm_t *pcm, snd_pcm_info_t * info) { snd_pcm_dmix_t *dmix = pcm->private_data; + memset(info, 0, sizeof(*info)); + info->stream = pcm->stream; + info->card = -1; + /* FIXME: fill this with something more useful: we know the hardware name */ + strncpy(info->id, pcm->name, sizeof(info->id)); + strncpy(info->name, pcm->name, sizeof(info->name)); + strncpy(info->subname, pcm->name, sizeof(info->subname)); + info->subdevices_count = 1; return 0; } @@ -499,26 +532,25 @@ static int snd_pcm_dmix_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) static int snd_pcm_dmix_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) { - snd_pcm_dmix_t *dmix = pcm->private_data; + // snd_pcm_dmix_t *dmix = pcm->private_data; return 0; } static int snd_pcm_dmix_hw_free(snd_pcm_t *pcm) { - snd_pcm_dmix_t *dmix = pcm->private_data; + // snd_pcm_dmix_t *dmix = pcm->private_data; return 0; } static int snd_pcm_dmix_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) { - snd_pcm_dmix_t *dmix = pcm->private_data; + // snd_pcm_dmix_t *dmix = pcm->private_data; return 0; } static int snd_pcm_dmix_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) { - snd_pcm_dmix_t *dmix = pcm->private_data; - return 0; + return snd_pcm_channel_info_shm(pcm, info, -1); } static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) @@ -595,33 +627,35 @@ static int snd_pcm_dmix_resume(snd_pcm_t *pcm) static snd_pcm_sframes_t snd_pcm_dmix_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { - return -ENODEV; + int res = snd_pcm_mmap_writei(pcm, buffer, size); + snd_pcm_dmix_sync_ptr(pcm, size); + return res; } static snd_pcm_sframes_t snd_pcm_dmix_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { - return -ENODEV; + int res = snd_pcm_mmap_writen(pcm, bufs, size); + snd_pcm_dmix_sync_ptr(pcm, size); + return res; } -static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) +static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED) { return -ENODEV; } -static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) +static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED) { return -ENODEV; } -static int snd_pcm_dmix_mmap(snd_pcm_t *pcm) +static int snd_pcm_dmix_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) { - snd_pcm_dmix_t *dmix = pcm->private_data; return 0; } -static int snd_pcm_dmix_munmap(snd_pcm_t *pcm) +static int snd_pcm_dmix_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) { - snd_pcm_dmix_t *dmix = pcm->private_data; return 0; } @@ -648,16 +682,17 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm) } static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm, - snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, - snd_pcm_uframes_t size) + snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, + snd_pcm_uframes_t size) { - snd_pcm_dmix_t *hw = pcm->private_data; - return 0; + snd_pcm_mmap_appl_forward(pcm, size); + snd_pcm_dmix_sync_ptr(pcm, size); + return size; } -static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm ATTRIBUTE_UNUSED) { - snd_pcm_dmix_t *hw = pcm->private_data; + //snd_pcm_dmix_t *dmix = pcm->private_data; return 0; } diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c index c52ded4f..04202a6f 100644 --- a/src/pcm/pcm_null.c +++ b/src/pcm/pcm_null.c @@ -65,7 +65,7 @@ static int snd_pcm_null_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int sig ATTRIBUTE return -ENOSYS; } -static int snd_pcm_null_info(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_info_t * info) +static int snd_pcm_null_info(snd_pcm_t *pcm, snd_pcm_info_t * info) { memset(info, 0, sizeof(*info)); info->stream = pcm->stream; @@ -79,7 +79,6 @@ static int snd_pcm_null_info(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_info_t * i static int snd_pcm_null_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) { - snd_pcm_null_t *null = pcm->private_data; return snd_pcm_channel_info_shm(pcm, info, -1); } diff --git a/src/timer/timer.c b/src/timer/timer.c index 2fc05bc8..6cada821 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -73,6 +73,7 @@ This example shows opening a timer device and reading of timer events. #include #include #include +#include #include #include "timer_local.h" @@ -350,6 +351,27 @@ int snd_timer_nonblock(snd_timer_t *timer, int nonblock) return 0; } +#ifndef DOC_HIDDEN +/** + * \brief set async mode + * \param timer timer handle + * \param sig Signal to raise: < 0 disable, 0 default (SIGIO) + * \param pid Process ID to signal: 0 current + * \return 0 on success otherwise a negative error code + * + * A signal is raised every period. + */ +int snd_timer(snd_timer_t *timer, int sig, pid_t pid) +{ + assert(timer); + if (sig == 0) + sig = SIGIO; + if (pid == 0) + pid = getpid(); + return timer->ops->async(timer, sig, pid); +} +#endif + /** * \brief get size of the snd_timer_info_t structure in bytes * \return size of the snd_timer_info_t structure in bytes diff --git a/src/timer/timer_hw.c b/src/timer/timer_hw.c index 0fc540bd..76651d89 100644 --- a/src/timer/timer_hw.c +++ b/src/timer/timer_hw.c @@ -23,6 +23,7 @@ #include #include #include +#define __USE_GNU #include #include #include "timer_local.h" @@ -61,6 +62,38 @@ static int snd_timer_hw_nonblock(snd_timer_t *timer, int nonblock) return 0; } +static int snd_timer_hw_async(snd_timer_t *timer, int sig, pid_t pid) +{ + long flags; + int fd; + + assert(timer); + fd = timer->poll_fd; + if ((flags = fcntl(fd, F_GETFL)) < 0) { + SYSERR("F_GETFL failed"); + return -errno; + } + if (sig >= 0) + flags |= O_ASYNC; + else + flags &= ~O_ASYNC; + if (fcntl(fd, F_SETFL, flags) < 0) { + SYSERR("F_SETFL for O_ASYNC failed"); + return -errno; + } + if (sig < 0) + return 0; + if (fcntl(fd, F_SETSIG, (long)sig) < 0) { + SYSERR("F_SETSIG failed"); + return -errno; + } + if (fcntl(fd, F_SETOWN, (long)pid) < 0) { + SYSERR("F_SETOWN failed"); + return -errno; + } + return 0; +} + static int snd_timer_hw_info(snd_timer_t *handle, snd_timer_info_t * info) { snd_timer_t *tmr; @@ -148,15 +181,16 @@ static ssize_t snd_timer_hw_read(snd_timer_t *handle, void *buffer, size_t size) } static snd_timer_ops_t snd_timer_hw_ops = { - close: snd_timer_hw_close, - nonblock: snd_timer_hw_nonblock, - info: snd_timer_hw_info, - params: snd_timer_hw_params, - status: snd_timer_hw_status, - rt_start: snd_timer_hw_start, - rt_stop: snd_timer_hw_stop, - rt_continue: snd_timer_hw_continue, - read: snd_timer_hw_read, + .close = snd_timer_hw_close, + .nonblock = snd_timer_hw_nonblock, + .async = snd_timer_hw_async, + .info = snd_timer_hw_info, + .params = snd_timer_hw_params, + .status = snd_timer_hw_status, + .rt_start = snd_timer_hw_start, + .rt_stop = snd_timer_hw_stop, + .rt_continue = snd_timer_hw_continue, + .read = snd_timer_hw_read, }; int snd_timer_hw_open(snd_timer_t **handle, const char *name, int dev_class, int dev_sclass, int card, int device, int subdevice, int mode) diff --git a/src/timer/timer_local.h b/src/timer/timer_local.h index 67aacf1b..8c3ad3d7 100644 --- a/src/timer/timer_local.h +++ b/src/timer/timer_local.h @@ -27,6 +27,7 @@ typedef struct { int (*close)(snd_timer_t *timer); int (*nonblock)(snd_timer_t *timer, int nonblock); + int (*async)(snd_timer_t *timer, int sig, pid_t pid); int (*info)(snd_timer_t *timer, snd_timer_info_t *info); int (*params)(snd_timer_t *timer, snd_timer_params_t *params); int (*status)(snd_timer_t *timer, snd_timer_status_t *status); @@ -62,3 +63,5 @@ struct _snd_timer_query { }; int snd_timer_query_hw_open(snd_timer_query_t **handle, const char *name, int mode); + +int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid); -- 2.47.1