Cabbage Logo
Back to Cabbage Site

Idea: preprocessor definition inserted into exported instruments and effects

Based on the discussion we had in another thread, I’ve been moving my test code behind a preprocessor definition. It’s working great, but while doing this I realized that it might be handy to have Cabbage automatically insert a define into the csound orchestra when exporting, so the instruments can be aware of whether or not they’re running exported or natively in cabbage… something like #define CABBAGE_EXPORTED #1#

I don’t know if you’d consider it useful, but it might even make sense to export a different variable name or perhaps value depending on whether it’s exported as an effect or an instrument.

That’s a good idea. I’ve added a reserved channel so users can query this. For example:

iIsAPlugin chnget "IS_A_PLUGIN"

chnget will return 1 if it is a plugin, otherwise it will return 0.

Awesome, thanks Rory!

I have to admit, I’m having a hard time using this the way I had hoped to… Because it’s a variable instead of a preprocessor directive means that it can only change code at run time.

If I have a diskin statement I use for testing, wrapping it in an “if conditional” doesn’t help when the effect is exported… it will still error saying the diskin file wasn’t found. It has to be wrapped with a #ifdef, that way if it’s not defined, it’s like the diskin code does’t even exist.

I had also tried doing something like this:
if chnget(“IS_A_PLUGIN”)==1 then
#undef DEBUG
endif
But you can’t wrap an #undef if an if conditional either, it will always be applied regardless since it’s parsed out before the code is evaluated…

Any suggestions for how to do this?

I’ve always done this with the filevalid opcode. If the files exists load it, otherwise don’t. But I see your point. As far as I know, I can’t make Csound defines through the API. But we can pass macros through the CsOptions section. Therefore it may be possible to work something out. Let me take a look.

[edit]
I’ve added a more workable solution. The macro IS_A_PLUGIN is now defined to 1 is the instrument is launched as a plugin. You can test it with something like

#ifdef IS_A_PLUGIN
code only reached is IS_A_PLUGIN is defined...
#end

This will be perfect!

Slightly related question… I don’t know how you achieved this, but would it make sense to also do the same for all cabbage defines? If it doesn’t add a lot of complexity, I would think this would be faster and more memory efficient than using channels… plus would (IMHO) result in more “proper” csound code in the sense that defines carry over as macro expansions instead of requiring variables read from a channel.

How DO we access the defines from a channel btw? I can’t find that thread anymore, I don’t see it mentioned in the docs, and my first two attempts to wing it have failed. :wink:

Check reserved channels in the docs. I thought about this when I was adding this particular mechanism. It may be the way to go. It’s easy to provide both.

I don’t see it in the reserved section either… what I mean is if in the cabbage section I do:
#define MYBLUE colour(0,0,255,255)

How do I access MYBLUE from the csound code? I thought it was supposed to be:

Sbuf chnget(“MYBLUE”)

but that didn’t seem to work for me.

Ah yeah sorry, it should be:

#define channel("name") NAME ....

It would be nice as you say to pass identifiers with macros, but it seem the only way to do it is with --strsetN which works more or less the same as chnget and a string. I’ve asked on the Csound dev list. I’ll see what they say. Maybe there is a way of doing it from the API.

Ah, setting the channel… that’s what I was forgetting. Thanks, that should definitely make it into the docs :wink:

So after testing this today, it looks like IS_A_PLUGIN ALWAYS gets defined, but is defined as 0 when running standalone. This doesn’t really help for preprocessing, since you can’t check it’s value… only if it’s defined or not.

My ultimate goal would be something like:

#ifndef IS_A_PLUGIN
#define DEBUG 1
#endif

Good point. I’ll change it so it is only defined when the instrument is a plugin.

Should this be working in the current version, or is it still in progress?

The following doesn’t appear to work, and it seems like it should:

#define DEBUG #1#
#ifdef IS_A_PLUGIN
  #ifdef DEBUG
    #undef DEBUG
  #endif
#endif

It looks like I never committed that. So it’s defined, but as 0. Anyhow, fixed now and re-uploaded:
https://github.com/rorywalsh/cabbage/releases/download/v0.5.15/CabbageOSXUniversal.pkg

Sweet, that did the trick. Thanks for the quick fix!

I just added some further code that allows use to grab all #defines from the Cabbage section in our Csound code. I just need to do some more tests, but it looks like it should work Ok.

Awesome news! Are there any caveats I should plan for? Such as a max number of definitions, max length of definitions, or max length of combined definitions?

I’ve no had any time to test this properly since since implementing it, so I just uploaded a build for you to test if you like. There is no installer here. Simply unzip and place it anywhere you like. It shouldn’t conflict with earlier version.

https://dl.dropboxusercontent.com/u/11301894/Cabbage.app.zip

There shouldn’t be any caveats, apart from those imposed by Csound. All we’re doing is passing the macro to Csound on startup using --omacro: flags. But it could be possible that Csound has some kind of string size limit for macro flags. I’m not sure.

Ok, I think I found the first caveat… all definitions are strings.

So, for example:

#define W_SINE 1

defined in the cabbage section is available to csound, but doesn’t work in a csound comparison such as:

if kshape==$W_SINE then

I get why it’s that way, and it’s not a big deal really… it’d be difficult to tell what type of definition is intended by context, so I can keep these defines in the csound section. But I just figured I’d point it out.

Ah yes. That’s a good point. If guess if you know the macro is a number you might be able to do:

if kshape==strtod($W_SINE) then