plugins: added dbus core plugin.
authorKrisztian Litkey <kli@iki.fi>
Fri, 6 Apr 2012 11:41:20 +0000 (14:41 +0300)
committerKrisztian Litkey <kli@iki.fi>
Fri, 6 Apr 2012 11:41:20 +0000 (14:41 +0300)
configure.ac
src/Makefile.am
src/plugins/plugin-dbus.c [new file with mode: 0644]

index 969eb1f..0557436 100644 (file)
@@ -152,6 +152,7 @@ function check_if_internal() {
 }
 
 AM_CONDITIONAL(BUILTIN_PLUGIN_TEST,    [check_if_internal test])
+AM_CONDITIONAL(BUILTIN_PLUGIN_DBUS,    [check_if_internal dbus])
 #AM_CONDITIONAL(BUILTIN_PLUGIN_STORAGE, [check_if_internal storage])
 #AM_CONDITIONAL(BUILTIN_PLUGIN_SYSFS,   [check_if_internal sysfs  ])
 #AM_CONDITIONAL(BUILTIN_PLUGIN_DISPLAY, [check_if_internal display])
index a554487..dbf0f94 100644 (file)
@@ -124,6 +124,24 @@ plugin_test_la_LIBADD  = $(TEST_PLUGIN_LIBS)
 plugin_LTLIBRARIES    += plugin-test.la
 endif
 
+# dbus plugin
+DBUS_PLUGIN_SOURCES = plugins/plugin-dbus.c
+DBUS_PLUGIN_CFLAGS  = $(DBUS_CFLAGS)
+DBUS_PLUGIN_LIBS    = $(DBUS_LIBS)
+
+if BUILTIN_PLUGIN_DBUS
+BUILTIN_PLUGINS += $(DBUS_PLUGIN_SOURCES)
+BUILTIN_CFLAGS  += $(DBUS_PLUGIN_CFLAGS)
+BUILTIN_LIBS    += $(DBUS_PLUGIN_LIBS)
+else
+plugin_dbus_la_SOURCES = $(DBUS_PLUGIN_SOURCES)
+plugin_dbus_la_CFLAGS  = $(DBUS_PLUGIN_CFLAGS) $(MURPHY_CFLAGS) $(AM_CFLAGS)
+plugin_dbus_la_LDFLAGS = -module -avoid-version
+plugin_dbus_la_LIBADD  = $(DBUS_PLUGIN_LIBS)
+
+plugin_LTLIBRARIES    += plugin-dbus.la
+endif
+
 
 ###################################
 # murphy daemon
diff --git a/src/plugins/plugin-dbus.c b/src/plugins/plugin-dbus.c
new file mode 100644 (file)
index 0000000..9836c19
--- /dev/null
@@ -0,0 +1,350 @@
+#include <dbus/dbus.h>
+
+#include <murphy/common/macros.h>
+#include <murphy/common/mm.h>
+#include <murphy/common/log.h>
+#include <murphy/common/list.h>
+#include <murphy/common/mainloop.h>
+#include <murphy/core/plugin.h>
+
+typedef struct dbus_glue_s dbus_glue_t;
+
+typedef struct {
+    dbus_glue_t     *glue;
+    mrp_io_watch_t  *mw;
+    DBusWatch       *dw;
+    mrp_list_hook_t  hook;
+} watch_t;
+
+
+typedef struct {
+    dbus_glue_t     *glue;
+    mrp_timer_t     *mt;
+    DBusTimeout     *dt;
+    mrp_list_hook_t  hook;
+} timeout_t;
+
+
+struct dbus_glue_s {
+    DBusConnection  *conn;
+    mrp_mainloop_t  *ml;
+    mrp_list_hook_t  watches;
+    mrp_list_hook_t  timers;
+    mrp_deferred_t  *pump;
+};
+
+
+static dbus_int32_t data_slot = -1;
+
+static void dispatch_watch(mrp_mainloop_t *ml, mrp_io_watch_t *mw, int fd,
+                          mrp_io_event_t events, void *user_data)
+{
+    watch_t        *watch = (watch_t *)user_data;
+    DBusConnection *conn  = watch->glue->conn;
+    unsigned int    mask  = 0;
+
+    MRP_UNUSED(ml);
+    MRP_UNUSED(mw);
+    MRP_UNUSED(fd);
+
+    if (events & MRP_IO_EVENT_IN)
+       mask |= DBUS_WATCH_READABLE;
+    if (events & MRP_IO_EVENT_OUT)
+       mask |= DBUS_WATCH_WRITABLE;
+    if (events & MRP_IO_EVENT_HUP)
+       mask |= DBUS_WATCH_HANGUP;
+    if (events & MRP_IO_EVENT_ERR)
+       mask |= DBUS_WATCH_ERROR;
+    
+    dbus_connection_ref(conn);
+    dbus_watch_handle(watch->dw, mask);
+    dbus_connection_unref(conn);
+}
+
+
+static void watch_freed_cb(void *data)
+{
+    watch_t *watch = (watch_t *)data;
+
+    if (watch != NULL) {
+       mrp_list_delete(&watch->hook);
+       mrp_del_io_watch(watch->mw);
+       mrp_free(watch);
+    }
+}
+
+
+static dbus_bool_t add_watch(DBusWatch *dw, void *data)
+{
+    dbus_glue_t    *glue = (dbus_glue_t *)data;
+    watch_t        *watch;
+    mrp_io_watch_t *mw;
+    mrp_io_event_t  mask;
+    int             fd;
+    unsigned int    flags;
+
+    if (!dbus_watch_get_enabled(dw))
+       return TRUE;
+    
+    fd    = dbus_watch_get_unix_fd(dw);
+    flags = dbus_watch_get_flags(dw);
+    mask  = MRP_IO_EVENT_HUP | MRP_IO_EVENT_ERR;
+
+    if (flags & DBUS_WATCH_READABLE)
+       mask |= MRP_IO_EVENT_IN;
+    if (flags & DBUS_WATCH_WRITABLE)
+       mask |= MRP_IO_EVENT_OUT;
+
+    if ((watch = mrp_allocz(sizeof(*watch))) != NULL) {
+       mrp_list_init(&watch->hook);
+       mw = mrp_add_io_watch(glue->ml, fd, mask, dispatch_watch, watch);
+
+       if (mw != NULL) {
+           watch->glue = glue;
+           watch->mw   = mw;
+           watch->dw   = dw;
+           dbus_watch_set_data(dw, watch, watch_freed_cb);
+           mrp_list_append(&glue->watches, &watch->hook);
+           
+           return TRUE;
+       }
+       else
+           mrp_free(watch);
+    }
+
+    return FALSE;
+}
+
+
+static void del_watch(DBusWatch *dw, void *data)
+{
+    watch_t *watch = (watch_t *)dbus_watch_get_data(dw);
+
+    MRP_UNUSED(data);
+
+    if (watch != NULL) {
+       mrp_del_io_watch(watch->mw);
+       watch->mw = NULL;
+    }
+}
+
+
+static void toggle_watch(DBusWatch *dw, void *data)
+{
+    if (dbus_watch_get_enabled(dw))
+       add_watch(dw, data);
+    else
+       del_watch(dw, data);
+}
+
+
+static void dispatch_timeout(mrp_mainloop_t *ml, mrp_timer_t *mt,
+                            void *user_data)
+{
+    timeout_t *timer = (timeout_t *)user_data;
+
+    MRP_UNUSED(ml);
+    MRP_UNUSED(mt);
+
+    dbus_timeout_handle(timer->dt);
+}
+
+
+static void timeout_freed_cb(void *data)
+{
+    timeout_t *timer = (timeout_t *)data;
+
+    if (timer != NULL) {
+       mrp_list_delete(&timer->hook);
+       mrp_del_timer(timer->mt);
+
+       mrp_free(timer);
+    }
+}
+
+
+static dbus_bool_t add_timeout(DBusTimeout *dt, void *data)
+{
+    dbus_glue_t  *glue = (dbus_glue_t *)data;
+    timeout_t    *timer;
+    mrp_timer_t  *mt;
+    unsigned int  msecs;
+    
+    if ((timer = mrp_allocz(sizeof(*timer))) != NULL) {
+       mrp_list_init(&timer->hook);
+       msecs = dbus_timeout_get_interval(dt);
+       mt    = mrp_add_timer(glue->ml, msecs, dispatch_timeout, timer);
+
+       if (mt != NULL) {
+           timer->glue = glue;
+           timer->mt   = mt;
+           timer->dt   = dt;
+           dbus_timeout_set_data(dt, timer, timeout_freed_cb);
+           mrp_list_append(&glue->timers, &timer->hook);
+           
+           return TRUE;
+       }
+       else
+           mrp_free(timer);
+    }
+
+    return FALSE;
+}
+
+
+static void del_timeout(DBusTimeout *dt, void *data)
+{
+    timeout_t *timer = (timeout_t *)dbus_timeout_get_data(dt);
+    
+    MRP_UNUSED(data);
+
+    if (timer != NULL) {
+       mrp_del_timer(timer->mt);
+       timer->mt = NULL;
+    }
+}
+
+
+static void toggle_timeout(DBusTimeout *dt, void *data)
+{
+    if (dbus_timeout_get_enabled(dt))
+       add_timeout(dt, data);
+    else
+       del_timeout(dt, data);
+}
+
+
+static void wakeup_mainloop(void *data)
+{
+    dbus_glue_t *glue = (dbus_glue_t *)data;
+
+    mrp_enable_deferred(glue->pump);
+}
+
+
+static void glue_free_cb(void *data)
+{
+    dbus_glue_t     *glue = (dbus_glue_t *)data;
+    mrp_list_hook_t *p, *n;
+    watch_t         *watch;
+    timeout_t       *timer;
+
+    mrp_list_foreach(&glue->watches, p, n) {
+       watch = mrp_list_entry(p, typeof(*watch), hook);
+
+       mrp_list_delete(&watch->hook);
+       mrp_del_io_watch(watch->mw);
+
+       mrp_free(watch);
+    }
+
+    mrp_list_foreach(&glue->timers, p, n) {
+       timer = mrp_list_entry(p, typeof(*timer), hook);
+
+       mrp_list_delete(&timer->hook);
+       mrp_del_timer(timer->mt);
+       
+       mrp_free(timer);
+    }
+    
+    mrp_free(glue);
+}
+
+
+static void pump_cb(mrp_mainloop_t *ml, mrp_deferred_t *d, void *user_data)
+{
+    dbus_glue_t *glue = (dbus_glue_t *)user_data;
+
+    MRP_UNUSED(ml);
+
+    if (dbus_connection_dispatch(glue->conn) == DBUS_DISPATCH_COMPLETE)
+       mrp_disable_deferred(d);
+}
+
+
+static void dispatch_status_cb(DBusConnection *conn, DBusDispatchStatus status,
+                              void *user_data)
+{
+    dbus_glue_t *glue = (dbus_glue_t *)user_data;
+
+    MRP_UNUSED(conn);
+
+    switch (status) {
+    case DBUS_DISPATCH_COMPLETE:
+       mrp_disable_deferred(glue->pump);
+       break;
+       
+    case DBUS_DISPATCH_DATA_REMAINS:
+    case DBUS_DISPATCH_NEED_MEMORY:
+    default:
+       mrp_enable_deferred(glue->pump);
+       break;
+    }
+}
+
+
+int mrp_setup_dbus_connection(mrp_mainloop_t *ml, DBusConnection *conn)
+{
+    dbus_glue_t *glue;
+    
+    if (!dbus_connection_allocate_data_slot(&data_slot))
+       return FALSE;
+    
+    if (dbus_connection_get_data(conn, data_slot) != NULL)
+       return FALSE;
+
+    if ((glue = mrp_allocz(sizeof(*glue))) != NULL) {
+       mrp_list_init(&glue->watches);
+       mrp_list_init(&glue->timers);
+       glue->pump = mrp_add_deferred(ml, pump_cb, glue);
+
+       if (glue->pump == NULL) {
+           mrp_free(glue);
+           return FALSE;
+       }
+       
+       glue->ml   = ml;
+       glue->conn = conn;
+    }
+    else
+       return FALSE;
+    
+    if (!dbus_connection_set_data(conn, data_slot, glue, glue_free_cb))
+       return FALSE;
+    
+    dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb,
+                                                glue, NULL);
+
+    dbus_connection_set_wakeup_main_function(conn, wakeup_mainloop,
+                                            glue, NULL);
+
+    return 
+       dbus_connection_set_watch_functions(conn, add_watch, del_watch,
+                                           toggle_watch, glue, NULL) &&
+       dbus_connection_set_timeout_functions(conn, add_timeout, del_timeout,
+                                             toggle_timeout, glue, NULL);
+}
+
+
+
+static int dbus_init(mrp_plugin_t *plugin)
+{
+    MRP_UNUSED(plugin);
+    
+    mrp_log_info("%s() called...", __FUNCTION__);
+    
+    return TRUE;
+}
+
+
+static void dbus_exit(mrp_plugin_t *plugin)
+{
+    MRP_UNUSED(plugin);
+    
+    mrp_log_info("%s() called...", __FUNCTION__);
+}
+
+
+#define DBUS_HELP "DBUS pump plugin (DBUS-mainloop integration)."
+
+MURPHY_REGISTER_CORE_PLUGIN("dbus", DBUS_HELP, dbus_init, dbus_exit);