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.

615 lines
34KB

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