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.

374 lines
9.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 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. #include "../core/juce_StandardHeader.h"
  19. #if JUCE_MSVC
  20. #pragma warning (push)
  21. #pragma warning (disable: 4245 4514 4100)
  22. #include <crtdbg.h>
  23. #pragma warning (pop)
  24. #endif
  25. BEGIN_JUCE_NAMESPACE
  26. #include "juce_Application.h"
  27. #include "../utilities/juce_DeletedAtShutdown.h"
  28. #include "../events/juce_MessageManager.h"
  29. #include "../gui/graphics/contexts/juce_Graphics.h"
  30. #include "../gui/components/windows/juce_AlertWindow.h"
  31. #include "../gui/components/buttons/juce_TextButton.h"
  32. #include "../gui/components/lookandfeel/juce_LookAndFeel.h"
  33. #include "../core/juce_Time.h"
  34. #include "../core/juce_Initialisation.h"
  35. #include "../threads/juce_Process.h"
  36. #include "../core/juce_PlatformUtilities.h"
  37. void juce_setCurrentThreadName (const String& name) throw();
  38. static JUCEApplication* appInstance = 0;
  39. //==============================================================================
  40. JUCEApplication::JUCEApplication()
  41. : appReturnValue (0),
  42. stillInitialising (true),
  43. appLock (0)
  44. {
  45. }
  46. JUCEApplication::~JUCEApplication()
  47. {
  48. if (appLock != 0)
  49. {
  50. appLock->exit();
  51. delete appLock;
  52. }
  53. }
  54. JUCEApplication* JUCEApplication::getInstance() throw()
  55. {
  56. return appInstance;
  57. }
  58. bool JUCEApplication::isInitialising() const throw()
  59. {
  60. return stillInitialising;
  61. }
  62. //==============================================================================
  63. const String JUCEApplication::getApplicationVersion()
  64. {
  65. return String::empty;
  66. }
  67. bool JUCEApplication::moreThanOneInstanceAllowed()
  68. {
  69. return true;
  70. }
  71. void JUCEApplication::anotherInstanceStarted (const String&)
  72. {
  73. }
  74. void JUCEApplication::systemRequestedQuit()
  75. {
  76. quit();
  77. }
  78. void JUCEApplication::quit()
  79. {
  80. MessageManager::getInstance()->stopDispatchLoop();
  81. }
  82. void JUCEApplication::setApplicationReturnValue (const int newReturnValue) throw()
  83. {
  84. appReturnValue = newReturnValue;
  85. }
  86. //==============================================================================
  87. void JUCEApplication::unhandledException (const std::exception*,
  88. const String&,
  89. const int)
  90. {
  91. jassertfalse
  92. }
  93. void JUCEApplication::sendUnhandledException (const std::exception* const e,
  94. const char* const sourceFile,
  95. const int lineNumber)
  96. {
  97. if (appInstance != 0)
  98. appInstance->unhandledException (e, sourceFile, lineNumber);
  99. }
  100. //==============================================================================
  101. ApplicationCommandTarget* JUCEApplication::getNextCommandTarget()
  102. {
  103. return 0;
  104. }
  105. void JUCEApplication::getAllCommands (Array <CommandID>& commands)
  106. {
  107. commands.add (StandardApplicationCommandIDs::quit);
  108. }
  109. void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
  110. {
  111. if (commandID == StandardApplicationCommandIDs::quit)
  112. {
  113. result.setInfo ("Quit",
  114. "Quits the application",
  115. "Application",
  116. 0);
  117. result.defaultKeypresses.add (KeyPress (T('q'), ModifierKeys::commandModifier, 0));
  118. }
  119. }
  120. bool JUCEApplication::perform (const InvocationInfo& info)
  121. {
  122. if (info.commandID == StandardApplicationCommandIDs::quit)
  123. {
  124. systemRequestedQuit();
  125. return true;
  126. }
  127. return false;
  128. }
  129. //==============================================================================
  130. int JUCEApplication::main (String& commandLine, JUCEApplication* const app)
  131. {
  132. if (! app->initialiseApp (commandLine))
  133. return 0;
  134. // now loop until a quit message is received..
  135. JUCE_TRY
  136. {
  137. MessageManager::getInstance()->runDispatchLoop();
  138. }
  139. #if JUCE_CATCH_UNHANDLED_EXCEPTIONS
  140. catch (const std::exception& e)
  141. {
  142. app->unhandledException (&e, __FILE__, __LINE__);
  143. }
  144. catch (...)
  145. {
  146. app->unhandledException (0, __FILE__, __LINE__);
  147. }
  148. #endif
  149. return shutdownAppAndClearUp();
  150. }
  151. bool JUCEApplication::initialiseApp (String& commandLine)
  152. {
  153. jassert (appInstance == 0);
  154. appInstance = this;
  155. commandLineParameters = commandLine.trim();
  156. commandLine = String::empty;
  157. initialiseJuce_GUI();
  158. #if ! JUCE_IPHONE
  159. jassert (appLock == 0); // initialiseApp must only be called once!
  160. if (! moreThanOneInstanceAllowed())
  161. {
  162. appLock = new InterProcessLock ("juceAppLock_" + getApplicationName());
  163. if (! appLock->enter(0))
  164. {
  165. MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters);
  166. delete appInstance;
  167. appInstance = 0;
  168. DBG ("Another instance is running - quitting...");
  169. return false;
  170. }
  171. }
  172. #endif
  173. // let the app do its setting-up..
  174. initialise (commandLineParameters);
  175. // register for broadcast new app messages
  176. MessageManager::getInstance()->registerBroadcastListener (this);
  177. stillInitialising = false;
  178. return true;
  179. }
  180. int JUCEApplication::shutdownAppAndClearUp()
  181. {
  182. jassert (appInstance != 0);
  183. JUCEApplication* const app = appInstance;
  184. int returnValue = 0;
  185. MessageManager::getInstance()->deregisterBroadcastListener (app);
  186. static bool reentrancyCheck = false;
  187. if (! reentrancyCheck)
  188. {
  189. reentrancyCheck = true;
  190. JUCE_TRY
  191. {
  192. // give the app a chance to clean up..
  193. app->shutdown();
  194. }
  195. #if JUCE_CATCH_UNHANDLED_EXCEPTIONS
  196. catch (const std::exception& e)
  197. {
  198. app->unhandledException (&e, __FILE__, __LINE__);
  199. }
  200. catch (...)
  201. {
  202. app->unhandledException (0, __FILE__, __LINE__);
  203. }
  204. #endif
  205. JUCE_TRY
  206. {
  207. shutdownJuce_GUI();
  208. returnValue = app->getApplicationReturnValue();
  209. appInstance = 0;
  210. delete app;
  211. }
  212. JUCE_CATCH_ALL_ASSERT
  213. reentrancyCheck = false;
  214. }
  215. return returnValue;
  216. }
  217. #if JUCE_IPHONE
  218. extern int juce_IPhoneMain (int argc, char* argv[], JUCEApplication* app);
  219. #endif
  220. #if ! JUCE_WINDOWS
  221. extern const char* juce_Argv0;
  222. #endif
  223. int JUCEApplication::main (int argc, char* argv[],
  224. JUCEApplication* const newApp)
  225. {
  226. #if ! JUCE_WINDOWS
  227. juce_Argv0 = argv[0];
  228. #endif
  229. #if JUCE_IPHONE
  230. const ScopedAutoReleasePool pool;
  231. return juce_IPhoneMain (argc, argv, newApp);
  232. #else
  233. #if JUCE_MAC
  234. const ScopedAutoReleasePool pool;
  235. #endif
  236. String cmd;
  237. for (int i = 1; i < argc; ++i)
  238. cmd << String::fromUTF8 ((const uint8*) argv[i]) << T(' ');
  239. return JUCEApplication::main (cmd, newApp);
  240. #endif
  241. }
  242. void JUCEApplication::actionListenerCallback (const String& message)
  243. {
  244. if (message.startsWith (getApplicationName() + "/"))
  245. anotherInstanceStarted (message.substring (getApplicationName().length() + 1));
  246. }
  247. //==============================================================================
  248. static bool juceInitialisedGUI = false;
  249. void JUCE_PUBLIC_FUNCTION initialiseJuce_GUI()
  250. {
  251. if (! juceInitialisedGUI)
  252. {
  253. #if JUCE_MAC || JUCE_IPHONE
  254. const ScopedAutoReleasePool pool;
  255. #endif
  256. juceInitialisedGUI = true;
  257. initialiseJuce_NonGUI();
  258. MessageManager::getInstance();
  259. LookAndFeel::setDefaultLookAndFeel (0);
  260. juce_setCurrentThreadName ("Juce Message Thread");
  261. #if JUCE_WINDOWS && JUCE_DEBUG
  262. // This section is just for catching people who mess up their project settings and
  263. // turn RTTI off..
  264. try
  265. {
  266. TextButton tb (String::empty);
  267. Component* c = &tb;
  268. // Got an exception here? Then TURN ON RTTI in your compiler settings!!
  269. c = dynamic_cast <Button*> (c);
  270. }
  271. catch (...)
  272. {
  273. // Ended up here? If so, TURN ON RTTI in your compiler settings!! And if you
  274. // got as far as this catch statement, then why haven't you got exception catching
  275. // turned on in the debugger???
  276. jassertfalse
  277. }
  278. #endif
  279. }
  280. }
  281. void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI()
  282. {
  283. if (juceInitialisedGUI)
  284. {
  285. #if JUCE_MAC
  286. const ScopedAutoReleasePool pool;
  287. #endif
  288. {
  289. DeletedAtShutdown::deleteAll();
  290. LookAndFeel::clearDefaultLookAndFeel();
  291. }
  292. delete MessageManager::getInstance();
  293. shutdownJuce_NonGUI();
  294. juceInitialisedGUI = false;
  295. }
  296. }
  297. END_JUCE_NAMESPACE