Cabbage Logo
Back to Cabbage Site

Internal Presets

Ah yes, but can you with the native presets (even if with a button and not automatically) save/replace a particular preset slot (the examples only show that you can append presets but I didn’t see a way to go to some previous preset and update it?)

Check out the namedPresets.csd file in the examples. It lets you overwrite existing slots.

Ok, will do :slight_smile: Thanks!

Is there a way to bypass the dialog box when replacing a specific preset? I think I’m not fully understanding how the system works (how to parse a specific preset). I tried the following code PN01.csd (1.4 KB) (to no avail) –– the combo box is populated with “p1, p2, p3” etc.:

combobox bounds(74, 190, 100, 25), channel("list"), populate("*.snaps"), channelType("string")

filebutton bounds(12, 190, 60, 25), channel("save"), text("Save As"), populate("*.snaps", "test"), mode("named preset")
filebutton bounds(12, 220, 60, 25), channel("replace"), text("Replace"), populate("p1.snaps"), mode("preset")
filebutton bounds(12, 250, 60, 25), channel("remove"), text("Remove"), populate("*.snaps", "test"), mode("remove preset")

</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>

ksmps = 32
nchnls = 2
0dbfs = 1

instr 1
    SFile, kTrig cabbageGetValue "list"

    if kTrig == 1 then
        SFile2 sprintfk "%s.snaps", SFile
        cabbageSet 1, "replace", "populate", SFile2
    endif
endin

The native preset system saves the state of every widget when you save a preset, and and recalls them when you you select a preset. You don’t parse the presets. They just automatically cause the widgets to update. As you can in the named preset example, there is no Csound code relating to the presets.

This modified example will print the preset name when each time you save or change the preset:

<Cabbage>
form caption("Presets") size(370, 280), guiMode("queue"), colour(58, 110, 182), pluginId("MPre")
keyboard bounds(10, 90, 345, 95)
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.")
combobox bounds(74, 190, 100, 25), populate("*.snaps"), channelType("string"), channel("presetName")
filebutton bounds(12, 190, 60, 25), text("Save"), populate("*.snaps", "test"), mode("named preset")
filebutton bounds(12, 220, 60, 25), text("Remove"), populate("*.snaps", "test"), mode("remove preset")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
;sr is set by the host
ksmps = 32
nchnls = 2
0dbfs = 1

;instrument will be triggered by keyboard widget
instr 1

endin

instr 1000
    SCombo, kTrig cabbageGetValue "presetName"
    printf SCombo, kTrig 
endin

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

Btw, if you do use the native preset system you can’t programmatically take snapshots from the Csound code. Perhaps this in itself is enough of a reason for you to persist with the other methods…

Mmm, I think I understand (BTW, I was thinking of creating dummy sliders for each grid so as to have only one ChannelSetSave instruction/file, which then I was hoping to save using the native preset system if that makes sense).

But, if I may, let’s go back to my last question first? According to the Docs/Native Presets:

You can also set the name of the custom preset file. Instead of passing “*.snaps” as the file type, pass the full file name, i.e, “myPresets.snaps”.

…that’s what I was attempting to do (or what I meant by ‘parsing a preset’): I’d like to update/replace a specific preset without having to go through a dialog box (and having to type the name of the preset to be replaced), is that possible?

I’ll continue working on the ChannelSetSave example in the meantime (perhaps there’s a way to do everything with this opcode?: 1) save to a default file using a slider/combobox/etc (as in the original example on this post) and 2) have a side button to save to an external location?).

Thanks either way :slight_smile:

No, that is not possible.

Why have a side button to save to an external location? If it is to give users a chance to ‘save as’ to a different location, you can use the cabbageCopyFile opcode.

Ok, thanks!

I was thinking of the file button “save” mode, but I think I misunderstood the native presets, which you explained here…

But if I can combine my ‘internal presets’ with the PresetsNamed, I think that should meet all the basic needs :wink: (if not, will look into cabbageCopyFile, if that can apply to a custom JSON file?)

I don’t think you can combine the two systems. One saves the presets in a single file, while the other saves presets in multiple files. Ok, you could write a JSON parser in Csound that would update a particular preset in one JSON file with the contents of a channelSave file. It might be a bit of work though.

I get the feeling that we’re still not on the same page here? :rofl:

Getting closer anyhow I think :wink: I’ll need a little time to try out an example to show what I mean (if I’m successful with it, of course).

Re: parsing to a JSON file, it makes sense and yes, I can see that it’d probably take some work to make it happen…will burn that bridge if/when the need arises.

Will post as soon as I’ve made some progress!

If you do need to do some file reading/writing, you might find these opcodes useful: strToFile and fileToStr. They are actually included with Cabbage but undocumented. I should prepend their names with cabbage to make it clear they are not part of canonical Csound.

Ah, great! Will try these. I haven’t yet tackled my idea/example yet (might have to wait until Monday I’m afraid).

I just tried the following code to get a snaps file outside of the plugin (sorry I’m being so slow in understanding how native presets are meant to be just internal! But perhaps this will be useful still)…

<Cabbage>
form caption("Presets Named 2") size(370, 280), guiMode("queue"), colour(58, 110, 182), pluginId("pn02")
keyboard bounds(10, 90, 345, 95)
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.")
combobox bounds(74, 190, 100, 25), populate("*.snaps"), channelType("string")
filebutton bounds(12, 190, 60, 25), channel("savep"), text("Preset"), populate("*.snaps"), mode("named snapshot")
button bounds(200, 190, 60, 25), channel("savef"), text("File")
filebutton bounds(12, 220, 60, 25), channel("open"), text("Open"), populate("*.snaps"), mode("file")
filebutton bounds(12, 250, 60, 25), channel("remove"), text("Remove"), populate("*.snaps", "test"), mode("remove preset")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>

ksmps = 32
nchnls = 2
0dbfs = 1

instr 1
kbut, ktrig cabbageGetValue "savef"
    if ktrig == 1 then
        cabbageCopyFile "/Users/flaviogaete/Desktop", "PN02.snaps"
    endif
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

Was wondering if there was a way that the user specify the path (and hopefully also the filename?) where to save (copy) to. I’ll check out strToFile and fileToStr in case that’s the way (unless you were meaning some other custom JSON file and then I’m still not on the same page? :thinking:).

Sorry, I’m on my phone here, but you can use the filebutton widget in you need to get a file and path from the user. Set it to save mode and it will prompt the user for a file. The full path and name will be returned to the channel.

1 Like

Thanks! I myself got distracted from my computer. Will look at all this soon.

Ok, so I managed to save the native presets to an external file. However, I’m having trouble getting to read a file, not sure if it’s possible. Here’s the code for both (save / open)…

<Cabbage>
form caption("Presets Named 2") size(340, 240), guiMode("queue"), colour(58, 110, 182), pluginId("pn02")

rslider bounds(20, 20, 60, 60), channel("att"), range(0, 1, 0.01), text("Att.")
rslider bounds(100, 20, 60, 60), channel("dec"), range(0, 1, 0.4), text("Dec.")
rslider bounds(180, 20, 60, 60), channel("sus"), range(0, 1, 0.7), text("Sus.")
rslider bounds(260, 20, 60, 60), channel("rel"), range(0, 1, 0.8), text("Rel.")

combobox bounds(100, 120, 100, 20), channel("list"), populate("*.snaps"), channelType("string")

filebutton bounds(20, 120, 60, 20), channel("savep"), text("Preset"), populate("*.snaps"), mode("named snapshot")
filebutton bounds(220, 120, 60, 20), channel("savef"), text("Save"), mode("save")
filebutton bounds(20, 160, 60, 20), channel("open"), text("Open"), mode("file")
filebutton bounds(20, 200, 60, 20), channel("remove"), text("Remove"), populate("*.snaps", "test"), mode("remove preset")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>

ksmps = 32
nchnls = 2
0dbfs = 1

instr 1
    gSSave, kts cabbageGetValue "savef"
    gSOpen, kto cabbageGetValue "open"
    
    if kts == 1 then
        event "i", "Save", 0, 1
    endif
        
    if kto == 1 then
        event "i", "Open", 0, 1
    endif
endin

instr Save
    SFromPreset fileToStr   "PN02.snaps"
    iRes        strToFile   SFromPreset, gSSave, 0
endin

instr Open
    SToPreset   fileToStr   gSOpen
    iRes        strToFile   SToPreset, "PN02.snaps", 0
    turnoff2    1, 0, 0
    event       "i", 1, 0, 1
endin
;
</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

I’m getting some running messages in the Cabbage console as soon as I choose an item in the combobox, so I’m sure there’s something I’m missing. Also, (haven’t tested this yet to confirm), I think I can pass the file back to the local path of the .csd file but I can’t manage to have the patch recognize it unless I stop and start the instrument again?

I’ll be in and out today so my responses will continue to be sporadic, but will get to the forum as soon as I get a chance!

Thanks very much for your time Rory :slight_smile:

My first thoughts about this were to send a populate() identifier to the combobox once you have copied the file over. It didn’t work, but does now. However, we have another issue. cabbageGetValue with a filebutton will only trigger an update IF the file name has changed. So if you want to keep copying the same file it will not work. Leave it with me. I’ll come up with a solution. And when I do I’ll push the populate() update too.

1 Like

This is a little hacky, but it works. In order to be able to pick up a change on a filebutton IF one always tries to use the same file we need to keep setting it’s file identifier to identifier("") once a file has been accessed. The following update to your code works.

<Cabbage>
form caption("Presets Named 2") size(340, 240), guiMode("queue"), colour(58, 110, 182), pluginId("pn02")

rslider bounds(20, 20, 60, 60), channel("att"), range(0, 1, 0.01, .2), text("Att.")
rslider bounds(100, 20, 60, 60), channel("dec"), range(0, 1, 0.4), text("Dec.")
rslider bounds(180, 20, 60, 60), channel("sus"), range(0, 1, 0.7), text("Sus.")
rslider bounds(260, 20, 60, 60), channel("rel"), range(0, 1, 0.8), text("Rel.")

combobox bounds(100, 120, 100, 20), channel("list"), populate("*.snaps"), channelType("string")

filebutton bounds(20, 120, 60, 20), channel("savep"), text("Preset"), populate("*.snaps"), mode("named snapshot")
filebutton bounds(220, 120, 60, 20), channel("savef"), text("Save"), mode("file")
filebutton bounds(20, 160, 60, 20), channel("open"), text("Open"), mode("file")
filebutton bounds(20, 200, 60, 20), channel("remove"), text("Remove"), populate("*.snaps", "test"), mode("remove preset")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>

ksmps = 32
nchnls = 2
0dbfs = 1

instr 1
    gSSave, kts cabbageGetValue "savef"
    gSOpen, kto cabbageGetValue "open"
    
    if kts == 1 then
        event "i", "Save", 0, 1
    endif
        
    if kto == 1 then
        event "i", "Open", 0, 1
    endif
endin

instr Save
    SFromPreset fileToStr   "PN02.snaps"
    iRes        strToFile   SFromPreset, gSSave, 0
    cabbageSet "savef", "file(\"\")"
endin

instr Open
    SToPreset   fileToStr   gSOpen
    iRes        strToFile   SToPreset, "PN02.snaps", 0
    cabbageSet "list", "populate(\"*.snaps\")" 
    cabbageSet "open", "file(\"\")"
endin
;
</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer> 

Note that it might take some work to get the combobox to display an item when you refresh it. If you know the name of a preset you can use cabbageSet "list", "text", SPresetName but you will need to parse the presets I guess.

Hi Rory,

First, thanks very much for taking the time to find a solution!

I tried the following example at the end of the main instrument

cabbageSet "list", "text", "p3"

…assuming a predefined name and in hopes to call a specific value for the combobox, but was not successful. I also tried creating a separate instrument that I can call with a slight delay just to refresh the value (not sure if that would make a difference with re: the widgets’ default value?). And I also tried setting the channelType to “float” and calling the combobox via cabbageSetValue (e.g. “list”, 2), but it didn’t work either. I’m sure there’s something I’m just not understanding about the combobox and how it works? At any rate, it’d be great if one could both get and set float values independently of the preset names etc. so one can, for example call specific presets with a MIDI note or cc value, etc.

Also wanted to send a few styling requests (though I realize this might not be a priority and that some of these might be complicated to implement, so: OK if you can’t get to it at this moment, but I throw it out there if it’s any helpful feedback): I’d love it if we could control the following on the combobox widget:

  • The corners (the ability to make them zero as well)
  • Hide/show triangle
  • Hide/show checkbox –– and instead have say a ‘selected item’ color (either font or background)
  • Menu background color (or it could be the same as the combobox background color).

Thanks again!
Flavio