Dynamic composition of a SysEx message with variable content and length

I am wondering how they do this:

With the delay I introduced I need ~3sec to recall all faders to the right position :thinking: (there are no internal banks, banks come from the DAW)

I think you should reach out to them and tell them what’s going on.

I send them a mail, but I think I just found how to solve the problem. The standard MCP configuration is to use a pitch bend message for the fader with one different channel per fader. I just modified this with the RIG manager and the fader are recalled properly. For the moment no idea if it is due to the pitch bend message or to the different channels used, but it works properly like this.

1 Like

I just had a feedback from Icon, it was a bug in the Platform control surface. They just released a firmware Platform M+ v2.07beta, where they solved the issue. I have to admit, that for the moment, I am impressed by their support. They gave me all the information to control the Platform M+ from Gig performer and fixed the bug with the delay to move the faders with CCxx rather than with Pitch Bend messages.
So, as it is still tricky to use knobs working in incremental mode (the scripting workaround makes you loose the advantage of the RIG manager) ), and the Platform M+ knobs are not surrounded from a LED circle (:-1:) so they probably did’nt think that it is necessary to let the knobs synchonize with the value from a PC host.
I know that working with knobs in incremental mode is in your list, but I also asked Icon to consider adding the possibility to synchronize their knobs with a value coming from GP.

Understand this thread is a bit old, but was there ever a way added to get hex characters from an ASCII string for use with SM_CreateSysexFromString(m, s) so you could do, for example:

var manager : SysexManager
SM_CreateSysexFromString(manager, "#f0 (...) " + stringtohex(s) + " (...) f7")

Thanks

Hi @rbmj, the solution I used for this is described here:

1 Like

Thanks! That’s quite the hack but it works great! I just wrote code to show the current rackspace name on my Arturia Keylab mk2’s LCD screen. A couple notes/wishlist items, and I’ll share the code at the bottom:

  • Global Scripts would be nice. If the interacted with the rig system that would be even better (though you’d probably need to add oop and inheritance to GPScript for the last bit so I understand that’s a stretch :D)
  • Some sort of way to share code between rackspaces, even if it’s just a basic #include style copypaste
  • Understand that documentation is a pain, especially for something like this. Maybe make it a wiki or host it on github so that the community can help?
  • Add me to the list of people asking for OnSongActivate - Looks like from another thread you’ve written the code so hopefully it’s easy!
  • String constant expressions are pass by reference, which leads to the rather confusing behavior that var s : String; s = "foo"; bar(s); is not equivalent to bar("foo"); if bar modifies its argument. If all non-primitive types exhibit this behavior it would be helpful if it was explained in the tutorial.

I’ll share my code in case anyone else is using the keylab:

var
    Keylab2          : MidiOutBlock;
    SysEx            : SysexManager;
    KEYLAB2_LCD_PRE  : String;
    KEYLAB2_LCD_SEP  : String;
    KEYLAB2_LCD_END  : String;
    ASCII_STRING     : String;
    ASCII_HEX_STRING : String array;

Initialization
    ASCII_STRING = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[Y]^_`abcdefghijklmnopqrstuvwxyz{|}><";
    ASCII_HEX_STRING = ["20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F","30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F","40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F","50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F","60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F","70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F"];
    KEYLAB2_LCD_PRE = "# F0 00 20 6B 7F 42 04 00 60 01 ";
    KEYLAB2_LCD_SEP = " 00 02 ";
    KEYLAB2_LCD_END = " 00 F7";
 End
    
Function StringToHexString(str : String) Returns String
   var i : Integer
   result = "";

   For i=0; i<Length(str) ; i=i+1 Do
     result = result + ASCII_HEX_STRING[IndexOfSubstring(ASCII_STRING, CopySubstring(str,i,1), True)];
   End
End
    
Function Keylab2LCD(line0 : String, line1 : String)
    If Length(line0) > 16
	Then
		line0 = CopySubstring(line0, 0, 16);
    End
    line0 = StringToHexString(line0);
    
    If Length(line1) > 16
    Then
        line1 = CopySubstring(line1, 0, 16);
    End
    line1 = StringToHexString(line1);


    SM_CreateSysexFromString(SysEx, KEYLAB2_LCD_PRE + line0 + KEYLAB2_LCD_SEP + line1 + KEYLAB2_LCD_END); 
    SM_SendMidiOut(SysEx, Keylab2);
End

On Activate
    var s : String;
    s = "Rackspace:";
    Keylab2LCD(s, GetRackspaceName());
End
3 Likes

Wow — I continue to be flabbergasted by how people have used GP Script, a language that was intended for writing 10-20 line programs for minor MIDI hacking :slight_smile:

Having said that, I’ll mention a couple of things (although not everything) happening (just) with GP Script (which sorely needs a new name, particularly since it’s not really a scripting language, it gets compiled!) for upcoming versions of Gig Performer. I’ll add the usual caveat that nothing is guaranteed as I don’t want someone to buy GP with the assumption that a particular feature will definitely be there and then be annoyed if it isn’t!

  1. GP4 will have the notion of a global script. I’m not sure what you mean by interacting with the rig system though. The global script can respond to certain events such as SongChanged and you can send sysex messages out through any midi output device. That will let you centralize such things as updating a display, without having to put code in every rackspace.

  2. Sharing code is a high priority — for various obscure reasons, it has turned out to be much harder to implement than expected but it’s on my high priority list, we’ll get there!

  3. GP4 will also have the notion of song scripts, paralleling rackspace scripts. Song scripts have On Activate. You can of course combine that local “On Activate” with a global “On Song Changed”

  4. Variable declarations will allow initialization as well so you will be able to write things like

var 
KEYLAB2_LCD_PRE : String = "# F0 00 20 6B 7F 42 04 00 60 01 ";

simplifying code significantly.

In principle this is a bug! Incoming variables are generally call-by-value but (similar to Java or Smalltalk), if the variable is an object, you can change stuff inside that object. String constants were implemented as simple objects so that I didn’t have to copy strings. At the time (very first version of GP Script) I was concerned much more about efficiency. As it turns out, subsequent improvements to the compiler and runtime system have pretty much eliminated that concern. I’ve put this issue in our tracking system.

Thanks for your comments.

2 Likes

Looking forward to all the improvements! By interacting with the rig system I simply mean that you could send a MIDI in/out block a message/signal, and it could intelligently decide what to do with it, or if no MIDI block had that GP Script tag in that rackspace then it might be gracefully ignored. I imagine such functionality would be rather niche - the bigger thing would definitely be global scripts, etc.

generally call-by-value but (similar to Java or Smalltalk)

Gotcha. Lazy C++ programmer me was just assuming they were char* based on the way that strings are manipulated - so I was rather surprised when line0 = StringToHexString(line0) decided to repeatedly encode itself every time the function was called :joy:

Thanks for responding - really cool to see how active you all are here.

1 Like

hi rbmj,
attention complete noob here…
i tried your script allthough i had to change from your “Keylab2” to “KeyLab_mkII_49”
i asume that is correct because the compiler is not “arguing”.but now i am stuck as before i can compile i get the error message:
Semantic error: Line 42, Col 27: Identifier not declared: KeyLab_mkII_49
i did not change anything but the name,the line looks like this:
SM_SendMidiOut(SysEx, KeyLab_mkII_49);
i hope i am not doing something basic wrong-i called up the script editor in edit rackspace mode.
thanks for your help

Can you paste your Script?
Did you give the midi out plugin the gpscript handle KeyLab_mkII_49?

i had a typo now it seems correct it is compiling but “says”
Plugin ‘KeyLab_mkII_49’ not found in rackspace ‘emu/jup/modular’…it is not recognising it
do i ha to use the whole “caption” of keylabs midi out? that would be:
MIDI Out (KeyLab mkII 49)

var
KeyLab_mkII_49 : MidiOutBlock;
SysEx : SysexManager;
KeyLab_mkII_49_LCD_PRE : String;
KeyLab_mkII_49_LCD_SEP : String;
KeyLab_mkII_49_LCD_END : String;
ASCII_STRING : String;
ASCII_HEX_STRING : String array;

Initialization
ASCII_STRING = " !"#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[Y]^_`abcdefghijklmnopqrstuvwxyz{|}><";
ASCII_HEX_STRING = [“20”,“21”,“22”,“23”,“24”,“25”,“26”,“27”,“28”,“29”,“2A”,“2B”,“2C”,“2D”,“2E”,“2F”,“30”,“31”,“32”,“33”,“34”,“35”,“36”,“37”,“38”,“39”,“3A”,“3B”,“3C”,“3D”,“3E”,“3F”,“40”,“41”,“42”,“43”,“44”,“45”,“46”,“47”,“48”,“49”,“4A”,“4B”,“4C”,“4D”,“4E”,“4F”,“50”,“51”,“52”,“53”,“54”,“55”,“56”,“57”,“58”,“59”,“5A”,“5B”,“5C”,“5D”,“5E”,“5F”,“60”,“61”,“62”,“63”,“64”,“65”,“66”,“67”,“68”,“69”,“6A”,“6B”,“6C”,“6D”,“6E”,“6F”,“70”,“71”,“72”,“73”,“74”,“75”,“76”,“77”,“78”,“79”,“7A”,“7B”,“7C”,“7D”,“7E”,“7F”];
KeyLab_mkII_49_LCD_PRE = "# F0 00 20 6B 7F 42 04 00 60 01 ";
KeyLab_mkII_49_LCD_SEP = " 00 02 “;
KeyLab_mkII_49_LCD_END = " 00 F7”;
End

Function StringToHexString(str : String) Returns String
var i : Integer
result = “”;

For i=0; i<Length(str) ; i=i+1 Do
result = result + ASCII_HEX_STRING[IndexOfSubstring(ASCII_STRING, CopySubstring(str,i,1), True)];
End
End

Function KeyLab_mkII_49_LCD(line0 : String, line1 : String)
If Length(line0) > 16
Then
line0 = CopySubstring(line0, 0, 16);
End
line0 = StringToHexString(line0);

If Length(line1) > 16
Then
    line1 = CopySubstring(line1, 0, 16);
End
line1 = StringToHexString(line1);


SM_CreateSysexFromString(SysEx, KeyLab_mkII_49_LCD_PRE + line0 + KeyLab_mkII_49_LCD_SEP + line1 + KeyLab_mkII_49_LCD_END); 
SM_SendMidiOut(SysEx, KeyLab_mkII_49);

End

On Activate
var s : String;
s = “Rackspace:”;
KeyLab_mkII_49_LCD(s, GetRackspaceName());
End

You have to give the gpscript handle.
Available via the popup menu you get when your right click with the mouse on the midi out plugin.

1 Like

thank you sir,inow i can continue

1 Like

hmm still does not display anything-gotta dig deeper

On activate is executed when you switch to that rackspace,
Did you do that?

here comes the anfänger : where do i do that?

Just create an additional rackspace and then navigate back to your rackspace

i do have two, both with the arturia midi out and the script enabled

Now when you switch between them, what happens?