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