FR: Allow custom VST3 UIDs

Hello,

I’m currently working on a project that uses a JUCE wrapper to replace a VST SDK-based plugin (and several other wrappers). With a matching Manufacturer Code and Plugin Code, I can get the VST2 and AU versions of the JUCE plugin to replace the existing plugin in DAW projects.

But for VST3, the UID that the host uses to identify plugins is partially hard-coded in JUCE:

inline static const FUID iid { TUID INLINE_UID (0xABCDEF01, 0x9182FAEB, JucePlugin_ManufacturerCode, JucePlugin_PluginCode) };

To get the new VST3 to replace the old one, the whole UID must be the same, so there is no choice but to modify this line in the JUCE source code.

My request then is some way of setting the entire VST3 UID with a JUCE setting.

Thank you for your consideration.

+1

I am dealing with the same issue, porting old code to JUCE and some way of assigning manual VST3 IDs. Any ideas?

This seems to do the trick (in my particular situation), but I’d appreciate some input from someone more experienced. So far only tested in Reaper (win and macOS).

In juce_VST3ModuleInfo.h:

[[maybe_unused]] static VST3Interface::Id getVST3InterfaceId (VST3Interface::Type interfaceType)
{
   #if JUCE_VST3_CAN_REPLACE_VST2
    if (interfaceType == VST3Interface::Type::controller || interfaceType == VST3Interface::Type::component)
        return VST3Interface::vst2PluginId (JucePlugin_VSTUniqueID, JucePlugin_Name, interfaceType);
   #endif

#if defined(CUSTOM_UID)
	if (interfaceType == VST3Interface::Type::component)
	{
		auto res = VST3Interface::Id();
		constexpr std::array<unsigned, 4> UID = CUSTOM_UID;

		for (int i = 0; i < 16; ++i)
		{
			const unsigned pos = i / 4;
			const unsigned off = (3 - (i % 4)) * 8; // big-endian
			res[i] = static_cast<std::byte>((UID[pos] >> off) & 0xFF);
		}
#if JUCE_WINDOWS
		std::swap(res[0], res[3]);
		std::swap(res[1], res[2]);
		std::swap(res[4], res[5]);
		std::swap(res[6], res[7]);
#endif

		return res;
	}
#endif

    return VST3Interface::jucePluginId (JucePlugin_ManufacturerCode, JucePlugin_PluginCode, interfaceType);
}

In your project’s preprocessor definitions (example):
CUSTOM_UID={0x01234567,0x89ABCDEF,0x78965412,0x19732846}

Rather than having to change JUCE can you use JUCE_VST3_COMPATIBLE_CLASSES to add the VST3 UID you need to be compatible with?

I must be doing something wrong, because this doesn’t work for me. I replaced the custom UID macro with this:
JUCE_VST3_COMPATIBLE_CLASSES=VST3Interface::hexStringToId(“0123456789ABCDEF7896541219732846”)
but Reaper doesn’t recognize it as the same plugin. It might also be a DAW issue, but that’s all the more reason to actually use the old UID.

Another (definitely not me doing things wrong) issue is that this approach doesn’t work if the user decides to go to a previous (pre-JUCE) version. Even though it would be a PITA to modify JUCE on every machine with every JUCE update, I’d still prefer to do that than introduce easily avoidable incompatibility.

EDIT: I guess the hexStringToId() approach needs some/all of the byte shuffling done when creating the UID string, is that correct? Still, I think my second point stands.

Yes you would need to check what the actual value is of the VST3 you want to replace.

Looking back at the implementation you’ve suggested I think if we add something like this we would expect the CUSTOM_UID to be the correct UID, no need to shuffle bytes. That should also make managing the change in JUCE for yourself that little bit easier.

Having it be the final UID without shuffling bytes is fair enough I guess.

I keep trying to figure out the hexStringToId() approach, but it just doesn’t want to work. I got to a point where my original implementation and hexStringToId() return the same byte array, but Reaper still doesn’t replace the instance with the new version.

I’m surprised, I thought reaper supported it.

Maybe check out the VST3PluginTestHost in the SDK (VST 3 Plug-in Test Host - VST 3 Developer Portal)

If nothing else I think you can use this to give you the UID you need from the original plugin.

I’m not sure how to check whether or not it works in the test host. I did just try it in Cubase and it doesn’t work there either, so I’m really confused…

EDIT: I just double checked and the byte arrays produced by my code and hexStringToId() are definitely the same, so I really have no idea what’s going on. Is there something more needed for this to work? I assumed not overriding VST3ClientExtensions::getCompatibleParameterIds() would just result in state being messed up, am I wrong?

Please check out the develop branch, we’ve added a new preprocessor definition JUCE_VST3_COMPONENT_CLASS this should be defined as a quoted string containing 32 hex characters representing the the class ID you want to use VST3: Add support for defining a custom VST3 component class ID · juce-framework/JUCE@1294562 · GitHub

1 Like

Awesome, that works great! Thank you.

2 Likes