From 8ec3e4ea6cdc57a63bbc91041a73392c0748400c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 11 May 2005 12:18:51 +0000 Subject: [PATCH] added full async interface to timer API - added snd_async_add_timer_handler and snd_async_handler_get_timer functions - added async command to test/timer.c --- include/local.h | 6 +++-- include/timer.h | 3 +++ src/Versions | 3 +++ src/timer/timer.c | 53 +++++++++++++++++++++++++++++++++++++++++ src/timer/timer_hw.c | 1 + src/timer/timer_local.h | 1 + test/timer.c | 35 ++++++++++++++++++++++++++- 7 files changed, 99 insertions(+), 3 deletions(-) diff --git a/include/local.h b/include/local.h index 61ec10d8..ee25de2d 100644 --- a/include/local.h +++ b/include/local.h @@ -129,13 +129,15 @@ typedef struct sndrv_seq_event snd_seq_event_t; struct _snd_async_handler { enum { SND_ASYNC_HANDLER_GENERIC, - SND_ASYNC_HANDLER_PCM, SND_ASYNC_HANDLER_CTL, + SND_ASYNC_HANDLER_PCM, + SND_ASYNC_HANDLER_TIMER, } type; int fd; union { - snd_pcm_t *pcm; snd_ctl_t *ctl; + snd_pcm_t *pcm; + snd_timer_t *timer; } u; snd_async_callback_t callback; void *private_data; diff --git a/include/timer.h b/include/timer.h index 105dee20..3420c6e7 100644 --- a/include/timer.h +++ b/include/timer.h @@ -144,6 +144,9 @@ int snd_timer_query_status(snd_timer_query_t *handle, snd_timer_gstatus_t *statu int snd_timer_open(snd_timer_t **handle, const char *name, int mode); int snd_timer_open_lconf(snd_timer_t **handle, const char *name, int mode, snd_config_t *lconf); int snd_timer_close(snd_timer_t *handle); +int snd_async_add_timer_handler(snd_async_handler_t **handler, snd_timer_t *timer, + snd_async_callback_t callback, void *private_data); +snd_timer_t *snd_async_handler_get_timer(snd_async_handler_t *handler); int snd_timer_poll_descriptors_count(snd_timer_t *handle); int snd_timer_poll_descriptors(snd_timer_t *handle, struct pollfd *pfds, unsigned int space); int snd_timer_poll_descriptors_revents(snd_timer_t *timer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); diff --git a/src/Versions b/src/Versions index 2fe0241a..793025f8 100644 --- a/src/Versions +++ b/src/Versions @@ -197,6 +197,9 @@ ALSA_1.0.9 { snd_pcm_parse_control_id; + snd_async_add_timer_handler; + snd_async_handler_get_timer; + snd_timer_ginfo_sizeof; snd_timer_ginfo_malloc; snd_timer_ginfo_free; diff --git a/src/timer/timer.c b/src/timer/timer.c index bb6125a2..7bd5838e 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -238,6 +238,10 @@ int snd_timer_close(snd_timer_t *timer) { int err; assert(timer); + while (!list_empty(&timer->async_handlers)) { + snd_async_handler_t *h = list_entry(timer->async_handlers.next, snd_async_handler_t, hlist); + snd_async_del_handler(h); + } if ((err = timer->ops->close(timer)) < 0) return err; if (timer->name) @@ -273,6 +277,55 @@ snd_timer_type_t snd_timer_type(snd_timer_t *timer) return timer->type; } +/** + * \brief Add an async handler for a timer + * \param handler Returned handler handle + * \param timer timer handle + * \param callback Callback function + * \param private_data Callback private data + * \return 0 otherwise a negative error code on failure + * + * The asynchronous callback is called when new timer event occurs. + */ +int snd_async_add_timer_handler(snd_async_handler_t **handler, snd_timer_t *timer, + snd_async_callback_t callback, void *private_data) +{ + int err; + int was_empty; + snd_async_handler_t *h; + err = snd_async_add_handler(&h, timer->poll_fd, + callback, private_data); + if (err < 0) + return err; + h->type = SND_ASYNC_HANDLER_TIMER; + h->u.timer = timer; + was_empty = list_empty(&timer->async_handlers); + list_add_tail(&h->hlist, &timer->async_handlers); + if (was_empty) { + err = snd_timer_async(timer, snd_async_handler_get_signo(h), getpid()); + if (err < 0) { + snd_async_del_handler(h); + return err; + } + } + *handler = h; + return 0; +} + +/** + * \brief Return timer handle related to an async handler + * \param handler Async handler handle + * \return timer handle + */ +snd_timer_t *snd_async_handler_get_timer(snd_async_handler_t *handler) +{ + if (handler->type != SND_ASYNC_HANDLER_TIMER) { + SNDMSG("invalid handler type %d", handler->type); + return NULL; + } + return handler->u.timer; +} + /** * \brief get count of poll descriptors for timer handle * \param timer timer handle diff --git a/src/timer/timer_hw.c b/src/timer/timer_hw.c index 2d5a92ee..4f64a616 100644 --- a/src/timer/timer_hw.c +++ b/src/timer/timer_hw.c @@ -265,6 +265,7 @@ int snd_timer_hw_open(snd_timer_t **handle, const char *name, int dev_class, int tmr->name = strdup(name); tmr->poll_fd = fd; tmr->ops = &snd_timer_hw_ops; + INIT_LIST_HEAD(&tmr->async_handlers); *handle = tmr; return 0; } diff --git a/src/timer/timer_local.h b/src/timer/timer_local.h index f11bce34..b4f064f3 100644 --- a/src/timer/timer_local.h +++ b/src/timer/timer_local.h @@ -45,6 +45,7 @@ struct _snd_timer { int poll_fd; snd_timer_ops_t *ops; void *private_data; + struct list_head async_handlers; }; 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/test/timer.c b/test/timer.c index 9e745f71..b05eb2f0 100644 --- a/test/timer.c +++ b/test/timer.c @@ -54,6 +54,19 @@ void read_loop(void *handle, int master_ticks, int timeout) free(fds); } +static void async_callback(snd_async_handler_t *ahandler) +{ + snd_timer_t *handle = snd_async_handler_get_timer(ahandler); + int *acount = snd_async_handler_get_callback_private(ahandler); + snd_timer_read_t tr; + + while (snd_timer_read(handle, &tr, sizeof(tr)) == sizeof(tr)) { + printf("TIMER: resolution = %uns, ticks = %u\n", + tr.resolution, tr.ticks); + } + (*acount)++; +} + int main(int argc, char *argv[]) { int idx, err; @@ -63,11 +76,14 @@ int main(int argc, char *argv[]) int device = SND_TIMER_GLOBAL_SYSTEM; int subdevice = 0; int list = 0; + int async = 0; + int acount = 0; snd_timer_t *handle; snd_timer_id_t *id; snd_timer_info_t *info; snd_timer_params_t *params; char timername[64]; + snd_async_handler_t *ahandler; snd_timer_id_alloca(&id); snd_timer_info_alloca(&info); @@ -87,6 +103,8 @@ int main(int argc, char *argv[]) subdevice = atoi(argv[idx]+10); } else if (!strcmp(argv[idx], "list")) { list = 1; + } else if (!strcmp(argv[idx], "async")) { + async = 1; } idx++; } @@ -148,11 +166,26 @@ int main(int argc, char *argv[]) exit(0); } show_status(handle); + if (async) { + err = snd_async_add_timer_handler(&ahandler, handle, async_callback, &acount); + if (err < 0) { + fprintf(stderr, "unable to add async handler %i (%s)\n", err, snd_strerror(err)); + exit(EXIT_FAILURE); + } + } if ((err = snd_timer_start(handle)) < 0) { fprintf(stderr, "timer start %i (%s)\n", err, snd_strerror(err)); exit(EXIT_FAILURE); } - read_loop(handle, 25, snd_timer_info_is_slave(info) ? 10000 : 25); + if (async) { + /* because all other work is done in the signal handler, + suspend the process */ + while (acount < 25) + sleep(1); + snd_timer_stop(handle); + } else { + read_loop(handle, 25, snd_timer_info_is_slave(info) ? 10000 : 25); + } show_status(handle); snd_timer_close(handle); printf("Done\n"); -- 2.47.1