14 #include "e_dbus_private.h"
16 static E_DBus_Version _version = { VMAJ, VMIN, VMIC, VREV };
17 EAPI E_DBus_Version *e_dbus_version = &_version;
19 #define NUM_BUS_TYPES 3
23 * listen for disconnected signal and clean up?
25 int _e_dbus_log_dom = -1;
26 static int connection_slot = -1;
28 static int _edbus_init_count = 0;
29 static int close_connection = 0;
30 EAPI int E_DBUS_DOMAIN_GLOBAL = 0;
31 EAPI int E_DBUS_EVENT_SIGNAL = 0;
33 static E_DBus_Connection *shared_connections[2] = {NULL, NULL};
35 typedef struct E_DBus_Handler_Data E_DBus_Handler_Data;
36 typedef struct E_DBus_Timeout_Data E_DBus_Timeout_Data;
39 struct E_DBus_Handler_Data
42 Ecore_Fd_Handler *fd_handler;
43 E_DBus_Connection *cd;
48 struct E_DBus_Timeout_Data
52 E_DBus_Connection *cd;
56 static Eina_Bool e_dbus_idler(void *data);
59 e_dbus_fd_handler_del(E_DBus_Handler_Data *hd)
61 if (!hd->fd_handler) return;
63 DBG("handler disabled");
64 hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
65 ecore_main_fd_handler_del(hd->fd_handler);
66 hd->fd_handler = NULL;
70 e_dbus_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
72 E_DBus_Handler_Data *hd;
73 unsigned int condition = 0;
75 DBG("fd handler (%p)!", fd_handler);
81 e_dbus_fd_handler_del(hd);
82 return ECORE_CALLBACK_CANCEL;
84 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) condition |= DBUS_WATCH_READABLE;
85 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) condition |= DBUS_WATCH_WRITABLE;
86 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) condition |= DBUS_WATCH_ERROR;
87 DBG("fdh || READ: %d, WRITE: %d",
88 (condition & DBUS_WATCH_READABLE) == DBUS_WATCH_READABLE,
89 (condition & DBUS_WATCH_WRITABLE) == DBUS_WATCH_WRITABLE);
91 if (condition & DBUS_WATCH_ERROR) DBG("DBUS watch error");
92 dbus_watch_handle(hd->watch, condition);
95 return ECORE_CALLBACK_RENEW;
99 e_dbus_fd_handler_add(E_DBus_Handler_Data *hd)
102 Ecore_Fd_Handler_Flags eflags;
104 Ecore_Fd_Handler *fdh;
106 if (hd->fd_handler) return;
107 dflags = dbus_watch_get_flags(hd->watch);
108 eflags = ECORE_FD_ERROR;
109 if (dflags & DBUS_WATCH_READABLE) eflags |= ECORE_FD_READ;
110 if (dflags & DBUS_WATCH_WRITABLE) eflags |= ECORE_FD_WRITE;
112 EINA_LIST_FOREACH(hd->cd->fd_handlers, l, fdh)
114 if (ecore_main_fd_handler_fd_get(fdh) == hd->fd) return;
117 DBG("fd handler add (%d)", hd->fd);
118 hd->fd_handler = ecore_main_fd_handler_add(hd->fd,
125 hd->cd->fd_handlers = eina_list_append(hd->cd->fd_handlers, hd->fd_handler);
130 e_dbus_handler_data_free(void *data)
132 E_DBus_Handler_Data *hd = data;
134 DBG("e_dbus_handler_data_free");
137 hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
138 ecore_main_fd_handler_del(hd->fd_handler);
144 e_dbus_connection_data_watch_add(E_DBus_Connection *cd, DBusWatch *watch)
146 E_DBus_Handler_Data *hd;
148 hd = calloc(1, sizeof(E_DBus_Handler_Data));
149 dbus_watch_set_data(watch, hd, e_dbus_handler_data_free);
153 hd->enabled = dbus_watch_get_enabled(watch);
154 #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)
155 hd->fd = dbus_watch_get_unix_fd(hd->watch);
157 hd->fd = dbus_watch_get_fd(hd->watch);
159 DBG("watch add (enabled: %d)", hd->enabled);
160 if (hd->enabled) e_dbus_fd_handler_add(hd);
163 static E_DBus_Connection *
164 e_dbus_connection_new(DBusConnection *conn)
166 E_DBus_Connection *cd;
167 const char *conn_name;
169 cd = calloc(1, sizeof(E_DBus_Connection));
170 if (!cd) return NULL;
173 conn_name = dbus_bus_get_unique_name(conn);
176 DBG("Connected! Name: %s", conn_name);
177 cd->conn_name = strdup(conn_name);
180 DBG("Not connected");
182 cd->shared_type = (unsigned int)-1;
183 cd->fd_handlers = NULL;
190 e_dbus_connection_free(void *data)
192 E_DBus_Connection *cd = data;
193 Ecore_Fd_Handler *fd_handler;
195 DBG("e_dbus_connection free!");
197 EINA_LIST_FREE(cd->fd_handlers, fd_handler)
198 ecore_main_fd_handler_del(fd_handler);
200 EINA_LIST_FREE(cd->timeouts, timer)
201 ecore_timer_del(timer);
203 if (cd->shared_type != (unsigned int)-1)
204 shared_connections[cd->shared_type] = NULL;
206 e_dbus_signal_handlers_free_all(cd);
208 if (cd->conn_name) free(cd->conn_name);
210 if (cd->idler) ecore_idler_del(cd->idler);
216 cb_dispatch_status(DBusConnection *conn __UNUSED__, DBusDispatchStatus new_status, void *data)
218 E_DBus_Connection *cd;
220 DBG("dispatch status: %d!", new_status);
223 if (new_status == DBUS_DISPATCH_DATA_REMAINS && !cd->idler)
224 cd->idler = ecore_idler_add(e_dbus_idler, cd);
225 else if (new_status != DBUS_DISPATCH_DATA_REMAINS && cd->idler)
227 ecore_idler_del(cd->idler);
233 e_dbus_timeout_handler(void *data)
235 E_DBus_Timeout_Data *td;
239 if (!dbus_timeout_get_enabled(td->timeout))
241 DBG("timeout_handler (not enabled, ending)");
243 return ECORE_CALLBACK_CANCEL;
246 DBG("timeout handler!");
247 dbus_timeout_handle(td->timeout);
248 return ECORE_CALLBACK_CANCEL;
252 e_dbus_timeout_data_free(void *timeout_data)
254 E_DBus_Timeout_Data *td = timeout_data;
255 DBG("e_dbus_timeout_data_free");
256 if (td->handler) ecore_timer_del(td->handler);
261 cb_timeout_add(DBusTimeout *timeout, void *data)
263 E_DBus_Connection *cd;
264 E_DBus_Timeout_Data *td;
268 td = calloc(1, sizeof(E_DBus_Timeout_Data));
270 dbus_timeout_set_data(timeout, (void *)td, e_dbus_timeout_data_free);
272 td->interval = dbus_timeout_get_interval(timeout);
273 td->timeout = timeout;
275 if (dbus_timeout_get_enabled(timeout)) td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
276 td->cd->timeouts = eina_list_append(td->cd->timeouts, td->handler);
282 cb_timeout_del(DBusTimeout *timeout, void *data __UNUSED__)
284 E_DBus_Timeout_Data *td;
287 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
291 td->cd->timeouts = eina_list_remove(td->cd->timeouts, td->handler);
292 ecore_timer_del(td->handler);
296 /* Note: timeout data gets freed when the timeout itself is freed by dbus */
300 cb_timeout_toggle(DBusTimeout *timeout, void *data __UNUSED__)
302 E_DBus_Timeout_Data *td;
303 DBG("timeout toggle!");
305 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
307 if (dbus_timeout_get_enabled(td->timeout))
309 td->interval = dbus_timeout_get_interval(timeout);
310 td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
314 ecore_timer_del(td->handler);
322 cb_watch_add(DBusWatch *watch, void *data)
324 E_DBus_Connection *cd;
328 e_dbus_connection_data_watch_add(cd, watch);
334 cb_watch_del(DBusWatch *watch, void *data __UNUSED__)
336 E_DBus_Handler_Data *hd;
339 hd = (E_DBus_Handler_Data *)dbus_watch_get_data(watch);
340 e_dbus_fd_handler_del(hd);
344 cb_watch_toggle(DBusWatch *watch, void *data __UNUSED__)
346 E_DBus_Handler_Data *hd;
348 DBG("cb_watch_toggle");
349 hd = dbus_watch_get_data(watch);
353 hd->enabled = dbus_watch_get_enabled(watch);
355 INFO("watch %p is %sabled", hd, hd->enabled ? "en" : "dis");
356 if (hd->enabled) e_dbus_fd_handler_add(hd);
357 else e_dbus_fd_handler_del(hd);
361 e_dbus_message_free(void *data __UNUSED__, void *message)
363 dbus_message_unref(message);
366 static DBusHandlerResult
367 e_dbus_filter(DBusConnection *conn __UNUSED__, DBusMessage *message, void *user_data)
369 E_DBus_Connection *cd = user_data;
370 DBG("-----------------");
373 DBG("type: %s", dbus_message_type_to_string(dbus_message_get_type(message)));
374 DBG("path: %s", dbus_message_get_path(message));
375 DBG("interface: %s", dbus_message_get_interface(message));
376 DBG("member: %s", dbus_message_get_member(message));
377 DBG("sender: %s", dbus_message_get_sender(message));
379 switch (dbus_message_get_type(message))
381 case DBUS_MESSAGE_TYPE_METHOD_CALL:
382 DBG("signature: %s", dbus_message_get_signature(message));
384 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
385 DBG("reply serial %d", dbus_message_get_reply_serial(message));
387 case DBUS_MESSAGE_TYPE_ERROR:
388 DBG("error: %s", dbus_message_get_error_name(message));
390 case DBUS_MESSAGE_TYPE_SIGNAL:
391 dbus_message_ref(message);
392 if (cd->signal_dispatcher) cd->signal_dispatcher(cd, message);
393 ecore_event_add(E_DBUS_EVENT_SIGNAL, message, e_dbus_message_free, NULL);
398 DBG("-----------------");
400 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
403 int e_dbus_idler_active = 0;
406 e_dbus_idler(void *data)
408 E_DBus_Connection *cd;
411 if (DBUS_DISPATCH_COMPLETE == dbus_connection_get_dispatch_status(cd->conn))
413 DBG("done dispatching!");
415 return ECORE_CALLBACK_CANCEL;
417 e_dbus_idler_active++;
418 dbus_connection_ref(cd->conn);
420 dbus_connection_dispatch(cd->conn);
421 dbus_connection_unref(cd->conn);
422 e_dbus_idler_active--;
423 e_dbus_signal_handlers_clean(cd);
424 if (!e_dbus_idler_active && close_connection)
428 e_dbus_connection_close(cd);
429 } while (--close_connection);
431 return ECORE_CALLBACK_RENEW;
434 EAPI E_DBus_Connection *
435 e_dbus_bus_get(DBusBusType type)
438 E_DBus_Connection *econn;
439 DBusConnection *conn;
441 /* each app only needs a single connection to either bus */
442 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
444 if (shared_connections[type])
446 e_dbus_connection_ref(shared_connections[type]);
447 return shared_connections[type];
451 dbus_error_init(&err);
453 conn = dbus_bus_get_private(type, &err);
454 if (dbus_error_is_set(&err))
456 ERR("Error connecting to bus: %s", err.message);
457 dbus_error_free(&err);
461 econn = e_dbus_connection_setup(conn);
464 ERR("Error setting up dbus connection.");
465 dbus_connection_close(conn);
466 dbus_connection_unref(conn);
470 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
472 econn->shared_type = type;
473 shared_connections[type] = econn;
475 dbus_error_free(&err);
476 e_dbus_connection_ref(econn);
480 EAPI E_DBus_Connection *
481 e_dbus_connection_setup(DBusConnection *conn)
483 E_DBus_Connection *cd;
485 cd = e_dbus_connection_new(conn);
486 if (!cd) return NULL;
488 /* connection_setup */
489 dbus_connection_set_exit_on_disconnect(cd->conn, EINA_FALSE);
490 dbus_connection_allocate_data_slot(&connection_slot);
492 dbus_connection_set_data(cd->conn, connection_slot, (void *)cd, e_dbus_connection_free);
493 dbus_connection_set_watch_functions(cd->conn,
500 dbus_connection_set_timeout_functions(cd->conn,
507 dbus_connection_set_dispatch_status_function(cd->conn, cb_dispatch_status, cd, NULL);
508 dbus_connection_add_filter(cd->conn, e_dbus_filter, cd, NULL);
510 cb_dispatch_status(cd->conn, dbus_connection_get_dispatch_status(cd->conn), cd);
517 e_dbus_connection_close(E_DBus_Connection *conn)
520 DBG("e_dbus_connection_close");
522 if (e_dbus_idler_active)
527 if (--(conn->refcount) != 0) return;
529 dbus_connection_free_data_slot(&connection_slot);
530 dbus_connection_remove_filter(conn->conn, e_dbus_filter, conn);
531 dbus_connection_set_watch_functions (conn->conn,
537 dbus_connection_set_timeout_functions (conn->conn,
543 dbus_connection_set_dispatch_status_function (conn->conn, NULL, NULL, NULL);
545 /* Idler functin must be cancelled when dbus connection is unreferenced */
548 ecore_idler_del(conn->idler);
552 dbus_connection_close(conn->conn);
553 dbus_connection_unref(conn->conn);
555 // Note: the E_DBus_Connection gets freed when the dbus_connection is cleaned up by the previous unref
559 e_dbus_connection_ref(E_DBus_Connection *conn)
561 EINA_SAFETY_ON_NULL_RETURN(conn);
566 e_dbus_connection_dbus_connection_get(E_DBus_Connection *conn)
568 EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
575 if (++_edbus_init_count != 1)
576 return _edbus_init_count;
580 fprintf(stderr,"E-dbus: Enable to initialize eina\n");
581 return --_edbus_init_count;
584 _e_dbus_log_dom = eina_log_domain_register("e_dbus", E_DBUS_COLOR_DEFAULT);
585 if (_e_dbus_log_dom < 0)
587 EINA_LOG_ERR("Unable to create an 'e_dbus' log domain");
589 return --_edbus_init_count;
593 ERR("E-dbus: Unable to initialize ecore");
594 eina_log_domain_unregister(_e_dbus_log_dom);
595 _e_dbus_log_dom = -1;
597 return --_edbus_init_count;
600 E_DBUS_DOMAIN_GLOBAL = _e_dbus_log_dom;
601 E_DBUS_EVENT_SIGNAL = ecore_event_type_new();
602 e_dbus_object_init();
604 return _edbus_init_count;
608 e_dbus_shutdown(void)
610 if (_edbus_init_count <= 0)
612 EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
615 if (--_edbus_init_count)
616 return _edbus_init_count;
618 e_dbus_object_shutdown();
620 eina_log_domain_unregister(_e_dbus_log_dom);
621 _e_dbus_log_dom = -1;
624 return _edbus_init_count;