Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lisp / net / dbus.el
index 870bd2e..4321500 100644 (file)
@@ -1,6 +1,6 @@
 ;;; 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
 (defmacro dbus-ignore-errors (&rest body)
   "Execute BODY; signal D-Bus error when `dbus-debug' is non-nil.
 Otherwise, return result of last form in BODY, or all other errors."
+  (declare (indent 0) (debug t))
   `(condition-case err
        (progn ,@body)
      (dbus-error (when dbus-debug (signal (car err) (cdr err))))))
-
-(put 'dbus-ignore-errors 'lisp-indent-function 0)
-(put 'dbus-ignore-errors 'edebug-form-spec '(form body))
 (font-lock-add-keywords 'emacs-lisp-mode '("\\<dbus-ignore-errors\\>"))
 
 (defvar dbus-event-error-hooks nil
@@ -108,15 +106,12 @@ catched in `condition-case' by `dbus-error'.")
 \f
 ;;; Hash table of registered functions.
 
-;; We create it here.  So we have a simple test in dbusbind.c, whether
-;; the Lisp code has been loaded.
-(setq dbus-registered-objects-table (make-hash-table :test 'equal))
-
 (defvar dbus-return-values-table (make-hash-table :test 'equal)
   "Hash table for temporary storing arguments of reply messages.
-A key in this hash table is a list (BUS SERIAL).  BUS is either the
-symbol `:system' or the symbol `:session'.  SERIAL is the serial number
-of the reply message.  See `dbus-call-method-non-blocking-handler' and
+A key in this hash table is a list (BUS SERIAL).  BUS is either a
+Lisp symbol, `:system' or `:session', or a string denoting the
+bus address.  SERIAL is the serial number of the reply message.
+See `dbus-call-method-non-blocking-handler' and
 `dbus-call-method-non-blocking'.")
 
 (defun dbus-list-hash-table ()
@@ -187,8 +182,19 @@ association to the service from D-Bus."
 
 (defun dbus-unregister-service (bus service)
   "Unregister all objects related to SERVICE from D-Bus BUS.
-BUS must be either the symbol `:system' or the symbol `:session'.
-SERVICE must be a known service name."
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+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)
@@ -198,9 +204,14 @@ SERVICE must be a known service name."
               (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.
@@ -244,7 +255,7 @@ This handler is applied when a \"NameOwnerChanged\" signal has
 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
@@ -353,15 +364,15 @@ EVENT is a list which starts with symbol `dbus-event':
   (dbus-event BUS TYPE SERIAL SERVICE PATH INTERFACE MEMBER HANDLER &rest ARGS)
 
 BUS identifies the D-Bus the message is coming from.  It is
-either the symbol `:system' or the symbol `:session'.  TYPE is
-the D-Bus message type which has caused the event, SERIAL is the
-serial number of the received D-Bus message.  SERVICE and PATH
-are the unique name and the object path of the D-Bus object
-emitting the message.  INTERFACE and MEMBER denote the message
-which has been sent.  HANDLER is the function which has been
-registered for this message.  ARGS are the arguments passed to
-HANDLER, when it is called during event handling in
-`dbus-handle-event'.
+either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.  TYPE is the D-Bus message type which
+has caused the event, SERIAL is the serial number of the received
+D-Bus message.  SERVICE and PATH are the unique name and the
+object path of the D-Bus object emitting the message.  INTERFACE
+and MEMBER denote the message which has been sent.  HANDLER is
+the function which has been registered for this message.  ARGS
+are the arguments passed to HANDLER, when it is called during
+event handling in `dbus-handle-event'.
 
 This function raises a `dbus-error' signal in case the event is
 not well formed."
@@ -369,7 +380,8 @@ not well formed."
   (unless (and (listp event)
               (eq (car event) 'dbus-event)
               ;; Bus symbol.
-              (symbolp (nth 1 event))
+              (or (symbolp (nth 1 event))
+                  (stringp (nth 1 event)))
               ;; Type.
               (and (natnump (nth 2 event))
                    (< dbus-message-type-invalid (nth 2 event)))
@@ -434,9 +446,10 @@ If the HANDLER returns a `dbus-error', it is propagated as return message."
 
 (defun dbus-event-bus-name (event)
   "Return the bus name the event is coming from.
-The result is either the symbol `:system' or the symbol `:session'.
-EVENT is a D-Bus event, see `dbus-check-event'.  This function
-raises a `dbus-error' signal in case the event is not well formed."
+The result is either a Lisp symbol, `:system' or `:session', or a
+string denoting the bus address.  EVENT is a D-Bus event, see
+`dbus-check-event'.  This function raises a `dbus-error' signal
+in case the event is not well formed."
   (dbus-check-event event)
   (nth 1 event))
 
@@ -566,10 +579,11 @@ apply
   "Return all interfaces and sub-nodes of SERVICE,
 registered at object path PATH at bus BUS.
 
-BUS must be either the symbol `:system' or the symbol `:session'.
-SERVICE must be a known service name, and PATH must be a valid
-object path.  The last two parameters are strings.  The result,
-the introspection data, is a string in XML format."
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.  SERVICE must be a known service name,
+and PATH must be a valid object path.  The last two parameters
+are strings.  The result, the introspection data, is a string in
+XML format."
   ;; We don't want to raise errors.  `dbus-call-method-non-blocking'
   ;; is used, because the handler can be registered in our Emacs
   ;; instance; caller an callee would block each other.
@@ -870,20 +884,23 @@ name of the property, and its value.  If there are no properties,
        (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 the symbol `:system' or the symbol `:session'.
+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
@@ -895,24 +912,38 @@ The interface \"org.freedesktop.DBus.Properties\" is added to
 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
@@ -1011,5 +1042,4 @@ It will be registered for all objects created by `dbus-register-object'."
 
 (provide 'dbus)
 
-;; arch-tag: a47caf84-9162-4811-90cc-5d388e37b9bd
 ;;; dbus.el ends here