Add Bug#.
[bpt/emacs.git] / src / dbusbind.c
CommitLineData
033b73e2 1/* Elisp bindings for D-Bus.
73b0cd50 2 Copyright (C) 2007-2011 Free Software Foundation, Inc.
033b73e2
MA
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
033b73e2 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
033b73e2
MA
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
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
033b73e2 18
08a494a3 19#include <config.h>
033b73e2
MA
20
21#ifdef HAVE_DBUS
f5306ca3 22#include <stdio.h>
033b73e2 23#include <dbus/dbus.h>
d7306fe6 24#include <setjmp.h>
033b73e2
MA
25#include "lisp.h"
26#include "frame.h"
27#include "termhooks.h"
28#include "keyboard.h"
3fad2ad2 29#include "process.h"
033b73e2
MA
30
31\f
32/* Subroutines. */
955cbe7b
PE
33static Lisp_Object Qdbus_init_bus;
34static Lisp_Object Qdbus_close_bus;
35static Lisp_Object Qdbus_get_unique_name;
36static Lisp_Object Qdbus_call_method;
37static Lisp_Object Qdbus_call_method_asynchronously;
38static Lisp_Object Qdbus_method_return_internal;
39static Lisp_Object Qdbus_method_error_internal;
40static Lisp_Object Qdbus_send_signal;
41static Lisp_Object Qdbus_register_service;
42static Lisp_Object Qdbus_register_signal;
43static Lisp_Object Qdbus_register_method;
033b73e2
MA
44
45/* D-Bus error symbol. */
955cbe7b 46static Lisp_Object Qdbus_error;
033b73e2
MA
47
48/* Lisp symbols of the system and session buses. */
955cbe7b 49static Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 50
90b3fc84 51/* Lisp symbol for method call timeout. */
955cbe7b 52static Lisp_Object QCdbus_timeout;
90b3fc84 53
5b83ba18 54/* Lisp symbols for name request flags. */
955cbe7b
PE
55static Lisp_Object QCdbus_request_name_allow_replacement;
56static Lisp_Object QCdbus_request_name_replace_existing;
57static Lisp_Object QCdbus_request_name_do_not_queue;
5b83ba18
MA
58
59/* Lisp symbols for name request replies. */
955cbe7b
PE
60static Lisp_Object QCdbus_request_name_reply_primary_owner;
61static Lisp_Object QCdbus_request_name_reply_in_queue;
62static Lisp_Object QCdbus_request_name_reply_exists;
63static Lisp_Object QCdbus_request_name_reply_already_owner;
5b83ba18 64
54371585 65/* Lisp symbols of D-Bus types. */
955cbe7b
PE
66static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
67static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
68static Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
69static Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
70static Lisp_Object QCdbus_type_double, QCdbus_type_string;
71static Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
da1fec2b 72#ifdef DBUS_TYPE_UNIX_FD
b4289b64 73static Lisp_Object QCdbus_type_unix_fd;
da1fec2b 74#endif
955cbe7b
PE
75static Lisp_Object QCdbus_type_array, QCdbus_type_variant;
76static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
54371585 77
1dae9197 78/* Whether we are reading a D-Bus event. */
16390cd2 79static int xd_in_read_queued_messages = 0;
1dae9197 80
033b73e2
MA
81\f
82/* We use "xd_" and "XD_" as prefix for all internal symbols, because
83 we don't want to poison other namespaces with "dbus_". */
84
1dae9197
MA
85/* Raise a signal. If we are reading events, we cannot signal; we
86 throw to xd_read_queued_messages then. */
87#define XD_SIGNAL1(arg) \
88 do { \
89 if (xd_in_read_queued_messages) \
90 Fthrow (Qdbus_error, Qnil); \
91 else \
92 xsignal1 (Qdbus_error, arg); \
93 } while (0)
94
95#define XD_SIGNAL2(arg1, arg2) \
96 do { \
97 if (xd_in_read_queued_messages) \
98 Fthrow (Qdbus_error, Qnil); \
99 else \
100 xsignal2 (Qdbus_error, arg1, arg2); \
101 } while (0)
102
103#define XD_SIGNAL3(arg1, arg2, arg3) \
104 do { \
105 if (xd_in_read_queued_messages) \
106 Fthrow (Qdbus_error, Qnil); \
107 else \
108 xsignal3 (Qdbus_error, arg1, arg2, arg3); \
109 } while (0)
110
54371585 111/* Raise a Lisp error from a D-Bus ERROR. */
033b73e2 112#define XD_ERROR(error) \
17bc8f94 113 do { \
033b73e2 114 char s[1024]; \
4baa2377 115 strncpy (s, error.message, 1023); \
033b73e2
MA
116 dbus_error_free (&error); \
117 /* Remove the trailing newline. */ \
118 if (strchr (s, '\n') != NULL) \
119 s[strlen (s) - 1] = '\0'; \
1dae9197 120 XD_SIGNAL1 (build_string (s)); \
17bc8f94 121 } while (0)
033b73e2
MA
122
123/* Macros for debugging. In order to enable them, build with
0c372655 124 "MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */
033b73e2
MA
125#ifdef DBUS_DEBUG
126#define XD_DEBUG_MESSAGE(...) \
17bc8f94 127 do { \
033b73e2 128 char s[1024]; \
4baa2377 129 snprintf (s, 1023, __VA_ARGS__); \
033b73e2
MA
130 printf ("%s: %s\n", __func__, s); \
131 message ("%s: %s", __func__, s); \
17bc8f94 132 } while (0)
033b73e2 133#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
17bc8f94
MA
134 do { \
135 if (!valid_lisp_object_p (object)) \
136 { \
137 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
1dae9197 138 XD_SIGNAL1 (build_string ("Assertion failure")); \
17bc8f94
MA
139 } \
140 } while (0)
033b73e2
MA
141
142#else /* !DBUS_DEBUG */
17bc8f94
MA
143#define XD_DEBUG_MESSAGE(...) \
144 do { \
145 if (!NILP (Vdbus_debug)) \
146 { \
147 char s[1024]; \
4baa2377 148 snprintf (s, 1023, __VA_ARGS__); \
17bc8f94 149 message ("%s: %s", __func__, s); \
80f9d13b 150 } \
17bc8f94 151 } while (0)
033b73e2
MA
152#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
153#endif
154
87cf1a39 155/* Check whether TYPE is a basic DBusType. */
da1fec2b
MA
156#ifdef DBUS_TYPE_UNIX_FD
157#define XD_BASIC_DBUS_TYPE(type) \
158 ((type == DBUS_TYPE_BYTE) \
159 || (type == DBUS_TYPE_BOOLEAN) \
160 || (type == DBUS_TYPE_INT16) \
161 || (type == DBUS_TYPE_UINT16) \
162 || (type == DBUS_TYPE_INT32) \
163 || (type == DBUS_TYPE_UINT32) \
164 || (type == DBUS_TYPE_INT64) \
165 || (type == DBUS_TYPE_UINT64) \
166 || (type == DBUS_TYPE_DOUBLE) \
167 || (type == DBUS_TYPE_STRING) \
168 || (type == DBUS_TYPE_OBJECT_PATH) \
01768686 169 || (type == DBUS_TYPE_SIGNATURE) \
da1fec2b
MA
170 || (type == DBUS_TYPE_UNIX_FD))
171#else
87cf1a39
MA
172#define XD_BASIC_DBUS_TYPE(type) \
173 ((type == DBUS_TYPE_BYTE) \
174 || (type == DBUS_TYPE_BOOLEAN) \
175 || (type == DBUS_TYPE_INT16) \
176 || (type == DBUS_TYPE_UINT16) \
177 || (type == DBUS_TYPE_INT32) \
178 || (type == DBUS_TYPE_UINT32) \
179 || (type == DBUS_TYPE_INT64) \
180 || (type == DBUS_TYPE_UINT64) \
181 || (type == DBUS_TYPE_DOUBLE) \
182 || (type == DBUS_TYPE_STRING) \
183 || (type == DBUS_TYPE_OBJECT_PATH) \
184 || (type == DBUS_TYPE_SIGNATURE))
da1fec2b 185#endif
87cf1a39 186
78c38319
MA
187/* This was a macro. On Solaris 2.11 it was said to compile for
188 hours, when optimzation is enabled. So we have transferred it into
189 a function. */
54371585
MA
190/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
191 of the predefined D-Bus type symbols. */
78c38319 192static int
971de7fb 193xd_symbol_to_dbus_type (Lisp_Object object)
78c38319
MA
194{
195 return
196 ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE
197 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN
198 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16
199 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16
200 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32
201 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32
202 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64
203 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64
204 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE
205 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING
206 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH
207 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE
da1fec2b
MA
208#ifdef DBUS_TYPE_UNIX_FD
209 : (EQ (object, QCdbus_type_unix_fd)) ? DBUS_TYPE_UNIX_FD
210#endif
78c38319
MA
211 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY
212 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT
213 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT
214 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY
215 : DBUS_TYPE_INVALID);
216}
87cf1a39
MA
217
218/* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
219#define XD_DBUS_TYPE_P(object) \
78c38319 220 (SYMBOLP (object) && ((xd_symbol_to_dbus_type (object) != DBUS_TYPE_INVALID)))
54371585
MA
221
222/* Determine the DBusType of a given Lisp OBJECT. It is used to
033b73e2
MA
223 convert Lisp objects, being arguments of `dbus-call-method' or
224 `dbus-send-signal', into corresponding C values appended as
225 arguments to a D-Bus message. */
87cf1a39
MA
226#define XD_OBJECT_TO_DBUS_TYPE(object) \
227 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
228 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
229 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
230 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
231 : (STRINGP (object)) ? DBUS_TYPE_STRING \
78c38319 232 : (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object) \
07a4cb03
MA
233 : (CONSP (object)) \
234 ? ((XD_DBUS_TYPE_P (CAR_SAFE (object))) \
78c38319 235 ? ((XD_BASIC_DBUS_TYPE (xd_symbol_to_dbus_type (CAR_SAFE (object)))) \
07a4cb03 236 ? DBUS_TYPE_ARRAY \
78c38319 237 : xd_symbol_to_dbus_type (CAR_SAFE (object))) \
07a4cb03 238 : DBUS_TYPE_ARRAY) \
87cf1a39
MA
239 : DBUS_TYPE_INVALID)
240
241/* Return a list pointer which does not have a Lisp symbol as car. */
a8e72f4f 242#define XD_NEXT_VALUE(object) \
5125905e 243 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
87cf1a39 244
08686060
PE
245/* Check whether X is a valid dbus serial number. If valid, set
246 SERIAL to its value. Otherwise, signal an error. */
247#define CHECK_DBUS_SERIAL_GET_SERIAL(x, serial) \
248 do \
249 { \
250 dbus_uint32_t DBUS_SERIAL_MAX = -1; \
251 if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX) \
252 serial = XINT (x); \
253 else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX \
254 && FLOATP (x) \
255 && 0 <= XFLOAT_DATA (x) \
256 && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX) \
257 serial = XFLOAT_DATA (x); \
258 else \
259 xd_invalid_serial (x); \
260 } \
261 while (0)
262
263static void xd_invalid_serial (Lisp_Object) NO_RETURN;
264static void
265xd_invalid_serial (Lisp_Object x)
266{
267 signal_error ("Invalid dbus serial", x);
268}
269
87cf1a39
MA
270/* Compute SIGNATURE of OBJECT. It must have a form that it can be
271 used in dbus_message_iter_open_container. DTYPE is the DBusType
272 the object is related to. It is passed as argument, because it
273 cannot be detected in basic type objects, when they are preceded by
274 a type symbol. PARENT_TYPE is the DBusType of a container this
275 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
276 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
78c38319 277static void
971de7fb 278xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lisp_Object object)
033b73e2 279{
87cf1a39
MA
280 unsigned int subtype;
281 Lisp_Object elt;
282 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
283
284 elt = object;
033b73e2 285
033b73e2
MA
286 switch (dtype)
287 {
54371585
MA
288 case DBUS_TYPE_BYTE:
289 case DBUS_TYPE_UINT16:
033b73e2 290 case DBUS_TYPE_UINT32:
54371585 291 case DBUS_TYPE_UINT64:
da1fec2b
MA
292#ifdef DBUS_TYPE_UNIX_FD
293 case DBUS_TYPE_UNIX_FD:
294#endif
54371585 295 CHECK_NATNUM (object);
87cf1a39 296 sprintf (signature, "%c", dtype);
54371585 297 break;
87cf1a39 298
54371585
MA
299 case DBUS_TYPE_BOOLEAN:
300 if (!EQ (object, Qt) && !EQ (object, Qnil))
301 wrong_type_argument (intern ("booleanp"), object);
87cf1a39 302 sprintf (signature, "%c", dtype);
54371585 303 break;
87cf1a39 304
54371585 305 case DBUS_TYPE_INT16:
033b73e2 306 case DBUS_TYPE_INT32:
54371585
MA
307 case DBUS_TYPE_INT64:
308 CHECK_NUMBER (object);
87cf1a39 309 sprintf (signature, "%c", dtype);
54371585 310 break;
87cf1a39 311
033b73e2 312 case DBUS_TYPE_DOUBLE:
54371585 313 CHECK_FLOAT (object);
87cf1a39 314 sprintf (signature, "%c", dtype);
54371585 315 break;
87cf1a39 316
033b73e2 317 case DBUS_TYPE_STRING:
54371585
MA
318 case DBUS_TYPE_OBJECT_PATH:
319 case DBUS_TYPE_SIGNATURE:
320 CHECK_STRING (object);
87cf1a39 321 sprintf (signature, "%c", dtype);
54371585 322 break;
87cf1a39 323
54371585 324 case DBUS_TYPE_ARRAY:
9af5078b 325 /* Check that all list elements have the same D-Bus type. For
87cf1a39
MA
326 complex element types, we just check the container type, not
327 the whole element's signature. */
54371585 328 CHECK_CONS (object);
87cf1a39 329
5125905e
MA
330 /* Type symbol is optional. */
331 if (EQ (QCdbus_type_array, CAR_SAFE (elt)))
87cf1a39 332 elt = XD_NEXT_VALUE (elt);
5125905e
MA
333
334 /* If the array is empty, DBUS_TYPE_STRING is the default
335 element type. */
336 if (NILP (elt))
337 {
338 subtype = DBUS_TYPE_STRING;
339 strcpy (x, DBUS_TYPE_STRING_AS_STRING);
340 }
341 else
342 {
343 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
344 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
345 }
346
347 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
348 only element, the value of this element is used as he array's
349 element signature. */
350 if ((subtype == DBUS_TYPE_SIGNATURE)
351 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
352 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
59d6fe83 353 strcpy (x, SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39
MA
354
355 while (!NILP (elt))
356 {
5125905e
MA
357 if (subtype != XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)))
358 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (elt));
359 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39
MA
360 }
361
362 sprintf (signature, "%c%s", dtype, x);
54371585 363 break;
87cf1a39 364
54371585 365 case DBUS_TYPE_VARIANT:
9af5078b 366 /* Check that there is exactly one list element. */
54371585 367 CHECK_CONS (object);
87cf1a39
MA
368
369 elt = XD_NEXT_VALUE (elt);
5125905e
MA
370 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
371 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 372
5125905e 373 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 374 wrong_type_argument (intern ("D-Bus"),
5125905e 375 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39 376
a271e124 377 sprintf (signature, "%c", dtype);
54371585 378 break;
87cf1a39 379
54371585 380 case DBUS_TYPE_STRUCT:
9af5078b
MA
381 /* A struct list might contain any number of elements with
382 different types. No further check needed. */
87cf1a39
MA
383 CHECK_CONS (object);
384
385 elt = XD_NEXT_VALUE (elt);
386
387 /* Compose the signature from the elements. It is enclosed by
388 parentheses. */
389 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
390 while (!NILP (elt))
391 {
5125905e
MA
392 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
393 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 394 strcat (signature, x);
5125905e 395 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39 396 }
0ef50993 397 strcat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
54371585 398 break;
54371585 399
87cf1a39 400 case DBUS_TYPE_DICT_ENTRY:
9af5078b
MA
401 /* Check that there are exactly two list elements, and the first
402 one is of basic type. The dictionary entry itself must be an
403 element of an array. */
87cf1a39 404 CHECK_CONS (object);
54371585 405
9af5078b 406 /* Check the parent object type. */
87cf1a39
MA
407 if (parent_type != DBUS_TYPE_ARRAY)
408 wrong_type_argument (intern ("D-Bus"), object);
54371585 409
87cf1a39
MA
410 /* Compose the signature from the elements. It is enclosed by
411 curly braces. */
412 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
54371585 413
87cf1a39
MA
414 /* First element. */
415 elt = XD_NEXT_VALUE (elt);
5125905e
MA
416 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
417 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 418 strcat (signature, x);
54371585 419
87cf1a39 420 if (!XD_BASIC_DBUS_TYPE (subtype))
5125905e 421 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
54371585 422
87cf1a39 423 /* Second element. */
5125905e
MA
424 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
425 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
426 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 427 strcat (signature, x);
54371585 428
5125905e 429 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 430 wrong_type_argument (intern ("D-Bus"),
5125905e 431 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
54371585 432
87cf1a39 433 /* Closing signature. */
0ef50993 434 strcat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
87cf1a39 435 break;
54371585 436
87cf1a39
MA
437 default:
438 wrong_type_argument (intern ("D-Bus"), object);
54371585
MA
439 }
440
87cf1a39
MA
441 XD_DEBUG_MESSAGE ("%s", signature);
442}
54371585 443
87cf1a39
MA
444/* Append C value, extracted from Lisp OBJECT, to iteration ITER.
445 DTYPE must be a valid DBusType. It is used to convert Lisp
446 objects, being arguments of `dbus-call-method' or
447 `dbus-send-signal', into corresponding C values appended as
448 arguments to a D-Bus message. */
78c38319 449static void
971de7fb 450xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
87cf1a39 451{
87cf1a39
MA
452 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
453 DBusMessageIter subiter;
87cf1a39
MA
454
455 if (XD_BASIC_DBUS_TYPE (dtype))
17bc8f94
MA
456 switch (dtype)
457 {
458 case DBUS_TYPE_BYTE:
2d1fc3c7 459 CHECK_NATNUM (object);
54371585 460 {
2d1fc3c7 461 unsigned char val = XFASTINT (object) & 0xFF;
17bc8f94
MA
462 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
463 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 464 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
465 return;
466 }
87cf1a39 467
17bc8f94
MA
468 case DBUS_TYPE_BOOLEAN:
469 {
470 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
471 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
472 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 473 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
474 return;
475 }
87cf1a39 476
17bc8f94 477 case DBUS_TYPE_INT16:
e454a4a3 478 CHECK_NUMBER (object);
17bc8f94
MA
479 {
480 dbus_int16_t val = XINT (object);
481 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
482 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 483 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
484 return;
485 }
87cf1a39 486
17bc8f94 487 case DBUS_TYPE_UINT16:
2d1fc3c7 488 CHECK_NATNUM (object);
17bc8f94 489 {
2d1fc3c7 490 dbus_uint16_t val = XFASTINT (object);
17bc8f94
MA
491 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
492 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 493 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
494 return;
495 }
87cf1a39 496
17bc8f94 497 case DBUS_TYPE_INT32:
e454a4a3 498 CHECK_NUMBER (object);
17bc8f94
MA
499 {
500 dbus_int32_t val = XINT (object);
501 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
502 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 503 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
504 return;
505 }
87cf1a39 506
17bc8f94 507 case DBUS_TYPE_UINT32:
da1fec2b
MA
508#ifdef DBUS_TYPE_UNIX_FD
509 case DBUS_TYPE_UNIX_FD:
510#endif
2d1fc3c7 511 CHECK_NATNUM (object);
17bc8f94 512 {
2d1fc3c7 513 dbus_uint32_t val = XFASTINT (object);
17bc8f94
MA
514 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
515 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 516 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
517 return;
518 }
87cf1a39 519
17bc8f94 520 case DBUS_TYPE_INT64:
e454a4a3 521 CHECK_NUMBER (object);
17bc8f94
MA
522 {
523 dbus_int64_t val = XINT (object);
524 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
525 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 526 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
527 return;
528 }
87cf1a39 529
17bc8f94 530 case DBUS_TYPE_UINT64:
2d1fc3c7 531 CHECK_NATNUM (object);
17bc8f94 532 {
2d1fc3c7
PE
533 dbus_uint64_t val = XFASTINT (object);
534 XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, XFASTINT (object));
17bc8f94 535 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 536 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94 537 return;
54371585 538 }
87cf1a39 539
17bc8f94 540 case DBUS_TYPE_DOUBLE:
e454a4a3 541 CHECK_FLOAT (object);
f601cdf3
KR
542 {
543 double val = XFLOAT_DATA (object);
544 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
545 if (!dbus_message_iter_append_basic (iter, dtype, &val))
546 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
547 return;
548 }
17bc8f94
MA
549
550 case DBUS_TYPE_STRING:
551 case DBUS_TYPE_OBJECT_PATH:
552 case DBUS_TYPE_SIGNATURE:
e454a4a3 553 CHECK_STRING (object);
17bc8f94 554 {
e454a4a3
SM
555 /* We need to send a valid UTF-8 string. We could encode `object'
556 but by not encoding it, we guarantee it's valid utf-8, even if
557 it contains eight-bit-bytes. Of course, you can still send
558 manually-crafted junk by passing a unibyte string. */
59d6fe83 559 char *val = SSDATA (object);
17bc8f94
MA
560 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
561 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 562 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
563 return;
564 }
565 }
87cf1a39
MA
566
567 else /* Compound types. */
568 {
569
570 /* All compound types except array have a type symbol. For
571 array, it is optional. Skip it. */
5125905e 572 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))))
87cf1a39
MA
573 object = XD_NEXT_VALUE (object);
574
575 /* Open new subiteration. */
576 switch (dtype)
577 {
578 case DBUS_TYPE_ARRAY:
5125905e
MA
579 /* An array has only elements of the same type. So it is
580 sufficient to check the first element's signature
581 only. */
582
583 if (NILP (object))
584 /* If the array is empty, DBUS_TYPE_STRING is the default
585 element type. */
586 strcpy (signature, DBUS_TYPE_STRING_AS_STRING);
587
588 else
589 /* If the element type is DBUS_TYPE_SIGNATURE, and this is
590 the only element, the value of this element is used as
591 the array's element signature. */
592 if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))
593 == DBUS_TYPE_SIGNATURE)
594 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object)))
595 && NILP (CDR_SAFE (XD_NEXT_VALUE (object))))
596 {
59d6fe83 597 strcpy (signature, SSDATA (CAR_SAFE (XD_NEXT_VALUE (object))));
5125905e
MA
598 object = CDR_SAFE (XD_NEXT_VALUE (object));
599 }
600
601 else
602 xd_signature (signature,
603 XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
604 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
605
606 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
607 SDATA (format2 ("%s", object, Qnil)));
608 if (!dbus_message_iter_open_container (iter, dtype,
609 signature, &subiter))
1dae9197
MA
610 XD_SIGNAL3 (build_string ("Cannot open container"),
611 make_number (dtype), build_string (signature));
5125905e
MA
612 break;
613
87cf1a39 614 case DBUS_TYPE_VARIANT:
5125905e
MA
615 /* A variant has just one element. */
616 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
617 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
618
87cf1a39
MA
619 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
620 SDATA (format2 ("%s", object, Qnil)));
621 if (!dbus_message_iter_open_container (iter, dtype,
622 signature, &subiter))
1dae9197
MA
623 XD_SIGNAL3 (build_string ("Cannot open container"),
624 make_number (dtype), build_string (signature));
87cf1a39
MA
625 break;
626
627 case DBUS_TYPE_STRUCT:
628 case DBUS_TYPE_DICT_ENTRY:
9af5078b 629 /* These containers do not require a signature. */
87cf1a39
MA
630 XD_DEBUG_MESSAGE ("%c %s", dtype,
631 SDATA (format2 ("%s", object, Qnil)));
632 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
1dae9197
MA
633 XD_SIGNAL2 (build_string ("Cannot open container"),
634 make_number (dtype));
87cf1a39
MA
635 break;
636 }
637
638 /* Loop over list elements. */
639 while (!NILP (object))
640 {
5125905e 641 dtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object));
87cf1a39
MA
642 object = XD_NEXT_VALUE (object);
643
5125905e 644 xd_append_arg (dtype, CAR_SAFE (object), &subiter);
87cf1a39 645
5125905e 646 object = CDR_SAFE (object);
87cf1a39
MA
647 }
648
9af5078b 649 /* Close the subiteration. */
87cf1a39 650 if (!dbus_message_iter_close_container (iter, &subiter))
1dae9197
MA
651 XD_SIGNAL2 (build_string ("Cannot close container"),
652 make_number (dtype));
87cf1a39 653 }
033b73e2
MA
654}
655
656/* Retrieve C value from a DBusMessageIter structure ITER, and return
657 a converted Lisp object. The type DTYPE of the argument of the
9af5078b
MA
658 D-Bus message must be a valid DBusType. Compound D-Bus types
659 result always in a Lisp list. */
78c38319 660static Lisp_Object
971de7fb 661xd_retrieve_arg (unsigned int dtype, DBusMessageIter *iter)
033b73e2
MA
662{
663
664 switch (dtype)
665 {
9af5078b 666 case DBUS_TYPE_BYTE:
9af5078b 667 {
17bc8f94 668 unsigned int val;
9af5078b 669 dbus_message_iter_get_basic (iter, &val);
17bc8f94 670 val = val & 0xFF;
9af5078b
MA
671 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
672 return make_number (val);
673 }
674
033b73e2
MA
675 case DBUS_TYPE_BOOLEAN:
676 {
677 dbus_bool_t val;
678 dbus_message_iter_get_basic (iter, &val);
87cf1a39 679 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
033b73e2
MA
680 return (val == FALSE) ? Qnil : Qt;
681 }
87cf1a39 682
17bc8f94 683 case DBUS_TYPE_INT16:
1cae01f7
AS
684 {
685 dbus_int16_t val;
686 dbus_message_iter_get_basic (iter, &val);
687 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
688 return make_number (val);
689 }
690
17bc8f94
MA
691 case DBUS_TYPE_UINT16:
692 {
693 dbus_uint16_t val;
694 dbus_message_iter_get_basic (iter, &val);
695 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
696 return make_number (val);
697 }
698
033b73e2 699 case DBUS_TYPE_INT32:
1cae01f7
AS
700 {
701 dbus_int32_t val;
702 dbus_message_iter_get_basic (iter, &val);
703 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
704 return make_fixnum_or_float (val);
705 }
706
033b73e2 707 case DBUS_TYPE_UINT32:
da1fec2b
MA
708#ifdef DBUS_TYPE_UNIX_FD
709 case DBUS_TYPE_UNIX_FD:
710#endif
033b73e2
MA
711 {
712 dbus_uint32_t val;
713 dbus_message_iter_get_basic (iter, &val);
17bc8f94 714 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
1cae01f7 715 return make_fixnum_or_float (val);
9af5078b
MA
716 }
717
718 case DBUS_TYPE_INT64:
1cae01f7
AS
719 {
720 dbus_int64_t val;
721 dbus_message_iter_get_basic (iter, &val);
722 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
723 return make_fixnum_or_float (val);
724 }
725
9af5078b
MA
726 case DBUS_TYPE_UINT64:
727 {
728 dbus_uint64_t val;
729 dbus_message_iter_get_basic (iter, &val);
17bc8f94 730 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
9af5078b
MA
731 return make_fixnum_or_float (val);
732 }
733
734 case DBUS_TYPE_DOUBLE:
735 {
736 double val;
737 dbus_message_iter_get_basic (iter, &val);
738 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
739 return make_float (val);
033b73e2 740 }
87cf1a39 741
033b73e2
MA
742 case DBUS_TYPE_STRING:
743 case DBUS_TYPE_OBJECT_PATH:
9af5078b 744 case DBUS_TYPE_SIGNATURE:
033b73e2
MA
745 {
746 char *val;
747 dbus_message_iter_get_basic (iter, &val);
87cf1a39 748 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
033b73e2
MA
749 return build_string (val);
750 }
87cf1a39 751
033b73e2
MA
752 case DBUS_TYPE_ARRAY:
753 case DBUS_TYPE_VARIANT:
754 case DBUS_TYPE_STRUCT:
755 case DBUS_TYPE_DICT_ENTRY:
756 {
757 Lisp_Object result;
758 struct gcpro gcpro1;
033b73e2
MA
759 DBusMessageIter subiter;
760 int subtype;
fa8e045a
MA
761 result = Qnil;
762 GCPRO1 (result);
033b73e2
MA
763 dbus_message_iter_recurse (iter, &subiter);
764 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
765 != DBUS_TYPE_INVALID)
766 {
767 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
768 dbus_message_iter_next (&subiter);
769 }
5125905e 770 XD_DEBUG_MESSAGE ("%c %s", dtype, SDATA (format2 ("%s", result, Qnil)));
033b73e2
MA
771 RETURN_UNGCPRO (Fnreverse (result));
772 }
87cf1a39 773
033b73e2 774 default:
87cf1a39 775 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
033b73e2
MA
776 return Qnil;
777 }
778}
779
0c372655
MA
780/* Initialize D-Bus connection. BUS is either a Lisp symbol, :system
781 or :session, or a string denoting the bus address. It tells which
782 D-Bus to initialize. If RAISE_ERROR is non-zero, signal an error
783 when the connection cannot be initialized. */
78c38319 784static DBusConnection *
2536a4b7 785xd_initialize (Lisp_Object bus, int raise_error)
033b73e2
MA
786{
787 DBusConnection *connection;
788 DBusError derror;
789
790 /* Parameter check. */
0c372655
MA
791 if (!STRINGP (bus))
792 {
793 CHECK_SYMBOL (bus);
794 if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus)))
795 {
796 if (raise_error)
797 XD_SIGNAL2 (build_string ("Wrong bus name"), bus);
798 else
799 return NULL;
800 }
033b73e2 801
0c372655
MA
802 /* We do not want to have an autolaunch for the session bus. */
803 if (EQ (bus, QCdbus_session_bus)
804 && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
805 {
806 if (raise_error)
807 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
808 else
809 return NULL;
810 }
811 }
3f56d3c6 812
033b73e2
MA
813 /* Open a connection to the bus. */
814 dbus_error_init (&derror);
815
0c372655 816 if (STRINGP (bus))
59d6fe83 817 connection = dbus_connection_open (SSDATA (bus), &derror);
033b73e2 818 else
0c372655
MA
819 if (EQ (bus, QCdbus_system_bus))
820 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
821 else
822 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
033b73e2
MA
823
824 if (dbus_error_is_set (&derror))
0c372655
MA
825 {
826 if (raise_error)
827 XD_ERROR (derror);
828 else
829 connection = NULL;
830 }
831
832 /* If it is not the system or session bus, we must register
833 ourselves. Otherwise, we have called dbus_bus_get, which has
834 configured us to exit if the connection closes - we undo this
835 setting. */
836 if (connection != NULL)
837 {
838 if (STRINGP (bus))
839 dbus_bus_register (connection, &derror);
840 else
841 dbus_connection_set_exit_on_disconnect (connection, FALSE);
842 }
843
844 if (dbus_error_is_set (&derror))
845 {
846 if (raise_error)
847 XD_ERROR (derror);
848 else
849 connection = NULL;
850 }
033b73e2 851
de06a2dd 852 if (connection == NULL && raise_error)
3f56d3c6 853 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
033b73e2 854
c1d5ce94
MA
855 /* Cleanup. */
856 dbus_error_free (&derror);
857
033b73e2
MA
858 /* Return the result. */
859 return connection;
860}
861
3fad2ad2 862/* Return the file descriptor for WATCH, -1 if not found. */
3fad2ad2
J
863static int
864xd_find_watch_fd (DBusWatch *watch)
058ed861 865{
eb4c6ace 866#if HAVE_DBUS_WATCH_GET_UNIX_FD
3fad2ad2
J
867 /* TODO: Reverse these on Win32, which prefers the opposite. */
868 int fd = dbus_watch_get_unix_fd (watch);
869 if (fd == -1)
870 fd = dbus_watch_get_socket (watch);
3f56d3c6 871#else
3fad2ad2 872 int fd = dbus_watch_get_fd (watch);
3f56d3c6 873#endif
3fad2ad2
J
874 return fd;
875}
3f56d3c6 876
08609ffd
MA
877/* Prototype. */
878static void
879xd_read_queued_messages (int fd, void *data, int for_read);
058ed861 880
3fad2ad2 881/* Start monitoring WATCH for possible I/O. */
3fad2ad2
J
882static dbus_bool_t
883xd_add_watch (DBusWatch *watch, void *data)
884{
885 unsigned int flags = dbus_watch_get_flags (watch);
886 int fd = xd_find_watch_fd (watch);
887
888 XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
889 fd, flags & DBUS_WATCH_WRITABLE,
890 dbus_watch_get_enabled (watch));
891
892 if (fd == -1)
893 return FALSE;
894
895 if (dbus_watch_get_enabled (watch))
896 {
897 if (flags & DBUS_WATCH_WRITABLE)
08609ffd 898 add_write_fd (fd, xd_read_queued_messages, data);
3fad2ad2 899 if (flags & DBUS_WATCH_READABLE)
08609ffd 900 add_read_fd (fd, xd_read_queued_messages, data);
3fad2ad2 901 }
058ed861
MA
902 return TRUE;
903}
904
3fad2ad2
J
905/* Stop monitoring WATCH for possible I/O.
906 DATA is the used bus, either a string or QCdbus_system_bus or
0c372655 907 QCdbus_session_bus. */
3fad2ad2 908static void
971de7fb 909xd_remove_watch (DBusWatch *watch, void *data)
058ed861 910{
3fad2ad2
J
911 unsigned int flags = dbus_watch_get_flags (watch);
912 int fd = xd_find_watch_fd (watch);
3f56d3c6 913
3fad2ad2
J
914 XD_DEBUG_MESSAGE ("fd %d", fd);
915
08609ffd
MA
916 if (fd == -1)
917 return;
777013f2 918
3fad2ad2 919 /* Unset session environment. */
b4289b64 920 if (XSYMBOL (QCdbus_session_bus) == data)
3fad2ad2
J
921 {
922 XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
923 unsetenv ("DBUS_SESSION_BUS_ADDRESS");
058ed861
MA
924 }
925
3fad2ad2
J
926 if (flags & DBUS_WATCH_WRITABLE)
927 delete_write_fd (fd);
928 if (flags & DBUS_WATCH_READABLE)
929 delete_read_fd (fd);
930}
931
932/* Toggle monitoring WATCH for possible I/O. */
3fad2ad2
J
933static void
934xd_toggle_watch (DBusWatch *watch, void *data)
935{
936 if (dbus_watch_get_enabled (watch))
937 xd_add_watch (watch, data);
938 else
939 xd_remove_watch (watch, data);
058ed861
MA
940}
941
942DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
0c372655 943 doc: /* Initialize connection to D-Bus BUS. */)
5842a27b 944 (Lisp_Object bus)
058ed861
MA
945{
946 DBusConnection *connection;
b4289b64 947 void *busp;
058ed861 948
b4289b64
MA
949 /* Check parameter. */
950 if (SYMBOLP (bus))
951 busp = XSYMBOL (bus);
952 else if (STRINGP (bus))
953 busp = XSTRING (bus);
954 else
955 wrong_type_argument (intern ("D-Bus"), bus);
371cac43 956
058ed861 957 /* Open a connection to the bus. */
2536a4b7 958 connection = xd_initialize (bus, TRUE);
058ed861 959
777013f2
MA
960 /* Add the watch functions. We pass also the bus as data, in order
961 to distinguish between the busses in xd_remove_watch. */
058ed861
MA
962 if (!dbus_connection_set_watch_functions (connection,
963 xd_add_watch,
964 xd_remove_watch,
3fad2ad2 965 xd_toggle_watch,
b4289b64 966 busp, NULL))
058ed861
MA
967 XD_SIGNAL1 (build_string ("Cannot add watch functions"));
968
0c372655
MA
969 /* Add bus to list of registered buses. */
970 Vdbus_registered_buses = Fcons (bus, Vdbus_registered_buses);
971
a79b0f28 972 /* We do not want to abort. */
78320123 973 putenv ((char *) "DBUS_FATAL_WARNINGS=0");
a79b0f28 974
0c372655
MA
975 /* Return. */
976 return Qnil;
977}
978
979DEFUN ("dbus-close-bus", Fdbus_close_bus, Sdbus_close_bus, 1, 1, 0,
980 doc: /* Close connection to D-Bus BUS. */)
981 (Lisp_Object bus)
982{
983 DBusConnection *connection;
984
985 /* Open a connection to the bus. */
986 connection = xd_initialize (bus, TRUE);
987
988 /* Decrement reference count to the bus. */
989 dbus_connection_unref (connection);
990
991 /* Remove bus from list of registered buses. */
992 Vdbus_registered_buses = Fdelete (bus, Vdbus_registered_buses);
993
058ed861
MA
994 /* Return. */
995 return Qnil;
996}
997
033b73e2
MA
998DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
999 1, 1, 0,
5125905e 1000 doc: /* Return the unique name of Emacs registered at D-Bus BUS. */)
5842a27b 1001 (Lisp_Object bus)
033b73e2
MA
1002{
1003 DBusConnection *connection;
48f7d213 1004 const char *name;
033b73e2 1005
033b73e2 1006 /* Open a connection to the bus. */
2536a4b7 1007 connection = xd_initialize (bus, TRUE);
033b73e2
MA
1008
1009 /* Request the name. */
48f7d213 1010 name = dbus_bus_get_unique_name (connection);
033b73e2 1011 if (name == NULL)
1dae9197 1012 XD_SIGNAL1 (build_string ("No unique name available"));
033b73e2
MA
1013
1014 /* Return. */
1015 return build_string (name);
1016}
1017
1018DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
1019 doc: /* Call METHOD on the D-Bus BUS.
1020
0c372655
MA
1021BUS is either a Lisp symbol, `:system' or `:session', or a string
1022denoting the bus address.
033b73e2
MA
1023
1024SERVICE is the D-Bus service name to be used. PATH is the D-Bus
1025object path SERVICE is registered at. INTERFACE is an interface
1026offered by SERVICE. It must provide METHOD.
1027
90b3fc84 1028If the parameter `:timeout' is given, the following integer TIMEOUT
f04bb9b2 1029specifies the maximum number of milliseconds the method call must
1574224c 1030return. The default value is 25,000. If the method call doesn't
48f7d213 1031return in time, a D-Bus error is raised.
90b3fc84 1032
033b73e2
MA
1033All other arguments ARGS are passed to METHOD as arguments. They are
1034converted into D-Bus types via the following rules:
1035
1036 t and nil => DBUS_TYPE_BOOLEAN
1037 number => DBUS_TYPE_UINT32
1038 integer => DBUS_TYPE_INT32
1039 float => DBUS_TYPE_DOUBLE
1040 string => DBUS_TYPE_STRING
87cf1a39 1041 list => DBUS_TYPE_ARRAY
033b73e2 1042
87cf1a39
MA
1043All arguments can be preceded by a type symbol. For details about
1044type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
1045
1046`dbus-call-method' returns the resulting values of METHOD as a list of
1047Lisp objects. The type conversion happens the other direction as for
87cf1a39
MA
1048input arguments. It follows the mapping rules:
1049
1050 DBUS_TYPE_BOOLEAN => t or nil
1051 DBUS_TYPE_BYTE => number
1052 DBUS_TYPE_UINT16 => number
1053 DBUS_TYPE_INT16 => integer
9af5078b 1054 DBUS_TYPE_UINT32 => number or float
da1fec2b 1055 DBUS_TYPE_UNIX_FD => number or float
9af5078b
MA
1056 DBUS_TYPE_INT32 => integer or float
1057 DBUS_TYPE_UINT64 => number or float
1058 DBUS_TYPE_INT64 => integer or float
87cf1a39
MA
1059 DBUS_TYPE_DOUBLE => float
1060 DBUS_TYPE_STRING => string
1061 DBUS_TYPE_OBJECT_PATH => string
1062 DBUS_TYPE_SIGNATURE => string
1063 DBUS_TYPE_ARRAY => list
1064 DBUS_TYPE_VARIANT => list
1065 DBUS_TYPE_STRUCT => list
1066 DBUS_TYPE_DICT_ENTRY => list
1067
1068Example:
033b73e2
MA
1069
1070\(dbus-call-method
52da95fa
MA
1071 :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
1072 "org.gnome.seahorse.Keys" "GetKeyField"
033b73e2
MA
1073 "openpgp:657984B8C7A966DD" "simple-name")
1074
1075 => (t ("Philip R. Zimmermann"))
1076
1077If the result of the METHOD call is just one value, the converted Lisp
1078object is returned instead of a list containing this single Lisp object.
1079
1080\(dbus-call-method
52da95fa
MA
1081 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
1082 "org.freedesktop.Hal.Device" "GetPropertyString"
033b73e2
MA
1083 "system.kernel.machine")
1084
1085 => "i686"
1086
edd9ab1e 1087usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TIMEOUT &rest ARGS) */)
c5101a77 1088 (size_t nargs, register Lisp_Object *args)
033b73e2 1089{
52da95fa 1090 Lisp_Object bus, service, path, interface, method;
033b73e2
MA
1091 Lisp_Object result;
1092 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
1093 DBusConnection *connection;
1094 DBusMessage *dmessage;
1095 DBusMessage *reply;
1096 DBusMessageIter iter;
1097 DBusError derror;
eb7c7bf5 1098 unsigned int dtype;
90b3fc84 1099 int timeout = -1;
c5101a77 1100 size_t i = 5;
87cf1a39 1101 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
1102
1103 /* Check parameters. */
1104 bus = args[0];
52da95fa
MA
1105 service = args[1];
1106 path = args[2];
1107 interface = args[3];
1108 method = args[4];
033b73e2 1109
033b73e2
MA
1110 CHECK_STRING (service);
1111 CHECK_STRING (path);
1112 CHECK_STRING (interface);
52da95fa
MA
1113 CHECK_STRING (method);
1114 GCPRO5 (bus, service, path, interface, method);
033b73e2
MA
1115
1116 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
1117 SDATA (service),
1118 SDATA (path),
52da95fa
MA
1119 SDATA (interface),
1120 SDATA (method));
033b73e2
MA
1121
1122 /* Open a connection to the bus. */
2536a4b7 1123 connection = xd_initialize (bus, TRUE);
033b73e2
MA
1124
1125 /* Create the message. */
59d6fe83
PE
1126 dmessage = dbus_message_new_method_call (SSDATA (service),
1127 SSDATA (path),
1128 SSDATA (interface),
1129 SSDATA (method));
90b3fc84 1130 UNGCPRO;
033b73e2 1131 if (dmessage == NULL)
1dae9197 1132 XD_SIGNAL1 (build_string ("Unable to create a new message"));
90b3fc84
MA
1133
1134 /* Check for timeout parameter. */
1135 if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
033b73e2 1136 {
90b3fc84 1137 CHECK_NATNUM (args[i+1]);
2d1fc3c7 1138 timeout = XFASTINT (args[i+1]);
90b3fc84 1139 i = i+2;
033b73e2
MA
1140 }
1141
54371585
MA
1142 /* Initialize parameter list of message. */
1143 dbus_message_iter_init_append (dmessage, &iter);
1144
033b73e2 1145 /* Append parameters to the message. */
90b3fc84 1146 for (; i < nargs; ++i)
033b73e2 1147 {
87cf1a39
MA
1148 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1149 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1150 {
1151 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1152 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
c5101a77 1153 XD_DEBUG_MESSAGE ("Parameter%lu %s %s", (unsigned long) (i-4),
8c7a4ac5
MA
1154 SDATA (format2 ("%s", args[i], Qnil)),
1155 SDATA (format2 ("%s", args[i+1], Qnil)));
1156 ++i;
1157 }
1158 else
1159 {
1160 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
c5101a77 1161 XD_DEBUG_MESSAGE ("Parameter%lu %s", (unsigned long) (i-4),
8c7a4ac5
MA
1162 SDATA (format2 ("%s", args[i], Qnil)));
1163 }
033b73e2 1164
abe136ee 1165 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39
MA
1166 indication that there is no parent type. */
1167 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1168
54371585 1169 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
1170 }
1171
1172 /* Send the message. */
1173 dbus_error_init (&derror);
1174 reply = dbus_connection_send_with_reply_and_block (connection,
1175 dmessage,
90b3fc84 1176 timeout,
033b73e2
MA
1177 &derror);
1178
1179 if (dbus_error_is_set (&derror))
1180 XD_ERROR (derror);
1181
1182 if (reply == NULL)
1dae9197 1183 XD_SIGNAL1 (build_string ("No reply"));
033b73e2
MA
1184
1185 XD_DEBUG_MESSAGE ("Message sent");
1186
1187 /* Collect the results. */
1188 result = Qnil;
1189 GCPRO1 (result);
1190
2c3a8b27 1191 if (dbus_message_iter_init (reply, &iter))
033b73e2 1192 {
2c3a8b27
MH
1193 /* Loop over the parameters of the D-Bus reply message. Construct a
1194 Lisp list, which is returned by `dbus-call-method'. */
8c7a4ac5
MA
1195 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1196 != DBUS_TYPE_INVALID)
2c3a8b27
MH
1197 {
1198 result = Fcons (xd_retrieve_arg (dtype, &iter), result);
1199 dbus_message_iter_next (&iter);
1200 }
033b73e2 1201 }
2c3a8b27 1202 else
033b73e2 1203 {
8c7a4ac5 1204 /* No arguments: just return nil. */
033b73e2
MA
1205 }
1206
1207 /* Cleanup. */
c1d5ce94 1208 dbus_error_free (&derror);
033b73e2
MA
1209 dbus_message_unref (dmessage);
1210 dbus_message_unref (reply);
1211
1212 /* Return the result. If there is only one single Lisp object,
1213 return it as-it-is, otherwise return the reversed list. */
2d1fc3c7 1214 if (XFASTINT (Flength (result)) == 1)
5125905e 1215 RETURN_UNGCPRO (CAR_SAFE (result));
033b73e2
MA
1216 else
1217 RETURN_UNGCPRO (Fnreverse (result));
1218}
1219
13ecc6dc
MA
1220DEFUN ("dbus-call-method-asynchronously", Fdbus_call_method_asynchronously,
1221 Sdbus_call_method_asynchronously, 6, MANY, 0,
1222 doc: /* Call METHOD on the D-Bus BUS asynchronously.
1223
0c372655
MA
1224BUS is either a Lisp symbol, `:system' or `:session', or a string
1225denoting the bus address.
13ecc6dc
MA
1226
1227SERVICE is the D-Bus service name to be used. PATH is the D-Bus
1228object path SERVICE is registered at. INTERFACE is an interface
1229offered by SERVICE. It must provide METHOD.
1230
1231HANDLER is a Lisp function, which is called when the corresponding
ca4f31ea
MA
1232return message has arrived. If HANDLER is nil, no return message will
1233be expected.
13ecc6dc
MA
1234
1235If the parameter `:timeout' is given, the following integer TIMEOUT
f04bb9b2 1236specifies the maximum number of milliseconds the method call must
1574224c 1237return. The default value is 25,000. If the method call doesn't
13ecc6dc
MA
1238return in time, a D-Bus error is raised.
1239
1240All other arguments ARGS are passed to METHOD as arguments. They are
1241converted into D-Bus types via the following rules:
1242
1243 t and nil => DBUS_TYPE_BOOLEAN
1244 number => DBUS_TYPE_UINT32
1245 integer => DBUS_TYPE_INT32
1246 float => DBUS_TYPE_DOUBLE
1247 string => DBUS_TYPE_STRING
1248 list => DBUS_TYPE_ARRAY
1249
1250All arguments can be preceded by a type symbol. For details about
1251type symbols, see Info node `(dbus)Type Conversion'.
1252
ca4f31ea 1253Unless HANDLER is nil, the function returns a key into the hash table
f04bb9b2
MA
1254`dbus-registered-objects-table'. The corresponding entry in the hash
1255table is removed, when the return message has been arrived, and
13ecc6dc
MA
1256HANDLER is called.
1257
1258Example:
1259
1260\(dbus-call-method-asynchronously
1261 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
1262 "org.freedesktop.Hal.Device" "GetPropertyString" 'message
1263 "system.kernel.machine")
1264
1265 => (:system 2)
1266
1267 -| i686
1268
edd9ab1e 1269usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLER &optional :timeout TIMEOUT &rest ARGS) */)
c5101a77 1270 (size_t nargs, register Lisp_Object *args)
13ecc6dc
MA
1271{
1272 Lisp_Object bus, service, path, interface, method, handler;
1273 Lisp_Object result;
1274 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
1275 DBusConnection *connection;
1276 DBusMessage *dmessage;
1277 DBusMessageIter iter;
1278 unsigned int dtype;
08686060 1279 dbus_uint32_t serial;
13ecc6dc 1280 int timeout = -1;
c5101a77 1281 size_t i = 6;
13ecc6dc
MA
1282 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1283
1284 /* Check parameters. */
1285 bus = args[0];
1286 service = args[1];
1287 path = args[2];
1288 interface = args[3];
1289 method = args[4];
1290 handler = args[5];
1291
13ecc6dc
MA
1292 CHECK_STRING (service);
1293 CHECK_STRING (path);
1294 CHECK_STRING (interface);
1295 CHECK_STRING (method);
ca4f31ea 1296 if (!NILP (handler) && !FUNCTIONP (handler))
b4289b64 1297 wrong_type_argument (Qinvalid_function, handler);
13ecc6dc
MA
1298 GCPRO6 (bus, service, path, interface, method, handler);
1299
1300 XD_DEBUG_MESSAGE ("%s %s %s %s",
1301 SDATA (service),
1302 SDATA (path),
1303 SDATA (interface),
1304 SDATA (method));
1305
1306 /* Open a connection to the bus. */
2536a4b7 1307 connection = xd_initialize (bus, TRUE);
13ecc6dc
MA
1308
1309 /* Create the message. */
59d6fe83
PE
1310 dmessage = dbus_message_new_method_call (SSDATA (service),
1311 SSDATA (path),
1312 SSDATA (interface),
1313 SSDATA (method));
13ecc6dc 1314 if (dmessage == NULL)
1dae9197 1315 XD_SIGNAL1 (build_string ("Unable to create a new message"));
13ecc6dc
MA
1316
1317 /* Check for timeout parameter. */
1318 if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
1319 {
1320 CHECK_NATNUM (args[i+1]);
2d1fc3c7 1321 timeout = XFASTINT (args[i+1]);
13ecc6dc
MA
1322 i = i+2;
1323 }
1324
1325 /* Initialize parameter list of message. */
1326 dbus_message_iter_init_append (dmessage, &iter);
1327
1328 /* Append parameters to the message. */
1329 for (; i < nargs; ++i)
1330 {
1331 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1332 if (XD_DBUS_TYPE_P (args[i]))
1333 {
1334 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1335 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
c5101a77 1336 XD_DEBUG_MESSAGE ("Parameter%lu %s %s", (unsigned long) (i-4),
13ecc6dc
MA
1337 SDATA (format2 ("%s", args[i], Qnil)),
1338 SDATA (format2 ("%s", args[i+1], Qnil)));
1339 ++i;
1340 }
1341 else
1342 {
1343 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
c5101a77 1344 XD_DEBUG_MESSAGE ("Parameter%lu %s", (unsigned long) (i - 4),
13ecc6dc
MA
1345 SDATA (format2 ("%s", args[i], Qnil)));
1346 }
1347
1348 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1349 indication that there is no parent type. */
1350 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1351
1352 xd_append_arg (dtype, args[i], &iter);
1353 }
1354
ca4f31ea
MA
1355 if (!NILP (handler))
1356 {
1357 /* Send the message. The message is just added to the outgoing
1358 message queue. */
1359 if (!dbus_connection_send_with_reply (connection, dmessage,
1360 NULL, timeout))
1361 XD_SIGNAL1 (build_string ("Cannot send message"));
13ecc6dc 1362
f04bb9b2 1363 /* The result is the key in Vdbus_registered_objects_table. */
08686060
PE
1364 serial = dbus_message_get_serial (dmessage);
1365 result = list2 (bus, make_fixnum_or_float (serial));
13ecc6dc 1366
ca4f31ea 1367 /* Create a hash table entry. */
f04bb9b2 1368 Fputhash (result, handler, Vdbus_registered_objects_table);
ca4f31ea
MA
1369 }
1370 else
1371 {
1372 /* Send the message. The message is just added to the outgoing
1373 message queue. */
1374 if (!dbus_connection_send (connection, dmessage, NULL))
1375 XD_SIGNAL1 (build_string ("Cannot send message"));
13ecc6dc 1376
ca4f31ea
MA
1377 result = Qnil;
1378 }
1379
ca4f31ea 1380 XD_DEBUG_MESSAGE ("Message sent");
13ecc6dc
MA
1381
1382 /* Cleanup. */
1383 dbus_message_unref (dmessage);
1384
1385 /* Return the result. */
1386 RETURN_UNGCPRO (result);
1387}
1388
8c7a4ac5
MA
1389DEFUN ("dbus-method-return-internal", Fdbus_method_return_internal,
1390 Sdbus_method_return_internal,
abe136ee 1391 3, MANY, 0,
8c7a4ac5 1392 doc: /* Return for message SERIAL on the D-Bus BUS.
abe136ee
MA
1393This is an internal function, it shall not be used outside dbus.el.
1394
8c7a4ac5 1395usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
c5101a77 1396 (size_t nargs, register Lisp_Object *args)
abe136ee 1397{
08686060
PE
1398 Lisp_Object bus, service;
1399 struct gcpro gcpro1, gcpro2;
abe136ee
MA
1400 DBusConnection *connection;
1401 DBusMessage *dmessage;
1402 DBusMessageIter iter;
08686060
PE
1403 dbus_uint32_t serial;
1404 unsigned int ui_serial, dtype;
c5101a77 1405 size_t i;
abe136ee
MA
1406 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1407
1408 /* Check parameters. */
1409 bus = args[0];
abe136ee
MA
1410 service = args[2];
1411
08686060 1412 CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
abe136ee 1413 CHECK_STRING (service);
08686060 1414 GCPRO2 (bus, service);
abe136ee 1415
08686060
PE
1416 ui_serial = serial;
1417 XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
abe136ee
MA
1418
1419 /* Open a connection to the bus. */
2536a4b7 1420 connection = xd_initialize (bus, TRUE);
abe136ee
MA
1421
1422 /* Create the message. */
1423 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1424 if ((dmessage == NULL)
08686060 1425 || (!dbus_message_set_reply_serial (dmessage, serial))
59d6fe83 1426 || (!dbus_message_set_destination (dmessage, SSDATA (service))))
abe136ee
MA
1427 {
1428 UNGCPRO;
1dae9197 1429 XD_SIGNAL1 (build_string ("Unable to create a return message"));
abe136ee
MA
1430 }
1431
1432 UNGCPRO;
1433
1434 /* Initialize parameter list of message. */
1435 dbus_message_iter_init_append (dmessage, &iter);
1436
1437 /* Append parameters to the message. */
1438 for (i = 3; i < nargs; ++i)
1439 {
abe136ee
MA
1440 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1441 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1442 {
1443 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1444 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
c5101a77 1445 XD_DEBUG_MESSAGE ("Parameter%lu %s %s", (unsigned long) (i-2),
8c7a4ac5
MA
1446 SDATA (format2 ("%s", args[i], Qnil)),
1447 SDATA (format2 ("%s", args[i+1], Qnil)));
1448 ++i;
1449 }
1450 else
1451 {
1452 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
c5101a77 1453 XD_DEBUG_MESSAGE ("Parameter%lu %s", (unsigned long) (i-2),
8c7a4ac5
MA
1454 SDATA (format2 ("%s", args[i], Qnil)));
1455 }
abe136ee
MA
1456
1457 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1458 indication that there is no parent type. */
1459 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1460
1461 xd_append_arg (dtype, args[i], &iter);
1462 }
1463
1464 /* Send the message. The message is just added to the outgoing
1465 message queue. */
1466 if (!dbus_connection_send (connection, dmessage, NULL))
1dae9197 1467 XD_SIGNAL1 (build_string ("Cannot send message"));
abe136ee 1468
abe136ee
MA
1469 XD_DEBUG_MESSAGE ("Message sent");
1470
1471 /* Cleanup. */
1472 dbus_message_unref (dmessage);
1473
1474 /* Return. */
1475 return Qt;
1476}
1477
13ecc6dc
MA
1478DEFUN ("dbus-method-error-internal", Fdbus_method_error_internal,
1479 Sdbus_method_error_internal,
1480 3, MANY, 0,
1481 doc: /* Return error message for message SERIAL on the D-Bus BUS.
1482This is an internal function, it shall not be used outside dbus.el.
1483
1484usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */)
c5101a77 1485 (size_t nargs, register Lisp_Object *args)
13ecc6dc 1486{
08686060
PE
1487 Lisp_Object bus, service;
1488 struct gcpro gcpro1, gcpro2;
13ecc6dc
MA
1489 DBusConnection *connection;
1490 DBusMessage *dmessage;
1491 DBusMessageIter iter;
08686060
PE
1492 dbus_uint32_t serial;
1493 unsigned int ui_serial, dtype;
c5101a77 1494 size_t i;
13ecc6dc
MA
1495 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1496
1497 /* Check parameters. */
1498 bus = args[0];
13ecc6dc
MA
1499 service = args[2];
1500
08686060 1501 CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
13ecc6dc 1502 CHECK_STRING (service);
08686060 1503 GCPRO2 (bus, service);
13ecc6dc 1504
08686060
PE
1505 ui_serial = serial;
1506 XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
13ecc6dc
MA
1507
1508 /* Open a connection to the bus. */
2536a4b7 1509 connection = xd_initialize (bus, TRUE);
13ecc6dc
MA
1510
1511 /* Create the message. */
1512 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1513 if ((dmessage == NULL)
1514 || (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED))
08686060 1515 || (!dbus_message_set_reply_serial (dmessage, serial))
59d6fe83 1516 || (!dbus_message_set_destination (dmessage, SSDATA (service))))
13ecc6dc
MA
1517 {
1518 UNGCPRO;
1dae9197 1519 XD_SIGNAL1 (build_string ("Unable to create a error message"));
13ecc6dc
MA
1520 }
1521
1522 UNGCPRO;
1523
1524 /* Initialize parameter list of message. */
1525 dbus_message_iter_init_append (dmessage, &iter);
1526
1527 /* Append parameters to the message. */
1528 for (i = 3; i < nargs; ++i)
1529 {
1530 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1531 if (XD_DBUS_TYPE_P (args[i]))
1532 {
1533 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1534 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
c5101a77 1535 XD_DEBUG_MESSAGE ("Parameter%lu %s %s", (unsigned long) (i-2),
13ecc6dc
MA
1536 SDATA (format2 ("%s", args[i], Qnil)),
1537 SDATA (format2 ("%s", args[i+1], Qnil)));
1538 ++i;
1539 }
1540 else
1541 {
1542 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
c5101a77 1543 XD_DEBUG_MESSAGE ("Parameter%lu %s", (unsigned long) (i-2),
13ecc6dc
MA
1544 SDATA (format2 ("%s", args[i], Qnil)));
1545 }
1546
1547 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1548 indication that there is no parent type. */
1549 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1550
1551 xd_append_arg (dtype, args[i], &iter);
1552 }
1553
1554 /* Send the message. The message is just added to the outgoing
1555 message queue. */
1556 if (!dbus_connection_send (connection, dmessage, NULL))
1dae9197 1557 XD_SIGNAL1 (build_string ("Cannot send message"));
13ecc6dc 1558
13ecc6dc
MA
1559 XD_DEBUG_MESSAGE ("Message sent");
1560
1561 /* Cleanup. */
1562 dbus_message_unref (dmessage);
1563
1564 /* Return. */
1565 return Qt;
1566}
1567
033b73e2
MA
1568DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
1569 doc: /* Send signal SIGNAL on the D-Bus BUS.
1570
0c372655
MA
1571BUS is either a Lisp symbol, `:system' or `:session', or a string
1572denoting the bus address.
033b73e2
MA
1573
1574SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
1575D-Bus object path SERVICE is registered at. INTERFACE is an interface
1576offered by SERVICE. It must provide signal SIGNAL.
1577
1578All other arguments ARGS are passed to SIGNAL as arguments. They are
1579converted into D-Bus types via the following rules:
1580
1581 t and nil => DBUS_TYPE_BOOLEAN
1582 number => DBUS_TYPE_UINT32
1583 integer => DBUS_TYPE_INT32
1584 float => DBUS_TYPE_DOUBLE
1585 string => DBUS_TYPE_STRING
87cf1a39 1586 list => DBUS_TYPE_ARRAY
033b73e2 1587
87cf1a39
MA
1588All arguments can be preceded by a type symbol. For details about
1589type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
1590
1591Example:
1592
1593\(dbus-send-signal
52da95fa
MA
1594 :session "org.gnu.Emacs" "/org/gnu/Emacs"
1595 "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
033b73e2 1596
52da95fa 1597usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
c5101a77 1598 (size_t nargs, register Lisp_Object *args)
033b73e2 1599{
52da95fa 1600 Lisp_Object bus, service, path, interface, signal;
033b73e2
MA
1601 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
1602 DBusConnection *connection;
1603 DBusMessage *dmessage;
54371585 1604 DBusMessageIter iter;
eb7c7bf5 1605 unsigned int dtype;
c5101a77 1606 size_t i;
87cf1a39 1607 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
1608
1609 /* Check parameters. */
1610 bus = args[0];
52da95fa
MA
1611 service = args[1];
1612 path = args[2];
1613 interface = args[3];
1614 signal = args[4];
033b73e2 1615
033b73e2
MA
1616 CHECK_STRING (service);
1617 CHECK_STRING (path);
1618 CHECK_STRING (interface);
52da95fa
MA
1619 CHECK_STRING (signal);
1620 GCPRO5 (bus, service, path, interface, signal);
033b73e2
MA
1621
1622 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
1623 SDATA (service),
1624 SDATA (path),
52da95fa
MA
1625 SDATA (interface),
1626 SDATA (signal));
033b73e2
MA
1627
1628 /* Open a connection to the bus. */
2536a4b7 1629 connection = xd_initialize (bus, TRUE);
033b73e2
MA
1630
1631 /* Create the message. */
59d6fe83
PE
1632 dmessage = dbus_message_new_signal (SSDATA (path),
1633 SSDATA (interface),
1634 SSDATA (signal));
033b73e2 1635 UNGCPRO;
90b3fc84 1636 if (dmessage == NULL)
1dae9197 1637 XD_SIGNAL1 (build_string ("Unable to create a new message"));
033b73e2 1638
54371585
MA
1639 /* Initialize parameter list of message. */
1640 dbus_message_iter_init_append (dmessage, &iter);
1641
033b73e2
MA
1642 /* Append parameters to the message. */
1643 for (i = 5; i < nargs; ++i)
1644 {
87cf1a39
MA
1645 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1646 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1647 {
1648 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1649 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
c5101a77 1650 XD_DEBUG_MESSAGE ("Parameter%lu %s %s", (unsigned long) (i-4),
8c7a4ac5
MA
1651 SDATA (format2 ("%s", args[i], Qnil)),
1652 SDATA (format2 ("%s", args[i+1], Qnil)));
1653 ++i;
1654 }
1655 else
1656 {
1657 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
c5101a77 1658 XD_DEBUG_MESSAGE ("Parameter%lu %s", (unsigned long) (i-4),
8c7a4ac5
MA
1659 SDATA (format2 ("%s", args[i], Qnil)));
1660 }
033b73e2 1661
abe136ee 1662 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39
MA
1663 indication that there is no parent type. */
1664 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1665
54371585 1666 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
1667 }
1668
1669 /* Send the message. The message is just added to the outgoing
1670 message queue. */
1671 if (!dbus_connection_send (connection, dmessage, NULL))
1dae9197 1672 XD_SIGNAL1 (build_string ("Cannot send message"));
033b73e2 1673
033b73e2
MA
1674 XD_DEBUG_MESSAGE ("Signal sent");
1675
1676 /* Cleanup. */
1677 dbus_message_unref (dmessage);
1678
1679 /* Return. */
1680 return Qt;
1681}
1682
3fad2ad2
J
1683/* Read one queued incoming message of the D-Bus BUS.
1684 BUS is either a Lisp symbol, :system or :session, or a string denoting
1685 the bus address. */
3fad2ad2
J
1686static void
1687xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
033b73e2 1688{
a31d47c7 1689 Lisp_Object args, key, value;
033b73e2 1690 struct gcpro gcpro1;
15f16c1b 1691 struct input_event event;
033b73e2
MA
1692 DBusMessage *dmessage;
1693 DBusMessageIter iter;
eb7c7bf5 1694 unsigned int dtype;
30217ff0
PE
1695 int mtype;
1696 dbus_uint32_t serial;
08686060 1697 unsigned int ui_serial;
a8e72f4f 1698 const char *uname, *path, *interface, *member;
39abdd4a 1699
033b73e2
MA
1700 dmessage = dbus_connection_pop_message (connection);
1701
1702 /* Return if there is no queued message. */
1703 if (dmessage == NULL)
3fad2ad2 1704 return;
033b73e2
MA
1705
1706 /* Collect the parameters. */
a31d47c7
MA
1707 args = Qnil;
1708 GCPRO1 (args);
033b73e2 1709
033b73e2 1710 /* Loop over the resulting parameters. Construct a list. */
17bc8f94 1711 if (dbus_message_iter_init (dmessage, &iter))
033b73e2 1712 {
17bc8f94
MA
1713 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1714 != DBUS_TYPE_INVALID)
1715 {
1716 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
1717 dbus_message_iter_next (&iter);
1718 }
1719 /* The arguments are stored in reverse order. Reorder them. */
1720 args = Fnreverse (args);
033b73e2
MA
1721 }
1722
13ecc6dc
MA
1723 /* Read message type, message serial, unique name, object path,
1724 interface and member from the message. */
367ea173 1725 mtype = dbus_message_get_type (dmessage);
08686060 1726 ui_serial = serial =
367ea173
MA
1727 ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1728 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1729 ? dbus_message_get_reply_serial (dmessage)
1730 : dbus_message_get_serial (dmessage);
1731 uname = dbus_message_get_sender (dmessage);
1732 path = dbus_message_get_path (dmessage);
a8e72f4f 1733 interface = dbus_message_get_interface (dmessage);
367ea173 1734 member = dbus_message_get_member (dmessage);
a8e72f4f 1735
30217ff0 1736 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
367ea173
MA
1737 (mtype == DBUS_MESSAGE_TYPE_INVALID)
1738 ? "DBUS_MESSAGE_TYPE_INVALID"
1739 : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1740 ? "DBUS_MESSAGE_TYPE_METHOD_CALL"
1741 : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1742 ? "DBUS_MESSAGE_TYPE_METHOD_RETURN"
1743 : (mtype == DBUS_MESSAGE_TYPE_ERROR)
1744 ? "DBUS_MESSAGE_TYPE_ERROR"
1745 : "DBUS_MESSAGE_TYPE_SIGNAL",
08686060 1746 ui_serial, uname, path, interface, member,
17bc8f94
MA
1747 SDATA (format2 ("%s", args, Qnil)));
1748
367ea173
MA
1749 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1750 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
13ecc6dc
MA
1751 {
1752 /* Search for a registered function of the message. */
08686060 1753 key = list2 (bus, make_fixnum_or_float (serial));
f04bb9b2 1754 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1755
1756 /* There shall be exactly one entry. Construct an event. */
1757 if (NILP (value))
1758 goto cleanup;
1759
1760 /* Remove the entry. */
f04bb9b2 1761 Fremhash (key, Vdbus_registered_objects_table);
13ecc6dc
MA
1762
1763 /* Construct an event. */
1764 EVENT_INIT (event);
1765 event.kind = DBUS_EVENT;
1766 event.frame_or_window = Qnil;
1767 event.arg = Fcons (value, args);
1768 }
a31d47c7 1769
13ecc6dc 1770 else /* (mtype != DBUS_MESSAGE_TYPE_METHOD_RETURN) */
a31d47c7 1771 {
f04bb9b2
MA
1772 /* Vdbus_registered_objects_table requires non-nil interface and
1773 member. */
13ecc6dc
MA
1774 if ((interface == NULL) || (member == NULL))
1775 goto cleanup;
1776
1777 /* Search for a registered function of the message. */
1778 key = list3 (bus, build_string (interface), build_string (member));
f04bb9b2 1779 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1780
1781 /* Loop over the registered functions. Construct an event. */
1782 while (!NILP (value))
a31d47c7 1783 {
13ecc6dc
MA
1784 key = CAR_SAFE (value);
1785 /* key has the structure (UNAME SERVICE PATH HANDLER). */
1786 if (((uname == NULL)
1787 || (NILP (CAR_SAFE (key)))
59d6fe83 1788 || (strcmp (uname, SSDATA (CAR_SAFE (key))) == 0))
13ecc6dc
MA
1789 && ((path == NULL)
1790 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1791 || (strcmp (path,
59d6fe83 1792 SSDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
13ecc6dc
MA
1793 == 0))
1794 && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
1795 {
1796 EVENT_INIT (event);
1797 event.kind = DBUS_EVENT;
1798 event.frame_or_window = Qnil;
b4289b64
MA
1799 event.arg
1800 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args);
13ecc6dc
MA
1801 break;
1802 }
1803 value = CDR_SAFE (value);
a31d47c7 1804 }
13ecc6dc
MA
1805
1806 if (NILP (value))
1807 goto cleanup;
a31d47c7 1808 }
033b73e2 1809
13ecc6dc
MA
1810 /* Add type, serial, uname, path, interface and member to the event. */
1811 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1812 event.arg);
1813 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1814 event.arg);
1815 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1816 event.arg);
1817 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1818 event.arg);
08686060 1819 event.arg = Fcons (make_fixnum_or_float (serial), event.arg);
13ecc6dc
MA
1820 event.arg = Fcons (make_number (mtype), event.arg);
1821
1822 /* Add the bus symbol to the event. */
1823 event.arg = Fcons (bus, event.arg);
1824
1825 /* Store it into the input event queue. */
1826 kbd_buffer_store_event (&event);
1827
1828 XD_DEBUG_MESSAGE ("Event stored: %s",
1829 SDATA (format2 ("%s", event.arg, Qnil)));
1830
c1d5ce94 1831 /* Cleanup. */
a8e72f4f 1832 cleanup:
033b73e2 1833 dbus_message_unref (dmessage);
c1d5ce94 1834
3fad2ad2
J
1835 UNGCPRO;
1836}
1837
1838/* Read queued incoming messages of the D-Bus BUS.
1839 BUS is either a Lisp symbol, :system or :session, or a string denoting
1840 the bus address. */
3fad2ad2
J
1841static Lisp_Object
1842xd_read_message (Lisp_Object bus)
1843{
1844 /* Open a connection to the bus. */
1845 DBusConnection *connection = xd_initialize (bus, TRUE);
1846
1847 /* Non blocking read of the next available message. */
1848 dbus_connection_read_write (connection, 0);
1849
1850 while (dbus_connection_get_dispatch_status (connection)
1851 != DBUS_DISPATCH_COMPLETE)
1852 xd_read_message_1 (connection, bus);
1853 return Qnil;
033b73e2
MA
1854}
1855
08609ffd
MA
1856/* Callback called when something is ready to read or write. */
1857static void
1858xd_read_queued_messages (int fd, void *data, int for_read)
033b73e2 1859{
0c372655 1860 Lisp_Object busp = Vdbus_registered_buses;
08609ffd 1861 Lisp_Object bus = Qnil;
96faeb40 1862
08609ffd
MA
1863 /* Find bus related to fd. */
1864 if (data != NULL)
1865 while (!NILP (busp))
1866 {
b4289b64
MA
1867 if ((SYMBOLP (CAR_SAFE (busp)) && XSYMBOL (CAR_SAFE (busp)) == data)
1868 || (STRINGP (CAR_SAFE (busp)) && XSTRING (CAR_SAFE (busp)) == data))
08609ffd
MA
1869 bus = CAR_SAFE (busp);
1870 busp = CDR_SAFE (busp);
1871 }
1872
1873 if (NILP(bus))
1874 return;
1875
1876 /* We ignore all Lisp errors during the call. */
0c372655 1877 xd_in_read_queued_messages = 1;
08609ffd 1878 internal_catch (Qdbus_error, xd_read_message, bus);
0c372655 1879 xd_in_read_queued_messages = 0;
033b73e2
MA
1880}
1881
5b83ba18
MA
1882DEFUN ("dbus-register-service", Fdbus_register_service, Sdbus_register_service,
1883 2, MANY, 0,
1884 doc: /* Register known name SERVICE on the D-Bus BUS.
1885
1886BUS is either a Lisp symbol, `:system' or `:session', or a string
1887denoting the bus address.
1888
1889SERVICE is the D-Bus service name that should be registered. It must
1890be a known name.
1891
1892FLAGS are keywords, which control how the service name is registered.
1893The following keywords are recognized:
1894
1895`:allow-replacement': Allow another service to become the primary
1896owner if requested.
1897
1898`:replace-existing': Request to replace the current primary owner.
1899
1900`:do-not-queue': If we can not become the primary owner do not place
1901us in the queue.
1902
1903The function returns a keyword, indicating the result of the
1904operation. One of the following keywords is returned:
1905
1906`:primary-owner': Service has become the primary owner of the
1907requested name.
1908
1909`:in-queue': Service could not become the primary owner and has been
1910placed in the queue.
1911
1912`:exists': Service is already in the queue.
1913
1914`:already-owner': Service is already the primary owner.
1915
1916Example:
1917
1918\(dbus-register-service :session dbus-service-emacs)
1919
1920 => :primary-owner.
1921
1922\(dbus-register-service
2bc92a93
MA
1923 :session "org.freedesktop.TextEditor"
1924 dbus-service-allow-replacement dbus-service-replace-existing)
5b83ba18
MA
1925
1926 => :already-owner.
1927
1928usage: (dbus-register-service BUS SERVICE &rest FLAGS) */)
c5101a77 1929 (size_t nargs, register Lisp_Object *args)
5b83ba18
MA
1930{
1931 Lisp_Object bus, service;
5b83ba18 1932 DBusConnection *connection;
c5101a77 1933 size_t i;
5b83ba18
MA
1934 unsigned int value;
1935 unsigned int flags = 0;
1936 int result;
1937 DBusError derror;
1938
1939 bus = args[0];
1940 service = args[1];
1941
1942 /* Check parameters. */
1943 CHECK_STRING (service);
1944
1945 /* Process flags. */
1946 for (i = 2; i < nargs; ++i) {
1947 value = ((EQ (args[i], QCdbus_request_name_replace_existing))
1948 ? DBUS_NAME_FLAG_REPLACE_EXISTING
1949 : (EQ (args[i], QCdbus_request_name_allow_replacement))
1950 ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT
1951 : (EQ (args[i], QCdbus_request_name_do_not_queue))
1952 ? DBUS_NAME_FLAG_DO_NOT_QUEUE
1953 : -1);
1954 if (value == -1)
1955 XD_SIGNAL2 (build_string ("Unrecognized name request flag"), args[i]);
1956 flags |= value;
1957 }
1958
1959 /* Open a connection to the bus. */
1960 connection = xd_initialize (bus, TRUE);
1961
1962 /* Request the known name from the bus. */
1963 dbus_error_init (&derror);
59d6fe83 1964 result = dbus_bus_request_name (connection, SSDATA (service), flags,
5b83ba18
MA
1965 &derror);
1966 if (dbus_error_is_set (&derror))
1967 XD_ERROR (derror);
1968
1969 /* Cleanup. */
1970 dbus_error_free (&derror);
1971
1972 /* Return object. */
2bc92a93
MA
1973 switch (result)
1974 {
1975 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
1976 return QCdbus_request_name_reply_primary_owner;
1977 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
1978 return QCdbus_request_name_reply_in_queue;
1979 case DBUS_REQUEST_NAME_REPLY_EXISTS:
1980 return QCdbus_request_name_reply_exists;
1981 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
1982 return QCdbus_request_name_reply_already_owner;
1983 default:
1984 /* This should not happen. */
1985 XD_SIGNAL2 (build_string ("Could not register service"), service);
1986 }
5b83ba18
MA
1987}
1988
033b73e2 1989DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
944cc4a8 1990 6, MANY, 0,
033b73e2
MA
1991 doc: /* Register for signal SIGNAL on the D-Bus BUS.
1992
0c372655
MA
1993BUS is either a Lisp symbol, `:system' or `:session', or a string
1994denoting the bus address.
033b73e2 1995
39abdd4a
MA
1996SERVICE is the D-Bus service name used by the sending D-Bus object.
1997It can be either a known name or the unique name of the D-Bus object
1998sending the signal. When SERVICE is nil, related signals from all
1999D-Bus objects shall be accepted.
033b73e2 2000
39abdd4a
MA
2001PATH is the D-Bus object path SERVICE is registered. It can also be
2002nil if the path name of incoming signals shall not be checked.
033b73e2 2003
39abdd4a
MA
2004INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
2005HANDLER is a Lisp function to be called when the signal is received.
944cc4a8
MA
2006It must accept as arguments the values SIGNAL is sending.
2007
2008All other arguments ARGS, if specified, must be strings. They stand
2009for the respective arguments of the signal in their order, and are
2010used for filtering as well. A nil argument might be used to preserve
2011the order.
2012
2013INTERFACE, SIGNAL and HANDLER must not be nil. Example:
033b73e2
MA
2014
2015\(defun my-signal-handler (device)
2016 (message "Device %s added" device))
2017
2018\(dbus-register-signal
52da95fa
MA
2019 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
2020 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
033b73e2 2021
f5306ca3
MA
2022 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
2023 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
033b73e2
MA
2024
2025`dbus-register-signal' returns an object, which can be used in
944cc4a8
MA
2026`dbus-unregister-object' for removing the registration.
2027
2028usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARGS) */)
c5101a77 2029 (size_t nargs, register Lisp_Object *args)
033b73e2 2030{
944cc4a8
MA
2031 Lisp_Object bus, service, path, interface, signal, handler;
2032 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
17bc8f94 2033 Lisp_Object uname, key, key1, value;
033b73e2 2034 DBusConnection *connection;
c5101a77 2035 size_t i;
52da95fa 2036 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
c0894fb9 2037 char x[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
39abdd4a 2038 DBusError derror;
033b73e2
MA
2039
2040 /* Check parameters. */
944cc4a8
MA
2041 bus = args[0];
2042 service = args[1];
2043 path = args[2];
2044 interface = args[3];
2045 signal = args[4];
2046 handler = args[5];
2047
39abdd4a
MA
2048 if (!NILP (service)) CHECK_STRING (service);
2049 if (!NILP (path)) CHECK_STRING (path);
033b73e2 2050 CHECK_STRING (interface);
52da95fa 2051 CHECK_STRING (signal);
17bc8f94 2052 if (!FUNCTIONP (handler))
b4289b64 2053 wrong_type_argument (Qinvalid_function, handler);
944cc4a8 2054 GCPRO6 (bus, service, path, interface, signal, handler);
033b73e2 2055
52da95fa
MA
2056 /* Retrieve unique name of service. If service is a known name, we
2057 will register for the corresponding unique name, if any. Signals
2058 are sent always with the unique name as sender. Note: the unique
2059 name of "org.freedesktop.DBus" is that string itself. */
5125905e
MA
2060 if ((STRINGP (service))
2061 && (SBYTES (service) > 0)
59d6fe83
PE
2062 && (strcmp (SSDATA (service), DBUS_SERVICE_DBUS) != 0)
2063 && (strncmp (SSDATA (service), ":", 1) != 0))
f5306ca3
MA
2064 {
2065 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
2066 /* When there is no unique name, we mark it with an empty
2067 string. */
2068 if (NILP (uname))
fff4e459 2069 uname = empty_unibyte_string;
f5306ca3 2070 }
52da95fa 2071 else
f5306ca3 2072 uname = service;
52da95fa 2073
f5306ca3
MA
2074 /* Create a matching rule if the unique name exists (when no
2075 wildcard). */
5125905e 2076 if (NILP (uname) || (SBYTES (uname) > 0))
f5306ca3
MA
2077 {
2078 /* Open a connection to the bus. */
2536a4b7 2079 connection = xd_initialize (bus, TRUE);
033b73e2 2080
f5306ca3
MA
2081 /* Create a rule to receive related signals. */
2082 sprintf (rule,
2083 "type='signal',interface='%s',member='%s'",
2084 SDATA (interface),
2085 SDATA (signal));
033b73e2 2086
f5306ca3
MA
2087 /* Add unique name and path to the rule if they are non-nil. */
2088 if (!NILP (uname))
c0894fb9
MA
2089 {
2090 sprintf (x, ",sender='%s'", SDATA (uname));
2091 strcat (rule, x);
2092 }
39abdd4a 2093
f5306ca3 2094 if (!NILP (path))
c0894fb9
MA
2095 {
2096 sprintf (x, ",path='%s'", SDATA (path));
2097 strcat (rule, x);
2098 }
39abdd4a 2099
944cc4a8
MA
2100 /* Add arguments to the rule if they are non-nil. */
2101 for (i = 6; i < nargs; ++i)
2102 if (!NILP (args[i]))
2103 {
2104 CHECK_STRING (args[i]);
c5101a77
PE
2105 sprintf (x, ",arg%lu='%s'", (unsigned long) (i-6),
2106 SDATA (args[i]));
c0894fb9 2107 strcat (rule, x);
944cc4a8
MA
2108 }
2109
f5306ca3
MA
2110 /* Add the rule to the bus. */
2111 dbus_error_init (&derror);
2112 dbus_bus_add_match (connection, rule, &derror);
2113 if (dbus_error_is_set (&derror))
944cc4a8
MA
2114 {
2115 UNGCPRO;
2116 XD_ERROR (derror);
2117 }
033b73e2 2118
c1d5ce94
MA
2119 /* Cleanup. */
2120 dbus_error_free (&derror);
2121
f5306ca3
MA
2122 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
2123 }
033b73e2 2124
39abdd4a 2125 /* Create a hash table entry. */
a31d47c7 2126 key = list3 (bus, interface, signal);
17bc8f94 2127 key1 = list4 (uname, service, path, handler);
f04bb9b2 2128 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
17bc8f94
MA
2129
2130 if (NILP (Fmember (key1, value)))
f04bb9b2 2131 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
17bc8f94
MA
2132
2133 /* Return object. */
944cc4a8 2134 RETURN_UNGCPRO (list2 (key, list3 (service, path, handler)));
17bc8f94
MA
2135}
2136
2137DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
6ed843e5 2138 6, 7, 0,
17bc8f94
MA
2139 doc: /* Register for method METHOD on the D-Bus BUS.
2140
0c372655
MA
2141BUS is either a Lisp symbol, `:system' or `:session', or a string
2142denoting the bus address.
17bc8f94
MA
2143
2144SERVICE is the D-Bus service name of the D-Bus object METHOD is
6ed843e5
MA
2145registered for. It must be a known name (See discussion of
2146DONT-REGISTER-SERVICE below).
2147
2148PATH is the D-Bus object path SERVICE is registered (See discussion of
2149DONT-REGISTER-SERVICE below). INTERFACE is the interface offered by
2150SERVICE. It must provide METHOD. HANDLER is a Lisp function to be
2151called when a method call is received. It must accept the input
2152arguments of METHOD. The return value of HANDLER is used for
2153composing the returning D-Bus message.
2154
2155When DONT-REGISTER-SERVICE is non-nil, the known name SERVICE is not
2156registered. This means that other D-Bus clients have no way of
2157noticing the newly registered method. When interfaces are constructed
2158incrementally by adding single methods or properties at a time,
2159DONT-REGISTER-SERVICE can be use to prevent other clients from
2160discovering the still incomplete interface.*/)
2161 (Lisp_Object bus, Lisp_Object service, Lisp_Object path,
2162 Lisp_Object interface, Lisp_Object method, Lisp_Object handler,
2163 Lisp_Object dont_register_service)
17bc8f94
MA
2164{
2165 Lisp_Object key, key1, value;
5b83ba18 2166 Lisp_Object args[2] = { bus, service };
17bc8f94 2167
17bc8f94 2168 /* Check parameters. */
17bc8f94
MA
2169 CHECK_STRING (service);
2170 CHECK_STRING (path);
2171 CHECK_STRING (interface);
2172 CHECK_STRING (method);
2173 if (!FUNCTIONP (handler))
b4289b64 2174 wrong_type_argument (Qinvalid_function, handler);
17bc8f94
MA
2175 /* TODO: We must check for a valid service name, otherwise there is
2176 a segmentation fault. */
2177
5b83ba18 2178 /* Request the name. */
2bc92a93 2179 if (NILP (dont_register_service))
5b83ba18 2180 Fdbus_register_service (2, args);
17bc8f94 2181
f04bb9b2
MA
2182 /* Create a hash table entry. We use nil for the unique name,
2183 because the method might be called from anybody. */
17bc8f94
MA
2184 key = list3 (bus, interface, method);
2185 key1 = list4 (Qnil, service, path, handler);
f04bb9b2 2186 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
a31d47c7 2187
17bc8f94 2188 if (NILP (Fmember (key1, value)))
f04bb9b2 2189 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
033b73e2 2190
f5306ca3
MA
2191 /* Return object. */
2192 return list2 (key, list3 (service, path, handler));
033b73e2
MA
2193}
2194
033b73e2
MA
2195\f
2196void
971de7fb 2197syms_of_dbusbind (void)
033b73e2
MA
2198{
2199
d67b4f80 2200 Qdbus_init_bus = intern_c_string ("dbus-init-bus");
058ed861
MA
2201 staticpro (&Qdbus_init_bus);
2202 defsubr (&Sdbus_init_bus);
2203
0c372655
MA
2204 Qdbus_close_bus = intern_c_string ("dbus-close-bus");
2205 staticpro (&Qdbus_close_bus);
2206 defsubr (&Sdbus_close_bus);
2207
d67b4f80 2208 Qdbus_get_unique_name = intern_c_string ("dbus-get-unique-name");
033b73e2
MA
2209 staticpro (&Qdbus_get_unique_name);
2210 defsubr (&Sdbus_get_unique_name);
2211
d67b4f80 2212 Qdbus_call_method = intern_c_string ("dbus-call-method");
033b73e2
MA
2213 staticpro (&Qdbus_call_method);
2214 defsubr (&Sdbus_call_method);
2215
b4289b64
MA
2216 Qdbus_call_method_asynchronously
2217 = intern_c_string ("dbus-call-method-asynchronously");
13ecc6dc
MA
2218 staticpro (&Qdbus_call_method_asynchronously);
2219 defsubr (&Sdbus_call_method_asynchronously);
2220
b4289b64
MA
2221 Qdbus_method_return_internal
2222 = intern_c_string ("dbus-method-return-internal");
8c7a4ac5
MA
2223 staticpro (&Qdbus_method_return_internal);
2224 defsubr (&Sdbus_method_return_internal);
abe136ee 2225
d67b4f80 2226 Qdbus_method_error_internal = intern_c_string ("dbus-method-error-internal");
13ecc6dc
MA
2227 staticpro (&Qdbus_method_error_internal);
2228 defsubr (&Sdbus_method_error_internal);
2229
d67b4f80 2230 Qdbus_send_signal = intern_c_string ("dbus-send-signal");
033b73e2
MA
2231 staticpro (&Qdbus_send_signal);
2232 defsubr (&Sdbus_send_signal);
2233
5b83ba18
MA
2234 Qdbus_register_service = intern_c_string ("dbus-register-service");
2235 staticpro (&Qdbus_register_service);
2236 defsubr (&Sdbus_register_service);
2237
d67b4f80 2238 Qdbus_register_signal = intern_c_string ("dbus-register-signal");
033b73e2
MA
2239 staticpro (&Qdbus_register_signal);
2240 defsubr (&Sdbus_register_signal);
2241
d67b4f80 2242 Qdbus_register_method = intern_c_string ("dbus-register-method");
17bc8f94
MA
2243 staticpro (&Qdbus_register_method);
2244 defsubr (&Sdbus_register_method);
2245
d67b4f80 2246 Qdbus_error = intern_c_string ("dbus-error");
033b73e2
MA
2247 staticpro (&Qdbus_error);
2248 Fput (Qdbus_error, Qerror_conditions,
2249 list2 (Qdbus_error, Qerror));
2250 Fput (Qdbus_error, Qerror_message,
d67b4f80 2251 make_pure_c_string ("D-Bus error"));
033b73e2 2252
d67b4f80 2253 QCdbus_system_bus = intern_c_string (":system");
39abdd4a
MA
2254 staticpro (&QCdbus_system_bus);
2255
d67b4f80 2256 QCdbus_session_bus = intern_c_string (":session");
39abdd4a 2257 staticpro (&QCdbus_session_bus);
033b73e2 2258
b4289b64
MA
2259 QCdbus_request_name_allow_replacement
2260 = intern_c_string (":allow-replacement");
5b83ba18
MA
2261 staticpro (&QCdbus_request_name_allow_replacement);
2262
2263 QCdbus_request_name_replace_existing = intern_c_string (":replace-existing");
2264 staticpro (&QCdbus_request_name_replace_existing);
2265
2266 QCdbus_request_name_do_not_queue = intern_c_string (":do-not-queue");
2267 staticpro (&QCdbus_request_name_do_not_queue);
2268
2269 QCdbus_request_name_reply_primary_owner = intern_c_string (":primary-owner");
2270 staticpro (&QCdbus_request_name_reply_primary_owner);
2271
2272 QCdbus_request_name_reply_exists = intern_c_string (":exists");
2273 staticpro (&QCdbus_request_name_reply_exists);
2274
2275 QCdbus_request_name_reply_in_queue = intern_c_string (":in-queue");
2276 staticpro (&QCdbus_request_name_reply_in_queue);
2277
2278 QCdbus_request_name_reply_already_owner = intern_c_string (":already-owner");
2279 staticpro (&QCdbus_request_name_reply_already_owner);
2280
d67b4f80 2281 QCdbus_timeout = intern_c_string (":timeout");
90b3fc84
MA
2282 staticpro (&QCdbus_timeout);
2283
d67b4f80 2284 QCdbus_type_byte = intern_c_string (":byte");
54371585
MA
2285 staticpro (&QCdbus_type_byte);
2286
d67b4f80 2287 QCdbus_type_boolean = intern_c_string (":boolean");
54371585
MA
2288 staticpro (&QCdbus_type_boolean);
2289
d67b4f80 2290 QCdbus_type_int16 = intern_c_string (":int16");
54371585
MA
2291 staticpro (&QCdbus_type_int16);
2292
d67b4f80 2293 QCdbus_type_uint16 = intern_c_string (":uint16");
54371585
MA
2294 staticpro (&QCdbus_type_uint16);
2295
d67b4f80 2296 QCdbus_type_int32 = intern_c_string (":int32");
54371585
MA
2297 staticpro (&QCdbus_type_int32);
2298
d67b4f80 2299 QCdbus_type_uint32 = intern_c_string (":uint32");
54371585
MA
2300 staticpro (&QCdbus_type_uint32);
2301
d67b4f80 2302 QCdbus_type_int64 = intern_c_string (":int64");
54371585
MA
2303 staticpro (&QCdbus_type_int64);
2304
d67b4f80 2305 QCdbus_type_uint64 = intern_c_string (":uint64");
54371585
MA
2306 staticpro (&QCdbus_type_uint64);
2307
d67b4f80 2308 QCdbus_type_double = intern_c_string (":double");
54371585
MA
2309 staticpro (&QCdbus_type_double);
2310
d67b4f80 2311 QCdbus_type_string = intern_c_string (":string");
54371585
MA
2312 staticpro (&QCdbus_type_string);
2313
d67b4f80 2314 QCdbus_type_object_path = intern_c_string (":object-path");
54371585
MA
2315 staticpro (&QCdbus_type_object_path);
2316
d67b4f80 2317 QCdbus_type_signature = intern_c_string (":signature");
54371585
MA
2318 staticpro (&QCdbus_type_signature);
2319
da1fec2b
MA
2320#ifdef DBUS_TYPE_UNIX_FD
2321 QCdbus_type_unix_fd = intern_c_string (":unix-fd");
2322 staticpro (&QCdbus_type_unix_fd);
2323#endif
2324
d67b4f80 2325 QCdbus_type_array = intern_c_string (":array");
54371585
MA
2326 staticpro (&QCdbus_type_array);
2327
d67b4f80 2328 QCdbus_type_variant = intern_c_string (":variant");
54371585
MA
2329 staticpro (&QCdbus_type_variant);
2330
d67b4f80 2331 QCdbus_type_struct = intern_c_string (":struct");
54371585
MA
2332 staticpro (&QCdbus_type_struct);
2333
d67b4f80 2334 QCdbus_type_dict_entry = intern_c_string (":dict-entry");
54371585
MA
2335 staticpro (&QCdbus_type_dict_entry);
2336
0c372655 2337 DEFVAR_LISP ("dbus-registered-buses",
29208e82 2338 Vdbus_registered_buses,
0c372655
MA
2339 doc: /* List of D-Bus buses we are polling for messages. */);
2340 Vdbus_registered_buses = Qnil;
2341
f04bb9b2 2342 DEFVAR_LISP ("dbus-registered-objects-table",
29208e82 2343 Vdbus_registered_objects_table,
39abdd4a 2344 doc: /* Hash table of registered functions for D-Bus.
0c372655 2345
f04bb9b2
MA
2346There are two different uses of the hash table: for accessing
2347registered interfaces properties, targeted by signals or method calls,
2348and for calling handlers in case of non-blocking method call returns.
13ecc6dc
MA
2349
2350In the first case, the key in the hash table is the list (BUS
0c372655
MA
2351INTERFACE MEMBER). BUS is either a Lisp symbol, `:system' or
2352`:session', or a string denoting the bus address. INTERFACE is a
2353string which denotes a D-Bus interface, and MEMBER, also a string, is
2354either a method, a signal or a property INTERFACE is offering. All
2355arguments but BUS must not be nil.
a31d47c7 2356
f5306ca3 2357The value in the hash table is a list of quadruple lists
f04bb9b2 2358\((UNAME SERVICE PATH OBJECT) (UNAME SERVICE PATH OBJECT) ...).
a31d47c7 2359SERVICE is the service name as registered, UNAME is the corresponding
f04bb9b2
MA
2360unique name. In case of registered methods and properties, UNAME is
2361nil. PATH is the object path of the sending object. All of them can
2362be nil, which means a wildcard then. OBJECT is either the handler to
2363be called when a D-Bus message, which matches the key criteria,
2364arrives (methods and signals), or a cons cell containing the value of
2365the property.
13ecc6dc 2366
0c372655
MA
2367In the second case, the key in the hash table is the list (BUS
2368SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
2369string denoting the bus address. SERIAL is the serial number of the
2370non-blocking method call, a reply is expected. Both arguments must
2371not be nil. The value in the hash table is HANDLER, the function to
2372be called when the D-Bus reply message arrives. */);
2373 {
2374 Lisp_Object args[2];
2375 args[0] = QCtest;
2376 args[1] = Qequal;
2377 Vdbus_registered_objects_table = Fmake_hash_table (2, args);
2378 }
033b73e2 2379
29208e82 2380 DEFVAR_LISP ("dbus-debug", Vdbus_debug,
39abdd4a 2381 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
2382#ifdef DBUS_DEBUG
2383 Vdbus_debug = Qt;
a79b0f28
MA
2384 /* We can also set environment variable DBUS_VERBOSE=1 in order to
2385 see more traces. This requires libdbus-1 to be configured with
2386 --enable-verbose-mode. */
033b73e2
MA
2387#else
2388 Vdbus_debug = Qnil;
2389#endif
2390
d67b4f80 2391 Fprovide (intern_c_string ("dbusbind"), Qnil);
033b73e2
MA
2392
2393}
2394
2395#endif /* HAVE_DBUS */