What: dbif
Where: https://chiselapp.com/user/schelte/repository/dbif
Description: The DBif project provides a Tcl interface to the dbus message
        bus system. It allows Tcl programs to create and publish a fully
        introspectable dbus interface.
Updated: 12/2009
Contact: [Schelte Bron]

The dbif package builds on the dbus-tcl package to allow you to provide a fully functional dbus interface for your application that other programs can use to communicate with your application.

As an example, you can use dbif to add some debugging facility to your application by including something similar to the following code (Note: use your own domain and application name instead of 'tk.tcl.wiki' and 'demo'):

package require dbif
dbif connect tk.tcl.wiki.demo
dbif method /debug eval Expression Result {
    uplevel #0 $Expression

Then, while your application is running, executing the qdbus command will include 'tk.tcl.wiki.demo' in the list of reported names. Next, running 'qdbus tk.tcl.wiki.demo' shows:


Drilling down deeper using 'qdbus tk.tcl.wiki.demo /debug' returns:

method QString tk.tcl.wiki.demo.eval(QString Expression)
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()

To execute a Tcl command in your running application, you would use:

# qdbus tk.tcl.wiki.demo /debug tk.tcl.wiki.demo.eval "info patchlevel"

Another example: The code below will add a dbus interface to tkchat. Save it in a file called ~/.tkchat_plugins/tkchat_dbus.tcl and the next time you start tkchat you can interact with it via the dbus.

package require dbif

dbif connect tk.tcl.tkchat

namespace eval tkchat::dbus {
    namespace path ::tkchat
    variable signal

    # General methods and signals
    dbif method / quit {
        dbif return $msgid

    # User related methods and signals
    dbif method /users list {} names:a{sas} {
        dbif return $msgid [names]
    dbif method /users hide nick {
        visibility $nick 1
    dbif method /users show nick {
        visibility $nick 0
    set signal(entered) [dbif signal /users entered nick]
    set signal(left) [dbif signal /users left nick]
    set signal(nickchange) [dbif signal /users nickchange {oldnick newnick}]
    set signal(status) [dbif signal /users status {nick status message}]

    # Message related methods and signals
    dbif method /messages post text {
        tkjabber::msgSend $text
    set signal(message) [dbif signal /messages message {nick message}]
    set signal(action) [dbif signal /messages action {nick message}]

    Hook add message [namespace code message]

proc tkchat::dbus::message {nick data type mark ts} {
    variable signal
    switch -- $type {
        TRAFFIC {
            switch -- $data {
                entered - left {
                    dbif generate $signal($data) $nick
                nickchange {
                    lassign $nick old new
                    dbif generate $signal($data) $old $new
                availability {
                    lassign $nick nick status
                    lassign $status status message
                    dbif generate $signal(status) $nick $status $message
        NORMAL {
            dbif generate $signal(message) $nick $data
        ACTION {
            dbif generate $signal(action) $nick $data

proc tkchat::dbus::visibility {nick hide} {
    global Options
    set Options(Visibility,NICK-$nick) $hide
    DoVis NICK-$nick

proc tkchat::dbus::names {} {
    namespace upvar ::tkchat OnlineUsers OnlineUsers
    set rc {}
    foreach network {Jabber IRC WebChat} {
        set x [string length $network-]
        foreach n [lsort -dictionary [array names OnlineUsers $network-*,status]] {
            dict lappend rc $network [string range $n $x end-7]
    return $rc