comparison lisp/net/dbus.el @ 109127:6b757d9cacac

* net/dbus.el: Implement signal "PropertiesChanged" (from D-Bus 1.3.1). (dbus-register-property): New optional argument EMITS-SIGNAL. (dbus-property-handler): Send signal "PropertiesChanged" if requested.
author Michael Albinus <albinus@detlef>
date Sun, 04 Jul 2010 11:52:57 +0200
parents 319b48a599cf
children 0f3ed79830e9
comparison
equal deleted inserted replaced
109126:aec1143e8d85 109127:6b757d9cacac
867 "GetAll" :timeout 500 interface) 867 "GetAll" :timeout 500 interface)
868 result) 868 result)
869 (add-to-list 'result (cons (car dict) (caadr dict)) 'append))))) 869 (add-to-list 'result (cons (car dict) (caadr dict)) 'append)))))
870 870
871 (defun dbus-register-property 871 (defun dbus-register-property
872 (bus service path interface property access value) 872 (bus service path interface property access value &optional emits-signal)
873 "Register property PROPERTY on the D-Bus BUS. 873 "Register property PROPERTY on the D-Bus BUS.
874 874
875 BUS is either the symbol `:system' or the symbol `:session'. 875 BUS is either the symbol `:system' or the symbol `:session'.
876 876
877 SERVICE is the D-Bus service name of the D-Bus. It must be a 877 SERVICE is the D-Bus service name of the D-Bus. It must be a
890 change their values. Properties with access type `:readwrite' 890 change their values. Properties with access type `:readwrite'
891 can be changed by `dbus-set-property'. 891 can be changed by `dbus-set-property'.
892 892
893 The interface \"org.freedesktop.DBus.Properties\" is added to 893 The interface \"org.freedesktop.DBus.Properties\" is added to
894 PATH, including a default handler for the \"Get\", \"GetAll\" and 894 PATH, including a default handler for the \"Get\", \"GetAll\" and
895 \"Set\" methods of this interface." 895 \"Set\" methods of this interface. When EMITS-SIGNAL is non-nil,
896 the signal \"PropertiesChanged\" is sent when the property is
897 changed by `dbus-set-property'."
896 (unless (member access '(:read :readwrite)) 898 (unless (member access '(:read :readwrite))
897 (signal 'dbus-error (list "Access type invalid" access))) 899 (signal 'dbus-error (list "Access type invalid" access)))
898 900
899 ;; Register SERVICE. 901 ;; Register SERVICE.
900 (unless (member service (dbus-list-names bus)) 902 (unless (member service (dbus-list-names bus))
909 (dbus-register-method 911 (dbus-register-method
910 bus service path dbus-interface-properties "GetAll" 'dbus-property-handler) 912 bus service path dbus-interface-properties "GetAll" 'dbus-property-handler)
911 (dbus-register-method 913 (dbus-register-method
912 bus service path dbus-interface-properties "Set" 'dbus-property-handler) 914 bus service path dbus-interface-properties "Set" 'dbus-property-handler)
913 915
916 ;; Send the PropertiesChanged signal.
917 (when emits-signal
918 (dbus-send-signal
919 bus service path dbus-interface-properties "PropertiesChanged"
920 (list (list :dict-entry property (list :variant value)))
921 '(:array)))
922
914 ;; Create a hash table entry. We use nil for the unique name, 923 ;; Create a hash table entry. We use nil for the unique name,
915 ;; because the property might be accessed from anybody. 924 ;; because the property might be accessed from anybody.
916 (let ((key (list bus interface property)) 925 (let ((key (list bus interface property))
917 (val (list (list nil service path (cons access value))))) 926 (val
927 (list
928 (list
929 nil service path
930 (cons
931 (if emits-signal (list access :emits-signal) (list access))
932 value)))))
918 (puthash key val dbus-registered-objects-table) 933 (puthash key val dbus-registered-objects-table)
919 934
920 ;; Return the object. 935 ;; Return the object.
921 (list key (list service path)))) 936 (list key (list service path))))
922 937
923 (defun dbus-property-handler (&rest args) 938 (defun dbus-property-handler (&rest args)
924 "Default handler for the \"org.freedesktop.DBus.Properties\" interface. 939 "Default handler for the \"org.freedesktop.DBus.Properties\" interface.
925 It will be registered for all objects created by `dbus-register-object'." 940 It will be registered for all objects created by `dbus-register-object'."
926 (let ((bus (dbus-event-bus-name last-input-event)) 941 (let ((bus (dbus-event-bus-name last-input-event))
942 (service (dbus-event-service-name last-input-event))
927 (path (dbus-event-path-name last-input-event)) 943 (path (dbus-event-path-name last-input-event))
928 (method (dbus-event-member-name last-input-event)) 944 (method (dbus-event-member-name last-input-event))
929 (interface (car args)) 945 (interface (car args))
930 (property (cadr args))) 946 (property (cadr args)))
931 (cond 947 (cond
932 ;; "Get" returns a variant. 948 ;; "Get" returns a variant.
933 ((string-equal method "Get") 949 ((string-equal method "Get")
934 (let ((val (gethash (list bus interface property) 950 (let ((entry (gethash (list bus interface property)
935 dbus-registered-objects-table))) 951 dbus-registered-objects-table)))
936 (when (string-equal path (nth 2 (car val))) 952 (when (string-equal path (nth 2 (car entry)))
937 (list (list :variant (cdar (last (car val)))))))) 953 (list (list :variant (cdar (last (car entry))))))))
938 954
939 ;; "Set" expects a variant. 955 ;; "Set" expects a variant.
940 ((string-equal method "Set") 956 ((string-equal method "Set")
941 (let ((val (gethash (list bus interface property) 957 (let* ((value (caar (cddr args)))
942 dbus-registered-objects-table))) 958 (entry (gethash (list bus interface property)
943 (unless (consp (car (last (car val)))) 959 dbus-registered-objects-table))
960 ;; The value of the hash table is a list; in case of
961 ;; properties it contains just one element (UNAME SERVICE
962 ;; PATH OBJECT). OBJECT is a cons cell of a list, which
963 ;; contains a list of annotations (like :read,
964 ;; :read-write, :emits-signal), and the value of the
965 ;; property.
966 (object (car (last (car entry)))))
967 (unless (consp object)
944 (signal 'dbus-error 968 (signal 'dbus-error
945 (list "Property not registered at path" property path))) 969 (list "Property not registered at path" property path)))
946 (unless (equal (caar (last (car val))) :readwrite) 970 (unless (member :readwrite (car object))
947 (signal 'dbus-error 971 (signal 'dbus-error
948 (list "Property not writable at path" property path))) 972 (list "Property not writable at path" property path)))
949 (puthash (list bus interface property) 973 (puthash (list bus interface property)
950 (list (append (butlast (car val)) 974 (list (append (butlast (car entry))
951 (list (cons :readwrite (caar (cddr args)))))) 975 (list (cons (car object) value))))
952 dbus-registered-objects-table) 976 dbus-registered-objects-table)
977 ;; Send the "PropertiesChanged" signal.
978 (when (member :emits-signal (car object))
979 (dbus-send-signal
980 bus service path dbus-interface-properties "PropertiesChanged"
981 (list (list :dict-entry property (list :variant value)))
982 '(:array)))
983 ;; Return empty reply.
953 :ignore)) 984 :ignore))
954 985
955 ;; "GetAll" returns "a{sv}". 986 ;; "GetAll" returns "a{sv}".
956 ((string-equal method "GetAll") 987 ((string-equal method "GetAll")
957 (let (result) 988 (let (result)