Sharing Data/Variables/Functions Between scripts?

KVRist
74 posts since 12 Dec, 2007 from Fort Bragg, CA

Post Sun Apr 19, 2020 10:30 pm

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/

KVRist

Topic Starter

74 posts since 12 Dec, 2007 from Fort Bragg, CA

Post Sun Apr 19, 2020 10:30 pm

hydrogxn wrote:
Sun Apr 19, 2020 10:30 pm
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/

User avatar
KVRAF
2741 posts since 13 May, 2004

Post Sun Apr 19, 2020 11:19 pm

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.

KVRist

Topic Starter

74 posts since 12 Dec, 2007 from Fort Bragg, CA

Post Sun Apr 19, 2020 11:48 pm

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/

User avatar
KVRAF
2741 posts since 13 May, 2004

Post Mon Apr 20, 2020 12:13 am

This depends on what you are trying to achieve.

KVRist

Topic Starter

74 posts since 12 Dec, 2007 from Fort Bragg, CA

Post Wed Apr 29, 2020 8:14 am

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/

KVRer
15 posts since 21 Apr, 2020

Post Mon May 04, 2020 10:15 am

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".

KVRer
16 posts since 7 Apr, 2010 from Newcastle, Australia

Post Fri May 22, 2020 10:22 pm

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

User avatar
KVRian
1274 posts since 22 Sep, 2016

Post Sat May 23, 2020 2:20 am

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.

KVRer
14 posts since 17 Oct, 2017

Post Sat May 23, 2020 8:36 am

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.

KVRer
15 posts since 21 Apr, 2020

Post Wed Dec 30, 2020 10:58 pm

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
    }
}

User avatar
KVRist
125 posts since 12 Apr, 2020

Post Sat Apr 17, 2021 9:43 pm

outterback wrote:
Sat May 23, 2020 8:36 am
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?
----------------------------------------------------------------------
http://instagram.com/kirkwoodwest/
http://soundcloud.com/kirkwoodwest

Return to “Controller Scripting”