Controlling Bela from a GUI

Using p5.js to Create a Custom Control Interface

The Bela IDE now integrates with p5.js, a library specially designed for creating visual interfaces and interactive elements. You can send data from your Pure Data patch to be visualised using the p5.js GUI and you can also send control messages from your GUI to control the patch running on the board. In this example we will look at both cases.

Table of contents

  1. Creative coding for visuals
  2. The code

Creative coding for visuals

The Processing foundation have been responsible for a revolution in the way that coding is taught. By placing the emphasis on creative interactive tasks, simple understandable coding concepts and great educational materials Processing (the standalone version of p5.js) has become widely adopted in universities and art colleges around the world and is responsible for introducing a whole generation of makers to coding.

At Bela we are a huge fan of Processing and p5.js and have been keen to integrate it with our IDE for a long time. This dream has been realised and you can now create custom GUIs that interact with the code you have running on your Bela. To launch the GUI there is now a dedicated button in the IDE which will open your creation in another tab.

What is p5.js?

p5.js is a JavaScript library for creating visuals in the browser. Because Bela’s IDE is native to the browser, p5 was an obvious choice. p5 also has the advantage of being very similar to Processing. Processing is an application for creating interactive visual applications that is very popular among artists, designers and educators. Since Bela is geared towards people who make creative things with technology, it means that people were likely to have some familiarity with p5 concepts already.

The structure of a project with a GUI

In addition to your Pure Data patches you will see that this project has a file which is called sketch.js which is your GUI file written in p5.js. In this tutorial we are going to concentrate on how you receive data from the GUI in Pure Data rather than looking in detail at how you write the javascript code which makes up the sketch.js file. If you would like to delve deeper into that check out our page on Crafting GUIs in the IDE and it is also worth looking at the brilliant resources on the p5.js website.

Whether you’re working in C++ or Pure Data, your sketch.js is a p5.js file and should have the structure of any p5 sketch:

function setup() { // This function runs once at the beginning of the sketch

}

function draw() { // This function repeats over and over as the sketch runs

}
Important

sketch.js is a p5.js file, so remember that we're writing in Javascript, not C++!

The code

Find the gui-receive sketch in the Pure Data section of the Examples tab of the Bela IDE.

Let’s have a deeper look at what is happening in this patch. The bela_setGui sends a message to the backend, which has some C++ code that initialises a corresponding object. The syntax for [bela_setGui] is new <type> <name> as you can see in the example.

Where <type> can be either control or array. When it is control, it means that any time the property <name> is sent from the sketch.js this is passed to [r bela_guiControl] with the <name> selector.

Let’s look at an example where we initialise the GUI like so:

In sketch.js we send info using the following form:

Bela.control.send({myname: 123});

Then in our Pd patch if we had something like the below we would see 123 printed.

When <type> is array, any values sent from sketch.js with Bela.data.sendBuffer(n, 'float', [...]) will be received in Pd in an array called <name>, where n is an index that starts from 0 and increments after each call to new array.

Here’s an example of that:

In sketch.js:

Bela.data.sendBuffer(0, 'float', [0, 1, 2])
Bela.data.sendBuffer(0, 'float', [100, 101, 102])

This will result in arrays named a and b in Pd which contain: a: [ 0, 1, 2] b: [100, 101, 102]

Here are the main differences between the two methods:

Array

Using array can be more efficient because it does not require parsing JSON on Bela. It does not - however - warn you of when new data comes in, so you would normally poll the array at fixed intervals. This is more suitable for large amounts of data sent often. This maps to Gui::setBuffer() and Gui::getDataBuffer() in C++.

Control

Using control is less efficient (in that it requires parsing JSON on Bela) but it can be more intuitive as each received value has its own label. It is more suitable for small amounts of data sent occasionally. This maps to Gui::setControlCallback() in C++, where the callback (outside the audio thread) parses the JSON and sends the results to the audio thread via a Pipe.

1. Sending data from p5.js to Bela

To see how data is sent in other direction (from sketch.js to our Pure Data patch) open the gui-receive example. In sketch.js the key line is Bela.data.sendBuffer(0, 'float', [mouseX, mouseY]); which sends a buffer of data to the Pure Data sketch.

2. Receiving signals on Bela

Initialise:

Receive through [r bela_guiControl] prepended by variable name which needs to be stripped off.