]> git.alsa-project.org Git - alsa-lib.git/commitdiff
added full async interface to timer API
authorJaroslav Kysela <perex@perex.cz>
Wed, 11 May 2005 12:18:51 +0000 (12:18 +0000)
committerJaroslav Kysela <perex@perex.cz>
Wed, 11 May 2005 12:18:51 +0000 (12:18 +0000)
- added snd_async_add_timer_handler and snd_async_handler_get_timer functions
- added async command to test/timer.c

include/local.h
include/timer.h
src/Versions
src/timer/timer.c
src/timer/timer_hw.c
src/timer/timer_local.h
test/timer.c

index 61ec10d8abb4fbd768560b8a7bc42dad435386c2..ee25de2d78bc9905ac1e5dab0bdc7234bbb30c28 100644 (file)
@@ -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;
index 105dee201de8eb983b09869e0404a0047c58a5c9..3420c6e7947700a5b204570caa113cab36388833 100644 (file)
@@ -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);
index 2fe0241aab278ea6758139c649f749881fdb2db5..793025f877bea4906a0b1d381ee5695e7b8067fb 100644 (file)
@@ -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;
index bb6125a2ff18bff3633493efc56e7b26c3f67bde..7bd5838e98f47933895988ba1c91df48af642f6a 100644 (file)
@@ -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
index 2d5a92ee53c94903a3ee141b2c6b3153e21511c7..4f64a616a7dd9c4b0b6d2c5fb14deb6ae12d8ad4 100644 (file)
@@ -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;
 }
index f11bce34b701e97167e2be48e38945b6f27bd8d4..b4f064f325f15cb008bc79d3d55fe49afb578510 100644 (file)
@@ -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);
index 9e745f71ded970a3c142e42bf46a7ad54de16e51..b05eb2f00d15bcce0f40720fc29eff59b551796f 100644 (file)
@@ -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");