9 #include "e_dbus_private.h"
11 static E_DBus_Version _version = { VMAJ, VMIN, VMIC, VREV };
12 EAPI E_DBus_Version *e_dbus_version = &_version;
14 #define NUM_BUS_TYPES 3
18 * listen for disconnected signal and clean up?
19 * listen for NameOwnerChanged signals for names we have SignalHandler's for
20 * remap SH to listen for signals from new owner
22 int _e_dbus_log_dom = -1;
23 static int connection_slot = -1;
25 static int _edbus_init_count = 0;
26 static int close_connection = 0;
27 EAPI int E_DBUS_EVENT_SIGNAL = 0;
29 static E_DBus_Connection *shared_connections[2] = {NULL, NULL};
31 typedef struct E_DBus_Handler_Data E_DBus_Handler_Data;
32 typedef struct E_DBus_Timeout_Data E_DBus_Timeout_Data;
35 struct E_DBus_Handler_Data
38 Ecore_Fd_Handler *fd_handler;
39 E_DBus_Connection *cd;
44 struct E_DBus_Timeout_Data
48 E_DBus_Connection *cd;
52 static Eina_Bool e_dbus_idler(void *data);
55 e_dbus_fd_handler_del(E_DBus_Handler_Data *hd)
57 if (!hd->fd_handler) return;
59 DBG("handler disabled");
60 hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
61 ecore_main_fd_handler_del(hd->fd_handler);
62 hd->fd_handler = NULL;
66 e_dbus_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
68 E_DBus_Handler_Data *hd;
69 unsigned int condition = 0;
71 DBG("fd handler (%p)!", fd_handler);
77 e_dbus_fd_handler_del(hd);
78 return ECORE_CALLBACK_CANCEL;
80 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) condition |= DBUS_WATCH_READABLE;
81 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) condition |= DBUS_WATCH_WRITABLE;
82 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) condition |= DBUS_WATCH_ERROR;
83 DBG("fdh || READ: %d, WRITE: %d",
84 (condition & DBUS_WATCH_READABLE) == DBUS_WATCH_READABLE,
85 (condition & DBUS_WATCH_WRITABLE) == DBUS_WATCH_WRITABLE);
87 if (condition & DBUS_WATCH_ERROR) DBG("DBUS watch error");
88 dbus_watch_handle(hd->watch, condition);
91 return ECORE_CALLBACK_RENEW;
95 e_dbus_fd_handler_add(E_DBus_Handler_Data *hd)
98 Ecore_Fd_Handler_Flags eflags;
100 Ecore_Fd_Handler *fdh;
102 if (hd->fd_handler) return;
103 dflags = dbus_watch_get_flags(hd->watch);
104 eflags = ECORE_FD_ERROR;
105 if (dflags & DBUS_WATCH_READABLE) eflags |= ECORE_FD_READ;
106 if (dflags & DBUS_WATCH_WRITABLE) eflags |= ECORE_FD_WRITE;
108 EINA_LIST_FOREACH(hd->cd->fd_handlers, l, fdh)
110 if (ecore_main_fd_handler_fd_get(fdh) == hd->fd) return;
113 DBG("fd handler add (%d)", hd->fd);
114 hd->fd_handler = ecore_main_fd_handler_add(hd->fd,
121 hd->cd->fd_handlers = eina_list_append(hd->cd->fd_handlers, hd->fd_handler);
126 e_dbus_handler_data_free(void *data)
128 E_DBus_Handler_Data *hd = data;
130 DBG("e_dbus_handler_data_free");
133 hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
134 ecore_main_fd_handler_del(hd->fd_handler);
140 e_dbus_connection_data_watch_add(E_DBus_Connection *cd, DBusWatch *watch)
142 E_DBus_Handler_Data *hd;
144 hd = calloc(1, sizeof(E_DBus_Handler_Data));
145 dbus_watch_set_data(watch, hd, e_dbus_handler_data_free);
149 hd->enabled = dbus_watch_get_enabled(watch);
150 #if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO>= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR > 1) || (DBUS_VERSION_MAJOR > 1)
151 hd->fd = dbus_watch_get_unix_fd(hd->watch);
153 hd->fd = dbus_watch_get_fd(hd->watch);
155 DBG("watch add (enabled: %d)", hd->enabled);
156 if (hd->enabled) e_dbus_fd_handler_add(hd);
159 static E_DBus_Connection *
160 e_dbus_connection_new(DBusConnection *conn)
162 E_DBus_Connection *cd;
163 const char *conn_name;
165 cd = calloc(1, sizeof(E_DBus_Connection));
166 if (!cd) return NULL;
169 conn_name = dbus_bus_get_unique_name(conn);
172 DBG("Connected! Name: %s", conn_name);
173 cd->conn_name = strdup(conn_name);
176 DBG("Not connected");
178 cd->shared_type = (unsigned int)-1;
179 cd->fd_handlers = NULL;
186 e_dbus_connection_free(void *data)
188 E_DBus_Connection *cd = data;
189 Ecore_Fd_Handler *fd_handler;
191 DBG("e_dbus_connection free!");
193 EINA_LIST_FREE(cd->fd_handlers, fd_handler)
194 ecore_main_fd_handler_del(fd_handler);
196 EINA_LIST_FREE(cd->timeouts, timer)
197 ecore_timer_del(timer);
199 if (cd->shared_type != (unsigned int)-1)
200 shared_connections[cd->shared_type] = NULL;
202 e_dbus_signal_handlers_free_all(cd);
204 if (cd->conn_name) free(cd->conn_name);
206 if (cd->idler) ecore_idle_enterer_del(cd->idler);
213 cb_main_wakeup(void *data)
215 E_DBus_Connection *cd;
220 if (!cd->idler) cd->idler = ecore_idle_enterer_add(e_dbus_idler, cd);
221 else DBG("already idling");
225 e_dbus_loop_wakeup(void)
227 static int dummy_event = 0;
229 /* post a dummy event to get the mainloop back to normal - this is
230 * needed because idlers are very special things that won't re-evaluate
231 * timers and other stuff while idelrs run - idle_exiters and enterers
232 * can do this safely, but not idlers. idelrs were meant to be used
233 * very sparingly for very special cases */
234 if (dummy_event == 0) dummy_event = ecore_event_type_new();
235 ecore_event_add(dummy_event, NULL, NULL, NULL);
239 cb_dispatch_status(DBusConnection *conn __UNUSED__, DBusDispatchStatus new_status, void *data)
241 E_DBus_Connection *cd;
243 DBG("dispatch status: %d!", new_status);
246 if (new_status == DBUS_DISPATCH_DATA_REMAINS && !cd->idler) cd->idler = ecore_idle_enterer_add(e_dbus_idler, cd);
248 else if (new_status != DBUS_DISPATCH_DATA_REMAINS && cd->idler)
250 ecore_idle_enterer_del(cd->idler);
252 e_dbus_loop_wakeup();
257 e_dbus_timeout_handler(void *data)
259 E_DBus_Timeout_Data *td;
263 if (dbus_timeout_get_enabled(td->timeout))
265 DBG("timeout_handler (not enabled, ending)");
267 return ECORE_CALLBACK_CANCEL;
270 DBG("timeout handler!");
271 dbus_timeout_handle(td->timeout);
272 return ECORE_CALLBACK_RENEW;
276 e_dbus_timeout_data_free(void *timeout_data)
278 E_DBus_Timeout_Data *td = timeout_data;
279 DBG("e_dbus_timeout_data_free");
280 if (td->handler) ecore_timer_del(td->handler);
285 cb_timeout_add(DBusTimeout *timeout, void *data)
287 E_DBus_Connection *cd;
288 E_DBus_Timeout_Data *td;
292 td = calloc(1, sizeof(E_DBus_Timeout_Data));
294 dbus_timeout_set_data(timeout, (void *)td, e_dbus_timeout_data_free);
296 td->interval = dbus_timeout_get_interval(timeout);
297 td->timeout = timeout;
299 if (dbus_timeout_get_enabled(timeout)) td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
300 td->cd->timeouts = eina_list_append(td->cd->timeouts, td->handler);
306 cb_timeout_del(DBusTimeout *timeout, void *data __UNUSED__)
308 E_DBus_Timeout_Data *td;
311 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
315 td->cd->timeouts = eina_list_remove(td->cd->timeouts, td->handler);
316 ecore_timer_del(td->handler);
320 /* Note: timeout data gets freed when the timeout itself is freed by dbus */
324 cb_timeout_toggle(DBusTimeout *timeout, void *data __UNUSED__)
326 E_DBus_Timeout_Data *td;
327 DBG("timeout toggle!");
329 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
331 if (dbus_timeout_get_enabled(td->timeout))
333 td->interval = dbus_timeout_get_interval(timeout);
334 td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
338 ecore_timer_del(td->handler);
346 cb_watch_add(DBusWatch *watch, void *data)
348 E_DBus_Connection *cd;
352 e_dbus_connection_data_watch_add(cd, watch);
358 cb_watch_del(DBusWatch *watch, void *data __UNUSED__)
360 E_DBus_Handler_Data *hd;
363 hd = (E_DBus_Handler_Data *)dbus_watch_get_data(watch);
364 e_dbus_fd_handler_del(hd);
368 cb_watch_toggle(DBusWatch *watch, void *data __UNUSED__)
370 E_DBus_Handler_Data *hd;
372 DBG("cb_watch_toggle");
373 hd = dbus_watch_get_data(watch);
377 hd->enabled = dbus_watch_get_enabled(watch);
379 INFO("watch %p is %sabled", hd, hd->enabled ? "en" : "dis");
380 if (hd->enabled) e_dbus_fd_handler_add(hd);
381 else e_dbus_fd_handler_del(hd);
385 e_dbus_message_free(void *data __UNUSED__, void *message)
387 dbus_message_unref(message);
390 static DBusHandlerResult
391 e_dbus_filter(DBusConnection *conn __UNUSED__, DBusMessage *message, void *user_data)
393 E_DBus_Connection *cd = user_data;
394 DBG("-----------------");
397 DBG("type: %s", dbus_message_type_to_string(dbus_message_get_type(message)));
398 DBG("path: %s", dbus_message_get_path(message));
399 DBG("interface: %s", dbus_message_get_interface(message));
400 DBG("member: %s", dbus_message_get_member(message));
401 DBG("sender: %s", dbus_message_get_sender(message));
403 switch (dbus_message_get_type(message))
405 case DBUS_MESSAGE_TYPE_METHOD_CALL:
406 DBG("signature: %s", dbus_message_get_signature(message));
408 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
409 DBG("reply serial %d", dbus_message_get_reply_serial(message));
411 case DBUS_MESSAGE_TYPE_ERROR:
412 DBG("error: %s", dbus_message_get_error_name(message));
414 case DBUS_MESSAGE_TYPE_SIGNAL:
415 dbus_message_ref(message);
417 if (cd->signal_dispatcher)
418 cd->signal_dispatcher(cd, message);
420 ecore_event_add(E_DBUS_EVENT_SIGNAL, message, e_dbus_message_free, NULL);
421 /* don't need to handle signals, they're for everyone who wants them */
422 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
427 DBG("-----------------");
429 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
432 int e_dbus_idler_active = 0;
435 e_dbus_idler(void *data)
437 E_DBus_Connection *cd;
440 if (DBUS_DISPATCH_COMPLETE == dbus_connection_get_dispatch_status(cd->conn))
442 DBG("done dispatching!");
444 return ECORE_CALLBACK_CANCEL;
446 e_dbus_idler_active++;
447 dbus_connection_ref(cd->conn);
449 dbus_connection_dispatch(cd->conn);
450 dbus_connection_unref(cd->conn);
451 e_dbus_idler_active--;
452 e_dbus_signal_handlers_clean(cd);
453 if (!e_dbus_idler_active && close_connection)
457 e_dbus_connection_close(cd);
458 } while (--close_connection);
460 e_dbus_loop_wakeup();
461 return ECORE_CALLBACK_RENEW;
464 EAPI E_DBus_Connection *
465 e_dbus_bus_get(DBusBusType type)
468 E_DBus_Connection *econn;
469 DBusConnection *conn;
471 /* each app only needs a single connection to either bus */
472 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
474 if (shared_connections[type])
476 e_dbus_connection_ref(shared_connections[type]);
477 return shared_connections[type];
481 dbus_error_init(&err);
483 conn = dbus_bus_get_private(type, &err);
484 if (dbus_error_is_set(&err))
486 ERR("Error connecting to bus: %s", err.message);
487 dbus_error_free(&err);
491 econn = e_dbus_connection_setup(conn);
494 ERR("Error setting up dbus connection.");
495 dbus_connection_close(conn);
496 dbus_connection_unref(conn);
500 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
502 econn->shared_type = type;
503 shared_connections[type] = econn;
505 dbus_error_free(&err);
506 e_dbus_connection_ref(econn);
510 EAPI E_DBus_Connection *
511 e_dbus_connection_setup(DBusConnection *conn)
513 E_DBus_Connection *cd;
515 cd = e_dbus_connection_new(conn);
516 if (!cd) return NULL;
518 /* connection_setup */
519 dbus_connection_set_exit_on_disconnect(cd->conn, EINA_FALSE);
520 dbus_connection_allocate_data_slot(&connection_slot);
522 dbus_connection_set_data(cd->conn, connection_slot, (void *)cd, e_dbus_connection_free);
523 dbus_connection_set_watch_functions(cd->conn,
530 dbus_connection_set_timeout_functions(cd->conn,
537 dbus_connection_set_wakeup_main_function(cd->conn, cb_main_wakeup, cd, NULL);
538 dbus_connection_set_dispatch_status_function(cd->conn, cb_dispatch_status, cd, NULL);
539 dbus_connection_add_filter(cd->conn, e_dbus_filter, cd, NULL);
541 cb_dispatch_status(cd->conn, dbus_connection_get_dispatch_status(cd->conn), cd);
548 e_dbus_connection_close(E_DBus_Connection *conn)
550 DBG("e_dbus_connection_close");
552 if (e_dbus_idler_active)
557 if (--(conn->refcount) != 0) return;
559 dbus_connection_free_data_slot(&connection_slot);
560 dbus_connection_remove_filter(conn->conn, e_dbus_filter, conn);
561 dbus_connection_set_watch_functions (conn->conn,
567 dbus_connection_set_timeout_functions (conn->conn,
573 dbus_connection_set_dispatch_status_function (conn->conn, NULL, NULL, NULL);
575 /* Idler functin must be cancelled when dbus connection is unreferenced */
578 ecore_idle_enterer_del(conn->idler);
582 dbus_connection_close(conn->conn);
583 dbus_connection_unref(conn->conn);
585 // Note: the E_DBus_Connection gets freed when the dbus_connection is cleaned up by the previous unref
589 e_dbus_connection_ref(E_DBus_Connection *conn)
595 e_dbus_connection_dbus_connection_get(E_DBus_Connection *conn)
603 if (++_edbus_init_count != 1)
604 return _edbus_init_count;
608 fprintf(stderr,"E-dbus: Enable to initialize eina\n");
609 return --_edbus_init_count;
612 _e_dbus_log_dom = eina_log_domain_register("e_dbus", E_DBUS_COLOR_DEFAULT);
613 if (_e_dbus_log_dom < 0)
615 EINA_LOG_ERR("Unable to create an 'e_dbus' log domain");
617 return --_edbus_init_count;
621 ERR("E-dbus: Unable to initialize ecore");
622 eina_log_domain_unregister(_e_dbus_log_dom);
623 _e_dbus_log_dom = -1;
625 return --_edbus_init_count;
629 E_DBUS_EVENT_SIGNAL = ecore_event_type_new();
630 e_dbus_object_init();
632 return _edbus_init_count;
636 e_dbus_shutdown(void)
638 if (--_edbus_init_count)
639 return _edbus_init_count;
641 e_dbus_object_shutdown();
643 eina_log_domain_unregister(_e_dbus_log_dom);
644 _e_dbus_log_dom = -1;
647 return _edbus_init_count;