Tcl DBus Interface

Artifact Content
Login

Artifact 3ad654f7e4bc6b0e67d7eac488e6d36d8db84329736012a62d480d9dc4e7b341:

Wiki page [Tcl DBus Interface] by schelte 2018-01-19 12:04:17.
D 2018-01-19T12:04:17.752
L Tcl\sDBus\sInterface
U schelte
W 23199
<h1>Tcl D-Bus Interface</h1>

<p>dbif - Application layer around the Tcl D-Bus library

<hr>

<h2>Synopsis</h2>

<p>
package require <b>Tcl 8.5</b><br>
package require <b>dbus 2.1</b><br>
package require <b>dbif 1.3</b><br>
<p>
<b>dbif</b> <b>connect</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-noqueue</b>? ?<b>-replace</b>? ?<b>-yield</b>? ?<i>name</i> ...?<br>
<b>dbif</b> <b>default</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>?<br>
<b>dbif</b> <b>delete</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? ?<b>-single</b>? <i>path</i><br>
<b>dbif</b> <b>error</b> <i>messageID</i> <i>errormessage</i> ?<i>errorname</i>?<br>
<b>dbif</b> <b>generate</b> <i>signalID</i> ?<i>arg</i> ...?<br>
<b>dbif</b> <b>get</b> <i>messageID</i> <i>name</i><br>
<b>dbif</b> <b>listen</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i> ?<i>arglist</i>? ?<i>interp</i>? <i>body</i><br>
<b>dbif</b> <b>method</b> ?<b>-attributes</b> <i>attributes</i>? ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i> ?<i>inputargs</i> ?<i>outputargs</i>?? ?<i>interp</i>? <i>body</i><br>
<b>dbif</b> <b>pave</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i><br>
<b>dbif</b> <b>property</b> ?<b>-access</b> <i>mode</i>? ?<b>-attributes</b> <i>attributes</i>? ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i>?:<i>signature</i>? <i>variable</i> ??<i>interp</i>? <i>body</i>?<br>
<b>dbif</b> <b>return</b> <i>messageID</i> <i>returnvalue</i><br>
<b>dbif</b> <b>signal</b> ?<b>-attributes</b> <i>attributes</i>? ?<b>-bus</b> <i>bustype</i>? ?<b>-id</b> <i>signalID</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i> ?<i>arglist</i> ??<i>interp</i>? <i>args</i> <i>body</i>??<br>

<hr>

<h2>Description</h2>

The <b>dbif</b> package provides a higher level wrapper around
the low-level D-Bus commands provided by the dbus package. The package also
provides an implementation of a number of standard D-Bus interfaces.
See <b>STANDARD INTERFACES</b> for more information.

<p>

Access to all functions of the <b>dbif</b> package from within
a Tcl program is done using the <b>dbif</b> command. The command
supports several subcommands that determine what action is carried out.
<dl>
<dt><b>dbif</b> <b>connect</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-noqueue</b>? ?<b>-replace</b>? ?<b>-yield</b>? ?<i>name</i> ...?
<dd>Connect to a message bus and optionally request the D-Bus server to assign
one or more names to the current application.

<p>

The <b>-yield</b> option specifies that the application will release the
requested name when some other application requests the same name and has
indicated that it wants to take over ownership of the name. The application
will be informed by a <em>NameLost</em> signal when it loses ownership of the
name.

<p>

The <b>-replace</b> option indicates that the application wants to take
over the ownership of the name from the application that is currently the
primary owner, if any. This request will only be honoured if the current
owner has indicated that it will release the name on request. See also the
<b>-yield</b> option.

<p>

If the requested name is currently in use and the -replace option has not
been specified, or the <b>-replace</b> option was specified but the
current owner is unwilling to give up its ownership, the name request will
normally be queued. Then when the name is released by the current owner it
is assigned to the next requester in the queue and a signal is sent to
inform that requester that it is now the primary owner of the name. The
<b>-noqueue</b> option may be specified to indicate that the name request
should not be queued.

<p>

The command returns a list of names that have successfully been acquired.
If the dbus connection handle is needed, it can be obtained from the -bus
return option.

<p>

The following code can be used to allow a new instance of a program to 
replace the current one. This can be useful during program development:

<verbatim>
dbif connect -yield -replace $dbusname
dbif listen -interface [dbus info service] \
  [dbus info path] NameLost name {if {$name eq $::dbusname} exit}
</verbatim>
<dt><b>dbif</b> <b>default</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>?
<dd>Generally an application will perform several <b>dbif</b> commands
related to the same message bus and interface. To avoid having to pass the
same values for the <b>-bus</b> and <b>-interface</b> options with all
those commands, their defaults can be setup with the <b>dbif</b>
<b>default</b> subcommand.

<p>

An interface name must consist of at least two elements separated by
a period ('.') character. Each element may only contain the characters
&quot;&#91;A-Z&#93;&#91;a-z&#93;&#91;0-9&#93;_&quot; and must not begin with a digit.

<p>

The initial value for <b>-bus</b> is session. The initial value for
<b>-interface</b> is taken from the first name requested for the
application in a <b>dbif</b> <b>connect</b> command. If no
name was ever requested with the connect subcommand, it defaults to
&quot;com.tclcode.default&quot;.
<dt><b>dbif</b> <b>delete</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? ?<b>-single</b>? <i>path</i>
<dd>While there currently is no way to remove individual signals, methods, or
properties from the published interface, this subcommand allows the removal
of a complete node. Unless the <b>-single</b> option is specified, the
command will also recursively delete nodes on all underlying object paths.
<dt><b>dbif</b> <b>error</b> <i>messageID</i> <i>errormessage</i> ?<i>errorname</i>?
<dd>Send a D-Bus error message in response to a D-Bus method call. If the
<i>errorname</i> argument is not specified, it defaults to
&quot;org.freedesktop.DBus.Error.Failed&quot;.
<dt><b>dbif</b> <b>generate</b> <i>signalID</i> ?<i>arg</i> ...?
<dd>Generate a signal as defined by a previous <b>dbif</b> 
<b>signal</b> command. If a body was specified with the signal definition,
the provided arguments must match the args definition for the body. Otherwise
they must match the arglist specified during the definition of the signal.
<dt><b>dbif</b> <b>get</b> <i>messageID</i> <i>name</i>
<dd>Access additional information about a D-Bus message. Recognized names are
<i>bus</i>, <i>member</i>, <i>interface</i>, <i>path</i>, <i>sender</i>,
<i>destination</i>, <i>messagetype</i>, <i>signature</i>, <i>serial</i>,
<i>replyserial</i>, <i>noreply</i>, <i>autostart</i>, and <i>errorname</i>.
<dt><b>dbif</b> <b>listen</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i> ?<i>arglist</i>? ?<i>interp</i>? <i>body</i>
<dd>Start listening for the specified signal and execute <i>body</i> when such a
signal appears on the D-Bus.

<p>

The code in <i>body</i> will be executed in the namespace the
<b>dbif</b> <b>listen</b> command was issued from.

The <i>arglist</i> argument follows the special rules for dbif
argument lists. See <b>ARGUMENT LISTS</b> below for more information.
<dt><b>dbif</b> <b>method</b> ?<b>-attributes</b> <i>attributes</i>? ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i> ?<i>inputargs</i> ?<i>outputargs</i>?? ?<i>interp</i>? <i>body</i>
<dd>Define a method that may be accessed through the D-Bus and execute <i>body</i>
when the method is invoked. 
In addition to valid dbus paths, an empty string may be specified for the
<i>path</i> argument. This makes the method available on all paths.
The <i>inputargs</i> argument specifies which arguments must be provided by
the caller. The <i>outputargs</i> argument indicates the type of result the
method returns.

<p>

Attributes may be specified via the <b>-attributes</b> option to provide
hints to users of your API.
See <b>ATTRIBUTES</b> below for more information.

<p>

The return value resulting from executing the body will normally be returned
to the caller in a D-Bus return message. If an uncaught error occurs or the
result of body doesn't match <i>outputargs</i>, an error message will be
returned to the caller instead.

<p>

The body code recognizes an additional <b>-async</b> option for the Tcl
<b>return</b> command. When that option is specified with a true boolean
value (<b class="const">true</b>, <b class="const">yes</b>, <b class="const">1</b>), the return value from the body
will not automatically be returned to the caller. A response message should
then be generated using the <b>dbif</b> <b>return</b> or
<b>dbif</b> <b>error</b> subcommands.

<p>

An additional variable <b>msgid</b> will be passed to the method body. This
variable contains a messageID that may be used in combination with the
<b>get</b>, <b>return</b>, or <b>error</b> subcommands. The messageID
remains valid for a period of time (default 25 seconds), or until a response
has been returned to the caller, whichever happens first.

<p>

The code in <i>body</i> will be executed in the namespace the
<b>dbif</b> <b>method</b> command was issued from.

The <i>inputargs</i> and <i>outputargs</i> arguments follow the special rules
for dbif argument lists.
See <b>ARGUMENT LISTS</b> below for more information.
<dt><b>dbif</b> <b>pave</b> ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i>
<dd>Create a path. Normally a path is automatically created when a property,
method, or signal is defined on that path. This command is intended for paths
that only have universal methods and/or signals (i.e. methods and/or signals
that are defined with an empty string as their path).
<dt><b>dbif</b> <b>property</b> ?<b>-access</b> <i>mode</i>? ?<b>-attributes</b> <i>attributes</i>? ?<b>-bus</b> <i>bustype</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i>?:<i>signature</i>? <i>variable</i> ??<i>interp</i>? <i>body</i>?
<dd>Define a property that may be accessed through the D-Bus using methods defined 
by the org.freedesktop.DBus.Properties standard interface. The <i>variable</i>
argument defines the global variable holding the value of the property.

The <i>signature</i> of a property must be a single complete type.
<p>

The <b>-access</b> option specifies whether the property can be viewed
and/or modified through the D-Bus. Valid access modes are <b class="const">read</b>,
<b class="const">write</b>, and <b class="const">readwrite</b>. If no access mode is specified, it
defaults to readwrite.

<p>

Attributes may be specified via the <b>-attributes</b> option to provide
hints to users of your API.
See <b>ATTRIBUTES</b> below for more information.

<p>

The code in the optional <i>body</i> argument will be executed when the
property is modified through the D-Bus. During the execution of <i>body</i>
the global variable will still have its original value, if any. The new
value for the property is passed to the script as an argument with the same
name as the property. If execution of <i>body</i> results in an error, the
global variable will not be modified. This allows restrictions to be imposed
on the value for the property.

<p>

The code in <i>body</i> will be executed in the namespace the
<b>dbif</b> <b>property</b> command was issued from or, if a slave
interpreter was specified, in the current namespace of that slave interpreter
at definition time.

<p>

Generating the property value only when needed can be implemented by putting
a read trace on the global variable. Example:

<verbatim>
dbif property -attributes {Property.EmitsChangedSignal false} / clock sec
trace add variable sec read {apply {args {set ::sec [clock seconds]}}}
</verbatim>

In this example the Property.EmitsChangedSignal attribute is used to
prevent the <em>PropertiesChanged</em> signal being generated, which would
involve a second read of the variable.
<dt><b>dbif</b> <b>return</b> <i>messageID</i> <i>returnvalue</i>
<dd>Send a D-Bus return message in response to a D-Bus method call. The provided
<i>returnvalue</i> must match the signature specified earlier in the
<b>dbif</b> <b>method</b> command for the method.
<dt><b>dbif</b> <b>signal</b> ?<b>-attributes</b> <i>attributes</i>? ?<b>-bus</b> <i>bustype</i>? ?<b>-id</b> <i>signalID</i>? ?<b>-interface</b> <i>interface</i>? <i>path</i> <i>name</i> ?<i>arglist</i> ??<i>interp</i>? <i>args</i> <i>body</i>??
<dd>Define a signal that the application may emit using the <b>dbif</b>
<b>generate</b> subcommand. Signals are referred to by their SignalID.
If <b>-id</b> is specified, it is used as the SignalID. Otherwise a new
unique identifier is generated. Specifying an existing SignalID replaces
the previously defined signal.

<p>

Attributes may be specified via the <b>-attributes</b> option to provide
hints to users of your API.
See <b>ATTRIBUTES</b> below for more information.

<p>

The command returns the SignalID of the newly created signal.

<p>

If the optional <i>args</i> and <i>body</i> arguments are specified, body
will be executed when the signal is transmitted on the D-Bus as a result
of the <b>dbif</b> <b>generate</b> subcommand. It is the
responsibility of the body code to produce a return value that matches
the specified arglist.

<p>

The code in <i>body</i> will be executed in the namespace the
<b>dbif</b> <b>signal</b> command was issued from.

If any uncaught error happens during the execution of the body code, the
<b>dbif</b> <b>generate</b> command will also throw an error with
the same error message. 

When the body code comes to the conclusion that the signal doesn't need to
be sent after all, it may abort the operation by returning using
&#91;return -code return&#93;.

The <i>arglist</i> argument follows the special rules for dbif
argument lists. See <b>ARGUMENT LISTS</b> below for more information.

<p>

In addition to valid dbus paths, an empty string may be specified for the
<i>path</i> argument. This makes the signal available on all paths. In this
case a body must be provided and the body code must provide a path in the
<b>-path</b> option to the <b>return</b> command.
For example: The following helper proc could be used to allow providing a
path to the <b>dbif</b> <b>generate</b> command in front of the
signal arguments:

<verbatim>
proc stdsignal {path args} {
    # Single argument signal bodies are not expected to produce a list
    if {[llength $args] == 1} {set args [lindex $args 0]}
    return -path $path $args
}
</verbatim>
</dl>

<h2>BUS TYPES</h2>

The <b>-bus</b> option of the various subcommands takes a <i>bustype</i>
value that can take several forms:
<ul>

<li>One of the well-known bus names: 'session', 'system', or 'startup'.
</li>
<li>A bus address, consisting of a transport name followed by a colon,
and then an optional, comma-separated list of keys and values in the form
key=value.
</li>
<li>A handle as returned by the <b>dbus</b> <b>connect</b> subcommand.
</li>
</ul>

<h2>VALID NAMES</h2>

The dbif package enforces some limitations on names used with the
<b>dbif</b> subcommands. All names must only use the characters
&quot;&#91;A-Z&#93;&#91;a-z&#93;&#91;0-9&#93;_&quot;. This limitation applies to method
names, property names, signal names, and argument names. Out of this group,
only argument names may begin with a digit.

<p>

Interface names and error names must consist of at least two elements
separated by a period ('.') character. Each element must only contain the
characters &quot;&#91;A-Z&#93;&#91;a-z&#93;&#91;0-9&#93;_&quot; and must not begin with a
digit.

<p>

D-Bus names for applications must follow the same rules as interface names,
except that also dash ('-') characters are allowed. Unique D-Bus names begin
with a colon (':'). The elements of unique D-Bus names are allowed to begin
with a digit.

<p>

Paths must start with a slash ('/') and must consist of elements separated
by slash characters. Each element must only contain the characters
&quot;&#91;A-Z&#93;&#91;a-z&#93;&#91;0-9&#93;_&quot;. Empty elements are not allowed.

<h2>ARGUMENT LISTS</h2>

Due to the fact that the D-Bus specification works with typed arguments, a
slightly modified method for specifying argument lists has been adopted for
the dbif package. The normal Tcl argument list as used with the
<b>proc</b> and <b>apply</b> commands may still be used. In that case all
arguments will be of the string type. To specify a different type, the
variable name must be followed by a colon and the D-Bus signature
specification for that argument. Example: to define the count argument as
a 32-bit integer, it should be specified as count:i.

<p>

The following argument types are available:
<dl>
<dt>s
<dd>A UTF-8 encoded, nul-terminated Unicode string.
<dt>b
<dd>A boolean, FALSE (0), or TRUE (1).
<dt>y
<dd>A byte (8-bit unsigned integer).
<dt>n
<dd>A 16-bit signed integer.
<dt>q
<dd>A 16-bit unsigned integer.
<dt>i
<dd>A 32-bit signed integer.
<dt>u
<dd>A 32-bit unsigned integer.
<dt>x
<dd>A 64-bit signed integer.
<dt>t
<dd>A 64-bit unsigned integer.
<dt>d
<dd>An 8-byte double in IEEE 754 format.
<dt>g
<dd>A type signature.
<dt>o
<dd>An object path.
<dt>a#
<dd>A D-Bus array type, which is similar to a Tcl list. The # specifies
the type of the array elements. This can be any type, including another
array, a struct or a dict entry.
<dt>v
<dd>A D-Bus variant type. Specifying this type will cause the code to
automatically determine the type of the provided value (by looking at the
internal representation).
<dt>(...)
<dd>A struct. The string inside the parentheses defines the types of
the arguments within the struct, which may consist of a combination of any
of the existing types.
<dt>{##}
<dd>A dict entry. Dict entries may only occur as array elements. The
first # specifies the type of the dict key. This must be a basic type
(one of 'sbynqiuxtdgo'). The second # specifies the type of the dict value.
This can again be any existing type.
</dl>

<p>

Argument lists may contain optional arguments. The use of optional arguments
will result in multiple prototypes being reported for the object when
introspected. The special meaning of the <b class="const">args</b> argument does not
translate well in the D-Bus concept. For that reason using <i>args</i> as the
last argument of an argument list should be avoided.

<h2>STANDARD INTERFACES</h2>

A number of standard interfaces have been defined in the D-Bus specification
that may be useful across various D-Bus applications.

<div id="subsection1" class="subsection"><h3>org.freedesktop.DBus.Peer</h3>
<dl>
<dt><em>org.freedesktop.DBus.Peer.Ping</em>
<dd>Returns an empty response.
<dt><em>org.freedesktop.DBus.Peer.GetMachineId</em>
<dd>Returns a hex-encoded UUID representing the identity of the machine the
application is running on.
</dl>

</div>
<div id="subsection2" class="subsection"><h3>org.freedesktop.DBus.Introspectable</h3>
<dl>
<dt><em>org.freedesktop.DBus.Introspectable.Introspect</em>
<dd>Returns an XML description of the D-Bus structure, including its interfaces
(with signals and methods), objects below it in the object path tree, and
its properties.
</dl>

</div>
<div id="subsection3" class="subsection"><h3>org.freedesktop.DBus.Properties</h3>
<dl>
<dt><em>org.freedesktop.DBus.Properties.Get</em>
<dd>Returns the value of the specified property. Only valid for properties with
read or readwrite access.
<dt><em>org.freedesktop.DBus.Properties.Set</em>
<dd>Changes the value of the specified property. Only valid for properties with
write or readwrite access.
<dt><em>org.freedesktop.DBus.Properties.GetAll</em>
<dd>Returns a dict of all properties with read or readwrite access.
<dt><em>org.freedesktop.DBus.Properties.PropertiesChanged</em>
<dd>This signal is emitted when one or more properties change.
The behavior for individual properties may be influenced by their
Property.EmitsChangedSignal attribute. See <b>ATTRIBUTES</b> below.

<p>

All applicable property changes are collected and reported via a single
<em>PropertiesChanged</em> signal per path/interface/bus combination when the
application enters the idle loop. The signal may also be generated on demand
via the command:
<dl>
<dl>
<dt><b>dbif</b> <b>generate</b> PropertiesChanged <i>path</i> ?<i>interface</i>? ?<i>bus</i>?
<dd>
</dl>
</dl>

<p>

The functionality for automatically populating this signal is implemented
via variable traces. If this feature is not needed, you can avoid the
associated overhead by redefining the PropertiesChanged signal id to your
own version.
To completely get rid of the signal, you can use the following code snippet
before defining any other part of your dbus interface:

<pre class="example">
package require dbif
dbif signal -id PropertiesChanged / foobar
dbif delete /
</pre>
</dl>

<h2>ATTRIBUTES</h2>

Attributes may be specified as a list of key/value pairs for methods,
signals, and properties. These attributes are reported via annotations in
the XML description obtained via an <em>Introspect</em> method call.
Annotations may be used to provide hints to users of your API.

<p>

Some well-know attributes are (default, if any, shown in italics):
<dl>
<dt>Description
<dd>Provide a short 1-line description of the method, signal or property.
<dt>Deprecated
<dd>Indicate that this method is deprecated (true, <em>false</em>).
<dt>Method.NoReply
<dd>This method may not produce a reply (true, <em>false</em>). For example if you
provide a method to exit your application.
<dt>Method.Error
<dd>This method may throw the indicated Exception in addition to the standard
ones.
<dt>Property.EmitsChangedSignal
<dd>Indicates whether a change to the property is reported via the 
<em>PropertiesChanged</em> signal (<em>true</em>, false, invalidates, const).
<p>
The value of this attribute, if specified, is also used internally to
influence the automatic generation of the <em>PropertiesChanged</em> signal.
<dl>
<dt>true
<dd>The signal is emitted with the value included. This is the default.
<dt>false
<dd>The signal is not automatically emitted on a change.
Parties interested in the property should obtain it every time they need it.
The application code may still emit a <em>PropertiesChanged</em> signal
whenever desired.
This may be used for properties that are implemented with a read trace on
the global variable.
<dt>invalidates
<dd>The signal is emitted but the value is not included in the signal. This may
be useful for properties that change much more frequently than they are
expected to be queried, and/or have large values.
<dt>const
<dd>The property never changes its value during the lifetime of the object it
belongs to, and hence the signal is never emitted for it.
</dl>
</dl>

</div>

Z e0badd492a2f8dc3b5ccbf6b857d2aed