diff --git a/src/modules/fileman/Makefile.am b/src/modules/fileman/Makefile.am index f0e13dbbd..569c09c64 100644 --- a/src/modules/fileman/Makefile.am +++ b/src/modules/fileman/Makefile.am @@ -22,6 +22,8 @@ module_la_SOURCES = e_mod_main.c \ e_mod_main.h \ e_mod_config.c \ e_mod_config.h \ + e_mod_dbus.c \ + e_mod_dbus.h \ e_fwin.c \ e_fwin.h diff --git a/src/modules/fileman/e_mod_dbus.c b/src/modules/fileman/e_mod_dbus.c new file mode 100644 index 000000000..f8ecb646c --- /dev/null +++ b/src/modules/fileman/e_mod_dbus.c @@ -0,0 +1,231 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_dbus.h" + +static const char E_FILEMAN_BUS_NAME[] = "org.enlightenment.FileManager"; +static const char E_FILEMAN_INTERFACE[] = "org.enlightenment.FileManager"; +static const char E_FILEMAN_ERROR[] = "org.enlightenment.FileManager.Error"; +static const char E_FILEMAN_PATH[] = "/org/enlightenment/FileManager"; + +typedef struct _E_Fileman_DBus_Daemon E_Fileman_DBus_Daemon; +struct _E_Fileman_DBus_Daemon +{ + E_DBus_Connection *conn; + E_DBus_Interface *iface; + E_DBus_Object *obj; + + struct { + DBusPendingCall *request_name; + } pending; +}; + +static DBusMessage * +_e_fileman_dbus_daemon_error(DBusMessage *message, const char *msg) +{ + return dbus_message_new_error(message, E_FILEMAN_ERROR, msg); +} + +static void +_e_fileman_dbus_daemon_object_init(E_Fileman_DBus_Daemon *d) +{ + if (d->obj) + return; + + d->obj = e_dbus_object_add(d->conn, E_FILEMAN_PATH, d); + if (!d->obj) + { + fprintf(stderr, "ERROR: cannot add object to %s\n", E_FILEMAN_PATH); + return; + } + + e_dbus_object_interface_attach(d->obj, d->iface); +} + +static void +_e_fileman_dbus_daemon_free(E_Fileman_DBus_Daemon *d) +{ + if (d->pending.request_name) + dbus_pending_call_cancel(d->pending.request_name); + + if (d->obj) + { + e_dbus_object_interface_detach(d->obj, d->iface); + e_dbus_object_free(d->obj); + } + + if (d->iface) + e_dbus_interface_unref(d->iface); + + if (d->conn) + e_dbus_connection_close(d->conn); + + free(d); +} + +DBusMessage * +_e_fileman_dbus_daemon_open_directory_cb(E_DBus_Object *obj, DBusMessage *message) +{ + DBusMessageIter itr; + const char *directory = NULL, *p; + char *dev; + E_Zone *zone; + + dbus_message_iter_init(message, &itr); + dbus_message_iter_get_basic(&itr, &directory); + + if ((!directory) || (directory[0] == '\0')) + return _e_fileman_dbus_daemon_error(message, "no directory provided."); + + if (strncmp(directory, "file://", sizeof("file://") - 1) == 0) + directory += sizeof("file://") - 1; + + zone = e_util_zone_current_get(e_manager_current_get()); + if (!zone) + return _e_fileman_dbus_daemon_error(message, "could not find a zone."); + + + p = strchr(directory, '/'); + if (p) + { + int len = p - directory + 1; + + dev = malloc(len + 1); + if (!dev) + return _e_fileman_dbus_daemon_error + (message, "could not allocate memory."); + + memcpy(dev, directory, len); + dev[len] = '\0'; + + if ((dev[0] != '/') && (dev[0] != '~')) + dev[len - 1] = '\0'; /* remove trailing '/' */ + + directory += p - directory; + } + else + { + dev = strdup(directory); + directory = "/"; + } + + e_fwin_new(zone->container, dev, directory); + free(dev); + return dbus_message_new_method_return(message); +} + +static void +_e_fileman_dbus_daemon_request_name_cb(void *data, DBusMessage *msg, DBusError *err) +{ + E_Fileman_DBus_Daemon *d = data; + dbus_uint32_t ret; + DBusError new_err; + + d->pending.request_name = NULL; + + if (dbus_error_is_set(err)) + { + fprintf(stderr, "ERROR: FILEMAN: RequestName failed: %s\n", + err->message); + dbus_error_free(err); + return; + } + + dbus_error_init(&new_err); + dbus_message_get_args(msg, &new_err, DBUS_TYPE_UINT32, &ret, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&new_err)) + { + fprintf(stderr, + "ERROR: FILEMAN: could not get arguments of RequestName: %s\n", + new_err.message); + dbus_error_free(&new_err); + return; + } + + switch (ret) + { + case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: + case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: + _e_fileman_dbus_daemon_object_init(d); + break; + case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: + //XXX mark daemon as queued? + break; + case DBUS_REQUEST_NAME_REPLY_EXISTS: + //XXX exit? + break; + } +} + +static E_Fileman_DBus_Daemon * +_e_fileman_dbus_daemon_new(void) +{ + E_Fileman_DBus_Daemon *d; + + d = calloc(1, sizeof(*d)); + if (!d) + { + perror("ERROR: FILEMAN: cannot allocate fileman dbus daemon memory."); + return NULL; + } + + d->conn = e_dbus_bus_get(DBUS_BUS_SESSION); + if (!d->conn) + goto error; + + d->iface = e_dbus_interface_new(E_FILEMAN_INTERFACE); + if (!d->iface) + goto error; + + d->pending.request_name = e_dbus_request_name + (d->conn, E_FILEMAN_BUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, + _e_fileman_dbus_daemon_request_name_cb, d); + if (!d->pending.request_name) + goto error; + + const struct { + const char *method; + const char *signature; + const char *ret_signature; + E_DBus_Method_Cb func; + } *itr, desc[] = { + {"OpenDirectory", "s", "", _e_fileman_dbus_daemon_open_directory_cb}, + {NULL} + }; + + for (itr = desc; itr->method != NULL; itr++) + e_dbus_interface_method_add + (d->iface, itr->method, itr->signature, itr->ret_signature, itr->func); + + return d; + + error: + fprintf(stderr, "ERROR: FILEMAN: failed to create daemon at %p\n", d); + _e_fileman_dbus_daemon_free(d); + return NULL; +} + + +static E_Fileman_DBus_Daemon *_daemon = NULL; + +void +e_fileman_dbus_init(void) +{ + if (_daemon) + return; + + e_dbus_init(); + _daemon = _e_fileman_dbus_daemon_new(); +} + +void +e_fileman_dbus_shutdown(void) +{ + if (!_daemon) + return; + + _e_fileman_dbus_daemon_free(_daemon); + _daemon = NULL; + e_dbus_shutdown(); +} diff --git a/src/modules/fileman/e_mod_dbus.h b/src/modules/fileman/e_mod_dbus.h new file mode 100644 index 000000000..4db0e40c5 --- /dev/null +++ b/src/modules/fileman/e_mod_dbus.h @@ -0,0 +1,7 @@ +#ifndef E_MOD_DBUS_H +#define E_MOD_DBUS_H + +void e_fileman_dbus_init(void); +void e_fileman_dbus_shutdown(void); + +#endif diff --git a/src/modules/fileman/e_mod_main.c b/src/modules/fileman/e_mod_main.c index fa44eb363..66f997bbd 100644 --- a/src/modules/fileman/e_mod_main.c +++ b/src/modules/fileman/e_mod_main.c @@ -4,6 +4,7 @@ #include "e.h" #include "e_mod_main.h" #include "e_mod_config.h" +#include "e_mod_dbus.h" /* actual module specifics */ static void _e_mod_action_fileman_cb(E_Object *obj, const char *params); @@ -96,6 +97,9 @@ e_modapi_init(E_Module *m) /* FIXME: add system event for new zone creation, and on creation, add an fwin to the zone */ + + e_fileman_dbus_init(); + return m; } @@ -107,6 +111,8 @@ e_modapi_shutdown(E_Module *m) E_Container *con; E_Zone *zone; + e_fileman_dbus_shutdown(); + ecore_event_handler_del(zone_add_handler); zone_add_handler = NULL;