Scriptlet MidiInBlock var not compiling

Hi there, new to gigperformer and scriptlets. a bit of context: I’m trying to hack around my weird keyboard setup. Basically, I want to use my keyboard’s onboard tonewheel sounds, but also use it to control VSTs and it turns out that the best way to turn off the internal organ sound is to set its drawbars to zero. So I’ve got a script that monitors the drawbar positions (controlchangeevents) and stores the values in an array, and I want it to send all those cc’s to zero when I switch a widget; when I switch the widget back, it should restore those cc’s to the values in the array.
I suppose the best way is to have this script respond to the widget is to have the widget produce midi to the Local GP port. (is that right?)
So I want my script to listen to both the real midi in from my organ, and the local gp port. So I want to declare two MidiInBlocks at the top of my script, but when I hit “compile” I always get the error
organ toggle (Script Entity: Scriptlet) - owned by rackspace: Rackspace - Semantic error in “Main”: Line 2, Col 13: Allowed in rackspace script only. This type is only allowed in rackspace scripts

How do I resolve this? Is a “rackspace script” some other sort of script that I should be writing instead? I’m creating this from the wiring view of my rackspace.

Thanks, Jez.

What keyboard?

I do something similar with my Casio CTK-7200.

But, I think the preferred way is to route the audio from the keyboard into GP and set if for “local off”. Then you can keep from triggering sounds on your hardware keyboard easily (I think by just not running any midi out to the keyboard.)

A scriptlet is essentially just another plugin, and as such is unaware of other blocks and plugins in the rackspace—just like your Delay plugin knows nothing about your Reverb plugin. It only processes the data it receives, it can’t discriminate where that data comes from. So that’s why you can’t declare your MIDI In blocks as variables to use in a scriptlet. If you want to do that, you’ll want to make a Rackspace (or Global Rackspace) script instead of a scriptlet.

125

1 Like

Couldn’t have explained it better than @edm11. And with @jeffn1’s suggestion you have even another option to choose from.

If you want to do it your way then it’s the exact same that I do (but for lights).
So I’d go for a scriptlet, too. You can just connect it between the MIDI input from the organ and the MIDI output block to the organ. Just make sure to “block unhandled messages”.

You declare a parameter and map your widget to that parameter. The script will send the necessary CCs to the organ if the parameter (mapped widget) is “mute” or send the saved values from the array if the parameter is “live”.

Here’s the missing part for your scriptlet:

var
    Mode : discrete parameter "mute", "live" = "mute"

On ParameterValueChanged matching Mode
    Select
        Mode == "mute" do
            SendNow(...) // Here go your reset control change messages
        Mode == "live" do
            SendNow(...) // Here go your control change messages recalled from the array
    End
End

Will you be able to do the saving of the values into and sending the recalled values from an array?

Many thanks everyone! Looking forward to trying these ideas when I get a moment.
@edm11 that makes sense, I’ll definitely try creating this as a rackspace or global rackspace script. Then I can declare the two midi in blocks? Out of interest, could I make a scriptlet with two midi inputs, and wire it up that way? @Florian So that’s a way around reading the state from the local GP port? So the scriptlet doesn’t know about the widget (I think that’s not permitted either), it knows about the parameter… I think that’s something I’ve not tried yet as well.

@jeffn1 short version: it’s a numa organ 2. Long version: it’s screwed into a chassis with a controller keyboard underneath to make it a 2-manual organ. I want to be able to switch the upper or lower manuals over to a VST independently, “local off” would turn off both manuals. btw, I love gigperformer. I only have one set of hardware drawbars to cover both manuals, and as a newcomer I fairly quickly set up a panel with a set of drawbar controls so I can see/control both manuals at the same time :slight_smile: This hack I’m trying to implement deservedly has a bit more of a learning curve…
I’ll let you know how it turns out!
Jez.

Welcome. Yeah, you’re right and there’s no need to declare anything with your idea of using a scriptlet!

With this method you’ve just created your custom plugin (that’s what a scriptlet is) in the global rackspace that can directly take midi in and outputs from and to wherever you want (and as many as you want).
With the line “Mode : discrete parameter…” you’ve designed this plugin with exactly one automation parameter that a widget can directly access and whose state the script inside the scriptlet knows about.
The storage of the incoming values into an array would also live inside this scriptlet.

Yes. So it’s basically the other way round: Not the scriptlet needs to know about the widget - the widget links to the parameter of the scriptlet.

The cool thing is: If you assign a MIDI controller to this widget, you can remotely mute or unmute the organ.
Or, to advance even further, if you link widgets in your local rackspaces to this widget in the global rackspace, you could even automate the mute status depending on the variation!

With this additional info, you could simply add a second parameter in the scriptlet (one for each manual).

By the way:

Could you please share a picture of your controllers? I love building such things myself.

If it is a Numa Organ 2, it is probably not the best way. You have basically 3 modes in the NO2 that you can change using the MIDI LED button (Local On with no MIDI, Local On with MIDI and Local Off with MIDI, as far as I remember). Choosing the right mode is on or two pushes on this button which is probably easier than changing the Drawbars. But, I perhaps missed something.

To get a better help, I think you should rather expose clearly what you would like to achieve rather then exposing a complicated scripting solution. In many situations you don’t need scripting, even if it is fun.:nerd_face: And in the present situation I don’t see the benefit of using scripting.

Credit to the previous owner!

It’s a slightly clunky solution but I couldn’t justify the expense of a crumar or viscount. (the dmc-122 is my dream control keyboard!) Also, nice thing about this is I have the original side-cheeks so I can dismantle it and use the standard numa as a top board over my piano for a less insane setup… but most of what I’m doing atm is featuring the organ, so I think it’s nice to give the audience something intimidating to look at :wink:

1 Like

Putting the organ in “local off” mutes the organ from both manuals, which I don’t necessarily want. Only way to have upper manual on organ and lower manual on clavs or something is to zero all the lower drawbars. I’ll be leaving the organ in Local On with Midi.
My constraints are fairly unique to this hardware setup, so I thought it’d be easier to jump into the scripting problem – I didn’t expect a response from anyone as familiar with the numa as you are!

How cool is that! :+1:

I tried to build something around the Studiologic SL73 with a monitor and room for two iPads but the quality of the keyboard turned out to be so bad that I couldn’t use it very long before various keys stopped triggering. :man_shrugging:

1 Like

I think I better understand what you want to do and of course the very bad MIDI implementation of the NO2 doesn’t help for what you want to do. If I understand well your issue is mainly related to the upper keyboard, i.e. the NO2 itself. You want to be able to play a VST from the NO2 without hearing the upper organ sound, while the lower organ sound (on CH 2 in the NO2) is playing. So you cannot mute or change the global volume of the NO2, when you don’t want to their the upper organ sound.

So the solution you imagine is to have a Scriptlet always memorizing the current hardware drawbars setup in order to recover it when needed and set all drawbar to 0 in the internal sound module without changing the physical drawbars when you need to mute the sound. Do I understand well?

Yes, that’s right. Also the other way round (top manual organ, lower manual VST). I’m hopeful that a combination of @Florian’s suggestions with what I’ve got already will work out well :slight_smile:

Do you have the necessary programming skills or do you need some help?

By the way take care of the NO2 MIDI implementation. It is quite easy to create MIDI loops when using both MIDI IN and OUT, because as far as I remember MIDI OUT acts like a MIDI THRU… don’t ask me why! :face_with_diagonal_mouth:

I should be ok, the main issue is snatching some time to work on it between work and family… I’ll post my solution for you guys to critique when I get it working.

2 Likes

Had an hour this morning to look at this. I’ve got muting working (see below), and I’m using a separate scriptlet for each manual. Thanks very much for all your suggestions! (Slight frustration that I couldn’t work out how to use User Variables for non-strings, would have been handy to define a couple of integers for multiple instances of closely related scripts like this).

This works for muting the manuals, but what I want to implement now is a selector widget (for each manual) to switch between organ and an arbitrary list of soft instruments, ie one widget controlling both the mode parameter on this scriptlet, and also toggling the bypass on a bunch of other VSTs (or rather, midi filters).

Do I need another (rack?) script to handle this?

working drawbar mute script:

Var
  mode : discrete parameter "mute", "live" = "live"
  draws : integer Array = [0,0,0,0,0,0,0,0,0]
  chan : integer = 1
  
On ControlChangeEvent(m : ControlChangeMessage) Matching[12..21]
  var cc : integer = m.GetCCNumber()
  SetDisplayMessage("Received cc " + cc + ", " + Size(draws))
    if cc < 12 + Size(draws) then

    Select
      mode == "mute" do
        SendNow(MakeControlChangeMessageEx(cc, 0, chan))
      mode == "live" do
        draws[cc-12] = m.GetCCValue()
    End
  End
End

On ParameterValueChanged matching mode
  var i : integer
  Select
    mode == "mute" do
      for i=0; i<Size(draws); i = i+1 do
        SendNow(MakeControlChangeMessageEx(i+12, 0, chan))
      End
    mode == "live" do
      for i=0; i<Size(draws); i = i+1 do
        SendNow(MakeControlChangeMessageEx(i+12, draws[i], chan))
      End
  End
End

Looks like you’ve done a good job so far. I’ll be heading off to a gig in a minute so I hope I’ll get it right.

Let’s optimize the capturing part of the CC values (12-20, not 21?). I see no reason why you should monitor the drawbars’ states depending on the “mode” setting. I would just continuously capture their position and store this into the array. So this could be simplified and we always now the latest drawbar setting.

var 
    draws : Integer[9]   // creates an array with 9 positions
On ControlChangeEvent(m : ControlChangeMessage) Matching [12..20]
     draws[GetCCNumber(m)-12] = GetCCValue(m)   // stores the CC Value in one of the 9 positions (starting with 0)
End

(Please note I also simplified the declaration of the array)

It’s working fine - just tried it. :+1:

Thanks for your help with this.

May I make a couple of programming selections that might be convenient?

Why not just declare an array that contains 21 values and you’ll only care about the last 9 but that will let you write things like this


draws : Integer[21]  

draws[GetCCNumber(m)] = GetCCValue(m)

and you don’t have to worry about dealing with that -12 all over the place

1 Like