2 #include "e_dbus_private.h"
11 #include <Ecore_Data.h>
13 #define NUM_BUS_TYPES 3
17 * listen for disconnected signal and clean up?
18 * listen for NameOwnerChanged signals for names we have SignalHandler's for
19 * remap SH to listen for signals from new owner
22 static int connection_slot = -1;
25 EAPI int E_DBUS_EVENT_SIGNAL = 0;
27 static E_DBus_Connection *shared_connections[2] = {NULL, NULL};
29 typedef struct E_DBus_Handler_Data E_DBus_Handler_Data;
30 typedef struct E_DBus_Timeout_Data E_DBus_Timeout_Data;
33 struct E_DBus_Handler_Data
36 Ecore_Fd_Handler *fd_handler;
37 E_DBus_Connection *cd;
42 struct E_DBus_Timeout_Data
46 E_DBus_Connection *cd;
50 static int e_dbus_idler(void *data);
53 e_dbus_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
55 E_DBus_Handler_Data *hd;
57 unsigned int condition = 0;
59 DEBUG(5, "fd handler (%ld)!\n", (long int)fd_handler);
64 DEBUG(5, "handler disabled\n");
65 if (hd->fd_handler) ecore_main_fd_handler_del(hd->fd_handler);
66 hd->fd_handler = NULL;
72 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) condition |= DBUS_WATCH_READABLE;
73 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) condition |= DBUS_WATCH_WRITABLE;
74 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) condition |= DBUS_WATCH_ERROR;
76 if (condition & DBUS_WATCH_ERROR) DEBUG(5, "DBUS watch error\n");
77 dbus_watch_handle(hd->watch, condition);
85 e_dbus_fd_handler_add(E_DBus_Handler_Data *hd)
88 Ecore_Fd_Handler_Flags eflags;
90 if (hd->fd_handler) return;
91 DEBUG(5, "fd handler add (%d)\n", hd->fd);
93 dflags = dbus_watch_get_flags(hd->watch);
94 eflags = ECORE_FD_ERROR;
95 if (dflags & DBUS_WATCH_READABLE) eflags |= ECORE_FD_READ;
96 if (dflags & DBUS_WATCH_WRITABLE) eflags |= ECORE_FD_WRITE;
99 hd->fd_handler = ecore_main_fd_handler_add(hd->fd,
106 ecore_list_append(hd->cd->fd_handlers, hd->fd_handler);
111 e_dbus_handler_data_free(void *data)
113 E_DBus_Handler_Data *hd = data;
115 DEBUG(5, "e_dbus_handler_data_free\n");
118 if (ecore_list_goto(hd->cd->fd_handlers, hd->fd_handler))
119 ecore_list_remove(hd->cd->fd_handlers);
120 ecore_main_fd_handler_del(hd->fd_handler);
126 e_dbus_connection_data_watch_add(E_DBus_Connection *cd, DBusWatch *watch)
128 E_DBus_Handler_Data *hd;
130 hd = calloc(1, sizeof(E_DBus_Handler_Data));
131 dbus_watch_set_data(watch, hd, e_dbus_handler_data_free);
135 hd->enabled = dbus_watch_get_enabled(watch);
136 hd->fd = dbus_watch_get_unix_fd(hd->watch);
137 DEBUG(5, "watch add (enabled: %d)\n", hd->enabled);
138 if (hd->enabled) e_dbus_fd_handler_add(hd);
141 static E_DBus_Connection *
142 e_dbus_connection_new(DBusConnection *conn)
144 E_DBus_Connection *cd;
145 const char *conn_name;
147 cd = calloc(1, sizeof(E_DBus_Connection));
148 if (!cd) return NULL;
151 conn_name = dbus_bus_get_unique_name(conn);
154 DEBUG(1, "Connected! Name: %s\n", conn_name);
155 cd->conn_name = strdup(conn_name);
158 DEBUG(1, "Not connected\n");
160 cd->shared_type = -1;
161 cd->fd_handlers = ecore_list_new();
162 cd->timeouts = ecore_list_new();
168 e_dbus_connection_free(void *data)
170 E_DBus_Connection *cd = data;
171 Ecore_Fd_Handler *fd_handler;
173 DEBUG(5, "e_dbus_connection free!\n");
175 ecore_list_first_goto(cd->fd_handlers);
176 while ((fd_handler = ecore_list_next(cd->fd_handlers)))
177 ecore_main_fd_handler_del(fd_handler);
178 ecore_list_destroy(cd->fd_handlers);
180 ecore_list_first_goto(cd->timeouts);
181 while ((timer = ecore_list_next(cd->timeouts)))
182 ecore_timer_del(timer);
183 ecore_list_destroy(cd->timeouts);
185 if (cd->shared_type != -1)
186 shared_connections[cd->shared_type] = NULL;
188 if (cd->signal_handlers)
189 ecore_list_destroy(cd->signal_handlers);
191 if (cd->conn_name) free(cd->conn_name);
193 if (cd->idler) ecore_idler_del(cd->idler);
200 cb_main_wakeup(void *data)
202 E_DBus_Connection *cd;
203 DEBUG(5, "wakeup main!\n");
207 if (!cd->idler) cd->idler = ecore_idler_add(e_dbus_idler, cd);
208 else DEBUG(1, "already idling\n");
212 cb_dispatch_status(DBusConnection *conn, DBusDispatchStatus new_status, void *data)
214 E_DBus_Connection *cd;
216 DEBUG(5, "dispatch status: %d!\n", new_status);
219 if (new_status == DBUS_DISPATCH_DATA_REMAINS && !cd->idler) cd->idler = ecore_idler_add(e_dbus_idler, cd);
221 else if (new_status != DBUS_DISPATCH_DATA_REMAINS && cd->idler)
223 static int dummy_event = 0;
225 ecore_idler_del(cd->idler);
227 /* post a dummy event to get the mainloop back to normal - this is
228 * needed because idlers are very special things that won't re-evaluate
229 * timers and other stuff while idelrs run - idle_exiters and enterers
230 * can do this safely, but not idlers. idelrs were meant to be used
231 * very sparingly for very special cases */
232 if (dummy_event == 0) dummy_event = ecore_event_type_new();
233 ecore_event_add(dummy_event, NULL, NULL, NULL);
238 e_dbus_timeout_handler(void *data)
240 E_DBus_Timeout_Data *td;
244 if (dbus_timeout_get_enabled(td->timeout))
246 DEBUG(5, "timeout_handler (not enabled, ending)\n");
251 DEBUG(5, "timeout handler!\n");
252 dbus_timeout_handle(td->timeout);
257 e_dbus_timeout_data_free(void *timeout_data)
259 E_DBus_Timeout_Data *td = timeout_data;
260 DEBUG(5, "e_dbus_timeout_data_free\n");
261 if (td->handler) ecore_timer_del(td->handler);
266 cb_timeout_add(DBusTimeout *timeout, void *data)
268 E_DBus_Connection *cd;
269 E_DBus_Timeout_Data *td;
272 DEBUG(5, "timeout add!\n");
273 td = calloc(1, sizeof(E_DBus_Timeout_Data));
275 dbus_timeout_set_data(timeout, (void *)td, e_dbus_timeout_data_free);
277 td->interval = dbus_timeout_get_interval(timeout);
278 td->timeout = timeout;
280 if (dbus_timeout_get_enabled(timeout)) td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
281 ecore_list_append(td->cd->timeouts, td->handler);
287 cb_timeout_del(DBusTimeout *timeout, void *data)
289 E_DBus_Timeout_Data *td;
290 DEBUG(5, "timeout del!\n");
292 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
296 if (ecore_list_goto(td->cd->timeouts, td->handler))
297 ecore_list_remove(td->cd->timeouts);
298 ecore_timer_del(td->handler);
302 /* Note: timeout data gets freed when the timeout itself is freed by dbus */
306 cb_timeout_toggle(DBusTimeout *timeout, void *data)
308 E_DBus_Timeout_Data *td;
309 DEBUG(5, "timeout toggle!\n");
311 td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
313 if (dbus_timeout_get_enabled(td->timeout))
315 td->interval = dbus_timeout_get_interval(timeout);
316 td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
320 ecore_timer_del(td->handler);
328 cb_watch_add(DBusWatch *watch, void *data)
330 E_DBus_Connection *cd;
333 DEBUG(5, "cb_watch_add\n");
334 e_dbus_connection_data_watch_add(cd, watch);
340 cb_watch_del(DBusWatch *watch, void *data)
342 E_DBus_Connection *cd;
343 E_DBus_Handler_Data *hd;
346 DEBUG(5, "cb_watch_del\n");
347 hd = (E_DBus_Handler_Data *)dbus_watch_get_data(watch);
351 if (ecore_list_goto(hd->cd->fd_handlers, hd->fd_handler))
352 ecore_list_remove(hd->cd->fd_handlers);
353 ecore_main_fd_handler_del(hd->fd_handler);
354 hd->fd_handler = NULL;
359 cb_watch_toggle(DBusWatch *watch, void *data)
361 E_DBus_Handler_Data *hd;
363 DEBUG(5, "cb_watch_toggle\n");
364 hd = dbus_watch_get_data(watch);
368 hd->enabled = dbus_watch_get_enabled(watch);
370 if (hd->enabled) e_dbus_fd_handler_add(hd);
374 e_dbus_message_free(void *data, void *message)
376 dbus_message_unref(message);
379 static DBusHandlerResult
380 e_dbus_filter(DBusConnection *conn, DBusMessage *message, void *user_data)
382 E_DBus_Connection *cd = user_data;
383 DEBUG(3, "-----------------\nMessage!\n\n");
385 DEBUG(3, "type: %s\n", dbus_message_type_to_string(dbus_message_get_type(message)));
386 DEBUG(3, "path: %s\n", dbus_message_get_path(message));
387 DEBUG(3, "interface: %s\n", dbus_message_get_interface(message));
388 DEBUG(3, "member: %s\n", dbus_message_get_member(message));
389 DEBUG(3, "sender: %s\n", dbus_message_get_sender(message));
391 switch (dbus_message_get_type(message))
393 case DBUS_MESSAGE_TYPE_METHOD_CALL:
394 DEBUG(3, "signature: %s\n", dbus_message_get_signature(message));
396 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
397 DEBUG(3, "reply serial %d\n", dbus_message_get_reply_serial(message));
399 case DBUS_MESSAGE_TYPE_ERROR:
400 DEBUG(3, "error: %s\n", dbus_message_get_error_name(message));
402 case DBUS_MESSAGE_TYPE_SIGNAL:
403 dbus_message_ref(message);
405 if (cd->signal_dispatcher)
406 cd->signal_dispatcher(cd, message);
408 ecore_event_add(E_DBUS_EVENT_SIGNAL, message, e_dbus_message_free, NULL);
409 /* don't need to handle signals, they're for everyone who wants them */
410 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
415 DEBUG(3, "-----------------\n\n");
417 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
420 int e_dbus_idler_active = 0;
423 e_dbus_idler(void *data)
425 E_DBus_Connection *cd;
428 if (DBUS_DISPATCH_COMPLETE == dbus_connection_get_dispatch_status(cd->conn))
430 DEBUG(5, "done dispatching!\n");
434 e_dbus_idler_active++;
435 dbus_connection_ref(cd->conn);
436 DEBUG(5, "dispatch!\n");
437 dbus_connection_dispatch(cd->conn);
438 dbus_connection_unref(cd->conn);
439 e_dbus_signal_handlers_clean(cd);
440 e_dbus_idler_active--;
445 * Retrieve a connection to the bus and integrate it with the ecore main loop.
446 * @param type the type of bus to connect to, e.g. DBUS_BUS_SYSTEM or DBUS_BUS_SESSION
448 EAPI E_DBus_Connection *
449 e_dbus_bus_get(DBusBusType type)
452 E_DBus_Connection *econn;
453 DBusConnection *conn;
455 /* each app only needs a single connection to either bus */
456 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
458 if (shared_connections[type])
460 e_dbus_connection_ref(shared_connections[type]);
461 return shared_connections[type];
465 dbus_error_init(&err);
467 conn = dbus_bus_get_private(type, &err);
468 if (dbus_error_is_set(&err))
470 fprintf(stderr, "Error connecting to bus: %s\n", err.message);
471 dbus_error_free(&err);
475 econn = e_dbus_connection_setup(conn);
478 fprintf(stderr, "Error setting up dbus connection.\n");
479 dbus_connection_close(conn);
480 dbus_connection_unref(conn);
484 if (type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION)
486 econn->shared_type = type;
487 shared_connections[type] = econn;
489 dbus_error_free(&err);
490 e_dbus_connection_ref(econn);
495 * Integrate a DBus connection with the ecore main loop
497 * @param conn - a dbus connection
499 EAPI E_DBus_Connection *
500 e_dbus_connection_setup(DBusConnection *conn)
502 E_DBus_Connection *cd;
504 cd = e_dbus_connection_new(conn);
505 if (!cd) return NULL;
507 /* connection_setup */
508 dbus_connection_set_exit_on_disconnect(cd->conn, FALSE);
509 dbus_connection_allocate_data_slot(&connection_slot);
511 dbus_connection_set_data(cd->conn, connection_slot, (void *)cd, e_dbus_connection_free);
512 dbus_connection_set_watch_functions(cd->conn,
519 dbus_connection_set_timeout_functions(cd->conn,
526 dbus_connection_set_wakeup_main_function(cd->conn, cb_main_wakeup, cd, NULL);
527 dbus_connection_set_dispatch_status_function(cd->conn, cb_dispatch_status, cd, NULL);
528 dbus_connection_add_filter(cd->conn, e_dbus_filter, cd, NULL);
530 cb_dispatch_status(cd->conn, dbus_connection_get_dispatch_status(cd->conn), cd);
537 * Close out a connection retrieved with e_dbus_bus_get()
538 * @param conn the connection to close
541 e_dbus_connection_close(E_DBus_Connection *conn)
543 DEBUG(5, "e_dbus_connection_close\n");
545 if (--(conn->refcount) != 0) return;
547 dbus_connection_free_data_slot(&connection_slot);
548 dbus_connection_remove_filter(conn->conn, e_dbus_filter, conn);
549 dbus_connection_set_watch_functions (conn->conn,
555 dbus_connection_set_timeout_functions (conn->conn,
561 dbus_connection_set_dispatch_status_function (conn->conn, NULL, NULL, NULL);
563 dbus_connection_close(conn->conn);
564 dbus_connection_unref(conn->conn);
566 // Note: the E_DBus_Connection gets freed when the dbus_connection is cleaned up by the previous unref
570 e_dbus_connection_ref(E_DBus_Connection *conn)
576 e_dbus_connection_dbus_connection_get(E_DBus_Connection *conn)
582 * @brief Initialize e_dbus
587 if (++init != 1) return init;
589 E_DBUS_EVENT_SIGNAL = ecore_event_type_new();
591 e_dbus_object_init();
599 e_dbus_shutdown(void)
601 if (--init) return init;
602 e_dbus_object_shutdown();
603 ecore_string_shutdown();