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