;;; dbus.el --- Elisp bindings for D-Bus.
-;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2011 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, hardware
hash table."
(let (result)
(maphash
- '(lambda (key value) (add-to-list 'result (cons key value) 'append))
+ (lambda (key value) (add-to-list 'result (cons key value) 'append))
dbus-registered-objects-table)
result))
(defun dbus-unregister-service (bus service)
"Unregister all objects related to SERVICE from D-Bus BUS.
BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address. SERVICE must be a known service name."
+denoting the bus address. SERVICE must be a known service name.
+
+The function returns a keyword, indicating the result of the
+operation. One of the following keywords is returned:
+
+`:released': Service has become the primary owner of the name.
+
+`:non-existent': Service name does not exist on this bus.
+
+`:not-owner': We are neither the primary owner nor waiting in the
+queue of this service."
+
(maphash
(lambda (key value)
(dolist (elt value)
(puthash key (delete elt value) dbus-registered-objects-table)
(remhash key dbus-registered-objects-table))))))
dbus-registered-objects-table)
- (dbus-call-method
- bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
- "ReleaseName" service))
+ (let ((reply (dbus-call-method
+ bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+ "ReleaseName" service)))
+ (case reply
+ (1 :released)
+ (2 :non-existent)
+ (3 :not-owner)
+ (t (signal 'dbus-error (list "Could not unregister service" service))))))
(defun dbus-call-method-non-blocking-handler (&rest args)
"Handler for reply messages of asynchronous D-Bus message calls.
arrived. SERVICE is the object name for which the name owner has
been changed. OLD-OWNER is the previous owner of SERVICE, or the
empty string if SERVICE was not owned yet. NEW-OWNER is the new
-owner of SERVICE, or the empty string if SERVICE looses any name owner.
+owner of SERVICE, or the empty string if SERVICE loses any name owner.
usage: (dbus-name-owner-changed-handler service old-owner new-owner)"
(save-match-data
;; Check whether SERVICE is a known name.
(when (not (string-match "^:" service))
(maphash
- '(lambda (key value)
- (dolist (elt value)
- ;; key has the structure (BUS INTERFACE MEMBER).
- ;; elt has the structure (UNAME SERVICE PATH HANDLER).
- (when (string-equal old-owner (car elt))
- ;; Remove old key, and add new entry with changed name.
- (dbus-unregister-object (list key (cdr elt)))
- ;; Maybe we could arrange the lists a little bit better
- ;; that we don't need to extract every single element?
- (dbus-register-signal
- ;; BUS SERVICE PATH
- (nth 0 key) (nth 1 elt) (nth 2 elt)
- ;; INTERFACE MEMBER HANDLER
- (nth 1 key) (nth 2 key) (nth 3 elt)))))
+ (lambda (key value)
+ (dolist (elt value)
+ ;; key has the structure (BUS INTERFACE MEMBER).
+ ;; elt has the structure (UNAME SERVICE PATH HANDLER).
+ (when (string-equal old-owner (car elt))
+ ;; Remove old key, and add new entry with changed name.
+ (dbus-unregister-object (list key (cdr elt)))
+ ;; Maybe we could arrange the lists a little bit better
+ ;; that we don't need to extract every single element?
+ (dbus-register-signal
+ ;; BUS SERVICE PATH
+ (nth 0 key) (nth 1 elt) (nth 2 elt)
+ ;; INTERFACE MEMBER HANDLER
+ (nth 1 key) (nth 2 key) (nth 3 elt)))))
(copy-hash-table dbus-registered-objects-table))))
;; The error is reported only in debug mode.
(when dbus-debug
\f
;;; D-Bus registered names.
-(defun dbus-list-activatable-names ()
+(defun dbus-list-activatable-names (&optional bus)
"Return the D-Bus service names which can be activated as list.
-The result is a list of strings, which is `nil' when there are no
-activatable service names at all."
+If BUS is left nil, `:system' is assumed. The result is a list
+of strings, which is `nil' when there are no activatable service
+names at all."
(dbus-ignore-errors
(dbus-call-method
- :system dbus-service-dbus
+ (or bus :system) dbus-service-dbus
dbus-path-dbus dbus-interface-dbus "ListActivatableNames")))
(defun dbus-list-names (bus)
(setq direction nil))
;; Collect the signatures.
(mapconcat
- '(lambda (x)
- (let ((arg (dbus-introspect-get-argument
- bus service path interface name x)))
- (if (or (not (stringp direction))
- (string-equal
- direction
- (dbus-introspect-get-attribute arg "direction")))
- (dbus-introspect-get-attribute arg "type")
- "")))
+ (lambda (x)
+ (let ((arg (dbus-introspect-get-argument
+ bus service path interface name x)))
+ (if (or (not (stringp direction))
+ (string-equal
+ direction
+ (dbus-introspect-get-attribute arg "direction")))
+ (dbus-introspect-get-attribute arg "type")
+ "")))
(dbus-introspect-get-argument-names bus service path interface name)
"")))
(add-to-list 'result (cons (car dict) (caadr dict)) 'append)))))
(defun dbus-register-property
- (bus service path interface property access value &optional emits-signal)
+ (bus service path interface property access value
+ &optional emits-signal dont-register-service)
"Register property PROPERTY on the D-Bus BUS.
BUS is either a Lisp symbol, `:system' or `:session', or a string
denoting the bus address.
SERVICE is the D-Bus service name of the D-Bus. It must be a
-known name.
-
-PATH is the D-Bus object path SERVICE is registered. INTERFACE
-is the name of the interface used at PATH, PROPERTY is the name
-of the property of INTERFACE. ACCESS indicates, whether the
-property can be changed by other services via D-Bus. It must be
-either the symbol `:read' or `:readwrite'. VALUE is the initial
-value of the property, it can be of any valid type (see
+known name (See discussion of DONT-REGISTER-SERVICE below).
+
+PATH is the D-Bus object path SERVICE is registered (See
+discussion of DONT-REGISTER-SERVICE below). INTERFACE is the
+name of the interface used at PATH, PROPERTY is the name of the
+property of INTERFACE. ACCESS indicates, whether the property
+can be changed by other services via D-Bus. It must be either
+the symbol `:read' or `:readwrite'. VALUE is the initial value
+of the property, it can be of any valid type (see
`dbus-call-method' for details).
If PROPERTY already exists on PATH, it will be overwritten. For
PATH, including a default handler for the \"Get\", \"GetAll\" and
\"Set\" methods of this interface. When EMITS-SIGNAL is non-nil,
the signal \"PropertiesChanged\" is sent when the property is
-changed by `dbus-set-property'."
+changed by `dbus-set-property'.
+
+When DONT-REGISTER-SERVICE is non-nil, the known name SERVICE is
+not registered. This means that other D-Bus clients have no way
+of noticing the newly registered property. When interfaces are
+constructed incrementally by adding single methods or properties
+at a time, DONT-REGISTER-SERVICE can be used to prevent other
+clients from discovering the still incomplete interface."
(unless (member access '(:read :readwrite))
(signal 'dbus-error (list "Access type invalid" access)))
;; Register SERVICE.
- (unless (member service (dbus-list-names bus))
+ (unless (or dont-register-service
+ (member service (dbus-list-names bus)))
(dbus-call-method
bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
"RequestName" service 0))
- ;; Add the handler. We use `dbus-service-emacs' as service name, in
- ;; order to let unregister SERVICE despite of this default handler.
+ ;; Add handlers for the three property-related methods.
(dbus-register-method
- bus service path dbus-interface-properties "Get" 'dbus-property-handler)
+ bus service path dbus-interface-properties "Get"
+ 'dbus-property-handler 'dont-register)
(dbus-register-method
- bus service path dbus-interface-properties "GetAll" 'dbus-property-handler)
+ bus service path dbus-interface-properties "GetAll"
+ 'dbus-property-handler 'dont-register)
(dbus-register-method
- bus service path dbus-interface-properties "Set" 'dbus-property-handler)
+ bus service path dbus-interface-properties "Set"
+ 'dbus-property-handler 'dont-register)
+
+ ;; Register the name SERVICE with BUS.
+ (unless dont-register-service
+ (dbus-register-service bus service))
;; Send the PropertiesChanged signal.
(when emits-signal
(provide 'dbus)
-;; arch-tag: a47caf84-9162-4811-90cc-5d388e37b9bd
;;; dbus.el ends here