10 #include "e_dbus_private.h"
12 static E_DBus_Version _version = { VMAJ, VMIN, VMIC, VREV };
13 EAPI E_DBus_Version *e_dbus_version = &_version;
15 #define NUM_BUS_TYPES 3
19 * listen for disconnected signal and clean up?
20 * listen for NameOwnerChanged signals for names we have SignalHandler's for
21 * remap SH to listen for signals from new owner
23 int _e_dbus_log_dom = -1;
24 static int connection_slot = -1;
26 static int _edbus_init_count = 0;
27 static int close_connection = 0;
28 EAPI int E_DBUS_EVENT_SIGNAL = 0;
30 static E_DBus_Connection *shared_connections[2] = {NULL, NULL};
32 typedef struct E_DBus_Handler_Data E_DBus_Handler_Data;
33 typedef struct E_DBus_Timeout_Data E_DBus_Timeout_Data;
36 struct E_DBus_Handler_Data
39 Ecore_Fd_Handler *fd_handler;
40 E_DBus_Connection *cd;
45 struct E_DBus_Timeout_Data
49 E_DBus_Connection *cd;
53 static Eina_Bool e_dbus_idler(void *data);
56 e_dbus_fd_handler_del(E_DBus_Handler_Data *hd)
58 if (!hd->fd_handler) return;
60 DBG("handler disabled");
61 hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
62 ecore_main_fd_handler_del(hd->fd_handler);
63 hd->fd_handler = NULL;
67 e_dbus_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
69 E_DBus_Handler_Data *hd;
70 unsigned int condition = 0;
72 DBG("fd handler (%p)!", fd_handler);
78 e_dbus_fd_handler_del(hd);
79 return ECORE_CALLBACK_CANCEL;
81 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) condition |= DBUS_WATCH_READABLE;
82 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) condition |= DBUS_WATCH_WRITABLE;
83 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) condition |= DBUS_WATCH_ERROR;
84 DBG("fdh || READ: %d, WRITE: %d",
85 (condition & DBUS_WATCH_READABLE) == DBUS_WATCH_READABLE,
86 (condition & DBUS_WATCH_WRITABLE) == DBUS_WATCH_WRITABLE);
88 if (condition & DBUS_WATCH_ERROR) DBG("DBUS watch error");
89 dbus_watch_handle(hd->watch, condition);
92 return ECORE_CALLBACK_RENEW;
96 e_dbus_fd_handler_add(E_DBus_Handler_Data *hd)
99 Ecore_Fd_Handler_Flags eflags;
101 Ecore_Fd_Handler *fdh;
103 if (hd->fd_handler) return;
104 dflags = dbus_watch_get_flags(hd->watch);
105 eflags = ECORE_FD_ERROR;
106 if (dflags & DBUS_WATCH_READABLE) eflags |= ECORE_FD_READ;
107 if (dflags & DBUS_WATCH_WRITABLE) eflags |= ECORE_FD_WRITE;
109 EINA_LIST_FOREACH(hd->cd->fd_handlers, l, fdh)
111 if (ecore_main_fd_handler_fd_get(fdh) == hd->fd) return;
114 DBG("fd handler add (%d)", hd->fd);
115 hd->fd_handler = ecore_main_fd_handler_add(hd->fd,
122 hd->cd->fd_handlers = eina_list_append(hd->cd->fd_handlers, hd->fd_handler);
127 e_dbus_handler_data_free(void *data)
129 E_DBus_Handler_Data *hd = data;
131 DBG("e_dbus_handler_data_free");
134 hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
135 ecore_main_fd_handler_del(hd->fd_handler);
141 e_dbus_connection_data_watch_add(E_DBus_Connection *cd, DBusWatch *watch)
143 E_DBus_Handler_Data *hd;
145 hd = calloc(1, sizeof(E_DBus_Handler_Data));
146 dbus_watch_set_data(watch, hd, e_dbus_handler_data_free);
150 hd->enabled = dbus_watch_get_enabled(watch);
151 #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)
152 hd->fd = dbus_watch_get_unix_fd(hd->watch);
154 hd->fd = dbus_watch_get_fd(hd->watch);
156 DBG("watch add (enabled: %d)", hd->enabled);
157 if (hd->enabled) e_dbus_fd_handler_add(hd);
160 static E_DBus_Connection *
161 e_dbus_connection_new(DBusConnection *conn)
163 E_DBus_Connection *cd;
164 const char *conn_name;
166 cd = calloc(1, sizeof(E_DBus_Connection));
167 if (!cd) return NULL;
170 conn_name = dbus_bus_get_unique_name(conn);
173 DBG("Connected! Name: %s", conn_name);
174 cd->conn_name = strdup(conn_name);
177 DBG("Not connected");
179 cd->shared_type = (unsigned int)-1;
180 cd->fd_handlers = NULL;
187 e_dbus_connection_free(void *data)
189 E_DBus_Connection *cd = data;
190 Ecore_Fd_Handler *fd_handler;
192 DBG("e_dbus_connection free!");
194 EINA_LIST_FREE(cd->fd_handlers, fd_handler)
195 ecore_main_fd_handler_del(fd_handler);
197 EINA_LIST_FREE(cd->timeouts, timer)
198 ecore_timer_del(timer);
200 if (cd->shared_type != (unsigned int)-1)
201 shared_connections[cd->shared_type] = NULL;
203 e_dbus_signal_handlers_free_all(cd);
205 if (cd->conn_name) free(cd->conn_name);
207 if (cd->idler) ecore_idle_enterer_del(cd->idler);
214 cb_main_wakeup(void *data)
216 E_DBus_Connection *cd;
221 if (!cd->idler) cd->idler = ecore_idle_enterer_add(e_dbus_idler, cd);
222 else DBG("already idling");
226 e_dbus_loop_wakeup(void)
228 static int dummy_event = 0;
230 /* post a dummy event to get the mainloop back to normal - this is
231 * needed because idlers are very special things that won't re-evaluate
232 * timers and other stuff while idelrs run - idle_exiters and enterers
233 * can do this safely, but not idlers. idelrs were meant to be used
234 * very sparingly for very special cases */
235 if (dummy_event == 0) dummy_event = ecore_event_type_new();
236 ecore_event_add(dummy_event, NULL, NULL, NULL);
240 cb_dispatch_status(DBusConnection *conn __UNUSED__, DBusDispatchStatus new_status, void *data)
242 E_DBus_Connection *cd;
244 DBG("dispatch status: %d!", new_status);
247 if (new_status == DBUS_DISPATCH_DATA_REMAINS && !cd->idler) cd->idler = ecore_idle_enterer_add(e_dbus_idler, cd);
249 else if (new_status != DBUS_DISPATCH_DATA_REMAINS && cd->idler)
251 ecore_idle_enterer_del(cd->idler);
253 e_dbus_loop_wakeup();
258 e_dbus_timeout_handler(void *data)
260 E_DBus_Timeout_Data *td;
264 if (dbus_timeout_get_enabled(td->timeout))
266 DBG("timeout_handler (not enabled, ending)");
268 return ECORE_CALLBACK_CANCEL;
271 DBG("timeout handler!");
272 dbus_timeout_handle(td->timeout);
273 return ECORE_CALLBACK_RENEW;
277 e_dbus_timeout_data_free(void *timeout_data)
279 E_DBus_Timeout_Data *td = timeout_data;
280 DBG("e_dbus_timeout_data_free");
281 if (td->handler) ecore_timer_del(td->handler);
286 cb_timeout_add(DBusTimeout *timeout, void *data)
288 E_DBus_Connection *cd;
289 E_DBus_Timeout_Data *td;
293 td = calloc(1, sizeof(E_DBus_Timeout_Data));
295 dbus_timeout_set_data(timeout, (void *)td, e_dbus_timeout_data_free);
297 td->interval = dbus_timeout_get_interval(timeout);
298 td->timeout = timeout;
300 if (dbus_timeout_get_enabled(timeout)) td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
301 td->cd->timeouts = eina_list_append(td->cd->timeouts, td->handler);
307 cb_timeout_del(DBusTimeout *timeout, void *data __UNUSED__)
309 E_DBus_Timeout_Data *td;
312 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
316 td->cd->timeouts = eina_list_remove(td->cd->timeouts, td->handler);
317 ecore_timer_del(td->handler);
321 /* Note: timeout data gets freed when the timeout itself is freed by dbus */
325 cb_timeout_toggle(DBusTimeout *timeout, void *data __UNUSED__)
327 E_DBus_Timeout_Data *td;
328 DBG("timeout toggle!");
330 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
332 if (dbus_timeout_get_enabled(td->timeout))
334 td->interval = dbus_timeout_get_interval(timeout);
335 td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
339 ecore_timer_del(td->handler);
347 cb_watch_add(DBusWatch *watch, void *data)
349 E_DBus_Connection *cd;
353 e_dbus_connection_data_watch_add(cd, watch);
359 cb_watch_del(DBusWatch *watch, void *data __UNUSED__)
361 E_DBus_Handler_Data *hd;
364 hd = (E_DBus_Handler_Data *)dbus_watch_get_data(watch);
365 e_dbus_fd_handler_del(hd);
369 cb_watch_toggle(DBusWatch *watch, void *data __UNUSED__)
371 E_DBus_Handler_Data *hd;
373 DBG("cb_watch_toggle");
374 hd = dbus_watch_get_data(watch);
378 hd->enabled = dbus_watch_get_enabled(watch);
380 INFO("watch %p is %sabled", hd, hd->enabled ? "en" : "dis");
381 if (hd->enabled) e_dbus_fd_handler_add(hd);
382 else e_dbus_fd_handler_del(hd);
386 e_dbus_message_free(void *data __UNUSED__, void *message)
388 dbus_message_unref(message);
391 static DBusHandlerResult
392 e_dbus_filter(DBusConnection *conn __UNUSED__, DBusMessage *message, void *user_data)
394 E_DBus_Connection *cd = user_data;
395 DBG("-----------------");
398 DBG("type: %s", dbus_message_type_to_string(dbus_message_get_type(message)));
399 DBG("path: %s", dbus_message_get_path(message));
400 DBG("interface: %s", dbus_message_get_interface(message));
401 DBG("member: %s", dbus_message_get_member(message));
402 DBG("sender: %s", dbus_message_get_sender(message));
404 switch (dbus_message_get_type(message))
406 case DBUS_MESSAGE_TYPE_METHOD_CALL:
407 DBG("signature: %s", dbus_message_get_signature(message));
409 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
410 DBG("reply serial %d", dbus_message_get_reply_serial(message));
412 case DBUS_MESSAGE_TYPE_ERROR:
413 DBG("error: %s", dbus_message_get_error_name(message));
415 case DBUS_MESSAGE_TYPE_SIGNAL:
416 dbus_message_ref(message);
418 if (cd->signal_dispatcher)
419 cd->signal_dispatcher(cd, message);
421 ecore_event_add(E_DBUS_EVENT_SIGNAL, message, e_dbus_message_free, NULL);
422 /* don't need to handle signals, they're for everyone who wants them */
423 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
428 DBG("-----------------");
430 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
433 int e_dbus_idler_active = 0;
436 e_dbus_idler(void *data)
438 E_DBus_Connection *cd;
441 if (DBUS_DISPATCH_COMPLETE == dbus_connection_get_dispatch_status(cd->conn))
443 DBG("done dispatching!");
445 return ECORE_CALLBACK_CANCEL;
447 e_dbus_idler_active++;
448 dbus_connection_ref(cd->conn);
450 dbus_connection_dispatch(cd->conn);
451 dbus_connection_unref(cd->conn);
452 e_dbus_idler_active--;
453 e_dbus_signal_handlers_clean(cd);
454 if (!e_dbus_idler_active && close_connection)
458 e_dbus_connection_close(cd);
459 } while (--close_connection);
461 e_dbus_loop_wakeup();
462 return ECORE_CALLBACK_RENEW;
465 EAPI E_DBus_Connection *
466 e_dbus_bus_get(DBusBusType type)
469 E_DBus_Connection *econn;
470 DBusConnection *conn;
472 /* each app only needs a single connection to either bus */
473 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
475 if (shared_connections[type])
477 e_dbus_connection_ref(shared_connections[type]);
478 return shared_connections[type];
482 dbus_error_init(&err);
484 conn = dbus_bus_get_private(type, &err);
485 if (dbus_error_is_set(&err))
487 ERR("Error connecting to bus: %s", err.message);
488 dbus_error_free(&err);
492 econn = e_dbus_connection_setup(conn);
495 ERR("Error setting up dbus connection.");
496 dbus_connection_close(conn);
497 dbus_connection_unref(conn);
501 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
503 econn->shared_type = type;
504 shared_connections[type] = econn;
506 dbus_error_free(&err);
507 e_dbus_connection_ref(econn);
511 EAPI E_DBus_Connection *
512 e_dbus_connection_setup(DBusConnection *conn)
514 E_DBus_Connection *cd;
516 cd = e_dbus_connection_new(conn);
517 if (!cd) return NULL;
519 /* connection_setup */
520 dbus_connection_set_exit_on_disconnect(cd->conn, EINA_FALSE);
521 dbus_connection_allocate_data_slot(&connection_slot);
523 dbus_connection_set_data(cd->conn, connection_slot, (void *)cd, e_dbus_connection_free);
524 dbus_connection_set_watch_functions(cd->conn,
531 dbus_connection_set_timeout_functions(cd->conn,
538 dbus_connection_set_wakeup_main_function(cd->conn, cb_main_wakeup, cd, NULL);
539 dbus_connection_set_dispatch_status_function(cd->conn, cb_dispatch_status, cd, NULL);
540 dbus_connection_add_filter(cd->conn, e_dbus_filter, cd, NULL);
542 cb_dispatch_status(cd->conn, dbus_connection_get_dispatch_status(cd->conn), cd);
549 e_dbus_connection_close(E_DBus_Connection *conn)
551 DBG("e_dbus_connection_close");
553 if (e_dbus_idler_active)
558 if (--(conn->refcount) != 0) return;
560 dbus_connection_free_data_slot(&connection_slot);
561 dbus_connection_remove_filter(conn->conn, e_dbus_filter, conn);
562 dbus_connection_set_watch_functions (conn->conn,
568 dbus_connection_set_timeout_functions (conn->conn,
574 dbus_connection_set_dispatch_status_function (conn->conn, NULL, NULL, NULL);
576 /* Idler functin must be cancelled when dbus connection is unreferenced */
579 ecore_idle_enterer_del(conn->idler);
583 dbus_connection_close(conn->conn);
584 dbus_connection_unref(conn->conn);
586 // Note: the E_DBus_Connection gets freed when the dbus_connection is cleaned up by the previous unref
590 e_dbus_connection_ref(E_DBus_Connection *conn)
596 e_dbus_connection_dbus_connection_get(E_DBus_Connection *conn)
604 if (++_edbus_init_count != 1)
605 return _edbus_init_count;
609 fprintf(stderr,"E-dbus: Enable to initialize eina\n");
610 return --_edbus_init_count;
613 _e_dbus_log_dom = eina_log_domain_register("e_dbus", E_DBUS_COLOR_DEFAULT);
614 if (_e_dbus_log_dom < 0)
616 EINA_LOG_ERR("Unable to create an 'e_dbus' log domain");
618 return --_edbus_init_count;
622 ERR("E-dbus: Unable to initialize ecore");
623 eina_log_domain_unregister(_e_dbus_log_dom);
624 _e_dbus_log_dom = -1;
626 return --_edbus_init_count;
630 E_DBUS_EVENT_SIGNAL = ecore_event_type_new();
631 e_dbus_object_init();
633 return _edbus_init_count;
637 e_dbus_shutdown(void)
639 if (--_edbus_init_count)
640 return _edbus_init_count;
642 e_dbus_object_shutdown();
644 eina_log_domain_unregister(_e_dbus_log_dom);
645 _e_dbus_log_dom = -1;
648 return _edbus_init_count;