Version 3 of dbus-intf

Updated 2012-03-03 14:44:42 by sbron
What: dbus-intf
Where: http://sourceforge.net/projects/dbus-tcl 
Description: The DBus-Intf 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 dbus-intf 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 dbus-intf 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 dbus-intf
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:

/
/debug

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"
8.5.9

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 dbus-intf 0.4

dbif connect tk.tcl.tkchat

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

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

    # User related methods and signals
    dbif method /users list {} names:a{sas} {
        dbif return $msgid [::tkchat::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
}