Blender homepage link
header graphic
 

Coding Intro

To get started, you first need to download Verse and build it on your platform. All files starting with "vs_" should be included if you want to build the server. The API can be found in the file "verse.h".

A Verse application is always either a host or a client. Only in very specific cases (like implementing your own server) should one implement a host, therefore this text will only cover clients. Both clients and hosts use the same API, but there are some differences how they use it. A client always connects to a host and never the other way around (a host is defined by the fact that it answers to connection attempts). The host is always authoritative, meaning that any change that the client want to make to the data has to be cleared with the host.

For a client to get information form a server it needs to subscribe to data. there are various commands in Verse that the client can use to subscribe to different types of data. A client therefore only has to store the data that it is interested in. When a client sends a subscription command, the host will reply by sending the current state of the requested data, but will also remember that the client wants any updates that may occur to the data. So a client doesn't have to ask for updates, they will be sent automatically from the host whenever needed. Accompanying all subscription commands are unsubscribe commands that the client can use to tell the server that it is no longer interested in data. In Verse the commands hosts use to tell the clients of the current state and updates to the data are the same.

As the API on both sides are the same all commands that can be sent can also be received. All functions that send commands to the other side startswith verse_send_.

 
 

To receive commands you use the function verse_callback_set(). This command lets you register a callback function (a function pointer) that you want Verse to call whenever that command is received. To tell Verse which command to listen for, you also pass in a pointer to the corresponding verse_send function. Finally, a user data pointer is passed to the verse_callback_set() function. This pointer will be passed to the callback function; all callbacks must be take a void pointer as their first argument, and the remaining arguments must mirror the declaration of the corresponding send function.

So the command
void verse_send_node_create(VNodeID node_id, VNodeType type, VNodeOwner owner);
will have a corresponding callback looking like this:
void callback_node_create(void *user, VNodeID node_id, VNodeType type, VNodeOwner owner);

You only need to register callbacks for the commands you are interested in, and if you pass in a NULL pointer as the callback pointer, Verse will no longer call your callback. Any commands that arrive where you have not set a callback will be ignored. To tell Verse that you want to look for new incoming commands, and that Verse should generate callbacks, use the function verse_callback_update().

Lets look at a very simple Verse example and see how it all works.

 

/* A minimalist Verse example. Ask server for nodes, print information.
 *
 * Last updated on 2005-08-26.
*/

#include <stdio.h>
#include <stdlib.h>

#include "verse.h"      /* Bring in the Verse API. */

/* A callback for connection acceptation: will be called when server accepts this client. */
static void callback_connect_accept(void *user, uint32 avatar, void *address, void *connection, const uint8 *host_id)
{
    uint i, mask = 0;

    printf("Connected to a Verse host!\n\nListing nodes:\n");

    /* Build node subscription mask, include all node types. */
    for(i = 0; i < V_NT_NUM_TYPES; i++)
        mask |= 1 << i;
    verse_send_node_index_subscribe(mask);     /* Request listing of all nodes. */
}


/* A callback for node creation: is called to report information about existing nodes, too. */
static void callback_node_create(void *user, VNodeID node_id, VNodeType type, VNodeOwner owner)
{
    printf(" Node #%u has type %u, owner %s\n", node_id, type, owner == VN_OWNER_MINE ? "me" : "someone else");
}

int main(void)
{
    /* Register callbacks for interesting commands. */
    verse_callback_set(verse_send_connect_accept, callback_connect_accept, NULL);
    verse_callback_set(verse_send_node_create,	  callback_node_create, NULL);

    /* Kick off program by connecting to Verse host on local machine. */
    verse_send_connect("My_name", "My_password", "localhost", NULL);
    while(TRUE)
        verse_callback_update(100);   /* Listen to network, get callbacks. */

    return EXIT_SUCCESS;    /* This is never reached. */
}

First we include verse.h and some standard headers (for printf() etc). Then we define our callback functions. In this example there are two such functions; callback_accept_connect() is called whenever the host accepts our attempt to connect. callback_node_create() tells the client about the nodes that exists on the host.

Note that the callback_accept_connect() callback calls verse_send_node_list(). This command tells the host to send a list of all existing nodes. If this line is commented out, the callback callback_node_create() will never be called. This is very common behavior in Verse: you have to ask in order to receive.

You may notice that callback_node_create() receives very little information about the node, only its id, type and owner. To get more information about it, you need to subscribe to the node itself, and even then you won't get all information; nodes have parts to which it is also necessary to subscribe. This is referred to as a subscription tree and defines how you access data in nested layers of increasing detail.

 
 

Back to the example. In the main() function you can see two verse_callback_set() calls that registers our callbacks with the Verse API. Note that there is no need to initialize the API; it's ready to use right away.

Once the callbacks are set, we call verse_send_connect() to contact a host. This call takes a name, a password and an address. The address can be in the form of a dotted-decimal IP address like "128.43.97.156", a host name like "verse.blender.org", or "localhost" to connect to a host on the same machine as the client. After the address you can add a colon and a specific port number if you don't want to access the standard Verse port. Example: "128.43.97.156:4509".

You can use verse_callback_set() to set callbacks after the verse_send_connect() command has been called, but in our case we do it before to make sure no calls are missed. Finally we have an infinite loop that calls the verse_callback_update() API function. It has a timeout and will wait for 100 ms before it returns. If any data is received it will immediately return once all callbacks have been called.