emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: on-the-fly D-Bus proxy creation


From: joakim
Subject: Re: on-the-fly D-Bus proxy creation
Date: Tue, 24 Feb 2015 16:13:49 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux)

Daiki Ueno <address@hidden> writes:

> Hello,

Hello Daiki,

>
> There are several programming languages with support for D-Bus client
> implementation.  For example, with the following code:
> https://git.gnome.org/browse/gnome-shell/tree/js/ui/keyboard.js#n56
>
>   const CaribouDaemonIface = '<node> \
>   <interface name="org.gnome.Caribou.Daemon"> \
>   <method name="Run" /> \
>   <method name="Quit" /> \
>   </interface> \
>   </node>';

I use Jan Moringens dbus-proxy in my Inkmacs project, which is an Emacs
interface for Inkscape. 

It would be nice if there were comparable functionality directly in
Emacs or ELPA.

>
>   const CaribouDaemonProxy = 
> Gio.DBusProxy.makeProxyWrapper(CaribouDaemonIface);
>
> One can call a D-Bus method as a normal method of CaribouDaemonProxy.
> This is really handy and I wished to have similar feature in Elisp
> (though I haven't ever written any practical D-Bus code in Elisp).
>
> Thanks to cl-generic, I gave it a try.  With the attached code (far from
> complete though), a client can be implemented as:
>
>   (dbus-define-proxy search-provider "\
>   <node>
>     <interface name=\"org.gnome.Shell.SearchProvider2\">
>       <method name=\"GetInitialResultSet\">
>         <arg type=\"as\" name=\"terms\" direction=\"in\" />
>         <arg type=\"as\" name=\"results\" direction=\"out\" />
>       </method>
>       <!-- actually, there are more methods in this interface -->
>     </interface>
>   </node>")
>
> Then you can create a client and call D-Bus methods:
>
>   (setq search-provider
>         (search-provider-make :session
>                               "org.gnome.Weather.BackgroundService"
>                               "/org/gnome/Weather/BackgroundService"))
>   (search-provider-call-GetInitialResultSet search-provider '("tokyo"))
>
> If this seems to be useful, I can finish it off as a patch.
>
> Thanks,
> --
> Daiki Ueno
>
> (require 'dbus)
>
> (eval-when-compile (require 'cl-lib))
> (eval-when-compile (require 'xml))
>
> (cl-defstruct dbus-proxy
>   (bus :read-only t)
>   (service :read-only t)
>   (path :read-only t))
>
> (defmacro dbus-define-proxy (name xml)
>   (let* ((node (car (with-temp-buffer
>                     (insert xml)
>                     (xml-parse-region (point-min) (point-max)))))
>        (interface (car (xml-get-children node 'interface)))
>        (methods (xml-get-children interface 'method))
>        (interface-name (xml-get-attribute-or-nil interface 'name)))
>     `(progn
>        (cl-defstruct (,name (:include dbus-proxy)
>                           (:constructor nil)
>                           (:constructor ,(intern (format "%s-make" name))
>                            (bus service path)))
>        ;; FIXME: slots for cached properties?
>        )
>        ,@(mapcar
>         (lambda (method)
>           (let ((method-name (xml-get-attribute-or-nil method 'name))
>                 ;; FIXME: parse argument types?
>                 (in-args
>                  (mapcar #'intern
>                          (delq nil
>                                (mapcar
>                                 (lambda (arg)
>                                   (let ((direction (xml-get-attribute-or-nil
>                                                     arg 'direction)))
>                                     (if (or (null direction)
>                                             (not (equal direction "out")))
>                                         (xml-get-attribute-or-nil
>                                          arg 'name))))
>                                 (xml-get-children method 'arg))))))
>             ;; FIXME: un-CamelCasify method-name?
>             `(cl-defmethod ,(intern (format "%s-call-%s" name method-name))
>                            ((proxy ,name) ,@in-args &rest args)
>                (apply #'dbus-call-method
>                       (dbus-proxy-bus proxy)
>                       (dbus-proxy-service proxy)
>                       (dbus-proxy-path proxy)
>                       ,interface-name
>                       ,method-name
>                       ,@in-args
>                       args))))
>         methods)
>        ;; FIXME: asynchronous method calls, signals?
>        )))
>
> (dbus-define-proxy search-provider "\
> <node>
>   <interface name=\"org.gnome.Shell.SearchProvider2\">
>     <method name=\"GetInitialResultSet\">
>       <arg type=\"as\" name=\"terms\" direction=\"in\" />
>       <arg type=\"as\" name=\"results\" direction=\"out\" />
>     </method>
>     <!-- actually, there are more methods in this interface -->
>   </interface>
> </node>")
>
> ;; (setq search-provider
> ;;       (search-provider-make :session
> ;;                             "org.gnome.Weather.BackgroundService"
> ;;                             "/org/gnome/Weather/BackgroundService"))
> ;; (search-provider-call-GetInitialResultSet search-provider '("tokyo"))
>

-- 
Joakim Verona



reply via email to

[Prev in Thread] Current Thread [Next in Thread]