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.

270 lines
7.5KB

  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() { return true; }
  50. void JUCEApplication::anotherInstanceStarted (const String&) {}
  51. void JUCEApplication::suspended() {}
  52. void JUCEApplication::resumed() {}
  53. void JUCEApplication::systemRequestedQuit()
  54. {
  55. quit();
  56. }
  57. void JUCEApplication::quit()
  58. {
  59. MessageManager::getInstance()->stopDispatchLoop();
  60. }
  61. void JUCEApplication::setApplicationReturnValue (const int newReturnValue) noexcept
  62. {
  63. appReturnValue = newReturnValue;
  64. }
  65. //==============================================================================
  66. void JUCEApplication::unhandledException (const std::exception*,
  67. const String&,
  68. const int)
  69. {
  70. jassertfalse;
  71. }
  72. void JUCEApplication::sendUnhandledException (const std::exception* const e,
  73. const char* const sourceFile,
  74. const int lineNumber)
  75. {
  76. if (JUCEApplicationBase::getInstance() != nullptr)
  77. JUCEApplicationBase::getInstance()->unhandledException (e, sourceFile, lineNumber);
  78. }
  79. //==============================================================================
  80. ApplicationCommandTarget* JUCEApplication::getNextCommandTarget()
  81. {
  82. return nullptr;
  83. }
  84. void JUCEApplication::getAllCommands (Array <CommandID>& commands)
  85. {
  86. commands.add (StandardApplicationCommandIDs::quit);
  87. }
  88. void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
  89. {
  90. if (commandID == StandardApplicationCommandIDs::quit)
  91. {
  92. result.setInfo (TRANS("Quit"),
  93. TRANS("Quits the application"),
  94. "Application",
  95. 0);
  96. result.defaultKeypresses.add (KeyPress ('q', ModifierKeys::commandModifier, 0));
  97. }
  98. }
  99. bool JUCEApplication::perform (const InvocationInfo& info)
  100. {
  101. if (info.commandID == StandardApplicationCommandIDs::quit)
  102. {
  103. systemRequestedQuit();
  104. return true;
  105. }
  106. return false;
  107. }
  108. //==============================================================================
  109. bool JUCEApplication::initialiseApp()
  110. {
  111. #if ! (JUCE_IOS || JUCE_ANDROID)
  112. jassert (appLock == nullptr); // initialiseApp must only be called once!
  113. if (! moreThanOneInstanceAllowed())
  114. {
  115. appLock = new InterProcessLock ("juceAppLock_" + getApplicationName());
  116. if (! appLock->enter(0))
  117. {
  118. appLock = nullptr;
  119. MessageManager::broadcastMessage (getApplicationName() + "/" + getCommandLineParameters());
  120. DBG ("Another instance is running - quitting...");
  121. return false;
  122. }
  123. }
  124. #endif
  125. // let the app do its setting-up..
  126. initialise (getCommandLineParameters());
  127. #if JUCE_MAC
  128. juce_initialiseMacMainMenu(); // needs to be called after the app object has created, to get its name
  129. #endif
  130. #if ! (JUCE_IOS || JUCE_ANDROID)
  131. broadcastCallback = new AppBroadcastCallback();
  132. #endif
  133. stillInitialising = false;
  134. return true;
  135. }
  136. int JUCEApplication::shutdownApp()
  137. {
  138. jassert (JUCEApplicationBase::getInstance() == this);
  139. broadcastCallback = nullptr;
  140. JUCE_TRY
  141. {
  142. // give the app a chance to clean up..
  143. shutdown();
  144. }
  145. JUCE_CATCH_EXCEPTION
  146. return getApplicationReturnValue();
  147. }
  148. //==============================================================================
  149. #if JUCE_ANDROID
  150. StringArray JUCEApplication::getCommandLineParameterArray() { return StringArray(); }
  151. String JUCEApplication::getCommandLineParameters() { return String::empty; }
  152. #else
  153. int JUCEApplication::main()
  154. {
  155. ScopedJuceInitialiser_GUI libraryInitialiser;
  156. jassert (createInstance != nullptr);
  157. const ScopedPointer<JUCEApplication> app (dynamic_cast <JUCEApplication*> (createInstance()));
  158. jassert (app != nullptr);
  159. if (! app->initialiseApp())
  160. return 0;
  161. JUCE_TRY
  162. {
  163. // loop until a quit message is received..
  164. MessageManager::getInstance()->runDispatchLoop();
  165. }
  166. JUCE_CATCH_EXCEPTION
  167. return app->shutdownApp();
  168. }
  169. #if ! JUCE_WINDOWS
  170. #if JUCE_IOS
  171. extern int juce_iOSMain (int argc, const char* argv[]);
  172. #endif
  173. #if JUCE_MAC
  174. extern void initialiseNSApplication();
  175. #endif
  176. extern const char** juce_argv; // declared in juce_core
  177. extern int juce_argc;
  178. StringArray JUCEApplication::getCommandLineParameterArray()
  179. {
  180. return StringArray (juce_argv + 1, juce_argc - 1);
  181. }
  182. String JUCEApplication::getCommandLineParameters()
  183. {
  184. String argString;
  185. for (int i = 1; i < juce_argc; ++i)
  186. {
  187. String arg (juce_argv[i]);
  188. if (arg.containsChar (' ') && ! arg.isQuotedString())
  189. arg = arg.quoted ('"');
  190. argString << arg << ' ';
  191. }
  192. return argString.trim();
  193. }
  194. int JUCEApplication::main (int argc, const char* argv[])
  195. {
  196. JUCE_AUTORELEASEPOOL
  197. juce_argc = argc;
  198. juce_argv = argv;
  199. #if JUCE_MAC
  200. initialiseNSApplication();
  201. #endif
  202. #if JUCE_IOS
  203. return juce_iOSMain (argc, argv);
  204. #else
  205. return JUCEApplication::main();
  206. #endif
  207. }
  208. #endif
  209. #endif