diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-07-05 16:14:44 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2007-07-05 16:14:44 +0200 |
commit | 13585db857b220173875baffae1f4847e3e484bb (patch) | |
tree | ae60c2313a593702f65d6c9bb4072ffb2d71b03c | |
parent | 6f5ad82ce51190e9782077343346a1d7641848e3 (diff) | |
download | salsa-lib-13585db857b220173875baffae1f4847e3e484bb.tar.gz |
Add async handler support
-rw-r--r-- | configure.ac | 19 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/async.c | 135 | ||||
-rw-r--r-- | src/control.c | 27 | ||||
-rw-r--r-- | src/control.h | 6 | ||||
-rw-r--r-- | src/ctl_macros.h | 15 | ||||
-rw-r--r-- | src/global.h | 56 | ||||
-rw-r--r-- | src/pcm.c | 26 | ||||
-rw-r--r-- | src/pcm.h | 6 | ||||
-rw-r--r-- | src/pcm_macros.h | 15 | ||||
-rw-r--r-- | src/recipe.h.in | 3 |
11 files changed, 301 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac index d86b42b..40f8891 100644 --- a/configure.ac +++ b/configure.ac @@ -37,6 +37,10 @@ AC_SUBST(SND_LIB_EXTRAVER) dnl Component selections +AC_ARG_ENABLE(pcm, + AS_HELP_STRING([--disable-pcm], + [disable PCM interface]), + pcm="$enableval", pcm="yes") AC_ARG_ENABLE(mixer, AS_HELP_STRING([--disable-mixer], [disable mixer interface]), @@ -66,6 +70,10 @@ AC_ARG_ENABLE(tlv, AS_HELP_STRING([--enable-tlv], [enable TLV (dB) support]), tlv="$enableval", tlv="no") +AC_ARG_ENABLE(async, + AS_HELP_STRING([--enable-async], + [enable async handler support]), + async="$enableval", async="yes") AC_ARG_ENABLE(libasound, AS_HELP_STRING([--enable-libasound], @@ -78,6 +86,7 @@ AC_ARG_ENABLE(everything, everything="$enableval", everything="no") if test "$everything" = "yes"; then + pcm="yes" mixer="yes" rawmidi="yes" hwdep="yes" @@ -85,15 +94,18 @@ if test "$everything" = "yes"; then sndconf="yes" sndseq="yes" tlv="yes" + async="yes" libasound="yes" fi +AM_CONDITIONAL(BUILD_PCM, test "$pcm" = "yes") AM_CONDITIONAL(BUILD_MIXER, test "$mixer" = "yes") AM_CONDITIONAL(BUILD_RAWMIDI, test "$rawmidi" = "yes") AM_CONDITIONAL(BUILD_HWDEP, test "$hwdep" = "yes") AM_CONDITIONAL(BUILD_TIMER, test "$timer" = "yes") AM_CONDITIONAL(BUILD_CONF, test "$sndconf" = "yes") AM_CONDITIONAL(BUILD_SEQ, test "$sndseq" = "yes") +AM_CONDITIONAL(BUILD_ASYNC, test "$async" = "yes") if test "$tlv" = "yes"; then SALSA_HAS_TLV_SUPPORT=1 @@ -102,6 +114,13 @@ else fi AC_SUBST(SALSA_HAS_TLV_SUPPORT) +if test "$async" = "yes"; then + SALSA_HAS_ASYNC_SUPPORT=1 +else + SALSA_HAS_ASYNC_SUPPORT=0 +fi +AC_SUBST(SALSA_HAS_ASYNC_SUPPORT) + AM_CONDITIONAL(LINK_LIBASOUND, test "$libasound" = "yes") dnl OK, let's output... diff --git a/src/Makefile.am b/src/Makefile.am index 9592aa3..6b4ec1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,8 +1,13 @@ AM_CFLAGS = -Wall -g lib_LTLIBRARIES = libsalsa.la -libsalsa_la_SOURCES = control.c cards.c \ - pcm.c pcm_params.c pcm_misc.c +libsalsa_la_SOURCES = control.c cards.c +if BUILD_PCM +libsalsa_la_SOURCES += pcm.c pcm_params.c pcm_misc.c +endif +if BUILD_ASYNC +libsalsa_la_SOURCES += async.c +endif if BUILD_MIXER libsalsa_la_SOURCES += hcontrol.c mixer.c endif diff --git a/src/async.c b/src/async.c new file mode 100644 index 0000000..28a82b9 --- /dev/null +++ b/src/async.c @@ -0,0 +1,135 @@ +/* + * SALSA-Lib - Async handler helpers + * + * Copyright (c) 2007 by Takashi Iwai <tiwai@suse.de> + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#define __USE_GNU +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <sys/ioctl.h> +#include "recipe.h" +#include "global.h" + + +static snd_async_handler_t *async_list; + +static int snd_set_async(snd_async_handler_t *h, int sig) +{ + long flags; + int err; + + flags = fcntl(h->fd, F_GETFL); + if (flags < 0) + return -errno; + if (sig >= 0) + flags |= O_ASYNC; + else + flags &= ~O_ASYNC; + if (fcntl(h->fd, F_SETFL, flags) < 0) + return -errno; + if (sig >= 0) { + if (fcntl(h->fd, F_SETSIG, (long)sig) < 0 || + fcntl(h->fd, F_SETOWN, (long)getpid()) < 0) { + err = -errno; + fcntl(h->fd, F_SETFL, flags & ~O_ASYNC); + return err; + } + } + return 0; +} + +static void snd_async_handler(int signo, siginfo_t *siginfo, void *context) +{ + snd_async_handler_t *h; + int fd = siginfo->si_fd; + + for (h = async_list; h; h = h->next) { + if (h->fd == fd && h->callback) + h->callback(h); + } +} + +int snd_async_add_handler(snd_async_handler_t **handler, int fd, + snd_async_callback_t callback, void *private_data) +{ + snd_async_handler_t *h; + int err; + + h = calloc(1, sizeof(*h)); + if (!h) + return -ENOMEM; + h->fd = fd; + h->callback = callback; + h->private_data = private_data; + h->next = async_list; + err = snd_set_async(h, SIGIO); + if (err < 0) { + free(h); + return err; + } + if (!async_list) { + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_flags = SA_RESTART | SA_SIGINFO; + act.sa_sigaction = snd_async_handler; + sigemptyset(&act.sa_mask); + if (sigaction(SIGIO, &act, NULL) < 0) { + int err = -errno; + snd_set_async(h, -1); + free(h); + return err; + } + } + async_list = h; + *handler = h; + return 0; +} + +int snd_async_del_handler(snd_async_handler_t *handler) +{ + snd_async_handler_t *h, *prev; + + for (h = async_list, prev = NULL; h; prev = h, h = h->next) { + if (h == handler) { + if (prev) + prev->next = h->next; + else + async_list = h; + snd_set_async(h, -1); + if (h->pointer) + *h->pointer = NULL; + free(h); + break; + } + } + + if (!async_list) { + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_flags = 0; + act.sa_handler = SIG_DFL; + sigaction(SIGIO, &act, NULL); + } + return 0; +} diff --git a/src/control.c b/src/control.c index 4e1ccba..ab2dddd 100644 --- a/src/control.c +++ b/src/control.c @@ -85,6 +85,10 @@ int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode) int snd_ctl_close(snd_ctl_t *ctl) { +#if SALSA_HAS_ASYNC_SUPPORT + if (ctl->async) + snd_async_del_handler(ctl->async); +#endif close(ctl->fd); free(ctl); return 0; @@ -315,3 +319,26 @@ const char *_snd_ctl_elem_iface_names[] = { const char *_snd_ctl_event_type_names[] = { EVENT(ELEM), }; + + +#if SALSA_HAS_ASYNC_SUPPORT +/* + * async helper + */ +int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, + snd_async_callback_t callback, + void *private_data) +{ + int err; + + if (ctl->async) + return -EBUSY; + err = snd_async_add_handler(&ctl->async, ctl->fd, + callback, private_data); + if (err < 0) + return err; + ctl->async->rec = ctl; + ctl->async->pointer = &ctl->async; + return 0; +} +#endif /* SALSA_HAS_ASYNC_SUPPORT */ diff --git a/src/control.h b/src/control.h index 1176848..36e41ce 100644 --- a/src/control.h +++ b/src/control.h @@ -45,6 +45,12 @@ int snd_ctl_elem_tlv_command(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, const unsigned int *tlv); #endif +#if SALSA_HAS_ASYNC_SUPPORT +int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, + snd_async_callback_t callback, + void *private_data); +#endif + #include "ctl_macros.h" #define snd_ctl_elem_id_alloca(ptr) do { *ptr = alloca(snd_ctl_elem_id_sizeof()); memset(*ptr, 0, snd_ctl_elem_id_sizeof()); } while (0) diff --git a/src/ctl_macros.h b/src/ctl_macros.h index 1f0efd6..6c72bff 100644 --- a/src/ctl_macros.h +++ b/src/ctl_macros.h @@ -20,6 +20,9 @@ struct _snd_ctl { int card; int protocol; struct pollfd pollfd; +#if SALSA_HAS_ASYNC_SUPPORT + snd_async_handler_t *async; +#endif }; @@ -1187,6 +1190,16 @@ char *snd_device_name_get_hint(const void *hint, const char *id) return NULL; } +#if SALSA_HAS_ASYNC_SUPPORT + +static inline +snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler) +{ + return handler->rec; +} + +#else + static inline __attribute__ ((deprecated)) int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, snd_async_callback_t callback, @@ -1201,4 +1214,6 @@ snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler) return NULL; } +#endif /* SALSA_HAS_ASYNC_SUPPORT */ + #endif /* __ALSA_CTL_MACROS_H */ diff --git a/src/global.h b/src/global.h index 4a85af2..f33215f 100644 --- a/src/global.h +++ b/src/global.h @@ -23,20 +23,6 @@ #define __ALSA_GLOBAL_H typedef struct _snd_config snd_config_t; -typedef struct _snd_async_handler snd_async_handler_t; -typedef void (*snd_async_callback_t)(snd_async_handler_t *handler); - -#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE) -struct timeval { - time_t tv_sec; /* seconds */ - long tv_usec; /* microseconds */ -}; - -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -#endif typedef struct timeval snd_timestamp_t; typedef struct timespec snd_htimestamp_t; @@ -56,6 +42,48 @@ typedef struct _snd_seq snd_seq_t; #define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #endif +/* async helpers */ +typedef struct _snd_async_handler snd_async_handler_t; +typedef void (*snd_async_callback_t)(snd_async_handler_t *handler); + +#if SALSA_HAS_ASYNC_SUPPORT + +struct _snd_async_handler { + int fd; + snd_async_callback_t callback; + void *private_data; + void *rec; + struct _snd_async_handler **pointer; + struct _snd_async_handler *next; +}; + +#define snd_async_handler_get_signo(h) SIGIO +#define snd_async_handler_get_fd(h) (h)->fd +#define snd_async_handler_get_callback_private(h) (h)->private_data +int snd_async_add_handler(snd_async_handler_t **handler, int fd, + snd_async_callback_t callback, void *private_data); +int snd_async_del_handler(snd_async_handler_t *handler); + +#else + +#define snd_async_handler_get_signo(h) -1 +#define snd_async_handler_get_fd(h) -1 +#define snd_async_handler_get_callback_private(h) NULL +static inline __attribute__((deprecated)) +int snd_async_add_handler(snd_async_handler_t **handler, int fd, + snd_async_callback_t callback, void *private_data) +{ + return -ENXIO; +} +static inline __attribute__((deprecated)) +int snd_async_del_handler(snd_async_handler_t *handler) +{ + return -ENXIO; +} + +#endif /* SALSA_HAS_ASYNC_SUPPORT */ + +/* only for internal use */ int _snd_set_nonblock(int fd, int nonblock); #endif /* __ALSA_GLOBAL_H */ @@ -158,6 +158,10 @@ int snd_pcm_close(snd_pcm_t *pcm) } _snd_pcm_munmap(pcm); snd_pcm_hw_munmap_status(pcm); +#if SALSA_HAS_ASYNC_SUPPORT + if (pcm->async) + snd_async_del_handler(pcm->async); +#endif close(pcm->fd); free(pcm); return 0; @@ -980,6 +984,28 @@ snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm, } +#if SALSA_HAS_ASYNC_SUPPORT +/* + * async handler + */ +int snd_async_add_pcm_handler(snd_async_handler_t **handlerp, snd_pcm_t *pcm, + snd_async_callback_t callback, + void *private_data) +{ + int err; + + if (pcm->async) + return -EBUSY; + err = snd_async_add_handler(&pcm->async, pcm->fd, + callback, private_data); + if (err < 0) + return err; + pcm->async->rec = pcm; + pcm->async->pointer = &pcm->async; + return 0; +} +#endif /* SALSA_HAS_ASYNC_SUPPORT */ + /* * HELPERS */ @@ -104,6 +104,12 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_channels, unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format); +#if SALSA_HAS_ASYNC_SUPPORT +int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, + snd_async_callback_t callback, + void *private_data); +#endif + #include "pcm_macros.h" #define snd_pcm_info_alloca(ptr) do { *ptr = alloca(snd_pcm_info_sizeof()); memset(*ptr, 0, snd_pcm_info_sizeof()); } while (0) diff --git a/src/pcm_macros.h b/src/pcm_macros.h index 8c343bd..dbbbdcc 100644 --- a/src/pcm_macros.h +++ b/src/pcm_macros.h @@ -64,6 +64,9 @@ struct _snd_pcm { snd_pcm_channel_info_t *mmap_channels; snd_pcm_channel_area_t *running_areas; +#if SALSA_HAS_ASYNC_SUPPORT + snd_async_handler_t *async; +#endif }; /* @@ -2166,6 +2169,16 @@ snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, return -ENXIO; } +#if SALSA_HAS_ASYNC_SUPPORT + +static inline +snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler) +{ + return handler->rec; +} + +#else /* !SALSA_HAS_ASYNC_SUPPORT */ + static inline __attribute__ ((deprecated)) int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, snd_async_callback_t callback, @@ -2180,4 +2193,6 @@ snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler) return NULL; } +#endif /* SALSA_HAS_ASYNC_SUPPORT */ + #endif /* __ALSA_PCM_MACROS_H */ diff --git a/src/recipe.h.in b/src/recipe.h.in index f667aee..7de7393 100644 --- a/src/recipe.h.in +++ b/src/recipe.h.in @@ -4,4 +4,7 @@ /* Build with TLV support */ #define SALSA_HAS_TLV_SUPPORT @SALSA_HAS_TLV_SUPPORT@ +/* Build with async support */ +#define SALSA_HAS_ASYNC_SUPPORT @SALSA_HAS_ASYNC_SUPPORT@ + #endif /* __ALSA_RECIPE_H */ |