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.

674 lines
37KB

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