Table of Contents

xeosc So I’ve been working on XeOSC a bit recently. I managed to get the scripting engine fairly functional now and you can actually do some pretty cool stuff with it. I’m using gopher-lua for the Lua implementation and that allows the use of Go channels for concurrency, which is great. Go’s concurrency model is a lot easier and more powerful than Lua’s, so it’s really great having access to it.

Lua scripts, as of now, can be run at either initialization of the program or on the receipt of a message. Having a script run at initialization allows you to setup any connections or state, such as sending a password to QLab to access a password protected workspace. With the ability to run scripts on the receipt of a message, you can do any advanced pattern matching or math that’s needed; no need for some convoluted DSL. You can also send messages from Lua, so if you want some advanced conditional routing, that’s quite easy.

There’s a limited set of functions exported to Lua right now, but I plan on having a lot of the Go standard library available to be called, like the strings and http package. I have made channels fairly easy to use, just have to define them in the config file first and then they’re made global objects in every Lua state.

Let’s see an example

This is a simple config file that listens to message from QLab and connects to and initializes a cue light. It will also blink one of the lights if it gets /test from an QLab network cue on port 8777.

[inputs."qlab"]
proto="udp"
host="127.0.0.1"
port=8777
disable=false # the disable property is optional.

[outputs.bgoat] # can put the name in quotes or not
proto="tcp"
host="10.0.0.184"
port=8765

[routes."qlab to lua"] # nice simple route
from=["qlab"]
path="/test"
lua='''
for i=1,2,1 do
    om = xe.newMsg("/led/1/high")
    xe.send("bgoat", om)
    os.execute("sleep 1")
    offm = xe.newMsg("/led/1/low")
    xe.send("bgoat", offm)
    os.execute("sleep 1") 
end
'''

[scripts.init."goat light setup"] # this runs on startup
lua='''
m = xe.newMsg("/draw/")
m:Append("L00")
m:Append("S00")
m:Append("CONNECT")
xe.send("bgoat", m)
-- blink yellow
bl = xe.newMsg("/led/2/high")
xe.send("bgoat", bl)
os.execute("sleep 2")
b2 = xe.newMsg("/led/2/low")
xe.send("bgoat", b2)
'''

TOML is usually pretty easy to read, which I why I chose it over YAML or something else. Lua needs to be embedded in the config file as of now, but I’ll be adding support for external Lua files later on. On startup, it will parse the config file and then see where it needs to connect. It will then connect to all the necessary destinations and start listening on any inputs specified. Once those are nice and ready, it runs all of the init scripts. The Lua associated with the route will only be run if the path matches. As of now, the “match”" is only if it starts with that string. I’ll have more advanced path matching available later on, but I haven’t found the need for it right now as I can do most of it from Lua.

What’s to come

I think the major thing XeOSC needs right now is some kind of user interface. It’s command line based now, which is fine if you know your way around one, but it’s a bit unintuitive and there’s no way to interact with it as it runs right now; just spits out a bunch of logs. I’ve looked at nearly every Go GUI library out there and haven’t found one that makes me very happy. The best course of actions seems to be to build a web frontend. This would allow it to be controlled from other devices too, so that’s nice a benefit. Could have XeOSC installed on a headless server in a rack and just control it from a laptop/iPad.

Having a web frontend kind of necessitates having the ability to change the config and reload it, so I’ll have to change the way the program is structured a little. I’d like to have variables/fields that you can set from the web panel and be able access them from Lua. Maybe a page with some buttons so you can initiate some actions or something. I might add the ability to customize the frontend with Lua too, in a similar way to Repetier-server. Having a page that can show the state of some cue lights or something would be great.

In the past, I’ve had the idea for TVs mounted around showing the state of a show. Things like what light or sound cue was last fired, maybe the page number that the show is on. Maybe have actor entrances that are coming up be displayed. Or approximate time until intermission or something. I’d like this to all be doable within XeOSC and not necessitate any external programs. I’d love to have it be as simple as loading a predefined module in the config file. This is where I want to take XeOSC eventually.