aboutsummaryrefslogtreecommitdiffstats
path: root/src/dbusbind.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbusbind.c')
-rw-r--r--src/dbusbind.c817
1 files changed, 817 insertions, 0 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c
new file mode 100644
index 00000000000..07fc24243d7
--- /dev/null
+++ b/src/dbusbind.c
@@ -0,0 +1,817 @@
1/* Elisp bindings for D-Bus.
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19Boston, MA 02110-1301, USA. */
20
21#include "config.h"
22
23#ifdef HAVE_DBUS
24#include <stdlib.h>
25#include <dbus/dbus.h>
26#include "lisp.h"
27#include "frame.h"
28#include "termhooks.h"
29#include "keyboard.h"
30
31
32/* Subroutines. */
33Lisp_Object Qdbus_get_unique_name;
34Lisp_Object Qdbus_call_method;
35Lisp_Object Qdbus_send_signal;
36Lisp_Object Qdbus_register_signal;
37Lisp_Object Qdbus_unregister_signal;
38
39/* D-Bus error symbol. */
40Lisp_Object Qdbus_error;
41
42/* Lisp symbols of the system and session buses. */
43Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
44
45/* Hash table which keeps function definitions. */
46Lisp_Object Vdbus_registered_functions_table;
47
48/* Whether to debug D-Bus. */
49Lisp_Object Vdbus_debug;
50
51
52/* We use "xd_" and "XD_" as prefix for all internal symbols, because
53 we don't want to poison other namespaces with "dbus_". */
54
55/* Raise a Lisp error from a D-Bus error. */
56#define XD_ERROR(error) \
57 { \
58 char s[1024]; \
59 strcpy (s, error.message); \
60 dbus_error_free (&error); \
61 /* Remove the trailing newline. */ \
62 if (strchr (s, '\n') != NULL) \
63 s[strlen (s) - 1] = '\0'; \
64 xsignal1 (Qdbus_error, build_string (s)); \
65 }
66
67/* Macros for debugging. In order to enable them, build with
68 "make MYCPPFLAGS='-DDBUS_DEBUG'". */
69#ifdef DBUS_DEBUG
70#define XD_DEBUG_MESSAGE(...) \
71 { \
72 char s[1024]; \
73 sprintf (s, __VA_ARGS__); \
74 printf ("%s: %s\n", __func__, s); \
75 message ("%s: %s", __func__, s); \
76 }
77#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
78 if (!valid_lisp_object_p (object)) \
79 { \
80 XD_DEBUG_MESSAGE ("%s Assertion failure", __LINE__); \
81 xsignal1 (Qdbus_error, build_string ("Assertion failure")); \
82 }
83
84#else /* !DBUS_DEBUG */
85#define XD_DEBUG_MESSAGE(...) \
86 if (!NILP (Vdbus_debug)) \
87 { \
88 char s[1024]; \
89 sprintf (s, __VA_ARGS__); \
90 message ("%s: %s", __func__, s); \
91 }
92#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
93#endif
94
95/* Determine the DBusType of a given Lisp object. It is used to
96 convert Lisp objects, being arguments of `dbus-call-method' or
97 `dbus-send-signal', into corresponding C values appended as
98 arguments to a D-Bus message. */
99#define XD_LISP_OBJECT_TO_DBUS_TYPE(object) \
100 (EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN : \
101 (NATNUMP (object)) ? DBUS_TYPE_UINT32 : \
102 (INTEGERP (object)) ? DBUS_TYPE_INT32 : \
103 (FLOATP (object)) ? DBUS_TYPE_DOUBLE : \
104 (STRINGP (object)) ? DBUS_TYPE_STRING : \
105 DBUS_TYPE_INVALID
106
107/* Extract C value from Lisp OBJECT. DTYPE must be a valid DBusType,
108 as detected by XD_LISP_OBJECT_TO_DBUS_TYPE. Compound types are not
109 supported (yet). It is used to convert Lisp objects, being
110 arguments of `dbus-call-method' or `dbus-send-signal', into
111 corresponding C values appended as arguments to a D-Bus
112 message. */
113char *
114xd_retrieve_value (dtype, object)
115 uint dtype;
116 Lisp_Object object;
117{
118
119 XD_DEBUG_VALID_LISP_OBJECT_P (object);
120 switch (dtype)
121 {
122 case DBUS_TYPE_BOOLEAN:
123 XD_DEBUG_MESSAGE ("%d %s", dtype, (NILP (object)) ? "false" : "true");
124 return (NILP (object)) ? (char *) FALSE : (char *) TRUE;
125 case DBUS_TYPE_UINT32:
126 XD_DEBUG_MESSAGE ("%d %d", dtype, XUINT (object));
127 return (char *) XUINT (object);
128 case DBUS_TYPE_INT32:
129 XD_DEBUG_MESSAGE ("%d %d", dtype, XINT (object));
130 return (char *) XINT (object);
131 case DBUS_TYPE_DOUBLE:
132 XD_DEBUG_MESSAGE ("%d %d", dtype, XFLOAT (object));
133 return (char *) XFLOAT (object);
134 case DBUS_TYPE_STRING:
135 XD_DEBUG_MESSAGE ("%d %s", dtype, SDATA (object));
136 return SDATA (object);
137 default:
138 XD_DEBUG_MESSAGE ("DBus-Type %d not supported", dtype);
139 return NULL;
140 }
141}
142
143/* Retrieve C value from a DBusMessageIter structure ITER, and return
144 a converted Lisp object. The type DTYPE of the argument of the
145 D-Bus message must be a valid DBusType. Compound D-Bus types are
146 partly supported; they result always in a Lisp list. */
147Lisp_Object
148xd_retrieve_arg (dtype, iter)
149 uint dtype;
150 DBusMessageIter *iter;
151{
152
153 switch (dtype)
154 {
155 case DBUS_TYPE_BOOLEAN:
156 {
157 dbus_bool_t val;
158 dbus_message_iter_get_basic (iter, &val);
159 XD_DEBUG_MESSAGE ("%d %s", dtype, (val == FALSE) ? "false" : "true");
160 return (val == FALSE) ? Qnil : Qt;
161 }
162 case DBUS_TYPE_INT32:
163 case DBUS_TYPE_UINT32:
164 {
165 dbus_uint32_t val;
166 dbus_message_iter_get_basic (iter, &val);
167 XD_DEBUG_MESSAGE ("%d %d", dtype, val);
168 return make_number (val);
169 }
170 case DBUS_TYPE_STRING:
171 case DBUS_TYPE_OBJECT_PATH:
172 {
173 char *val;
174 dbus_message_iter_get_basic (iter, &val);
175 XD_DEBUG_MESSAGE ("%d %s", dtype, val);
176 return build_string (val);
177 }
178 case DBUS_TYPE_ARRAY:
179 case DBUS_TYPE_VARIANT:
180 case DBUS_TYPE_STRUCT:
181 case DBUS_TYPE_DICT_ENTRY:
182 {
183 Lisp_Object result;
184 struct gcpro gcpro1;
185 result = Qnil;
186 GCPRO1 (result);
187 DBusMessageIter subiter;
188 int subtype;
189 dbus_message_iter_recurse (iter, &subiter);
190 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
191 != DBUS_TYPE_INVALID)
192 {
193 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
194 dbus_message_iter_next (&subiter);
195 }
196 RETURN_UNGCPRO (Fnreverse (result));
197 }
198 default:
199 XD_DEBUG_MESSAGE ("DBusType %d not supported", dtype);
200 return Qnil;
201 }
202}
203
204
205/* Initialize D-Bus connection. BUS is a Lisp symbol, either :system
206 or :session. It tells which D-Bus to be initialized. */
207DBusConnection *
208xd_initialize (bus)
209 Lisp_Object bus;
210{
211 DBusConnection *connection;
212 DBusError derror;
213
214 /* Parameter check. */
215 CHECK_SYMBOL (bus);
216 if (!((EQ (bus, QCdbus_system_bus)) || (EQ (bus, QCdbus_session_bus))))
217 xsignal2 (Qdbus_error, build_string ("Wrong bus name"), bus);
218
219 /* Open a connection to the bus. */
220 dbus_error_init (&derror);
221
222 if (EQ (bus, QCdbus_system_bus))
223 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
224 else
225 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
226
227 if (dbus_error_is_set (&derror))
228 XD_ERROR (derror);
229
230 if (connection == NULL)
231 xsignal2 (Qdbus_error, build_string ("No connection"), bus);
232
233 /* Return the result. */
234 return connection;
235}
236
237DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
238 1, 1, 0,
239 doc: /* Return the unique name of Emacs registered at D-Bus BUS as string. */)
240 (bus)
241 Lisp_Object bus;
242{
243 DBusConnection *connection;
244 char name[1024];
245
246 /* Check parameters. */
247 CHECK_SYMBOL (bus);
248
249 /* Open a connection to the bus. */
250 connection = xd_initialize (bus);
251
252 /* Request the name. */
253 strcpy (name, dbus_bus_get_unique_name (connection));
254 if (name == NULL)
255 xsignal1 (Qdbus_error, build_string ("No unique name available"));
256
257 /* Return. */
258 return build_string (name);
259}
260
261DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
262 doc: /* Call METHOD on the D-Bus BUS.
263
264BUS is either the symbol `:system' or the symbol `:session'.
265
266SERVICE is the D-Bus service name to be used. PATH is the D-Bus
267object path SERVICE is registered at. INTERFACE is an interface
268offered by SERVICE. It must provide METHOD.
269
270All other arguments ARGS are passed to METHOD as arguments. They are
271converted into D-Bus types via the following rules:
272
273 t and nil => DBUS_TYPE_BOOLEAN
274 number => DBUS_TYPE_UINT32
275 integer => DBUS_TYPE_INT32
276 float => DBUS_TYPE_DOUBLE
277 string => DBUS_TYPE_STRING
278
279Other Lisp objects are not supported as input arguments of METHOD.
280
281`dbus-call-method' returns the resulting values of METHOD as a list of
282Lisp objects. The type conversion happens the other direction as for
283input arguments. Additionally to the types supported for input
284arguments, the D-Bus compound types DBUS_TYPE_ARRAY, DBUS_TYPE_VARIANT,
285DBUS_TYPE_STRUCT and DBUS_TYPE_DICT_ENTRY are accepted. All of them
286are converted into a list of Lisp objects which correspond to the
287elements of the D-Bus container. Example:
288
289\(dbus-call-method
290 :session "GetKeyField" "org.gnome.seahorse"
291 "/org/gnome/seahorse/keys/openpgp" "org.gnome.seahorse.Keys"
292 "openpgp:657984B8C7A966DD" "simple-name")
293
294 => (t ("Philip R. Zimmermann"))
295
296If the result of the METHOD call is just one value, the converted Lisp
297object is returned instead of a list containing this single Lisp object.
298
299\(dbus-call-method
300 :system "GetPropertyString" "org.freedesktop.Hal"
301 "/org/freedesktop/Hal/devices/computer" "org.freedesktop.Hal.Device"
302 "system.kernel.machine")
303
304 => "i686"
305
306usage: (dbus-call-method BUS METHOD SERVICE PATH INTERFACE &rest ARGS) */)
307 (nargs, args)
308 int nargs;
309 register Lisp_Object *args;
310{
311 Lisp_Object bus, method, service, path, interface;
312 Lisp_Object result;
313 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
314 DBusConnection *connection;
315 DBusMessage *dmessage;
316 DBusMessage *reply;
317 DBusMessageIter iter;
318 DBusError derror;
319 uint dtype;
320 int i;
321 char *value;
322
323 /* Check parameters. */
324 bus = args[0];
325 method = args[1];
326 service = args[2];
327 path = args[3];
328 interface = args[4];
329
330 CHECK_SYMBOL (bus);
331 CHECK_STRING (method);
332 CHECK_STRING (service);
333 CHECK_STRING (path);
334 CHECK_STRING (interface);
335 GCPRO5 (bus, method, service, path, interface);
336
337 XD_DEBUG_MESSAGE ("%s %s %s %s",
338 SDATA (method),
339 SDATA (service),
340 SDATA (path),
341 SDATA (interface));
342
343 /* Open a connection to the bus. */
344 connection = xd_initialize (bus);
345
346 /* Create the message. */
347 dmessage = dbus_message_new_method_call (SDATA (service),
348 SDATA (path),
349 SDATA (interface),
350 SDATA (method));
351 if (dmessage == NULL)
352 {
353 UNGCPRO;
354 xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
355 }
356
357 UNGCPRO;
358
359 /* Append parameters to the message. */
360 for (i = 5; i < nargs; ++i)
361 {
362
363 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
364 XD_DEBUG_MESSAGE ("Parameter%d %s",
365 i-4,
366 SDATA (format2 ("%s", args[i], Qnil)));
367
368 dtype = XD_LISP_OBJECT_TO_DBUS_TYPE (args[i]);
369 if (dtype == DBUS_TYPE_INVALID)
370 xsignal2 (Qdbus_error, build_string ("Not a valid argument"), args[i]);
371
372 value = (char *) xd_retrieve_value (dtype, args[i]);
373
374 if (!dbus_message_append_args (dmessage,
375 dtype,
376 &value,
377 DBUS_TYPE_INVALID))
378 xsignal2 (Qdbus_error,
379 build_string ("Unable to append argument"), args[i]);
380 }
381
382 /* Send the message. */
383 dbus_error_init (&derror);
384 reply = dbus_connection_send_with_reply_and_block (connection,
385 dmessage,
386 -1,
387 &derror);
388
389 if (dbus_error_is_set (&derror))
390 XD_ERROR (derror);
391
392 if (reply == NULL)
393 xsignal1 (Qdbus_error, build_string ("No reply"));
394
395 XD_DEBUG_MESSAGE ("Message sent");
396
397 /* Collect the results. */
398 result = Qnil;
399 GCPRO1 (result);
400
401 if (!dbus_message_iter_init (reply, &iter))
402 {
403 UNGCPRO;
404 xsignal1 (Qdbus_error, build_string ("Cannot read reply"));
405 }
406
407 /* Loop over the parameters of the D-Bus reply message. Construct a
408 Lisp list, which is returned by `dbus-call-method'. */
409 while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
410 {
411 result = Fcons (xd_retrieve_arg (dtype, &iter), result);
412 dbus_message_iter_next (&iter);
413 }
414
415 /* Cleanup. */
416 dbus_message_unref (dmessage);
417 dbus_message_unref (reply);
418
419 /* Return the result. If there is only one single Lisp object,
420 return it as-it-is, otherwise return the reversed list. */
421 if (XUINT (Flength (result)) == 1)
422 RETURN_UNGCPRO (XCAR (result));
423 else
424 RETURN_UNGCPRO (Fnreverse (result));
425}
426
427DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
428 doc: /* Send signal SIGNAL on the D-Bus BUS.
429
430BUS is either the symbol `:system' or the symbol `:session'.
431
432SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
433D-Bus object path SERVICE is registered at. INTERFACE is an interface
434offered by SERVICE. It must provide signal SIGNAL.
435
436All other arguments ARGS are passed to SIGNAL as arguments. They are
437converted into D-Bus types via the following rules:
438
439 t and nil => DBUS_TYPE_BOOLEAN
440 number => DBUS_TYPE_UINT32
441 integer => DBUS_TYPE_INT32
442 float => DBUS_TYPE_DOUBLE
443 string => DBUS_TYPE_STRING
444
445Other Lisp objects are not supported as arguments of SIGNAL.
446
447Example:
448
449\(dbus-send-signal
450 :session "Started" "org.gnu.emacs" "/org/gnu/emacs" "org.gnu.emacs")))
451
452usage: (dbus-send-signal BUS SIGNAL SERVICE PATH INTERFACE &rest ARGS) */)
453 (nargs, args)
454 int nargs;
455 register Lisp_Object *args;
456{
457 Lisp_Object bus, signal, service, path, interface;
458 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
459 DBusConnection *connection;
460 DBusMessage *dmessage;
461 uint dtype;
462 int i;
463 char *value;
464
465 /* Check parameters. */
466 bus = args[0];
467 signal = args[1];
468 service = args[2];
469 path = args[3];
470 interface = args[4];
471
472 CHECK_SYMBOL (bus);
473 CHECK_STRING (signal);
474 CHECK_STRING (service);
475 CHECK_STRING (path);
476 CHECK_STRING (interface);
477 GCPRO5 (bus, signal, service, path, interface);
478
479 XD_DEBUG_MESSAGE ("%s %s %s %s",
480 SDATA (signal),
481 SDATA (service),
482 SDATA (path),
483 SDATA (interface));
484
485 /* Open a connection to the bus. */
486 connection = xd_initialize (bus);
487
488 /* Create the message. */
489 dmessage = dbus_message_new_signal (SDATA (path),
490 SDATA (interface),
491 SDATA (signal));
492 if (dmessage == NULL)
493 {
494 UNGCPRO;
495 xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
496 }
497
498 UNGCPRO;
499
500 /* Append parameters to the message. */
501 for (i = 5; i < nargs; ++i)
502 {
503 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
504 XD_DEBUG_MESSAGE ("Parameter%d %s",
505 i-4,
506 SDATA (format2 ("%s", args[i], Qnil)));
507
508 dtype = XD_LISP_OBJECT_TO_DBUS_TYPE (args[i]);
509 if (dtype == DBUS_TYPE_INVALID)
510 xsignal2 (Qdbus_error, build_string ("Not a valid argument"), args[i]);
511
512 value = (char *) xd_retrieve_value (dtype, args[i]);
513
514 if (!dbus_message_append_args (dmessage,
515 dtype,
516 &value,
517 DBUS_TYPE_INVALID))
518 xsignal2 (Qdbus_error,
519 build_string ("Unable to append argument"), args[i]);
520 }
521
522 /* Send the message. The message is just added to the outgoing
523 message queue. */
524 if (!dbus_connection_send (connection, dmessage, NULL))
525 xsignal1 (Qdbus_error, build_string ("Cannot send message"));
526
527 /* Flush connection to ensure the message is handled. */
528 dbus_connection_flush (connection);
529
530 XD_DEBUG_MESSAGE ("Signal sent");
531
532 /* Cleanup. */
533 dbus_message_unref (dmessage);
534
535 /* Return. */
536 return Qt;
537}
538
539/* Read queued incoming message of the D-Bus BUS. BUS is a Lisp
540 symbol, either :system or :session. */
541Lisp_Object
542xd_read_message (bus)
543 Lisp_Object bus;
544{
545 Lisp_Object key;
546 struct gcpro gcpro1;
547 static struct input_event event;
548 DBusConnection *connection;
549 DBusMessage *dmessage;
550 DBusMessageIter iter;
551 uint dtype;
552 char service[1024], path[1024], interface[1024], member[1024];
553
554 /* Open a connection to the bus. */
555 connection = xd_initialize (bus);
556
557 /* Non blocking read of the next available message. */
558 dbus_connection_read_write (connection, 0);
559 dmessage = dbus_connection_pop_message (connection);
560
561 /* Return if there is no queued message. */
562 if (dmessage == NULL)
563 return;
564
565 /* There is a message in the queue. Construct the D-Bus event. */
566 XD_DEBUG_MESSAGE ("Event received");
567 EVENT_INIT (event);
568
569 event.kind = DBUS_EVENT;
570 event.frame_or_window = Qnil;
571
572 /* Collect the parameters. */
573 event.arg = Qnil;
574 GCPRO1 (event.arg);
575
576 if (!dbus_message_iter_init (dmessage, &iter))
577 {
578 UNGCPRO;
579 XD_DEBUG_MESSAGE ("Cannot read event");
580 return;
581 }
582
583 /* Loop over the resulting parameters. Construct a list. */
584 while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
585 {
586 event.arg = Fcons (xd_retrieve_arg (dtype, &iter), event.arg);
587 dbus_message_iter_next (&iter);
588 }
589
590 /* The arguments are stored in reverse order. Reorder them. */
591 event.arg = Fnreverse (event.arg);
592
593 /* Read service, object path interface and member from the
594 message. */
595 strcpy (service, dbus_message_get_sender (dmessage));
596 strcpy (path, dbus_message_get_path (dmessage));
597 strcpy (interface, dbus_message_get_interface (dmessage));
598 strcpy (member, dbus_message_get_member (dmessage));
599
600 /* Add them to the event. */
601 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
602 event.arg);
603 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
604 event.arg);
605 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
606 event.arg);
607 event.arg = Fcons ((service == NULL ? Qnil : build_string (service)),
608 event.arg);
609
610 /* Add the bus symbol to the event. */
611 event.arg = Fcons (bus, event.arg);
612
613 /* Add the registered function of the message. */
614 key = list3 (bus,
615 (interface == NULL ? Qnil : build_string (interface)),
616 (member == NULL ? Qnil : build_string (member)));
617 event.arg = Fcons (Fgethash (key, Vdbus_registered_functions_table, Qnil),
618 event.arg);
619
620 /* Store it into the input event queue. */
621 kbd_buffer_store_event (&event);
622
623 /* Cleanup. */
624 dbus_message_unref (dmessage);
625 UNGCPRO;
626}
627
628/* Read queued incoming messages from the system and session buses. */
629void
630xd_read_queued_messages ()
631{
632
633 /* Vdbus_registered_functions_table will be made as hash table in
634 dbus.el. When it isn't loaded yet, it doesn't make sense to
635 handle D-Bus messages. Furthermore, we ignore all Lisp errors
636 during the call. */
637 if (HASH_TABLE_P (Vdbus_registered_functions_table))
638 {
639 internal_condition_case_1 (xd_read_message, QCdbus_system_bus,
640 Qerror, Fidentity);
641 internal_condition_case_1 (xd_read_message, QCdbus_session_bus,
642 Qerror, Fidentity);
643 }
644}
645
646DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
647 6, 6, 0,
648 doc: /* Register for signal SIGNAL on the D-Bus BUS.
649
650BUS is either the symbol `:system' or the symbol `:session'.
651
652SERVICE is the D-Bus service name used by the sending D-Bus object.
653It can be either a known name or the unique name of the D-Bus object
654sending the signal. When SERVICE is nil, related signals from all
655D-Bus objects shall be accepted.
656
657PATH is the D-Bus object path SERVICE is registered. It can also be
658nil if the path name of incoming signals shall not be checked.
659
660INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
661HANDLER is a Lisp function to be called when the signal is received.
662It must accept as arguments the values SIGNAL is sending. INTERFACE,
663SIGNAL and HANDLER must not be nil. Example:
664
665\(defun my-signal-handler (device)
666 (message "Device %s added" device))
667
668\(dbus-register-signal
669 :system "DeviceAdded"
670 (dbus-get-name-owner :system "org.freedesktop.Hal")
671 "/org/freedesktop/Hal/Manager" "org.freedesktop.Hal.Manager"
672 'my-signal-handler)
673
674 => (:system "org.freedesktop.Hal.Manager" "DeviceAdded")
675
676`dbus-register-signal' returns an object, which can be used in
677`dbus-unregister-signal' for removing the registration. */)
678 (bus, signal, service, path, interface, handler)
679 Lisp_Object bus, signal, service, path, interface, handler;
680{
681 Lisp_Object key;
682 DBusConnection *connection;
683 char rule[1024];
684 DBusError derror;
685
686 /* Check parameters. */
687 CHECK_SYMBOL (bus);
688 CHECK_STRING (signal);
689 if (!NILP (service)) CHECK_STRING (service);
690 if (!NILP (path)) CHECK_STRING (path);
691 CHECK_STRING (interface);
692 CHECK_SYMBOL (handler);
693
694 /* Open a connection to the bus. */
695 connection = xd_initialize (bus);
696
697 /* Create a rule to receive related signals. */
698 sprintf (rule,
699 "type='signal',interface='%s',member=%s%",
700 SDATA (interface),
701 SDATA (signal));
702
703 /* Add service and path to the rule if they are non-nil. */
704 if (!NILP (service))
705 sprintf (rule, "%s,sender='%s'%", rule, SDATA (service));
706
707 if (!NILP (path))
708 sprintf (rule, "%s,path='%s'", rule, SDATA (path));
709
710 /* Add the rule to the bus. */
711 dbus_error_init (&derror);
712 dbus_bus_add_match (connection, rule, &derror);
713 if (dbus_error_is_set (&derror))
714 XD_ERROR (derror);
715
716 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
717
718 /* Create a hash table entry. */
719 key = list3 (bus, interface, signal);
720 Fputhash (key, handler, Vdbus_registered_functions_table);
721 XD_DEBUG_MESSAGE ("\"%s\" registered with handler \"%s\"",
722 SDATA (format2 ("%s", key, Qnil)),
723 SDATA (format2 ("%s", handler, Qnil)));
724
725 /* Return key. */
726 return key;
727}
728
729DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal,
730 1, 1, 0,
731 doc: /* Unregister OBJECT from the D-Bus.
732OBJECT must be the result of a preceding `dbus-register-signal' call. */)
733 (object)
734 Lisp_Object object;
735{
736
737 /* Check parameters. */
738 CHECK_SYMBOL (object);
739
740 XD_DEBUG_MESSAGE ("\"%s\" unregistered with handler \"%s\"",
741 SDATA (format2 ("%s", object, Qnil)),
742 SDATA (format2 ("%s", Fsymbol_function (object), Qnil)));
743
744 /* Unintern the signal symbol. */
745 Fremhash (object, Vdbus_registered_functions_table);
746
747 /* Return. */
748 return Qnil;
749}
750
751
752void
753syms_of_dbusbind ()
754{
755
756 Qdbus_get_unique_name = intern ("dbus-get-unique-name");
757 staticpro (&Qdbus_get_unique_name);
758 defsubr (&Sdbus_get_unique_name);
759
760 Qdbus_call_method = intern ("dbus-call-method");
761 staticpro (&Qdbus_call_method);
762 defsubr (&Sdbus_call_method);
763
764 Qdbus_send_signal = intern ("dbus-send-signal");
765 staticpro (&Qdbus_send_signal);
766 defsubr (&Sdbus_send_signal);
767
768 Qdbus_register_signal = intern ("dbus-register-signal");
769 staticpro (&Qdbus_register_signal);
770 defsubr (&Sdbus_register_signal);
771
772 Qdbus_unregister_signal = intern ("dbus-unregister-signal");
773 staticpro (&Qdbus_unregister_signal);
774 defsubr (&Sdbus_unregister_signal);
775
776 Qdbus_error = intern ("dbus-error");
777 staticpro (&Qdbus_error);
778 Fput (Qdbus_error, Qerror_conditions,
779 list2 (Qdbus_error, Qerror));
780 Fput (Qdbus_error, Qerror_message,
781 build_string ("D-Bus error"));
782
783 QCdbus_system_bus = intern (":system");
784 staticpro (&QCdbus_system_bus);
785
786 QCdbus_session_bus = intern (":session");
787 staticpro (&QCdbus_session_bus);
788
789 DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table,
790 doc: /* Hash table of registered functions for D-Bus.
791The key in the hash table is the list (BUS INTERFACE MEMBER). BUS is
792either the symbol `:system' or the symbol `:session'. INTERFACE is a
793string which denotes a D-Bus interface, and MEMBER, also a string, is
794either a method or a signal INTERFACE is offering.
795
796The value in the hash table a the function to be called when a D-Bus
797message, which matches the key criteria, arrives. */);
798 /* We initialize Vdbus_registered_functions_table in dbus.el,
799 because we need to define a hash table function first. */
800 Vdbus_registered_functions_table = Qnil;
801
802 DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
803 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
804#ifdef DBUS_DEBUG
805 Vdbus_debug = Qt;
806#else
807 Vdbus_debug = Qnil;
808#endif
809
810 Fprovide (intern ("dbusbind"), Qnil);
811
812}
813
814#endif /* HAVE_DBUS */
815
816/* arch-tag: 0e828477-b571-4fe4-b559-5c9211bc14b8
817 (do not change this comment) */