Mozilla Skin*/?>

CL2 Deeper With Data

From ConduitWiki

Back to User's Guide contents


Conduit Live 2 is a realtime video compositing application, but video is not the only type of input that can be processed. Using the Project view, it's possible to create realtime systems that work with any kind of data like user interface events, external MIDI signals, and realtime online data from a web site.

To unleash this potential, Conduit Live 2 offers a set of node widgets with a JavaScript interface. Using these building blocks and a bit of programming, you can do almost anything.

Script Widget

Script Widget is a customizable node that has two input ports and outputs a single value.

The output value is determined by the onRender function. Here's a code example that simply passes through whatever data came from the first input port:

this.onRender = function(inputMap1, inputMap2) {
    return inputMap1;
}

inputMap1 and inputMap2 are Map objects, explained in the next chapter. The onRender function can return either a Map or a regular JavaScript array object.

Map object in JavaScript

In a previous topic discussing node widget connection types, it wasn't necessary to get into detail about the exact type of data that's transferred over a value connection between node widgets. To be able to efficiently use Script Widget, we need some more specifics.

The data from an input port is given to Script Widget as a JavaScript object of type Map. This is essentially like an array that also has names for indexes. These names are called keys. The map can be accessed either by index or key.

Let's see some code samples for how a Map is created, modified and accessed:

var map = new Map();
map.set("first", 123);
map.set("second", "abc");
map.push("xyz");
var a = map.get("first");
var b = map.getByIndex(1);
var c = map.getByIndex(map.length - 1);
sys.trace("Map values are "+a+" and "+b+" and "+c);

This code would output the following text to the trace output:

Map values are 123 and abc and xyz

Map objects are used because the data being passed around in a Conduit Live project usually has some kind of meaning, and we don't want to lose that information. For example, the data output by a Slider Bank node is a Map with keys such as Slider 1, etc.

Custom interfaces

It's possible to create a custom interface for a Script Widget. Here's an example that creates two buttons and a slider, and also has binding functions so that the user interface elements actually do something:

this.counter = 0;

this.nodeInterfaceDef = [
  { "type": "label", "id": "infoLabel", "text": "Hello! This is a sample interface.", "color": "white" }, 
  { "type": "floatControl", "id": "slider", "min": -50, "max": 50, "resize": "width", "actionBinding": "this.onSlider" }, 
  { "type": "button", "id": "button1", "text": "A button", "actionBinding": "this.onButton" }, 
  { "type": "button", "id": "button2", "text": "A fixed-width button", "width": 130, "actionBinding": "this.onButton" } 
]

this.onButton = function(buttonId) {
  this.counter++;
  var button = this.getUI().getChildById(buttonId);
  var slider = this.getUI().getChildById("slider");
  button.label = "Click "+this.counter;
  slider.numberValue = this.counter;
  return true;
}

this.onSlider = function(sliderId) {
  var slider = this.getUI().getChildById(sliderId);
  this.counter = Math.round(slider.numberValue);
  return true;
}

The node interface definition is a JSON array, and needs to be declared as this.nodeInterfaceDef. Conduit Live uses this declaration to create the actual user interface elements. (This is roughly similar to how HTML works in a web browser.)

The onButton and onSlider function names are arbitrary, they could be called anything. These names are referred in the actionBinding properties within the node interface definition.

These action binding functions modify a counter variable. The onSlider function simply gets the slider's current value and sets the counter to that. The onButton function is a bit more involved: after incrementing the counter, it changes the label on the button and moves the slider to a new position.

The user interface elements are accessed with a this.getUI().getChildById() call. Each user interface element needs to have an "id", a simple name. For our buttons and slider, these ids were set in the node interface definition.


Back to User's Guide contents