Initial steps, some thoughts about docs

Just installed Open Stage Control -- nice work!

My question is whether my initial experience is normal (expected), or is there perhaps a bug?

I started by looking for a demo file -- for incoming users, it isn't clear whether we should search for a .state file or .json (the latter of which would be a tricky filesystem search, because there are a lot of JSON files).

So one thing that would make it much easier for brand-new users is if there is a demo session, and the demo session is automatically populated in the launcher's "load" field. (If a brand-new user has to go looking for it, then they won't find it and it effectively doesn't exist.)

In the absence of a demo session, I started the server, and created a session, added a couple of widgets, saved the session. Then in a browser, I went to localhost:8080 and got a blank Open Stage Control page (no widgets).

Trying a couple of tests, it looks like the page works (and auto-updates with new widgets!) if you loaded the session at the moment of starting the server. If I clear the "load" field in the launcher, then opening a session doesn't make it available to other clients. (Is that a bug?)

To sum that up:

  • It wasn't clear to me how to get widgets to display on pages. Nobody is going to immediately think of the sequence "save your session, stop the server, set the 'load' parameter, restart the server" but this is what it took.
  • It wasn't clear to me which are the minimum required server configuration options. It turns out it's as simple as a send target and a load session -- just pointing out that incoming users' initial experience is to read the Server configuration doc page and see a long list of options, with no guidance. All it needs is a short paragraph at the top saying "make sure to specify send and load, the others are gravy."

All in all, minor hiccups -- after getting past those, it looks really good!


It's not a bug, clients can load different sessions.

It wasn't clear to me how to get widgets to display on pages. Nobody is going to immediately think of the sequence "save your session, stop the server, set the 'load' parameter, restart the server" but this is what it took.

Using the load option is not mandatory, the following works too

  • create / save the the session on device A
  • load the session (from the recent sessions menu) on device B
  • now saving the session on either device A or B will reload it on the other

All it needs is a short paragraph at the top saying "make sure to specify send and load, the others are gravy."

This options are not mandatory, o-s-c works fine with zero options specified.

1 Like

Ohhhh... OK. That's the part that wasn't clear. I thought the model was that the server loads a session, and the same session goes out to all clients.

I still think it would be helpful if you had:

  • Getting started
    • Introduction
    • Server configuration (with a "for dummies" paragraph at the top)
    • Step-by-step working demo (doesn't exist now)
    • Running from sources etc.

... where the working demo would also introduce the architecture concepts. It was not obvious to me that a session was the thing that I needed, rather than a "state" (and to be honest, even searching the documentation, I still don't know what a "state" file is -- "Path to a state file (.state)" does not explain it). The web-client menu wasn't obvious to me either.

The software looks incredible, just thinking of ways to ease new users in more smoothly. The step-by-step can be literally just one page on the web. I'll even draft it if you want, save you some time.


Thanks for the offer, contributions to the docs are always appreciated so be my guest :). The forums can be used as a place for drafts if you want, they use more or less the same syntax as the site (markdown-based)

1 Like

Will do -- it's a really cool project, glad to help!


First try:

First Steps with Open Stage Control

Let's walk through the basic steps to build a simple interface in Open Stage Control, send information to another app, and deploy the interface to remote (even mobile) devices.

Before beginning, you should already have installed Open Stage Control -- see the Introduction.

Also: This document provides sample patches for SuperCollider, Pure Data and Max/MSP, to receive control data from the Open Stage Control interface. If you do not have any of these tools, I suggest to install Pure Data because it has the smallest footprint.

The Launcher

Use your system's application launcher, open the Open Stage Control app. Here, you can configure options for the interface server.

For now, go to the first box ("send") and type in This will tell the server to send Open Sound Control messages to the same machine where the server is running, on port 57120.

NOTE: For your own applications, you can use any port that is not in use. For this example, I chose 57120 because it is SuperCollider's default UDP port (and I set the Pure Data and Max patches to use the same port, to simplify.)

You don't need to set any other options at this time.

Addresses and ports

Many users approaching Open Sound Control for the first time get confused about ports. You need to be aware of the FROM and TO addresses. The "send" field in the Launcher should reference the address TO which messages should be sent. In this demo, we are assuming that Open Stage Control and the target app are running on the same machine. So the TO address is localhost: The "send" box should use the port on which the target app is receiving messages. This is typically under control of the target app: 1/ SuperCollider opens 57120 by default; 2/ Pd's [netreceive] object, and Max's [udpreceive], both require the TO port as an argument. So the TO port is your choice, as long as they match.

Open Stage Control sends messages FROM the IP address of the machine where Open Stage Control is running, and from port 8080 (or localhost = if on the same machine). Thus, if the receiving app will filter incoming messages based on address, the filtering address should be the FROM address, port 8080. The target app can also update Open Stage Control's display by sending messages back to exactly this address. So you will see later, in the demo patches, that messages are sent to so that the user's interaction with the target app appears in Open Stage Control as well.

Starting the server

Click the "play" button near the top left of the window. You should see status messages in the launcher window such as:

(INFO) Server started, app available at

And a new, mostly empty, window will open. This new, larger window is the client.

The client

The client allows you to edit and perform your interface.

The interface design is called a session. To create a new session, go to the "three-dots" menu at the top left, and choose Session > New session.

Two new panels are displayed: a project browser, and an object inspector (to set properties). The empty space in the middle is the editor, where you will build the interface.

Let's start with a toggle button. Right-click in the empty editor panel in the middle, and navigate to Add widget > Basics > button. For this demo, we don't need to change anything else: the button defaults to toggle behavior, and the display text is not important for now (although you can change it in the inspector, if you want).

And let's add one more control, to the right of this: Right-click, Add widget > Sliders > fader.


When a widget is selected, you can move it by dragging the top-left handle, and resize it by dragging the bottom-right handle. Let's use these handles to position the fader to the right of the button, and stretch it to be horizontal instead of vertical.


Notice, however, that the fader's value handle is still vertical. To fix this, look in the Inspector at the right, expand "Fader style," and check the "horizontal" checkbox.



By the way: I suggest to keep the widgets closer to the top left, so that they are still visible on a phone screen (later).

When designing an interface for production, you would change other object properties as well. In particular, the Open Sound Control addresses /button_1 and /fader_1 are not very descriptive. You would probably want to assign different command paths, in the "osc" tab. As this is just an introduction, we won't do that now.

Receiving the data

At this time, the interface can already be used: three-dots menu > Editor > "Enabled" (click to disable the editor). (The controls will respond also when the editor is enabled, but you have to click an extra time to select the widget before changing its value.)

To see the effect, launch one of the following apps and open the given patch. The Open Stage Control button should open and close the envelope, and the fader should control frequency. The patches also send control data from their own GUIs back to Open Stage Control, so all of the controls should be synced in both directions.

NOTE: In Pure Data and Max, the default slider/fader range is 0-127, integers. Open Stage Control uses the range 0.0 - 1.0 by default. If you just create a slider and connect it, you won't see much action. In the example patches, the slider's properties have been modified to take a 0.0 - 1.0 floating-point range, matching the data from Open Stage Control.

NOTE: Because all of the patches bind to the same UDP port, you can open only one at a time. You could, if you like, change the port number in one patch, and add that port by specifying multiple "send" targets in the Launcher, e.g.

NOTE: These patches are provided as a courtesy to get you started more quickly. Maintaining, extending or developing them is outside the scope of the Open Stage Control community.

Pure Data

Copy the code below, and save it into a text file osc-first-steps.pd. Then open it in Pure Data.

#N canvas 436 127 562 502 12;
#X obj 86 51 loadbang;
#X msg 86 76 \; pd dsp 1;
#X obj 253 51 netreceive -u -b 57120;
#X obj 253 76 oscparse;
#X obj 253 101 list trim;
#X obj 253 126 route fader_1 button_1;
#X msg 253 190 4 \$1;
#X obj 253 215 pow;
#X obj 253 240 * 200;
#X obj 253 265 lop~ 3;
#X msg 328 265 \$1 100;
#X obj 328 304 line~;
#X obj 279 356 *~;
#X obj 279 381 *~ 0.1;
#X obj 266 424 dac~;
#X text 38 139 Open Stage Control \; "First Steps" tutorial \; hjh
#X obj 253 304 osc~ 200;
#X obj 328 159 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000
#000000 0 1;
#X obj 256 159 hsl 60 15 0 1 0 0 empty empty empty -2 -8 0 10 #fcfcfc
#000000 #000000 0 1;
#X obj 70 251 unpack f s;
#X obj 70 325 oscformat;
#X msg 137 283 set \$1;
#X obj 70 424 netsend -u -b;
#X obj 93 356 loadbang;
#X msg 93 381 connect 8080;
#X obj 70 226 r sendback;
#X msg 379 200 \; sendback \$1 button_1;
#X msg 379 233 \; sendback \$1 fader_1;
#X connect 0 0 1 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 5 0;
#X connect 5 0 18 0;
#X connect 5 1 17 0;
#X connect 6 0 7 0;
#X connect 7 0 8 0;
#X connect 8 0 9 0;
#X connect 9 0 16 0;
#X connect 10 0 11 0;
#X connect 11 0 12 1;
#X connect 12 0 13 0;
#X connect 13 0 14 0;
#X connect 13 0 14 1;
#X connect 16 0 12 0;
#X connect 17 0 10 0;
#X connect 17 0 26 0;
#X connect 18 0 6 0;
#X connect 18 0 27 0;
#X connect 19 0 20 0;
#X connect 19 1 21 0;
#X connect 20 0 22 0;
#X connect 21 0 20 0;
#X connect 23 0 24 0;
#X connect 24 0 22 0;
#X connect 25 0 19 0;


Copy the text below. In Max, choose File > New from clipboard.



Copy/paste the code below into a new code document. Run the entire block to start. It will clean up when you close the GUI window.

// OSC response part
var addr = NetAddr("", 8080);  // FROM address
var freqRange = ControlSpec(200.0, 800.0, \exp);
var button, slider;

OSCdef(\button, { |msg|
	defer { button.value = msg[1] };
	if(x.notNil) { x.set(\gate, msg[1]) };
}, '/button_1', addr);

OSCdef(\slider, { |msg|
	defer { slider.value = msg[1] };
	if(x.notNil) { x.set(\freq,[1])) };
}, '/fader_1', addr);

w = Window("Open Stage Control", Rect(800, 200, 400, 100)).front;
w.layout = HLayout(
	button = Button(),
	slider = Slider().orientation_(\horizontal)
w.alwaysOnTop = true;  // may not take effect in all window managers

button.states = [["off"], ["playing",, Color(0.7, 1, 0.7)]];
button.action = { |view|
	if(x.notNil) { x.set(\gate, view.value) };
	addr.sendMsg('/button_1', view.value);

slider.action = { |view|
	if(x.notNil) { x.set(\freq, };
	addr.sendMsg('/fader_1', view.value);

w.onClose = {
	if(x.notNil) { };

// audio part
// if this fails (if you have an issue with audio devices),
// you won't hear anything but the onscreen GUIs
// will reflect changes from Open Stage Control
s.waitForBoot {
	x = { |freq = 200, amp = 0.1, gate = 0|
		var eg =, 1, 0.1), gate);
		(, 0.1)) * amp * eg).dup

Deploying the interface

The whole point of Open Stage Control is to make the interface available on other devices, especially mobile devices.

The interface will not be visible to other clients, however, until you save it to disk: three-dots menu > Session > Save, and give the file a name such as open-stage-demo (you don't need to type the .json extension).

Now -- remember those status messages in the launcher window? On another device (computer, phone or tablet), go to the address. The device should be on the same (W)LAN. (If there is another remote address, it may or may not work, depending on your network.) Supported browsers are Firefox v. 75 and higher, or Chromium/Chrome v. 60 and higher.

This should open an empty client window, similar to the one you saw before.

From here, you can open the session that you just saved: three-dots menu in the webpage > Session > Open Recent (yes, this is synced from the server!). This should display the controls created in that session, and the controls should function the same as in the other client window.

And that is... it! Basic usage is as simple as that.

For convenience, if there is a session you know that you will use often, and you don't want to load it in the webpage by hand every time, you can choose the file under "load" in the initial Launcher window. This is also useful for public deployments with audience participation, where you don't want audience members to have to load manually.

When not using Open Stage Control, you can also stop the server from the launcher window (stop button, top-left).

H. James Harkins, Feb. 2023

1 Like

Very good, I'll try to add it to the site soon, thanks for the effort !

1 Like

It's online here and the sources are here, feel free to submit changes !

1 Like

Looks like I posted the same link twice, here is the tutorial's page on the site: First Steps with Open Stage Control - Open Stage Control