From 41f6aea8fdbc744c13bc461056a2d694a5c4d06f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:12:30 +0000 Subject: rename src to polyp git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@90 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/mainloop-signal.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 polyp/mainloop-signal.c (limited to 'polyp/mainloop-signal.c') diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c new file mode 100644 index 00000000..642ca5e0 --- /dev/null +++ b/polyp/mainloop-signal.c @@ -0,0 +1,163 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "mainloop-signal.h" +#include "util.h" + +struct signal_info { + int sig; + struct sigaction saved_sigaction; + void (*callback) (void *id, int signal, void *userdata); + void *userdata; + struct signal_info *previous, *next; +}; + +static struct pa_mainloop_api *api = NULL; +static int signal_pipe[2] = { -1, -1 }; +static void* mainloop_source = NULL; +static struct signal_info *signals = NULL; + +static void signal_handler(int sig) { + write(signal_pipe[1], &sig, sizeof(sig)); +} + +static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + assert(a && id && events == PA_MAINLOOP_API_IO_EVENT_INPUT && id == mainloop_source && fd == signal_pipe[0]); + + for (;;) { + ssize_t r; + int sig; + struct signal_info*s; + + if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { + if (errno == EAGAIN) + return; + + fprintf(stderr, "signal.c: read(): %s\n", strerror(errno)); + return; + } + + if (r != sizeof(sig)) { + fprintf(stderr, "signal.c: short read()\n"); + return; + } + + for (s = signals; s; s = s->next) + if (s->sig == sig) { + assert(s->callback); + s->callback(s, sig, s->userdata); + break; + } + } +} + +int pa_signal_init(struct pa_mainloop_api *a) { + assert(a); + if (pipe(signal_pipe) < 0) { + fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); + return -1; + } + + pa_make_nonblock_fd(signal_pipe[0]); + pa_make_nonblock_fd(signal_pipe[1]); + + api = a; + mainloop_source = api->source_io(api, signal_pipe[0], PA_MAINLOOP_API_IO_EVENT_INPUT, callback, NULL); + assert(mainloop_source); + return 0; +} + +void pa_signal_done(void) { + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && mainloop_source); + + api->cancel_io(api, mainloop_source); + mainloop_source = NULL; + + close(signal_pipe[0]); + close(signal_pipe[1]); + signal_pipe[0] = signal_pipe[1] = -1; + + while (signals) + pa_signal_unregister(signals); + + api = NULL; +} + +void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void *userdata), void *userdata) { + struct signal_info *s = NULL; + struct sigaction sa; + assert(sig > 0 && callback); + + for (s = signals; s; s = s->next) + if (s->sig == sig) + goto fail; + + s = malloc(sizeof(struct signal_info)); + assert(s); + s->sig = sig; + s->callback = callback; + s->userdata = userdata; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction(sig, &sa, &s->saved_sigaction) < 0) + goto fail; + + s->previous = NULL; + s->next = signals; + signals = s; + + return s; +fail: + if (s) + free(s); + return NULL; +} + +void pa_signal_unregister(void *id) { + struct signal_info *s = id; + assert(s); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + signals = s->next; + + sigaction(s->sig, &s->saved_sigaction, NULL); + free(s); +} -- cgit