Thanks to all who assisted above!
I have arrived at a scriptlet that works well for me.
Here it is:
/*
Scriptlet: PC Knob Final Value 01a (Sends PCs)
Written to pair with a knob widget, an Incr widget, and a Decr widget
This code always sends the final value for the connected knob, but not all the values in-between as the knob is turned.
This can be very helpful if gear downstream doesn't respond all-so-well to a blast of multiple program change messages (PCs).
Note: Results are timer-based. if you twist the connected widget knob slowly, then some intermediate values will go out at
intervals of SnapShot_Time_ms. SnapShot_Time_ms is a Parameter, so you can control it also via widge if you like, or else
just accept the value compiled from the code here.
Use Case #1: Sending PCs to BIAS FX plugin to select guitar patch presets
01a (Progster, 20240916) Initial version
*/
var
ProgramChangeNumber ("Program"): Subrange Parameter 0 .. 127 = 0
Decr : Parameter 0..1 = 0
Incr : Parameter 0..1 = 0
// specify a nominal 500ms ramp - we will wait for it's completion for-to-send the PC
SnapShot_Time_ms : Parameter 0..2000 = 500
Last_PC_Sent : Integer = 0
PC_Ever_Sent : Boolean = False
Waiting_For_Ramp : Boolean = False
MyRamp : Ramp
Ramp_Start_Time: Double
Ramp_End_Time: Double
Ramp_Elapsed_Time : Double
function SendPchange( PC : Int )
if ( PC <> Last_PC_Sent ) then // never send the same PC twice in a row
//Print( "Called SendPchange: " + PC )
SendNow( MakeProgramChangeMessage(PC) ) // PC message on Ch 1
Last_PC_Sent = ProgramChangeNumber
Print( "Last_PC_Sent: " + Last_PC_Sent )
end
end
On GeneratorEndCycle(timeX : integer) from MyRamp
Ramp_End_Time = TimeSinceStartup()
Ramp_Elapsed_Time = Ramp_End_Time - Ramp_Start_Time
//Print( "Ramp Finished: " + TimeSinceStartup() + " Ramp Elapsed time: " + Ramp_Elapsed_Time )
// Send Out PC message
SendPchange( ProgramChangeNumber ) // ProgramChangeNumber is always most current one as provided by the connected knob widget
// reset to "neutral" state
Waiting_For_Ramp = False
End
// ParameterValueChanged callbacks
On ParameterValueChanged matching ProgramChangeNumber
// If in the "neutral" state, start a new Ramp to wait for
if ( !Waiting_For_Ramp ) then
Ramp_Start_Time = TimeSinceStartup()
TriggerOneShotRamp(MyRamp, SnapShot_Time_ms, 10)
//Print( "Ramp Started: " + Ramp_Start_Time + " SnapShot_Time_ms: " + SnapShot_Time_ms )
Waiting_For_Ramp = True
end
End
// Act on change of connected widget used for Increment of preset
On ParameterValueChanged matching Incr
ProgramChangeNumber = Last_PC_Sent
//Print( "ParameterValueChanged matching Incr " + Incr )
if (Incr == 1) and (Last_PC_Sent < 127) then
//Print( " Incr button" )
ProgramChangeNumber = ProgramChangeNumber + 1
SendPchange( ProgramChangeNumber )
Last_PC_Sent = ProgramChangeNumber
end
End
// Act on change of connected widget used for Decrement of preset
On ParameterValueChanged matching Decr
ProgramChangeNumber = Last_PC_Sent
//Print( "ParameterValueChanged matching Decr " + Decr )
if (Decr == 1) and (Last_PC_Sent > 0) then
//Print( " Decr button" )
ProgramChangeNumber = ProgramChangeNumber - 1
SendPchange( ProgramChangeNumber )
Last_PC_Sent = ProgramChangeNumber
end
End
And here is a short video demo of it in action: