summaryrefslogtreecommitdiff
path: root/src/common/pulse-glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/pulse-glue.c')
-rw-r--r--src/common/pulse-glue.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/src/common/pulse-glue.c b/src/common/pulse-glue.c
new file mode 100644
index 0000000..98dbf24
--- /dev/null
+++ b/src/common/pulse-glue.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <pulse/mainloop-api.h>
+#include <pulse/timeval.h>
+
+#include <murphy/common/mm.h>
+#include <murphy/common/mainloop.h>
+
+#include <murphy/common/pulse-glue.h>
+
+
+typedef struct {
+ pa_mainloop_api *pa;
+} pulse_glue_t;
+
+
+typedef struct {
+ pa_io_event *pa_io;
+ void (*cb)(void *glue_data,
+ void *id, int fd, mrp_io_event_t events,
+ void *user_data);
+ void *user_data;
+ void *glue_data;
+} io_t;
+
+
+typedef struct {
+ pa_time_event *pa_t;
+ void (*cb)(void *glue_data, void *id, void *user_data);
+ void *user_data;
+ void *glue_data;
+} tmr_t;
+
+
+typedef struct {
+ pa_defer_event *pa_d;
+ void (*cb)(void *glue_data, void *id, void *user_data);
+ void *user_data;
+ void *glue_data;
+} dfr_t;
+
+
+static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
+ void (*cb)(void *glue_data, void *id, int fd,
+ mrp_io_event_t events, void *user_data),
+ void *user_data);
+static void del_io(void *glue_data, void *id);
+
+static void *add_timer(void *glue_data, unsigned int msecs,
+ void (*cb)(void *glue_data, void *id, void *user_data),
+ void *user_data);
+static void del_timer(void *glue_data, void *id);
+static void mod_timer(void *glue_data, void *id, unsigned int msecs);
+
+static void *add_defer(void *glue_data,
+ void (*cb)(void *glue_data, void *id, void *user_data),
+ void *user_data);
+static void del_defer(void *glue_data, void *id);
+static void mod_defer(void *glue_data, void *id, int enabled);
+
+
+static void io_cb(pa_mainloop_api *pa, pa_io_event *e, int fd,
+ pa_io_event_flags_t mask, void *user_data)
+{
+ io_t *io = (io_t *)user_data;
+ mrp_io_event_t events = MRP_IO_EVENT_NONE;
+
+ MRP_UNUSED(pa);
+ MRP_UNUSED(e);
+
+ if (mask & PA_IO_EVENT_INPUT) events |= MRP_IO_EVENT_IN;
+ if (mask & PA_IO_EVENT_OUTPUT) events |= MRP_IO_EVENT_OUT;
+ if (mask & PA_IO_EVENT_HANGUP) events |= MRP_IO_EVENT_HUP;
+ if (mask & PA_IO_EVENT_ERROR) events |= MRP_IO_EVENT_ERR;
+
+ io->cb(io->glue_data, io, fd, events, io->user_data);
+}
+
+
+static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
+ void (*cb)(void *glue_data, void *id, int fd,
+ mrp_io_event_t events, void *user_data),
+ void *user_data)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ pa_io_event_flags_t mask = PA_IO_EVENT_NULL;
+ io_t *io;
+
+ io = mrp_allocz(sizeof(*io));
+
+ if (io != NULL) {
+ if (events & MRP_IO_EVENT_IN) mask |= PA_IO_EVENT_INPUT;
+ if (events & MRP_IO_EVENT_OUT) mask |= PA_IO_EVENT_OUTPUT;
+ if (events & MRP_IO_EVENT_HUP) mask |= PA_IO_EVENT_HANGUP;
+ if (events & MRP_IO_EVENT_ERR) mask |= PA_IO_EVENT_ERROR;
+
+ io->pa_io = pa->io_new(pa, fd, mask, io_cb, io);
+
+ if (io->pa_io != NULL) {
+ io->cb = cb;
+ io->user_data = user_data;
+ io->glue_data = glue_data;
+
+ return io;
+ }
+ else
+ mrp_free(io);
+ }
+
+ return NULL;
+}
+
+
+static void del_io(void *glue_data, void *id)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ io_t *io = (io_t *)id;
+
+ pa->io_free(io->pa_io);
+ mrp_free(io);
+}
+
+
+static void timer_cb(pa_mainloop_api *pa, pa_time_event *e,
+ const struct timeval *tv, void *user_data)
+{
+ tmr_t *t = (tmr_t *)user_data;
+
+ MRP_UNUSED(pa);
+ MRP_UNUSED(e);
+ MRP_UNUSED(tv);
+
+ t->cb(t->glue_data, t, t->user_data);
+}
+
+
+static void *add_timer(void *glue_data, unsigned int msecs,
+ void (*cb)(void *glue_data, void *id, void *user_data),
+ void *user_data)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ struct timeval tv;
+ tmr_t *t;
+
+ t = mrp_allocz(sizeof(*t));
+
+ if (t != NULL) {
+ pa_gettimeofday(&tv);
+
+ tv.tv_sec += msecs / 1000;
+ tv.tv_usec += 1000 * (msecs % 1000);
+
+ t->pa_t = pa->time_new(pa, &tv, timer_cb, t);
+
+ if (t->pa_t != NULL) {
+ t->cb = cb;
+ t->user_data = user_data;
+ t->glue_data = glue_data;
+
+ return t;
+ }
+ else
+ mrp_free(t);
+ }
+
+ return NULL;
+}
+
+
+static void del_timer(void *glue_data, void *id)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ tmr_t *t = (tmr_t *)id;
+
+ pa->time_free(t->pa_t);
+ mrp_free(t);
+}
+
+
+static void mod_timer(void *glue_data, void *id, unsigned int msecs)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ tmr_t *t = (tmr_t *)id;
+ struct timeval tv;
+
+ if (t != NULL) {
+ pa_gettimeofday(&tv);
+
+ tv.tv_sec += msecs / 1000;
+ tv.tv_usec += 1000 * (msecs % 1000);
+
+ pa->time_restart(t->pa_t, &tv);
+ }
+}
+
+
+static void defer_cb(pa_mainloop_api *pa, pa_defer_event *e, void *user_data)
+{
+ dfr_t *d = (dfr_t *)user_data;
+
+ MRP_UNUSED(pa);
+ MRP_UNUSED(e);
+
+ d->cb(d->glue_data, d, d->user_data);
+}
+
+
+static void *add_defer(void *glue_data,
+ void (*cb)(void *glue_data, void *id, void *user_data),
+ void *user_data)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ dfr_t *d;
+
+ d = mrp_allocz(sizeof(*d));
+
+ if (d != NULL) {
+ d->pa_d = pa->defer_new(pa, defer_cb, d);
+
+ if (d->pa_d != NULL) {
+ d->cb = cb;
+ d->user_data = user_data;
+ d->glue_data = glue_data;
+
+ return d;
+ }
+ else
+ mrp_free(d);
+ }
+
+ return NULL;
+}
+
+
+static void del_defer(void *glue_data, void *id)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ dfr_t *d = (dfr_t *)id;
+
+ pa->defer_free(d->pa_d);
+ mrp_free(d);
+}
+
+
+static void mod_defer(void *glue_data, void *id, int enabled)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)glue_data;
+ pa_mainloop_api *pa = glue->pa;
+ dfr_t *d = (dfr_t *)id;
+
+ pa->defer_enable(d->pa_d, !!enabled);
+}
+
+
+static void unregister(void *data)
+{
+ pulse_glue_t *glue = (pulse_glue_t *)data;
+
+ mrp_free(glue);
+}
+
+
+static mrp_superloop_ops_t pa_ops = {
+ .add_io = add_io,
+ .del_io = del_io,
+ .add_timer = add_timer,
+ .del_timer = del_timer,
+ .mod_timer = mod_timer,
+ .add_defer = add_defer,
+ .del_defer = del_defer,
+ .mod_defer = mod_defer,
+ .unregister = unregister,
+};
+
+
+int mrp_mainloop_register_with_pulse(mrp_mainloop_t *ml, pa_mainloop_api *pa)
+{
+ pulse_glue_t *glue;
+
+ glue = mrp_allocz(sizeof(*glue));
+
+ if (glue != NULL) {
+ glue->pa = pa;
+
+ if (mrp_set_superloop(ml, &pa_ops, glue))
+ return TRUE;
+ else
+ mrp_free(glue);
+ }
+
+ return FALSE;
+}
+
+
+int mrp_mainloop_unregister_from_pulse(mrp_mainloop_t *ml)
+{
+ return mrp_mainloop_unregister(ml);
+}
+
+
+
+static mrp_mainloop_t *pulse_ml;
+
+mrp_mainloop_t *mrp_mainloop_pulse_get(pa_mainloop_api *pa)
+{
+ if (pulse_ml == NULL) {
+ pulse_ml = mrp_mainloop_create();
+
+ if (pulse_ml != NULL) {
+ if (!mrp_mainloop_register_with_pulse(pulse_ml, pa)) {
+ mrp_mainloop_destroy(pulse_ml);
+ pulse_ml = NULL;
+ }
+ }
+ }
+
+ return pulse_ml;
+}