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.

195 lines
5.3KB

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