Tcl DBus Interface

Manual page
Login

Tcl D-Bus Interface

dbif - Application layer around the Tcl D-Bus library

SYNOPSIS

package require Tcl 8.5
package require dbus 3.0
package require dbif 2.2
dbif close ?-bus bustype?
dbif connect ?-bus bustype? ?-noqueue? ?-replace? ?-yield? ?name ...?
dbif default ?-bus bustype? ?-interface interface?
dbif delete ?-bus bustype? ?-interface interface? ?-single? path
dbif error messageID errormessage ?errorname?
dbif generate signalID ?arg ...?
dbif get messageID name
dbif listen ?-bus bustype? ?-interface interface? path name ?arglist? body
dbif method ?-attributes attributes? ?-bus bustype? ?-interface interface? path name ?inputargs ?outputargs?? body
dbif pave ?-bus bustype? ?-interface interface? path
dbif property ?-access mode? ?-attributes attributes? ?-bus bustype? ?-interface interface? path name?:signature? variable ?body?
dbif return messageID returnvalue
dbif signal ?-attributes attributes? ?-bus bustype? ?-id signalID? ?-interface interface? path name ?arglist ?args body??

DESCRIPTION

The dbif 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 STANDARD INTERFACES for more information.

Access to all functions of the dbif package from within a Tcl program is done using the dbif command. The command supports several subcommands that determine what action is carried out.

dbif close ?-bus bustype?

Close the dbus connection, cleaning up all associated signals, methods, and properties.

dbif connect ?-bus bustype? ?-noqueue? ?-replace? ?-yield? ?name ...?

Connect to a message bus and optionally request the D-Bus server to assign one or more names to the current application.

The -yield 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 NameLost signal when it loses ownership of the name.

The -replace 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 -yield option.

If the requested name is currently in use and the -replace option has not been specified, or the -replace 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 -noqueue option may be specified to indicate that the name request should not be queued.

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.

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:

    dbif connect -yield -replace $dbusname
    dbif listen -interface [dbus info service] \
      [dbus info path] NameLost name {if {$name eq $::dbusname} exit}
    
dbif default ?-bus bustype? ?-interface interface?

Generally an application will perform several dbif commands related to the same message bus and interface. To avoid having to pass the same values for the -bus and -interface options with all those commands, their defaults can be setup with the dbif default subcommand.

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

The initial value for -bus is session. The initial value for -interface is taken from the first name requested for the application in a dbif connect command. If no name was ever requested with the connect subcommand, it defaults to "com.tclcode.default".

dbif delete ?-bus bustype? ?-interface interface? ?-single? path

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 -single option is specified, the command will also recursively delete nodes on all underlying object paths.

dbif error messageID errormessage ?errorname?

Send a D-Bus error message in response to a D-Bus method call. If the errorname argument is not specified, it defaults to "org.freedesktop.DBus.Error.Failed".

dbif generate signalID ?arg ...?

Generate a signal as defined by a previous dbif signal 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.

dbif get messageID name

Access additional information about a D-Bus message. Recognized names are bus, member, interface, path, sender, destination, messagetype, signature, serial, replyserial, noreply, autostart, and errorname.

dbif listen ?-bus bustype? ?-interface interface? path name ?arglist? body

Start listening for the specified signal and execute body when such a signal appears on the D-Bus. If body is specified as an empty string, the signal handler with a matching argument signature is deleted.

The code in body will be executed in the namespace the dbif listen command was issued from. The arglist argument follows the special rules for dbif argument lists. See ARGUMENT LISTS below for more information.

dbif method ?-attributes attributes? ?-bus bustype? ?-interface interface? path name ?inputargs ?outputargs?? body

Define a method that may be accessed through the D-Bus and execute body when the method is invoked. In addition to valid dbus paths, an empty string may be specified for the path argument. This makes the method available on all paths. The inputargs argument specifies which arguments must be provided by the caller. The outputargs argument indicates the type of result the method returns.

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

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 outputargs, an error message will be returned to the caller instead.

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

An additional variable msgid will be passed to the method body. This variable contains a messageID that may be used in combination with the get, return, or error 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.

The code in body will be executed in the namespace the dbif method command was issued from. The inputargs and outputargs arguments follow the special rules for dbif argument lists. See ARGUMENT LISTS below for more information.

dbif pave ?-bus bustype? ?-interface interface? path

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).

dbif property ?-access mode? ?-attributes attributes? ?-bus bustype? ?-interface interface? path name?:signature? variable ?body?

Define a property that may be accessed through the D-Bus using methods defined by the org.freedesktop.DBus.Properties standard interface. The variable argument defines the global variable holding the value of the property. The signature of a property must be a single complete type.

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

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

The code in the optional body argument will be executed when the property is modified through the D-Bus. During the execution of body 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 body results in an error, the global variable will not be modified. This allows restrictions to be imposed on the value for the property.

The code in body will be executed in the namespace the dbif property command was issued from.

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

    dbif property -attributes {Property.EmitsChangedSignal false} / clock sec
    trace add variable sec read {apply {args {set ::sec [clock seconds]}}}
    
In this example the Property.EmitsChangedSignal attribute is used to prevent the PropertiesChanged signal being generated, which would involve a second read of the variable.
dbif return messageID returnvalue

Send a D-Bus return message in response to a D-Bus method call. The provided returnvalue must match the signature specified earlier in the dbif method command for the method.

dbif signal ?-attributes attributes? ?-bus bustype? ?-id signalID? ?-interface interface? path name ?arglist ?args body??

Define a signal that the application may emit using the dbif generate subcommand. Signals are referred to by their SignalID. If -id is specified, it is used as the SignalID. Otherwise a new unique identifier is generated. Specifying an existing SignalID replaces the previously defined signal.

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

The command returns the SignalID of the newly created signal.

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

The code in body will be executed in the namespace the dbif signal command was issued from. If any uncaught error happens during the execution of the body code, the dbif generate 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 [return -code return]. The arglist argument follows the special rules for dbif argument lists. See ARGUMENT LISTS below for more information.

In addition to valid dbus paths, an empty string may be specified for the path 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 -path option to the return command. For example: The following helper proc could be used to allow providing a path to the dbif generate command in front of the signal arguments:

    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
    }
    

BUS TYPES

The -bus option of the various subcommands takes a bustype value that can take several forms:

  • One of the well-known bus names: 'session', 'system', or 'startup'.
  • 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.
  • A handle as returned by the dbus connect subcommand.

VALID NAMES

The dbif package enforces some limitations on names used with the dbif subcommands. All names must only use the characters "[A-Z][a-z][0-9]_". 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.

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

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.

Paths must start with a slash ('/') and must consist of elements separated by slash characters. Each element must only contain the characters "[A-Z][a-z][0-9]_". Empty elements are not allowed.

ARGUMENT LISTS

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 proc and apply 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.

The following argument types are available:

s
A UTF-8 encoded, nul-terminated Unicode string.
b
A boolean, FALSE (0), or TRUE (1).
y
A byte (8-bit unsigned integer).
n
A 16-bit signed integer.
q
A 16-bit unsigned integer.
i
A 32-bit signed integer.
u
A 32-bit unsigned integer.
x
A 64-bit signed integer.
t
A 64-bit unsigned integer.
d
An 8-byte double in IEEE 754 format.
g
A type signature.
o
An object path.
a#
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.
v
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).
(...)
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.
{##}
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.

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 args argument does not translate well in the D-Bus concept. For that reason using args as the last argument of an argument list should be avoided.

STANDARD INTERFACES

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

ORG.FREEDESKTOP.DBUS.PEER

org.freedesktop.DBus.Peer.Ping
Returns an empty response.
org.freedesktop.DBus.Peer.GetMachineId
Returns a hex-encoded UUID representing the identity of the machine the application is running on.

ORG.FREEDESKTOP.DBUS.INTROSPECTABLE

org.freedesktop.DBus.Introspectable.Introspect
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.

ORG.FREEDESKTOP.DBUS.PROPERTIES

org.freedesktop.DBus.Properties.Get
Returns the value of the specified property. Only valid for properties with read or readwrite access.
org.freedesktop.DBus.Properties.Set
Changes the value of the specified property. Only valid for properties with write or readwrite access.
org.freedesktop.DBus.Properties.GetAll
Returns a dict of all properties with read or readwrite access.
org.freedesktop.DBus.Properties.PropertiesChanged
This signal is emitted when one or more properties change. The behavior for individual properties may be influenced by their Property.EmitsChangedSignal attribute. See ATTRIBUTES below.

All applicable property changes are collected and reported via a single PropertiesChanged signal per path/interface/bus combination when the application enters the idle loop. The signal may also be generated on demand via the command:

dbif generate PropertiesChanged path ?interface? ?bus?

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:

    package require dbif
    dbif signal -id PropertiesChanged / foobar
    dbif delete /
    

ATTRIBUTES

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 Introspect method call. Annotations may be used to provide hints to users of your API.

Some well-know attributes are (default, if any, shown in italics):

Description
Provide a short 1-line description of the method, signal or property.
Deprecated
Indicate that this method is deprecated (true, false).
Method.NoReply
This method may not produce a reply (true, false). For example if you provide a method to exit your application.
Method.Error
This method may throw the indicated Exception in addition to the standard ones.
Property.EmitsChangedSignal
Indicates whether a change to the property is reported via the PropertiesChanged signal (true, false, invalidates, const).

The value of this attribute, if specified, is also used internally to influence the automatic generation of the PropertiesChanged signal.

true
The signal is emitted with the value included. This is the default.
false
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 PropertiesChanged signal whenever desired. This may be used for properties that are implemented with a read trace on the global variable.
invalidates
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.
const
The property never changes its value during the lifetime of the object it belongs to, and hence the signal is never emitted for it.

COPYRIGHT

Copyright © 2008-2017 Schelte Bron