I’m using the radio buttons script and would like to send specific CC’s ONLY for the button that is ON (value 1.0). Currently in the script, the widget values are grouped together. In my case S1, S2, S3 and S4. I’m only pasting the 2nd half of the radio buttons code for this example. Is there a way to send CC11 when S1 is active, CC12 when S2 is active, CC13 when S3 is active and CC14 for S4? I can’t do another On WidgetValueChanged for those buttons since they have all been declared already. Does the code have to be ungrouped and do individual On WidgetValueChanged for each button? Or is there a way to incorporated into this neat grouped call?
var
sceneblock : MidiInBlock
S1, S2, S3, S4 : Widget
//Radio Buttons: Called when any of several widgets changed
On WidgetValueChanged(w : Widget, index: integer, newValue : double) from S1, S2, S3, S4
var i : integer
if newValue == 1.0 and index <> u_last then
// Deselect other buttons
for i = 0; i < Size(u_buttons); i = i + 1 do
if i <> index then SetWidgetValue(u_buttons[i],0.0)
end
end
u_last = index
end
//Radio Buttons: Prevent a button to be switched off manually
If newValue == 0.0 and index == u_last Then
SetWidgetValue(u_buttons[index],1.0)
End
If newValue == 1.0 Then
end
End
Took a bit of searching, but finally got it working, but its sending the same CC messages (at the bottom of script) twice. Why?
var
sceneblock : MidiInBlock
CC : ControlChangeMessage
S1, S2, S3, S4 : Widget
A : double
B : double
C : double
D : double
// Radio Buttons: buffer variables to store the last pressed button
u_last : Integer
//Radio Buttons:Declaration of widget arrays for upper and lower preset buttons
u_buttons : Widget Array = [S1, S2, S3, S4]
initialization
//Radio Buttons: Called on first run
var i : Integer
//Check & store state of buttons - if all off, assume the first as "ON"
For i = 0; i < Size(u_buttons); i = i + 1 Do
If GetWidgetValue(u_buttons[i]) == 1.0 Then
u_last = i
Else
u_last = 0
End
End
End
//Radio Buttons: Called when any of several widgets changed
On WidgetValueChanged(w : Widget, index: integer, newValue : double) from S1, S2, S3, S4
var i : integer
if newValue == 1.0 and index <> u_last then
// Deselect other buttons
for i = 0; i < Size(u_buttons); i = i + 1 do
if i <> index then SetWidgetValue(u_buttons[i],0.0)
end
end
u_last = index
end
//Radio Buttons: Prevent a button to be switched off manually
If newValue == 0.0 and index == u_last Then
SetWidgetValue(u_buttons[index],1.0)
End
//Send CC for scene
A = GetWidgetValue(S1)
If A == 1.0 Then
CC = MakeControlChangeMessage(11, 127)
SendNow(sceneblock, CC)
End
//Send CC for scene
B = GetWidgetValue(S2)
If B == 1.0 Then
CC = MakeControlChangeMessage(12, 127)
SendNow(sceneblock, CC)
End
//Send CC for scene
C = GetWidgetValue(S3)
If C == 1.0 Then
CC = MakeControlChangeMessage(13, 127)
SendNow(sceneblock, CC)
End
//Send CC for scene
D = GetWidgetValue(S4)
If D == 1.0 Then
CC = MakeControlChangeMessage(14, 127)
SendNow(sceneblock, CC)
End
End
All that work and seems the state of the radio button widgets in the variations are lost when switching rackspaces??? They work when switching variations WITHIN the same rackspace, but when switching to another rackspace and back, the button states are lost and the 1st button is ON in all variations. Ignore variations is OFF.
Well, I’m talking to myself here, but maybe this will help someone and wanted to post the solution. Much simpler… works like “radio buttons” and state is remembered when switching rackspaces (and only sending CC’s once ;)).
Var
S1 : Widget
S2 : Widget
S3 : Widget
S4 : Widget
CC : ControlChangeMessage
sceneblock : MidiInBlock
On WidgetValueChanged(newValue : double) from S1
if newValue == 1.0 then
CC = MakeControlChangeMessage(11, 127)
SendNow(sceneblock, CC)
SetWidgetValue(S2,0.0)
SetWidgetValue(S3,0.0)
SetWidgetValue(S4,0.0)
End
End
On WidgetValueChanged(newValue : double) from S2
if newValue == 1.0 then
CC = MakeControlChangeMessage(12, 127)
SendNow(sceneblock, CC)
SetWidgetValue(S1,0.0)
SetWidgetValue(S3,0.0)
SetWidgetValue(S4,0.0)
End
End
On WidgetValueChanged(newValue : double) from S3
if newValue == 1.0 then
CC = MakeControlChangeMessage(13, 127)
SendNow(sceneblock, CC)
SetWidgetValue(S1,0.0)
SetWidgetValue(S2,0.0)
SetWidgetValue(S4,0.0)
End
End
On WidgetValueChanged(newValue : double) from S4
if newValue == 1.0 then
CC = MakeControlChangeMessage(14, 127)
SendNow(sceneblock, CC)
SetWidgetValue(S1,0.0)
SetWidgetValue(S2,0.0)
SetWidgetValue(S3,0.0)
End
End
When you are using the multi-widget callbacks, you need to keep in mind that the callback will be triggered when any of the widgets change. So it will also be triggered for the radio button that gets switched OFF when another button is clicked e.g. every radio button that gets clicked will generate two callbacks - one for itself (when it’s clicked), and one for the prior button that is switched off.
In your earlier code, the part that was checking the widget value for each switch (to then send the CC message) did not do any checks for which scenario triggered the callback. And was therefore sending the CC message on both occasions.
One of the benefits of the multi-widget callback, is the ability to use the widget index in combination with arrays, to make things more efficient. In your use-case, an array could be used to hold the CC numbers you want linked to each radio button. It makes the code to send the CC message very simple.
Var
sceneblock : MidiInBlock
// Radio Buttons
S1, S2, S3, S4 : Widget
u_buttons : Widget Array = [S1, S2, S3, S4]
u_cc_msgs : Integer Array = [11, 12, 13, 14]
u_last : Integer = 0
//Radio Buttons: Called when any of several widgets changed
On WidgetValueChanged(w : Widget, index: integer, newValue : double) from S1, S2, S3, S4
var i : integer
if newValue == 1.0 and index <> u_last then
// Send the CC message
SendNow(sceneblock, MakeControlChangeMessage(u_cc_msgs[index], 127))
// Deselect other buttons
for i = 0; i < Size(u_buttons); i = i + 1 do
if i <> index then
SetWidgetValue(u_buttons[i], 0.0)
end
end
u_last = index
end
//Radio Buttons: Prevent the active button being de-selected if clicked again
if newValue == 0.0 and index == u_last then
SetWidgetValue(u_buttons[index], 1.0)
end
End
NOTE: you probably want to keep the code that you had in the Initialization section, as it is identifying the widget that was selected when you last saved the gig (will prevent the button being reset to the first one when you open the gig).
I get that 2 buttons are being triggered, but only one of them will have the value of 1.0 right? The code said if the value is 1.0 then send CC. So while two buttons are changing states, I would expect that only one of them (1.0) would trigger the CC. Am I not understanding this correctly?
Thanks for the explanation on sending the rest of the code. I will look at it later when I’m home.
//Send CC for scene
A = GetWidgetValue(S1)
If A == 1.0 Then
CC = MakeControlChangeMessage(11, 127)
SendNow(sceneblock, CC)
End
This code you had is not checking which widget was just clicked, and will evaluate as true on the S1 callback (if it was just clicked) as well as the second callback for whatever other button was just switched off.
Got it. So the code is basically saying when S1 is 1.0, send CC, but at that moment 2 events happen and it is sending for both. Ah! I thought it would only send it for the event that equals 1.0. Got it! Thanks!
This code is so elegant and short! Like it! The problem is the same as with the original code, it doesn’t stick when switching to variations or other rackspaces. It would probably be OK as is in the global rackspace. is there a way to save the widget state just like any other regular widget?