Intro to Controller Scripting - Bitwig Studio 1.0.x

Post Reply New Topic
RELATED
PRODUCTS

Post

ThomasHelzle wrote:For collaboration with others it's best to host your scripts on Github:
http://www.github.com/
It's free and easy to do and they have tutorials on their site if you should be stuck.

The final niggles are worked on as we speak, but if you find major problems with the site, please report them to support:
http://www.bitwig.com/en/support/tech-support.html

If the authors of the scripts already in the database want to make any changes, please also feel free to contact me or tech-support so we can take care of it!

Happy Scripting and Controlling!

Cheers,

Tom
Congrats on your efforts...

Post

Cheers mate ;-)

Tom
"Out beyond the ideas of wrongdoing and rightdoing, there is a field. I’ll meet you there." · Rumi
UrbanFlow.art · Instagram · YouTube

Post

I Have uploaded the Mapping for Touch OSC and the Modifyed Bi-Drectional Script from Thomas (still under the original Name) to my Dropbox Account.

https://www.dropbox.com/s/c14qy5le4zknp ... 20test.rar

Encoders/Fader and the 4 X/Y Pads are freely Mappable for now. Play, Stop, Record, Overdub and Restart are working.
The Encoders on Page two are mapped to Bitwig defaults (cc 20-27) but not Coded in the Script ( i simply just can´t get my Head around it)

The Mapping works on Android, should also work on an iPad as i used the size def for an iPad in the Touch OSC Editor.

For getting Midi Back and forth between Touch OSC and Bitwig the Touch OSC Bridge is used.

Far from perfect but i hope you enjoy it anyway ;-)

Post

Can you set up a Github Repository for it?

Cheers,

Tom
"Out beyond the ideas of wrongdoing and rightdoing, there is a field. I’ll meet you there." · Rumi
UrbanFlow.art · Instagram · YouTube

Post

For the Script: Yes
But i haven´t found a way to upload the TouchOSC Mapping to Github as of jet. Repo is in the Works btw.
Al long as i can´t get the Touch OSC Mapping up to Github i´ll keep it on Dropbox (together with your slightly modified Bi-Dir Script) and put the script i´m working on up at Github.

Here it is: https://github.com/astartes72/TouchOSC- ... ree/master

On the Script at Github i can´t figure out the correct Naming of the Bridge. Bitwig won´t recognize it for now. UUID is set correctly.
Implemented as of Now: Transport Control (working)

Mappings in Touch OSC:
Page 1:
Buttons for Restart, Stop, Play, Record, Overdub (all Working with the Modification made to Thomas´original Script, included in the Dropbox Folder. Same code on Github)
Volume Faders: CCs 101-108
Masterfader: CC 109
Encoders (Pan): CCs 91-98
(All not Scripted yet)
Two Buttons for Trackbank Up/Down. No CCs assigned as of yet

Page 2:
Encoders for Primary Device/UserControls: CCs 20-27 (Not Scripted yet)

Page 3:
4 X/Y Pads with CCs 12-19 mapped, starting with the top left Pad
A Copy of the transport Controls (for testing purposes, will maybe be removed in the Future)

If there are any Mistakes on the Repo itself please tell me (first Time i work with Github, so...)

Post

No problem, I only started using Github recently myself ;-)
We're all here to learn.

Everything you put in your local repo folder is "mirrored" to Github when you commit and sync, so if you drag the TouchOSC mapping file in that same folder, it should go to the repo.

A Bitwig Controller Script file needs to end with .control.js, otherwise it's not recognized.

Good stuff!

Cheers,

Tom
"Out beyond the ideas of wrongdoing and rightdoing, there is a field. I’ll meet you there." · Rumi
UrbanFlow.art · Instagram · YouTube

Post

Little Update: I Updated the Repo on Github and opened a Seperate Thread. Touch OSC Mapping now included. Script Modifications Work, Script gets recognised by Bitwig

Post

:tu:
"Out beyond the ideas of wrongdoing and rightdoing, there is a field. I’ll meet you there." · Rumi
UrbanFlow.art · Instagram · YouTube

Post

i'm currently updating my control scripts for the edirol pcr-300 and novation launchpad for live use.. (will upload them somewhere soon).. but the api isn't that well documented, so i have some questions:

*** what's the difference between host.createTrackBank and host.createMainTrackBank? my script seems to work similarly using either of them..

*** is there a host.toggleEngine() somewhere? i can only find separate activate/deacivate functions.. i would like to use button to toggle it on and off..

*** is it possible to switch to next/prev Tab (project) from a control script?

Post

tor.helge.skei wrote:i'm currently updating my control scripts for the edirol pcr-300 and novation launchpad for live use.. (will upload them somewhere soon).. but the api isn't that well documented, so i have some questions:

*** what's the difference between host.createTrackBank and host.createMainTrackBank? my script seems to work similarly using either of them..

*** is there a host.toggleEngine() somewhere? i can only find separate activate/deacivate functions.. i would like to use button to toggle it on and off..

*** is it possible to switch to next/prev Tab (project) from a control script?
host.createTrackBank is a bank of all tracks.
host.createMainTrackBank is "normal tracks" only, without effect and master tracks.
host.createEffectTrackBank is effect tracks only.
host.createMaster is the master track only.

You can mix and match as you need.

- I don't see a toggleEngine either, but creating a toggle is simple: save a variable with a state and then you can put something like the following pseudocode in your script:

Code: Select all

var engingState = true; //global or however you want to define it
On receiving the respective midi command you can use:

Code: Select all

engineState = !EngineState;
if(engineState){
   Application.activateEngine();
}
else {
   Application.deactivateEngine();
}
to toggle the value between true and false and switch the engine accordingly.

Or shorter:

Code: Select all

engineState = !engineState;
(engineState) ? Application.activateEngine() : Application.deactivateEngine();
- I don't think it's possible to switch tabs yet.

Cheers,

Tom
"Out beyond the ideas of wrongdoing and rightdoing, there is a field. I’ll meet you there." · Rumi
UrbanFlow.art · Instagram · YouTube

Post

thanks a lot!!
will check it all out a little later tonight, when i get home from rehearsals...

another question:
how do i read the value of a macro control (primaryDevice, currently selected track)?
i can find a set() function, but not get().. there is an addValueObserver() function there, but i didn't get it to work properly when i tried.. how should i use it? i would need the macro index as well as the (current) value (preferably in a 0-127 range) to implement the scaled value mode i'm trying to get working...

Post

tor.helge.skei wrote:another question:
how do i read the value of a macro control (primaryDevice, currently selected track)?
i can find a set() function, but not get().. there is an addValueObserver() function there, but i didn't get it to work properly when i tried.. how should i use it? i would need the macro index as well as the (current) value (preferably in a 0-127 range) to implement the scaled value mode i'm trying to get working...
Yeah, that's one of the more baffling things in the API. I wrote a tutorial on it a while ago but it's supposed to be part of the Bitwig API Ressources and not online yet... :oops:

In short: you can't read values directly. What you have to do instead is creating an observer with a callback function that is called every time the value changes inside the application. Inside the callback function you can for instance save the value to a global variable (for simple scripts) or a general state-object created for your controller (I'm getting into that by and by).

This is part of some code I work on ATM for a touchOSC script:

Code: Select all

tOSC.cDevice = tOSC.cTrack.getPrimaryDevice();
tOSC.cMacro = [];

for (var i=0; i<8; i++) {
   // Macro
   tOSC.cMacro[i] = tOSC.cDevice.getMacro(i);
   tOSC.cMacro[i].getAmount().setIndication(true);
   tOSC.cMacro[i].getAmount().addValueObserver(127, getTrackValueFunc(i, tOSC.deviceMacro, tOSC.deviceMacroHasChanged));

// A function to create an indexed function for the Observers and set a dirty flag for fllush()
function getTrackValueFunc(index, varToStore, varToSet)
{
   return function(value)
   {
      varToStore[index] = value;
      varToSet[index] = true;
   }
}
tOSC is my main object that holds basically all data I use.
tOSC.cTrack is my cursor track.
I first initialize an empty array on it (tOSC.cMacro = [];)
Then I go through a loop, save each macro object in the array, set the indication (so that the active macro knobs are colourised in BWS) and then add a value observer on each. This happens in init().

Below that is my getTrackValueFunction, which contains an additional variable since I often set a "dirty flag" when parameters have changed so I can update them in the flush() function (only needed for controller feedback).

This whole business is typical JS stuff that I'm still in the process of wrapping my head around. The outer function has three function parameters, but it returns the inner function that has only one (and the callback can only have one).
What I send it is the index, the array that holds the values (tOSC.deviceMacro) and the array that holds the boolean flags (tOSC.deviceMacroHasChanged).
Because of the obscure "closure" rules of JS, the inner function can access the parameters of the outer function even when the whole enchilada has returned. For a C-head like me that is pretty much voodoo ;-)

The "127" does the scaling for you.

Was that understandable?

My TouchOSC fork of astartes idea can be found here:
https://github.com/ThomasHelzle/TouchOSC-Bitwig

It's work in progress and not really usable yet, but you can see the above stuff in context.

Cheers,

Tom
"Out beyond the ideas of wrongdoing and rightdoing, there is a field. I’ll meet you there." · Rumi
UrbanFlow.art · Instagram · YouTube

Post

ThomasHelzle wrote:For a C-head like me that is pretty much voodoo ;-)
hehe.. same here!!

again, thanks a lot!
i think i understand it all a little bit better now..
i will do some tests and experiments later tonight..
then we'll see if i _really_ understood it.. :-)

cheers!

Post

aaahhh..
the general idea actually seems to work!
this video shows what i'm trying to do.. (the "value scaling" mode is describe from around 5 minutes in):

and here's what i did:

// global

Code: Select all

var knob_values = [];
var macro_values = [];

function getMacroValueFunc(index,variable) {
  return function(value) {
    variable[index] = value;
  }
}
// init()

Code: Select all

// are these necessary? does javascript zero/clear the buffers?
for (var i=0; i<128; i++) macro_values[i] = 0;
for (var i=0; i<128; i++) knob_values[i] = 0;

for (var i=0; i<8; i++) {
  macro = primaryDevice.getMacro(i);
  macro.getAmount().setIndication(true);
  macro.getAmount().addValueObserver(128,getMacroValueFunc(i,macro_values)); // 127 or 128?
}
// onMidi() callback

Code: Select all

var param = 0;
var prev_val  = knob_values[chan];
var cur_val   = value;

if (cur_val > prev_val) {
  // up
  var range     = 127 - prev_val;
  var diff      = cur_val - prev_val;
  var scale     = diff / range;
  var prange    = 127 - macro_values[chan];
  var change    = (prange*scale);
  param         = macro_values[chan] + change;
} else {
  // down
  var range     = prev_val;
  var diff      = prev_val - cur_val;
  var scale     = diff / range;
  var prange    = macro_values[chan];
  var change    = (prange*scale);
  param         = macro_values[chan] - change;
}

knob_values[chan] = value;
//macro_values[chan] = param; // 'automagically' set by macro value observer?
primaryDevice.getMacro(chan).getAmount().set(param,128);
this is just a prototype, and it can probably be done a lot better.. i'm just excited that the idea actually worked, and want to share it :-).. there might be some 127 vs 128 issues/errors in there.. and, my javascript skills are noting to rave about.. so, any suggestions or comments about the code is welcome :-)

i have to wiggle the knobs a little when i start bitwig studio, so that the script knows the physical positions of the knobs, but after that it seems to work as intended, or pretty close..

cheers
- tor-helge

Post

@Thomas: Your Script for TouchOSC is great. Big Thanks for this. Just tested it with your Layout and the one i´m working on. Works as expected.
I Ported your Layout to the size of an iPad and (for now) copied over one of the Pages you made to my Script (to get the correct mappings in the Editor). I´ll use your Controlscript for further Work if you don´t mind.

Post Reply

Return to “Controller Scripting”