The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../Application/jucer_Headers.h"
  20. #include "jucer_ProjectSaver.h"
  21. #include "jucer_ProjectExport_CLion.h"
  22. //==============================================================================
  23. namespace
  24. {
  25. inline int countMaxPluginChannels (const String& configString, bool isInput)
  26. {
  27. auto configs = StringArray::fromTokens (configString, ", {}", {});
  28. configs.trim();
  29. configs.removeEmptyStrings();
  30. jassert ((configs.size() & 1) == 0); // looks like a syntax error in the configs?
  31. int maxVal = 0;
  32. for (int i = (isInput ? 0 : 1); i < configs.size(); i += 2)
  33. maxVal = jmax (maxVal, configs[i].getIntValue());
  34. return maxVal;
  35. }
  36. inline String boolToString (bool b)
  37. {
  38. return b ? "1" : "0";
  39. }
  40. inline String toStringLiteral (const String& v)
  41. {
  42. return CppTokeniserFunctions::addEscapeChars (v).quoted();
  43. }
  44. inline String toCharLiteral (const String& v)
  45. {
  46. auto fourCharCode = v.substring (0, 4);
  47. uint32 hexRepresentation = 0;
  48. for (int i = 0; i < 4; ++i)
  49. hexRepresentation = (hexRepresentation << 8u)
  50. | (static_cast<unsigned int> (fourCharCode[i]) & 0xffu);
  51. return "0x" + String::toHexString (static_cast<int> (hexRepresentation))
  52. + " // "
  53. + CppTokeniserFunctions::addEscapeChars (fourCharCode).quoted ('\'');
  54. }
  55. }
  56. //==============================================================================
  57. void ProjectSaver::writePluginCharacteristicsFile()
  58. {
  59. StringPairArray flags;
  60. flags.set ("JucePlugin_Build_VST", boolToString (project.shouldBuildVST()));
  61. flags.set ("JucePlugin_Build_VST3", boolToString (project.shouldBuildVST3()));
  62. flags.set ("JucePlugin_Build_AU", boolToString (project.shouldBuildAU()));
  63. flags.set ("JucePlugin_Build_AUv3", boolToString (project.shouldBuildAUv3()));
  64. flags.set ("JucePlugin_Build_RTAS", boolToString (project.shouldBuildRTAS()));
  65. flags.set ("JucePlugin_Build_AAX", boolToString (project.shouldBuildAAX()));
  66. flags.set ("JucePlugin_Build_Standalone", boolToString (project.shouldBuildStandalonePlugin()));
  67. flags.set ("JucePlugin_Build_Unity", boolToString (project.shouldBuildUnityPlugin()));
  68. flags.set ("JucePlugin_Enable_IAA", boolToString (project.shouldEnableIAA()));
  69. flags.set ("JucePlugin_Name", toStringLiteral (project.getPluginNameString()));
  70. flags.set ("JucePlugin_Desc", toStringLiteral (project.getPluginDescriptionString()));
  71. flags.set ("JucePlugin_Manufacturer", toStringLiteral (project.getPluginManufacturerString()));
  72. flags.set ("JucePlugin_ManufacturerWebsite", toStringLiteral (project.getCompanyWebsiteString()));
  73. flags.set ("JucePlugin_ManufacturerEmail", toStringLiteral (project.getCompanyEmailString()));
  74. flags.set ("JucePlugin_ManufacturerCode", toCharLiteral (project.getPluginManufacturerCodeString()));
  75. flags.set ("JucePlugin_PluginCode", toCharLiteral (project.getPluginCodeString()));
  76. flags.set ("JucePlugin_IsSynth", boolToString (project.isPluginSynth()));
  77. flags.set ("JucePlugin_WantsMidiInput", boolToString (project.pluginWantsMidiInput()));
  78. flags.set ("JucePlugin_ProducesMidiOutput", boolToString (project.pluginProducesMidiOutput()));
  79. flags.set ("JucePlugin_IsMidiEffect", boolToString (project.isPluginMidiEffect()));
  80. flags.set ("JucePlugin_EditorRequiresKeyboardFocus", boolToString (project.pluginEditorNeedsKeyFocus()));
  81. flags.set ("JucePlugin_Version", project.getVersionString());
  82. flags.set ("JucePlugin_VersionCode", project.getVersionAsHex());
  83. flags.set ("JucePlugin_VersionString", toStringLiteral (project.getVersionString()));
  84. flags.set ("JucePlugin_VSTUniqueID", "JucePlugin_PluginCode");
  85. flags.set ("JucePlugin_VSTCategory", project.getVSTCategoryString());
  86. flags.set ("JucePlugin_Vst3Category", toStringLiteral (project.getVST3CategoryString()));
  87. flags.set ("JucePlugin_AUMainType", project.getAUMainTypeString());
  88. flags.set ("JucePlugin_AUSubType", "JucePlugin_PluginCode");
  89. flags.set ("JucePlugin_AUExportPrefix", project.getPluginAUExportPrefixString());
  90. flags.set ("JucePlugin_AUExportPrefixQuoted", toStringLiteral (project.getPluginAUExportPrefixString()));
  91. flags.set ("JucePlugin_AUManufacturerCode", "JucePlugin_ManufacturerCode");
  92. flags.set ("JucePlugin_CFBundleIdentifier", project.getBundleIdentifierString());
  93. flags.set ("JucePlugin_RTASCategory", String (project.getRTASCategory()));
  94. flags.set ("JucePlugin_RTASManufacturerCode", "JucePlugin_ManufacturerCode");
  95. flags.set ("JucePlugin_RTASProductId", "JucePlugin_PluginCode");
  96. flags.set ("JucePlugin_RTASDisableBypass", boolToString (project.isPluginRTASBypassDisabled()));
  97. flags.set ("JucePlugin_RTASDisableMultiMono", boolToString (project.isPluginRTASMultiMonoDisabled()));
  98. flags.set ("JucePlugin_AAXIdentifier", project.getAAXIdentifierString());
  99. flags.set ("JucePlugin_AAXManufacturerCode", "JucePlugin_ManufacturerCode");
  100. flags.set ("JucePlugin_AAXProductId", "JucePlugin_PluginCode");
  101. flags.set ("JucePlugin_AAXCategory", String (project.getAAXCategory()));
  102. flags.set ("JucePlugin_AAXDisableBypass", boolToString (project.isPluginAAXBypassDisabled()));
  103. flags.set ("JucePlugin_AAXDisableMultiMono", boolToString (project.isPluginAAXMultiMonoDisabled()));
  104. flags.set ("JucePlugin_IAAType", toCharLiteral (project.getIAATypeCode()));
  105. flags.set ("JucePlugin_IAASubType", "JucePlugin_PluginCode");
  106. flags.set ("JucePlugin_IAAName", project.getIAAPluginName().quoted());
  107. flags.set ("JucePlugin_VSTNumMidiInputs", project.getVSTNumMIDIInputsString());
  108. flags.set ("JucePlugin_VSTNumMidiOutputs", project.getVSTNumMIDIOutputsString());
  109. {
  110. String plugInChannelConfig = project.getPluginChannelConfigsString();
  111. if (plugInChannelConfig.isNotEmpty())
  112. {
  113. flags.set ("JucePlugin_MaxNumInputChannels", String (countMaxPluginChannels (plugInChannelConfig, true)));
  114. flags.set ("JucePlugin_MaxNumOutputChannels", String (countMaxPluginChannels (plugInChannelConfig, false)));
  115. flags.set ("JucePlugin_PreferredChannelConfigurations", plugInChannelConfig);
  116. }
  117. }
  118. MemoryOutputStream mem;
  119. mem.setNewLineString (projectLineFeed);
  120. mem << "//==============================================================================" << newLine
  121. << "// Audio plugin settings.." << newLine
  122. << newLine;
  123. for (int i = 0; i < flags.size(); ++i)
  124. {
  125. mem << "#ifndef " << flags.getAllKeys()[i] << newLine
  126. << " #define " << flags.getAllKeys()[i].paddedRight (' ', 32) << " "
  127. << flags.getAllValues()[i] << newLine
  128. << "#endif" << newLine;
  129. }
  130. setExtraAppConfigFileContent (mem.toString());
  131. }
  132. void ProjectSaver::writeProjects (const OwnedArray<LibraryModule>& modules, const String& specifiedExporterToSave, bool isCommandLineApp)
  133. {
  134. ThreadPool threadPool;
  135. // keep a copy of the basic generated files group, as each exporter may modify it.
  136. auto originalGeneratedGroup = generatedFilesGroup.state.createCopy();
  137. CLionProjectExporter* clionExporter = nullptr;
  138. OwnedArray<ProjectExporter> exporters;
  139. try
  140. {
  141. for (Project::ExporterIterator exp (project); exp.next();)
  142. {
  143. if (specifiedExporterToSave.isNotEmpty() && exp->getName() != specifiedExporterToSave)
  144. continue;
  145. auto exporter = exporters.add (std::move (exp.exporter));
  146. exporter->initialiseDependencyPathValues();
  147. if (exporter->getTargetFolder().createDirectory())
  148. {
  149. if (exporter->isCLion())
  150. {
  151. clionExporter = dynamic_cast<CLionProjectExporter*> (exporter);
  152. }
  153. else
  154. {
  155. exporter->copyMainGroupFromProject();
  156. exporter->settings = exporter->settings.createCopy();
  157. exporter->addToExtraSearchPaths (RelativePath ("JuceLibraryCode", RelativePath::projectFolder));
  158. generatedFilesGroup.state = originalGeneratedGroup.createCopy();
  159. exporter->addSettingsForProjectType (project.getProjectType());
  160. for (auto& module: modules)
  161. module->addSettingsForModuleToExporter (*exporter, *this);
  162. generatedFilesGroup.sortAlphabetically (true, true);
  163. exporter->getAllGroups().add (generatedFilesGroup);
  164. }
  165. if (isCommandLineApp)
  166. saveExporter (exporter, modules);
  167. else
  168. threadPool.addJob (new ExporterJob (*this, exporter, modules), true);
  169. }
  170. else
  171. {
  172. addError ("Can't create folder: " + exporter->getTargetFolder().getFullPathName());
  173. }
  174. }
  175. }
  176. catch (ProjectExporter::SaveError& saveError)
  177. {
  178. addError (saveError.message);
  179. }
  180. if (! isCommandLineApp)
  181. while (threadPool.getNumJobs() > 0)
  182. Thread::sleep (10);
  183. if (clionExporter != nullptr)
  184. {
  185. for (auto* exporter : exporters)
  186. clionExporter->writeCMakeListsExporterSection (exporter);
  187. std::cout << "Finished saving: " << clionExporter->getName() << std::endl;
  188. }
  189. }