3 * \brief Async notification helpers
4 * \author Abramo Bagnara <abramo@alsa-project.org>
8 * Async notification helpers
9 * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
11 * This library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as
13 * published by the Free Software Foundation; either version 2.1 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "pcm/pcm_local.h"
28 #include "control/control_local.h"
31 #ifdef SND_ASYNC_RT_SIGNAL
32 /** async signal number */
33 static int snd_async_signo;
35 void snd_async_init(void) __attribute__ ((constructor));
37 void snd_async_init(void)
39 snd_async_signo = __libc_allocate_rtsig(0);
40 if (snd_async_signo < 0) {
41 SNDERR("Unable to find a RT signal to use for snd_async");
46 /** async signal number */
47 static const int snd_async_signo = SIGIO;
50 static LIST_HEAD(snd_async_handlers);
52 static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, void *context ATTRIBUTE_UNUSED)
56 //assert(siginfo->si_code == SI_SIGIO);
58 list_for_each(i, &snd_async_handlers) {
59 snd_async_handler_t *h = list_entry(i, snd_async_handler_t, glist);
60 if (h->fd == fd && h->callback)
66 * \brief Registers an async handler.
67 * \param handler The function puts the pointer to the new async handler
68 * object at the address specified by \p handler.
69 * \param fd The file descriptor to be associated with the callback.
70 * \param callback The async callback function.
71 * \param private_data Private data for the async callback function.
72 * \result Zero if successful, otherwise a negative error code.
74 * This function associates the callback function with the given file,
75 * and saves this association in a \c snd_async_handler_t object.
77 * Whenever the \c SIGIO signal is raised for the file \p fd, the callback
78 * function will be called with its parameter pointing to the async handler
79 * object returned by this function.
81 * The ALSA \c sigaction handler for the \c SIGIO signal automatically
82 * multiplexes the notifications to the registered async callbacks.
83 * However, the application is responsible for instructing the device driver
84 * to generate the \c SIGIO signal.
86 * The \c SIGIO signal may have been replaced with another signal,
87 * see #snd_async_handler_get_signo.
89 * When the async handler isn't needed anymore, you must delete it with
90 * #snd_async_del_handler.
92 * \see snd_async_add_pcm_handler, snd_async_add_ctl_handler
94 int snd_async_add_handler(snd_async_handler_t **handler, int fd,
95 snd_async_callback_t callback, void *private_data)
97 snd_async_handler_t *h;
100 h = malloc(sizeof(*h));
104 h->callback = callback;
105 h->private_data = private_data;
106 was_empty = list_empty(&snd_async_handlers);
107 list_add_tail(&h->glist, &snd_async_handlers);
108 INIT_LIST_HEAD(&h->hlist);
112 struct sigaction act;
113 memset(&act, 0, sizeof(act));
114 act.sa_flags = SA_RESTART | SA_SIGINFO;
115 act.sa_sigaction = snd_async_handler;
116 sigemptyset(&act.sa_mask);
117 err = sigaction(snd_async_signo, &act, NULL);
127 * \brief Deletes an async handler.
128 * \param handler Handle of the async handler to delete.
129 * \result Zero if successful, otherwise a negative error code.
131 int snd_async_del_handler(snd_async_handler_t *handler)
135 list_del(&handler->glist);
136 if (list_empty(&snd_async_handlers)) {
137 struct sigaction act;
138 memset(&act, 0, sizeof(act));
140 act.sa_handler = SIG_DFL;
141 err = sigaction(snd_async_signo, &act, NULL);
147 if (handler->type == SND_ASYNC_HANDLER_GENERIC)
149 if (!list_empty(&handler->hlist))
150 list_del(&handler->hlist);
151 if (!list_empty(&handler->hlist))
153 switch (handler->type) {
155 case SND_ASYNC_HANDLER_PCM:
156 err = snd_pcm_async(handler->u.pcm, -1, 1);
159 case SND_ASYNC_HANDLER_CTL:
160 err = snd_ctl_async(handler->u.ctl, -1, 1);
171 * \brief Returns the signal number assigned to an async handler.
172 * \param handler Handle to an async handler.
173 * \result The signal number if successful, otherwise a negative error code.
175 * The signal number for async handlers usually is \c SIGIO,
176 * but wizards can redefine it to a realtime signal
177 * when compiling the ALSA library.
179 int snd_async_handler_get_signo(snd_async_handler_t *handler)
182 return snd_async_signo;
186 * \brief Returns the file descriptor assigned to an async handler.
187 * \param handler Handle to an async handler.
188 * \result The file descriptor if successful, otherwise a negative error code.
190 int snd_async_handler_get_fd(snd_async_handler_t *handler)
197 * \brief Returns the private data assigned to an async handler.
198 * \param handler Handle to an async handler.
199 * \result The \c private_data value registered with the async handler.
201 void *snd_async_handler_get_callback_private(snd_async_handler_t *handler)
204 return handler->private_data;