libose
Loading...
Searching...
No Matches
The Bundle as a Stack

discusses the bundle as a stack

An OSC bundle contains a header followed by zero or more bundle elements. A bundle element may be a bundle, or a message.

The elements of a bundle are ordered, with the first element being the one in closest proximity to the header. Throughout this library, the bundle is thought of as a stack, that grows away from the header, i.e. the top of the stack is the element furthest from the header.

Since bundle elements themselves may contain many things—more bundle elements in the case of bundles, or typed data like numbers, strings, etc. in messages—they too may each be thought of as stacks that grow away from their header or address.

Adding Messages to a Bundle

To add a new message to a bundle, you push it onto the end:

#include <string.h>
#include "ose.h"
#include "ose_context.h"
#include "ose_stackops.h"
#define NUM_BYTES 65536
int main(int ac, char **av)
{
char bytes[NUM_BYTES];
ose_bundle bundle = ose_newBundleFromCBytes(NUM_BYTES, bytes);
ose_pushMessage(bundle, /* the bundle to add the message to */
"/hello", /* the address of the message */
strlen("/hello"), /* the length of the address */
1, /* the number of arguments */
OSETT_STRING, /* the type of the first arg */
"world!"); /* the first arg */
ose_pushMessage(bundle, /* the bundle to add the message to */
"/list", /* the address of the message */
strlen("/list"), /* the length of the address */
3, /* the number of arguments */
OSETT_INT32, /* the type of the first arg */
1, /* the first arg */
OSETT_INT32, /* the type of the second arg */
2, /* the second arg */
OSETT_INT32, /* the type of the third arg */
3); /* the third arg */
return 0;
}
provides global definitions and types
contains functions that structure an OSC bundle for use with other parts of this library
contains functions that manipulate the structure and contents of an OSE bundle and its elements
Definition ose.h:374

This example creates a new bundle from an array of bytes, and adds two messages to to the bundle, one with address /hello, which will be the first message closest to the header, and one with address /list, which will be the last message, furthest from the header.

Messages can also be built up incrementally by first creating a message with only an address, and then pushing items into the bundle (as messages), and then further pushing them onto the message.

#include <string.h>
#include "ose.h"
#include "ose_context.h"
#include "ose_stackops.h"
#define NUM_BYTES 65536
int main(int ac, char **av)
{
char bytes[NUM_BYTES];
ose_bundle bundle = ose_newBundleFromCBytes(NUM_BYTES, bytes);
// Create an empty message.
ose_pushMessage(bundle, "/list", strlen("/list"), 0);
for(int i = 0; i < 10; ++i)
{
// Push an int onto the stack (as a message with no address).
ose_pushInt32(bundle, i);
// Push the int onto the end of the message with address "/list"
ose_push(bundle);
}
}

Here, each item is pushed into the bundle and then pushed onto the end of the message we are creating. The important thing to note is that typed items such as integers cannot exist in a bundle on their own, since a bundle can only contain bundle elements (i.e. bundles and messages). So, when we push an int into the bundle, we are actually creating a message that contains that int and has an empty address. Then, when we call ose_push(), the value of that message gets concatenated onto the end of the message below it.

Evaluating a Bundle

Evaluation of the elements of a bundle is done using the OSE virtual machine. The VM consists of multiple bundles that serve each play a role in its operation. The simplest description of its operation is that it moves elements from the input bundle to the stack bundle; bundles found in the input bundle are moved as-is to the stack, while messages are destructured, each item becoming its own message on the stack.

Given an input bundle with two messages:

{
/list/1 : [1, 2, 3],
/list/two : ["one", "two", "three"]
}

after running the VM, the stack will look like this:

{
: "one",
: "two",
: "three",
: "/list/two",
: 1,
: 2,
: 3,
: "/list/1"
}

The input bundle is read in reverse order—each element is popped off the end. The items of each message, however, are read starting from the item closest to the address, and ending with the address itself as a string. See OSE Virtual Machine and the various examples for more info about how to use the VM as an OSC server.