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.

267 lines
7.3KB

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