(frame-geom-value-cons, frame-geom-spec-cons): New fns.
[bpt/emacs.git] / src / dbusbind.c
CommitLineData
033b73e2
MA
1/* Elisp bindings for D-Bus.
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19Boston, MA 02110-1301, USA. */
20
21#include "config.h"
22
23#ifdef HAVE_DBUS
24#include <stdlib.h>
f5306ca3 25#include <stdio.h>
033b73e2
MA
26#include <dbus/dbus.h>
27#include "lisp.h"
28#include "frame.h"
29#include "termhooks.h"
30#include "keyboard.h"
31
32\f
33/* Subroutines. */
34Lisp_Object Qdbus_get_unique_name;
35Lisp_Object Qdbus_call_method;
36Lisp_Object Qdbus_send_signal;
37Lisp_Object Qdbus_register_signal;
17bc8f94
MA
38Lisp_Object Qdbus_register_method;
39Lisp_Object Qdbus_unregister_object;
033b73e2
MA
40
41/* D-Bus error symbol. */
42Lisp_Object Qdbus_error;
43
44/* Lisp symbols of the system and session buses. */
39abdd4a 45Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 46
54371585
MA
47/* Lisp symbols of D-Bus types. */
48Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
49Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
50Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
51Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
52Lisp_Object QCdbus_type_double, QCdbus_type_string;
53Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
54Lisp_Object QCdbus_type_array, QCdbus_type_variant;
55Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
56
39abdd4a
MA
57/* Hash table which keeps function definitions. */
58Lisp_Object Vdbus_registered_functions_table;
033b73e2
MA
59
60/* Whether to debug D-Bus. */
61Lisp_Object Vdbus_debug;
62
63\f
64/* We use "xd_" and "XD_" as prefix for all internal symbols, because
65 we don't want to poison other namespaces with "dbus_". */
66
54371585 67/* Raise a Lisp error from a D-Bus ERROR. */
033b73e2 68#define XD_ERROR(error) \
17bc8f94 69 do { \
033b73e2
MA
70 char s[1024]; \
71 strcpy (s, error.message); \
72 dbus_error_free (&error); \
73 /* Remove the trailing newline. */ \
74 if (strchr (s, '\n') != NULL) \
75 s[strlen (s) - 1] = '\0'; \
76 xsignal1 (Qdbus_error, build_string (s)); \
17bc8f94 77 } while (0)
033b73e2
MA
78
79/* Macros for debugging. In order to enable them, build with
17bc8f94 80 "make MYCPPFLAGS='-DDBUS_DEBUG -Wall'". */
033b73e2
MA
81#ifdef DBUS_DEBUG
82#define XD_DEBUG_MESSAGE(...) \
17bc8f94 83 do { \
033b73e2
MA
84 char s[1024]; \
85 sprintf (s, __VA_ARGS__); \
86 printf ("%s: %s\n", __func__, s); \
87 message ("%s: %s", __func__, s); \
17bc8f94 88 } while (0)
033b73e2 89#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
17bc8f94
MA
90 do { \
91 if (!valid_lisp_object_p (object)) \
92 { \
93 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
94 xsignal1 (Qdbus_error, build_string ("Assertion failure")); \
95 } \
96 } while (0)
033b73e2
MA
97
98#else /* !DBUS_DEBUG */
17bc8f94
MA
99#define XD_DEBUG_MESSAGE(...) \
100 do { \
101 if (!NILP (Vdbus_debug)) \
102 { \
103 char s[1024]; \
104 sprintf (s, __VA_ARGS__); \
105 message ("%s: %s", __func__, s); \
80f9d13b 106 } \
17bc8f94 107 } while (0)
033b73e2
MA
108#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
109#endif
110
87cf1a39
MA
111/* Check whether TYPE is a basic DBusType. */
112#define XD_BASIC_DBUS_TYPE(type) \
113 ((type == DBUS_TYPE_BYTE) \
114 || (type == DBUS_TYPE_BOOLEAN) \
115 || (type == DBUS_TYPE_INT16) \
116 || (type == DBUS_TYPE_UINT16) \
117 || (type == DBUS_TYPE_INT32) \
118 || (type == DBUS_TYPE_UINT32) \
119 || (type == DBUS_TYPE_INT64) \
120 || (type == DBUS_TYPE_UINT64) \
121 || (type == DBUS_TYPE_DOUBLE) \
122 || (type == DBUS_TYPE_STRING) \
123 || (type == DBUS_TYPE_OBJECT_PATH) \
124 || (type == DBUS_TYPE_SIGNATURE))
125
54371585
MA
126/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
127 of the predefined D-Bus type symbols. */
87cf1a39
MA
128#define XD_SYMBOL_TO_DBUS_TYPE(object) \
129 ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE \
130 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN \
131 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16 \
132 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16 \
133 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32 \
134 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32 \
135 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64 \
136 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64 \
137 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE \
138 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING \
139 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH \
140 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE \
141 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY \
142 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT \
143 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT \
144 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY \
145 : DBUS_TYPE_INVALID)
146
147/* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
148#define XD_DBUS_TYPE_P(object) \
149 (SYMBOLP (object) && ((XD_SYMBOL_TO_DBUS_TYPE (object) != DBUS_TYPE_INVALID)))
54371585
MA
150
151/* Determine the DBusType of a given Lisp OBJECT. It is used to
033b73e2
MA
152 convert Lisp objects, being arguments of `dbus-call-method' or
153 `dbus-send-signal', into corresponding C values appended as
154 arguments to a D-Bus message. */
87cf1a39
MA
155#define XD_OBJECT_TO_DBUS_TYPE(object) \
156 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
157 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
158 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
159 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
160 : (STRINGP (object)) ? DBUS_TYPE_STRING \
161 : (XD_DBUS_TYPE_P (object)) ? XD_SYMBOL_TO_DBUS_TYPE (object) \
162 : (CONSP (object)) ? ((XD_DBUS_TYPE_P (XCAR (object))) \
163 ? XD_SYMBOL_TO_DBUS_TYPE (XCAR (object)) \
164 : DBUS_TYPE_ARRAY) \
165 : DBUS_TYPE_INVALID)
166
167/* Return a list pointer which does not have a Lisp symbol as car. */
168#define XD_NEXT_VALUE(object) \
169 ((XD_DBUS_TYPE_P (XCAR (object))) ? XCDR (object) : object)
170
171/* Compute SIGNATURE of OBJECT. It must have a form that it can be
172 used in dbus_message_iter_open_container. DTYPE is the DBusType
173 the object is related to. It is passed as argument, because it
174 cannot be detected in basic type objects, when they are preceded by
175 a type symbol. PARENT_TYPE is the DBusType of a container this
176 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
177 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
54371585 178void
87cf1a39
MA
179xd_signature(signature, dtype, parent_type, object)
180 char *signature;
181 unsigned int dtype, parent_type;
033b73e2
MA
182 Lisp_Object object;
183{
87cf1a39
MA
184 unsigned int subtype;
185 Lisp_Object elt;
186 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
187
188 elt = object;
033b73e2 189
033b73e2
MA
190 switch (dtype)
191 {
54371585
MA
192 case DBUS_TYPE_BYTE:
193 case DBUS_TYPE_UINT16:
033b73e2 194 case DBUS_TYPE_UINT32:
54371585
MA
195 case DBUS_TYPE_UINT64:
196 CHECK_NATNUM (object);
87cf1a39 197 sprintf (signature, "%c", dtype);
54371585 198 break;
87cf1a39 199
54371585
MA
200 case DBUS_TYPE_BOOLEAN:
201 if (!EQ (object, Qt) && !EQ (object, Qnil))
202 wrong_type_argument (intern ("booleanp"), object);
87cf1a39 203 sprintf (signature, "%c", dtype);
54371585 204 break;
87cf1a39 205
54371585 206 case DBUS_TYPE_INT16:
033b73e2 207 case DBUS_TYPE_INT32:
54371585
MA
208 case DBUS_TYPE_INT64:
209 CHECK_NUMBER (object);
87cf1a39 210 sprintf (signature, "%c", dtype);
54371585 211 break;
87cf1a39 212
033b73e2 213 case DBUS_TYPE_DOUBLE:
54371585 214 CHECK_FLOAT (object);
87cf1a39 215 sprintf (signature, "%c", dtype);
54371585 216 break;
87cf1a39 217
033b73e2 218 case DBUS_TYPE_STRING:
54371585
MA
219 case DBUS_TYPE_OBJECT_PATH:
220 case DBUS_TYPE_SIGNATURE:
221 CHECK_STRING (object);
87cf1a39 222 sprintf (signature, "%c", dtype);
54371585 223 break;
87cf1a39 224
54371585 225 case DBUS_TYPE_ARRAY:
9af5078b 226 /* Check that all list elements have the same D-Bus type. For
87cf1a39
MA
227 complex element types, we just check the container type, not
228 the whole element's signature. */
54371585 229 CHECK_CONS (object);
87cf1a39
MA
230
231 if (EQ (QCdbus_type_array, XCAR (elt))) /* Type symbol is optional. */
232 elt = XD_NEXT_VALUE (elt);
233 subtype = XD_OBJECT_TO_DBUS_TYPE (XCAR (elt));
234 xd_signature (x, subtype, dtype, XCAR (XD_NEXT_VALUE (elt)));
235
236 while (!NILP (elt))
237 {
238 if (subtype != XD_OBJECT_TO_DBUS_TYPE (XCAR (elt)))
239 wrong_type_argument (intern ("D-Bus"), XCAR (elt));
240 elt = XCDR (XD_NEXT_VALUE (elt));
241 }
242
243 sprintf (signature, "%c%s", dtype, x);
54371585 244 break;
87cf1a39 245
54371585 246 case DBUS_TYPE_VARIANT:
9af5078b 247 /* Check that there is exactly one list element. */
54371585 248 CHECK_CONS (object);
87cf1a39
MA
249
250 elt = XD_NEXT_VALUE (elt);
251 subtype = XD_OBJECT_TO_DBUS_TYPE (XCAR (elt));
252 xd_signature (x, subtype, dtype, XCAR (XD_NEXT_VALUE (elt)));
253
254 if (!NILP (XCDR (XD_NEXT_VALUE (elt))))
255 wrong_type_argument (intern ("D-Bus"),
256 XCAR (XCDR (XD_NEXT_VALUE (elt))));
257
a271e124 258 sprintf (signature, "%c", dtype);
54371585 259 break;
87cf1a39 260
54371585 261 case DBUS_TYPE_STRUCT:
9af5078b
MA
262 /* A struct list might contain any number of elements with
263 different types. No further check needed. */
87cf1a39
MA
264 CHECK_CONS (object);
265
266 elt = XD_NEXT_VALUE (elt);
267
268 /* Compose the signature from the elements. It is enclosed by
269 parentheses. */
270 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
271 while (!NILP (elt))
272 {
273 subtype = XD_OBJECT_TO_DBUS_TYPE (XCAR (elt));
274 xd_signature (x, subtype, dtype, XCAR (XD_NEXT_VALUE (elt)));
275 strcat (signature, x);
276 elt = XCDR (XD_NEXT_VALUE (elt));
277 }
278 sprintf (signature, "%s%c", signature, DBUS_STRUCT_END_CHAR);
54371585 279 break;
54371585 280
87cf1a39 281 case DBUS_TYPE_DICT_ENTRY:
9af5078b
MA
282 /* Check that there are exactly two list elements, and the first
283 one is of basic type. The dictionary entry itself must be an
284 element of an array. */
87cf1a39 285 CHECK_CONS (object);
54371585 286
9af5078b 287 /* Check the parent object type. */
87cf1a39
MA
288 if (parent_type != DBUS_TYPE_ARRAY)
289 wrong_type_argument (intern ("D-Bus"), object);
54371585 290
87cf1a39
MA
291 /* Compose the signature from the elements. It is enclosed by
292 curly braces. */
293 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
54371585 294
87cf1a39
MA
295 /* First element. */
296 elt = XD_NEXT_VALUE (elt);
297 subtype = XD_OBJECT_TO_DBUS_TYPE (XCAR (elt));
298 xd_signature (x, subtype, dtype, XCAR (XD_NEXT_VALUE (elt)));
299 strcat (signature, x);
54371585 300
87cf1a39
MA
301 if (!XD_BASIC_DBUS_TYPE (subtype))
302 wrong_type_argument (intern ("D-Bus"), XCAR (XD_NEXT_VALUE (elt)));
54371585 303
87cf1a39
MA
304 /* Second element. */
305 elt = XCDR (XD_NEXT_VALUE (elt));
306 subtype = XD_OBJECT_TO_DBUS_TYPE (XCAR (elt));
307 xd_signature (x, subtype, dtype, XCAR (XD_NEXT_VALUE (elt)));
308 strcat (signature, x);
54371585 309
87cf1a39
MA
310 if (!NILP (XCDR (XD_NEXT_VALUE (elt))))
311 wrong_type_argument (intern ("D-Bus"),
312 XCAR (XCDR (XD_NEXT_VALUE (elt))));
54371585 313
87cf1a39
MA
314 /* Closing signature. */
315 sprintf (signature, "%s%c", signature, DBUS_DICT_ENTRY_END_CHAR);
316 break;
54371585 317
87cf1a39
MA
318 default:
319 wrong_type_argument (intern ("D-Bus"), object);
54371585
MA
320 }
321
87cf1a39
MA
322 XD_DEBUG_MESSAGE ("%s", signature);
323}
54371585 324
87cf1a39
MA
325/* Append C value, extracted from Lisp OBJECT, to iteration ITER.
326 DTYPE must be a valid DBusType. It is used to convert Lisp
327 objects, being arguments of `dbus-call-method' or
328 `dbus-send-signal', into corresponding C values appended as
329 arguments to a D-Bus message. */
330void
331xd_append_arg (dtype, object, iter)
332 unsigned int dtype;
333 Lisp_Object object;
334 DBusMessageIter *iter;
335{
87cf1a39
MA
336 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
337 DBusMessageIter subiter;
87cf1a39
MA
338
339 if (XD_BASIC_DBUS_TYPE (dtype))
17bc8f94
MA
340 switch (dtype)
341 {
342 case DBUS_TYPE_BYTE:
54371585 343 {
17bc8f94
MA
344 unsigned int val = XUINT (object) & 0xFF;
345 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
346 if (!dbus_message_iter_append_basic (iter, dtype, &val))
347 xsignal2 (Qdbus_error,
348 build_string ("Unable to append argument"), object);
349 return;
350 }
87cf1a39 351
17bc8f94
MA
352 case DBUS_TYPE_BOOLEAN:
353 {
354 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
355 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
356 if (!dbus_message_iter_append_basic (iter, dtype, &val))
357 xsignal2 (Qdbus_error,
358 build_string ("Unable to append argument"), object);
359 return;
360 }
87cf1a39 361
17bc8f94
MA
362 case DBUS_TYPE_INT16:
363 {
364 dbus_int16_t val = XINT (object);
365 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
366 if (!dbus_message_iter_append_basic (iter, dtype, &val))
367 xsignal2 (Qdbus_error,
368 build_string ("Unable to append argument"), object);
369 return;
370 }
87cf1a39 371
17bc8f94
MA
372 case DBUS_TYPE_UINT16:
373 {
374 dbus_uint16_t val = XUINT (object);
375 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
376 if (!dbus_message_iter_append_basic (iter, dtype, &val))
377 xsignal2 (Qdbus_error,
378 build_string ("Unable to append argument"), object);
379 return;
380 }
87cf1a39 381
17bc8f94
MA
382 case DBUS_TYPE_INT32:
383 {
384 dbus_int32_t val = XINT (object);
385 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
386 if (!dbus_message_iter_append_basic (iter, dtype, &val))
387 xsignal2 (Qdbus_error,
388 build_string ("Unable to append argument"), object);
389 return;
390 }
87cf1a39 391
17bc8f94
MA
392 case DBUS_TYPE_UINT32:
393 {
394 dbus_uint32_t val = XUINT (object);
395 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
396 if (!dbus_message_iter_append_basic (iter, dtype, &val))
397 xsignal2 (Qdbus_error,
398 build_string ("Unable to append argument"), object);
399 return;
400 }
87cf1a39 401
17bc8f94
MA
402 case DBUS_TYPE_INT64:
403 {
404 dbus_int64_t val = XINT (object);
405 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
406 if (!dbus_message_iter_append_basic (iter, dtype, &val))
407 xsignal2 (Qdbus_error,
408 build_string ("Unable to append argument"), object);
409 return;
410 }
87cf1a39 411
17bc8f94
MA
412 case DBUS_TYPE_UINT64:
413 {
414 dbus_uint64_t val = XUINT (object);
415 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
416 if (!dbus_message_iter_append_basic (iter, dtype, &val))
417 xsignal2 (Qdbus_error,
418 build_string ("Unable to append argument"), object);
419 return;
54371585 420 }
87cf1a39 421
17bc8f94
MA
422 case DBUS_TYPE_DOUBLE:
423 XD_DEBUG_MESSAGE ("%c %f", dtype, XFLOAT_DATA (object));
424 if (!dbus_message_iter_append_basic (iter, dtype,
425 &XFLOAT_DATA (object)))
426 xsignal2 (Qdbus_error,
427 build_string ("Unable to append argument"), object);
428 return;
429
430 case DBUS_TYPE_STRING:
431 case DBUS_TYPE_OBJECT_PATH:
432 case DBUS_TYPE_SIGNATURE:
433 {
434 char *val = SDATA (object);
435 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
436 if (!dbus_message_iter_append_basic (iter, dtype, &val))
437 xsignal2 (Qdbus_error,
438 build_string ("Unable to append argument"), object);
439 return;
440 }
441 }
87cf1a39
MA
442
443 else /* Compound types. */
444 {
445
446 /* All compound types except array have a type symbol. For
447 array, it is optional. Skip it. */
448 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (XCAR (object))))
449 object = XD_NEXT_VALUE (object);
450
451 /* Open new subiteration. */
452 switch (dtype)
453 {
454 case DBUS_TYPE_ARRAY:
455 case DBUS_TYPE_VARIANT:
456 /* A variant has just one element. An array has elements of
9af5078b
MA
457 the same type. Both have been checked already for
458 correct types, it is sufficient to retrieve just the
459 signature of the first element. */
87cf1a39
MA
460 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (XCAR (object)),
461 dtype, XCAR (XD_NEXT_VALUE (object)));
462 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
463 SDATA (format2 ("%s", object, Qnil)));
464 if (!dbus_message_iter_open_container (iter, dtype,
465 signature, &subiter))
466 xsignal3 (Qdbus_error,
467 build_string ("Cannot open container"),
468 make_number (dtype), build_string (signature));
469 break;
470
471 case DBUS_TYPE_STRUCT:
472 case DBUS_TYPE_DICT_ENTRY:
9af5078b 473 /* These containers do not require a signature. */
87cf1a39
MA
474 XD_DEBUG_MESSAGE ("%c %s", dtype,
475 SDATA (format2 ("%s", object, Qnil)));
476 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
477 xsignal2 (Qdbus_error,
478 build_string ("Cannot open container"),
479 make_number (dtype));
480 break;
481 }
482
483 /* Loop over list elements. */
484 while (!NILP (object))
485 {
486 dtype = XD_OBJECT_TO_DBUS_TYPE (XCAR (object));
487 object = XD_NEXT_VALUE (object);
488
489 xd_append_arg (dtype, XCAR (object), &subiter);
490
491 object = XCDR (object);
492 }
493
9af5078b 494 /* Close the subiteration. */
87cf1a39
MA
495 if (!dbus_message_iter_close_container (iter, &subiter))
496 xsignal2 (Qdbus_error,
497 build_string ("Cannot close container"),
498 make_number (dtype));
499 }
033b73e2
MA
500}
501
502/* Retrieve C value from a DBusMessageIter structure ITER, and return
503 a converted Lisp object. The type DTYPE of the argument of the
9af5078b
MA
504 D-Bus message must be a valid DBusType. Compound D-Bus types
505 result always in a Lisp list. */
033b73e2
MA
506Lisp_Object
507xd_retrieve_arg (dtype, iter)
eb7c7bf5 508 unsigned int dtype;
033b73e2
MA
509 DBusMessageIter *iter;
510{
511
512 switch (dtype)
513 {
9af5078b 514 case DBUS_TYPE_BYTE:
9af5078b 515 {
17bc8f94 516 unsigned int val;
9af5078b 517 dbus_message_iter_get_basic (iter, &val);
17bc8f94 518 val = val & 0xFF;
9af5078b
MA
519 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
520 return make_number (val);
521 }
522
033b73e2
MA
523 case DBUS_TYPE_BOOLEAN:
524 {
525 dbus_bool_t val;
526 dbus_message_iter_get_basic (iter, &val);
87cf1a39 527 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
033b73e2
MA
528 return (val == FALSE) ? Qnil : Qt;
529 }
87cf1a39 530
17bc8f94
MA
531 case DBUS_TYPE_INT16:
532 case DBUS_TYPE_UINT16:
533 {
534 dbus_uint16_t val;
535 dbus_message_iter_get_basic (iter, &val);
536 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
537 return make_number (val);
538 }
539
033b73e2
MA
540 case DBUS_TYPE_INT32:
541 case DBUS_TYPE_UINT32:
542 {
543 dbus_uint32_t val;
544 dbus_message_iter_get_basic (iter, &val);
17bc8f94 545 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
9af5078b
MA
546 return make_fixnum_or_float (val);
547 }
548
549 case DBUS_TYPE_INT64:
550 case DBUS_TYPE_UINT64:
551 {
552 dbus_uint64_t val;
553 dbus_message_iter_get_basic (iter, &val);
17bc8f94 554 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
9af5078b
MA
555 return make_fixnum_or_float (val);
556 }
557
558 case DBUS_TYPE_DOUBLE:
559 {
560 double val;
561 dbus_message_iter_get_basic (iter, &val);
562 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
563 return make_float (val);
033b73e2 564 }
87cf1a39 565
033b73e2
MA
566 case DBUS_TYPE_STRING:
567 case DBUS_TYPE_OBJECT_PATH:
9af5078b 568 case DBUS_TYPE_SIGNATURE:
033b73e2
MA
569 {
570 char *val;
571 dbus_message_iter_get_basic (iter, &val);
87cf1a39 572 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
033b73e2
MA
573 return build_string (val);
574 }
87cf1a39 575
033b73e2
MA
576 case DBUS_TYPE_ARRAY:
577 case DBUS_TYPE_VARIANT:
578 case DBUS_TYPE_STRUCT:
579 case DBUS_TYPE_DICT_ENTRY:
580 {
581 Lisp_Object result;
582 struct gcpro gcpro1;
583 result = Qnil;
584 GCPRO1 (result);
585 DBusMessageIter subiter;
586 int subtype;
587 dbus_message_iter_recurse (iter, &subiter);
588 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
589 != DBUS_TYPE_INVALID)
590 {
591 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
592 dbus_message_iter_next (&subiter);
593 }
594 RETURN_UNGCPRO (Fnreverse (result));
595 }
87cf1a39 596
033b73e2 597 default:
87cf1a39 598 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
033b73e2
MA
599 return Qnil;
600 }
601}
602
603
604/* Initialize D-Bus connection. BUS is a Lisp symbol, either :system
605 or :session. It tells which D-Bus to be initialized. */
606DBusConnection *
607xd_initialize (bus)
608 Lisp_Object bus;
609{
610 DBusConnection *connection;
611 DBusError derror;
612
613 /* Parameter check. */
614 CHECK_SYMBOL (bus);
39abdd4a 615 if (!((EQ (bus, QCdbus_system_bus)) || (EQ (bus, QCdbus_session_bus))))
033b73e2
MA
616 xsignal2 (Qdbus_error, build_string ("Wrong bus name"), bus);
617
618 /* Open a connection to the bus. */
619 dbus_error_init (&derror);
620
39abdd4a 621 if (EQ (bus, QCdbus_system_bus))
033b73e2
MA
622 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
623 else
624 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
625
626 if (dbus_error_is_set (&derror))
627 XD_ERROR (derror);
628
629 if (connection == NULL)
630 xsignal2 (Qdbus_error, build_string ("No connection"), bus);
631
632 /* Return the result. */
633 return connection;
634}
635
636DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
637 1, 1, 0,
638 doc: /* Return the unique name of Emacs registered at D-Bus BUS as string. */)
639 (bus)
640 Lisp_Object bus;
641{
642 DBusConnection *connection;
52da95fa 643 char name[DBUS_MAXIMUM_NAME_LENGTH];
033b73e2
MA
644
645 /* Check parameters. */
646 CHECK_SYMBOL (bus);
647
648 /* Open a connection to the bus. */
649 connection = xd_initialize (bus);
650
651 /* Request the name. */
652 strcpy (name, dbus_bus_get_unique_name (connection));
653 if (name == NULL)
654 xsignal1 (Qdbus_error, build_string ("No unique name available"));
655
656 /* Return. */
657 return build_string (name);
658}
659
660DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
661 doc: /* Call METHOD on the D-Bus BUS.
662
663BUS is either the symbol `:system' or the symbol `:session'.
664
665SERVICE is the D-Bus service name to be used. PATH is the D-Bus
666object path SERVICE is registered at. INTERFACE is an interface
667offered by SERVICE. It must provide METHOD.
668
669All other arguments ARGS are passed to METHOD as arguments. They are
670converted into D-Bus types via the following rules:
671
672 t and nil => DBUS_TYPE_BOOLEAN
673 number => DBUS_TYPE_UINT32
674 integer => DBUS_TYPE_INT32
675 float => DBUS_TYPE_DOUBLE
676 string => DBUS_TYPE_STRING
87cf1a39 677 list => DBUS_TYPE_ARRAY
033b73e2 678
87cf1a39
MA
679All arguments can be preceded by a type symbol. For details about
680type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
681
682`dbus-call-method' returns the resulting values of METHOD as a list of
683Lisp objects. The type conversion happens the other direction as for
87cf1a39
MA
684input arguments. It follows the mapping rules:
685
686 DBUS_TYPE_BOOLEAN => t or nil
687 DBUS_TYPE_BYTE => number
688 DBUS_TYPE_UINT16 => number
689 DBUS_TYPE_INT16 => integer
9af5078b
MA
690 DBUS_TYPE_UINT32 => number or float
691 DBUS_TYPE_INT32 => integer or float
692 DBUS_TYPE_UINT64 => number or float
693 DBUS_TYPE_INT64 => integer or float
87cf1a39
MA
694 DBUS_TYPE_DOUBLE => float
695 DBUS_TYPE_STRING => string
696 DBUS_TYPE_OBJECT_PATH => string
697 DBUS_TYPE_SIGNATURE => string
698 DBUS_TYPE_ARRAY => list
699 DBUS_TYPE_VARIANT => list
700 DBUS_TYPE_STRUCT => list
701 DBUS_TYPE_DICT_ENTRY => list
702
703Example:
033b73e2
MA
704
705\(dbus-call-method
52da95fa
MA
706 :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
707 "org.gnome.seahorse.Keys" "GetKeyField"
033b73e2
MA
708 "openpgp:657984B8C7A966DD" "simple-name")
709
710 => (t ("Philip R. Zimmermann"))
711
712If the result of the METHOD call is just one value, the converted Lisp
713object is returned instead of a list containing this single Lisp object.
714
715\(dbus-call-method
52da95fa
MA
716 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
717 "org.freedesktop.Hal.Device" "GetPropertyString"
033b73e2
MA
718 "system.kernel.machine")
719
720 => "i686"
721
52da95fa 722usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &rest ARGS) */)
033b73e2
MA
723 (nargs, args)
724 int nargs;
725 register Lisp_Object *args;
726{
52da95fa 727 Lisp_Object bus, service, path, interface, method;
033b73e2
MA
728 Lisp_Object result;
729 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
730 DBusConnection *connection;
731 DBusMessage *dmessage;
732 DBusMessage *reply;
733 DBusMessageIter iter;
734 DBusError derror;
eb7c7bf5 735 unsigned int dtype;
033b73e2 736 int i;
87cf1a39 737 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
738
739 /* Check parameters. */
740 bus = args[0];
52da95fa
MA
741 service = args[1];
742 path = args[2];
743 interface = args[3];
744 method = args[4];
033b73e2
MA
745
746 CHECK_SYMBOL (bus);
033b73e2
MA
747 CHECK_STRING (service);
748 CHECK_STRING (path);
749 CHECK_STRING (interface);
52da95fa
MA
750 CHECK_STRING (method);
751 GCPRO5 (bus, service, path, interface, method);
033b73e2
MA
752
753 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
754 SDATA (service),
755 SDATA (path),
52da95fa
MA
756 SDATA (interface),
757 SDATA (method));
033b73e2
MA
758
759 /* Open a connection to the bus. */
760 connection = xd_initialize (bus);
761
762 /* Create the message. */
f5306ca3
MA
763 dmessage = dbus_message_new_method_call ((char *) SDATA (service),
764 (char *) SDATA (path),
765 (char *) SDATA (interface),
766 (char *) SDATA (method));
033b73e2
MA
767 if (dmessage == NULL)
768 {
769 UNGCPRO;
770 xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
771 }
772
773 UNGCPRO;
774
54371585
MA
775 /* Initialize parameter list of message. */
776 dbus_message_iter_init_append (dmessage, &iter);
777
033b73e2
MA
778 /* Append parameters to the message. */
779 for (i = 5; i < nargs; ++i)
780 {
781
782 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
783 XD_DEBUG_MESSAGE ("Parameter%d %s",
87cf1a39 784 i-4, SDATA (format2 ("%s", args[i], Qnil)));
033b73e2 785
87cf1a39
MA
786 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
787 if (XD_DBUS_TYPE_P (args[i]))
54371585 788 ++i;
033b73e2 789
87cf1a39
MA
790 /* Check for valid signature. We use DBUS_TYPE_INVALID is
791 indication that there is no parent type. */
792 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
793
54371585 794 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
795 }
796
797 /* Send the message. */
798 dbus_error_init (&derror);
799 reply = dbus_connection_send_with_reply_and_block (connection,
800 dmessage,
801 -1,
802 &derror);
803
804 if (dbus_error_is_set (&derror))
805 XD_ERROR (derror);
806
807 if (reply == NULL)
808 xsignal1 (Qdbus_error, build_string ("No reply"));
809
810 XD_DEBUG_MESSAGE ("Message sent");
811
812 /* Collect the results. */
813 result = Qnil;
814 GCPRO1 (result);
815
816 if (!dbus_message_iter_init (reply, &iter))
817 {
818 UNGCPRO;
819 xsignal1 (Qdbus_error, build_string ("Cannot read reply"));
820 }
821
822 /* Loop over the parameters of the D-Bus reply message. Construct a
823 Lisp list, which is returned by `dbus-call-method'. */
824 while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
825 {
826 result = Fcons (xd_retrieve_arg (dtype, &iter), result);
827 dbus_message_iter_next (&iter);
828 }
829
830 /* Cleanup. */
831 dbus_message_unref (dmessage);
832 dbus_message_unref (reply);
833
834 /* Return the result. If there is only one single Lisp object,
835 return it as-it-is, otherwise return the reversed list. */
836 if (XUINT (Flength (result)) == 1)
837 RETURN_UNGCPRO (XCAR (result));
838 else
839 RETURN_UNGCPRO (Fnreverse (result));
840}
841
842DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
843 doc: /* Send signal SIGNAL on the D-Bus BUS.
844
845BUS is either the symbol `:system' or the symbol `:session'.
846
847SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
848D-Bus object path SERVICE is registered at. INTERFACE is an interface
849offered by SERVICE. It must provide signal SIGNAL.
850
851All other arguments ARGS are passed to SIGNAL as arguments. They are
852converted into D-Bus types via the following rules:
853
854 t and nil => DBUS_TYPE_BOOLEAN
855 number => DBUS_TYPE_UINT32
856 integer => DBUS_TYPE_INT32
857 float => DBUS_TYPE_DOUBLE
858 string => DBUS_TYPE_STRING
87cf1a39 859 list => DBUS_TYPE_ARRAY
033b73e2 860
87cf1a39
MA
861All arguments can be preceded by a type symbol. For details about
862type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
863
864Example:
865
866\(dbus-send-signal
52da95fa
MA
867 :session "org.gnu.Emacs" "/org/gnu/Emacs"
868 "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
033b73e2 869
52da95fa 870usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
033b73e2
MA
871 (nargs, args)
872 int nargs;
873 register Lisp_Object *args;
874{
52da95fa 875 Lisp_Object bus, service, path, interface, signal;
033b73e2
MA
876 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
877 DBusConnection *connection;
878 DBusMessage *dmessage;
54371585 879 DBusMessageIter iter;
eb7c7bf5 880 unsigned int dtype;
033b73e2 881 int i;
87cf1a39 882 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
883
884 /* Check parameters. */
885 bus = args[0];
52da95fa
MA
886 service = args[1];
887 path = args[2];
888 interface = args[3];
889 signal = args[4];
033b73e2
MA
890
891 CHECK_SYMBOL (bus);
033b73e2
MA
892 CHECK_STRING (service);
893 CHECK_STRING (path);
894 CHECK_STRING (interface);
52da95fa
MA
895 CHECK_STRING (signal);
896 GCPRO5 (bus, service, path, interface, signal);
033b73e2
MA
897
898 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
899 SDATA (service),
900 SDATA (path),
52da95fa
MA
901 SDATA (interface),
902 SDATA (signal));
033b73e2
MA
903
904 /* Open a connection to the bus. */
905 connection = xd_initialize (bus);
906
907 /* Create the message. */
f5306ca3
MA
908 dmessage = dbus_message_new_signal ((char *) SDATA (path),
909 (char *) SDATA (interface),
910 (char *) SDATA (signal));
033b73e2
MA
911 if (dmessage == NULL)
912 {
913 UNGCPRO;
914 xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
915 }
916
917 UNGCPRO;
918
54371585
MA
919 /* Initialize parameter list of message. */
920 dbus_message_iter_init_append (dmessage, &iter);
921
033b73e2
MA
922 /* Append parameters to the message. */
923 for (i = 5; i < nargs; ++i)
924 {
925 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
926 XD_DEBUG_MESSAGE ("Parameter%d %s",
87cf1a39 927 i-4, SDATA (format2 ("%s", args[i], Qnil)));
033b73e2 928
87cf1a39
MA
929 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
930 if (XD_DBUS_TYPE_P (args[i]))
54371585 931 ++i;
033b73e2 932
87cf1a39
MA
933 /* Check for valid signature. We use DBUS_TYPE_INVALID is
934 indication that there is no parent type. */
935 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
936
54371585 937 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
938 }
939
940 /* Send the message. The message is just added to the outgoing
941 message queue. */
942 if (!dbus_connection_send (connection, dmessage, NULL))
943 xsignal1 (Qdbus_error, build_string ("Cannot send message"));
944
945 /* Flush connection to ensure the message is handled. */
946 dbus_connection_flush (connection);
947
948 XD_DEBUG_MESSAGE ("Signal sent");
949
950 /* Cleanup. */
951 dbus_message_unref (dmessage);
952
953 /* Return. */
954 return Qt;
955}
956
957/* Read queued incoming message of the D-Bus BUS. BUS is a Lisp
958 symbol, either :system or :session. */
96faeb40 959Lisp_Object
033b73e2
MA
960xd_read_message (bus)
961 Lisp_Object bus;
962{
a31d47c7 963 Lisp_Object args, key, value;
033b73e2 964 struct gcpro gcpro1;
15f16c1b 965 struct input_event event;
033b73e2
MA
966 DBusConnection *connection;
967 DBusMessage *dmessage;
968 DBusMessageIter iter;
eb7c7bf5 969 unsigned int dtype;
17bc8f94 970 int mtype;
a31d47c7 971 char uname[DBUS_MAXIMUM_NAME_LENGTH];
52da95fa
MA
972 char path[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; /* Unlimited in D-Bus spec. */
973 char interface[DBUS_MAXIMUM_NAME_LENGTH];
974 char member[DBUS_MAXIMUM_NAME_LENGTH];
39abdd4a 975
033b73e2
MA
976 /* Open a connection to the bus. */
977 connection = xd_initialize (bus);
978
979 /* Non blocking read of the next available message. */
980 dbus_connection_read_write (connection, 0);
981 dmessage = dbus_connection_pop_message (connection);
982
983 /* Return if there is no queued message. */
984 if (dmessage == NULL)
17bc8f94 985 return Qnil;
033b73e2
MA
986
987 /* Collect the parameters. */
a31d47c7
MA
988 args = Qnil;
989 GCPRO1 (args);
033b73e2 990
033b73e2 991 /* Loop over the resulting parameters. Construct a list. */
17bc8f94 992 if (dbus_message_iter_init (dmessage, &iter))
033b73e2 993 {
17bc8f94
MA
994 while ((dtype = dbus_message_iter_get_arg_type (&iter))
995 != DBUS_TYPE_INVALID)
996 {
997 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
998 dbus_message_iter_next (&iter);
999 }
1000 /* The arguments are stored in reverse order. Reorder them. */
1001 args = Fnreverse (args);
033b73e2
MA
1002 }
1003
17bc8f94
MA
1004 /* Read message type, unique name, object path, interface and member
1005 from the message. */
1006 mtype = dbus_message_get_type (dmessage);
a31d47c7 1007 strcpy (uname, dbus_message_get_sender (dmessage));
39abdd4a
MA
1008 strcpy (path, dbus_message_get_path (dmessage));
1009 strcpy (interface, dbus_message_get_interface (dmessage));
1010 strcpy (member, dbus_message_get_member (dmessage));
1011
17bc8f94
MA
1012 XD_DEBUG_MESSAGE ("Event received: %d %s %s %s %s %s",
1013 mtype, uname, path, interface, member,
1014 SDATA (format2 ("%s", args, Qnil)));
1015
a31d47c7
MA
1016 /* Search for a registered function of the message. */
1017 key = list3 (bus, build_string (interface), build_string (member));
1018 value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
1019
1020 /* Loop over the registered functions. Construct an event. */
1021 while (!NILP (value))
1022 {
1023 key = XCAR (value);
f5306ca3 1024 /* key has the structure (UNAME SERVICE PATH HANDLER). */
eb7c7bf5 1025 if (((uname == NULL)
f5306ca3
MA
1026 || (NILP (XCAR (key)))
1027 || (strcmp (uname, SDATA (XCAR (key))) == 0))
eb7c7bf5
MA
1028 && ((path == NULL)
1029 || (NILP (XCAR (XCDR (XCDR (key)))))
1030 || (strcmp (path, SDATA (XCAR (XCDR (XCDR (key))))) == 0))
1031 && (!NILP (XCAR (XCDR (XCDR (XCDR (key)))))))
a31d47c7
MA
1032 {
1033 EVENT_INIT (event);
1034 event.kind = DBUS_EVENT;
1035 event.frame_or_window = Qnil;
1036 event.arg = Fcons (XCAR (XCDR (XCDR (XCDR (key)))), args);
1037
1038 /* Add uname, path, interface and member to the event. */
1039 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1040 event.arg);
1041 event.arg = Fcons ((interface == NULL
1042 ? Qnil : build_string (interface)),
1043 event.arg);
1044 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1045 event.arg);
1046 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1047 event.arg);
1048
1049 /* Add the bus symbol to the event. */
1050 event.arg = Fcons (bus, event.arg);
1051
1052 /* Store it into the input event queue. */
1053 kbd_buffer_store_event (&event);
1054 }
1055 value = XCDR (value);
1056 }
033b73e2
MA
1057
1058 /* Cleanup. */
1059 dbus_message_unref (dmessage);
17bc8f94 1060 RETURN_UNGCPRO (Qnil);
033b73e2
MA
1061}
1062
1063/* Read queued incoming messages from the system and session buses. */
1064void
1065xd_read_queued_messages ()
1066{
96faeb40 1067
f5306ca3
MA
1068 /* Vdbus_registered_functions_table will be initialized as hash
1069 table in dbus.el. When this package isn't loaded yet, it doesn't
1070 make sense to handle D-Bus messages. Furthermore, we ignore all
1071 Lisp errors during the call. */
96faeb40
MA
1072 if (HASH_TABLE_P (Vdbus_registered_functions_table))
1073 {
1074 internal_condition_case_1 (xd_read_message, QCdbus_system_bus,
1075 Qerror, Fidentity);
1076 internal_condition_case_1 (xd_read_message, QCdbus_session_bus,
1077 Qerror, Fidentity);
1078 }
033b73e2
MA
1079}
1080
1081DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
1082 6, 6, 0,
1083 doc: /* Register for signal SIGNAL on the D-Bus BUS.
1084
1085BUS is either the symbol `:system' or the symbol `:session'.
1086
39abdd4a
MA
1087SERVICE is the D-Bus service name used by the sending D-Bus object.
1088It can be either a known name or the unique name of the D-Bus object
1089sending the signal. When SERVICE is nil, related signals from all
1090D-Bus objects shall be accepted.
033b73e2 1091
39abdd4a
MA
1092PATH is the D-Bus object path SERVICE is registered. It can also be
1093nil if the path name of incoming signals shall not be checked.
033b73e2 1094
39abdd4a
MA
1095INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
1096HANDLER is a Lisp function to be called when the signal is received.
1097It must accept as arguments the values SIGNAL is sending. INTERFACE,
1098SIGNAL and HANDLER must not be nil. Example:
033b73e2
MA
1099
1100\(defun my-signal-handler (device)
1101 (message "Device %s added" device))
1102
1103\(dbus-register-signal
52da95fa
MA
1104 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
1105 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
033b73e2 1106
f5306ca3
MA
1107 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
1108 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
033b73e2
MA
1109
1110`dbus-register-signal' returns an object, which can be used in
17bc8f94 1111`dbus-unregister-object' for removing the registration. */)
52da95fa
MA
1112 (bus, service, path, interface, signal, handler)
1113 Lisp_Object bus, service, path, interface, signal, handler;
033b73e2 1114{
17bc8f94 1115 Lisp_Object uname, key, key1, value;
033b73e2 1116 DBusConnection *connection;
52da95fa 1117 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
39abdd4a 1118 DBusError derror;
033b73e2
MA
1119
1120 /* Check parameters. */
1121 CHECK_SYMBOL (bus);
39abdd4a
MA
1122 if (!NILP (service)) CHECK_STRING (service);
1123 if (!NILP (path)) CHECK_STRING (path);
033b73e2 1124 CHECK_STRING (interface);
52da95fa 1125 CHECK_STRING (signal);
17bc8f94
MA
1126 if (!FUNCTIONP (handler))
1127 wrong_type_argument (intern ("functionp"), handler);
033b73e2 1128
52da95fa
MA
1129 /* Retrieve unique name of service. If service is a known name, we
1130 will register for the corresponding unique name, if any. Signals
1131 are sent always with the unique name as sender. Note: the unique
1132 name of "org.freedesktop.DBus" is that string itself. */
eb7c7bf5
MA
1133 if ((!NILP (service))
1134 && (strlen (SDATA (service)) > 0)
1135 && (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0)
1136 && (strncmp (SDATA (service), ":", 1) != 0))
f5306ca3
MA
1137 {
1138 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1139 /* When there is no unique name, we mark it with an empty
1140 string. */
1141 if (NILP (uname))
1142 uname = build_string ("");
1143 }
52da95fa 1144 else
f5306ca3 1145 uname = service;
52da95fa 1146
f5306ca3
MA
1147 /* Create a matching rule if the unique name exists (when no
1148 wildcard). */
1149 if (NILP (uname) || (strlen (SDATA (uname)) > 0))
1150 {
1151 /* Open a connection to the bus. */
1152 connection = xd_initialize (bus);
033b73e2 1153
f5306ca3
MA
1154 /* Create a rule to receive related signals. */
1155 sprintf (rule,
1156 "type='signal',interface='%s',member='%s'",
1157 SDATA (interface),
1158 SDATA (signal));
033b73e2 1159
f5306ca3
MA
1160 /* Add unique name and path to the rule if they are non-nil. */
1161 if (!NILP (uname))
1162 sprintf (rule, "%s,sender='%s'", rule, SDATA (uname));
39abdd4a 1163
f5306ca3
MA
1164 if (!NILP (path))
1165 sprintf (rule, "%s,path='%s'", rule, SDATA (path));
39abdd4a 1166
f5306ca3
MA
1167 /* Add the rule to the bus. */
1168 dbus_error_init (&derror);
1169 dbus_bus_add_match (connection, rule, &derror);
1170 if (dbus_error_is_set (&derror))
1171 XD_ERROR (derror);
033b73e2 1172
f5306ca3
MA
1173 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
1174 }
033b73e2 1175
39abdd4a 1176 /* Create a hash table entry. */
a31d47c7 1177 key = list3 (bus, interface, signal);
17bc8f94
MA
1178 key1 = list4 (uname, service, path, handler);
1179 value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
1180
1181 if (NILP (Fmember (key1, value)))
1182 Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
1183
1184 /* Return object. */
1185 return list2 (key, list3 (service, path, handler));
1186}
1187
1188DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
1189 6, 6, 0,
1190 doc: /* Register for method METHOD on the D-Bus BUS.
1191
1192BUS is either the symbol `:system' or the symbol `:session'.
1193
1194SERVICE is the D-Bus service name of the D-Bus object METHOD is
1195registered for. It must be a known name.
1196
1197PATH is the D-Bus object path SERVICE is registered. INTERFACE is the
1198interface offered by SERVICE. It must provide METHOD. HANDLER is a
1199Lisp function to be called when a method call is received. It must
1200accept the input arguments of METHOD. The return value of HANDLER is
1201used for composing the returning D-Bus message.
1202
1203The function is not fully implemented and documented. Don't use it. */)
1204 (bus, service, path, interface, method, handler)
1205 Lisp_Object bus, service, path, interface, method, handler;
1206{
1207 Lisp_Object key, key1, value;
1208 DBusConnection *connection;
1209 int result;
1210 DBusError derror;
1211
1212 if (NILP (Vdbus_debug))
1213 xsignal1 (Qdbus_error, build_string ("Not implemented yet"));
1214
1215 /* Check parameters. */
1216 CHECK_SYMBOL (bus);
1217 CHECK_STRING (service);
1218 CHECK_STRING (path);
1219 CHECK_STRING (interface);
1220 CHECK_STRING (method);
1221 if (!FUNCTIONP (handler))
1222 wrong_type_argument (intern ("functionp"), handler);
1223 /* TODO: We must check for a valid service name, otherwise there is
1224 a segmentation fault. */
1225
1226 /* Open a connection to the bus. */
1227 connection = xd_initialize (bus);
1228
1229 /* Request the known name from the bus. We can ignore the result,
1230 it is set to -1 if there is an error - kind of redundancy. */
1231 dbus_error_init (&derror);
1232 result = dbus_bus_request_name (connection, SDATA (service), 0, &derror);
1233 if (dbus_error_is_set (&derror))
1234 XD_ERROR (derror);
1235
1236 /* Create a hash table entry. */
1237 key = list3 (bus, interface, method);
1238 key1 = list4 (Qnil, service, path, handler);
a31d47c7
MA
1239 value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
1240
17bc8f94
MA
1241 /* We use nil for the unique name, because the method might be
1242 called from everybody. */
1243 if (NILP (Fmember (key1, value)))
1244 Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
033b73e2 1245
f5306ca3
MA
1246 /* Return object. */
1247 return list2 (key, list3 (service, path, handler));
033b73e2
MA
1248}
1249
17bc8f94 1250DEFUN ("dbus-unregister-object", Fdbus_unregister_object, Sdbus_unregister_object,
033b73e2
MA
1251 1, 1, 0,
1252 doc: /* Unregister OBJECT from the D-Bus.
17bc8f94
MA
1253OBJECT must be the result of a preceding `dbus-register-signal' or
1254`dbus-register-method' call. It returns t if OBJECT has been
1255unregistered, nil otherwise. */)
033b73e2
MA
1256 (object)
1257 Lisp_Object object;
1258{
f5306ca3
MA
1259 Lisp_Object value;
1260 struct gcpro gcpro1;
033b73e2 1261
f5306ca3 1262 /* Check parameter. */
17bc8f94
MA
1263 if (!(CONSP (object) && (!NILP (XCAR (object))) && CONSP (XCDR (object))))
1264 wrong_type_argument (intern ("D-Bus"), object);
f5306ca3
MA
1265
1266 /* Find the corresponding entry in the hash table. */
1267 value = Fgethash (XCAR (object), Vdbus_registered_functions_table, Qnil);
1268
1269 /* Loop over the registered functions. */
1270 while (!NILP (value))
1271 {
1272 GCPRO1 (value);
1273
1274 /* (car value) has the structure (UNAME SERVICE PATH HANDLER).
1275 (cdr object) has the structure ((SERVICE PATH HANDLER) ...). */
1276 if (!NILP (Fequal (XCDR (XCAR (value)), XCAR (XCDR (object)))))
1277 {
1278 /* Compute new hash value. */
1279 value = Fdelete (XCAR (value),
1280 Fgethash (XCAR (object),
1281 Vdbus_registered_functions_table, Qnil));
1282 if (NILP (value))
1283 Fremhash (XCAR (object), Vdbus_registered_functions_table);
1284 else
1285 Fputhash (XCAR (object), value, Vdbus_registered_functions_table);
1286 RETURN_UNGCPRO (Qt);
1287 }
1288 UNGCPRO;
1289 value = XCDR (value);
1290 }
033b73e2
MA
1291
1292 /* Return. */
1293 return Qnil;
1294}
1295
1296\f
1297void
1298syms_of_dbusbind ()
1299{
1300
1301 Qdbus_get_unique_name = intern ("dbus-get-unique-name");
1302 staticpro (&Qdbus_get_unique_name);
1303 defsubr (&Sdbus_get_unique_name);
1304
1305 Qdbus_call_method = intern ("dbus-call-method");
1306 staticpro (&Qdbus_call_method);
1307 defsubr (&Sdbus_call_method);
1308
1309 Qdbus_send_signal = intern ("dbus-send-signal");
1310 staticpro (&Qdbus_send_signal);
1311 defsubr (&Sdbus_send_signal);
1312
1313 Qdbus_register_signal = intern ("dbus-register-signal");
1314 staticpro (&Qdbus_register_signal);
1315 defsubr (&Sdbus_register_signal);
1316
17bc8f94
MA
1317 Qdbus_register_method = intern ("dbus-register-method");
1318 staticpro (&Qdbus_register_method);
1319 defsubr (&Sdbus_register_method);
1320
1321 Qdbus_unregister_object = intern ("dbus-unregister-object");
1322 staticpro (&Qdbus_unregister_object);
1323 defsubr (&Sdbus_unregister_object);
033b73e2
MA
1324
1325 Qdbus_error = intern ("dbus-error");
1326 staticpro (&Qdbus_error);
1327 Fput (Qdbus_error, Qerror_conditions,
1328 list2 (Qdbus_error, Qerror));
1329 Fput (Qdbus_error, Qerror_message,
1330 build_string ("D-Bus error"));
1331
39abdd4a
MA
1332 QCdbus_system_bus = intern (":system");
1333 staticpro (&QCdbus_system_bus);
1334
1335 QCdbus_session_bus = intern (":session");
1336 staticpro (&QCdbus_session_bus);
033b73e2 1337
54371585
MA
1338 QCdbus_type_byte = intern (":byte");
1339 staticpro (&QCdbus_type_byte);
1340
1341 QCdbus_type_boolean = intern (":boolean");
1342 staticpro (&QCdbus_type_boolean);
1343
1344 QCdbus_type_int16 = intern (":int16");
1345 staticpro (&QCdbus_type_int16);
1346
1347 QCdbus_type_uint16 = intern (":uint16");
1348 staticpro (&QCdbus_type_uint16);
1349
1350 QCdbus_type_int32 = intern (":int32");
1351 staticpro (&QCdbus_type_int32);
1352
1353 QCdbus_type_uint32 = intern (":uint32");
1354 staticpro (&QCdbus_type_uint32);
1355
1356 QCdbus_type_int64 = intern (":int64");
1357 staticpro (&QCdbus_type_int64);
1358
1359 QCdbus_type_uint64 = intern (":uint64");
1360 staticpro (&QCdbus_type_uint64);
1361
1362 QCdbus_type_double = intern (":double");
1363 staticpro (&QCdbus_type_double);
1364
1365 QCdbus_type_string = intern (":string");
1366 staticpro (&QCdbus_type_string);
1367
1368 QCdbus_type_object_path = intern (":object-path");
1369 staticpro (&QCdbus_type_object_path);
1370
1371 QCdbus_type_signature = intern (":signature");
1372 staticpro (&QCdbus_type_signature);
1373
1374 QCdbus_type_array = intern (":array");
1375 staticpro (&QCdbus_type_array);
1376
1377 QCdbus_type_variant = intern (":variant");
1378 staticpro (&QCdbus_type_variant);
1379
1380 QCdbus_type_struct = intern (":struct");
1381 staticpro (&QCdbus_type_struct);
1382
1383 QCdbus_type_dict_entry = intern (":dict-entry");
1384 staticpro (&QCdbus_type_dict_entry);
1385
39abdd4a
MA
1386 DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table,
1387 doc: /* Hash table of registered functions for D-Bus.
f5306ca3 1388The key in the hash table is the list (BUS INTERFACE MEMBER). BUS is
a31d47c7
MA
1389either the symbol `:system' or the symbol `:session'. INTERFACE is a
1390string which denotes a D-Bus interface, and MEMBER, also a string, is
1391either a method or a signal INTERFACE is offering. All arguments but
1392BUS must not be nil.
1393
f5306ca3
MA
1394The value in the hash table is a list of quadruple lists
1395\((UNAME SERVICE PATH HANDLER) (UNAME SERVICE PATH HANDLER) ...).
a31d47c7
MA
1396SERVICE is the service name as registered, UNAME is the corresponding
1397unique name. PATH is the object path of the sending object. All of
f5306ca3
MA
1398them can be nil, which means a wildcard then. HANDLER is the function
1399to be called when a D-Bus message, which matches the key criteria,
a31d47c7 1400arrives. */);
39abdd4a
MA
1401 /* We initialize Vdbus_registered_functions_table in dbus.el,
1402 because we need to define a hash table function first. */
1403 Vdbus_registered_functions_table = Qnil;
033b73e2
MA
1404
1405 DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
39abdd4a 1406 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
1407#ifdef DBUS_DEBUG
1408 Vdbus_debug = Qt;
1409#else
1410 Vdbus_debug = Qnil;
1411#endif
1412
1413 Fprovide (intern ("dbusbind"), Qnil);
1414
1415}
1416
1417#endif /* HAVE_DBUS */
79f10da0
MB
1418
1419/* arch-tag: 0e828477-b571-4fe4-b559-5c9211bc14b8
1420 (do not change this comment) */