Cabbage Logo
Back to Cabbage Site

Solution for user-made presets?

Okey, will try it!

So what I’m trying to do is to trigger the save and delete button through a combobox. I have collected different options into one combobox to reduce clutter.

ComboboxTrigger

Edit: Basically have the save and delete button invisible, but trigger then through this main combobox

Oh I see. Nope that’s ain’t going to work. File buttons are a kind of special case.

Okey, thanks for confirming it

So I’ve tried making some presets now, and I noticed something odd.

I have two buttons that switches between two knobs.

Example of one of them:

 if changed2(gkSyncButton) == 1 then
     if gkSyncButton == 0 then
         SIdent_1 sprintfk "visible(%d)", 0
         chnset SIdent_1, "delaysyncIdent"
         SIdent_2 sprintfk "visible(%d)", 1
         chnset SIdent_2, "delayIdent"
     
     else
         SIdent_1 sprintfk "visible(%d)", 1
         chnset SIdent_1, "delaysyncIdent"
         SIdent_2 sprintfk "visible(%d)", 0
         chnset SIdent_2, "delayIdent"
  
     endif
 endif

This is what happens when I switch between presets (notice the pitch-knob). This only happens with the Pitch and the Delay-knobs. It’s worth mentioning that both the hidden and the visible knob is sharing the same channel so when you push the button, it won’t jump to another value.

Having widget share channels is not the best idea. All the same, it’s hard to see what’s happening. Any chance you can produce a simplified version of the problem for me to run through the debugger?

PresetManagerButton.csd (1.5 KB)

Yeah, this is definitely the result of you using the same channel for each widget. Only one value is saved to disk. I think you might have to come up with another solution :thinking:

Okey, I can use two seperate channels. It seemed so pro when I switched between them and they stayed at the same value :rofl:

1 Like

Okey so that definitely fixed it, but I wonder if there is any way to sync the value when switching? If not then I will leave it as it is now:

if changed2(gkSemiButton) == 1 then
    if gkSemiButton == 0 then
        SIdent_1 sprintfk "visible(%d)", 0
        chnset SIdent_1, "pitchsemiIdent"
        SIdent_2 sprintfk "visible(%d)", 1
        chnset SIdent_2, "pitchIdent"
    
    else
        SIdent_1 sprintfk "visible(%d)", 1
        chnset SIdent_1, "pitchsemiIdent"
        SIdent_2 sprintfk "visible(%d)", 0
        chnset SIdent_2, "pitchIdent"
 
    endif
endif

if gkSemiButton == 1 then
    gkPitch chnget "PitchSemi"
    
else
    gkPitch chnget "Pitch"

endif 

SIdent sprintfk "text(%d)", gkPitch
chnset SIdent, "PitchLabel" 

gkPitch	= 2^(gkPitch/12)

Can you do:

if gkSemiButton == 1 then
    gkPitch chnget "PitchSemi"
    chnset gkPitch, "Pitch"
else
    gkPitch chnget "Pitch"
    chnset gkPitch, "PitchSemi"
endif

I sure can :man_facepalming:

Thanks!

1 Like

Until now, I was happy with using the standard (“snaps”) preset manager built into Cabbage. Now, I am working on an instrument which requires saving a table together with the presets. So I wanted to use the approach by @Retornz with the combobox. I found that the combobox does not ‘populate’. So I dug out an example which I think was working some months ago: PresetManager2 (combobox).csd (2.8 KB) The same there: The combobox always shows ‘(no choices)’ even after creating new .pres files in the subdirectory presets and restarting the instrument.

The combo-box is populating fine here, although the latest file name doesn’t automatically appear. It won’t until you set it to. In this code here, after we save a preset, I send the name of the preset to the combobox. In this case I’m just ending “preset2”. In practice you will need to parse the file name and remove the extension and path. It’s a bit awkward because on Windows paths will made up with \\ while on other systems you’ll be parsing for /.

<Cabbage>
form caption("Presets") size(370, 280), guiMode("queue") colour(58, 110, 182), pluginId("MPre")
rslider bounds(12, 8, 85, 79), channel("att"), range(0, 1, 0.01), text("Att.")
rslider bounds(98, 8, 85, 79), channel("dec"), range(0, 1, 0.4), text("Dec.")
rslider bounds(184, 8, 85, 79), channel("sus"), range(0, 1, 0.7), text("Sus.")
rslider bounds(270, 8, 85, 79), channel("rel"), range(0, 1, 0.8), text("Rel.")

filebutton bounds(12, 190, 60, 28), channel("saveFile"), text("Save"), populate("*.pres","presets"), mode("save")
filebutton bounds(74, 190, 60, 28), channel("openFile") text("Open"), populate("*.pres"), mode("file")

combobox bounds(170, 126, 180, 15) populate("*.pres", "pres") channel("box") channelType("string")
label bounds(14, 108, 336, 11) text("<No Preset>")
button bounds(74, 220, 60, 28), channel("reload") text("reload")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1
gSFileName init 0

;always on and listening for preset updates..
instr 1000
    SSaveFile, kSaveTrigger cabbageGetValue "saveFile"
    if kSaveTrigger == 1 then
        event "i", 1003, 0, .1
    endif
endin

;================================================
instr 1003 ;save presets
    SFile, kFileTrigger cabbageGet "saveFile"

    if strrindex(SFile, ".pres") == -1 then
        SFile strcat SFile, ".pres"
    endif

    fprints SFile, "%f %f %f %f", chnget:i("att"), chnget:i("dec"), chnget:i("sus"), chnget:i("rel")
    ficlose SFile
    
    cabbageSet "box", "value(\"preset3\")"
    
endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
i1000 0 z
</CsScore>
</CsoundSynthesizer>

P.S. I updated this to use the new guiMode("queue") system…

Thank you for the quick response! I tried your code and it showed the empty combobox again. First, I thought I were under some kind of “spell of irreproducible errors”. But then I saw that in your code files are written to the directory presets but read by the combobox from pres. So if you already have some presets in pres it works but not for me not even having the directory pres and writing new presets into presets.

I will look for my code now and whether it is a similar error.

I got my code running. I added ,"Mpresets" to all populate commands. Anyway, it is better not to clutter the main directory. Just for fun I deleted these additions after creating a couple of presets. Surprisingly it works too. combobox populate searchs recursively?

I believe it might, although it’s probably not a good idea! I think I might add a few simple opcodes for dealing with filenames. It’s a pain to parse filenames in Csound, and the fact that different platforms use different slashes makes it pretty awkward. An opcode that could return just the file name, or just the path, or just the extension would be quite useful I think.

Something like this might be quite useful. We just pass the filename, and we can then retrieve what parts of it we want.

1 Like

How about everything Rory?
I am observing that combobox and listbox when used outside of preconfigured snaps code like the (PresetNamed) example, they again need moving audio to be able to store and read presets. The moment a channel is assigned to it for example and populate is changed to another name, it works fine, but it needs that audio moving.
Respecting the PresetNamed code, it does obey the read and write changes, even if the audio is stopped.
I am using guiMode (“queue”).

It would be great if combobox and listbox could respond with the audio at rest :wink:

Yes, I agree. I’ll look into it. My time is restricted at the moment because we welcomed a new baby girl into our family last week :wink: I’ll let you know when I get around to this :+1:

1 Like