Sharing Data/Variables/Functions Between scripts?

Post Reply New Topic
RELATED
PRODUCTS

Post

Is it possible to share data either variables or functions between scripts? like one instance of a script calling another? or leaving data between them somehow in some sort of global object?

I'm wanting one controller to affect the state of another.... like one controller to change track selection and another to adjust the parameters.

Is my best bet to make a mega script with all of my controllers in one? Could seem unweildly.

I could also see some hacks/workaround using bomes midi translater to pass certain events thru to the different scripts but this would be dire extremes.
---------------------------------------------------------------
http://kirkwoodwest.com/

Post

hydrogxn wrote: Mon Apr 20, 2020 6:30 am Is it possible to share data either variables or functions between scripts? like one instance of a script calling another? or leaving data between them somehow in some sort of global object?

I'm wanting one controller to affect the state of another.... like one controller to change track selection and another to adjust the parameters.

Is my best bet to make a mega script with all of my controllers in one? Could seem unweildly.

I could also see some hacks/workaround using bomes midi translater to pass certain events thru to the different scripts but this would be dire extremes of wanting to use individual scripts...
---------------------------------------------------------------
http://kirkwoodwest.com/

Post

Scripts / Extensions are separated but you can use any kind of inter-process communication. Supported by the API you get UDP and OSC. Especially, if you use Java there are plenty of additional options.

Post

got it. what would you suggest if you went the java route?

I'm currently prototyping a lot of my controller scripts in .js and will migrate to java eventually.
---------------------------------------------------------------
http://kirkwoodwest.com/

Post

This depends on what you are trying to achieve.

Post

what im wanting is to call a function directly in each script lol. :) :) but i think with the .js includes and some customization ill be able to have some sort of roundabout osc thing so they can all talk to each other...

im gonna attempt something where one script talks to many others to do something.

one thing i cant wrap my head around is how to make each instance of a controller script to use a different port. i think that will be necessary somehow.
---------------------------------------------------------------
http://kirkwoodwest.com/

Post

You can use Node.js to set up a local server and each of your scripts can be a client. You should be able to get 2 way communication going. You'll have to download node.js (https://nodejs.org/en/download)

logsrv.node.js - this will be the server. you can run it using "node logsrv.node.js" in the command prompt, or as a windows service

Code: Select all

var net = require('net');
var fs = require('fs');
function str2ab(str) {
  var buf = new ArrayBuffer(str.length + 4); // 1 byte for each char
  var bufView = new Uint8Array(buf);
  
  bufView[3] = str.length;
  
  for (var i=4, strLen=str.length; i < strLen+4; i++) {
    bufView[i] = str.charCodeAt(i-4);
  }
  return bufView;
}

// Create our socket
var server = net.createServer(
  function (socket) {
	
	
	// Callback when data is received
	socket.on('data', function(data) 
	{
		var messagetxt = "";
		
		// Convert bytes to string		
		for(var i = 0; i < data.length; i++) 
		{
			messagetxt += String.fromCharCode(data[i]);
		}
		
		// Print message to console
		console.log(messagetxt);
		socket.write(Uint8Array.from(str2ab("Hello client")));
		socket.pipe(socket);
	});
  }
);

// Start server
console.log("Listening on 127.0.0.1:58000 ...");
server.listen(58000, '127.0.0.1');

In your controller script, add this in init():

Code: Select all

socket = host.createRemoteConnection("BitwigNodeService", 58000);
host.connectToRemoteHost('127.0.0.1', 58000, function(conn) 
{
	if (typeof this.remoteConnection === 'undefined') 
	{
		this.remoteConnection = conn;
	}
	
	this.remoteConnection.setReceiveCallback(remoteReceiveCallback);
});
and add these 2 functions:

Code: Select all

function remoteReceiveCallback( data )
{
	println(bin2String(data));
}

function bin2String(array) 
{
	var result = "";
	for (var i = 0; i < array.length; i++) 
	{
		result += String.fromCharCode(array[i]);
	}
	return result;
}
to send a message to the server, use:

Code: Select all

var messagetxt = "Hello server";
this.remoteConnection.send(messagetxt.getBytes());
So using this example, as soon as the client (your controller script) sends "Hello server" on port 58000 to the server, the server will reply with "Hello client".

Post

@vadmired13 That is amazing! Thank you so much for this example! :D

Post

Hm, just a complete noob to Bitwig Programming but with a solid Java Knowhow...
I think the possibility of Inter-Script communication should be built into the platform itself.
Thinking about simple version of OSGI here. OSGI is the framework for instance eclipse IDE of various application servers are built on top. OSGI is built with the idea of extensibility, it's extensible with plug-ins, yet shields plug-ins which are only exposing API objects to each other.
In OSGI you have extensions that ...
  • ...implement and provide interfaces ... just in Pseudo-Code for your intuition Bundle.getContext().publish("myInterface", implObj)
  • ...require interface theService = Bundle.getContext().getImpl("myInterface")
Yes, I know, this is simplified, but that's for the sake of providing the idea.

If you think about that, even Bitwig itself could expose it's APIs through this mechanism.

Not saying that it has to be OSGI, but there are other examples like for instance the Android platform which comes with similar mechanismas. Please don't get me wrong - I don't say implement this or that, I'm just giving examples for "platfrom concepts" people/programmers might know and which have proven usefull... Bitwig never need to become a full blown android, but could "borrow" some concepts ;-)

Anyway... just 2cents of a old Java Guy.

Post

I did this between a bitwig controller script and python using Py4j: https://github.com/outterback/bitwig-py ... /README.md

Which I believe works over tcp. I used it to have access to clips, tracks, and notes from a python console just to prototype some stuff. It worked surprisingly well! The code is very simple if you want to take a look at it.

Post

Here's an updated version of logsrv.node.js. What I'm doing here is keeping track of the connected clients (in my case, 2 launchcontrolxl controllers), and when one of them sends a message to the server, the server relays that message to the other controller only. It would work the same if you have multiple controllers...the server will relay the message to all controllers aside from the one that sent it. The clients are indexed using their unique client address.

Code: Select all

var net = require('net');

function str2ab(str) {
  var buf = new ArrayBuffer(str.length + 4); // 1 byte for each char
  var bufView = new Uint8Array(buf);
  
  bufView[3] = str.length;
  
  for (var i=4, strLen=str.length; i < strLen+4; i++) {
    bufView[i] = str.charCodeAt(i-4);
  }
  return bufView;
}

var clients = new Map();

var net = require('net');
var server = net.createServer(function(connection) { 
	// new connection established
	var clientAddress = connection.remotePort;
	clients.set(clientAddress, connection);
	
	// callback for end connection
	connection.on('end', function() {
		if (clients.has(clientAddress))
		{
			clients.delete(clientAddress);
		}
		connection.end();
	});

	// callback for data received from client
	connection.on('data', function(data) 
	{
		var messagetxt = "";
		
		// Convert bytes to string		
		for(var i = 0; i < data.length; i++) 
		{
			messagetxt += String.fromCharCode(data[i]);
		}
		
		clients.forEach(function(val, key, map)
		{
			if (key !== clientAddress)
			{
				val.write(Uint8Array.from(str2ab(messagetxt)));
			}
		});
		
		// Print message to console
		console.log(messagetxt);
	});

});

// Start server
server.listen(58000, function() { 
	console.log('server is listening');
});
In my controller script, I use the following to send messages to the server

Code: Select all

var messagetxt = "send_down";
remoteConnection.send(messagetxt.getBytes());
And finally, also in the controller script, I use the following to receive and handle messages from the server

Code: Select all

function remoteReceiveCallback( data )
{
    msg = bin2String(data);
    if (msg === "send_up")
    {
        // do stuff
    }
    if (msg === "send_down")
    {
        // do butt stuff
    }
}

Post

outterback wrote: Sat May 23, 2020 4:36 pm I did this between a bitwig controller script and python using Py4j: https://github.com/outterback/bitwig-py ... /README.md

Which I believe works over tcp. I used it to have access to clips, tracks, and notes from a python console just to prototype some stuff. It worked surprisingly well! The code is very simple if you want to take a look at it.
This looks bad ass my guy. what kind of stuff have you used this for? did you have something specific you are trying to achieve?
----------------------------------------------------------------------
/CTRL → http://slashctrl.io
Music & mixes → http://soundcloud.com/kirkwoodwest

Post Reply

Return to “Controller Scripting”