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.

202 lines
5.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #pragma once
  19. #include "jucer_LiveCodeBuilderDLL.h"
  20. //==============================================================================
  21. struct CompileEngineDLL : private DeletedAtShutdown
  22. {
  23. CompileEngineDLL()
  24. {
  25. tryLoadDll();
  26. }
  27. ~CompileEngineDLL()
  28. {
  29. shutdown();
  30. clearSingletonInstance();
  31. }
  32. bool tryLoadDll()
  33. {
  34. // never load the dynamic lib multiple times
  35. if (! isLoaded())
  36. {
  37. auto f = findDLLFile();
  38. if (f != File() && dll.open (f.getLinkedTarget().getFullPathName()))
  39. {
  40. #define INIT_LIVE_DLL_FN(name, returnType, params) name = (name##_type) dll.getFunction (#name);
  41. LIVE_DLL_FUNCTIONS (INIT_LIVE_DLL_FN);
  42. #undef INIT_LIVE_DLL_FN
  43. return true;
  44. }
  45. return false;
  46. }
  47. return true;
  48. }
  49. void initialise (CrashCallbackFunction crashFn, QuitCallbackFunction quitFn, bool setupSignals)
  50. {
  51. if (isLoaded())
  52. projucer_initialise (crashFn, quitFn, setPropertyCallback, getPropertyCallback, setupSignals);
  53. }
  54. void shutdown()
  55. {
  56. if (isLoaded())
  57. projucer_shutdown();
  58. }
  59. bool isLoaded() const
  60. {
  61. #define CHECK_LIVE_DLL_FN(name, returnType, params) if (name == nullptr) return false;
  62. LIVE_DLL_FUNCTIONS (CHECK_LIVE_DLL_FN);
  63. #undef CHECK_LIVE_DLL_FN
  64. return projucer_getVersion() == requiredVersion;
  65. }
  66. #define DECLARE_LIVE_DLL_FN(name, returnType, params) \
  67. typedef returnType (*name##_type) params; \
  68. name##_type name = nullptr;
  69. LIVE_DLL_FUNCTIONS (DECLARE_LIVE_DLL_FN)
  70. #undef DECLARE_LIVE_DLL_FN
  71. static String getDLLName()
  72. {
  73. #if JUCE_MAC
  74. return "JUCECompileEngine.dylib";
  75. #elif JUCE_LINUX
  76. return "JUCECompileEngine.so";
  77. #elif JUCE_WINDOWS
  78. return "JUCECompileEngine.dll";
  79. #else
  80. #error
  81. return "JUCECompileEngine.so";
  82. #endif
  83. }
  84. static File getVersionedUserAppSupportFolder()
  85. {
  86. auto userAppData = File::getSpecialLocation (File::userApplicationDataDirectory);
  87. #if JUCE_MAC
  88. userAppData = userAppData.getChildFile ("Application Support");
  89. #endif
  90. return userAppData.getChildFile ("Projucer").getChildFile (String ("CompileEngine-") + ProjectInfo::versionString);
  91. }
  92. JUCE_DECLARE_SINGLETON (CompileEngineDLL, false)
  93. private:
  94. DynamicLibrary dll;
  95. enum { requiredVersion = 2 };
  96. static File findDLLFile()
  97. {
  98. auto dllFile = File();
  99. if (tryFindDLLFileInAppFolder (dllFile))
  100. return dllFile;
  101. #if JUCE_MAC
  102. if (tryFindDLLFileInAppBundle(dllFile))
  103. return dllFile;
  104. #endif
  105. if (tryFindDLLFileInAppConfigFolder (dllFile))
  106. return dllFile;
  107. return {};
  108. }
  109. #if JUCE_MAC
  110. static bool tryFindDLLFileInAppBundle (File& outFile)
  111. {
  112. File currentAppFile (File::getSpecialLocation (File::currentApplicationFile));
  113. return tryFindDLLFileInFolder (currentAppFile.getChildFile ("Contents"), outFile);
  114. }
  115. #endif
  116. static bool tryFindDLLFileInAppFolder (File& outFile)
  117. {
  118. auto currentAppFile = File::getSpecialLocation (File::currentApplicationFile);
  119. return tryFindDLLFileInFolder (currentAppFile.getParentDirectory(), outFile);
  120. }
  121. static bool tryFindDLLFileInAppConfigFolder (File& outFile)
  122. {
  123. auto userAppDataFolder = getVersionedUserAppSupportFolder();
  124. return tryFindDLLFileInFolder (userAppDataFolder, outFile);
  125. }
  126. static bool tryFindDLLFileInFolder(File folder, File& outFile)
  127. {
  128. auto file = folder.getChildFile (getDLLName());
  129. if (isDLLFile (file))
  130. {
  131. outFile = file;
  132. return true;
  133. }
  134. return false;
  135. }
  136. static bool isDLLFile (const File& f)
  137. {
  138. return f.getFileName().equalsIgnoreCase (getDLLName()) && f.exists();
  139. }
  140. static void setPropertyCallback (const char* key, const char* value)
  141. {
  142. auto keyStr = String (key);
  143. if (keyStr.isNotEmpty())
  144. getGlobalProperties().setValue (key, value);
  145. else
  146. jassertfalse;
  147. }
  148. static void getPropertyCallback (const char* key, char* value, size_t size)
  149. {
  150. jassert (getGlobalProperties().getValue (key).getNumBytesAsUTF8() < size);
  151. value[0] = 0;
  152. getGlobalProperties().getValue (key).copyToUTF8 (value, size);
  153. }
  154. static void crashCallback (const char*) {}
  155. static void quitCallback() {}
  156. };