= lsp-dbus.a(8) :doctype: manpage :revdate: {sys:date "+%Y-%m-%d %H:%M:%S"} :BC: *:* == NAME lsp-dbus.a - Dbus API for newlisp. == SYNOPSIS .With packnl packnl _main.lsp_ *-A lsp-misc.a* *-A lsp-dbus.a* .With incore.lsp (load "incore.lsp") + (archive "lsp-misc.a") + (archive "lsp-utils.a") + (load "lsp-dbus.lsp") == DESCRIPTION *lsp-dbus.a* implements a newlisp API for Dbus. The module includes a context _DbusConnection_ that implements the connection/authorization level and a context _Dbus_ that implements the "object modelling"/messaging level. The source software is divided into a couple of different source files that are packed together into an _ar_ archive. Note that *lsp-dbus.a* depends on _FOOP_ and _prog1_ from *lsp-misc.a*. === lsp-dbus API (*load* "lsp-dbus.lsp"):: The main file, *lsp-dbus.lsp*, includes connection setup (see *:initialize* below) and client registration (i.e. issuing the dbus "Hello():s" message as part of its loading. Currently it connects on the system bus (only). It also installs the funcion _main-loop_ as _prompt-event_ function for processing any unsolicited messages from dbus (so called "signals"). ==== The Dbus Context (*Dbus* _PATH_ [_DESTINATION_]):: The _Dbus_ context is used for identifying remote "objects" with the given _PATH_ and _DESTINATION_ (aka bus name). The resulting _FOOP_ object provides a proxying channel for invoking methods targeting the given path on the given bus-name application. When omitted, the _DESTINATION_ string is obtained from the _PATH_ string following the convention of chopping the initial "/" and replacing remaining "/" with ".". + ==== Note that a term like _(Dbus "/org/freedesktop/DBus")_ defines an identifer for, or pointer to, a remote "dbus object", and it is here referred to as _PROXY_. The _PATH_ part serves as the object identifier for dbus while the _DESTINATION_ part is an identfier for the application that we expect holds the actual "dbus object" for the given _PATH_. This particular term identifies object path "/org/freedesktop/DBus" held by the application named "org.freedesktop.DBus", which belongs to the dbus framewok. There is however no central arbitration for paths in dbus. It all relies on application developers documenting which paths their applications service and access, and then client applications rely on using the destination tags for directing their messages to the intended applications. ==== (*:new-path* _PROXY_ _PATH_):: The _:new-path_ method clones the FOOP object to dentify the given _PATH_ for the same destination. (*:invoke* _PROXY_ _METHOD_ _ARGUMENTS_ _FLAGS_):: The _:invoke_ method performs a Dbus _METHOD_CALL_ handshake for the gven _PROXY_ using the given _METHOD_, _ARGUMENTS_ and message _FLAGS_. The function sends a dbus message and then polls for debus messages until the reply message has arrived. any and all other messages recevied meanwhile are added to the _pending_ list. + The _METHOD_ is given as a string composed as path, interface, name and signature + ==== _path:interface.name(signature)_ ==== + The _path:_ component including the colon is optional and taken from the _PROXY_ by default. The _interface._ component incuding the period is also optional as per dbus documentation: a method call without explicit interface results in that the method name is looked up across all interfaces of the destination path. + The _SIGNATURE_ is the dbus style signature as a character sequence, where y, b, n, q, i, u, x, t, d and h indicate the basic types BYTE, BOOLEAN, INT16, UINT16, INT32, UINT32, INT64, UINT64, DOUBLE and FD respectivly (both BOOLEAN and FD are also UINT32); a indicates "array"; s, o and g indicate strings of various restrictions; parentheses and curly braces wrap "struct" signatures, and v indicates a pair of a data item preceded by its signature. Refer to dbus documentation for further details. + The given _ARGUMENTS_ is a list structure that must correspond to the given signature. All number and string values are mapped naturally into the indicated signatures while arrays, struct and variant elements should occur as lists: an array is formed from the list of elements, as is a struct. A variant typed element must occur as the list of signature and data. See also the MARSHALLING section below. + The optional _FLAGS_ argument is given either a bit mask (number) or a list of the _Dbus_ context symbols _NO_REPLY_EXPECTED_, _NO_AUTO_START_ and _ALLOW_INTERACTIVE_AUTHORIZATION_. Each of these correspond to a bit position in the _FLAGS_ mask and they are combined with bit-OR. Refer to dbus documentation for further details. + .Some :invoke usage examples ---- (:invoke Dbus:ROOT "RequestName(su)" '("my.client" 0)) (:invoke Dbus:ROOT "GetNameOwner(s)" '("org.bluez" 0)) (setf BT (Dbus "/" "org.bluez")) (:invoke BT "GetManagedObjects()") (Dbus:process-pending) ---- + Note "org.bluez" here provides the "GetManagedObjects()" method of interface "org.freedesktop.ObjectManager" unambiguously on the root path, "/", rather than its bus name path "/org/bluez". + While this process is waiting for the _METHOD_CALL_ reply it may receive signal messsages from _dbus_. These will be added to the list of "pending callbacks" that is processed via the _process-all-pending_ function, either via an explicit call following the handshake or "automagically" as part of the _main-loop_ function that gets installed as as _prompt-event_ function. + .Return value: [caption=""] ==== The return value of *:invoke* is the METHOD_REPLY message reduced into an association list of the headers (with the _Dbus_ header symbols as keys) extended with the method return value as a list wrapped into a final association that is keyed by the empty string. In other words, the template for using *:invoke* may look like the following: ---- (if (:invoke ...) ($it -1 -1 -1)) ---- ==== (*Dbus:process-all-pending*):: The _process-all-pending_ function processes all pending signal messages by invoking their associated handler functions. (*prompt-event Dbus:main-loop*):: The _main-loop_ function is set up as _prompt-event_ function for a combined _net-select_ on both stdin and the dbus socket as well as to process all pending signal messages. Any input from dbus, which are signal messages, are added to the pending list, which also is processed one message at a time until empty. + Note that newlisp uses readline for input but that this is not activated in _main-loop_. Therefore line editing is not available immediately. However the operator may use ^D to leave the main-loop and enter the "normal" command line input state for a single line input (with line editing), or an initial newline for multi-line input that is "submitted" by means of two newlines. (*:handler* _OBJ_ _KEY_ _HANDLER_):: This function registers a handler callback for a key that is a string composed as "path:interface.member(signature)". The handler function takes a single argument, which is the list of unmarshalled actual call arguments. ==== The DbusConnection Context (*DbusConnection* _PATH):: The _DbusConnection_ context is a FOOP implementation intended for the dbus socket connection. Each _(DbusConnection PATH)_ is intended to be like a real object that contains state, namely the opened socket file descriptor, the connection name given to it by DBus on connection and and the messaging serial. (*:serial++* _OBJECT_):: This method increments the serial of the given object. (*:open-socket* _OBJECT_):: This method opens the path and assignes the socket file descriptor of the given object. Before that though, if the socket file descriptor is non-negative then that file descriptor is closed before opening the object's path. (*:read-message* _OBJECT_):: This method reads the next message by reading data from the socket successively while there's something to read within a millisecond. (*:handshake* _OBJECT_ _MESSAGE_ [_PATTERN_]):: This method performs a "raw" text-based handshake on the connection, which means to send the given message and then read and return the response message. If a _PATTERN_ is given, then the response must match the pattern (assigning the automatic variables $1 etc according to the pattern). The method returns nil if the given pattern is not matched. Note that this method is used only during connection setup and dbus communication uses its own marshalling subsequently. (*:initialize* _OBJECT_ [_USER_]):: This method performs the connection set up including the very first newline and the subsequent AUTH handshake. It ends with the connection in "BEGIN" mode and returns the received connection name. === MARSHALLING dbus documentation uses the terms "marshalling" and "unmarshalling" for the translations of data from/to program data to/from dbus message bytes. The data in newlisp mapped straight-forwardly with the special note that both "struct" and "array" are held as lists in newlisp. To that end, the data for the variant type signature must be wrapped into an extra list of the format _(signature value)_ with explcit dbus signature string. However, such wrapping does not take place upon unmarshalling. == SEE ALSO *newlisp*, *packnl*, *incore.lsp* == AUTHOR Ralph Ronnquist