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.

203 lines
5.6KB

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