1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

VST3: Add a new PluginDescription::uniqueId field

This commit is contained in:
reuk 2021-03-30 18:32:33 +01:00
parent a533e86044
commit 041da08474
No known key found for this signature in database
GPG key ID: 9ADCD339CFC98A11
12 changed files with 107 additions and 56 deletions

View file

@ -1,6 +1,34 @@
JUCE breaking changes
=====================
Develop
=======
Change
------
PluginDescription::uid has been deprecated and replaced with a new 'uniqueId'
data member.
Possible Issues
---------------
Code using the old data member will need to be updated in order to compile.
Workaround
----------
Code that used to use 'uid' to identify plugins should switch to using
'uniqueId', with some caveats - see "Rationale" for details.
Rationale
---------
The 'uniqueId' member has the benefit of being consistent for
a given VST3 across Windows, macOS, and Linux. However, the value of the
uniqueId may differ from the value of the old uid on some platforms. The value
of the old 'uid' member can now be found in the 'deprecatedUid' member, which
should allow clients to implement logic such as checking a saved uid against
the new uniqueId, and falling back to the deprecatedUid. This should allow
hosts to gracefully upgrade from the old uid values to the new values.
Version 6.0.8
=============

View file

@ -113,17 +113,18 @@ private:
PluginDescription descr;
descr.name = identifier;
descr.descriptiveName = identifier;
descr.pluginFormatName = InternalPluginFormat::getIdentifier();
descr.category = (registerAsGenerator ? (acceptsMidi ? "Synth" : "Generator") : "Effect");
descr.manufacturerName = "JUCE";
descr.version = ProjectInfo::versionString;
descr.fileOrIdentifier = identifier;
descr.uid = identifier.hashCode();
descr.isInstrument = (acceptsMidi && registerAsGenerator);
descr.numInputChannels = ins;
descr.numOutputChannels = outs;
descr.name = identifier;
descr.descriptiveName = identifier;
descr.pluginFormatName = InternalPluginFormat::getIdentifier();
descr.category = (registerAsGenerator ? (acceptsMidi ? "Synth" : "Generator") : "Effect");
descr.manufacturerName = "JUCE";
descr.version = ProjectInfo::versionString;
descr.fileOrIdentifier = identifier;
descr.isInstrument = (acceptsMidi && registerAsGenerator);
descr.numInputChannels = ins;
descr.numOutputChannels = outs;
descr.uniqueId = descr.deprecatedUid = identifier.hashCode();
return descr;
}

View file

@ -2274,8 +2274,7 @@ function(juce_add_pip header)
target_compile_definitions(${JUCE_PIP_NAME}
PRIVATE ${pip_moduleflags}
PUBLIC
JUCE_VST3_CAN_REPLACE_VST2=0
JUCE_VST3_HOST_CROSS_PLATFORM_UID=1)
JUCE_VST3_CAN_REPLACE_VST2=0)
_juce_get_pip_targets(${JUCE_PIP_NAME} pip_targets)

View file

@ -63,7 +63,6 @@ static void doBasicProjectSetup (Project& project, const NewProjectTemplates::Pr
project.getMainGroup().addNewSubGroup ("Source", 0);
project.getConfigFlag ("JUCE_STRICT_REFCOUNTEDPOINTER") = true;
project.getConfigFlag ("JUCE_VST3_HOST_CROSS_PLATFORM_UID") = true;
project.getProjectValue (Ids::useAppConfig) = false;
project.getProjectValue (Ids::addUsingNamespaceToJuceHeader) = false;

View file

@ -846,9 +846,9 @@ public:
desc.name = pluginName;
desc.descriptiveName = pluginName;
desc.fileOrIdentifier = AudioUnitFormatHelpers::createPluginIdentifier (componentDesc);
desc.uid = ((int) componentDesc.componentType)
^ ((int) componentDesc.componentSubType)
^ ((int) componentDesc.componentManufacturer);
desc.uniqueId = desc.deprecatedUid = ((int) componentDesc.componentType)
^ ((int) componentDesc.componentSubType)
^ ((int) componentDesc.componentManufacturer);
desc.lastFileModTime = Time();
desc.lastInfoUpdateTime = Time::getCurrentTime();
desc.pluginFormatName = "AudioUnit";
@ -2634,7 +2634,7 @@ void AudioUnitPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>&
PluginDescription desc;
desc.fileOrIdentifier = fileOrIdentifier;
desc.uid = 0;
desc.uniqueId = desc.deprecatedUid = 0;
if (MessageManager::getInstance()->isThisTheMessageThread()
&& requiresUnblockedMessageThreadDuringCreation (desc))

View file

@ -220,7 +220,7 @@ public:
{
desc.name = getName();
desc.fileOrIdentifier = module->file.getFullPathName();
desc.uid = getUID();
desc.uniqueId = desc.deprecatedUid = getUID();
desc.lastFileModTime = module->file.getLastModificationTime();
desc.lastInfoUpdateTime = Time::getCurrentTime();
desc.pluginFormatName = "LADSPA";
@ -583,7 +583,7 @@ void LADSPAPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& res
PluginDescription desc;
desc.fileOrIdentifier = fileOrIdentifier;
desc.uid = 0;
desc.uniqueId = desc.deprecatedUid = 0;
auto createdInstance = createInstanceFromDescription (desc, 44100.0, 512);
auto instance = dynamic_cast<LADSPAPluginInstance*> (createdInstance.get());
@ -600,7 +600,7 @@ void LADSPAPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& res
{
if (auto* plugin = instance->module->moduleMain ((size_t) uid))
{
desc.uid = uid;
desc.uniqueId = desc.deprecatedUid = uid;
desc.name = plugin->Name != nullptr ? plugin->Name : "Unknown";
if (! arrayContainsPlugin (results, desc))
@ -631,7 +631,7 @@ void LADSPAPluginFormat::createPluginInstance (const PluginDescription& desc,
if (module != nullptr)
{
shellLADSPAUIDToCreate = desc.uid;
shellLADSPAUIDToCreate = desc.uniqueId;
result.reset (new LADSPAPluginInstance (module));

View file

@ -79,18 +79,18 @@ static int warnOnFailureIfImplemented (int result) noexcept
#endif
//==============================================================================
static int getHashForTUID (const TUID& tuid) noexcept
std::array<uint32, 4> getNormalisedTUID (const TUID& tuid) noexcept
{
#if JUCE_VST3_HOST_CROSS_PLATFORM_UID
const FUID fuid { tuid };
const uint32 inputArray[] { fuid.getLong1(), fuid.getLong2(), fuid.getLong3(), fuid.getLong4() };
#else
const auto& inputArray = tuid;
#endif
return { { fuid.getLong1(), fuid.getLong2(), fuid.getLong3(), fuid.getLong4() } };
}
template <typename Range>
static int getHashForRange (Range&& range) noexcept
{
uint32 value = 0;
for (const auto& item : inputArray)
for (const auto& item : range)
value = (value * 31) + (uint32) item;
return (int) value;
@ -120,7 +120,9 @@ static void createPluginDescription (PluginDescription& description,
description.pluginFormatName = "VST3";
description.numInputChannels = numInputs;
description.numOutputChannels = numOutputs;
description.uid = getHashForTUID (info.cid);
description.deprecatedUid = getHashForRange (info.cid);
description.uniqueId = getHashForRange (getNormalisedTUID (info.cid));
if (infoW != nullptr) fillDescriptionWith (description, *infoW);
else if (info2 != nullptr) fillDescriptionWith (description, *info2);
@ -780,7 +782,7 @@ struct DescriptionFactory
}
}
if (desc.uid != 0)
if (desc.uniqueId != 0)
result = performOnDescription (desc);
if (result.failed())
@ -1105,7 +1107,8 @@ private:
continue;
if (toString (info.name).trim() == description.name
&& getHashForTUID (info.cid) == description.uid)
&& (getHashForRange (getNormalisedTUID (info.cid)) == description.uniqueId
|| getHashForRange (info.cid) == description.deprecatedUid))
{
name = description.name;
return true;

View file

@ -1170,7 +1170,7 @@ struct VSTPluginInstance : public AudioPluginInstance,
}
desc.fileOrIdentifier = vstModule->file.getFullPathName();
desc.uid = getUID();
desc.uniqueId = desc.deprecatedUid = getUID();
desc.lastFileModTime = vstModule->file.getLastModificationTime();
desc.lastInfoUpdateTime = Time::getCurrentTime();
desc.pluginFormatName = "VST";
@ -3470,7 +3470,7 @@ void VSTPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& result
PluginDescription desc;
desc.fileOrIdentifier = fileOrIdentifier;
desc.uid = 0;
desc.uniqueId = desc.deprecatedUid = 0;
auto instance = createAndUpdateDesc (*this, desc);
@ -3495,7 +3495,7 @@ void VSTPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& result
if (uid == 0)
break;
desc.uid = uid;
desc.uniqueId = desc.deprecatedUid = uid;
desc.name = shellEffectName;
aboutToScanVSTShellPlugin (desc);
@ -3504,7 +3504,8 @@ void VSTPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& result
if (shellInstance != nullptr)
{
jassert (desc.uid == uid);
jassert (desc.deprecatedUid == uid);
jassert (desc.uniqueId == uid);
desc.hasSharedContainer = true;
desc.name = shellEffectName;
@ -3530,7 +3531,7 @@ void VSTPluginFormat::createPluginInstance (const PluginDescription& desc,
if (auto module = ModuleHandle::findOrCreateModule (file))
{
shellUIDToCreate = desc.uid;
shellUIDToCreate = desc.uniqueId;
result.reset (VSTPluginInstance::create (module, sampleRate, blockSize));

View file

@ -102,15 +102,6 @@
#define JUCE_CUSTOM_VST3_SDK 0
#endif
/** Config: JUCE_VST3_HOST_CROSS_PLATFORM_UID
If enabled, ensures that PluginDescription::uid will produce consistent values for VST3 plugins on all platforms.
It is recommended to enable this flag in all new projects.
Projects which predate this flag should leave it disabled, in case they need to interact with uid values which they previously stored.
*/
#ifndef JUCE_VST3_HOST_CROSS_PLATFORM_UID
#define JUCE_VST3_HOST_CROSS_PLATFORM_UID 0
#endif
#if ! (JUCE_PLUGINHOST_AU || JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_LADSPA)
// #error "You need to set either the JUCE_PLUGINHOST_AU and/or JUCE_PLUGINHOST_VST and/or JUCE_PLUGINHOST_VST3 and/or JUCE_PLUGINHOST_LADSPA flags if you're using this module!"
#endif

View file

@ -1418,13 +1418,14 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getName() const
void AudioProcessorGraph::AudioGraphIOProcessor::fillInPluginDescription (PluginDescription& d) const
{
d.name = getName();
d.uid = d.name.hashCode();
d.category = "I/O devices";
d.pluginFormatName = "Internal";
d.manufacturerName = "JUCE";
d.version = "1.0";
d.isInstrument = false;
d.deprecatedUid = d.uniqueId = d.name.hashCode();
d.numInputChannels = getTotalNumInputChannels();
if (type == audioOutputNode && graph != nullptr)

View file

@ -28,14 +28,18 @@ namespace juce
bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept
{
return fileOrIdentifier == other.fileOrIdentifier
&& uid == other.uid;
const auto tie = [] (const PluginDescription& d)
{
return std::tie (d.fileOrIdentifier, d.deprecatedUid, d.uniqueId);
};
return tie (*this) == tie (other);
}
static String getPluginDescSuffix (const PluginDescription& d)
{
return "-" + String::toHexString (d.fileOrIdentifier.hashCode())
+ "-" + String::toHexString (d.uid);
+ "-" + String::toHexString (d.uniqueId);
}
bool PluginDescription::matchesIdentifierString (const String& identifierString) const
@ -62,7 +66,7 @@ std::unique_ptr<XmlElement> PluginDescription::createXml() const
e->setAttribute ("manufacturer", manufacturerName);
e->setAttribute ("version", version);
e->setAttribute ("file", fileOrIdentifier);
e->setAttribute ("uid", String::toHexString (uid));
e->setAttribute ("uniqueId", String::toHexString (uniqueId));
e->setAttribute ("isInstrument", isInstrument);
e->setAttribute ("fileTime", String::toHexString (lastFileModTime.toMilliseconds()));
e->setAttribute ("infoUpdateTime", String::toHexString (lastInfoUpdateTime.toMilliseconds()));
@ -70,6 +74,8 @@ std::unique_ptr<XmlElement> PluginDescription::createXml() const
e->setAttribute ("numOutputs", numOutputChannels);
e->setAttribute ("isShell", hasSharedContainer);
e->setAttribute ("uid", String::toHexString (deprecatedUid));
return e;
}
@ -84,7 +90,6 @@ bool PluginDescription::loadFromXml (const XmlElement& xml)
manufacturerName = xml.getStringAttribute ("manufacturer");
version = xml.getStringAttribute ("version");
fileOrIdentifier = xml.getStringAttribute ("file");
uid = xml.getStringAttribute ("uid").getHexValue32();
isInstrument = xml.getBoolAttribute ("isInstrument", false);
lastFileModTime = Time (xml.getStringAttribute ("fileTime").getHexValue64());
lastInfoUpdateTime = Time (xml.getStringAttribute ("infoUpdateTime").getHexValue64());
@ -92,6 +97,9 @@ bool PluginDescription::loadFromXml (const XmlElement& xml)
numOutputChannels = xml.getIntAttribute ("numOutputs");
hasSharedContainer = xml.getBoolAttribute ("isShell", false);
deprecatedUid = xml.getStringAttribute ("uid").getHexValue32();
uniqueId = xml.getStringAttribute ("uniqueId", "0").getHexValue32();
return true;
}

View file

@ -44,9 +44,12 @@ class JUCE_API PluginDescription
public:
//==============================================================================
PluginDescription() = default;
PluginDescription (const PluginDescription& other) = default;
PluginDescription& operator= (const PluginDescription& other) = default;
PluginDescription (const PluginDescription&) = default;
PluginDescription (PluginDescription&&) = default;
PluginDescription& operator= (const PluginDescription&) = default;
PluginDescription& operator= (PluginDescription&&) = default;
//==============================================================================
/** The name of the plug-in. */
@ -88,14 +91,31 @@ public:
*/
Time lastInfoUpdateTime;
/** A unique ID for the plug-in.
/** Deprecated: New projects should use uniqueId instead.
A unique ID for the plug-in.
Note that this might not be unique between formats, e.g. a VST and some
other format might actually have the same id.
@see createIdentifierString
*/
int uid = 0;
int deprecatedUid = 0;
/** A unique ID for the plug-in.
Note that this might not be unique between formats, e.g. a VST and some
other format might actually have the same id.
The uniqueId field replaces the deprecatedUid field, and fixes an issue
where VST3 plugins with matching FUIDs would generate different uid
values depending on the platform. The deprecatedUid field is kept for
backwards compatibility, allowing existing hosts to migrate from the
old uid to the new uniqueId.
@see createIdentifierString
*/
int uniqueId = 0;
/** True if the plug-in identifies itself as a synthesiser. */
bool isInstrument = false;