desktop.crosstalk

Lucid’s crosstalk system is similar to D-Bus; it provides a simple way for two application instances to communicate with one another. Lucid’s adaptation adds the ability to send and recieve messages between two different users as well. The api is influenced from Dojo’s dojo.subscribe and dojo.publish methods.

Lifecycle of a message

The way messages are sent depend on the destination, but the API acts the same either way. Each message sent can have a user, application, and instance as it’s destination. Both routes have a message dispacher that takes messages from a message queue and routes them to the other application. If the message only specifies an application, and the application is not running, then the dispacher will start the application and pass the message to it. If the message specifies a specific application instance, and that instance is not listening for messages, then the message is dropped.

Between two application instances

Diagram of message flow between two applications

When done locally, the message is pushed into a message queue by the API to be processed by the dispacher.

Between two users

Diagram of message flow between two applications running under different users

In the event that the message specifies a different user then the current, the message is sent to the server. When the other person starts the desktop, and the message checker polls the server, then the message checker pushes the message into it’s message queue to be handled by the dispacher. The dispacher then sends the message to the application.

Topics and subscriptions

Topics

Messages are separated into topics that can be subscribed to. For example, if you were writing a multiplayer checkers game, you could have a “movements” topic and a “chat” topic.

Subscribing

When subscribing to topics, you provide a handler function. This function will handle any messages recieved by the dispacher.

It’s important that you subscribe to topics inside of the init method of your app, since the dispacher may launch your app to send it a message. If it does not find any subscriptions after the init method is called, then it will kill the app. Applications launched by the dispacher are passed a crosstalk argument, which is set to true.

Subscribing to topics is pretty simple:

this.myTopicSubscription = desktop.crosstalk.subscribe("myTopic", dojo.hitch(this, "myTopicHandler"), this.sysname);

The dispacher will pass a single argument to the handler function, that will contain the message. Messages are always objects, their keys being specified by the application that sent it.

myTopicHandler: function(msg){
    desktop.dialog.notify(msg.someKey);
},

Messages also have a _crosstalk property, that has information about where the message came from:

topic
The topic that the sender specified
instance
the instance that the sender specified
appsysname
the application's sysname that was specified by the sender
sender
the userID (not username) that the message originated from. This is null if it was sent locally.

Unsubscribing

Unsubscribing from a topic will tell the dispacher to stop sending messages to the handler function:

desktop.crosstalk.unsubscribe(this.myTopicSubscription);

Publishing messages to topics

To publish a message, use the publish method.

Publishing messages between two users

To publish messages to a specific user, all you need to do is speicfy the userid and the app's system name, as well as the topic and message.

var message = {
    someKey: "Some Value",
    foo: "bar"
};
var userid = 5;
desktop.crosstalk.publish("myTopic", message, userid, this.sysname);

Publishing messages between two instances

To publish a message between two instances of an app being run by the same user, you need to pass null as the userid, and provide a system name and app instance.

var message = {
    someKey: "Some Value",
    foo: "bar"
};
var instance = 2;
desktop.crosstalk.publish("myTopic", message, null, this.sysname, instance);

Checking if a message is on the database

This feature is handy if you want to check if the message has been sent to the user or not. If it has been sent, it will not exist on the database. You need to pass a event ID and a callback. The callback will be called with 'true' (it exists, not sent) or 'false' (it doesn't exist, sent).

var message = {
    someKey: "Some Value",
    foo: "bar"
};
var instance = 2;
desktop.crosstalk.publish("myTopic", message, null, this.sysname, instance, dojo.hitch(this, function(id) {
     setTimeout(dojo.hitch(this, function() {
             desktop.crosstalk.exists(id, dojo.hitch(this, function(exists) {
                     if(exists) alert('event exists! message not yet sent');
                     else alert('event doesn't exist! message sent!');
             }));
     }), (desktop.config.crosstalkPing * 2));
}));

Cancelling an event

This is handy if you want an event sent to the user, but if the user isn't logged in or responding to crosstalk, it might as well be cancelled.

var message = {
    someKey: "Some Value",
    foo: "bar"
};
var instance = 2;
desktop.crosstalk.publish("myTopic", message, null, this.sysname, instance, dojo.hitch(this, function(id) {
     setTimeout(dojo.hitch(this, function() {
             desktop.crosstalk.exists(id, dojo.hitch(this, function(exists) {
                     if(exists){
                             desktop.crosstalk.cancel(id);
                     }
                     else alert('event doesn't exist! message sent!');
             }));
     }), (desktop.config.crosstalkPing * 2));
}));