3 * \brief Timer Interface
4 * \author Jaroslav Kysela <perex@perex.cz>
7 * Timer Interface is designed to access timers.
8 * See \ref timer page for more details.
11 * Timer Interface - main file
12 * Copyright (c) 1998-2001 by Jaroslav Kysela <perex@perex.cz>
15 * This library is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as
17 * published by the Free Software Foundation; either version 2.1 of
18 * the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 /*! \page timer Timer interface
33 <P> Timer interface is designed to use internal timers in sound hardware, but
34 it can be driven with any timer.
36 \section timer_general_overview General overview
38 The timer implementation uses ring buffer to store information about timing
39 events. In this buffer is recorded count of ticks and current tick resolution
42 \section timer_open Opening
44 Timer devices can be opened in two ways. When #SND_TIMER_OPEN_NONBLOCK flag
45 is used, then the open functions return immediately with -EBUSY error code when
46 resources are occupied with another application. When #SND_TIMER_OPEN_NONBLOCK
47 is not used (by default) the open functions block the application requesting
48 device until resources are not free.
50 \section timer_events Events
52 Events are read via snd_timer_read() function.
54 \section timer_examples Examples
56 The full featured examples with cross-links:
58 \par Simple timer test program
59 \ref example_test_timer "example code"
61 This example shows opening a timer device and reading of timer events.
66 * \example ../test/timer.c
67 * \anchor example_test_timer
76 #include <sys/ioctl.h>
77 #include "timer_local.h"
79 static int snd_timer_open_conf(snd_timer_t **timer,
80 const char *name, snd_config_t *timer_root,
81 snd_config_t *timer_conf, int mode)
86 snd_config_t *conf, *type_conf = NULL;
87 snd_config_iterator_t i, next;
89 const char *lib = NULL, *open_name = NULL;
90 int (*open_func)(snd_timer_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
92 extern void *snd_timer_open_symbols(void);
95 if (snd_config_get_type(timer_conf) != SND_CONFIG_TYPE_COMPOUND) {
97 SNDERR("Invalid type for TIMER %s definition", name);
99 SNDERR("Invalid type for TIMER definition");
102 err = snd_config_search(timer_conf, "type", &conf);
104 SNDERR("type is not defined");
107 err = snd_config_get_id(conf, &id);
109 SNDERR("unable to get id");
112 err = snd_config_get_string(conf, &str);
114 SNDERR("Invalid type for %s", id);
117 err = snd_config_search_definition(timer_root, "timer_type", str, &type_conf);
119 if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
120 SNDERR("Invalid type for TIMER type %s definition", str);
123 snd_config_for_each(i, next, type_conf) {
124 snd_config_t *n = snd_config_iterator_entry(i);
126 if (snd_config_get_id(n, &id) < 0)
128 if (strcmp(id, "comment") == 0)
130 if (strcmp(id, "lib") == 0) {
131 err = snd_config_get_string(n, &lib);
133 SNDERR("Invalid type for %s", id);
138 if (strcmp(id, "open") == 0) {
139 err = snd_config_get_string(n, &open_name);
141 SNDERR("Invalid type for %s", id);
146 SNDERR("Unknown field %s", id);
153 snprintf(buf, sizeof(buf), "_snd_timer_%s_open", str);
156 snd_timer_open_symbols();
158 h = snd_dlopen(lib, RTLD_NOW);
160 open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_DLSYM_VERSION));
163 SNDERR("Cannot open shared library %s", lib);
165 } else if (!open_func) {
166 SNDERR("symbol %s is not defined inside %s", open_name, lib);
172 snd_config_delete(type_conf);
174 err = open_func(timer, name, timer_root, timer_conf, mode);
178 (*timer)->dl_handle = h;
183 static int snd_timer_open_noupdate(snd_timer_t **timer, snd_config_t *root, const char *name, int mode)
186 snd_config_t *timer_conf;
187 err = snd_config_search_definition(root, "timer", name, &timer_conf);
189 SNDERR("Unknown timer %s", name);
192 err = snd_timer_open_conf(timer, name, root, timer_conf, mode);
193 snd_config_delete(timer_conf);
198 * \brief Opens a new connection to the timer interface.
199 * \param timer Returned handle (NULL if not wanted)
200 * \param name ASCII identifier of the timer handle
201 * \param mode Open mode
202 * \return 0 on success otherwise a negative error code
204 * Opens a new connection to the timer interface specified with
205 * an ASCII identifier and mode.
207 int snd_timer_open(snd_timer_t **timer, const char *name, int mode)
210 assert(timer && name);
211 err = snd_config_update();
214 return snd_timer_open_noupdate(timer, snd_config, name, mode);
218 * \brief Opens a new connection to the timer interface using local configuration
219 * \param timer Returned handle (NULL if not wanted)
220 * \param name ASCII identifier of the timer handle
221 * \param mode Open mode
222 * \param lconf Local configuration
223 * \return 0 on success otherwise a negative error code
225 * Opens a new connection to the timer interface specified with
226 * an ASCII identifier and mode.
228 int snd_timer_open_lconf(snd_timer_t **timer, const char *name,
229 int mode, snd_config_t *lconf)
231 assert(timer && name && lconf);
232 return snd_timer_open_noupdate(timer, lconf, name, mode);
236 * \brief close timer handle
237 * \param timer timer handle
238 * \return 0 on success otherwise a negative error code
240 * Closes the specified timer handle and frees all associated
243 int snd_timer_close(snd_timer_t *timer)
247 while (!list_empty(&timer->async_handlers)) {
248 snd_async_handler_t *h = list_entry(timer->async_handlers.next, snd_async_handler_t, hlist);
249 snd_async_del_handler(h);
251 err = timer->ops->close(timer);
252 if (timer->dl_handle)
253 snd_dlclose(timer->dl_handle);
260 * \brief get identifier of timer handle
261 * \param timer a timer handle
262 * \return ascii identifier of timer handle
264 * Returns the ASCII identifier of given timer handle. It's the same
265 * identifier specified in snd_timer_open().
267 const char *snd_timer_name(snd_timer_t *timer)
274 * \brief get type of timer handle
275 * \param timer a timer handle
276 * \return type of timer handle
278 * Returns the type #snd_timer_type_t of given timer handle.
280 snd_timer_type_t snd_timer_type(snd_timer_t *timer)
287 * \brief Add an async handler for a timer
288 * \param handler Returned handler handle
289 * \param timer timer handle
290 * \param callback Callback function
291 * \param private_data Callback private data
292 * \return 0 otherwise a negative error code on failure
294 * The asynchronous callback is called when new timer event occurs.
296 int snd_async_add_timer_handler(snd_async_handler_t **handler, snd_timer_t *timer,
297 snd_async_callback_t callback, void *private_data)
301 snd_async_handler_t *h;
302 err = snd_async_add_handler(&h, timer->poll_fd,
303 callback, private_data);
306 h->type = SND_ASYNC_HANDLER_TIMER;
308 was_empty = list_empty(&timer->async_handlers);
309 list_add_tail(&h->hlist, &timer->async_handlers);
311 err = snd_timer_async(timer, snd_async_handler_get_signo(h), getpid());
313 snd_async_del_handler(h);
322 * \brief Return timer handle related to an async handler
323 * \param handler Async handler handle
324 * \return timer handle
326 snd_timer_t *snd_async_handler_get_timer(snd_async_handler_t *handler)
328 if (handler->type != SND_ASYNC_HANDLER_TIMER) {
329 SNDMSG("invalid handler type %d", handler->type);
332 return handler->u.timer;
336 * \brief get count of poll descriptors for timer handle
337 * \param timer timer handle
338 * \return count of poll descriptors
340 int snd_timer_poll_descriptors_count(snd_timer_t *timer)
347 * \brief get poll descriptors
348 * \param timer timer handle
349 * \param pfds array of poll descriptors
350 * \param space space in the poll descriptor array
351 * \return count of filled descriptors
353 int snd_timer_poll_descriptors(snd_timer_t *timer, struct pollfd *pfds, unsigned int space)
357 pfds->fd = timer->poll_fd;
358 switch (timer->mode & O_ACCMODE) {
360 pfds->events = POLLOUT|POLLERR|POLLNVAL;
363 pfds->events = POLLIN|POLLERR|POLLNVAL;
366 pfds->events = POLLOUT|POLLIN|POLLERR|POLLNVAL;
377 * \brief get returned events from poll descriptors
378 * \param timer timer handle
379 * \param pfds array of poll descriptors
380 * \param nfds count of poll descriptors
381 * \param revents returned events
382 * \return zero if success, otherwise a negative error code
384 int snd_timer_poll_descriptors_revents(snd_timer_t *timer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
386 assert(timer && pfds && revents);
388 *revents = pfds->revents;
395 * \brief set nonblock mode
396 * \param timer timer handle
397 * \param nonblock 0 = block, 1 = nonblock mode
398 * \return 0 on success otherwise a negative error code
400 int snd_timer_nonblock(snd_timer_t *timer, int nonblock)
404 if ((err = timer->ops->nonblock(timer, nonblock)) < 0)
407 timer->mode |= SND_TIMER_OPEN_NONBLOCK;
409 timer->mode &= ~SND_TIMER_OPEN_NONBLOCK;
415 * \brief set async mode
416 * \param timer timer handle
417 * \param sig Signal to raise: < 0 disable, 0 default (SIGIO)
418 * \param pid Process ID to signal: 0 current
419 * \return 0 on success otherwise a negative error code
421 * A signal is raised every period.
423 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid)
430 return timer->ops->async(timer, sig, pid);
435 * \brief get size of the snd_timer_info_t structure in bytes
436 * \return size of the snd_timer_info_t structure in bytes
438 size_t snd_timer_info_sizeof()
440 return sizeof(snd_timer_info_t);
444 * \brief allocate a new snd_timer_info_t structure
445 * \param info returned pointer
446 * \return 0 on success otherwise a negative error code if fails
448 * Allocates a new snd_timer_info_t structure using the standard
449 * malloc C library function.
451 int snd_timer_info_malloc(snd_timer_info_t **info)
454 *info = calloc(1, sizeof(snd_timer_info_t));
461 * \brief frees the snd_timer_info_t structure
462 * \param info pointer to the snd_timer_info_t structure to free
464 * Frees the given snd_timer_info_t structure using the standard
465 * free C library function.
467 void snd_timer_info_free(snd_timer_info_t *info)
474 * \brief copy one snd_timer_info_t structure to another
475 * \param dst destination snd_timer_info_t structure
476 * \param src source snd_timer_info_t structure
478 void snd_timer_info_copy(snd_timer_info_t *dst, const snd_timer_info_t *src)
485 * \brief determine, if timer is slave
486 * \param info pointer to #snd_timer_info_t structure
487 * \return nonzero if timer is slave
489 int snd_timer_info_is_slave(snd_timer_info_t * info)
492 return info->flags & SNDRV_TIMER_FLG_SLAVE ? 1 : 0;
496 * \brief get timer card
497 * \param info pointer to #snd_timer_info_t structure
498 * \return timer card number
500 int snd_timer_info_get_card(snd_timer_info_t * info)
507 * \brief get timer id
508 * \param info pointer to #snd_timer_info_t structure
511 const char *snd_timer_info_get_id(snd_timer_info_t * info)
514 return (const char *)info->id;
518 * \brief get timer name
519 * \param info pointer to #snd_timer_info_t structure
522 const char *snd_timer_info_get_name(snd_timer_info_t * info)
525 return (const char *)info->name;
530 * \brief get timer resolution in us
531 * \param info pointer to #snd_timer_info_t structure
532 * \return timer resolution
534 long snd_timer_info_get_resolution(snd_timer_info_t * info)
537 return info->resolution;
541 * \brief get information about timer handle
542 * \param timer timer handle
543 * \param info pointer to a snd_timer_info_t structure to be filled
544 * \return 0 on success otherwise a negative error code
546 int snd_timer_info(snd_timer_t *timer, snd_timer_info_t * info)
550 return timer->ops->info(timer, info);
554 * \brief get size of the snd_timer_params_t structure in bytes
555 * \return size of the snd_timer_params_t structure in bytes
557 size_t snd_timer_params_sizeof()
559 return sizeof(snd_timer_params_t);
563 * \brief allocate a new snd_timer_params_t structure
564 * \param params returned pointer
565 * \return 0 on success otherwise a negative error code if fails
567 * Allocates a new snd_timer_params_t structure using the standard
568 * malloc C library function.
570 int snd_timer_params_malloc(snd_timer_params_t **params)
573 *params = calloc(1, sizeof(snd_timer_params_t));
580 * \brief frees the snd_timer_params_t structure
581 * \param params pointer to the snd_timer_params_t structure to free
583 * Frees the given snd_timer_params_t structure using the standard
584 * free C library function.
586 void snd_timer_params_free(snd_timer_params_t *params)
593 * \brief copy one snd_timer_params_t structure to another
594 * \param dst destination snd_timer_params_t structure
595 * \param src source snd_timer_params_t structure
597 void snd_timer_params_copy(snd_timer_params_t *dst, const snd_timer_params_t *src)
604 * \brief set timer auto start
605 * \param params pointer to #snd_timer_params_t structure
606 * \param auto_start The boolean value to set
608 int snd_timer_params_set_auto_start(snd_timer_params_t * params, int auto_start)
612 params->flags |= SNDRV_TIMER_PSFLG_AUTO;
614 params->flags &= ~SNDRV_TIMER_PSFLG_AUTO;
619 * \brief determine if timer has auto start flag
620 * \param params pointer to #snd_timer_params_t structure
621 * \return nonzero if timer has auto start flag
623 int snd_timer_params_get_auto_start(snd_timer_params_t * params)
626 return params->flags & SNDRV_TIMER_PSFLG_AUTO ? 1 : 0;
630 * \brief set timer exclusive use
631 * \param params pointer to #snd_timer_params_t structure
632 * \param exclusive The boolean value to set
635 int INTERNAL(snd_timer_params_set_exclusive)(snd_timer_params_t * params, int exclusive)
637 int snd_timer_params_set_exclusive(snd_timer_params_t * params, int exclusive)
642 params->flags |= SNDRV_TIMER_PSFLG_EXCLUSIVE;
644 params->flags &= ~SNDRV_TIMER_PSFLG_EXCLUSIVE;
647 use_default_symbol_version(__snd_timer_params_set_exclusive, snd_timer_params_set_exclusive, ALSA_0.9.0);
650 * \brief determine if timer has exclusive flag
651 * \param params pointer to #snd_timer_params_t structure
652 * \return nonzero if timer has exclusive flag
655 int INTERNAL(snd_timer_params_get_exclusive)(snd_timer_params_t * params)
657 int snd_timer_params_get_exclusive(snd_timer_params_t * params)
661 return params->flags & SNDRV_TIMER_PSFLG_EXCLUSIVE ? 1 : 0;
663 use_default_symbol_version(__snd_timer_params_get_exclusive, snd_timer_params_get_exclusive, ALSA_0.9.0);
666 * \brief set timer early event
667 * \param params pointer to #snd_timer_params_t structure
668 * \param early_event The boolean value to set
670 int snd_timer_params_set_early_event(snd_timer_params_t * params, int early_event)
674 params->flags |= SNDRV_TIMER_PSFLG_EARLY_EVENT;
676 params->flags &= ~SNDRV_TIMER_PSFLG_EARLY_EVENT;
681 * \brief determine if timer has early event flag
682 * \param params pointer to #snd_timer_params_t structure
683 * \return nonzero if timer has early event flag set
685 int snd_timer_params_get_early_event(snd_timer_params_t * params)
688 return params->flags & SNDRV_TIMER_PSFLG_EARLY_EVENT ? 1 : 0;
692 * \brief set timer ticks
693 * \param params pointer to #snd_timer_params_t structure
694 * \param ticks Ticks to set
696 void snd_timer_params_set_ticks(snd_timer_params_t * params, long ticks)
699 params->ticks = ticks;
703 * \brief get timer ticks
704 * \param params pointer to #snd_timer_params_t structure
705 * \return timer ticks
707 long snd_timer_params_get_ticks(snd_timer_params_t * params)
710 return params->ticks;
714 * \brief set timer queue size (32-1024)
715 * \param params pointer to #snd_timer_params_t structure
716 * \param queue_size The queue size to set
718 void snd_timer_params_set_queue_size(snd_timer_params_t * params, long queue_size)
721 params->queue_size = queue_size;
725 * \brief get queue size
726 * \param params pointer to #snd_timer_params_t structure
729 long snd_timer_params_get_queue_size(snd_timer_params_t * params)
732 return params->queue_size;
736 * \brief set timer event filter
737 * \param params pointer to #snd_timer_params_t structure
738 * \param filter The event filter bits to set
741 void INTERNAL(snd_timer_params_set_filter)(snd_timer_params_t * params, unsigned int filter)
743 void snd_timer_params_set_filter(snd_timer_params_t * params, unsigned int filter)
747 params->filter = filter;
749 use_default_symbol_version(__snd_timer_params_set_filter, snd_timer_params_set_filter, ALSA_0.9.0);
752 * \brief get timer event filter
753 * \param params pointer to #snd_timer_params_t structure
754 * \return timer event filter
757 unsigned int INTERNAL(snd_timer_params_get_filter)(snd_timer_params_t * params)
759 unsigned int snd_timer_params_get_filter(snd_timer_params_t * params)
763 return params->filter;
765 use_default_symbol_version(__snd_timer_params_get_filter, snd_timer_params_get_filter, ALSA_0.9.0);
768 * \brief set parameters for timer handle
769 * \param timer timer handle
770 * \param params pointer to a #snd_timer_params_t structure
771 * \return 0 on success otherwise a negative error code
773 int snd_timer_params(snd_timer_t *timer, snd_timer_params_t * params)
777 return timer->ops->params(timer, params);
781 * \brief get size of the snd_timer_status_t structure in bytes
782 * \return size of the snd_timer_status_t structure in bytes
784 size_t snd_timer_status_sizeof()
786 return sizeof(snd_timer_status_t);
790 * \brief allocate a new snd_timer_status_t structure
791 * \param status returned pointer
792 * \return 0 on success otherwise a negative error code if fails
794 * Allocates a new snd_timer_status_t structure using the standard
795 * malloc C library function.
797 int snd_timer_status_malloc(snd_timer_status_t **status)
800 *status = calloc(1, sizeof(snd_timer_status_t));
807 * \brief frees the snd_timer_status_t structure
808 * \param status pointer to the snd_timer_status_t structure to free
810 * Frees the given snd_timer_status_t structure using the standard
811 * free C library function.
813 void snd_timer_status_free(snd_timer_status_t *status)
820 * \brief copy one snd_timer_status_t structure to another
821 * \param dst destination snd_timer_status_t structure
822 * \param src source snd_timer_status_t structure
824 void snd_timer_status_copy(snd_timer_status_t *dst, const snd_timer_status_t *src)
833 * \brief get timestamp
834 * \param status pointer to #snd_timer_status_t structure
837 snd_htimestamp_t snd_timer_status_get_timestamp(snd_timer_status_t * status)
840 return status->tstamp;
844 * \brief get resolution in us
845 * \param status pointer to #snd_timer_status_t structure
848 long snd_timer_status_get_resolution(snd_timer_status_t * status)
851 return status->resolution;
855 * \brief get master tick lost count
856 * \param status pointer to #snd_timer_status_t structure
857 * \return master tick lost count
859 long snd_timer_status_get_lost(snd_timer_status_t * status)
866 * \brief get overrun count
867 * \param status pointer to #snd_timer_status_t structure
868 * \return overrun count
870 long snd_timer_status_get_overrun(snd_timer_status_t * status)
873 return status->overrun;
877 * \brief get count of used queue elements
878 * \param status pointer to #snd_timer_status_t structure
879 * \return count of used queue elements
881 long snd_timer_status_get_queue(snd_timer_status_t * status)
884 return status->queue;
888 * \brief get status from timer handle
889 * \param timer timer handle
890 * \param status pointer to a #snd_timer_status_t structure to be filled
891 * \return 0 on success otherwise a negative error code
893 int snd_timer_status(snd_timer_t *timer, snd_timer_status_t * status)
897 return timer->ops->status(timer, status);
901 * \brief start the timer
902 * \param timer timer handle
903 * \return 0 on success otherwise a negative error code
905 int snd_timer_start(snd_timer_t *timer)
908 return timer->ops->rt_start(timer);
912 * \brief stop the timer
913 * \param timer timer handle
914 * \return 0 on success otherwise a negative error code
916 int snd_timer_stop(snd_timer_t *timer)
919 return timer->ops->rt_stop(timer);
923 * \brief continue the timer
924 * \param timer timer handle
925 * \return 0 on success otherwise a negative error code
927 int snd_timer_continue(snd_timer_t *timer)
930 return timer->ops->rt_continue(timer);
934 * \brief read bytes using timer handle
935 * \param timer timer handle
936 * \param buffer buffer to store the input bytes
937 * \param size input buffer size in bytes
939 ssize_t snd_timer_read(snd_timer_t *timer, void *buffer, size_t size)
942 assert(((timer->mode & O_ACCMODE) == O_RDONLY) || ((timer->mode & O_ACCMODE) == O_RDWR));
943 assert(buffer || size == 0);
944 return (timer->ops->read)(timer, buffer, size);
948 * \brief (DEPRECATED) get maximum timer ticks
949 * \param info pointer to #snd_timer_info_t structure
950 * \return maximum timer ticks
952 long snd_timer_info_get_ticks(snd_timer_info_t * info)
958 link_warning(snd_timer_info_get_ticks, "Warning: snd_timer_info_get_ticks is deprecated");