SynthDescLib not loading SynthDescs with metadata

I am working on a plugin that needs to send u_cmd messages to UGens (to load config files). This is working wonderfully (thanks to @Spacechild1 very clear implementation in VSTPlugin). The problem is, when the language recompiles, the SynthDescLib doesn’t seem to load scsyndef files that require txarcmeta metadata files. Both the scsyndef file and the metadata file are skipped when compiling the class library.

I can confirm that the same problem exists with SynthDefs that use VSTPlugin (which also uses metadata files) in them. In the case of my UGen and for VSTPlugin SynthDefs, I can make a Synth with the corresponding Def after recompiling, but the necessary metadata that the language needs to communicate with the Ugen is missing. Also, no Descs with metadata appear in the “SynthDescLib.global.browse” window after recompiling the class library. Once the SynthDefs are recompiled in a fresh instance of the lang, they work great.

Any ideas on this? I can’t seem to find exactly where the language goes through and fills the SynthDescLib.global dictionary. Obviously, it is choosing not to load files with metadata for some reason.

[edit: I am on the current Dev build]

Thanks,

Sam

I don’t think that SynthDescLib automatically adds or remembers any SynthDefs. If I’m not mistaken, you always have to explicitly add your SynthDefs to the SynthDescLib with .add resp. .store. Once you recompile the Class Library, the corresponding SynthDescs are gone.

Here’s a simple test:

SynthDef(\foo, { Out.ar(0, SinOsc.ar)) }).add;
SynthDescLib.global.at(\foo); // -> SynthDesc 'foo'
// recompile Class Library
SynthDescLib.global.at(\foo); // -> nil

Or maybe I misunderstood the question?

I couldn’t reproduce that – though it is confusing that there’s no convenient interface to load all scsyndef files from a directory :expressionless: – like, 20+ years and there’s no SynthDescLib.readDir?

p = (SynthDef.synthDefDir +/+ "*.scsyndef").pathMatch;

SynthDescLib.at(p[0].basename.splitext[0].asSymbol)
-> nil  // i.e., not read from the folder by default

// uh wait what...?
// this doesn't exist as a method? Seriously?
p.do { |path|
	SynthDescLib.read(path);
};

SynthDescLib.at(p[0].basename.splitext[0].asSymbol)
-> SynthDesc 'system_env_0_audio' 
Controls:
ControlName  P 0 i_bus scalar 0.0
..... snip

// ok let's try with MD

SynthDef(\testmd, { |out = 0|
	Out.ar(0, SinOsc.ar(440))
}, metadata: (specs: (out: [0, 1023, \lin, 1]))).store;

thisProcess.recompile;

SynthDescLib.at(\testmd);  // nil

(SynthDef.synthDefDir +/+ "*.scsyndef").pathMatch.do { |path|
	SynthDescLib.read(path);
};

SynthDescLib.at(\testmd);
-> SynthDesc 'testmd' 
Controls:
ControlName  P 0 out control 0.0
   O audio Out 0.0 1

SynthDescLib.at(\testmd).metadata
-> ('specs': ('out': [0, 1023, lin, 1]))

hjh

Ah, wow. OK. I was trying so hard to figure out how it loaded the global SynthDescLib, I failed to see it wasn’t loading them at all. (I have so many SynthDefs that compile with the library, I was tricking myself)

I guess it is up to the user to know that UGens that require metadata to function correctly need to be recompiled or the scsyndef file needs to be loaded after every recompile? That doesn’t seem right. There are very few of these for sure (/u_cmd’s are seemingly nonexistent in the standard library), but it may cause confusion. Then again, I never noticed with VSTPlugin (or was just confused why things weren’t working and figured out a workaround).

Anyhow, thank you for the responses. I wonder if there is a way to add this to recompile without issues cropping up.

Sam

And answering my own question: you can just load the file manually when the Desc doesn’t already exist in the global SynthDescLib:

(
    ~synthIndex = SynthDescLib.global[\testmd];
		
    if (~synthIndex != nil) {
        ~metadata=~synthIndex.metadata();
    }{
        SynthDescLib.read(SynthDef.synthDefDir+/+'testmd'.asString++".scsyndef");
        ~metadata = SynthDescLib.global['testmd'].metadata();
    };

    ~metadata
)

Thanks for helping work through this.

Sam