Similar to enlightenment_fm_open but uses DBus instead of E IPC. We need more code to set it up, but it is more extensible. Command line example: dbus-send --session --print-reply \ --dest=org.enlightenment.FileManager \ /org/enlightenment/FileManager \ org.enlightenment.FileManager.OpenDirectory \ string:"/home" SVN revision: 37865devs/princeamd/enlightenment-0.17-elive
parent
365ac21772
commit
9df67037c6
4 changed files with 246 additions and 0 deletions
@ -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(); |
||||
} |
@ -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 |
Loading…
Reference in new issue