Cabbage Logo
Back to Cabbage Site

Creating custom UIs with Cabbage 3

I’m already getting question about this, so here’s some more info on top of what’s in the docs. To use a JS framework like React or Svelte, you first need to export a basic plugin. This will create the plugin binary, and the self-contained folder where the web front-end will be served from. By default, it will export the files needed to run a native Cabbage interface. The file structure looks like this:


The only file you really need is the cabbage.js file which includes functions that allow you to pass events to your plugin from the web interface. If you want to receive data from your plugin check out the event handler in main.js. A ‘widgetUpdate’ event message will be sent to the UI whenever a widget is updated through a call to the cabbageSet opcode. So you can basically remove all of these files and replace them with your own. The index.html will be served inside the plugin window and hey presto, custom interface.

This is all somewhat theoretical as I’ve yet to try it myself. If anyone wants to give it a go (I’m looking at you @hdale94!) please do and let me know how it goes. It may need some tweaking to get it to work.

2 Likes

I can confirm this works. I just did the following:

  1. Exported a basic plugin.
  2. Using vite, I created a new template Svelte app
  3. I imported cabbage.js and added a call to Cabbage.sendParameterUpdate to the Counter.svelte component:
<script>
  import { Cabbage } from "../cabbage.js";
  let count = $state(0)
  let parameterIndex = 0;
  const increment = () => {
    count = count < 10 ? count + 1 : 0;
    const msg = { paramIdx: parameterIndex, channel: "freq", value: count/10 }
    Cabbage.sendParameterUpdate(null, msg);

  }
</script>

<button onclick={increment}>
  count is {count}
</button>
  1. Built the svelte app
  2. Copied the dist file over to my plugin resources folder, replacing any files that were there.
  3. Launched Reaper :slight_smile:

Note that I still had to declare a parameter in my .csd file:

<Cabbage>[
    {"type":"form","caption":"Button Example","size":{"width":380,"height":300},"pluginId":"def1", "enableDevTools":true},
    {"type":"rotarySlider","channel":"freq", "range":{"min":0, "max":10, "increment":1}}
]</Cabbage>

And I had to also leave the cabbage/wdgets folders as Cabbage needs to read the widget descriptors from disk. But you can easily add your own classes. So, if it works for Svelte, it should work with any JS frontend framework.

amazing! congrats on the alpha release. I’m very much looking forward to playing around with this. hopefully will find some time over the next couple weeks.

Btw the time you start playing with it I should have a few more of the teething issue sorted :wink:

1 Like

I’m trying to create custom widgets now!

Do you have examples of widgets using an audio buffer as an input? I’m trying to understand how to do it using the keyboard.js as a template but instead of using midi events I’ll use audio events.

Thanks!

Edit: Actually the gentable example might be a good starting point, i’ll try with this one

Yes, gentable. We’ll need to work on a more robust approach to sending samples. But the gentable has a samples property, which get populated with audio from a Csound function table. I will add an array version of cabbageSetValue so that you can grab audio samples more easily.

I will try to get that done later today if I can :+1:

Ok, new build underway that should provide more options for drawing things. I’ve added array variants of cabbageSet and updated the placeholder docs. My advice for you would be to clone the most recent gentable widget. rename both the class and the filename, but leave it in the same directory as gentable.js. Then hack the drawing routine as you see fit. You can send an array of samples to it using the cabbageSet opcode. Here’s me doing it with a small array.

The current gentable widget sucks at smaller tables. I’l fix this when I get a chance.