mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-12-16 08:56:42 -05:00
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
This commit is contained in:
parent
a022bc1fbc
commit
8ec3e4ea6c
7 changed files with 99 additions and 3 deletions
|
|
@ -129,13 +129,15 @@ typedef struct sndrv_seq_event snd_seq_event_t;
|
||||||
struct _snd_async_handler {
|
struct _snd_async_handler {
|
||||||
enum {
|
enum {
|
||||||
SND_ASYNC_HANDLER_GENERIC,
|
SND_ASYNC_HANDLER_GENERIC,
|
||||||
SND_ASYNC_HANDLER_PCM,
|
|
||||||
SND_ASYNC_HANDLER_CTL,
|
SND_ASYNC_HANDLER_CTL,
|
||||||
|
SND_ASYNC_HANDLER_PCM,
|
||||||
|
SND_ASYNC_HANDLER_TIMER,
|
||||||
} type;
|
} type;
|
||||||
int fd;
|
int fd;
|
||||||
union {
|
union {
|
||||||
snd_pcm_t *pcm;
|
|
||||||
snd_ctl_t *ctl;
|
snd_ctl_t *ctl;
|
||||||
|
snd_pcm_t *pcm;
|
||||||
|
snd_timer_t *timer;
|
||||||
} u;
|
} u;
|
||||||
snd_async_callback_t callback;
|
snd_async_callback_t callback;
|
||||||
void *private_data;
|
void *private_data;
|
||||||
|
|
|
||||||
|
|
@ -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(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_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_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_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(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);
|
int snd_timer_poll_descriptors_revents(snd_timer_t *timer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,9 @@ ALSA_1.0.9 {
|
||||||
|
|
||||||
snd_pcm_parse_control_id;
|
snd_pcm_parse_control_id;
|
||||||
|
|
||||||
|
snd_async_add_timer_handler;
|
||||||
|
snd_async_handler_get_timer;
|
||||||
|
|
||||||
snd_timer_ginfo_sizeof;
|
snd_timer_ginfo_sizeof;
|
||||||
snd_timer_ginfo_malloc;
|
snd_timer_ginfo_malloc;
|
||||||
snd_timer_ginfo_free;
|
snd_timer_ginfo_free;
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,10 @@ int snd_timer_close(snd_timer_t *timer)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
assert(timer);
|
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)
|
if ((err = timer->ops->close(timer)) < 0)
|
||||||
return err;
|
return err;
|
||||||
if (timer->name)
|
if (timer->name)
|
||||||
|
|
@ -273,6 +277,55 @@ snd_timer_type_t snd_timer_type(snd_timer_t *timer)
|
||||||
return timer->type;
|
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
|
* \brief get count of poll descriptors for timer handle
|
||||||
* \param timer timer handle
|
* \param timer timer handle
|
||||||
|
|
|
||||||
|
|
@ -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->name = strdup(name);
|
||||||
tmr->poll_fd = fd;
|
tmr->poll_fd = fd;
|
||||||
tmr->ops = &snd_timer_hw_ops;
|
tmr->ops = &snd_timer_hw_ops;
|
||||||
|
INIT_LIST_HEAD(&tmr->async_handlers);
|
||||||
*handle = tmr;
|
*handle = tmr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ struct _snd_timer {
|
||||||
int poll_fd;
|
int poll_fd;
|
||||||
snd_timer_ops_t *ops;
|
snd_timer_ops_t *ops;
|
||||||
void *private_data;
|
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);
|
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);
|
||||||
|
|
|
||||||
35
test/timer.c
35
test/timer.c
|
|
@ -54,6 +54,19 @@ void read_loop(void *handle, int master_ticks, int timeout)
|
||||||
free(fds);
|
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 main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int idx, err;
|
int idx, err;
|
||||||
|
|
@ -63,11 +76,14 @@ int main(int argc, char *argv[])
|
||||||
int device = SND_TIMER_GLOBAL_SYSTEM;
|
int device = SND_TIMER_GLOBAL_SYSTEM;
|
||||||
int subdevice = 0;
|
int subdevice = 0;
|
||||||
int list = 0;
|
int list = 0;
|
||||||
|
int async = 0;
|
||||||
|
int acount = 0;
|
||||||
snd_timer_t *handle;
|
snd_timer_t *handle;
|
||||||
snd_timer_id_t *id;
|
snd_timer_id_t *id;
|
||||||
snd_timer_info_t *info;
|
snd_timer_info_t *info;
|
||||||
snd_timer_params_t *params;
|
snd_timer_params_t *params;
|
||||||
char timername[64];
|
char timername[64];
|
||||||
|
snd_async_handler_t *ahandler;
|
||||||
|
|
||||||
snd_timer_id_alloca(&id);
|
snd_timer_id_alloca(&id);
|
||||||
snd_timer_info_alloca(&info);
|
snd_timer_info_alloca(&info);
|
||||||
|
|
@ -87,6 +103,8 @@ int main(int argc, char *argv[])
|
||||||
subdevice = atoi(argv[idx]+10);
|
subdevice = atoi(argv[idx]+10);
|
||||||
} else if (!strcmp(argv[idx], "list")) {
|
} else if (!strcmp(argv[idx], "list")) {
|
||||||
list = 1;
|
list = 1;
|
||||||
|
} else if (!strcmp(argv[idx], "async")) {
|
||||||
|
async = 1;
|
||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
@ -148,11 +166,26 @@ int main(int argc, char *argv[])
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
show_status(handle);
|
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) {
|
if ((err = snd_timer_start(handle)) < 0) {
|
||||||
fprintf(stderr, "timer start %i (%s)\n", err, snd_strerror(err));
|
fprintf(stderr, "timer start %i (%s)\n", err, snd_strerror(err));
|
||||||
exit(EXIT_FAILURE);
|
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);
|
show_status(handle);
|
||||||
snd_timer_close(handle);
|
snd_timer_close(handle);
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue