Only send CC if button value is 1.0

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
2 Likes

I can see why the earlier script was sending the CC twice. But glad you figured it out.

BTW it will make it so much easier to read if you select the script/text and use the code format icon </> when posting :wink:

1 Like

Thanks for the tip, I will use it next time. :slight_smile:

Can you share why it was sending it twice? Thanks!

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).

2 Likes

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.

2 Likes

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! :slight_smile: 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?