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.

671 lines
37KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #ifndef __JUCER_AUDIOPLUGINMODULE_JUCEHEADER__
  18. #define __JUCER_AUDIOPLUGINMODULE_JUCEHEADER__
  19. //==============================================================================
  20. namespace
  21. {
  22. Value shouldBuildVST (Project& project) { return project.getProjectValue ("buildVST"); }
  23. Value shouldBuildVST3 (Project& project) { return project.getProjectValue ("buildVST3"); }
  24. Value shouldBuildAU (Project& project) { return project.getProjectValue ("buildAU"); }
  25. Value shouldBuildRTAS (Project& project) { return project.getProjectValue ("buildRTAS"); }
  26. Value shouldBuildAAX (Project& project) { return project.getProjectValue ("buildAAX"); }
  27. Value getPluginName (Project& project) { return project.getProjectValue ("pluginName"); }
  28. Value getPluginDesc (Project& project) { return project.getProjectValue ("pluginDesc"); }
  29. Value getPluginManufacturer (Project& project) { return project.getProjectValue ("pluginManufacturer"); }
  30. Value getPluginManufacturerCode (Project& project) { return project.getProjectValue ("pluginManufacturerCode"); }
  31. Value getPluginCode (Project& project) { return project.getProjectValue ("pluginCode"); }
  32. Value getPluginChannelConfigs (Project& project) { return project.getProjectValue ("pluginChannelConfigs"); }
  33. Value getPluginIsSynth (Project& project) { return project.getProjectValue ("pluginIsSynth"); }
  34. Value getPluginWantsMidiInput (Project& project) { return project.getProjectValue ("pluginWantsMidiIn"); }
  35. Value getPluginProducesMidiOut (Project& project) { return project.getProjectValue ("pluginProducesMidiOut"); }
  36. Value getPluginSilenceInProducesSilenceOut (Project& project) { return project.getProjectValue ("pluginSilenceInIsSilenceOut"); }
  37. Value getPluginEditorNeedsKeyFocus (Project& project) { return project.getProjectValue ("pluginEditorRequiresKeys"); }
  38. Value getPluginVSTCategory (Project& project) { return project.getProjectValue ("pluginVSTCategory"); }
  39. Value getPluginAUExportPrefix (Project& project) { return project.getProjectValue ("pluginAUExportPrefix"); }
  40. Value getPluginAUMainType (Project& project) { return project.getProjectValue ("pluginAUMainType"); }
  41. Value getPluginRTASCategory (Project& project) { return project.getProjectValue ("pluginRTASCategory"); }
  42. Value getPluginRTASBypassDisabled (Project& project) { return project.getProjectValue ("pluginRTASDisableBypass"); }
  43. Value getPluginRTASMultiMonoDisabled (Project& project) { return project.getProjectValue ("pluginRTASDisableMultiMono"); }
  44. Value getPluginAAXCategory (Project& project) { return project.getProjectValue ("pluginAAXCategory"); }
  45. Value getPluginAAXBypassDisabled (Project& project) { return project.getProjectValue ("pluginAAXDisableBypass"); }
  46. Value getPluginAAXMultiMonoDisabled (Project& project) { return project.getProjectValue ("pluginAAXDisableMultiMono"); }
  47. String getPluginRTASCategoryCode (Project& project)
  48. {
  49. if (static_cast <bool> (getPluginIsSynth (project).getValue()))
  50. return "ePlugInCategory_SWGenerators";
  51. String s (getPluginRTASCategory (project).toString());
  52. if (s.isEmpty())
  53. s = "ePlugInCategory_None";
  54. return s;
  55. }
  56. String getAUMainTypeString (Project& project)
  57. {
  58. String s (getPluginAUMainType (project).toString());
  59. if (s.isEmpty())
  60. {
  61. if (getPluginIsSynth (project).getValue()) s = "kAudioUnitType_MusicDevice";
  62. else if (getPluginWantsMidiInput (project).getValue()) s = "kAudioUnitType_MusicEffect";
  63. else s = "kAudioUnitType_Effect";
  64. }
  65. return s;
  66. }
  67. String getAUMainTypeCode (Project& project)
  68. {
  69. String s (getPluginAUMainType (project).toString());
  70. if (s.isEmpty())
  71. {
  72. if (getPluginIsSynth (project).getValue()) s = "aumu";
  73. else if (getPluginWantsMidiInput (project).getValue()) s = "aumf";
  74. else s = "aufx";
  75. }
  76. return s;
  77. }
  78. String getPluginVSTCategoryString (Project& project)
  79. {
  80. String s (getPluginVSTCategory (project).toString().trim());
  81. if (s.isEmpty())
  82. s = static_cast<bool> (getPluginIsSynth (project).getValue()) ? "kPlugCategSynth"
  83. : "kPlugCategEffect";
  84. return s;
  85. }
  86. int countMaxPluginChannels (const String& configString, bool isInput)
  87. {
  88. StringArray configs;
  89. configs.addTokens (configString, ", {}", String::empty);
  90. configs.trim();
  91. configs.removeEmptyStrings();
  92. jassert ((configs.size() & 1) == 0); // looks like a syntax error in the configs?
  93. int maxVal = 0;
  94. for (int i = (isInput ? 0 : 1); i < configs.size(); i += 2)
  95. maxVal = jmax (maxVal, configs[i].getIntValue());
  96. return maxVal;
  97. }
  98. String valueToBool (const Value& v)
  99. {
  100. return static_cast<bool> (v.getValue()) ? "1" : "0";
  101. }
  102. String valueToStringLiteral (const var& v)
  103. {
  104. return CodeHelpers::addEscapeChars (v.toString()).quoted();
  105. }
  106. String valueToCharLiteral (const var& v)
  107. {
  108. return CodeHelpers::addEscapeChars (v.toString().trim().substring (0, 4)).quoted ('\'');
  109. }
  110. void writePluginCharacteristicsFile (ProjectSaver& projectSaver)
  111. {
  112. Project& project = projectSaver.project;
  113. StringPairArray flags;
  114. //flags.set ("JUCE_MODAL_LOOPS_PERMITTED", "0");
  115. flags.set ("JucePlugin_Build_VST", valueToBool (shouldBuildVST (project)));
  116. flags.set ("JucePlugin_Build_VST3", valueToBool (shouldBuildVST3 (project)));
  117. flags.set ("JucePlugin_Build_AU", valueToBool (shouldBuildAU (project)));
  118. flags.set ("JucePlugin_Build_RTAS", valueToBool (shouldBuildRTAS (project)));
  119. flags.set ("JucePlugin_Build_AAX", valueToBool (shouldBuildAAX (project)));
  120. flags.set ("JucePlugin_Name", valueToStringLiteral (getPluginName (project)));
  121. flags.set ("JucePlugin_Desc", valueToStringLiteral (getPluginDesc (project)));
  122. flags.set ("JucePlugin_Manufacturer", valueToStringLiteral (getPluginManufacturer (project)));
  123. flags.set ("JucePlugin_ManufacturerWebsite", valueToStringLiteral (project.getCompanyWebsite()));
  124. flags.set ("JucePlugin_ManufacturerEmail", valueToStringLiteral (project.getCompanyEmail()));
  125. flags.set ("JucePlugin_ManufacturerCode", valueToCharLiteral (getPluginManufacturerCode (project)));
  126. flags.set ("JucePlugin_PluginCode", valueToCharLiteral (getPluginCode (project)));
  127. flags.set ("JucePlugin_MaxNumInputChannels", String (countMaxPluginChannels (getPluginChannelConfigs (project).toString(), true)));
  128. flags.set ("JucePlugin_MaxNumOutputChannels", String (countMaxPluginChannels (getPluginChannelConfigs (project).toString(), false)));
  129. flags.set ("JucePlugin_PreferredChannelConfigurations", getPluginChannelConfigs (project).toString());
  130. flags.set ("JucePlugin_IsSynth", valueToBool (getPluginIsSynth (project)));
  131. flags.set ("JucePlugin_WantsMidiInput", valueToBool (getPluginWantsMidiInput (project)));
  132. flags.set ("JucePlugin_ProducesMidiOutput", valueToBool (getPluginProducesMidiOut (project)));
  133. flags.set ("JucePlugin_SilenceInProducesSilenceOut", valueToBool (getPluginSilenceInProducesSilenceOut (project)));
  134. flags.set ("JucePlugin_EditorRequiresKeyboardFocus", valueToBool (getPluginEditorNeedsKeyFocus (project)));
  135. flags.set ("JucePlugin_Version", project.getVersionString());
  136. flags.set ("JucePlugin_VersionCode", project.getVersionAsHex());
  137. flags.set ("JucePlugin_VersionString", valueToStringLiteral (project.getVersionString()));
  138. flags.set ("JucePlugin_VSTUniqueID", "JucePlugin_PluginCode");
  139. flags.set ("JucePlugin_VSTCategory", getPluginVSTCategoryString (project));
  140. flags.set ("JucePlugin_AUMainType", getAUMainTypeString (project));
  141. flags.set ("JucePlugin_AUSubType", "JucePlugin_PluginCode");
  142. flags.set ("JucePlugin_AUExportPrefix", getPluginAUExportPrefix (project).toString());
  143. flags.set ("JucePlugin_AUExportPrefixQuoted", valueToStringLiteral (getPluginAUExportPrefix (project)));
  144. flags.set ("JucePlugin_AUManufacturerCode", "JucePlugin_ManufacturerCode");
  145. flags.set ("JucePlugin_CFBundleIdentifier", project.getBundleIdentifier().toString());
  146. flags.set ("JucePlugin_RTASCategory", getPluginRTASCategoryCode (project));
  147. flags.set ("JucePlugin_RTASManufacturerCode", "JucePlugin_ManufacturerCode");
  148. flags.set ("JucePlugin_RTASProductId", "JucePlugin_PluginCode");
  149. flags.set ("JucePlugin_RTASDisableBypass", valueToBool (getPluginRTASBypassDisabled (project)));
  150. flags.set ("JucePlugin_RTASDisableMultiMono", valueToBool (getPluginRTASMultiMonoDisabled (project)));
  151. flags.set ("JucePlugin_AAXIdentifier", project.getAAXIdentifier().toString());
  152. flags.set ("JucePlugin_AAXManufacturerCode", "JucePlugin_ManufacturerCode");
  153. flags.set ("JucePlugin_AAXProductId", "JucePlugin_PluginCode");
  154. flags.set ("JucePlugin_AAXCategory", getPluginAAXCategory (project).toString());
  155. flags.set ("JucePlugin_AAXDisableBypass", valueToBool (getPluginAAXBypassDisabled (project)));
  156. flags.set ("JucePlugin_AAXDisableMultiMono", valueToBool (getPluginAAXMultiMonoDisabled (project)));
  157. MemoryOutputStream mem;
  158. mem << "//==============================================================================" << newLine
  159. << "// Audio plugin settings.." << newLine
  160. << newLine;
  161. for (int i = 0; i < flags.size(); ++i)
  162. {
  163. mem << "#ifndef " << flags.getAllKeys()[i] << newLine
  164. << " #define " << flags.getAllKeys()[i].paddedRight (' ', 32) << " "
  165. << flags.getAllValues()[i] << newLine
  166. << "#endif" << newLine;
  167. }
  168. projectSaver.setExtraAppConfigFileContent (mem.toString());
  169. }
  170. static void fixMissingXcodePostBuildScript (ProjectExporter& exporter)
  171. {
  172. if (exporter.isXcode() && exporter.settings [Ids::postbuildCommand].toString().isEmpty())
  173. exporter.getSetting (Ids::postbuildCommand) = String::fromUTF8 (BinaryData::AudioPluginXCodeScript_txt,
  174. BinaryData::AudioPluginXCodeScript_txtSize);
  175. }
  176. String createEscapedStringForVersion (ProjectExporter& exporter, const String& text)
  177. {
  178. // (VS10 automatically adds escape characters to the quotes for this definition)
  179. return exporter.getVisualStudioVersion() < 10 ? CodeHelpers::addEscapeChars (text.quoted())
  180. : CodeHelpers::addEscapeChars (text).quoted();
  181. }
  182. String createRebasedPath (ProjectExporter& exporter, const RelativePath& path)
  183. {
  184. return createEscapedStringForVersion (exporter,
  185. exporter.rebaseFromProjectFolderToBuildTarget (path)
  186. .toWindowsStyle());
  187. }
  188. }
  189. //==============================================================================
  190. namespace VSTHelpers
  191. {
  192. static Value getVSTFolder (ProjectExporter& exporter, bool isVST3)
  193. {
  194. return exporter.getSetting (isVST3 ? Ids::vst3Folder
  195. : Ids::vstFolder);
  196. }
  197. static void addVSTFolderToPath (ProjectExporter& exporter, bool isVST3)
  198. {
  199. const String vstFolder (getVSTFolder (exporter, isVST3).toString());
  200. if (vstFolder.isNotEmpty())
  201. {
  202. RelativePath path (exporter.rebaseFromProjectFolderToBuildTarget (RelativePath (vstFolder, RelativePath::projectFolder)));
  203. if (exporter.isVisualStudio())
  204. exporter.extraSearchPaths.add (path.toWindowsStyle());
  205. else if (exporter.isLinux() || exporter.isXcode())
  206. exporter.extraSearchPaths.insert (0, path.toUnixStyle());
  207. }
  208. }
  209. static void createVSTPathEditor (ProjectExporter& exporter, PropertyListBuilder& props, bool isVST3)
  210. {
  211. const String vstFormat (isVST3 ? "VST3" : "VST");
  212. props.add (new TextPropertyComponent (getVSTFolder (exporter, isVST3), vstFormat + " Folder", 1024, false),
  213. "If you're building a " + vstFormat + ", this must be the folder containing the " + vstFormat + " SDK. This should be an absolute path.");
  214. }
  215. static void fixMissingVSTValues (ProjectExporter& exporter, bool isVST3)
  216. {
  217. if (getVSTFolder (exporter, isVST3).toString().isEmpty())
  218. getVSTFolder (exporter, isVST3) = exporter.isWindows() ? (isVST3 ? "c:\\SDKs\\VST3 SDK" : "c:\\SDKs\\vstsdk2.4")
  219. : (isVST3 ? "~/SDKs/VST3 SDK" : "~/SDKs/vstsdk2.4");
  220. fixMissingXcodePostBuildScript (exporter);
  221. }
  222. static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver, bool isVST3)
  223. {
  224. fixMissingVSTValues (exporter, isVST3);
  225. writePluginCharacteristicsFile (projectSaver);
  226. exporter.makefileTargetSuffix = ".so";
  227. Project::Item group (Project::Item::createGroup (const_cast<ProjectExporter&> (exporter).getProject(),
  228. "Juce VST Wrapper", "__jucevstfiles"));
  229. RelativePath juceWrapperFolder (exporter.getProject().getGeneratedCodeFolder(),
  230. exporter.getTargetFolder(), RelativePath::buildTargetFolder);
  231. addVSTFolderToPath (exporter, isVST3);
  232. if (exporter.isWindows())
  233. exporter.extraSearchPaths.add (juceWrapperFolder.toWindowsStyle());
  234. else if (exporter.isLinux())
  235. exporter.extraSearchPaths.add (juceWrapperFolder.toUnixStyle());
  236. if (exporter.isVisualStudio())
  237. {
  238. if (! exporter.getExtraLinkerFlagsString().contains ("/FORCE:multiple"))
  239. exporter.getExtraLinkerFlags() = exporter.getExtraLinkerFlags().toString() + " /FORCE:multiple";
  240. RelativePath modulePath (exporter.rebaseFromProjectFolderToBuildTarget (RelativePath (exporter.getPathForModuleString ("juce_audio_plugin_client"),
  241. RelativePath::projectFolder)
  242. .getChildFile ("juce_audio_plugin_client")
  243. .getChildFile ("VST3")));
  244. for (ProjectExporter::ConfigIterator config (exporter); config.next();)
  245. {
  246. if (config->getValue (Ids::useRuntimeLibDLL).getValue().isVoid())
  247. config->getValue (Ids::useRuntimeLibDLL) = true;
  248. if (config->getValue (Ids::postbuildCommand).toString().isEmpty())
  249. config->getValue (Ids::postbuildCommand) = "copy /Y \"$(OutDir)\\$(TargetFileName)\" \"$(OutDir)\\$(TargetName).vst3\"";
  250. }
  251. }
  252. }
  253. static inline void createPropertyEditors (ProjectExporter& exporter, PropertyListBuilder& props, bool isVST3)
  254. {
  255. fixMissingVSTValues (exporter, isVST3);
  256. createVSTPathEditor (exporter, props, isVST3);
  257. }
  258. }
  259. //==============================================================================
  260. namespace RTASHelpers
  261. {
  262. static Value getRTASFolder (ProjectExporter& exporter) { return exporter.getSetting (Ids::rtasFolder); }
  263. static RelativePath getRTASFolderPath (ProjectExporter& exporter) { return RelativePath (exporter.getSettingString (Ids::rtasFolder),
  264. RelativePath::projectFolder); }
  265. static bool isExporterSupported (ProjectExporter& exporter) { return exporter.isVisualStudio() || exporter.isXcode(); }
  266. static void fixMissingRTASValues (ProjectExporter& exporter)
  267. {
  268. if (getRTASFolder (exporter).toString().isEmpty())
  269. {
  270. if (exporter.isVisualStudio())
  271. getRTASFolder (exporter) = "c:\\SDKs\\PT_80_SDK";
  272. else
  273. getRTASFolder (exporter) = "~/SDKs/PT_80_SDK";
  274. }
  275. fixMissingXcodePostBuildScript (exporter);
  276. }
  277. static void addExtraSearchPaths (ProjectExporter& exporter)
  278. {
  279. RelativePath rtasFolder (getRTASFolderPath (exporter));
  280. if (exporter.isVisualStudio())
  281. {
  282. RelativePath juceWrapperFolder (exporter.getProject().getGeneratedCodeFolder(),
  283. exporter.getTargetFolder(), RelativePath::buildTargetFolder);
  284. exporter.extraSearchPaths.add (juceWrapperFolder.toWindowsStyle());
  285. static const char* p[] = { "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses",
  286. "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses",
  287. "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses/Interfaces",
  288. "AlturaPorts/TDMPlugins/PluginLibrary/Utilities",
  289. "AlturaPorts/TDMPlugins/PluginLibrary/RTASP_Adapt",
  290. "AlturaPorts/TDMPlugins/PluginLibrary/CoreClasses",
  291. "AlturaPorts/TDMPlugins/PluginLibrary/Controls",
  292. "AlturaPorts/TDMPlugins/PluginLibrary/Meters",
  293. "AlturaPorts/TDMPlugins/PluginLibrary/ViewClasses",
  294. "AlturaPorts/TDMPlugins/PluginLibrary/DSPClasses",
  295. "AlturaPorts/TDMPlugins/PluginLibrary/Interfaces",
  296. "AlturaPorts/TDMPlugins/common",
  297. "AlturaPorts/TDMPlugins/common/Platform",
  298. "AlturaPorts/TDMPlugins/common/Macros",
  299. "AlturaPorts/TDMPlugins/SignalProcessing/Public",
  300. "AlturaPorts/TDMPlugIns/DSPManager/Interfaces",
  301. "AlturaPorts/SADriver/Interfaces",
  302. "AlturaPorts/DigiPublic/Interfaces",
  303. "AlturaPorts/DigiPublic",
  304. "AlturaPorts/Fic/Interfaces/DAEClient",
  305. "AlturaPorts/NewFileLibs/Cmn",
  306. "AlturaPorts/NewFileLibs/DOA",
  307. "AlturaPorts/AlturaSource/PPC_H",
  308. "AlturaPorts/AlturaSource/AppSupport",
  309. "AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc",
  310. "xplat/AVX/avx2/avx2sdk/inc" };
  311. for (int i = 0; i < numElementsInArray (p); ++i)
  312. exporter.addToExtraSearchPaths (rtasFolder.getChildFile (p[i]));
  313. }
  314. else if (exporter.isXcode())
  315. {
  316. exporter.extraSearchPaths.add ("$(DEVELOPER_DIR)/Headers/FlatCarbon");
  317. exporter.extraSearchPaths.add ("$(SDKROOT)/Developer/Headers/FlatCarbon");
  318. static const char* p[] = { "AlturaPorts/TDMPlugIns/PlugInLibrary/Controls",
  319. "AlturaPorts/TDMPlugIns/PlugInLibrary/CoreClasses",
  320. "AlturaPorts/TDMPlugIns/PlugInLibrary/DSPClasses",
  321. "AlturaPorts/TDMPlugIns/PlugInLibrary/EffectClasses",
  322. "AlturaPorts/TDMPlugIns/PlugInLibrary/MacBuild",
  323. "AlturaPorts/TDMPlugIns/PlugInLibrary/Meters",
  324. "AlturaPorts/TDMPlugIns/PlugInLibrary/ProcessClasses",
  325. "AlturaPorts/TDMPlugIns/PlugInLibrary/ProcessClasses/Interfaces",
  326. "AlturaPorts/TDMPlugIns/PlugInLibrary/RTASP_Adapt",
  327. "AlturaPorts/TDMPlugIns/PlugInLibrary/Utilities",
  328. "AlturaPorts/TDMPlugIns/PlugInLibrary/ViewClasses",
  329. "AlturaPorts/TDMPlugIns/DSPManager/**",
  330. "AlturaPorts/TDMPlugIns/SupplementalPlugInLib/Encryption",
  331. "AlturaPorts/TDMPlugIns/SupplementalPlugInLib/GraphicsExtensions",
  332. "AlturaPorts/TDMPlugIns/common/**",
  333. "AlturaPorts/TDMPlugIns/common/PI_LibInterface",
  334. "AlturaPorts/TDMPlugIns/PACEProtection/**",
  335. "AlturaPorts/TDMPlugIns/SignalProcessing/**",
  336. "AlturaPorts/OMS/Headers",
  337. "AlturaPorts/Fic/Interfaces/**",
  338. "AlturaPorts/Fic/Source/SignalNets",
  339. "AlturaPorts/DSIPublicInterface/PublicHeaders",
  340. "DAEWin/Include",
  341. "AlturaPorts/DigiPublic/Interfaces",
  342. "AlturaPorts/DigiPublic",
  343. "AlturaPorts/NewFileLibs/DOA",
  344. "AlturaPorts/NewFileLibs/Cmn",
  345. "xplat/AVX/avx2/avx2sdk/inc",
  346. "xplat/AVX/avx2/avx2sdk/utils" };
  347. for (int i = 0; i < numElementsInArray (p); ++i)
  348. exporter.addToExtraSearchPaths (rtasFolder.getChildFile (p[i]));
  349. }
  350. }
  351. static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver)
  352. {
  353. if (isExporterSupported (exporter))
  354. {
  355. fixMissingRTASValues (exporter);
  356. const RelativePath rtasFolder (getRTASFolderPath (exporter));
  357. if (exporter.isVisualStudio())
  358. {
  359. exporter.msvcTargetSuffix = ".dpm";
  360. exporter.msvcExtraPreprocessorDefs.set ("JucePlugin_WinBag_path",
  361. createRebasedPath (exporter,
  362. rtasFolder.getChildFile ("WinBag")));
  363. exporter.msvcDelayLoadedDLLs = "DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; "
  364. "DSPManager.dll; DSPManager.dll; DSPManagerClientLib.dll; RTASClientLib.dll";
  365. if (! exporter.getExtraLinkerFlagsString().contains ("/FORCE:multiple"))
  366. exporter.getExtraLinkerFlags() = exporter.getExtraLinkerFlags().toString() + " /FORCE:multiple";
  367. RelativePath modulePath (exporter.rebaseFromProjectFolderToBuildTarget (RelativePath (exporter.getPathForModuleString ("juce_audio_plugin_client"),
  368. RelativePath::projectFolder)
  369. .getChildFile ("juce_audio_plugin_client")
  370. .getChildFile ("RTAS")));
  371. for (ProjectExporter::ConfigIterator config (exporter); config.next();)
  372. {
  373. config->getValue (Ids::msvcModuleDefinitionFile) = modulePath.getChildFile ("juce_RTAS_WinExports.def").toWindowsStyle();
  374. if (config->getValue (Ids::useRuntimeLibDLL).getValue().isVoid())
  375. config->getValue (Ids::useRuntimeLibDLL) = true;
  376. if (config->getValue (Ids::postbuildCommand).toString().isEmpty())
  377. config->getValue (Ids::postbuildCommand)
  378. = "copy /Y "
  379. + modulePath.getChildFile ("juce_RTAS_WinResources.rsr").toWindowsStyle().quoted()
  380. + " \"$(TargetPath)\".rsr";
  381. }
  382. }
  383. else
  384. {
  385. exporter.xcodeCanUseDwarf = false;
  386. exporter.xcodeExtraLibrariesDebug.add (rtasFolder.getChildFile ("MacBag/Libs/Debug/libPluginLibrary.a"));
  387. exporter.xcodeExtraLibrariesRelease.add (rtasFolder.getChildFile ("MacBag/Libs/Release/libPluginLibrary.a"));
  388. }
  389. writePluginCharacteristicsFile (projectSaver);
  390. addExtraSearchPaths (exporter);
  391. }
  392. }
  393. static inline void createPropertyEditors (ProjectExporter& exporter, PropertyListBuilder& props)
  394. {
  395. if (isExporterSupported (exporter))
  396. {
  397. fixMissingRTASValues (exporter);
  398. props.add (new TextPropertyComponent (getRTASFolder (exporter), "RTAS Folder", 1024, false),
  399. "If you're building an RTAS, this must be the folder containing the RTAS SDK. This should be an absolute path.");
  400. }
  401. }
  402. }
  403. //==============================================================================
  404. namespace AUHelpers
  405. {
  406. static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver)
  407. {
  408. writePluginCharacteristicsFile (projectSaver);
  409. if (exporter.isXcode())
  410. {
  411. exporter.extraSearchPaths.add ("$(DEVELOPER_DIR)/Extras/CoreAudio/PublicUtility");
  412. exporter.extraSearchPaths.add ("$(DEVELOPER_DIR)/Extras/CoreAudio/AudioUnits/AUPublic/Utility");
  413. exporter.extraSearchPaths.add ("$(DEVELOPER_DIR)/Extras/CoreAudio/AudioUnits/AUPublic/AUBase");
  414. exporter.xcodeFrameworks.addTokens ("AudioUnit CoreAudioKit", false);
  415. exporter.xcodeExcludedFiles64Bit = "\"*Carbon*.cpp\"";
  416. Project::Item subGroup (projectSaver.getGeneratedCodeGroup().addNewSubGroup ("Juce AU Wrapper", -1));
  417. subGroup.setID ("__juceappleaufiles");
  418. {
  419. #define JUCE_AU_PUBLICUTILITY "${DEVELOPER_DIR}/Extras/CoreAudio/PublicUtility/"
  420. #define JUCE_AU_PUBLIC "${DEVELOPER_DIR}/Extras/CoreAudio/AudioUnits/AUPublic/"
  421. static const char* appleAUFiles[] =
  422. {
  423. JUCE_AU_PUBLICUTILITY "CADebugMacros.h",
  424. JUCE_AU_PUBLICUTILITY "CAAUParameter.cpp",
  425. JUCE_AU_PUBLICUTILITY "CAAUParameter.h",
  426. JUCE_AU_PUBLICUTILITY "CAAudioChannelLayout.cpp",
  427. JUCE_AU_PUBLICUTILITY "CAAudioChannelLayout.h",
  428. JUCE_AU_PUBLICUTILITY "CAMutex.cpp",
  429. JUCE_AU_PUBLICUTILITY "CAMutex.h",
  430. JUCE_AU_PUBLICUTILITY "CAStreamBasicDescription.cpp",
  431. JUCE_AU_PUBLICUTILITY "CAStreamBasicDescription.h",
  432. JUCE_AU_PUBLICUTILITY "CAVectorUnitTypes.h",
  433. JUCE_AU_PUBLICUTILITY "CAVectorUnit.cpp",
  434. JUCE_AU_PUBLICUTILITY "CAVectorUnit.h",
  435. JUCE_AU_PUBLIC "AUViewBase/AUViewLocalizedStringKeys.h",
  436. JUCE_AU_PUBLIC "AUCarbonViewBase/AUCarbonViewDispatch.cpp",
  437. JUCE_AU_PUBLIC "AUCarbonViewBase/AUCarbonViewControl.cpp",
  438. JUCE_AU_PUBLIC "AUCarbonViewBase/AUCarbonViewControl.h",
  439. JUCE_AU_PUBLIC "AUCarbonViewBase/CarbonEventHandler.cpp",
  440. JUCE_AU_PUBLIC "AUCarbonViewBase/CarbonEventHandler.h",
  441. JUCE_AU_PUBLIC "AUCarbonViewBase/AUCarbonViewBase.cpp",
  442. JUCE_AU_PUBLIC "AUCarbonViewBase/AUCarbonViewBase.h",
  443. JUCE_AU_PUBLIC "AUBase/AUBase.cpp",
  444. JUCE_AU_PUBLIC "AUBase/AUBase.h",
  445. JUCE_AU_PUBLIC "AUBase/AUDispatch.cpp",
  446. JUCE_AU_PUBLIC "AUBase/AUDispatch.h",
  447. JUCE_AU_PUBLIC "AUBase/AUInputElement.cpp",
  448. JUCE_AU_PUBLIC "AUBase/AUInputElement.h",
  449. JUCE_AU_PUBLIC "AUBase/AUOutputElement.cpp",
  450. JUCE_AU_PUBLIC "AUBase/AUOutputElement.h",
  451. JUCE_AU_PUBLIC "AUBase/AUResources.r",
  452. JUCE_AU_PUBLIC "AUBase/AUScopeElement.cpp",
  453. JUCE_AU_PUBLIC "AUBase/AUScopeElement.h",
  454. JUCE_AU_PUBLIC "AUBase/ComponentBase.cpp",
  455. JUCE_AU_PUBLIC "AUBase/ComponentBase.h",
  456. JUCE_AU_PUBLIC "OtherBases/AUMIDIBase.cpp",
  457. JUCE_AU_PUBLIC "OtherBases/AUMIDIBase.h",
  458. JUCE_AU_PUBLIC "OtherBases/AUMIDIEffectBase.cpp",
  459. JUCE_AU_PUBLIC "OtherBases/AUMIDIEffectBase.h",
  460. JUCE_AU_PUBLIC "OtherBases/AUOutputBase.cpp",
  461. JUCE_AU_PUBLIC "OtherBases/AUOutputBase.h",
  462. JUCE_AU_PUBLIC "OtherBases/MusicDeviceBase.cpp",
  463. JUCE_AU_PUBLIC "OtherBases/MusicDeviceBase.h",
  464. JUCE_AU_PUBLIC "OtherBases/AUEffectBase.cpp",
  465. JUCE_AU_PUBLIC "OtherBases/AUEffectBase.h",
  466. JUCE_AU_PUBLIC "Utility/AUBuffer.cpp",
  467. JUCE_AU_PUBLIC "Utility/AUBuffer.h",
  468. JUCE_AU_PUBLIC "Utility/AUInputFormatConverter.h",
  469. JUCE_AU_PUBLIC "Utility/AUSilentTimeout.h",
  470. JUCE_AU_PUBLIC "Utility/AUTimestampGenerator.h",
  471. nullptr
  472. };
  473. for (const char** f = appleAUFiles; *f != nullptr; ++f)
  474. {
  475. const RelativePath file (*f, RelativePath::projectFolder);
  476. subGroup.addRelativeFile (file, -1, file.hasFileExtension ("cpp;mm"));
  477. subGroup.getChild (subGroup.getNumChildren() - 1).getShouldInhibitWarningsValue() = true;
  478. }
  479. }
  480. if (exporter.isXcode())
  481. {
  482. XmlElement plistKey ("key");
  483. plistKey.addTextElement ("AudioComponents");
  484. XmlElement plistEntry ("array");
  485. XmlElement* dict = plistEntry.createNewChildElement ("dict");
  486. Project& project = exporter.getProject();
  487. addPlistDictionaryKey (dict, "name", getPluginManufacturer (project).toString()
  488. + ": " + getPluginName (project).toString());
  489. addPlistDictionaryKey (dict, "description", getPluginDesc (project).toString());
  490. addPlistDictionaryKey (dict, "factoryFunction", getPluginAUExportPrefix (project).toString() + "Factory");
  491. addPlistDictionaryKey (dict, "manufacturer", getPluginManufacturerCode (project).toString().trim().substring (0, 4));
  492. addPlistDictionaryKey (dict, "type", getAUMainTypeCode (project));
  493. addPlistDictionaryKey (dict, "subtype", getPluginCode (project).toString().trim().substring (0, 4));
  494. addPlistDictionaryKeyInt (dict, "version", project.getVersionAsHexInteger());
  495. exporter.xcodeExtraPListEntries.add (plistKey);
  496. exporter.xcodeExtraPListEntries.add (plistEntry);
  497. }
  498. }
  499. }
  500. }
  501. //==============================================================================
  502. namespace AAXHelpers
  503. {
  504. static Value getAAXFolder (ProjectExporter& exporter) { return exporter.getSetting (Ids::aaxFolder); }
  505. static RelativePath getAAXFolderPath (ProjectExporter& exporter) { return RelativePath (exporter.getSettingString (Ids::aaxFolder),
  506. RelativePath::projectFolder); }
  507. static bool isExporterSupported (ProjectExporter& exporter) { return exporter.isVisualStudio() || exporter.isXcode(); }
  508. static void fixMissingAAXValues (ProjectExporter& exporter)
  509. {
  510. if (getAAXFolder (exporter).toString().isEmpty())
  511. {
  512. if (exporter.isVisualStudio())
  513. getAAXFolder (exporter) = "c:\\SDKs\\AAX";
  514. else
  515. getAAXFolder (exporter) = "~/SDKs/AAX";
  516. }
  517. fixMissingXcodePostBuildScript (exporter);
  518. }
  519. static void addExtraSearchPaths (ProjectExporter& exporter)
  520. {
  521. const RelativePath aaxFolder (getAAXFolderPath (exporter));
  522. exporter.addToExtraSearchPaths (aaxFolder);
  523. exporter.addToExtraSearchPaths (aaxFolder.getChildFile ("Interfaces"));
  524. exporter.addToExtraSearchPaths (aaxFolder.getChildFile ("Interfaces").getChildFile ("ACF"));
  525. }
  526. static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver)
  527. {
  528. if (isExporterSupported (exporter))
  529. {
  530. fixMissingAAXValues (exporter);
  531. const RelativePath aaxLibsFolder (getAAXFolderPath (exporter).getChildFile ("Libs"));
  532. if (exporter.isVisualStudio())
  533. {
  534. exporter.msvcTargetSuffix = ".aaxplugin";
  535. for (ProjectExporter::ConfigIterator config (exporter); config.next();)
  536. if (config->getValue (Ids::useRuntimeLibDLL).getValue().isVoid())
  537. config->getValue (Ids::useRuntimeLibDLL) = true;
  538. exporter.msvcExtraPreprocessorDefs.set ("JucePlugin_AAXLibs_path",
  539. createRebasedPath (exporter, aaxLibsFolder));
  540. }
  541. else
  542. {
  543. exporter.xcodeExtraLibrariesDebug.add (aaxLibsFolder.getChildFile ("Debug/libAAXLibrary.a"));
  544. exporter.xcodeExtraLibrariesRelease.add (aaxLibsFolder.getChildFile ("Release/libAAXLibrary.a"));
  545. }
  546. writePluginCharacteristicsFile (projectSaver);
  547. addExtraSearchPaths (exporter);
  548. }
  549. }
  550. static inline void createPropertyEditors (ProjectExporter& exporter, PropertyListBuilder& props)
  551. {
  552. if (isExporterSupported (exporter))
  553. {
  554. fixMissingAAXValues (exporter);
  555. props.add (new TextPropertyComponent (getAAXFolder (exporter), "AAX SDK Folder", 1024, false),
  556. "If you're building an AAX, this must be the folder containing the AAX SDK. This should be an absolute path.");
  557. }
  558. }
  559. }
  560. #endif // __JUCER_AUDIOPLUGINMODULE_JUCEHEADER__