/* ============================================================================== This file is part of the JUCE library - "Jules' Utility Class Extensions" Copyright 2004-10 by Raw Material Software Ltd. ------------------------------------------------------------------------------ JUCE can be redistributed and/or modified under the terms of the GNU General Public License (Version 2), as published by the Free Software Foundation. A copy of the license is included in the JUCE distribution, or can be found online at www.gnu.org/licenses. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.rawmaterialsoftware.com/juce for more information. ============================================================================== */ #include "../core/juce_StandardHeader.h" #if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4245 4514 4100) #include #pragma warning (pop) #endif BEGIN_JUCE_NAMESPACE #include "juce_Application.h" #include "../utilities/juce_DeletedAtShutdown.h" #include "../events/juce_MessageManager.h" #include "../gui/graphics/contexts/juce_Graphics.h" #include "../gui/components/windows/juce_AlertWindow.h" #include "../gui/components/buttons/juce_TextButton.h" #include "../gui/components/lookandfeel/juce_LookAndFeel.h" #include "../core/juce_Time.h" #include "../core/juce_Initialisation.h" #include "../threads/juce_Process.h" #include "../core/juce_PlatformUtilities.h" #include "../text/juce_LocalisedStrings.h" void juce_setCurrentThreadName (const String& name); static JUCEApplication* appInstance = 0; //============================================================================== JUCEApplication::JUCEApplication() : appReturnValue (0), stillInitialising (true) { } JUCEApplication::~JUCEApplication() { if (appLock != 0) { appLock->exit(); appLock = 0; } } JUCEApplication* JUCEApplication::getInstance() throw() { return appInstance; } bool JUCEApplication::isInitialising() const throw() { return stillInitialising; } //============================================================================== const String JUCEApplication::getApplicationVersion() { return String::empty; } bool JUCEApplication::moreThanOneInstanceAllowed() { return true; } void JUCEApplication::anotherInstanceStarted (const String&) { } void JUCEApplication::systemRequestedQuit() { quit(); } void JUCEApplication::quit() { MessageManager::getInstance()->stopDispatchLoop(); } void JUCEApplication::setApplicationReturnValue (const int newReturnValue) throw() { appReturnValue = newReturnValue; } //============================================================================== void JUCEApplication::unhandledException (const std::exception*, const String&, const int) { jassertfalse } void JUCEApplication::sendUnhandledException (const std::exception* const e, const char* const sourceFile, const int lineNumber) { if (appInstance != 0) appInstance->unhandledException (e, sourceFile, lineNumber); } //============================================================================== ApplicationCommandTarget* JUCEApplication::getNextCommandTarget() { return 0; } void JUCEApplication::getAllCommands (Array & commands) { commands.add (StandardApplicationCommandIDs::quit); } void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) { if (commandID == StandardApplicationCommandIDs::quit) { result.setInfo (TRANS("Quit"), TRANS("Quits the application"), "Application", 0); result.defaultKeypresses.add (KeyPress ('q', ModifierKeys::commandModifier, 0)); } } bool JUCEApplication::perform (const InvocationInfo& info) { if (info.commandID == StandardApplicationCommandIDs::quit) { systemRequestedQuit(); return true; } return false; } //============================================================================== int JUCEApplication::main (String& commandLine, JUCEApplication* const app) { if (! app->initialiseApp (commandLine)) return 0; // now loop until a quit message is received.. JUCE_TRY { MessageManager::getInstance()->runDispatchLoop(); } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS catch (const std::exception& e) { app->unhandledException (&e, __FILE__, __LINE__); } catch (...) { app->unhandledException (0, __FILE__, __LINE__); } #endif return shutdownAppAndClearUp(); } bool JUCEApplication::initialiseApp (String& commandLine) { jassert (appInstance == 0); appInstance = this; commandLineParameters = commandLine.trim(); commandLine = String::empty; initialiseJuce_GUI(); #if ! JUCE_IPHONE jassert (appLock == 0); // initialiseApp must only be called once! if (! moreThanOneInstanceAllowed()) { appLock = new InterProcessLock ("juceAppLock_" + getApplicationName()); if (! appLock->enter(0)) { MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters); delete appInstance; appInstance = 0; DBG ("Another instance is running - quitting..."); return false; } } #endif // let the app do its setting-up.. initialise (commandLineParameters); // register for broadcast new app messages MessageManager::getInstance()->registerBroadcastListener (this); stillInitialising = false; return true; } int JUCEApplication::shutdownAppAndClearUp() { jassert (appInstance != 0); ScopedPointer app (appInstance); int returnValue = 0; MessageManager::getInstance()->deregisterBroadcastListener (static_cast (app)); static bool reentrancyCheck = false; if (! reentrancyCheck) { reentrancyCheck = true; JUCE_TRY { // give the app a chance to clean up.. app->shutdown(); } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS catch (const std::exception& e) { app->unhandledException (&e, __FILE__, __LINE__); } catch (...) { app->unhandledException (0, __FILE__, __LINE__); } #endif JUCE_TRY { shutdownJuce_GUI(); returnValue = app->getApplicationReturnValue(); appInstance = 0; app = 0; } JUCE_CATCH_ALL_ASSERT reentrancyCheck = false; } return returnValue; } #if JUCE_IPHONE extern int juce_IPhoneMain (int argc, const char* argv[], JUCEApplication* app); #endif #if ! JUCE_WINDOWS extern const char* juce_Argv0; #endif int JUCEApplication::main (int argc, const char* argv[], JUCEApplication* const newApp) { #if ! JUCE_WINDOWS juce_Argv0 = argv[0]; #endif #if JUCE_IPHONE const ScopedAutoReleasePool pool; return juce_IPhoneMain (argc, argv, newApp); #else #if JUCE_MAC const ScopedAutoReleasePool pool; #endif String cmd; for (int i = 1; i < argc; ++i) cmd << argv[i] << ' '; return JUCEApplication::main (cmd, newApp); #endif } void JUCEApplication::actionListenerCallback (const String& message) { if (message.startsWith (getApplicationName() + "/")) anotherInstanceStarted (message.substring (getApplicationName().length() + 1)); } //============================================================================== static bool juceInitialisedGUI = false; void JUCE_PUBLIC_FUNCTION initialiseJuce_GUI() { if (! juceInitialisedGUI) { #if JUCE_MAC || JUCE_IPHONE const ScopedAutoReleasePool pool; #endif juceInitialisedGUI = true; initialiseJuce_NonGUI(); MessageManager::getInstance(); LookAndFeel::setDefaultLookAndFeel (0); juce_setCurrentThreadName ("Juce Message Thread"); #if JUCE_WINDOWS && JUCE_DEBUG // This section is just for catching people who mess up their project settings and // turn RTTI off.. try { TextButton tb (String::empty); Component* c = &tb; // Got an exception here? Then TURN ON RTTI in your compiler settings!! c = dynamic_cast (c); } catch (...) { // Ended up here? If so, TURN ON RTTI in your compiler settings!! And if you // got as far as this catch statement, then why haven't you got exception catching // turned on in the debugger??? jassertfalse } #endif } } void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI() { if (juceInitialisedGUI) { #if JUCE_MAC const ScopedAutoReleasePool pool; #endif { DeletedAtShutdown::deleteAll(); LookAndFeel::clearDefaultLookAndFeel(); } delete MessageManager::getInstance(); shutdownJuce_NonGUI(); juceInitialisedGUI = false; } } END_JUCE_NAMESPACE