Mercurial > pidgin
annotate src/dbus-server.c @ 13623:51d436a267ac
[gaim-migrate @ 16009]
Use the GSlice allocator (for logs and log sets) when compiling with glib 2.10 or greater and eliminate some unnecessary memory zeroing. This cuts the log loading time in half for one of Luke's contacts.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Tue, 11 Apr 2006 16:06:24 +0000 |
parents | ac5bc9a7b603 |
children | a849cf259d00 |
rev | line source |
---|---|
11055 | 1 /* |
2 * gaim | |
3 * | |
4 * Gaim is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
23 | |
11146 | 24 #define DBUS_API_SUBJECT_TO_CHANGE |
25 | |
11055 | 26 #include <stdio.h> |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 | |
30 #include "account.h" | |
11067 | 31 #include "blist.h" |
32 #include "conversation.h" | |
11055 | 33 #include "dbus-gaim.h" |
34 #include "dbus-server.h" | |
11146 | 35 #include "dbus-useful.h" |
11171 | 36 #include "dbus-bindings.h" |
11055 | 37 #include "debug.h" |
38 #include "core.h" | |
11067 | 39 #include "value.h" |
11055 | 40 |
11080 | 41 |
11067 | 42 /**************************************************************************/ |
11171 | 43 /** @name Gaim DBUS pointer registration mechanism */ |
11080 | 44 /**************************************************************************/ |
11055 | 45 |
11171 | 46 /* |
47 Here we include the list of #GAIM_DBUS_DEFINE_TYPE statements for | |
48 all structs defined in gaim. This file has been generated by the | |
49 #dbus-analize-types.py script. | |
50 */ | |
11055 | 51 |
11171 | 52 #include "dbus-types.c" |
11055 | 53 |
11171 | 54 /* The following three hashtables map are used to translate between |
55 pointers (nodes) and the corresponding handles (ids). */ | |
56 | |
57 static GHashTable *map_node_id; | |
58 static GHashTable *map_id_node; | |
59 static GHashTable *map_id_type; | |
11080 | 60 |
61 | |
11171 | 62 /* This function initializes the pointer-id traslation system. It |
63 creates the three above hashtables and defines parents of some types. | |
64 */ | |
65 void gaim_dbus_init_ids(void) { | |
66 map_id_node = g_hash_table_new (g_direct_hash, g_direct_equal); | |
67 map_id_type = g_hash_table_new (g_direct_hash, g_direct_equal); | |
68 map_node_id = g_hash_table_new (g_direct_hash, g_direct_equal); | |
69 | |
70 GAIM_DBUS_TYPE(GaimBuddy)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
71 GAIM_DBUS_TYPE(GaimContact)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
72 GAIM_DBUS_TYPE(GaimChat)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
73 GAIM_DBUS_TYPE(GaimGroup)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
74 } | |
75 | |
76 void gaim_dbus_register_pointer(gpointer node, GaimDBusType *type) | |
77 { | |
78 static gint last_id = 0; | |
79 | |
11291 | 80 g_return_if_fail(map_node_id); |
81 g_return_if_fail(g_hash_table_lookup(map_node_id, node) == NULL); | |
11171 | 82 |
83 last_id++; | |
84 g_hash_table_insert(map_node_id, node, GINT_TO_POINTER(last_id)); | |
85 g_hash_table_insert(map_id_node, GINT_TO_POINTER(last_id), node); | |
86 g_hash_table_insert(map_id_type, GINT_TO_POINTER(last_id), type); | |
87 } | |
88 | |
89 void gaim_dbus_unregister_pointer(gpointer node) { | |
90 gpointer id = g_hash_table_lookup(map_node_id, node); | |
91 | |
92 g_hash_table_remove(map_node_id, node); | |
93 g_hash_table_remove(map_id_node, GINT_TO_POINTER(id)); | |
94 g_hash_table_remove(map_id_type, GINT_TO_POINTER(id)); | |
95 } | |
11055 | 96 |
11171 | 97 gint gaim_dbus_pointer_to_id(gpointer node) { |
98 gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node)); | |
11187 | 99 g_return_val_if_fail(id || node == NULL, 0); |
11171 | 100 return id; |
101 } | |
102 | |
103 gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusType *type) { | |
104 GaimDBusType *objtype = | |
105 (GaimDBusType*) g_hash_table_lookup(map_id_type, | |
106 GINT_TO_POINTER(id)); | |
107 | |
108 while (objtype != type && objtype != NULL) | |
109 objtype = objtype->parent; | |
110 | |
111 if (objtype == type) | |
112 return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id)); | |
113 else | |
114 return NULL; | |
115 } | |
116 | |
117 gint gaim_dbus_pointer_to_id_error(gpointer ptr, DBusError *error) | |
118 { | |
119 gint id = gaim_dbus_pointer_to_id(ptr); | |
11055 | 120 |
11171 | 121 if (ptr != NULL && id == 0) |
13220
ac5bc9a7b603
[gaim-migrate @ 15584]
Richard Laager <rlaager@wiktel.com>
parents:
13134
diff
changeset
|
122 dbus_set_error(error, "net.sf.gaim.ObjectNotFound", |
11171 | 123 "The return object is not mapped (this is a Gaim error)"); |
124 | |
125 return id; | |
126 } | |
127 | |
128 gpointer gaim_dbus_id_to_pointer_error(gint id, GaimDBusType *type, | |
129 const char *typename, DBusError *error) | |
130 { | |
131 gpointer ptr = gaim_dbus_id_to_pointer(id, type); | |
11055 | 132 |
11171 | 133 if (ptr == NULL && id != 0) |
13220
ac5bc9a7b603
[gaim-migrate @ 15584]
Richard Laager <rlaager@wiktel.com>
parents:
13134
diff
changeset
|
134 dbus_set_error(error, "net.sf.gaim.InvalidHandle", |
11171 | 135 "%s object with ID = %i not found", typename, id); |
136 | |
137 return ptr; | |
138 } | |
11187 | 139 |
140 | |
141 /**************************************************************************/ | |
142 /** @name Modified versions of some DBus functions */ | |
143 /**************************************************************************/ | |
144 | |
145 dbus_bool_t | |
146 gaim_dbus_message_get_args (DBusMessage *message, | |
11277 | 147 DBusError *error, |
148 int first_arg_type, | |
149 ...) | |
11187 | 150 { |
151 dbus_bool_t retval; | |
152 va_list var_args; | |
153 | |
154 va_start (var_args, first_arg_type); | |
155 retval = gaim_dbus_message_get_args_valist (message, error, first_arg_type, var_args); | |
156 va_end (var_args); | |
157 | |
158 return retval; | |
159 } | |
160 | |
161 dbus_bool_t | |
162 gaim_dbus_message_get_args_valist (DBusMessage *message, | |
163 DBusError *error, | |
164 int first_arg_type, | |
165 va_list var_args) | |
166 { | |
167 DBusMessageIter iter; | |
168 | |
169 dbus_message_iter_init (message, &iter); | |
170 return gaim_dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); | |
171 } | |
172 | |
173 dbus_bool_t | |
174 gaim_dbus_message_iter_get_args(DBusMessageIter *iter, | |
175 DBusError *error, | |
176 int first_arg_type, | |
177 ...) | |
178 { | |
179 dbus_bool_t retval; | |
180 va_list var_args; | |
181 | |
182 va_start (var_args, first_arg_type); | |
183 retval = gaim_dbus_message_iter_get_args_valist(iter, error, first_arg_type, var_args); | |
184 va_end (var_args); | |
185 | |
186 return retval; | |
187 } | |
188 | |
189 #define TYPE_IS_CONTAINER(typecode) \ | |
190 ((typecode) == DBUS_TYPE_STRUCT || \ | |
191 (typecode) == DBUS_TYPE_DICT_ENTRY || \ | |
192 (typecode) == DBUS_TYPE_VARIANT || \ | |
193 (typecode) == DBUS_TYPE_ARRAY) | |
194 | |
195 | |
196 dbus_bool_t | |
197 gaim_dbus_message_iter_get_args_valist (DBusMessageIter *iter, | |
198 DBusError *error, | |
199 int first_arg_type, | |
200 va_list var_args) | |
201 { | |
202 int spec_type, msg_type, i; | |
203 | |
204 spec_type = first_arg_type; | |
205 | |
206 for(i=0; spec_type != DBUS_TYPE_INVALID; i++) { | |
207 msg_type = dbus_message_iter_get_arg_type (iter); | |
208 | |
209 if (msg_type != spec_type) { | |
210 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, | |
211 "Argument %d is specified to be of type \"%i\", but " | |
212 "is actually of type \"%i\"\n", i, | |
213 spec_type, msg_type); | |
214 return FALSE; | |
215 } | |
216 | |
217 if (!TYPE_IS_CONTAINER(spec_type)) { | |
218 gpointer ptr; | |
219 ptr = va_arg (var_args, gpointer); | |
220 dbus_message_iter_get_basic(iter, ptr); | |
221 } | |
222 else { | |
223 DBusMessageIter *sub; | |
224 sub = va_arg (var_args, DBusMessageIter*); | |
225 dbus_message_iter_recurse(iter, sub); | |
226 g_print("subiter %i:%i\n", (int) sub, * (int*) sub); | |
227 break; /* for testing only! */ | |
228 } | |
11171 | 229 |
11187 | 230 spec_type = va_arg (var_args, int); |
231 if (!dbus_message_iter_next(iter) && spec_type != DBUS_TYPE_INVALID) { | |
232 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, | |
233 "Message has only %d arguments, but more were expected", i); | |
234 return FALSE; | |
235 } | |
236 } | |
237 return TRUE; | |
238 } | |
239 | |
240 | |
241 | |
11171 | 242 /**************************************************************************/ |
243 /** @name Useful functions */ | |
244 /**************************************************************************/ | |
11146 | 245 |
11171 | 246 const char* empty_to_null(const char *str) { |
11146 | 247 if (str == NULL || str[0] == 0) |
248 return NULL; | |
249 else | |
250 return str; | |
251 } | |
252 | |
11171 | 253 const char* null_to_empty(const char *s) { |
11080 | 254 if (s) |
255 return s; | |
256 else | |
257 return ""; | |
11055 | 258 } |
259 | |
11171 | 260 dbus_int32_t* gaim_dbusify_GList(GList *list, gboolean free_memory, |
261 dbus_int32_t *len) | |
262 { | |
263 dbus_int32_t *array; | |
264 int i; | |
265 GList *elem; | |
11055 | 266 |
11171 | 267 *len = g_list_length(list); |
268 array = g_new0(dbus_int32_t, g_list_length(list)); | |
269 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
270 array[i] = gaim_dbus_pointer_to_id(elem->data); | |
271 | |
272 if (free_memory) | |
273 g_list_free(list); | |
274 | |
275 return array; | |
11080 | 276 } |
11055 | 277 |
11171 | 278 dbus_int32_t* gaim_dbusify_GSList(GSList *list, gboolean free_memory, |
279 dbus_int32_t *len) | |
280 { | |
281 dbus_int32_t *array; | |
11146 | 282 int i; |
11171 | 283 GSList *elem; |
11146 | 284 |
11171 | 285 *len = g_slist_length(list); |
286 array = g_new0(dbus_int32_t, g_slist_length(list)); | |
287 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
288 array[i] = gaim_dbus_pointer_to_id(elem->data); | |
11067 | 289 |
11171 | 290 if (free_memory) |
291 g_slist_free(list); | |
11080 | 292 |
11171 | 293 return array; |
11067 | 294 } |
295 | |
11187 | 296 gpointer* gaim_GList_to_array(GList *list, gboolean free_memory, |
297 dbus_int32_t *len) | |
298 { | |
299 gpointer *array; | |
300 int i; | |
301 GList *elem; | |
302 | |
303 *len = g_list_length(list); | |
304 array = g_new0(gpointer, g_list_length(list)); | |
305 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
306 array[i] = elem->data; | |
307 | |
308 if (free_memory) | |
309 g_list_free(list); | |
310 | |
311 return array; | |
312 } | |
313 | |
314 gpointer* gaim_GSList_to_array(GSList *list, gboolean free_memory, | |
315 dbus_int32_t *len) | |
316 { | |
317 gpointer *array; | |
318 int i; | |
319 GSList *elem; | |
320 | |
321 *len = g_slist_length(list); | |
322 array = g_new0(gpointer, g_slist_length(list)); | |
323 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
324 array[i] = elem->data; | |
325 | |
326 if (free_memory) | |
327 g_slist_free(list); | |
328 | |
329 return array; | |
330 } | |
331 | |
332 GHashTable *gaim_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error) { | |
333 GHashTable *hash; | |
334 | |
335 /* we do not need to destroy strings because they are part of the message */ | |
336 hash = g_hash_table_new(g_str_hash, g_str_equal); | |
337 | |
338 do { | |
339 char *key, *value; | |
340 DBusMessageIter subiter; | |
341 | |
342 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) | |
343 goto error; /* With all due respect to Dijkstra, | |
344 this goto is for exception | |
345 handling, and it is ok because it | |
346 avoids duplication of the code | |
347 responsible for destroying the hash | |
348 table. Exceptional instructions | |
349 for exceptional situations. */ | |
350 | |
351 dbus_message_iter_recurse(iter, &subiter); | |
352 if (!gaim_dbus_message_iter_get_args(&subiter, error, | |
353 DBUS_TYPE_STRING, &key, | |
354 DBUS_TYPE_STRING, &value, | |
355 DBUS_TYPE_INVALID)) | |
356 goto error; /* same here */ | |
357 | |
358 g_hash_table_insert(hash, key, value); | |
359 } while (dbus_message_iter_next(iter)); | |
360 | |
361 return hash; | |
362 | |
363 error: | |
364 g_hash_table_destroy(hash); | |
365 return NULL; | |
366 } | |
367 | |
11171 | 368 /**************************************************************/ |
369 /* DBus bindings ... */ | |
370 /**************************************************************/ | |
371 | |
372 static DBusConnection *gaim_dbus_connection; | |
373 | |
374 DBusConnection *gaim_dbus_get_connection(void) { | |
375 return gaim_dbus_connection; | |
376 } | |
377 | |
378 #include "dbus-bindings.c" | |
379 | |
380 void *gaim_dbus_get_handle(void) { | |
381 static int handle; | |
382 | |
383 return &handle; | |
11067 | 384 } |
385 | |
11171 | 386 static gboolean |
387 gaim_dbus_dispatch_cb(DBusConnection *connection, | |
388 DBusMessage *message, | |
389 void *user_data) | |
390 { | |
391 const char *name; | |
392 GaimDBusBinding *bindings; | |
393 int i; | |
394 | |
395 bindings = (GaimDBusBinding*) user_data; | |
396 | |
11175 | 397 if (!dbus_message_has_path(message, DBUS_PATH_GAIM)) |
11171 | 398 return FALSE; |
399 | |
400 name = dbus_message_get_member(message); | |
401 | |
11175 | 402 if (name == NULL) |
403 return FALSE; | |
404 | |
405 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) | |
11171 | 406 return FALSE; |
407 | |
408 for(i=0; bindings[i].name; i++) | |
409 if (!strcmp(name, bindings[i].name)) { | |
410 DBusMessage *reply; | |
411 DBusError error; | |
412 | |
413 dbus_error_init(&error); | |
414 | |
415 reply = bindings[i].handler(message, &error); | |
416 | |
417 if (reply == NULL && dbus_error_is_set(&error)) | |
418 reply = dbus_message_new_error (message, | |
419 error.name, | |
420 error.message); | |
421 | |
422 if (reply != NULL) { | |
423 dbus_connection_send (connection, reply, NULL); | |
424 dbus_message_unref(reply); | |
425 } | |
426 | |
427 return TRUE; /* return reply! */ | |
428 } | |
429 | |
430 return FALSE; | |
11067 | 431 } |
11146 | 432 |
11175 | 433 |
434 static const char *gettext(const char **ptr) { | |
435 const char *text = *ptr; | |
436 *ptr += strlen(text) + 1; | |
437 return text; | |
438 } | |
439 | |
440 static void | |
441 gaim_dbus_introspect_cb(GList **bindings_list, void *bindings) { | |
442 *bindings_list = g_list_prepend(*bindings_list, bindings); | |
443 } | |
444 | |
445 static DBusMessage *gaim_dbus_introspect(DBusMessage *message) | |
446 { | |
447 DBusMessage *reply; | |
448 GString *str; | |
449 GList *bindings_list, *node; | |
450 | |
451 str = g_string_sized_new(0x1000); /* fixme: why this size? */ | |
452 | |
453 g_string_append(str, "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n"); | |
454 g_string_append_printf(str, "<node name='%s'>\n", DBUS_PATH_GAIM); | |
455 g_string_append_printf(str, "<interface name='%s'>\n", DBUS_INTERFACE_GAIM); | |
456 | |
457 bindings_list = NULL; | |
458 gaim_signal_emit(gaim_dbus_get_handle(), "dbus-introspect", &bindings_list); | |
459 | |
460 for(node = bindings_list; node; node = node->next) { | |
461 GaimDBusBinding *bindings; | |
462 int i; | |
463 | |
464 bindings = (GaimDBusBinding*) node->data; | |
465 | |
466 for(i=0; bindings[i].name; i++) { | |
467 const char *text; | |
468 | |
469 g_string_append_printf(str, "<method name='%s'>\n", bindings[i].name); | |
470 | |
471 text = bindings[i].parameters; | |
472 while (*text) { | |
473 const char *name, *direction, *type; | |
474 | |
475 direction = gettext(&text); | |
476 type = gettext(&text); | |
477 name = gettext(&text); | |
478 | |
11187 | 479 g_string_append_printf(str, |
480 "<arg name='%s' type='%s' direction='%s'/>\n", | |
481 name, type, direction); | |
11175 | 482 } |
483 g_string_append(str, "</method>\n"); | |
484 } | |
485 } | |
486 | |
487 g_string_append(str, "</interface>\n</node>\n"); | |
488 | |
489 reply = dbus_message_new_method_return (message); | |
490 dbus_message_append_args(reply, DBUS_TYPE_STRING, &(str->str), | |
491 DBUS_TYPE_INVALID); | |
492 g_string_free(str, TRUE); | |
493 g_list_free(bindings_list); | |
494 | |
495 return reply; | |
496 | |
497 } | |
498 | |
11171 | 499 static DBusHandlerResult gaim_dbus_dispatch(DBusConnection *connection, |
500 DBusMessage *message, | |
501 void *user_data) | |
502 { | |
503 if (gaim_signal_emit_return_1(gaim_dbus_get_handle(), | |
504 "dbus-method-called", | |
505 connection, message)) | |
506 return DBUS_HANDLER_RESULT_HANDLED; | |
11175 | 507 |
508 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL && | |
509 dbus_message_has_path(message, DBUS_PATH_GAIM) && | |
510 dbus_message_has_interface(message, DBUS_INTERFACE_INTROSPECTABLE) && | |
511 dbus_message_has_member(message, "Introspect")) | |
512 { | |
513 DBusMessage *reply; | |
514 reply = gaim_dbus_introspect(message); | |
515 dbus_connection_send (connection, reply, NULL); | |
516 dbus_message_unref(reply); | |
517 return DBUS_HANDLER_RESULT_HANDLED; | |
518 } | |
519 | |
520 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | |
11067 | 521 } |
11171 | 522 |
523 void gaim_dbus_register_bindings(void *handle, GaimDBusBinding *bindings) { | |
524 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-method-called", | |
525 handle, | |
526 GAIM_CALLBACK(gaim_dbus_dispatch_cb), | |
527 bindings); | |
11175 | 528 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-introspect", |
529 handle, | |
530 GAIM_CALLBACK(gaim_dbus_introspect_cb), | |
531 bindings); | |
11171 | 532 } |
11146 | 533 |
534 | |
11171 | 535 |
12627 | 536 static gboolean gaim_dbus_dispatch_init(void) |
11171 | 537 { |
12627 | 538 static DBusObjectPathVTable vtable = {NULL, &gaim_dbus_dispatch, NULL, NULL, NULL, NULL}; |
11171 | 539 |
540 DBusError error; | |
541 int result; | |
542 | |
543 dbus_error_init (&error); | |
544 gaim_dbus_connection = dbus_bus_get (DBUS_BUS_STARTER, &error); | |
11146 | 545 |
11171 | 546 if (gaim_dbus_connection == NULL) { |
547 gaim_debug_error("dbus", "Failed to get connection\n"); | |
548 dbus_error_free(&error); | |
549 return FALSE; | |
550 } | |
551 | |
552 if (!dbus_connection_register_object_path (gaim_dbus_connection, | |
553 DBUS_PATH_GAIM, &vtable, NULL)) | |
554 { | |
555 gaim_debug_error("dbus", "Failed to get name: %s\n", error.name); | |
556 dbus_error_free(&error); | |
557 return FALSE; | |
558 } | |
559 | |
11146 | 560 |
11171 | 561 result = dbus_bus_request_name (gaim_dbus_connection, DBUS_SERVICE_GAIM, |
562 0, &error); | |
563 | |
564 if (dbus_error_is_set (&error)) { | |
565 dbus_connection_unref(gaim_dbus_connection); | |
566 dbus_error_free(&error); | |
11903 | 567 gaim_dbus_connection = NULL; |
11171 | 568 gaim_debug_error("dbus", "Failed to get serv name: %s\n", error.name); |
569 return FALSE; | |
570 } | |
571 | |
572 dbus_connection_setup_with_g_main(gaim_dbus_connection, NULL); | |
11146 | 573 |
11171 | 574 gaim_debug_misc ("dbus", "okkk\n"); |
575 | |
576 gaim_signal_register(gaim_dbus_get_handle(), "dbus-method-called", | |
577 gaim_marshal_BOOLEAN__POINTER_POINTER, | |
578 gaim_value_new(GAIM_TYPE_BOOLEAN), 2, | |
579 gaim_value_new(GAIM_TYPE_POINTER), | |
580 gaim_value_new(GAIM_TYPE_POINTER)); | |
581 | |
11175 | 582 gaim_signal_register(gaim_dbus_get_handle(), "dbus-introspect", |
583 gaim_marshal_VOID__POINTER, NULL, 1, | |
584 gaim_value_new_outgoing(GAIM_TYPE_POINTER)); | |
585 | |
11171 | 586 GAIM_DBUS_REGISTER_BINDINGS(gaim_dbus_get_handle()); |
587 | |
588 return TRUE; | |
589 } | |
590 | |
11146 | 591 |
592 | |
593 /**************************************************************************/ | |
594 /** @name Signals */ | |
595 /**************************************************************************/ | |
596 | |
597 | |
598 | |
599 static char *gaim_dbus_convert_signal_name(const char *gaim_name) | |
600 { | |
601 int gaim_index, g_index; | |
602 char *g_name = g_new(char, strlen(gaim_name)+1); | |
603 gboolean capitalize_next = TRUE; | |
604 | |
605 for(gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++) | |
606 if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_') { | |
607 if (capitalize_next) | |
608 g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]); | |
609 else | |
610 g_name[g_index++] = gaim_name[gaim_index]; | |
611 capitalize_next = FALSE; | |
612 } else | |
613 capitalize_next = TRUE; | |
614 g_name[g_index] = 0; | |
615 | |
616 return g_name; | |
617 } | |
618 | |
619 #define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type)) | |
620 | |
621 static void gaim_dbus_message_append_gaim_values(DBusMessageIter *iter, | |
622 int number, | |
623 GaimValue **gaim_values, | |
624 va_list data) | |
625 { | |
626 int i; | |
627 | |
628 for(i=0; i<number; i++) { | |
629 const char *str; | |
630 int id; | |
631 gint xint; | |
632 guint xuint; | |
633 gboolean xboolean; | |
634 gpointer ptr = NULL; | |
635 if (gaim_value_is_outgoing(gaim_values[i])) { | |
636 ptr = my_arg(gpointer); | |
11291 | 637 g_return_if_fail(ptr); |
11146 | 638 } |
639 | |
640 switch(gaim_values[i]->type) { | |
641 case GAIM_TYPE_INT: | |
642 xint = my_arg(gint); | |
643 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint); | |
644 break; | |
645 case GAIM_TYPE_UINT: | |
646 xuint = my_arg(guint); | |
647 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint); | |
648 break; | |
649 case GAIM_TYPE_BOOLEAN: | |
650 xboolean = my_arg(gboolean); | |
651 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean); | |
652 break; | |
653 case GAIM_TYPE_STRING: | |
654 str = null_to_empty(my_arg(char*)); | |
655 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str); | |
656 break; | |
657 case GAIM_TYPE_SUBTYPE: /* registered pointers only! */ | |
658 case GAIM_TYPE_POINTER: | |
13134
b2d838b7eb00
[gaim-migrate @ 15496]
Richard Laager <rlaager@wiktel.com>
parents:
12627
diff
changeset
|
659 case GAIM_TYPE_OBJECT: |
b2d838b7eb00
[gaim-migrate @ 15496]
Richard Laager <rlaager@wiktel.com>
parents:
12627
diff
changeset
|
660 case GAIM_TYPE_BOXED: |
11146 | 661 id = gaim_dbus_pointer_to_id(my_arg(gpointer)); |
13134
b2d838b7eb00
[gaim-migrate @ 15496]
Richard Laager <rlaager@wiktel.com>
parents:
12627
diff
changeset
|
662 dbus_message_iter_append_basic(iter, (sizeof(void *) == 4) ? DBUS_TYPE_UINT32 : DBUS_TYPE_UINT64, &id); |
11146 | 663 break; |
664 default: /* no conversion implemented */ | |
11291 | 665 g_return_if_reached(); |
11146 | 666 } |
667 } | |
668 } | |
669 | |
670 #undef my_arg | |
671 | |
11903 | 672 void gaim_dbus_signal_emit_gaim(const char *name, int num_values, |
11146 | 673 GaimValue **values, va_list vargs) |
674 { | |
675 DBusMessage *signal; | |
676 DBusMessageIter iter; | |
677 char *newname; | |
678 | |
11903 | 679 #if 0 /* this is noisy with no dbus connection */ |
11171 | 680 g_return_if_fail(gaim_dbus_connection); |
11903 | 681 #else |
682 if (gaim_dbus_connection == NULL) | |
683 return; | |
684 #endif | |
685 | |
11146 | 686 |
11277 | 687 /* The test below is a hack that prevents our "dbus-method-called" |
688 signal from being propagated to dbus. What we really need is a | |
689 flag for each signal that states whether this signal is to be | |
690 dbus-propagated or not. */ | |
691 if (!strcmp(name, "dbus-method-called")) | |
692 return; | |
693 | |
11146 | 694 newname = gaim_dbus_convert_signal_name(name); |
695 signal = dbus_message_new_signal(DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, newname); | |
696 dbus_message_iter_init_append(signal, &iter); | |
697 | |
698 gaim_dbus_message_append_gaim_values(&iter, num_values, values, vargs); | |
699 | |
11171 | 700 dbus_connection_send(gaim_dbus_connection, signal, NULL); |
11146 | 701 |
702 g_free(newname); | |
703 dbus_message_unref(signal); | |
704 } | |
705 | |
706 | |
11080 | 707 |
708 | |
709 | |
710 | |
711 gboolean gaim_dbus_init(void) | |
712 { | |
11171 | 713 gaim_dbus_init_ids(); |
714 return gaim_dbus_dispatch_init() ; | |
11080 | 715 } |
11146 | 716 |
717 |