Cabbage Logo
Back to Cabbage Site

New Cabbage widget opcodes

I’m trying to access rslider limits (min, max) with cabbageGet. While kArray[] cabbageGet "slider", "bounds" works, kArray[] cabbageGet "slider", "range" doesn’t. Is it possible and which identifier should be used?

Ah, try ‘min’, or ‘max’. I don’t think I added support for array output from range. I can do so, but not till later today.

No hurry!

Neither “min” nor “max” get anything (at i- or k-rate). Getting the range would be very useful, e.g. for randomization.

btw. it seems that one has to specify cabbageGetValue:i(...) when reading at init time only. On the other hand chnget() seems to work without the rate specifier (at least for the init pass). It makes sense to use “:i”, so it seems confusing on the Csound side rather then on the Cabbage side. Maybe you have a comment on this? Thanks!

I think chnget defaults to i-time. so you don’t have to use the identifier. But I always recommend using the rate specifier regardless as it’s make things easier to read.

Correct that combobox items names cannot be altered using cabbageSet?

cabbageSet "SynthMode2", {{ items("FM","AM") }}

This only works for combobox that are set to channelType(“string”), i.e, they are not automatable. A combobox is like a slider, in that its range cannot be modified without breaking the host.

got it. ok, i think i can work with that… thanks.

I thought I had this with strget/set. Sorry the String type widgets always trip me up… is there a way to get an index still or store the string somehow to compare it to an ivar?

Yes, but because I neglected to add the the option of passing arrays to cabbageSet it is a little long winded. We also have to write our own IndexOf UDO for finding the index of a string within an array. Nevertheless, here is an example that lets users populate a combobox with text they type into a texteditor. It will also give you the correct index whenever the combobox is updated or changed.

<Cabbage>
form caption("Untitled") size(400, 300), guiMode("queue") pluginId("def1")
combobox bounds(26, 74, 143, 20) channel("combo1"), channelType("string") items("AM", "FM", "PM", "LMN"), value("AM")
texteditor bounds(26, 38, 142, 30) channel("texteditor1")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d 
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1


opcode IndexOf, k,SS[]

    SString, SStrings[] xin
    kCount = 0
    kIndex init 0
    kSize  = lenarray:k(SStrings)
    
    while kCount < kSize do
        if strcmpk(SString, SStrings[kCount]) == 0 then
            kIndex = kCount
        endif
        kCount +=1
    od

    xout kIndex
    
endop

instr 1

    SNewItem, kNewItemTrig cabbageGetValue "texteditor1"
    SCurrentItems[] cabbageGet "combo1", "text"
    
    if kNewItemTrig == 1 then
        event "i", "UpdateCombo", 0, 0.01 
    endif

    SCombo, kComboTrig cabbageGetValue "combo1"
    printf SCombo, kComboTrig
    printarray SCurrentItems, kComboTrig
    printk2 IndexOf(SCombo, SCurrentItems) 

endin

instr UpdateCombo
        
    SItem cabbageGetValue "texteditor1"
    SCurrentItems[] cabbageGet "combo1", "text"
    iNewArraySize = lenarray(SCurrentItems)+1
        
    SNewList init "items("
    iIndex = 0
    while iIndex < iNewArraySize-1 do
        SNewList strcat SNewList, strcat("\"", strcat(SCurrentItems[iIndex], "\", "))
        iIndex += 1
    od
        
    SNewList strcat SNewList, strcat("\"", strcat(SItem, "\")")) 
        
    ;we only need to do this when the instrument is released...
    cabbageSet release(), "combo1", SNewList
    cabbageSet release(), "combo1", strcat("value(\"", strcat(SItem, "\")"))


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>

</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>

Thanks Rory - it’s a bit of a workaround I was hoping I wouldn’t have to do…

Is there a way to simply compare the string in the combobox to a value for a conditional operation?
Something like this - but that works correctly - assuming the strset strings are the same as the combobox strings

if (chnget:S("ComboBoxString") == strget(1)) then
        ivar = 1
    elseif (chnget:S("ComboBoxString") == strget(2)) then
        ivar = 2
    else
        ivar = 3
    endif

I know this is sort of a Csound 101 question but it has forever evaded me why we cannot simply compare string values. I feel like I’m overthinking this whole thing though…

Is there no way you can put all those strget strings into an array? That’s really the simplest way I can think of doing it. Csound doesn’t have switch statements, that would make things a little cleaner.

Another note about the code above, it uses the text() identifier to grab the items. items() doesn’t actually work in this context. I need to fix that.

Just wanted to remind you of this. In 2.7.2,
iArr[] cabbageGet "...", "bounds"
works but
iArr[] cabbageGet "...", "range"
does not. I’d like to get the min and max values.

1 Like

Setting a widget value with cabbageSet updates the widget display of the value but the value isn’t sent to the instrument?

cabbageSetValue works as expected for this, so I assume it’s by design? If so, just curious why both functions weren’t wrapped up in cabbageSet.

Setting a value through cabbageSet, should also work, but it won’t be as quick as cabbageSetValue as it incurs additional overhead. I’ll check it out. It might well be by design as I wanted to lead people to use the more efficient way of doing it :thinking:

I’ve added support for this. You can now do the following:

iRange[] cabbageGet "freq", "range"

I’ve added support for this you can now do:

cabbageSet kTrig, "freqSlider", "value", 500

The reason that I didn’t wrap them all up into one was because I didn’t think I could get a cabbageSet to perform as quick as cabbagetSetValue because of some extra overhead. But I think I could probably consolidate them without incurring much of a hit. It would definitely lead to better consistency.

Cool - thanks. I am only running them for 1 sec anyway to instance a new UI. Will try it now…

Hey i was just surfing around the forum… Wouldn’t using strcmp/strcmpk help out with this (comparing strings)? For example, using the model you posted:

if (strcmpk(chnget:S("CombobBoxString"), strget(1))==0) then
     ivar = 1
elseif (strcmpk(chnget:S("CombobBoxString"), strget(2))==0) then
     ivar = 2
endif

Correct. I think I somehow missed the point that @chronopolis was making here :man_facepalming:

Is this

SMacroName1, knameChange1 cabbageGetValue "MacroName1"    
    if knameChange1 == 1 then
        Snewname = sprintfk("text(\"%s\")", SMacroName1)
        cabbageSet knameChange1, "Macro1", Snewname
    endif

the same as this?

SMacroName1, knameChange1 cabbageGetValue "MacroName1"
cabbageSet knameChange1, "Macro1", SMacroName1

Trying to get this down to 2 lines of code. I thought it would be the same but it’s not functioning the same. I also tried…

cabbageSet knameChange1, "Macro1", sprintfk("%s", SMacroName1)