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.

263 lines
7.2KB

  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 (const String& commandLine)
  113. {
  114. commandLineParameters = commandLine.trim();
  115. #if ! (JUCE_IOS || JUCE_ANDROID)
  116. jassert (appLock == nullptr); // initialiseApp must only be called once!
  117. if (! moreThanOneInstanceAllowed())
  118. {
  119. appLock = new InterProcessLock ("juceAppLock_" + getApplicationName());
  120. if (! appLock->enter(0))
  121. {
  122. appLock = nullptr;
  123. MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters);
  124. DBG ("Another instance is running - quitting...");
  125. return false;
  126. }
  127. }
  128. #endif
  129. // let the app do its setting-up..
  130. initialise (commandLineParameters);
  131. #if JUCE_MAC
  132. juce_initialiseMacMainMenu(); // needs to be called after the app object has created, to get its name
  133. #endif
  134. #if ! (JUCE_IOS || JUCE_ANDROID)
  135. broadcastCallback = new AppBroadcastCallback();
  136. #endif
  137. stillInitialising = false;
  138. return true;
  139. }
  140. int JUCEApplication::shutdownApp()
  141. {
  142. jassert (JUCEApplicationBase::getInstance() == this);
  143. broadcastCallback = nullptr;
  144. JUCE_TRY
  145. {
  146. // give the app a chance to clean up..
  147. shutdown();
  148. }
  149. JUCE_CATCH_EXCEPTION
  150. return getApplicationReturnValue();
  151. }
  152. //==============================================================================
  153. #if ! JUCE_ANDROID
  154. int JUCEApplication::main (const String& commandLine)
  155. {
  156. ScopedJuceInitialiser_GUI libraryInitialiser;
  157. jassert (createInstance != nullptr);
  158. int returnCode = 0;
  159. {
  160. const ScopedPointer<JUCEApplication> app (dynamic_cast <JUCEApplication*> (createInstance()));
  161. jassert (app != nullptr);
  162. if (! app->initialiseApp (commandLine))
  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. returnCode = app->shutdownApp();
  171. }
  172. return returnCode;
  173. }
  174. #if JUCE_IOS
  175. extern int juce_iOSMain (int argc, const char* argv[]);
  176. #endif
  177. #if ! JUCE_WINDOWS
  178. extern const char* juce_Argv0;
  179. #endif
  180. #if JUCE_MAC
  181. extern void initialiseNSApplication();
  182. #endif
  183. int JUCEApplication::main (int argc, const char* argv[])
  184. {
  185. JUCE_AUTORELEASEPOOL
  186. #if JUCE_MAC
  187. initialiseNSApplication();
  188. #endif
  189. #if ! JUCE_WINDOWS
  190. jassert (createInstance != nullptr);
  191. juce_Argv0 = argv[0];
  192. #endif
  193. #if JUCE_IOS
  194. return juce_iOSMain (argc, argv);
  195. #else
  196. String cmd;
  197. for (int i = 1; i < argc; ++i)
  198. {
  199. String arg (argv[i]);
  200. if (arg.containsChar (' ') && ! arg.isQuotedString())
  201. arg = arg.quoted ('"');
  202. cmd << arg << ' ';
  203. }
  204. return JUCEApplication::main (cmd);
  205. #endif
  206. }
  207. #endif