aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2008-07-18 20:20:03 +0000
committerMichael Albinus2008-07-18 20:20:03 +0000
commitf636d3cafdf3e7e7bacac174baec13d25aa9882d (patch)
treed71e665b7a22579f24af652a0af9633313e716b6
parentc961325a15277936974954818cf06d9bceed83cd (diff)
downloademacs-f636d3cafdf3e7e7bacac174baec13d25aa9882d.tar.gz
emacs-f636d3cafdf3e7e7bacac174baec13d25aa9882d.zip
* net/dbus.el (dbus-interface-properties): New defconst.
(dbus-introspect): Update docstring. (dbus-introspect-xml, dbus-introspect-get-attribute) (dbus-introspect-get-node-names, dbus-introspect-get-all-nodes) (dbus-introspect-get-interface-names) (dbus-introspect-get-interface, dbus-introspect-get-method-names) (dbus-introspect-get-method, dbus-introspect-get-signal-names) (dbus-introspect-get-signal, dbus-introspect-get-property-names) (dbus-introspect-get-property) (dbus-introspect-get-annotation-names) (dbus-introspect-get-annotation) (dbus-introspect-get-argument-names, dbus-introspect-get-argument) (dbus-introspect-get-signature, dbus-get-property) (dbus-set-property, dbus-get-all-properties): New defuns.
-rw-r--r--lisp/net/dbus.el403
1 files changed, 336 insertions, 67 deletions
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index 5b108a909f6..2b1f4534aae 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -59,6 +59,9 @@
59 (concat dbus-interface-dbus ".Introspectable") 59 (concat dbus-interface-dbus ".Introspectable")
60 "The interface supported by introspectable objects.") 60 "The interface supported by introspectable objects.")
61 61
62(defconst dbus-interface-properties (concat dbus-interface-dbus ".Properties")
63 "The interface for property objects.")
64
62(defmacro dbus-ignore-errors (&rest body) 65(defmacro dbus-ignore-errors (&rest body)
63 "Execute BODY; signal D-Bus error when `dbus-debug' is non-nil. 66 "Execute BODY; signal D-Bus error when `dbus-debug' is non-nil.
64Otherwise, return result of last form in BODY, or all other errors." 67Otherwise, return result of last form in BODY, or all other errors."
@@ -91,8 +94,8 @@ hash table."
91(defun dbus-unregister-object (object) 94(defun dbus-unregister-object (object)
92 "Unregister OBJECT from D-Bus. 95 "Unregister OBJECT from D-Bus.
93OBJECT must be the result of a preceding `dbus-register-method' 96OBJECT must be the result of a preceding `dbus-register-method'
94or `dbus-register-signal' call. It returns t if OBJECT has been 97or `dbus-register-signal' call. It returns `t' if OBJECT has
95unregistered, nil otherwise." 98been unregistered, `nil' otherwise."
96 ;; Check parameter. 99 ;; Check parameter.
97 (unless (and (consp object) (not (null (car object))) (consp (cdr object))) 100 (unless (and (consp object) (not (null (car object))) (consp (cdr object)))
98 (signal 'wrong-type-argument (list 'D-Bus object))) 101 (signal 'wrong-type-argument (list 'D-Bus object)))
@@ -183,7 +186,7 @@ EVENT is a list which starts with symbol `dbus-event':
183BUS identifies the D-Bus the message is coming from. It is 186BUS identifies the D-Bus the message is coming from. It is
184either the symbol `:system' or the symbol `:session'. SERIAL is 187either the symbol `:system' or the symbol `:session'. SERIAL is
185the serial number of the received D-Bus message if it is a method 188the serial number of the received D-Bus message if it is a method
186call, or nil. SERVICE and PATH are the unique name and the 189call, or `nil'. SERVICE and PATH are the unique name and the
187object path of the D-Bus object emitting the message. INTERFACE 190object path of the D-Bus object emitting the message. INTERFACE
188and MEMBER denote the message which has been sent. HANDLER is 191and MEMBER denote the message which has been sent. HANDLER is
189the function which has been registered for this message. ARGS 192the function which has been registered for this message. ARGS
@@ -224,7 +227,7 @@ part of the event, is called with arguments ARGS."
224 (dbus-check-event event) 227 (dbus-check-event event)
225 (setq result (apply (nth 7 event) (nthcdr 8 event))) 228 (setq result (apply (nth 7 event) (nthcdr 8 event)))
226 (unless (consp result) (setq result (cons result nil))) 229 (unless (consp result) (setq result (cons result nil)))
227 ;; Return a message when serial is not nil. 230 ;; Return a message when serial is not `nil'.
228 (when (not (null (nth 2 event))) 231 (when (not (null (nth 2 event)))
229 (apply 'dbus-method-return-internal 232 (apply 'dbus-method-return-internal
230 (nth 1 event) (nth 2 event) (nth 3 event) result))))) 233 (nth 1 event) (nth 2 event) (nth 3 event) result)))))
@@ -241,7 +244,7 @@ formed."
241(defun dbus-event-serial-number (event) 244(defun dbus-event-serial-number (event)
242 "Return the serial number of the corresponding D-Bus message. 245 "Return the serial number of the corresponding D-Bus message.
243The result is a number in case the D-Bus message is a method 246The result is a number in case the D-Bus message is a method
244call, or nil for all other mesage types. The serial number is 247call, or `nil' for all other mesage types. The serial number is
245needed for generating a reply message. EVENT is a D-Bus event, 248needed for generating a reply message. EVENT is a D-Bus event,
246see `dbus-check-event'. This function raises a `dbus-error' 249see `dbus-check-event'. This function raises a `dbus-error'
247signal in case the event is not well formed." 250signal in case the event is not well formed."
@@ -286,7 +289,7 @@ well formed."
286 289
287(defun dbus-list-activatable-names () 290(defun dbus-list-activatable-names ()
288 "Return the D-Bus service names which can be activated as list. 291 "Return the D-Bus service names which can be activated as list.
289The result is a list of strings, which is nil when there are no 292The result is a list of strings, which is `nil' when there are no
290activatable service names at all." 293activatable service names at all."
291 (dbus-ignore-errors 294 (dbus-ignore-errors
292 (dbus-call-method 295 (dbus-call-method
@@ -295,10 +298,10 @@ activatable service names at all."
295 298
296(defun dbus-list-names (bus) 299(defun dbus-list-names (bus)
297 "Return the service names registered at D-Bus BUS. 300 "Return the service names registered at D-Bus BUS.
298The result is a list of strings, which is nil when there are no 301The result is a list of strings, which is `nil' when there are no
299registered service names at all. Well known names are strings like 302registered service names at all. Well known names are strings
300\"org.freedesktop.DBus\". Names starting with \":\" are unique names 303like \"org.freedesktop.DBus\". Names starting with \":\" are
301for services." 304unique names for services."
302 (dbus-ignore-errors 305 (dbus-ignore-errors
303 (dbus-call-method 306 (dbus-call-method
304 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus "ListNames"))) 307 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus "ListNames")))
@@ -312,9 +315,9 @@ A service has a known name if it doesn't start with \":\"."
312 (add-to-list 'result name 'append))))) 315 (add-to-list 'result name 'append)))))
313 316
314(defun dbus-list-queued-owners (bus service) 317(defun dbus-list-queued-owners (bus service)
315"Return the unique names registered at D-Bus BUS and queued for SERVICE. 318 "Return the unique names registered at D-Bus BUS and queued for SERVICE.
316The result is a list of strings, or nil when there are no queued name 319The result is a list of strings, or `nil' when there are no
317owners service names at all." 320queued name owners service names at all."
318 (dbus-ignore-errors 321 (dbus-ignore-errors
319 (dbus-call-method 322 (dbus-call-method
320 bus dbus-service-dbus dbus-path-dbus 323 bus dbus-service-dbus dbus-path-dbus
@@ -322,7 +325,7 @@ owners service names at all."
322 325
323(defun dbus-get-name-owner (bus service) 326(defun dbus-get-name-owner (bus service)
324 "Return the name owner of SERVICE registered at D-Bus BUS. 327 "Return the name owner of SERVICE registered at D-Bus BUS.
325The result is either a string, or nil if there is no name owner." 328The result is either a string, or `nil' if there is no name owner."
326 (dbus-ignore-errors 329 (dbus-ignore-errors
327 (dbus-call-method 330 (dbus-call-method
328 bus dbus-service-dbus dbus-path-dbus 331 bus dbus-service-dbus dbus-path-dbus
@@ -337,67 +340,333 @@ The result is either a string, or nil if there is no name owner."
337 (dbus-call-method bus service dbus-path-dbus dbus-interface-peer "Ping")) 340 (dbus-call-method bus service dbus-path-dbus dbus-interface-peer "Ping"))
338 (dbus-error nil))) 341 (dbus-error nil)))
339 342
340(defun dbus-introspect (bus service path) 343
341 "Return the introspection data of SERVICE in D-Bus BUS at object path PATH. 344;;; D-Bus introspection.
342The data are in XML format.
343
344Example:
345 345
346\(dbus-introspect 346(defun dbus-introspect (bus service path)
347 :system \"org.freedesktop.Hal\" 347 "This function returns all interfaces and sub-nodes of SERVICE,
348 \"/org/freedesktop/Hal/devices/computer\")" 348registered at object path PATH at bus BUS.
349
350BUS must be either the symbol `:system' or the symbol `:session'.
351SERVICE must be a known service name, and PATH must be a valid
352object path. The last two parameters are strings. The result,
353the introspection data, is a string in XML format."
354 ;; We don't want to raise errors.
349 (dbus-ignore-errors 355 (dbus-ignore-errors
350 (dbus-call-method 356 (dbus-call-method
351 bus service path dbus-interface-introspectable "Introspect"))) 357 bus service path dbus-interface-introspectable "Introspect")))
352 358
353(if nil ;; Must be reworked. Shall we offer D-Bus signatures at all? 359(defun dbus-introspect-xml (bus service path)
354(defun dbus-get-signatures (bus interface signal) 360 "Return the introspection data of SERVICE in D-Bus BUS at object path PATH.
355 "Retrieve SIGNAL's type signatures from D-Bus. 361The data are a parsed list. The root object is a \"node\",
356The result is a list of SIGNAL's type signatures. Example: 362representing the object path PATH. The root object can contain
357 363\"interface\" and further \"node\" objects."
358 \(\"s\" \"b\" \"ai\"\) 364 ;; We don't want to raise errors.
365 (xml-node-name
366 (ignore-errors
367 (with-temp-buffer
368 (insert (dbus-introspect bus service path))
369 (xml-parse-region (point-min) (point-max))))))
370
371(defun dbus-introspect-get-attribute (object attribute)
372 "Return the ATTRIBUTE value of D-Bus introspection OBJECT.
373ATTRIBUTE must be a string according to the attribute names in
374the D-Bus specification."
375 (xml-get-attribute-or-nil object (intern attribute)))
376
377(defun dbus-introspect-get-node-names (bus service path)
378 "Return all node names of SERVICE in D-Bus BUS at object path PATH.
379It returns a list of strings. The node names stand for further
380object paths of the D-Bus service."
381 (let ((object (dbus-introspect-xml bus service path))
382 result)
383 (dolist (elt (xml-get-children object 'node) result)
384 (add-to-list
385 'result (dbus-introspect-get-attribute elt "name") 'append))))
386
387(defun dbus-introspect-get-all-nodes (bus service path)
388 "Return all node names of SERVICE in D-Bus BUS at object path PATH.
389It returns a list of strings, which are further object paths of SERVICE."
390 (let ((result (list path)))
391 (dolist (elt
392 (dbus-introspect-get-node-names bus service path)
393 result)
394 (setq elt (expand-file-name elt path))
395 (setq result
396 (append result (dbus-introspect-get-all-nodes bus service elt))))))
397
398(defun dbus-introspect-get-interface-names (bus service path)
399 "Return all interface names of SERVICE in D-Bus BUS at object path PATH.
400It returns a list of strings.
401
402There will be always the default interface
403\"org.freedesktop.DBus.Introspectable\". Another default
404interface is \"org.freedesktop.DBus.Properties\". If present,
405\"interface\" objects can also have \"property\" objects as
406children, beside \"method\" and \"signal\" objects."
407 (let ((object (dbus-introspect-xml bus service path))
408 result)
409 (dolist (elt (xml-get-children object 'interface) result)
410 (add-to-list
411 'result (dbus-introspect-get-attribute elt "name") 'append))))
412
413(defun dbus-introspect-get-interface (bus service path interface)
414 "Return the INTERFACE of SERVICE in D-Bus BUS at object path PATH.
415The return value is an XML object. INTERFACE must be a string,
416element of the list returned by
417`dbus-introspect-get-interface-names'. The resulting
418\"interface\" object can contain \"method\", \"signal\",
419\"property\" and \"annotation\" children."
420 (let ((elt (xml-get-children
421 (dbus-introspect-xml bus service path) 'interface)))
422 (while (and elt
423 (not (string-equal
424 interface
425 (dbus-introspect-get-attribute (car elt) "name"))))
426 (setq elt (cdr elt)))
427 (car elt)))
428
429(defun dbus-introspect-get-method-names (bus service path interface)
430 "Return a list of strings of all method names of INTERFACE.
431SERVICE is a service of D-Bus BUS at object path PATH."
432 (let ((object (dbus-introspect-get-interface bus service path interface))
433 result)
434 (dolist (elt (xml-get-children object 'method) result)
435 (add-to-list
436 'result (dbus-introspect-get-attribute elt "name") 'append))))
437
438(defun dbus-introspect-get-method (bus service path interface method)
439 "Return method METHOD of interface INTERFACE as XML object.
440It must be located at SERVICE in D-Bus BUS at object path PATH.
441METHOD must be a string, element of the list returned by
442`dbus-introspect-get-method-names'. The resulting \"method\"
443object can contain \"arg\" and \"annotation\" children."
444 (let ((elt (xml-get-children
445 (dbus-introspect-get-interface bus service path interface)
446 'method)))
447 (while (and elt
448 (not (string-equal
449 method (dbus-introspect-get-attribute (car elt) "name"))))
450 (setq elt (cdr elt)))
451 (car elt)))
452
453(defun dbus-introspect-get-signal-names (bus service path interface)
454 "Return a list of strings of all signal names of INTERFACE.
455SERVICE is a service of D-Bus BUS at object path PATH."
456 (let ((object (dbus-introspect-get-interface bus service path interface))
457 result)
458 (dolist (elt (xml-get-children object 'signal) result)
459 (add-to-list
460 'result (dbus-introspect-get-attribute elt "name") 'append))))
461
462(defun dbus-introspect-get-signal (bus service path interface signal)
463 "Return signal SIGNAL of interface INTERFACE as XML object.
464It must be located at SERVICE in D-Bus BUS at object path PATH.
465SIGNAL must be a string, element of the list returned by
466`dbus-introspect-get-signal-names'. The resulting \"signal\"
467object can contain \"arg\" and \"annotation\" children."
468 (let ((elt (xml-get-children
469 (dbus-introspect-get-interface bus service path interface)
470 'signal)))
471 (while (and elt
472 (not (string-equal
473 signal (dbus-introspect-get-attribute (car elt) "name"))))
474 (setq elt (cdr elt)))
475 (car elt)))
476
477(defun dbus-introspect-get-property-names (bus service path interface)
478 "Return a list of strings of all property names of INTERFACE.
479SERVICE is a service of D-Bus BUS at object path PATH."
480 (let ((object (dbus-introspect-get-interface bus service path interface))
481 result)
482 (dolist (elt (xml-get-children object 'property) result)
483 (add-to-list
484 'result (dbus-introspect-get-attribute elt "name") 'append))))
485
486(defun dbus-introspect-get-property (bus service path interface property)
487 "This function returns PROPERTY of INTERFACE as XML object.
488It must be located at SERVICE in D-Bus BUS at object path PATH.
489PROPERTY must be a string, element of the list returned by
490`dbus-introspect-get-property-names'. The resulting PROPERTY
491object can contain \"annotation\" children."
492 (let ((elt (xml-get-children
493 (dbus-introspect-get-interface bus service path interface)
494 'property)))
495 (while (and elt
496 (not (string-equal
497 property
498 (dbus-introspect-get-attribute (car elt) "name"))))
499 (setq elt (cdr elt)))
500 (car elt)))
501
502(defun dbus-introspect-get-annotation-names
503 (bus service path interface &optional name)
504 "Return all annotation names as list of strings.
505If NAME is `nil', the annotations are children of INTERFACE,
506otherwise NAME must be a \"method\", \"signal\", or \"property\"
507object, where the annotations belong to."
508 (let ((object
509 (if name
510 (or (dbus-introspect-get-method bus service path interface name)
511 (dbus-introspect-get-signal bus service path interface name)
512 (dbus-introspect-get-property bus service path interface name))
513 (dbus-introspect-get-interface bus service path interface)))
514 result)
515 (dolist (elt (xml-get-children object 'annotation) result)
516 (add-to-list
517 'result (dbus-introspect-get-attribute elt "name") 'append))))
518
519(defun dbus-introspect-get-annotation
520 (bus service path interface name annotation)
521 "Return ANNOTATION as XML object.
522If NAME is `nil', ANNOTATION is a child of INTERFACE, otherwise
523NAME must be the name of a \"method\", \"signal\", or
524\"property\" object, where the ANNOTATION belongs to."
525 (let ((elt (xml-get-children
526 (if name
527 (or (dbus-introspect-get-method
528 bus service path interface name)
529 (dbus-introspect-get-signal
530 bus service path interface name)
531 (dbus-introspect-get-property
532 bus service path interface name))
533 (dbus-introspect-get-interface bus service path interface))
534 'annotation)))
535 (while (and elt
536 (not (string-equal
537 annotation
538 (dbus-introspect-get-attribute (car elt) "name"))))
539 (setq elt (cdr elt)))
540 (car elt)))
541
542(defun dbus-introspect-get-argument-names (bus service path interface name)
543 "Return a list of all argument names as list of strings.
544NAME must be a \"method\" or \"signal\" object.
545
546Argument names are optional, the function can return `nil'
547therefore, even if the method or signal has arguments."
548 (let ((object
549 (or (dbus-introspect-get-method bus service path interface name)
550 (dbus-introspect-get-signal bus service path interface name)))
551 result)
552 (dolist (elt (xml-get-children object 'arg) result)
553 (add-to-list
554 'result (dbus-introspect-get-attribute elt "name") 'append))))
555
556(defun dbus-introspect-get-argument (bus service path interface name arg)
557 "Return argument ARG as XML object.
558NAME must be a \"method\" or \"signal\" object. ARG must be a
559string, element of the list returned by `dbus-introspect-get-argument-names'."
560 (let ((elt (xml-get-children
561 (or (dbus-introspect-get-method bus service path interface name)
562 (dbus-introspect-get-signal bus service path interface name))
563 'arg)))
564 (while (and elt
565 (not (string-equal
566 arg (dbus-introspect-get-attribute (car elt) "name"))))
567 (setq elt (cdr elt)))
568 (car elt)))
569
570(defun dbus-introspect-get-signature
571 (bus service path interface name &optional direction)
572 "Return signature of a `method' or `signal', represented by NAME, as string.
573If NAME is a `method', DIRECTION can be either \"in\" or \"out\".
574If DIRECTION is `nil', \"in\" is assumed.
575
576If NAME is a `signal', and DIRECTION is non-`nil', DIRECTION must
577be \"out\"."
578 ;; For methods, we use "in" as default direction.
579 (let ((object (or (dbus-introspect-get-method
580 bus service path interface name)
581 (dbus-introspect-get-signal
582 bus service path interface name))))
583 (when (and (string-equal
584 "method" (dbus-introspect-get-attribute object "name"))
585 (not (stringp direction)))
586 (setq direction "in"))
587 ;; In signals, no direction is given.
588 (when (string-equal "signal" (dbus-introspect-get-attribute object "name"))
589 (setq direction nil))
590 ;; Collect the signatures.
591 (mapconcat
592 '(lambda (x)
593 (let ((arg (dbus-introspect-get-argument
594 bus service path interface name x)))
595 (if (or (not (stringp direction))
596 (string-equal
597 direction
598 (dbus-introspect-get-attribute arg "direction")))
599 (dbus-introspect-get-attribute arg "type")
600 "")))
601 (dbus-introspect-get-argument-names bus service path interface name)
602 "")))
359 603
360This list represents 3 parameters of SIGNAL. The first parameter 604
361is of type string, the second parameter is of type boolean, and 605;;; D-Bus properties.
362the third parameter is of type array of integer.
363 606
364If INTERFACE or SIGNAL do not exist, or if they do not support 607(defun dbus-get-property (bus service path interface property)
365the D-Bus method org.freedesktop.DBus.Introspectable.Introspect, 608 "Return the value of PROPERTY of INTERFACE.
366the function returns nil." 609It will be checked at BUS, SERVICE, PATH. The result can be any
610valid D-Bus value, or `nil' if there is no PROPERTY."
367 (dbus-ignore-errors 611 (dbus-ignore-errors
368 (let ((introspect-xml 612 ;; We must check, whether the "org.freedesktop.DBus.Properties"
369 (with-temp-buffer 613 ;; interface is supported; otherwise the call blocks.
370 (insert (dbus-introspect bus interface)) 614 (when
371 (xml-parse-region (point-min) (point-max)))) 615 (member
372 node interfaces signals args result) 616 "Get"
373 ;; Get the root node. 617 (dbus-introspect-get-method-names
374 (setq node (xml-node-name introspect-xml)) 618 bus service path "org.freedesktop.DBus.Properties"))
375 ;; Get all interfaces. 619 ;; "Get" returns a variant, so we must use the car.
376 (setq interfaces (xml-get-children node 'interface)) 620 (car
377 (while interfaces 621 (dbus-call-method
378 (when (string-equal (xml-get-attribute (car interfaces) 'name) 622 bus service path dbus-interface-properties
379 interface) 623 "Get" interface property)))))
380 ;; That's the requested interface. Check for signals. 624
381 (setq signals (xml-get-children (car interfaces) 'signal)) 625(defun dbus-set-property (bus service path interface property value)
382 (while signals 626 "Set value of PROPERTY of INTERFACE to VALUE.
383 (when (string-equal (xml-get-attribute (car signals) 'name) signal) 627It will be checked at BUS, SERVICE, PATH. When the value has
384 ;; The signal we are looking for. 628been set successful, the result is VALUE. Otherwise, `nil' is
385 (setq args (xml-get-children (car signals) 'arg)) 629returned."
386 (while args 630 (dbus-ignore-errors
387 (unless (xml-get-attribute (car args) 'type) 631 (when
388 ;; This shouldn't happen, let's escape. 632 (and
389 (signal 'dbus-error nil)) 633 ;; We must check, whether the
390 ;; We append the signature. 634 ;; "org.freedesktop.DBus.Properties" interface is supported;
391 (setq 635 ;; otherwise the call blocks.
392 result (append result 636 (member
393 (list (xml-get-attribute (car args) 'type)))) 637 "Set"
394 (setq args (cdr args))) 638 (dbus-introspect-get-method-names
395 (setq signals nil)) 639 bus service path "org.freedesktop.DBus.Properties"))
396 (setq signals (cdr signals))) 640 ;; PROPERTY must be writable.
397 (setq interfaces nil)) 641 (string-equal
398 (setq interfaces (cdr interfaces))) 642 "readwrite"
399 result))) 643 (dbus-introspect-get-attribute
400) ;; (if nil ... 644 bus service path interface property)
645 "access"))
646 ;; "Set" requires a variant.
647 (dbus-call-method
648 bus service path dbus-interface-properties
649 "Set" interface property (list :variant value))
650 ;; Return VALUE.
651 (dbus-get-property bus service path interface property))))
652
653(defun dbus-get-all-properties (bus service path interface)
654 "Return all properties of INTERFACE at BUS, SERVICE, PATH.
655The result is a list of entries. Every entry is a cons of the
656name of the property, and its value. If there are no properties,
657`nil' is returned."
658 ;; "org.freedesktop.DBus.Properties.GetAll" is not supported at
659 ;; all interfaces. Therefore, we do it ourselves.
660 (dbus-ignore-errors
661 (let (result)
662 (dolist (property
663 (dbus-introspect-get-property-names
664 bus service path interface)
665 result)
666 (add-to-list
667 'result
668 (cons property (dbus-get-property bus service path interface property))
669 'append)))))
401 670
402(provide 'dbus) 671(provide 'dbus)
403 672