Start a new topic

Lightpad Block M - XYZ Pad - Script to send aftertouch on Z Axis?


I wonder how straightforward it is to write a script to send after-touch on the Z axis of the XYZ pad app of the lightpad block M?

For users of keyboards that don't send after-touch like the Yamaha MODX or the Roland System 8, this would be invaluable.

I can convert controller data to after-touch in Cubase, but to do it directly from the Block would be great.

Is there an idiots guide to writing or installing scripts on the PC?



An idiots guide would be very much appreciated by this idiot here as well :). I didn't find one , so what I do is pretty much trial and error until (hopefully) success with the help of to look up functions available to be called directly. That list is daunting and I don't get a lot of it as of now, but don't let ignorance stop you from playing around with the stuff! It's the more rewarding when you finally get your idea to work out. And you will, if you are persistent enough and can put up with the occasional brain meltdown here and there.

Getting z axis in the XYZ Pad script to send channel aftertouch is actually relatively straightforward, if you don't mind a quick and dirty solution.

You need to have BLOCKS Code installed. It will connect to your Block, try to compile the code you write and upload it to the connected Block if compiling was successful (I am not sure if that was default, but in the Compiler menu I have it set to Auto Compile and Auto Upload to do that automatically while I write).

Find and open the file XYZ Pad from the File menu (in Windows the stock scripts are in C:\Program Files (x86)\ROLI\ROLI Dashboard\Littlefoot). First step is to save it under a new name in the directory where Dashboard can see it (in Windows that is C:\Users\[Your User Name]\Documents\ROLI\LittleFoot.

Now you're ready to mess around. Don't worry, code that doesn't compile doesn't get loaded into the Block and if it compiled but does weird stuff, just try something different :).

To send channel pressure messages there is a littlefoot function available:

sendChannelPressure (int channel, int pressure)

Means, if your script calls sendChannelPressure(0, 40) the Block will dutyfully send a channel aftertouch message on MIDI channel 1 with a value of 40.

The easiest solution is to just tweak the part of the code that determines what is done when you touch the lightpad in a way that it will call sendChannelPressure each time the z-value changes. A bit neater it is to tell it to only send aftertouch if the "Z axis CC" selector is set to a certain value, so that you still can send plain CC, should you want it. This is what I'll explain further down, We'll tell it to send aftertouch when the selector is set to CC 0 (which is Bank Select, you probably never wanted to send with Z axis anyway).

You can also add aftertouch explicitly to the available choices in the selector but I leave that to you :).

Off we go:

Find the function "handleTouch" in the script. It originally looks like this (line 37:

void handleTouch (int index, float x, float y, float z, float scale)

    if (index == 1)
        addPressurePoint (colour, x, y, z * scale);

        if (send == 0 || send == 1) outputCC (x, xCC, 7.0, 193.0, false);
        if (send == 0 || send == 2) outputCC (y, yCC, 7.0, 193.0, true);
        if (send == 0 || send == 3) outputCC (z, zCC, 0.0, 100.0, false);

that last line (I marked green) is the one that deals with Z (line 47). It basically says: "If the app is set to  send Z axis, then call the function "outputCC" (with the arguments as defined within the brackets)." "outputCC" is another function defined in the script, where the actual sending of CC messages takes place. For our purpose we circumvent that function if the Z axis CC is set to zero and send aftertouch from right here - quick and dirty, did I mention?

We want it to say: "If it is set to send CC 0 for the Z axis, then send Channel pressure instead, otherwise call "outputCC " as usual". The variable that holds the setting of your CC selector is "zCC". It is defined at the top of the script in "metadata". Looks like a comment block, but actually is where you define Dashboard widgets.

We change our line 47 (adding a few line on our way) to

if (send == 0 || send == 3)
            if (zCC != 0)
                outputCC (z, zCC, 0.0, 100.0, false);

            if (zCC == 0)
                sendChannelPressure ((channel - 1), (mapTouchToRange (z, 0.0, 100.0, 127.0)));           

Note the strange argument number 2. The script gets some value z from the Block as you touch and it needs to be mapped to the 0-127 value range. This mapping is originally called in "outputCC", but we circumvent "outputCC" in this decision branch, so I just borrowed the mapping function call and placed it right there. That is a bit dirty, there are nicer ways to put it. But it is the solution with least changes to the original script and works, so what :D

There is room for improvement, of course. For example aftertouch will be sent as soon as you touch, and it will be hard to keep it at zero and not lose touch while moving on the other two axes. I guess solving this will afford another approach to mapping Z to values.

("mapTouchToRange" is a function defined within the script and it uses the littlefoot "map" function. Probably it will be better to do an extra "mapZtoRange" and keep the lowest Z values from being processed)

Hope this gets you started :) I highly recommend to everyone who is even in the slightest inclined to just dive into it. The waters  may look weird, but it's all good and fun in the end. It is the scriptability where Lightpads shine the most (IMHO) and very rewarding to get something to work!

1 person likes this

Thanks for the detailed reply Frank! I'll give this a try and dip my toes in the water!

1 person likes this

Id just like to say a big thanks to Frank for his really helpful and encouraging post above.

By following his clear instructions, I was able to create the modification to the XYZ pad script that I wanted in a short space of time.

Im so glad Frank didnt just post the script, but encouraged me to do it myself. (Well, to type in his code anyway!) Adding aftertouch as an available choice within the selector is certainly beyond me at the moment but at least Im confident enough to try now! :)

So, Id echo Franks recommendation to users to Just dive into it if you are so inclined, it is rewarding and worth the little extra effort

For those who arent so inclined, Im posting the script in the Roli setups section of the forumbut if you have the time, try following Franks instructions for a more satisfying experience


1 person likes this

Oops, that post was long and I tried to be thorough as can be, but I forgot to mention the obvious last steps, which are

- save your new script in the directory Dashboard looks at

- close BLOCKS Code

- start Dashboard (needs a restart to update its list of apps) and load your script

- set Z Axis CC to 0

- enjoy

As a forum request: It would be very useful to have a "Show Comment" feature that would let us marvel at what our Post will look like and gives us a chance to clean it up and find oopsies like this before committing. A long post is very hard to troubleshoot in this small comment box and it's always a bit  worrying to hit "Post Comment".

Also: a post may take days (my personal record is 4 full days - over a weekend) before actually appearing in a thread. So if a post contains a mistake or the discussion partner has questions then a back and forth of three posts (comment - question - answer) may easily take a full week until it is finally resolved and confirmation of the answer has yet to come across. It always feels a bit like talking to someone on the other end of the galaxy and makes communication on this forum a prettyy poor experience.

Ha! Just to prove my rambling totally wrong, my first post appeared within half an hour :) Thanks, guys, love you.

Oh well, as uncomfortable as it feels to add yet another post, but dangit!

There are some more oopsies in my initial post I would have spotted and fixed if I could have reviewed it before committing.

Main one: The line to be changed is 45, not 47!

Then there is a missing closing bracket (luckily not in the code snippet) and probably some more typos.

Also, I put redundant brackets into the line

sendChannelPressure ((channel - 1), (mapTouchToRange (z, 0.0, 100.0, 127.0)));

They don't hurt in any way, but it is easier to read as follows:

sendChannelPressure ((channel - 1), mapTouchToRange (z, 0.0, 100.0, 127.0));

I am really sorry for quarduple posting. Not my style, normally, but it comes with the territory. I'd have preferred to spot them in the first place, or edit them in the original post...


Thanks for the detailed reply Frank! I'll give this a try and dip my toes in the water!


You're welcome! Hop right in, it's save and sound. Just try to keep the grin at a reasonable stupidity level once you're done and start to feel the warm thrill of accomplishment that comes with a job well done :D

If there's any questions, feel free to ask

Login to post a comment