mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Projucer: Added options for setting the VST, VST3, AAX and RTAS categories and simplified the plug-in project settings with MultiChoicePropertyComponent
This commit is contained in:
parent
51ff1daf60
commit
629f2a2979
5 changed files with 423 additions and 129 deletions
|
|
@ -265,7 +265,15 @@ public:
|
|||
}
|
||||
|
||||
if (auto* multiChoice = dynamic_cast<MultiChoicePropertyComponent*> (prop))
|
||||
multiChoice->onHeightChange = [this] { updateSize (getX(), getY(), getWidth()); };
|
||||
{
|
||||
multiChoice->onHeightChange = [this]
|
||||
{
|
||||
updateSize (getX(), getY(), getWidth());
|
||||
|
||||
if (auto* parent = getParentComponent())
|
||||
parent->parentSizeChanged();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ Project::Project (const File& f)
|
|||
initialiseMainGroup();
|
||||
initialiseAudioPluginValues();
|
||||
|
||||
coalescePluginFormatValues();
|
||||
coalescePluginCharacteristicsValues();
|
||||
updatePluginCategories();
|
||||
|
||||
parsedPreprocessorDefs = parsePreprocessorDefs (preprocessorDefsValue.get());
|
||||
|
||||
getModules().sortAlphabetically();
|
||||
|
|
@ -216,39 +220,24 @@ void Project::initialiseProjectValues()
|
|||
|
||||
void Project::initialiseAudioPluginValues()
|
||||
{
|
||||
buildVSTValue.referTo (projectRoot, Ids::buildVST, getUndoManager(), true);
|
||||
buildVST3Value.referTo (projectRoot, Ids::buildVST3, getUndoManager(), false);
|
||||
buildAUValue.referTo (projectRoot, Ids::buildAU, getUndoManager(), true);
|
||||
buildAUv3Value.referTo (projectRoot, Ids::buildAUv3, getUndoManager(), false);
|
||||
buildRTASValue.referTo (projectRoot, Ids::buildRTAS, getUndoManager(), false);
|
||||
buildAAXValue.referTo (projectRoot, Ids::buildAAX, getUndoManager(), false);
|
||||
buildStandaloneValue.referTo (projectRoot, Ids::buildStandalone, getUndoManager(), false);
|
||||
enableIAAValue.referTo (projectRoot, Ids::enableIAA, getUndoManager(), false);
|
||||
pluginFormatsValue.referTo (projectRoot, Ids::pluginFormats, getUndoManager(), Array<var> (Ids::buildVST.toString(), Ids::buildAU.toString()), ",");
|
||||
pluginCharacteristicsValue.referTo (projectRoot, Ids::pluginCharacteristicsValue, getUndoManager(), Array<var> (), ",");
|
||||
|
||||
pluginNameValue.referTo (projectRoot, Ids::pluginName, getUndoManager(), getProjectNameString());
|
||||
pluginDescriptionValue.referTo (projectRoot, Ids::pluginDesc, getUndoManager(), getProjectNameString());
|
||||
pluginManufacturerValue.referTo (projectRoot, Ids::pluginManufacturer, getUndoManager(), "yourcompany");
|
||||
pluginManufacturerCodeValue.referTo (projectRoot, Ids::pluginManufacturerCode, getUndoManager(), "Manu");
|
||||
pluginCodeValue.referTo (projectRoot, Ids::pluginCode, getUndoManager(), makeValid4CC (getProjectUIDString() + getProjectUIDString()));
|
||||
pluginChannelConfigsValue.referTo (projectRoot, Ids::pluginChannelConfigs, getUndoManager());
|
||||
|
||||
pluginIsSynthValue.referTo (projectRoot, Ids::pluginIsSynth, getUndoManager(), false);
|
||||
pluginWantsMidiInputValue.referTo (projectRoot, Ids::pluginWantsMidiIn, getUndoManager(), false);
|
||||
pluginProducesMidiOutValue.referTo (projectRoot, Ids::pluginProducesMidiOut, getUndoManager(), false);
|
||||
pluginIsMidiEffectPluginValue.referTo (projectRoot, Ids::pluginIsMidiEffectPlugin, getUndoManager(), false);
|
||||
pluginEditorNeedsKeyFocusValue.referTo (projectRoot, Ids::pluginEditorRequiresKeys, getUndoManager(), false);
|
||||
|
||||
pluginVSTCategoryValue.referTo (projectRoot, Ids::pluginVSTCategory, getUndoManager());
|
||||
pluginNameValue.referTo (projectRoot, Ids::pluginName, getUndoManager(), getProjectNameString());
|
||||
pluginDescriptionValue.referTo (projectRoot, Ids::pluginDesc, getUndoManager(), getProjectNameString());
|
||||
pluginManufacturerValue.referTo (projectRoot, Ids::pluginManufacturer, getUndoManager(), "yourcompany");
|
||||
pluginManufacturerCodeValue.referTo (projectRoot, Ids::pluginManufacturerCode, getUndoManager(), "Manu");
|
||||
pluginCodeValue.referTo (projectRoot, Ids::pluginCode, getUndoManager(), makeValid4CC (getProjectUIDString() + getProjectUIDString()));
|
||||
pluginChannelConfigsValue.referTo (projectRoot, Ids::pluginChannelConfigs, getUndoManager());
|
||||
pluginAAXIdentifierValue.referTo (projectRoot, Ids::aaxIdentifier, getUndoManager(), getDefaultAAXIdentifierString());
|
||||
pluginAUExportPrefixValue.referTo (projectRoot, Ids::pluginAUExportPrefix, getUndoManager(),
|
||||
CodeHelpers::makeValidIdentifier (getProjectNameString(), false, true, false) + "AU");
|
||||
pluginAUMainTypeValue.referTo (projectRoot, Ids::pluginAUMainType, getUndoManager());
|
||||
pluginRTASCategoryValue.referTo (projectRoot, Ids::pluginRTASCategory, getUndoManager());
|
||||
pluginRTASBypassDisabledValue.referTo (projectRoot, Ids::pluginRTASDisableBypass, getUndoManager());
|
||||
pluginRTASMultiMonoDisabledValue.referTo (projectRoot, Ids::pluginRTASDisableMultiMono, getUndoManager());
|
||||
pluginAAXIdentifierValue.referTo (projectRoot, Ids::aaxIdentifier, getUndoManager(), getDefaultAAXIdentifierString());
|
||||
pluginAAXCategoryValue.referTo (projectRoot, Ids::pluginAAXCategory, getUndoManager(), "AAX_ePlugInCategory_Dynamics");
|
||||
pluginAAXBypassDisabledValue.referTo (projectRoot, Ids::pluginAAXDisableBypass, getUndoManager());
|
||||
pluginAAXMultiMonoDisabledValue.referTo (projectRoot, Ids::pluginAAXDisableMultiMono, getUndoManager());
|
||||
|
||||
pluginVSTCategoryValue.referTo (projectRoot, Ids::pluginVSTCategory, getUndoManager(), getDefaultVSTCategories(), ",");
|
||||
pluginVST3CategoryValue.referTo (projectRoot, Ids::pluginVST3Category, getUndoManager(), getDefaultVSTCategories(), ",");
|
||||
pluginRTASCategoryValue.referTo (projectRoot, Ids::pluginRTASCategory, getUndoManager(), getDefaultRTASCategories(), ",");
|
||||
pluginAAXCategoryValue.referTo (projectRoot, Ids::pluginAAXCategory, getUndoManager(), getDefaultAAXCategories(), ",");
|
||||
}
|
||||
|
||||
void Project::updateOldStyleConfigList()
|
||||
|
|
@ -324,6 +313,119 @@ void Project::updateOldModulePaths()
|
|||
exporter->updateOldModulePaths();
|
||||
}
|
||||
|
||||
Array<Identifier> Project::getLegacyPluginFormatIdentifiers() noexcept
|
||||
{
|
||||
static Array<Identifier> legacyPluginFormatIdentifiers { Ids::buildVST, Ids::buildVST3, Ids::buildAU, Ids::buildAUv3,
|
||||
Ids::buildRTAS, Ids::buildAAX, Ids::buildStandalone, Ids::enableIAA };
|
||||
|
||||
return legacyPluginFormatIdentifiers;
|
||||
}
|
||||
|
||||
Array<Identifier> Project::getLegacyPluginCharacteristicsIdentifiers() noexcept
|
||||
{
|
||||
static Array<Identifier> legacyPluginCharacteristicsIdentifiers { Ids::pluginIsSynth, Ids::pluginWantsMidiIn, Ids::pluginProducesMidiOut,
|
||||
Ids::pluginIsMidiEffectPlugin, Ids::pluginEditorRequiresKeys, Ids::pluginRTASDisableBypass,
|
||||
Ids::pluginRTASDisableMultiMono, Ids::pluginAAXDisableBypass, Ids::pluginAAXDisableMultiMono };
|
||||
|
||||
return legacyPluginCharacteristicsIdentifiers;
|
||||
}
|
||||
|
||||
void Project::coalescePluginFormatValues()
|
||||
{
|
||||
Array<var> formatsToBuild;
|
||||
|
||||
for (auto& formatIdentifier : getLegacyPluginFormatIdentifiers())
|
||||
{
|
||||
if (projectRoot.getProperty (formatIdentifier, false))
|
||||
formatsToBuild.add (formatIdentifier.toString());
|
||||
}
|
||||
|
||||
if (formatsToBuild.size() > 0)
|
||||
{
|
||||
pluginFormatsValue = formatsToBuild;
|
||||
shouldWriteLegacyPluginFormatSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Project::coalescePluginCharacteristicsValues()
|
||||
{
|
||||
Array<var> pluginCharacteristics;
|
||||
|
||||
for (auto& characteristicIdentifier : getLegacyPluginCharacteristicsIdentifiers())
|
||||
{
|
||||
if (projectRoot.getProperty (characteristicIdentifier, false))
|
||||
pluginCharacteristics.add (characteristicIdentifier.toString());
|
||||
}
|
||||
|
||||
if (pluginCharacteristics.size() > 0)
|
||||
{
|
||||
pluginCharacteristicsValue = pluginCharacteristics;
|
||||
shouldWriteLegacyPluginCharacteristicsSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Project::updatePluginCategories()
|
||||
{
|
||||
{
|
||||
auto aaxCategory = projectRoot.getProperty (Ids::pluginAAXCategory, {}).toString();
|
||||
|
||||
if (aaxCategory.isNotEmpty())
|
||||
pluginAAXCategoryValue = Array<var> (getAllAAXCategoryVars()[getAllAAXCategoryStrings().indexOf (aaxCategory)]);
|
||||
}
|
||||
|
||||
{
|
||||
auto rtasCategory = projectRoot.getProperty (Ids::pluginRTASCategory, {}).toString();
|
||||
|
||||
if (rtasCategory.isNotEmpty())
|
||||
pluginRTASCategoryValue = Array<var> (getAllRTASCategoryVars()[getAllRTASCategoryStrings().indexOf (rtasCategory)]);
|
||||
}
|
||||
|
||||
{
|
||||
auto vstCategory = projectRoot.getProperty (Ids::pluginVSTCategory, {}).toString();
|
||||
|
||||
if (vstCategory.isNotEmpty() && getAllVSTCategoryStrings().contains (vstCategory))
|
||||
pluginVSTCategoryValue = Array<var> (vstCategory);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::writeLegacyPluginFormatSettings()
|
||||
{
|
||||
if (pluginFormatsValue.isUsingDefault())
|
||||
{
|
||||
for (auto& formatIdentifier : getLegacyPluginFormatIdentifiers())
|
||||
projectRoot.removeProperty (formatIdentifier, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto formatVar = pluginFormatsValue.get();
|
||||
|
||||
if (auto* arr = formatVar.getArray())
|
||||
{
|
||||
for (auto& formatIdentifier : getLegacyPluginFormatIdentifiers())
|
||||
projectRoot.setProperty (formatIdentifier, arr->contains (formatIdentifier.toString()), nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Project::writeLegacyPluginCharacteristicsSettings()
|
||||
{
|
||||
if (pluginFormatsValue.isUsingDefault())
|
||||
{
|
||||
for (auto& characteristicIdentifier : getLegacyPluginCharacteristicsIdentifiers())
|
||||
projectRoot.removeProperty (characteristicIdentifier, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto characteristicsVar = pluginCharacteristicsValue.get();
|
||||
|
||||
if (auto* arr = characteristicsVar.getArray())
|
||||
{
|
||||
for (auto& characteristicIdentifier : getLegacyPluginCharacteristicsIdentifiers())
|
||||
projectRoot.setProperty (characteristicIdentifier, arr->contains (characteristicIdentifier.toString()), nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static int getVersionElement (StringRef v, int index)
|
||||
{
|
||||
|
|
@ -429,6 +531,10 @@ Result Project::loadDocument (const File& file)
|
|||
initialiseMainGroup();
|
||||
initialiseAudioPluginValues();
|
||||
|
||||
coalescePluginFormatValues();
|
||||
coalescePluginCharacteristicsValues();
|
||||
updatePluginCategories();
|
||||
|
||||
parsedPreprocessorDefs = parsePreprocessorDefs (preprocessorDefsValue.get());
|
||||
|
||||
removeDefunctExporters();
|
||||
|
|
@ -563,6 +669,21 @@ void Project::valueTreePropertyChanged (ValueTree& tree, const Identifier& prope
|
|||
{
|
||||
sendProjectSettingAnalyticsEvent ("C++ Standard = " + cppStandardValue.get().toString());
|
||||
}
|
||||
else if (property == Ids::pluginFormats)
|
||||
{
|
||||
if (shouldWriteLegacyPluginFormatSettings)
|
||||
writeLegacyPluginFormatSettings();
|
||||
}
|
||||
else if (property == Ids::pluginCharacteristicsValue)
|
||||
{
|
||||
pluginVSTCategoryValue.setDefault (getDefaultVSTCategories());
|
||||
pluginVST3CategoryValue.setDefault (getDefaultVSTCategories());
|
||||
pluginRTASCategoryValue.setDefault (getDefaultRTASCategories());
|
||||
pluginAAXCategoryValue.setDefault (getDefaultAAXCategories());
|
||||
|
||||
if (shouldWriteLegacyPluginCharacteristicsSettings)
|
||||
writeLegacyPluginCharacteristicsSettings();
|
||||
}
|
||||
|
||||
changed();
|
||||
}
|
||||
|
|
@ -852,77 +973,63 @@ void Project::createPropertyEditors (PropertyListBuilder& props)
|
|||
|
||||
void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props)
|
||||
{
|
||||
props.add (new ChoicePropertyComponent (buildVSTValue, "Build VST"),
|
||||
"Whether the project should produce a VST plugin.");
|
||||
props.add (new ChoicePropertyComponent (buildVST3Value, "Build VST3"),
|
||||
"Whether the project should produce a VST3 plugin.");
|
||||
props.add (new ChoicePropertyComponent (buildAUValue, "Build AudioUnit"),
|
||||
"Whether the project should produce an AudioUnit plugin.");
|
||||
props.add (new ChoicePropertyComponent (buildAUv3Value, "Build AudioUnit v3"),
|
||||
"Whether the project should produce an AudioUnit version 3 plugin.");
|
||||
props.add (new ChoicePropertyComponent (buildRTASValue, "Build RTAS"),
|
||||
"Whether the project should produce an RTAS plugin.");
|
||||
props.add (new ChoicePropertyComponent (buildAAXValue, "Build AAX"),
|
||||
"Whether the project should produce an AAX plugin.");
|
||||
props.add (new ChoicePropertyComponent (buildStandaloneValue, "Build Standalone Plug-In"),
|
||||
"Whether the project should produce a standalone version of your plugin.");
|
||||
props.add (new ChoicePropertyComponent (enableIAAValue, "Enable Inter-App Audio"),
|
||||
"Whether a standalone plug-in should be an Inter-App Audio app. You should also enable the audio "
|
||||
"background capability in the iOS exporter.");
|
||||
props.add (new MultiChoicePropertyComponent (pluginFormatsValue, "Plugin Formats",
|
||||
{ "VST", "VST3", "AU", "AUv3", "RTAS", "AAX", "Standalone", "Enable IAA" },
|
||||
{ Ids::buildVST.toString(), Ids::buildVST3.toString(), Ids::buildAU.toString(), Ids::buildAUv3.toString(),
|
||||
Ids::buildRTAS.toString(), Ids::buildAAX.toString(), Ids::buildStandalone.toString(), Ids::enableIAA.toString() }),
|
||||
"Plugin formats to build.");
|
||||
props.add (new MultiChoicePropertyComponent (pluginCharacteristicsValue, "Plugin Characteristics",
|
||||
{ "Plugin is a Synth", "Plugin MIDI Input", "Plugin MIDI Output", "MIDI Effect Plugin", "Plugin Editor Requires Keyboard Focus",
|
||||
"Disable RTAS Bypass", "Disable AAX Bypass", "Disable RTAS Multi-Mono", "Disable AAX Multi-Mono" },
|
||||
{ Ids::pluginIsSynth.toString(), Ids::pluginWantsMidiIn.toString(), Ids::pluginProducesMidiOut.toString(),
|
||||
Ids::pluginIsMidiEffectPlugin.toString(), Ids::pluginEditorRequiresKeys.toString(), Ids::pluginRTASDisableBypass.toString(),
|
||||
Ids::pluginAAXDisableBypass.toString(), Ids::pluginRTASDisableMultiMono.toString(), Ids::pluginAAXDisableMultiMono.toString() }),
|
||||
"Some characteristics of your plugin such as whether it is a synth, produces MIDI messages, accepts MIDI messages etc.");
|
||||
|
||||
props.add (new TextPropertyComponent (pluginNameValue, "Plugin Name", 128, false),
|
||||
"The name of your plugin (keep it short!)");
|
||||
props.add (new TextPropertyComponent (pluginDescriptionValue, "Plugin Description", 256, false),
|
||||
"A short description of your plugin.");
|
||||
|
||||
props.add (new TextPropertyComponent (pluginManufacturerValue, "Plugin Manufacturer", 256, false),
|
||||
"The name of your company (cannot be blank).");
|
||||
props.add (new TextPropertyComponent (pluginManufacturerCodeValue, "Plugin Manufacturer Code", 4, false),
|
||||
"A four-character unique ID for your company. Note that for AU compatibility, this must contain at least one upper-case letter!");
|
||||
props.add (new TextPropertyComponent (pluginCodeValue, "Plugin Code", 4, false),
|
||||
"A four-character unique ID for your plugin. Note that for AU compatibility, this must contain at least one upper-case letter!");
|
||||
|
||||
props.add (new TextPropertyComponent (pluginChannelConfigsValue, "Plugin Channel Configurations", 1024, false),
|
||||
"This list is a comma-separated set list in the form {numIns, numOuts} and each pair indicates a valid plug-in "
|
||||
"configuration. For example {1, 1}, {2, 2} means that the plugin can be used either with 1 input and 1 output, "
|
||||
"or with 2 inputs and 2 outputs. If your plug-in requires side-chains, aux output buses etc., then you must leave "
|
||||
"this field empty and override the isBusesLayoutSupported callback in your AudioProcessor.");
|
||||
|
||||
props.add (new ChoicePropertyComponent (pluginIsSynthValue, "Plugin is a Synth"),
|
||||
"Enable this if you want your plugin to be treated as a synth or generator. It doesn't make much difference to the plugin itself, but some hosts treat synths differently to other plugins.");
|
||||
|
||||
props.add (new ChoicePropertyComponent (pluginWantsMidiInputValue, "Plugin Midi Input"),
|
||||
"Enable this if you want your plugin to accept midi messages.");
|
||||
|
||||
props.add (new ChoicePropertyComponent (pluginProducesMidiOutValue, "Plugin Midi Output"),
|
||||
"Enable this if your plugin is going to produce midi messages.");
|
||||
|
||||
props.add (new ChoicePropertyComponent (pluginIsMidiEffectPluginValue, "Midi Effect Plugin"),
|
||||
"Enable this if your plugin only processes midi and no audio.");
|
||||
|
||||
props.add (new ChoicePropertyComponent (pluginEditorNeedsKeyFocusValue, "Plugin Editor Requires Keyboard Focus"),
|
||||
"Enable this if your plugin needs keyboard input - some hosts can be a bit funny about keyboard focus..");
|
||||
|
||||
props.add (new TextPropertyComponent (pluginAAXIdentifierValue, "Plugin AAX Identifier", 256, false),
|
||||
"The value to use for the JucePlugin_AAXIdentifier setting");
|
||||
props.add (new TextPropertyComponent (pluginAUExportPrefixValue, "Plugin AU Export Prefix", 128, false),
|
||||
"A prefix for the names of exported entry-point functions that the component exposes - typically this will be a version of your plugin's name that can be used as part of a C++ token.");
|
||||
|
||||
props.add (new TextPropertyComponent (pluginAUMainTypeValue, "Plugin AU Main Type", 128, false),
|
||||
"In an AU, this is the value that is set as JucePlugin_AUMainType. Leave it blank unless you want to use a custom value.");
|
||||
|
||||
props.add (new TextPropertyComponent (pluginVSTCategoryValue, "Plugin VST Category", 128, false),
|
||||
"In a VST, this is the value that is set as JucePlugin_VSTCategory. Leave it blank unless you want to use a custom value.");
|
||||
{
|
||||
Array<var> vstCategoryVars;
|
||||
for (auto s : getAllVSTCategoryStrings())
|
||||
vstCategoryVars.add (s);
|
||||
|
||||
props.add (new TextPropertyComponent (pluginRTASCategoryValue, "Plugin RTAS Category", 128, false),
|
||||
"(Leave this blank if your plugin is a synth). This is one of the RTAS categories from FicPluginEnums.h, such as: ePlugInCategory_None, ePlugInCategory_EQ, ePlugInCategory_Dynamics, "
|
||||
"ePlugInCategory_PitchShift, ePlugInCategory_Reverb, ePlugInCategory_Delay, "
|
||||
"ePlugInCategory_Modulation, ePlugInCategory_Harmonic, ePlugInCategory_NoiseReduction, "
|
||||
"ePlugInCategory_Dither, ePlugInCategory_SoundField");
|
||||
props.add (new MultiChoicePropertyComponent (pluginVSTCategoryValue, "Plugin VST Category", getAllVSTCategoryStrings(), vstCategoryVars, 1),
|
||||
"VST category");
|
||||
}
|
||||
|
||||
props.add (new TextPropertyComponent (pluginAAXCategoryValue, "Plugin AAX Category", 128, false),
|
||||
"This is one of the categories from the AAX_EPlugInCategory enum");
|
||||
{
|
||||
Array<var> vst3CategoryVars;
|
||||
for (auto s : getAllVST3CategoryStrings())
|
||||
vst3CategoryVars.add (s);
|
||||
|
||||
props.add (new TextPropertyComponent (pluginAAXIdentifierValue, "Plugin AAX Identifier", 256, false),
|
||||
"The value to use for the JucePlugin_AAXIdentifier setting");
|
||||
props.add (new MultiChoicePropertyComponent (pluginVST3CategoryValue, "Plugin VST3 Category", getAllVST3CategoryStrings(), vst3CategoryVars),
|
||||
"VST3 category");
|
||||
}
|
||||
|
||||
props.add (new MultiChoicePropertyComponent (pluginRTASCategoryValue, "Plugin RTAS Category", getAllRTASCategoryStrings(), getAllRTASCategoryVars()),
|
||||
"RTAS category");
|
||||
props.add (new MultiChoicePropertyComponent (pluginAAXCategoryValue, "Plugin AAX Category", getAllAAXCategoryStrings(), getAllAAXCategoryVars()),
|
||||
"AAX category");
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1437,16 +1544,64 @@ bool Project::isConfigFlagEnabled (const String& name, bool defaultIsEnabled) co
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
String Project::getPluginRTASCategoryCode()
|
||||
static String getVSTCategoryStringFromSelection (Array<var> selected) noexcept
|
||||
{
|
||||
if (static_cast<bool> (isPluginSynth()))
|
||||
return "ePlugInCategory_SWGenerators";
|
||||
StringArray categories;
|
||||
|
||||
auto s = getPluginRTASCategoryString();
|
||||
if (s.isEmpty())
|
||||
s = "ePlugInCategory_None";
|
||||
for (auto& category : selected)
|
||||
categories.add (category);
|
||||
|
||||
return s;
|
||||
return categories.joinIntoString ("|");
|
||||
}
|
||||
|
||||
String Project::getVSTCategoryString() const noexcept
|
||||
{
|
||||
auto v = pluginVSTCategoryValue.get();
|
||||
|
||||
if (auto* arr = v.getArray())
|
||||
return getVSTCategoryStringFromSelection (*arr);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
String Project::getVST3CategoryString() const noexcept
|
||||
{
|
||||
auto v = pluginVST3CategoryValue.get();
|
||||
|
||||
if (auto* arr = v.getArray())
|
||||
return getVSTCategoryStringFromSelection (*arr);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int Project::getAAXCategory() const noexcept
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
auto v = pluginAAXCategoryValue.get();
|
||||
|
||||
if (auto* arr = v.getArray())
|
||||
{
|
||||
for (auto c : *arr)
|
||||
res |= static_cast<int> (c);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int Project::getRTASCategory() const noexcept
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
auto v = pluginRTASCategoryValue.get();
|
||||
|
||||
if (auto* arr = v.getArray())
|
||||
{
|
||||
for (auto c : *arr)
|
||||
res |= static_cast<int> (c);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
String Project::getAUMainTypeString()
|
||||
|
|
@ -1509,15 +1664,7 @@ String Project::getIAAPluginName()
|
|||
return s;
|
||||
}
|
||||
|
||||
String Project::getPluginVSTCategoryString()
|
||||
{
|
||||
auto s = pluginVSTCategoryValue.get().toString().trim();
|
||||
|
||||
if (s.isEmpty())
|
||||
s = isPluginSynth() ? "kPlugCategSynth" : "kPlugCategEffect";
|
||||
return s;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool Project::isAUPluginHost()
|
||||
{
|
||||
return getModules().isModuleEnabled ("juce_audio_processors") && isConfigFlagEnabled ("JUCE_PLUGINHOST_AU");
|
||||
|
|
@ -1533,6 +1680,96 @@ bool Project::isVST3PluginHost()
|
|||
return getModules().isModuleEnabled ("juce_audio_processors") && isConfigFlagEnabled ("JUCE_PLUGINHOST_VST3");
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
StringArray Project::getAllVSTCategoryStrings() noexcept
|
||||
{
|
||||
static StringArray vstCategoryStrings { "kPlugCategUnknown", "kPlugCategEffect", "kPlugCategSynth", "kPlugCategAnalysis", "kPlugCategMastering",
|
||||
"kPlugCategSpacializer", "kPlugCategRoomFx", "kPlugSurroundFx", "kPlugCategRestoration", "kPlugCategOfflineProcess",
|
||||
"kPlugCategShell", "kPlugCategGenerator" };
|
||||
return vstCategoryStrings;
|
||||
}
|
||||
|
||||
Array<var> Project::getDefaultVSTCategories() const noexcept
|
||||
{
|
||||
if (isPluginSynth())
|
||||
return { "kPlugCategSynth" };
|
||||
|
||||
return { "kPlugCategEffect" };
|
||||
}
|
||||
|
||||
StringArray Project::getAllVST3CategoryStrings() noexcept
|
||||
{
|
||||
static StringArray vst3CategoryStrings { "Fx", "Instrument", "Spatial", "Analyzer", "Delay", "Distortion", "EQ", "Filter", "Generator", "Mastering",
|
||||
"Modulation", "Pitch Shift", "Restoration", "Reverb", "Surround", "Tools", "Network", "Drum", "Sampler",
|
||||
"Synth", "External", "OnlyRT", "OnlyOfflineProcess", "NoOfflineProcess", "Up-Downmix" };
|
||||
|
||||
return vst3CategoryStrings;
|
||||
}
|
||||
|
||||
Array<var> Project::getDefaultVST3Categories() const noexcept
|
||||
{
|
||||
if (isPluginSynth())
|
||||
return { "Instrument", "Synth" };
|
||||
|
||||
return { "Fx" };
|
||||
}
|
||||
|
||||
StringArray Project::getAllAAXCategoryStrings() noexcept
|
||||
{
|
||||
static StringArray aaxCategoryStrings { "AAX_ePlugInCategory_None", "AAX_ePlugInCategory_EQ", "AAX_ePlugInCategory_Dynamics", "AAX_ePlugInCategory_PitchShift",
|
||||
"AAX_ePlugInCategory_Reverb", "AAX_ePlugInCategory_Delay", "AAX_ePlugInCategory_Modulation", "AAX_ePlugInCategory_Harmonic",
|
||||
"AAX_ePlugInCategory_NoiseReduction", "AAX_ePlugInCategory_Dither", "AAX_ePlugInCategory_SoundField", "AAX_ePlugInCategory_HWGenerators",
|
||||
"AAX_ePlugInCategory_SWGenerators", "AAX_ePlugInCategory_WrappedPlugin", "AAX_EPlugInCategory_Effect" };
|
||||
|
||||
return aaxCategoryStrings;
|
||||
}
|
||||
|
||||
Array<var> Project::getAllAAXCategoryVars() noexcept
|
||||
{
|
||||
static Array<var> aaxCategoryVars { 0x00000000, 0x00000001, 0x00000002, 0x00000004,
|
||||
0x00000008, 0x00000010, 0x00000020, 0x00000040,
|
||||
0x00000080, 0x00000100, 0x00000200, 0x00000400,
|
||||
0x00000800, 0x00001000, 0x00002000 };
|
||||
|
||||
return aaxCategoryVars;
|
||||
}
|
||||
|
||||
Array<var> Project::getDefaultAAXCategories() const noexcept
|
||||
{
|
||||
if (isPluginSynth())
|
||||
return getAllAAXCategoryVars()[getAllAAXCategoryStrings().indexOf ("AAX_ePlugInCategory_SWGenerators")];
|
||||
|
||||
return getAllAAXCategoryVars()[getAllAAXCategoryStrings().indexOf ("AAX_ePlugInCategory_None")];
|
||||
}
|
||||
|
||||
StringArray Project::getAllRTASCategoryStrings() noexcept
|
||||
{
|
||||
static StringArray rtasCategoryStrings { "ePlugInCategory_None", "ePlugInCategory_EQ", "ePlugInCategory_Dynamics", "ePlugInCategory_PitchShift",
|
||||
"ePlugInCategory_Reverb", "ePlugInCategory_Delay", "ePlugInCategory_Modulation", "ePlugInCategory_Harmonic",
|
||||
"ePlugInCategory_NoiseReduction", "ePlugInCategory_Dither", "ePlugInCategory_SoundField", "ePlugInCategory_HWGenerators",
|
||||
"ePlugInCategory_SWGenerators", "ePlugInCategory_WrappedPlugin", "ePlugInCategory_Effect" };
|
||||
|
||||
return rtasCategoryStrings;
|
||||
}
|
||||
|
||||
Array<var> Project::getAllRTASCategoryVars() noexcept
|
||||
{
|
||||
static Array<var> rtasCategoryVars { 0x00000000, 0x00000001, 0x00000002, 0x00000004,
|
||||
0x00000008, 0x00000010, 0x00000020, 0x00000040,
|
||||
0x00000080, 0x00000100, 0x00000200, 0x00000400,
|
||||
0x00000800, 0x00001000, 0x00002000 };
|
||||
|
||||
return rtasCategoryVars;
|
||||
}
|
||||
|
||||
Array<var> Project::getDefaultRTASCategories() const noexcept
|
||||
{
|
||||
if (isPluginSynth())
|
||||
return getAllRTASCategoryVars()[getAllRTASCategoryStrings().indexOf ("ePlugInCategory_SWGenerators")];
|
||||
|
||||
return getAllRTASCategoryVars()[getAllRTASCategoryStrings().indexOf ("ePlugInCategory_None")];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
EnabledModuleList& Project::getModules()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,16 +125,6 @@ public:
|
|||
|
||||
String getCppStandardString() const { return cppStandardValue.get(); }
|
||||
|
||||
//==============================================================================
|
||||
bool shouldBuildVST() const { return buildVSTValue.get(); }
|
||||
bool shouldBuildVST3() const { return buildVST3Value.get(); }
|
||||
bool shouldBuildAU() const { return buildAUValue.get(); }
|
||||
bool shouldBuildAUv3() const { return buildAUv3Value.get(); }
|
||||
bool shouldBuildRTAS() const { return buildRTASValue.get(); }
|
||||
bool shouldBuildAAX() const { return buildAAXValue.get(); }
|
||||
bool shouldBuildStandalonePlugin() const { return buildStandaloneValue.get(); }
|
||||
bool shouldEnableIAA() const { return enableIAAValue.get(); }
|
||||
|
||||
//==============================================================================
|
||||
String getPluginNameString() const { return pluginNameValue.get(); }
|
||||
String getPluginDescriptionString() const { return pluginDescriptionValue.get();}
|
||||
|
|
@ -142,29 +132,74 @@ public:
|
|||
String getPluginManufacturerCodeString() const { return pluginManufacturerCodeValue.get(); }
|
||||
String getPluginCodeString() const { return pluginCodeValue.get(); }
|
||||
String getPluginChannelConfigsString() const { return pluginChannelConfigsValue.get(); }
|
||||
String getAAXIdentifierString() const { return pluginAAXIdentifierValue.get(); }
|
||||
String getPluginAUExportPrefixString() const { return pluginAUExportPrefixValue.get(); }
|
||||
String getPluginAUMainTypeString() const { return pluginAUMainTypeValue.get(); }
|
||||
String getPluginRTASCategoryString() const { return pluginRTASCategoryValue.get(); }
|
||||
String getAAXIdentifierString() const { return pluginAAXIdentifierValue.get(); }
|
||||
String getPluginAAXCategoryString() const { return pluginAAXCategoryValue.get(); }
|
||||
|
||||
bool isPluginSynth() const { return pluginIsSynthValue.get(); }
|
||||
bool pluginWantsMidiInput() const { return pluginWantsMidiInputValue.get(); }
|
||||
bool pluginProducesMidiOutput() const { return pluginProducesMidiOutValue.get(); }
|
||||
bool isPluginMidiEffect() const { return pluginIsMidiEffectPluginValue.get(); }
|
||||
bool pluginEditorNeedsKeyFocus() const { return pluginEditorNeedsKeyFocusValue.get(); }
|
||||
bool isPluginRTASBypassDisabled() const { return pluginRTASBypassDisabledValue.get(); }
|
||||
bool isPluginRTASMultiMonoDisabled() const { return pluginRTASMultiMonoDisabledValue.get(); }
|
||||
bool isPluginAAXBypassDisabled() const { return pluginAAXBypassDisabledValue.get(); }
|
||||
bool isPluginAAXMultiMonoDisabled() const { return pluginAAXMultiMonoDisabledValue.get(); }
|
||||
//==============================================================================
|
||||
static bool checkMultiChoiceVar (const ValueWithDefault& valueToCheck, Identifier idToCheck) noexcept
|
||||
{
|
||||
if (! valueToCheck.get().isArray())
|
||||
return false;
|
||||
|
||||
auto v = valueToCheck.get();
|
||||
|
||||
if (auto* varArray = v.getArray())
|
||||
return varArray->contains (idToCheck.toString());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static StringArray getPluginFormatNames() noexcept;
|
||||
static Array<var> getPluginFormatVars() noexcept;
|
||||
|
||||
bool shouldBuildVST() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildVST); }
|
||||
bool shouldBuildVST3() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildVST3); }
|
||||
bool shouldBuildAU() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildAU); }
|
||||
bool shouldBuildAUv3() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildAUv3); }
|
||||
bool shouldBuildRTAS() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildRTAS); }
|
||||
bool shouldBuildAAX() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildAAX); }
|
||||
bool shouldBuildStandalonePlugin() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildStandalone); }
|
||||
bool shouldEnableIAA() const { return checkMultiChoiceVar (pluginFormatsValue, Ids::enableIAA); }
|
||||
|
||||
//==============================================================================
|
||||
bool isPluginSynth() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginIsSynth); }
|
||||
bool pluginWantsMidiInput() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginWantsMidiIn); }
|
||||
bool pluginProducesMidiOutput() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginProducesMidiOut); }
|
||||
bool isPluginMidiEffect() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginIsMidiEffectPlugin); }
|
||||
bool pluginEditorNeedsKeyFocus() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginEditorRequiresKeys); }
|
||||
bool isPluginRTASBypassDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginRTASDisableBypass); }
|
||||
bool isPluginRTASMultiMonoDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginRTASDisableMultiMono); }
|
||||
bool isPluginAAXBypassDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableBypass); }
|
||||
bool isPluginAAXMultiMonoDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableMultiMono); }
|
||||
|
||||
//==============================================================================
|
||||
static StringArray getAllVSTCategoryStrings() noexcept;
|
||||
Array<var> getDefaultVSTCategories() const noexcept;
|
||||
|
||||
static StringArray getAllVST3CategoryStrings() noexcept;
|
||||
Array<var> getDefaultVST3Categories() const noexcept;
|
||||
|
||||
static StringArray getAllAAXCategoryStrings() noexcept;
|
||||
static Array<var> getAllAAXCategoryVars() noexcept;
|
||||
Array<var> getDefaultAAXCategories() const noexcept;
|
||||
|
||||
static StringArray getAllRTASCategoryStrings() noexcept;
|
||||
static Array<var> getAllRTASCategoryVars() noexcept;
|
||||
Array<var> getDefaultRTASCategories() const noexcept;
|
||||
|
||||
String getVSTCategoryString() const noexcept;
|
||||
String getVST3CategoryString() const noexcept;
|
||||
int getAAXCategory() const noexcept;
|
||||
int getRTASCategory() const noexcept;
|
||||
|
||||
String getPluginRTASCategoryCode();
|
||||
String getAUMainTypeString();
|
||||
String getAUMainTypeCode();
|
||||
String getIAATypeCode();
|
||||
String getIAAPluginName();
|
||||
String getPluginVSTCategoryString();
|
||||
|
||||
//==============================================================================
|
||||
bool isAUPluginHost();
|
||||
bool isVSTPluginHost();
|
||||
bool isVST3PluginHost();
|
||||
|
|
@ -358,16 +393,27 @@ private:
|
|||
companyWebsiteValue, companyEmailValue, displaySplashScreenValue, reportAppUsageValue, splashScreenColourValue, cppStandardValue,
|
||||
headerSearchPathsValue, preprocessorDefsValue, userNotesValue, maxBinaryFileSizeValue, includeBinaryDataInAppConfigValue, binaryDataNamespaceValue;
|
||||
|
||||
ValueWithDefault buildVSTValue, buildVST3Value, buildAUValue, buildAUv3Value, buildRTASValue, buildAAXValue, buildStandaloneValue,
|
||||
enableIAAValue, pluginNameValue, pluginDescriptionValue, pluginManufacturerValue, pluginManufacturerCodeValue,
|
||||
pluginCodeValue, pluginChannelConfigsValue, pluginIsSynthValue, pluginWantsMidiInputValue, pluginProducesMidiOutValue,
|
||||
pluginIsMidiEffectPluginValue, pluginEditorNeedsKeyFocusValue, pluginVSTCategoryValue, pluginAUExportPrefixValue,
|
||||
pluginAUMainTypeValue, pluginRTASCategoryValue, pluginRTASBypassDisabledValue, pluginRTASMultiMonoDisabledValue,
|
||||
pluginAAXIdentifierValue, pluginAAXCategoryValue, pluginAAXBypassDisabledValue, pluginAAXMultiMonoDisabledValue;
|
||||
ValueWithDefault pluginFormatsValue, pluginNameValue, pluginDescriptionValue, pluginManufacturerValue, pluginManufacturerCodeValue,
|
||||
pluginCodeValue, pluginChannelConfigsValue, pluginCharacteristicsValue, pluginAUExportPrefixValue, pluginAAXIdentifierValue,
|
||||
pluginAUMainTypeValue, pluginRTASCategoryValue, pluginVSTCategoryValue, pluginVST3CategoryValue, pluginAAXCategoryValue;
|
||||
|
||||
//==============================================================================
|
||||
CompileEngineSettings compileEngineSettings { projectRoot };
|
||||
|
||||
//==============================================================================
|
||||
bool shouldWriteLegacyPluginFormatSettings = false;
|
||||
bool shouldWriteLegacyPluginCharacteristicsSettings = false;
|
||||
|
||||
static Array<Identifier> getLegacyPluginFormatIdentifiers() noexcept;
|
||||
static Array<Identifier> getLegacyPluginCharacteristicsIdentifiers() noexcept;
|
||||
|
||||
void writeLegacyPluginFormatSettings();
|
||||
void writeLegacyPluginCharacteristicsSettings();
|
||||
|
||||
void coalescePluginFormatValues();
|
||||
void coalescePluginCharacteristicsValues();
|
||||
void updatePluginCategories();
|
||||
|
||||
//==============================================================================
|
||||
File tempDirectory = {};
|
||||
bool openInIDEAfterSaving = false;
|
||||
|
|
|
|||
|
|
@ -100,14 +100,15 @@ void ProjectSaver::writePluginCharacteristicsFile()
|
|||
flags.set ("JucePlugin_VersionCode", project.getVersionAsHex());
|
||||
flags.set ("JucePlugin_VersionString", toStringLiteral (project.getVersionString()));
|
||||
flags.set ("JucePlugin_VSTUniqueID", "JucePlugin_PluginCode");
|
||||
flags.set ("JucePlugin_VSTCategory", project.getPluginVSTCategoryString());
|
||||
flags.set ("JucePlugin_VSTCategory", project.getVSTCategoryString());
|
||||
flags.set ("JucePlugin_Vst3Category", toStringLiteral (project.getVST3CategoryString()));
|
||||
flags.set ("JucePlugin_AUMainType", project.getAUMainTypeString());
|
||||
flags.set ("JucePlugin_AUSubType", "JucePlugin_PluginCode");
|
||||
flags.set ("JucePlugin_AUExportPrefix", project.getPluginAUExportPrefixString());
|
||||
flags.set ("JucePlugin_AUExportPrefixQuoted", toStringLiteral (project.getPluginAUExportPrefixString()));
|
||||
flags.set ("JucePlugin_AUManufacturerCode", "JucePlugin_ManufacturerCode");
|
||||
flags.set ("JucePlugin_CFBundleIdentifier", project.getBundleIdentifierString());
|
||||
flags.set ("JucePlugin_RTASCategory", project.getPluginRTASCategoryCode());
|
||||
flags.set ("JucePlugin_RTASCategory", String (project.getRTASCategory()));
|
||||
flags.set ("JucePlugin_RTASManufacturerCode", "JucePlugin_ManufacturerCode");
|
||||
flags.set ("JucePlugin_RTASProductId", "JucePlugin_PluginCode");
|
||||
flags.set ("JucePlugin_RTASDisableBypass", boolToString (project.isPluginRTASBypassDisabled()));
|
||||
|
|
@ -115,7 +116,7 @@ void ProjectSaver::writePluginCharacteristicsFile()
|
|||
flags.set ("JucePlugin_AAXIdentifier", project.getAAXIdentifierString());
|
||||
flags.set ("JucePlugin_AAXManufacturerCode", "JucePlugin_ManufacturerCode");
|
||||
flags.set ("JucePlugin_AAXProductId", "JucePlugin_PluginCode");
|
||||
flags.set ("JucePlugin_AAXCategory", project.getPluginAAXCategoryString());
|
||||
flags.set ("JucePlugin_AAXCategory", String (project.getAAXCategory()));
|
||||
flags.set ("JucePlugin_AAXDisableBypass", boolToString (project.isPluginAAXBypassDisabled()));
|
||||
flags.set ("JucePlugin_AAXDisableMultiMono", boolToString (project.isPluginAAXMultiMonoDisabled()));
|
||||
flags.set ("JucePlugin_IAAType", toCharLiteral (project.getIAATypeCode()));
|
||||
|
|
@ -127,8 +128,8 @@ void ProjectSaver::writePluginCharacteristicsFile()
|
|||
|
||||
if (plugInChannelConfig.isNotEmpty())
|
||||
{
|
||||
flags.set ("JucePlugin_MaxNumInputChannels", String (countMaxPluginChannels (plugInChannelConfig, true)));
|
||||
flags.set ("JucePlugin_MaxNumOutputChannels", String (countMaxPluginChannels (plugInChannelConfig, false)));
|
||||
flags.set ("JucePlugin_MaxNumInputChannels", String (countMaxPluginChannels (plugInChannelConfig, true)));
|
||||
flags.set ("JucePlugin_MaxNumOutputChannels", String (countMaxPluginChannels (plugInChannelConfig, false)));
|
||||
flags.set ("JucePlugin_PreferredChannelConfigurations", plugInChannelConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ namespace Ids
|
|||
DECLARE_ID (enableIncrementalLinking);
|
||||
DECLARE_ID (bundleIdentifier);
|
||||
DECLARE_ID (aaxIdentifier);
|
||||
DECLARE_ID (aaxCategory);
|
||||
DECLARE_ID (aaxFolder);
|
||||
DECLARE_ID (compile);
|
||||
DECLARE_ID (noWarnings);
|
||||
|
|
@ -289,6 +288,7 @@ namespace Ids
|
|||
DECLARE_ID (classDecl);
|
||||
DECLARE_ID (initialisers);
|
||||
DECLARE_ID (destructors);
|
||||
DECLARE_ID (pluginFormats);
|
||||
DECLARE_ID (buildVST);
|
||||
DECLARE_ID (buildVST3);
|
||||
DECLARE_ID (buildAU);
|
||||
|
|
@ -303,12 +303,14 @@ namespace Ids
|
|||
DECLARE_ID (pluginManufacturerCode);
|
||||
DECLARE_ID (pluginCode);
|
||||
DECLARE_ID (pluginChannelConfigs);
|
||||
DECLARE_ID (pluginCharacteristicsValue);
|
||||
DECLARE_ID (pluginIsSynth);
|
||||
DECLARE_ID (pluginWantsMidiIn);
|
||||
DECLARE_ID (pluginProducesMidiOut);
|
||||
DECLARE_ID (pluginIsMidiEffectPlugin);
|
||||
DECLARE_ID (pluginEditorRequiresKeys);
|
||||
DECLARE_ID (pluginVSTCategory);
|
||||
DECLARE_ID (pluginVST3Category);
|
||||
DECLARE_ID (pluginAUExportPrefix);
|
||||
DECLARE_ID (pluginAUMainType);
|
||||
DECLARE_ID (pluginRTASCategory);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue