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.

273 lines
7.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #if JUCE_MAC
  19. extern void juce_initialiseMacMainMenu();
  20. #endif
  21. //==============================================================================
  22. class AppBroadcastCallback : public ActionListener
  23. {
  24. public:
  25. AppBroadcastCallback() { MessageManager::getInstance()->registerBroadcastListener (this); }
  26. ~AppBroadcastCallback() { MessageManager::getInstance()->deregisterBroadcastListener (this); }
  27. void actionListenerCallback (const String& message)
  28. {
  29. JUCEApplication* const app = JUCEApplication::getInstance();
  30. if (app != 0 && message.startsWith (app->getApplicationName() + "/"))
  31. app->anotherInstanceStarted (message.substring (app->getApplicationName().length() + 1));
  32. }
  33. };
  34. //==============================================================================
  35. JUCEApplication::JUCEApplication()
  36. : appReturnValue (0),
  37. stillInitialising (true)
  38. {
  39. }
  40. JUCEApplication::~JUCEApplication()
  41. {
  42. if (appLock != nullptr)
  43. {
  44. appLock->exit();
  45. appLock = nullptr;
  46. }
  47. }
  48. //==============================================================================
  49. bool JUCEApplication::moreThanOneInstanceAllowed()
  50. {
  51. return true;
  52. }
  53. void JUCEApplication::anotherInstanceStarted (const String&)
  54. {
  55. }
  56. void JUCEApplication::systemRequestedQuit()
  57. {
  58. quit();
  59. }
  60. void JUCEApplication::quit()
  61. {
  62. MessageManager::getInstance()->stopDispatchLoop();
  63. }
  64. void JUCEApplication::setApplicationReturnValue (const int newReturnValue) noexcept
  65. {
  66. appReturnValue = newReturnValue;
  67. }
  68. //==============================================================================
  69. void JUCEApplication::unhandledException (const std::exception*,
  70. const String&,
  71. const int)
  72. {
  73. jassertfalse;
  74. }
  75. void JUCEApplication::sendUnhandledException (const std::exception* const e,
  76. const char* const sourceFile,
  77. const int lineNumber)
  78. {
  79. if (JUCEApplicationBase::getInstance() != nullptr)
  80. JUCEApplicationBase::getInstance()->unhandledException (e, sourceFile, lineNumber);
  81. }
  82. //==============================================================================
  83. ApplicationCommandTarget* JUCEApplication::getNextCommandTarget()
  84. {
  85. return nullptr;
  86. }
  87. void JUCEApplication::getAllCommands (Array <CommandID>& commands)
  88. {
  89. commands.add (StandardApplicationCommandIDs::quit);
  90. }
  91. void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
  92. {
  93. if (commandID == StandardApplicationCommandIDs::quit)
  94. {
  95. result.setInfo (TRANS("Quit"),
  96. TRANS("Quits the application"),
  97. "Application",
  98. 0);
  99. result.defaultKeypresses.add (KeyPress ('q', ModifierKeys::commandModifier, 0));
  100. }
  101. }
  102. bool JUCEApplication::perform (const InvocationInfo& info)
  103. {
  104. if (info.commandID == StandardApplicationCommandIDs::quit)
  105. {
  106. systemRequestedQuit();
  107. return true;
  108. }
  109. return false;
  110. }
  111. //==============================================================================
  112. bool JUCEApplication::initialiseApp()
  113. {
  114. #if ! (JUCE_IOS || JUCE_ANDROID)
  115. jassert (appLock == nullptr); // initialiseApp must only be called once!
  116. if (! moreThanOneInstanceAllowed())
  117. {
  118. appLock = new InterProcessLock ("juceAppLock_" + getApplicationName());
  119. if (! appLock->enter(0))
  120. {
  121. appLock = nullptr;
  122. MessageManager::broadcastMessage (getApplicationName() + "/" + getCommandLineParameters());
  123. DBG ("Another instance is running - quitting...");
  124. return false;
  125. }
  126. }
  127. #endif
  128. // let the app do its setting-up..
  129. initialise (getCommandLineParameters());
  130. #if JUCE_MAC
  131. juce_initialiseMacMainMenu(); // needs to be called after the app object has created, to get its name
  132. #endif
  133. #if ! (JUCE_IOS || JUCE_ANDROID)
  134. broadcastCallback = new AppBroadcastCallback();
  135. #endif
  136. stillInitialising = false;
  137. return true;
  138. }
  139. int JUCEApplication::shutdownApp()
  140. {
  141. jassert (JUCEApplicationBase::getInstance() == this);
  142. broadcastCallback = nullptr;
  143. JUCE_TRY
  144. {
  145. // give the app a chance to clean up..
  146. shutdown();
  147. }
  148. JUCE_CATCH_EXCEPTION
  149. return getApplicationReturnValue();
  150. }
  151. //==============================================================================
  152. #if JUCE_ANDROID
  153. StringArray JUCEApplication::getCommandLineParameterArray() { return StringArray(); }
  154. String JUCEApplication::getCommandLineParameters() { return String::empty; }
  155. #else
  156. int JUCEApplication::main()
  157. {
  158. ScopedJuceInitialiser_GUI libraryInitialiser;
  159. jassert (createInstance != nullptr);
  160. const ScopedPointer<JUCEApplication> app (dynamic_cast <JUCEApplication*> (createInstance()));
  161. jassert (app != nullptr);
  162. if (! app->initialiseApp())
  163. return 0;
  164. JUCE_TRY
  165. {
  166. // loop until a quit message is received..
  167. MessageManager::getInstance()->runDispatchLoop();
  168. }
  169. JUCE_CATCH_EXCEPTION
  170. return app->shutdownApp();
  171. }
  172. #if ! JUCE_WINDOWS
  173. #if JUCE_IOS
  174. extern int juce_iOSMain (int argc, const char* argv[]);
  175. #endif
  176. #if JUCE_MAC
  177. extern void initialiseNSApplication();
  178. #endif
  179. extern const char** juce_argv; // declared in juce_core
  180. extern int juce_argc;
  181. StringArray JUCEApplication::getCommandLineParameterArray()
  182. {
  183. return StringArray (juce_argv + 1, juce_argc - 1);
  184. }
  185. String JUCEApplication::getCommandLineParameters()
  186. {
  187. String argString;
  188. for (int i = 1; i < juce_argc; ++i)
  189. {
  190. String arg (juce_argv[i]);
  191. if (arg.containsChar (' ') && ! arg.isQuotedString())
  192. arg = arg.quoted ('"');
  193. argString << arg << ' ';
  194. }
  195. return argString.trim();
  196. }
  197. int JUCEApplication::main (int argc, const char* argv[])
  198. {
  199. JUCE_AUTORELEASEPOOL
  200. juce_argc = argc;
  201. juce_argv = argv;
  202. #if JUCE_MAC
  203. initialiseNSApplication();
  204. #endif
  205. #if JUCE_IOS
  206. return juce_iOSMain (argc, argv);
  207. #else
  208. return JUCEApplication::main();
  209. #endif
  210. }
  211. #endif
  212. #endif