Cabbage provides a set of built-in widgets, although it is also possible to create custom widgets using any JavaScript/HTML framework. Widgets can generally be divided into two categories: interactive and non-interactive.
Each widget has a unique set of properties and associated Csound software channels, defined in JSON format. These channels define parameters and serve as the communication bridge between Cabbage’s graphical interface and the Csound audio engine. Most widget properties can be modified at any time to adjust their appearance or behavior.
Named channels are a central part of the Cabbage architecture: they carry values and parameter updates between the GUI and Csound, forming a software “bus” for data transfer. Every widget must have a channel id. Channel ids can be set at the widget’s top level, but more often they are defined within channel objects that form part of the channels array. The channels array allows multiple channels to be associated with a single widget, enabling extended interactions.
range objects can be defined within channel objects. These are used both to name plugin parameters and to define their ranges. A typical channel definition with an embedded range object might look like this:
{
"type": "rotarySlider",
"channels": [
{
"id": "Gain",
"range": {
"min": 0, "max": 1, "value": 0, "skew": 1, "increment": 0.01
}
}
]
}
channel.id — in this case "Gain" — will be registered as a plugin parameter in a host DAW, with 0 and 1 defining its minimum and maximum range. The cabbageSetValue and cabbageGetValue opcodes can be used to send values back and forth to these channels.
Certain widgets, such as a groupBox, will rarely be set up to function as parameters. In these cases, a top-level id can be set. For example:
{
"type": "groupBox",
"id": "adsrPanel"
}
In such cases, the cabbageSet and cabbageGet opcodes can be used to send JSON data back and forth. Widgets can also combine a top-level id with channel ids. Consider an image widget for example, with multiple channels defined:
{
"type": "image",
"channels": [
{
"id": "mouseX",
"event": "mouseMoveX",
"range": {"min": 0, "max": 1000, "defaultValue": 0, "skew": 1, "increment": 0.01}
},
{
"id": "mouseY",
"event": "mouseMoveX",
"range": {"min": 0, "max": 1000, "defaultValue": 0, "skew": 1, "increment": 0.01}
},
{
"id": "image1MousePress",
"event": "mousePressLeft"
}
]
}
If no top-level id is set, the channels[0].id channel can be used, but the resulting code might not be very intuitive, for instance, calling cabbageSet to set the color of mouseX doesn’t make much sense. In such cases, it helps to define a more appropriately named top-level id:
{
"type": "image",
"id": "frequencyXyPad",
"channels": [
{
"id": "mouseX",
"event": "mouseMoveX",
"range": {"min": 0, "max": 1000, "defaultValue": 0, "skew": 1, "increment": 0.01}
},
{
"id": "mouseY",
"event": "mouseMoveX",
"range": {"min": 0, "max": 1000, "defaultValue": 0, "skew": 1, "increment": 0.01}
},
{
"id": "image1MousePress",
"event": "mousePressLeft"
}
]
}
Using well-named top-level ids to manage a widget’s visual state offers many benefits, not least when it comes to debugging complex instruments.
JSON doesn’t support comments. If you wish to add comments to your JSON, use a "//" : "This is a comment....." property. The extension will highlight this line to make it stands out from the rest of the JSON code.
A widget’s range is fixed and cannot be changed. However, there are ways to make it appear as though the range has changed. Please ask on the forum for tips and tricks on making this work.
Each and every Cabbage widget has a set of properties that define its behavior and appearance. All properties, except for channels and automatable, can be updated dynamically during run-time. The following properties are common to all widgets:
Bounds
"bounds": {"left":0, "top":0, "width":100, "height":100}
Visible
"visible": true
Active
"active": true
false. Interaction is not supported with widgets that have active set to false.Automatable
"automatable": true
true. Determines if a widget is automatable by a host DAW. Automatable widgets show up as plug-in parameters in the host. Non-automatable widgets can still communicate with Csound but are not accessible by the host. Note that hosts do not allow this parameter to change dynamically. If you change this setting, the plugin will need to be reloaded.Z-Index
"zIndex": 1
zIndex values appear in front of widgets with lower values. The default is 1.Each widget also has a unique set of styling properties accessed through the style object. Here, users can control how their widgets look. In a break from Cabbage 2 convention, and to align with CSS/HTML naming schemes, all style properties use CSS-style spelling—for example, background color is listed as backgroundColor. A full list of supported styles, along with all other properties, can be found in each widget’s manual entry.
All widgets include an automatable property. Only widgets with automatable set to true will appear as automatable parameters in a host environment. Through the named channels, these widgets can be controlled or modulated by the host, ensuring synchronisation between the interface and the audio engine. Many of the stock widgets that ship with Cabbage have their automatable property set to true by default.
Widgets with automatable:true can still send and receive data over named channels, but they will not appear in the list of plugin parameters presented in the DAW. A fileButton is a good example of one such widget. It makes little sense to give the DAW control to open a native file browser dialog. Note that this property cannot be toggled on and off; the host needs to know what is automatable when it loads.
Each widget in Cabbage is documented with its properties and available channels. Example .csd files are provided to demonstrate how to integrate the widget into a project and use its channels in practice.