# New Cabbage widget opcodes

**URL:** <https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388>\
**Category:** Announcements\
**Created:** [20 March 2021 15:44 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388 "2021-03-20T15:44:48Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [20 March 2021 15:44 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/1 "2021-03-20T15:44:48Z")

</div>

I’ve pushed through the latest changes. They are available now in Azure. Note that in order to use these you should add `guimode("queue")` to your form definition. Below is a quick rundown of new opcodes, and [here](https://www.youtube.com/watch?v=3Y7kkfUmZsw) is a short video overview of them in action.

* * *

**cabbageSet** _kTrig, SChannel, SIdentifier, XArgs_  
**cabbageSet** _kTrig, SChannel, SIdentifierString_  
**cabbageSet** _SChannel, SIdentifierString_

Sets/updates widget identifiers whenever kTrig is 1, or if you leave out the kTrig, it will set it at i-time. Identifiers can be updated by passing arguments to a single identifier, as show below. You can also set multiple identifiers as a single string.

**Example:**

```
cabbageSet metro(1), "image1", "colour", random:k(0, 255), random:k(0, 255), random:k(0, 255)
cabbageSet metro(1), "image1", "colour(255, 0, 0), bounds(10, 10, 100, 100)"

```

* * *

**cabbageSetValue** _SChannel, kValue [, kTrig]_

Set the value of a widget, for example the value of a slider, or combobox. kTrig is optional. If left out, this will update on every k-cycle.

**Example:**

```
cabbageSetValue "tempo", random:k(1, 100)

```

Let me know how you get on. I’ve not tested these thoroughly yet. Some identifiers might not work yet, but just let know and I will sort them out asap.

* * *

_kValue_ **cabbageGetValue** _SChannel_  
_SValue_ **cabbageGetValue** _SChannel_  
_iValue_ **cabbageGetValue** _SChannel_  
_kValue [, kTrig]_ **cabbageGetValue** _SChannel_  
_SValue [, kTrig]_ **cabbageGetValue** _SChannel_

Gets the current value of a widget, for example the current value of a slider, combobox, button, etc. You can optional an a trigger output variables, which will send a trigger signal of 1 whenever the value has changed.

Example:

```
kButtonValue, kTrig cabbageGetValue "mute"

```

* * *

_kIdent_ **cabbageGet** _SChannel, SIdentifier_  
_SIdent_ **cabbageGet** _SChannel, SIdentifier_  
_kIdent[]_ **cabbageGet** _SChannel, SIdentifier_  
_SIdent[]_ **cabbageGet** _SChannel, SIdentifier_  
_kIdent [, kTrig]_ **cabbageGet** _SChannel, SIdentifier_  
_SIdent [, kTrig]_ **cabbageGet** _SChannel, SIdentifier_

_kChannelValue_ [, kTrig] **cabbageGet** _SChannel_  
_kChannelValue_ **cabbageGet** _SChannel_  
_SChannelValue_ [, kTrig] **cabbageGet** _SChannel_  
_SChannelValue_ **cabbageGet** _SChannel_

Use to get the current value of an identifier. For example, the button text for a particular widget, or the colour of a widget. Widget must have a channel name specified. Where only a single value is passed to this widget, it will query a plain old channel. For example, you use it with the CURRENT\_WIDGET reserved channel to find out which widget is currently in focus:

```
SChannel, kTrig cabbageGet "CURRENT_WIDGET"
printf SChannel, kTrig

```

* * *

**cabbageCreate** _SCabbageCodeString_

Used to create a Cabbage widget at init-time. (only works at init-time!)

Example:

```
cabbageCreate SWidget "rslider bounds(10, 10, 100, 100) channel(\"slider1\")"

```

If you create your GUI using this opcode, you will no longer have any control over them using the Cabbage GUI editor.

---

<div class="post-metadata">

**Author:** ![t\_grey](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/t_grey/32/1234_2.png) [@t\_grey](https://forum.cabbageaudio.com/u/t_grey)\
**Post date:** [22 March 2021 00:25 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/2 "2021-03-22T00:25:44Z")

</div>

Awesome Rory! I’m not going to get a chance to start playing with this until tomorrow… but I had a quick question:

> [@rorywalsh](#):
>
> guimode(“queue”)

Does claiming this mode disable regular identchannels, or can both be used in a “hybrid” sense?

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [22 March 2021 08:51 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/3 "2021-03-22T08:51:31Z")

</div>

It’s one or the other I’m afraid. Well, it would be possible to have both enabled, but I think that it would need to be strictly for debugging and testing purposes? I could add a ‘hybrid’ option, but it’s not something I’d be putting in the docs!

---

<div class="post-metadata">

**Author:** ![t\_grey](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/t_grey/32/1234_2.png) [@t\_grey](https://forum.cabbageaudio.com/u/t_grey)\
**Post date:** [24 March 2021 10:38 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/4 "2021-03-24T10:38:32Z")

</div>

> [@rorywalsh](#):
>
> It’s one or the other I’m afraid. Well, it would be possible to have both enabled, but I think that it would need to be strictly for debugging and testing purposes?

Well, especially with regards to imported widgets… I see a real benefit in having the behavior potentially be hybrid. For example, if I make an importable widget that uses a gentable, I’ll be forced to use the new method… but that prevents anyone from easily importing into existing projects, at least without a complete overhaul.

Plus… with a massive project with tons of includes and imports (sound familiar? 😇) a hybrid behavior would allow incremental conversion and testing, rather than just going all in and hoping for the best (and struggling to find which change I messed up)

Just my two cents on it at least.

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [24 March 2021 10:42 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/5 "2021-03-24T10:42:58Z")

</div>

I can add a custom option then, but it will not be very efficient and will be a waste a CPU. But if you only ever plan to use it for testing it should be fine. Btw, have you thought at all about replacing any of the custom plant stuff with UDOs? I must try this myself and see how feasible it is. I like the idea of having all the code centralised.

---

<div class="post-metadata">

**Author:** ![t\_grey](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/t_grey/32/1234_2.png) [@t\_grey](https://forum.cabbageaudio.com/u/t_grey)\
**Post date:** [24 March 2021 10:55 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/6 "2021-03-24T10:55:21Z")

</div>

Well, I definitely think it’s worth having it, even if it’s documented as being functional but inefficient and not recommended for most cases.

But yes… that’s an incredibly interesting thought that hadn’t crossed my mind at first, until the through the looking glass example. Unfortunately I’ve just been getting caught up with other things the past few days and still haven’t had a chance to get a new beta, nevermind actually run it and test stuff.

Another use case I wanted to look into, detecting the total cabbage window size? I’m guessing that would be a possibility here, right?

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [24 March 2021 10:58 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/7 "2021-03-24T10:58:01Z")

</div>

> [@t\_grey](#):
>
> Another use case I wanted to look into, detecting the total cabbage window size? I’m guessing that would be a possibility here, right?

Yes, no issues there.

> [@t\_grey](#):
>
> Unfortunately I’ve just been getting caught up with other things the past few days and still haven’t had a chance to get a new beta, nevermind actually run it and test stuff.

Let me take one of the numerous examples we shared from way back and see how it runs as a UDO. I’ll let you know 🙂

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [24 March 2021 15:46 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/8 "2021-03-24T15:46:41Z")

</div>

Yeah, it works quite well.

 ![Screen Shot 2021-03-24 at 15.44.18](https://forum.cabbageaudio.com/uploads/default/original/2X/0/085eb66ee2b43623a7d4598df39fbed23976d07e.png)

Hmm. This is quite nice. At long last we can combine the GUI stuff directly with the DSP stuff. It would be trivial to write a UDO that would create a generic UI for an orchestra. That could be useful for prototyping.

---

<div class="post-metadata">

**Author:** ![t\_grey](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/t_grey/32/1234_2.png) [@t\_grey](https://forum.cabbageaudio.com/u/t_grey)\
**Post date:** [30 March 2021 09:26 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/9 "2021-03-30T09:26:43Z")

</div>

This does look quite impressive! Tomorrow I’m finally going to update and play with a few simple examples and ideas to try to get myself used to it.

What’s the final word on a hybrid behavior? I can’t even imagine trying to convert my entire project from identchannels in one go… 😰

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [30 March 2021 13:53 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/10 "2021-03-30T13:53:41Z")

</div>

Sorry, I will try to add that asap..

I’ve added this now. just don’t forget about the new camelCase restrictions. You need to do  
`guiMode("hybrid")`  
Btw, I have tested this, but it should work as all mechanisms get called in this instance. 👍

---

<div class="post-metadata">

**Author:** ![cybilopsin](https://forum.cabbageaudio.com/letter_avatar_proxy/v4/letter/c/c5a1d2/32.png) [@cybilopsin](https://forum.cabbageaudio.com/u/cybilopsin)\
**Post date:** [30 March 2021 20:34 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/11 "2021-03-30T20:34:26Z")

</div>

Hello Rory and congrats on the new features. I think it’s great. One thing, what can we do with texteditor widgets now?

`cabbageSetValue “myTextEditorChn”, SmyString`

does that work to fill a text editor and what about

`cabbageSet metro:k(1), “myTextEditorChn”, “file”, “read-100.txt”`

Also i don’t get cabbageCreate yet, but I wanted that feature. How many input arguments does the opcode take on the right?

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [31 March 2021 09:06 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/12 "2021-03-31T09:06:18Z")

</div>

> [@cybilopsin](#):
>
> One thing, what can we do with texteditor widgets now?
> 
> `cabbageSetValue “myTextEditorChn”, SmyString`

best to do it like this (i-time - I just added this now, will be available in Azure shortly..):

`cabbageSet "myTextEditorChn", "text", "post this to the text editor"`

or (k-time)

`cabbageSet metro(1), "myTextEditorChn", "text", "post this to the text editor"`

> [@cybilopsin](#):
>
> and what about
> 
> `cabbageSet metro:k(1), “myTextEditorChn”, “file”, “read-100.txt”`

This is now possible too, if you use the latest beta, which is building as I type..

> [@cybilopsin](#):
>
> How many input arguments does the opcode take on the right?

Just the one. Here’s a few different ways of using it. The method using {{'s is handy because you don’t have to escape quotation marks:

```
instr 1
    //using {{'s
    cabbageCreate {{ 
    rslider bounds(10, 10, 100, 100), channel("test")
    }}

    //using sprintf to dynamically create the Cabbage code
    SCode = sprintf("rslider bounds(%d, %d, 100, 100)", 50, 50)
    cabbageCreate SCode

    //using "s
    cabbageCreate "rslider bounds(200, 200, 100, 100)"
endin

```

---

<div class="post-metadata">

**Author:** ![Samo](https://forum.cabbageaudio.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@Samo](https://forum.cabbageaudio.com/u/Samo)\
**Post date:** [9 April 2021 18:33 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/13 "2021-04-09T18:33:27Z")

</div>

I’m trying to learn and translate some code to the new `guiMode("queue")` and I have a few questions (for now).

Having these widgets:

```
<Cabbage>
form caption("test CabbageSetGet") size(300, 250) colour(58, 110, 182) pluginId("tcsg") guiMode("queue") 
rslider bounds(4, 28, 120, 120) range(1, 2000, 200, 1, 1) channel("Frq") popupText("0") colour(200, 200, 100, 255) trackerColour(200, 200, 100, 255)
button bounds(126, 20, 65, 65) latched(0) channel("X2") text("x2","x2") value(0) corners(3) colour:0(255, 0, 0, 255) colour:1(255, 255, 0, 255) fontColour:0(0, 0, 0, 255) fontColour:1(160, 0, 0, 255)
button bounds(126, 88, 65, 65) latched(0) channel("X05") text("/2","/2") value(0) corners(3) colour:0(0, 255, 0, 255) colour:1(255, 255, 0, 255) fontColour:0(0, 0, 0, 255) fontColour:1(160, 0, 0, 255)
<Cabbage>

```

This works fine:

```
kTrig2 = trigger(cabbageGetValue:k("X2"), .5, 0)
cabbageSet kTrig2, "Frq", "trackerColour(255, 0, 0, 255), markerColour(255, 0, 0, 255)"

```

but not these:  
`cabbageSet kTrig2, "Frq", "markerColour", 100, 0, 0, 255`  
nor  
`cabbageSet kTrig2, "Frq", "trackerColour", 0, 100, 0, 255`

Having these widgets:

```
filebutton bounds(154, 190, 70, 14) channel("SaveAs") mode("save") value(0) text("SAVE AS", "SAVE AS") corners(3) colour:0(100, 0, 0, 255) colour:1(255, 255, 0, 255) fontColour:1(160, 0, 0, 255)
filebutton bounds(76, 190, 70, 14) channel("Browse") value(0) text("BROWSE", "BROWSE") corners(3) colour:0(140, 200, 30, 255) colour:1(255, 255, 0, 255) fontColour:0(160, 0, 0, 255)

```

I used to:

```
S_SaveFileName chnget "IO_SaveAs"
S_LoadFileName chnget "IO_Browse"

```

but how do I get the strings now? What is the `SIdentifier` in this case?  
`S_SaveFileName cabbageGet "IO_Browse", SIdentifier?`

`S_SaveFileName cabbageGetValue "IO_Browse"` doesn’t work.

Another thing I just wanted to check if I got it right: If I use the two buttons above to change the Frq value and update the slider, I shall do something like this:

```
kFrq = cabbageGetValue:k("Frq")
kTrig2 = trigger(cabbageGetValue:k("X2"), .5, 0)
kTrig05 = trigger(cabbageGetValue:k("X05"), .5, 0)

if kTrig2 == 1 then
    kFrq *= 2   
    cabbageSetValue "Frq", kFrq
elseif kTrig05 == 1 then
    kFrq *= 0.5   
    cabbageSetValue "Frq", kFrq
endif
chnset kFrq, "Frq"

```

or

```
if kTrig2 == 1 then
    chnset kFrq*2, "Frq"
elseif kTrig05 == 1 then
    chnset kFrq*0.5, "Frq"
endif
cabbageSetValue "Frq", kFrq, changed:k(kFrq)

```

So, I need to send a message to the channel and the widget. Is this the optimal way to deal with this (if I want to update both) or would you have other suggestions?

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [10 April 2021 10:44 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/14 "2021-04-10T10:44:38Z")

</div>

> [@Samo](#):
>
> but not these:  
> `cabbageSet kTrig2, "Frq", "markerColour", 100, 0, 0, 255`  
> nor  
> `cabbageSet kTrig2, "Frq", "trackerColour", 0, 100, 0, 255`

Fixed in git.

> [@Samo](#):
>
> ```
> S_SaveFileName chnget "IO_SaveAs" 
> S_LoadFileName chnget "IO_Browse"
> 
> ```

You are using different channel names. If I do this it works as expected:

```
S_SaveFileName chnget "SaveAs"
printf S_SaveFileName, changed(S_SaveFileName)

```

Using the new widgets you can do something like this:

```
S_SaveFileName, kSaveTrig cabbageGet "SaveAs"
printf S_SaveFileName, kSaveTrig

```

In this case there is very little difference between the `chnget` way of doing things and the new `cabbageGet` opcode.

> [@Samo](#):
>
> So, I need to send a message to the channel and the widget. Is this the optimal way to deal with this (if I want to update both) or would you have other suggestions?

You only need to either set the values using `chset`, or `cabbageSetValue`, not both. I think both versions of code should work so long as you remove the final call to the “frq” channel. On the other hand, it can be written more succinctly with the trigger version of the `cabbageSetValue` opcode:

```
kX2, kX2Trig cabbageGetValue "X2" 
k05, k05Trig cabbageGetValue "X05" 
cabbageSetValue "Frq", kFrq * 2, kX2Trig
cabbageSetValue "Frq", kFrq * .5, k05Trig

```

---

<div class="post-metadata">

**Author:** ![Samo](https://forum.cabbageaudio.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@Samo](https://forum.cabbageaudio.com/u/Samo)\
**Post date:** [10 April 2021 15:59 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/15 "2021-04-10T15:59:42Z")

</div>

> [@rorywalsh](#):
>
> Fixed in git.

Thanks!

> [@rorywalsh](#):
>
> You are using different channel names.

A silly mistake, sorry!  
I see that `cabbageGetValue` also gets the string from `filebutton`

You only need to either set the values using `chset` , or `cabbageSetValue` , not both

> [@rorywalsh](#):
>
> You only need to either set the values using `chset` , or `cabbageSetValue` , not both.

But if I don’t use `chnset`, the kFrq doesn’t get updated, so pressing e.g. X2 repeatedly only moves the slider one time, since subsequent triggers use the old (unchanged) kFrq value. But if I only use `chnset`, then the widget doesn’t update (as expected in “queue” mode). So it seems I need to use both. Am I missing something?

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [10 April 2021 18:55 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/16 "2021-04-10T18:55:03Z")

</div>

> [@Samo](#):
>
> But if I only use `chnset` , then the widget doesn’t update (as expected in “queue” mode). So it seems I need to use both. Am I missing something?

In this case, i don’t think I follow what you are trying to do? Here’s my test, based on what I thought you were trying to do..

```
<Cabbage>
form caption("test CabbageSetGet") size(300, 250) colour(58, 110, 182) pluginId("tcsg") guiMode("queue") 
rslider bounds(4, 28, 120, 120) valueTextBox(1) range(1, 2000, 200, 1, 1) channel("Frq") popupText("0") colour(200, 200, 100, 255) trackerColour(200, 200, 100, 255)
button bounds(126, 20, 65, 65) latched(0) channel("X2") text("x2","x2") value(0) corners(3) colour:0(255, 0, 0, 255) colour:1(255, 255, 0, 255) fontColour:0(0, 0, 0, 255) fontColour:1(160, 0, 0, 255)
button bounds(126, 88, 65, 65) latched(0) channel("X05") text("/2","/2") value(0) corners(3) colour:0(0, 255, 0, 255) colour:1(255, 255, 0, 255) fontColour:0(0, 0, 0, 255) fontColour:1(160, 0, 0, 255)
filebutton bounds(154, 190, 70, 14) channel("SaveAs") mode("save") value(0) text("SAVE AS", "SAVE AS") corners(3) colour:0(100, 0, 0, 255) colour:1(255, 255, 0, 255) fontColour:1(160, 0, 0, 255)
filebutton bounds(76, 190, 70, 14) channel("Browse") value(0) text("BROWSE", "BROWSE") corners(3) colour:0(140, 200, 30, 255) colour:1(255, 255, 0, 255) fontColour:0(160, 0, 0, 255)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d 
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 1
kTrig2 = trigger(cabbageGetValue:k("X2"), .5, 0)
cabbageSet kTrig2, "Frq", "markerColour", 255, 0, 0, 255
cabbageSet kTrig2, "Frq", "trackerColour", 0, 100, 0, 255

S_SaveFileName, kSaveTrig cabbageGet "SaveAs"
printf S_SaveFileName, kSaveTrig

kFrq = cabbageGetValue:k("Frq")
kX2, kX2Trig cabbageGetValue "X2" 
k05, k05Trig cabbageGetValue "X05" 

cabbageSetValue "Frq", kFrq * 2, kX2Trig
cabbageSetValue "Frq", kFrq * .5, k05Trig

endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7] 
</CsScore>
</CsoundSynthesizer>

```

---

<div class="post-metadata">

**Author:** ![Samo](https://forum.cabbageaudio.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@Samo](https://forum.cabbageaudio.com/u/Samo)\
**Post date:** [11 April 2021 08:00 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/17 "2021-04-11T08:00:43Z")

</div>

In the example below, the iCase = 1 and 2 are what I want, but iCase = 3 is not sufficient. I am wondering if there are any alternatives?

I’m using a similar system to save and load presets from table “slots”. From non-latched buttons I need in this case only triggers on 0-\>1 not on change and button state is not needed. Perhaps something like “CabbageGetTrigger” with parameters similar to the `trigger` opcode could be useful (probably overkill)?

```
<Cabbage>
form caption("test CabbageSetGet") size(300, 250) colour(58, 110, 182) pluginId("tcsg") guiMode("queue") 
rslider bounds(4, 28, 120, 120) range(1, 2000, 200, 1, 1) channel("Frq") popupText("0") colour(200, 200, 100, 255) trackerColour(200, 200, 100, 255) valueTextBox(1)
button bounds(126, 20, 65, 65) latched(0) channel("X2") text("x2","x2") value(0) corners(3) colour:0(255, 0, 0, 255) colour:1(255, 255, 0, 255) fontColour:0(0, 0, 0, 255) fontColour:1(160, 0, 0, 255)
button bounds(126, 88, 65, 65) latched(0) channel("X05") text("/2","/2") value(0) corners(3) colour:0(0, 255, 0, 255) colour:1(255, 255, 0, 255) fontColour:0(0, 0, 0, 255) fontColour:1(160, 0, 0, 255)

</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d 
</CsOptions>
<CsInstruments>
ksmps = 32

instr 1

; 1 - I need something like this
; 2 - or this
; 3 - this is not sufficient 
iCase = 1

kFrq cabbageGetValue "Frq"
; need trigger only for button push (0->1)  
kX2Trig = trigger(cabbageGetValue:k("X2"), .5, 0)
kX05Trig = trigger(cabbageGetValue:k("X05"), .5, 0)

; these trigger on change (0->1 and 1->0)
; kX2, kX2Trig cabbageGetValue "X2" 
; X05, kX05Trig cabbageGetValue "X05" 

if (iCase == 1) then 
   
    if kX2Trig == 1 then
        chnset kFrq*2, "Frq"
    elseif kX05Trig == 1 then
        chnset kFrq*0.5, "Frq"
    endif
    cabbageSetValue "Frq", kFrq, changed:k(kFrq)
       
elseif (iCase == 2) then      
  
    if kX2Trig == 1 then
        kFrq *= 2   
        cabbageSetValue "Frq", kFrq
    elseif kX05Trig == 1 then
        kFrq *= 0.5   
        cabbageSetValue "Frq", kFrq
    endif
    chnset kFrq, "Frq"
       
elseif (iCase == 3) then   

    cabbageSetValue "Frq", kFrq * 2, kX2Trig
    cabbageSetValue "Frq", kFrq * .5, kX05Trig
    
endif

printk2 kFrq
endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7] 
</CsScore>
</CsoundSynthesizer>
```

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [11 April 2021 11:49 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/18 "2021-04-11T11:49:16Z")

</div>

Can you check the value of the button at the same time? So if the button has changed AND its value is 1:

`if kX2Trig == 1 && cabbageGetValue:k("X2") == 1 then`

Wouldn’t that work?

---

<div class="post-metadata">

**Author:** ![Samo](https://forum.cabbageaudio.com/letter_avatar_proxy/v4/letter/s/71c47a/32.png) [@Samo](https://forum.cabbageaudio.com/u/Samo)\
**Post date:** [11 April 2021 13:22 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/19 "2021-04-11T13:22:13Z")

</div>

Sure that works, but requires handling two variables.

So, I guess you have no other suggestions regarding the need to set both channel and widget (cases 1 & 2 vs case 1 above)?

---

<div class="post-metadata">

**Author:** ![rorywalsh](https://forum.cabbageaudio.com/user_avatar/forum.cabbageaudio.com/rorywalsh/32/165_2.png) [@rorywalsh](https://forum.cabbageaudio.com/u/rorywalsh)\
**Post date:** [11 April 2021 15:16 UTC](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388/20 "2021-04-11T15:16:29Z")

</div>

If the button are non latched you can just check their value? They will send a 1 for only a single k cycle. No need for triggers at all 🤷

```
kX2 = cabbageGetValue:k("X2")
kX05 = cabbageGetValue:k("X05")

cabbageSetValue "Frq", kFrq*2, kX2
cabbageSetValue "Frq", kFrq*0.5, kX05
```

[Next page](https://forum.cabbageaudio.com/t/new-cabbage-widget-opcodes/2388.md?page=2)
