1
#include "eldbus_private.h"
2
#include "eldbus_private_types.h"
7
#define ELDBUS_SIGNAL_HANDLER_CHECK(handler) \
10
EINA_SAFETY_ON_NULL_RETURN(handler); \
11
if (!EINA_MAGIC_CHECK(handler, ELDBUS_SIGNAL_HANDLER_MAGIC)) \
13
EINA_MAGIC_FAIL(handler, ELDBUS_SIGNAL_HANDLER_MAGIC); \
19
#define ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, retval) \
22
EINA_SAFETY_ON_NULL_RETURN_VAL(handler, retval); \
23
if (!EINA_MAGIC_CHECK(handler, ELDBUS_SIGNAL_HANDLER_MAGIC)) \
25
EINA_MAGIC_FAIL(handler, ELDBUS_SIGNAL_HANDLER_MAGIC); \
31
static void _eldbus_signal_handler_del(Eldbus_Signal_Handler *handler);
32
static void _eldbus_signal_handler_clean(Eldbus_Signal_Handler *handler);
35
eldbus_signal_handler_init(void)
41
eldbus_signal_handler_shutdown(void)
46
_match_append(Eina_Strbuf *match, const char *key, const char *value)
50
if ((eina_strbuf_length_get(match) + strlen(",=''") + strlen(key) + strlen(value))
51
>= DBUS_MAXIMUM_MATCH_RULE_LENGTH)
53
ERR("cannot add match %s='%s' to %s: too long!", key, value,
54
eina_strbuf_string_get(match));
58
eina_strbuf_append_printf(match, ",%s='%s'", key, value);
62
_sort_arg(const void *d1, const void *d2)
64
const Signal_Argument *arg1, *arg2;
67
return arg1->index - arg2->index;
72
eldbus_signal_handler_match_extra_vset(Eldbus_Signal_Handler *sh, va_list ap)
74
const char *key = NULL, *read;
77
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(sh, EINA_FALSE);
79
dbus_error_init(&err);
80
dbus_bus_remove_match(sh->conn->dbus_conn,
81
eina_strbuf_string_get(sh->match), NULL);
83
for (read = va_arg(ap, char *); read; read = va_arg(ap, char *))
92
arg = calloc(1, sizeof(Signal_Argument));
93
EINA_SAFETY_ON_NULL_GOTO(arg, error);
94
if (!strncmp(key, ARGX, strlen(ARGX)))
96
int id = atoi(key + strlen(ARGX));
97
arg->index = (unsigned short) id;
98
arg->value = eina_stringshare_add(read);
99
sh->args = eina_inlist_sorted_state_insert(sh->args,
100
EINA_INLIST_GET(arg),
103
_match_append(sh->match, key, read);
107
ERR("%s not supported", key);
113
dbus_bus_add_match(sh->conn->dbus_conn,
114
eina_strbuf_string_get(sh->match), NULL);
118
dbus_bus_add_match(sh->conn->dbus_conn,
119
eina_strbuf_string_get(sh->match), NULL);
124
eldbus_signal_handler_match_extra_set(Eldbus_Signal_Handler *sh, ...)
130
ret = eldbus_signal_handler_match_extra_vset(sh, ap);
135
static void _on_handler_of_conn_free(void *data, const void *dead_pointer);
138
_on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
140
Eldbus_Signal_Handler *sh = data;
141
eldbus_signal_handler_free_cb_del(sh, _on_handler_of_conn_free, sh->conn);
142
eldbus_signal_handler_del(sh);
146
_on_handler_of_conn_free(void *data, const void *dead_pointer)
148
Eldbus_Connection *conn = data;
149
eldbus_connection_free_cb_del(conn, _on_connection_free, dead_pointer);
152
EAPI Eldbus_Signal_Handler *
153
eldbus_signal_handler_add(Eldbus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, Eldbus_Signal_Cb cb, const void *cb_data)
155
Eldbus_Signal_Handler *sh;
156
sh = _eldbus_signal_handler_add(conn, sender, path, interface, member, cb, cb_data);
157
EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
158
eldbus_connection_free_cb_add(conn, _on_connection_free, sh);
159
eldbus_signal_handler_free_cb_add(sh, _on_handler_of_conn_free, conn);
163
Eldbus_Signal_Handler *
164
_eldbus_signal_handler_add(Eldbus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, Eldbus_Signal_Cb cb, const void *cb_data)
166
Eldbus_Signal_Handler *sh;
169
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
170
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
171
DBG("conn=%p, sender=%s, path=%s, interface=%s, member=%s, cb=%p %p",
172
conn, sender, path, interface, member, cb, cb_data);
174
sh = calloc(1, sizeof(Eldbus_Signal_Handler));
175
EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
177
match = eina_strbuf_new();
178
EINA_SAFETY_ON_NULL_GOTO(match, cleanup_create_strbuf);
179
eina_strbuf_append(match, "type='signal'");
180
_match_append(match, "sender", sender);
181
_match_append(match, "path", path);
182
_match_append(match, "interface", interface);
183
_match_append(match, "member", member);
185
dbus_bus_add_match(conn->dbus_conn, eina_strbuf_string_get(match), NULL);
189
sh->bus = eldbus_connection_name_get(conn, sender);
190
if (!sh->bus) goto cleanup;
191
eldbus_connection_name_ref(sh->bus);
195
sh->cb_data = cb_data;
197
sh->interface = eina_stringshare_add(interface);
198
sh->member = eina_stringshare_add(member);
199
sh->path = eina_stringshare_add(path);
200
sh->sender = eina_stringshare_add(sender);
203
sh->dangling = EINA_FALSE;
204
sh->state_args = eina_inlist_sorted_state_new();
205
EINA_MAGIC_SET(sh, ELDBUS_SIGNAL_HANDLER_MAGIC);
207
eldbus_connection_signal_handler_add(conn, sh);
211
eina_strbuf_free(match);
212
cleanup_create_strbuf:
219
_eldbus_signal_handler_clean(Eldbus_Signal_Handler *handler)
223
if (handler->dangling) return;
224
DBG("clean handler=%p path=%p cb=%p", handler, handler->path, handler->cb);
225
dbus_error_init(&err);
226
dbus_bus_remove_match(handler->conn->dbus_conn,
227
eina_strbuf_string_get(handler->match), NULL);
228
handler->dangling = EINA_TRUE;
232
_eldbus_signal_handler_del(Eldbus_Signal_Handler *handler)
235
Signal_Argument *arg;
236
DBG("handler %p, refcount=%d, conn=%p %s",
237
handler, handler->refcount, handler->conn, handler->sender);
238
eldbus_cbs_free_dispatch(&(handler->cbs_free), handler);
239
eldbus_connection_signal_handler_del(handler->conn, handler);
240
EINA_MAGIC_SET(handler, EINA_MAGIC_NONE);
244
eina_stringshare_replace(&handler->sender, NULL);
245
eina_stringshare_replace(&handler->path, NULL);
246
eina_stringshare_replace(&handler->interface, NULL);
247
eina_stringshare_replace(&handler->member, NULL);
248
eina_strbuf_free(handler->match);
249
EINA_INLIST_FOREACH_SAFE(handler->args, list, arg)
251
eina_stringshare_replace(&arg->value, NULL);
254
eina_inlist_sorted_state_free(handler->state_args);
257
eldbus_connection_name_unref(handler->conn, handler->bus);
261
EAPI Eldbus_Signal_Handler *
262
eldbus_signal_handler_ref(Eldbus_Signal_Handler *handler)
264
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
265
DBG("handler=%p, pre-refcount=%d, match=%s",
266
handler, handler->refcount, eina_strbuf_string_get(handler->match));
272
eldbus_signal_handler_unref(Eldbus_Signal_Handler *handler)
274
ELDBUS_SIGNAL_HANDLER_CHECK(handler);
275
DBG("handler=%p, pre-refcount=%d, match=%s",
276
handler, handler->refcount, eina_strbuf_string_get(handler->match));
278
if (handler->refcount > 0) return;
280
_eldbus_signal_handler_clean(handler);
281
_eldbus_signal_handler_del(handler);
285
eldbus_signal_handler_del(Eldbus_Signal_Handler *handler)
287
ELDBUS_SIGNAL_HANDLER_CHECK(handler);
288
_eldbus_signal_handler_clean(handler);
289
eldbus_signal_handler_unref(handler);
293
eldbus_signal_handler_free_cb_add(Eldbus_Signal_Handler *handler, Eldbus_Free_Cb cb, const void *data)
295
ELDBUS_SIGNAL_HANDLER_CHECK(handler);
296
EINA_SAFETY_ON_NULL_RETURN(cb);
297
handler->cbs_free = eldbus_cbs_free_add(handler->cbs_free, cb, data);
301
eldbus_signal_handler_free_cb_del(Eldbus_Signal_Handler *handler, Eldbus_Free_Cb cb, const void *data)
303
ELDBUS_SIGNAL_HANDLER_CHECK(handler);
304
EINA_SAFETY_ON_NULL_RETURN(cb);
305
handler->cbs_free = eldbus_cbs_free_del(handler->cbs_free, cb, data);
309
eldbus_signal_handler_sender_get(const Eldbus_Signal_Handler *handler)
311
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
312
return handler->sender;
316
eldbus_signal_handler_path_get(const Eldbus_Signal_Handler *handler)
318
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
319
return handler->path;
323
eldbus_signal_handler_interface_get(const Eldbus_Signal_Handler *handler)
325
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
326
return handler->interface;
330
eldbus_signal_handler_member_get(const Eldbus_Signal_Handler *handler)
332
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
333
return handler->member;
337
eldbus_signal_handler_match_get(const Eldbus_Signal_Handler *handler)
339
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
340
return eina_strbuf_string_get(handler->match);
343
EAPI Eldbus_Connection *
344
eldbus_signal_handler_connection_get(const Eldbus_Signal_Handler *handler)
346
ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
347
return handler->conn;