diff --git a/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h b/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h index f9404b277c..1994965567 100644 --- a/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h +++ b/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h @@ -265,7 +265,15 @@ public: } if (auto* multiChoice = dynamic_cast (prop)) - multiChoice->onHeightChange = [this] { updateSize (getX(), getY(), getWidth()); }; + { + multiChoice->onHeightChange = [this] + { + updateSize (getX(), getY(), getWidth()); + + if (auto* parent = getParentComponent()) + parent->parentSizeChanged(); + }; + } } } diff --git a/extras/Projucer/Source/Project/jucer_Project.cpp b/extras/Projucer/Source/Project/jucer_Project.cpp index 8f97c84cb3..99e53eb9c6 100644 --- a/extras/Projucer/Source/Project/jucer_Project.cpp +++ b/extras/Projucer/Source/Project/jucer_Project.cpp @@ -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 (Ids::buildVST.toString(), Ids::buildAU.toString()), ","); + pluginCharacteristicsValue.referTo (projectRoot, Ids::pluginCharacteristicsValue, getUndoManager(), Array (), ","); - 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 Project::getLegacyPluginFormatIdentifiers() noexcept +{ + static Array legacyPluginFormatIdentifiers { Ids::buildVST, Ids::buildVST3, Ids::buildAU, Ids::buildAUv3, + Ids::buildRTAS, Ids::buildAAX, Ids::buildStandalone, Ids::enableIAA }; + + return legacyPluginFormatIdentifiers; +} + +Array Project::getLegacyPluginCharacteristicsIdentifiers() noexcept +{ + static Array 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 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 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 (getAllAAXCategoryVars()[getAllAAXCategoryStrings().indexOf (aaxCategory)]); + } + + { + auto rtasCategory = projectRoot.getProperty (Ids::pluginRTASCategory, {}).toString(); + + if (rtasCategory.isNotEmpty()) + pluginRTASCategoryValue = Array (getAllRTASCategoryVars()[getAllRTASCategoryStrings().indexOf (rtasCategory)]); + } + + { + auto vstCategory = projectRoot.getProperty (Ids::pluginVSTCategory, {}).toString(); + + if (vstCategory.isNotEmpty() && getAllVSTCategoryStrings().contains (vstCategory)) + pluginVSTCategoryValue = Array (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 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 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 selected) noexcept { - if (static_cast (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 (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 (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 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 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 Project::getAllAAXCategoryVars() noexcept +{ + static Array aaxCategoryVars { 0x00000000, 0x00000001, 0x00000002, 0x00000004, + 0x00000008, 0x00000010, 0x00000020, 0x00000040, + 0x00000080, 0x00000100, 0x00000200, 0x00000400, + 0x00000800, 0x00001000, 0x00002000 }; + + return aaxCategoryVars; +} + +Array 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 Project::getAllRTASCategoryVars() noexcept +{ + static Array rtasCategoryVars { 0x00000000, 0x00000001, 0x00000002, 0x00000004, + 0x00000008, 0x00000010, 0x00000020, 0x00000040, + 0x00000080, 0x00000100, 0x00000200, 0x00000400, + 0x00000800, 0x00001000, 0x00002000 }; + + return rtasCategoryVars; +} + +Array Project::getDefaultRTASCategories() const noexcept +{ + if (isPluginSynth()) + return getAllRTASCategoryVars()[getAllRTASCategoryStrings().indexOf ("ePlugInCategory_SWGenerators")]; + + return getAllRTASCategoryVars()[getAllRTASCategoryStrings().indexOf ("ePlugInCategory_None")]; +} + //============================================================================== EnabledModuleList& Project::getModules() { diff --git a/extras/Projucer/Source/Project/jucer_Project.h b/extras/Projucer/Source/Project/jucer_Project.h index 445235a764..0379ab1d9b 100644 --- a/extras/Projucer/Source/Project/jucer_Project.h +++ b/extras/Projucer/Source/Project/jucer_Project.h @@ -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 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 getDefaultVSTCategories() const noexcept; + + static StringArray getAllVST3CategoryStrings() noexcept; + Array getDefaultVST3Categories() const noexcept; + + static StringArray getAllAAXCategoryStrings() noexcept; + static Array getAllAAXCategoryVars() noexcept; + Array getDefaultAAXCategories() const noexcept; + + static StringArray getAllRTASCategoryStrings() noexcept; + static Array getAllRTASCategoryVars() noexcept; + Array 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 getLegacyPluginFormatIdentifiers() noexcept; + static Array getLegacyPluginCharacteristicsIdentifiers() noexcept; + + void writeLegacyPluginFormatSettings(); + void writeLegacyPluginCharacteristicsSettings(); + + void coalescePluginFormatValues(); + void coalescePluginCharacteristicsValues(); + void updatePluginCategories(); + //============================================================================== File tempDirectory = {}; bool openInIDEAfterSaving = false; diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp index 1e077f16d3..d5075906a8 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp @@ -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); } } diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h index 045e9cf92d..172a0182ef 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h @@ -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);