sendNrpn broken: workaround

have been using sendNrpn in the past, but now it’s throwing errors:

error running function 'runFunction': ctrlv2/slots/p065.lua:26: bad argument #0 to 'sendNrpn' (number expected, got table)

In line 26 I’ve got the following, which should not generate any error…
midi.sendNrpn(1, 7, 6, 2)

Because the documentation states the following syntax:

midi.sendNrpn(port, channel, parameterNumber, value)

However the doc now mentions 5, not 4 arguments. In what order should they be?
I get other errors if I add a boolean as fifth argument.

A function to send a NRPN MIDI message.

  • port - integer, a port identifier(see Globals for details).
  • channel - integer, a numeric representation of the MIDI channel(1 … 16).
  • parameterNumber - integer, an identifier of the NRPN(0 … 16383).
  • value - integer, a value to be sent(0 … 16383).
  • lsbFirst - boolean, when true, the lsb and msb bytes will be swapped.

I’ve been using the sendNrpn() method posted by someone else for a long time. The Lua version has been broken for a while. The webUI version does work.

function sendNrpn(port, channel, parameter, value)
    local parameterMSB = (parameter >> 7) & 0x7F
    local parameterLSB = parameter & 0x7F
    local valueMSB = (value >> 7) & 0x7F
    local valueLSB = value & 0x7F

    local messages = {
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 99, value = parameterMSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 98, value = parameterLSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 6, value = valueMSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 38, value = valueLSB}
    }

    for i, msg in ipairs(messages) do
        midi.sendMessage(port, msg)
    end
1 Like

Thanks,

the workaround is very usable.
For those who want to use it: then swap ‘midi.sendNrpn’ for sendNrpn’

sendNrpn is fixed in the upcoming release. I have added extra parameters to change order of bytes and including the reset bytes. The documentation will be updated.

1 Like

Hi, sendNrpn is still broken but it’s a bit functional now:

  • I had to add a dummy argument as argument 1 to make it work.
  • the two loast arguments do not expect a boolean, so I changed them to 0 and 1
  • It doesn’t respond to the reset 0/1 option. The reset CC 100 and 101 are always sent.

Hi, is there a way to override the standard sendNrpn function for a bespoke one?

I tried this at the start of the script, to no avail.

local originalSendNrpn = midi.sendNrpn  -- keep original
function mySendNrpn(port, channel, parameter, value)
    print("Custom NRPN code")
    local parameterMSB = (parameter >> 7) & 0x7F
    local parameterLSB = parameter & 0x7F
    local valueMSB = (value >> 7) & 0x7F
    local valueLSB = value & 0x7F
    local messages = {
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 98, value = parameterLSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 99, value = parameterMSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 6, value = valueMSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 38, value = valueLSB}
    }
    for i, msg in ipairs(messages) do
        midi.sendMessage(port, msg)
    end
end

_G.midi.sendNrpn = mySendNrpn

Martin may have that answer, but my only thought is to put the call into the custom version in each control (and have those controls be virtual)

I did that before, but it’s a lot of work if first the preset is made and only afterwards you find out the default NRPN for that particalur preset isn’t quite what you need.

Thanks anway :slight_smile:

I have fixed the sendNrpn function. The fix will be released in the upcoming release. The issue was caused by the optional interface parameter that was not included in your call. The fix covers both calling the function with and without the optional parameter.

regarding the function overriding, you can do that like this:

function midi.sendNrpn(port, channel, parameter, value)
    print("sendNrpn")
end

midi.sendNrpn(1, 7, 6, 2)

It works for any function. Any standard function can be overridden by redefining it in the global context.

weird

I thought I tried that before going the more complex way. I’ll surely try again now :slight_smile:
Thanks Martin!