Make your X32 talk to Vor (or anything else that reads custom OSC I suppose)
Working, in testing. My test rig has a wired ethernet to the X32, and VOR is on the same machine.
X32Vor has a pretty ansi styled terminal to show it's working. It even sizes itself to fit as best it can.
$ node index.js --ip x32_address
$ node index.js --config config.file.json
$ node index.js --help
-i, --ip address IP Address of the X32 [required]
-o, --vor-ip address IP for Vor (127.0.0.1)
-o, --vor-port port Port for Vor (3333)
-c, --config config.json Read configuration from a file
-w, --write new.config.json Write configuration to a file
--no-gui Suppress the ansi terminal display
X32Vor might be configured just fine out of the box. But, the easiest way to mess with things is to launch the script with the --write
option and edit the file. You'll need to provide at least a X32 IP address to write the file.
If you name your configuration file x32_vor.config.json
, it will be automatically loaded at startup (unless another configuration file is specified)
X32Vor tracks cues, scenes, snippets, dca's, and busses. The vor.output
directive controls which of these are sent to Vor - the valid options are cue
, dca
, bus
, dca1
->dca8
, and bus01
->bus16
For more detailed information on the rest of the possible settings, take a look at the default settings
X32Vor sends the current cue string that is appropriate to the X32 Show Control setting.
Because OSC uses UDP with all of the technical considerations and limits that implies, it is important to set your vor.output
directive with the minimum you need.
The maximum safe UDP payload is 508 bytes. This is a packet size of 576 (the "minimum maximum reassembly buffer size"), minus the maximum 60-byte IP header and the 8-byte UDP header.
If your packet size exceeds the maximum above, it will be fragmented - on a local network, this is probably still fine (including local loopback), but if one fragment fails to deliver, the entire packet is dropped. Because X32Vor transmits the entire state each send 10th send window (those windows between only what has changed sends), in practice, this is probably fine - but if you notice a lot of stutter in the data, try reducing the amount of measurements you are listening to.
Likewise, it takes some amount of time for the UDP packet to arrive - and each packet is timestamped 50ms in the future (by default) - if it arrives after this time, it will be ignored (configurable in VOR). If your stream jitters, you can try increasing this time offset.
Windows is similar, but Vor does not run on Windows PC's - you still may want to use a windows machine if you need to process the X32 messages on somewhere else - X32Vor can broadcast the Vor packets to a network address other than localhost.
create ~/.zprofile
if it does not already exist (default mac shell is zsh - if you've changed it, you likely already have a .profile or .bashrc or whatever.)
$ touch ~/.zprofile
install nvm (Node Version Manager)
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
restart the terminal and install node.js
$ nvm install 20
Verify installation
$ node -v
v20.14.0
$ npm -v
10.7.0
Use GIT to clone the repository, or, download the source ZIP file from GitHub
$ git clone https://github.com/jtsage/X32_Vor.git
In the folder of the repository (or the unzipped files), run npm
$ npm install
$ node index.js -i [X32_IP_Address] -w x32_vor.config.json
Add a Custom OSC connection of type UDP.
By default, X32Vor uses port 3333, but you can use whatever you want as a command line switch -p 4444 (Option vor.port
). Outputting to VOR on a different physical address is possible with the -o 10.1.1.10 switch (Option vor.address
). This has been briefly tested with Vor Mobile
Add any of the available address endpoints. They must be configured with the vor.output
option (or in the defaults). All addresses return only strings
Available:
- /currentCue [cue string]
- /dca/[dca number] [single fader string]
- /bus/[bus number] [single fader string]
The fader string can be set with the vor.singleStringFormat
option. If you prefer to do more layout work in Vor, you can have faders sent as three strings instead by setting vor.singleStringMode
to false
to get:
- /bus/[bus number] [level] [on/off] [name]
Note: Bus number must be zero-padded, e.g. /bus/01
, not /bus/1
Example shown for current cue.
This is a list with processed arguments of what OSC messages X32_Vor processes. Everything else is silently ignored. Some of these are node
messages - the real message is in the first string argument of the node
address - not the lack of preceding slash
/-prefs/show_control [i~index of]
node s~{-prefs/show_control [s~CUES,SCENES,SNIPPETS] }
/-show/prepos/current [i~current cue/scene/snippet index]
node s~{-show/prepos/current [i~current cue/scene/snippet index]}
node s~{-show/showfile/show (no args processed, when seen, clear internal cue list)}
node s~{-show/showfile/cue/[index] [i~cueNumber] [s~cue Name] [i~skip?] [i~scene index] [i~snippet index] }
node s~{-show/showfile/scene/[index] [s~scene name] [s~scene note] }
node s~{-show/showfile/snippet/[index] [s~snippet Name] }
node s~{dca/[1-8] [s~ON/OFF] [s~level in dB]}
node s~{dca/[1-8]/config [s~DCA Name] (others ignored)}
/dca/[1-8]/config/name [s~DCA Name]
/dca/[1-8]/on [i~ON/OFF bool]
/dca/[1-8]/fader [f~level in float]
node s~{bus/[01-16]/mix [s~ON/OFF] [s~level in dB] (others ignored)}
node s~{bus/[01-16]/config [s~DCA Name] (others ignored)}
/bus/[01-16]/mix/fader [f~level in float]
/bus/[01-16]/mix/on [i~ON/OFF bool]
/bus/[01-16]/config/name [s~DCA Name]
Pseudo-code follows, for anyone looking to do something similar for the X32/M32 series
function sendToX32(oscAddress, parameter1, parameter2, ...) { /* ... */ }
Get the show control mode, current cue index, and show data. Get the fader, mute, and name status for all DCA's and BUS's
sendToX32('/node', '-prefs/show_control')
sendToX32('/node', '-show/prepos/current')
sendToX32('/showdata')
sendToX32('/node', 'dca/[1-8]')
sendToX32('/node', 'dca/[1-8]/config')
sendToX32('/node', 'bus/[01-16]')
sendToX32('/node', 'bus/[01-16]/config')
sendToX32('/xremote')
The X32 times out the xremote
command after 10 seconds. X32Vor re-sends every 5 seconds just to be sure.
sendToX32('/xremote')
Or, when an event is received where we think the cue list has changed - this includes cue/scene/snippet save/delete/edit
sendToX32('/showdata')
Sure. Check the dist folder.
Open a ticket, or find me on the VOR or TGR discord groups.
"Can I do...?" -> sure. go for it. If you can, and it might be useful to others, send a pull request to include it in the repo.
As a rule, I always prefer optional behavior - e.g. levels are in dB right now, but if you wanted the raw number, add it as an option rather than changing existing functionality.