|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2016 - ROLI Ltd.
-
- Permission is granted to use this software under the terms of the ISC license
- http://www.isc.org/downloads/software-support-policy/isc-license/
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
- TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
- OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- OF THIS SOFTWARE.
-
- -----------------------------------------------------------------------------
-
- To release a closed-source product which uses other parts of JUCE not
- licensed under the ISC terms, commercial licenses are available: visit
- www.juce.com for more information.
-
- ==============================================================================
- */
-
- JUCEApplicationBase::CreateInstanceFunction JUCEApplicationBase::createInstance = 0;
- JUCEApplicationBase* JUCEApplicationBase::appInstance = nullptr;
-
- JUCEApplicationBase::JUCEApplicationBase()
- : appReturnValue (0),
- stillInitialising (true)
- {
- jassert (isStandaloneApp() && appInstance == nullptr);
- appInstance = this;
- }
-
- JUCEApplicationBase::~JUCEApplicationBase()
- {
- jassert (appInstance == this);
- appInstance = nullptr;
- }
-
- void JUCEApplicationBase::setApplicationReturnValue (const int newReturnValue) noexcept
- {
- appReturnValue = newReturnValue;
- }
-
- // This is called on the Mac and iOS where the OS doesn't allow the stack to unwind on shutdown..
- void JUCEApplicationBase::appWillTerminateByForce()
- {
- JUCE_AUTORELEASEPOOL
- {
- {
- const ScopedPointer<JUCEApplicationBase> app (appInstance);
-
- if (app != nullptr)
- app->shutdownApp();
- }
-
- DeletedAtShutdown::deleteAll();
- MessageManager::deleteInstance();
- }
- }
-
- void JUCEApplicationBase::quit()
- {
- MessageManager::getInstance()->stopDispatchLoop();
- }
-
- void JUCEApplicationBase::sendUnhandledException (const std::exception* const e,
- const char* const sourceFile,
- const int lineNumber)
- {
- if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
- app->unhandledException (e, sourceFile, lineNumber);
- }
-
- //==============================================================================
- #if ! (JUCE_IOS || JUCE_ANDROID)
- #define JUCE_HANDLE_MULTIPLE_INSTANCES 1
- #endif
-
- #if JUCE_HANDLE_MULTIPLE_INSTANCES
- struct JUCEApplicationBase::MultipleInstanceHandler : public ActionListener
- {
- public:
- MultipleInstanceHandler (const String& appName)
- : appLock ("juceAppLock_" + appName)
- {
- }
-
- bool sendCommandLineToPreexistingInstance()
- {
- if (appLock.enter (0))
- return false;
-
- JUCEApplicationBase* const app = JUCEApplicationBase::getInstance();
- jassert (app != nullptr);
-
- MessageManager::broadcastMessage (app->getApplicationName()
- + "/" + app->getCommandLineParameters());
- return true;
- }
-
- void actionListenerCallback (const String& message) override
- {
- if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
- {
- const String appName (app->getApplicationName());
-
- if (message.startsWith (appName + "/"))
- app->anotherInstanceStarted (message.substring (appName.length() + 1));
- }
- }
-
- private:
- InterProcessLock appLock;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultipleInstanceHandler)
- };
-
- bool JUCEApplicationBase::sendCommandLineToPreexistingInstance()
- {
- jassert (multipleInstanceHandler == nullptr); // this must only be called once!
-
- multipleInstanceHandler = new MultipleInstanceHandler (getApplicationName());
- return multipleInstanceHandler->sendCommandLineToPreexistingInstance();
- }
-
- #else
- struct JUCEApplicationBase::MultipleInstanceHandler {};
- #endif
-
- //==============================================================================
- #if JUCE_ANDROID
-
- StringArray JUCEApplicationBase::getCommandLineParameterArray() { return StringArray(); }
- String JUCEApplicationBase::getCommandLineParameters() { return String(); }
-
- #else
-
- #if JUCE_WINDOWS && ! defined (_CONSOLE)
-
- String JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameters()
- {
- return CharacterFunctions::findEndOfToken (CharPointer_UTF16 (GetCommandLineW()),
- CharPointer_UTF16 (L" "),
- CharPointer_UTF16 (L"\"")).findEndOfWhitespace();
- }
-
- StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray()
- {
- StringArray s;
-
- int argc = 0;
- if (LPWSTR* const argv = CommandLineToArgvW (GetCommandLineW(), &argc))
- {
- s = StringArray (argv + 1, argc - 1);
- LocalFree (argv);
- }
-
- return s;
- }
-
- #else
-
- #if JUCE_IOS
- extern int juce_iOSMain (int argc, const char* argv[], void* classPtr);
- #endif
-
- #if JUCE_MAC
- extern void initialiseNSApplication();
- #endif
-
- #if JUCE_WINDOWS
- const char* const* juce_argv = nullptr;
- int juce_argc = 0;
- #else
- extern const char* const* juce_argv; // declared in juce_core
- extern int juce_argc;
- #endif
-
- String JUCEApplicationBase::getCommandLineParameters()
- {
- String argString;
-
- for (int i = 1; i < juce_argc; ++i)
- {
- String arg (juce_argv[i]);
-
- if (arg.containsChar (' ') && ! arg.isQuotedString())
- arg = arg.quoted ('"');
-
- argString << arg << ' ';
- }
-
- return argString.trim();
- }
-
- StringArray JUCEApplicationBase::getCommandLineParameterArray()
- {
- return StringArray (juce_argv + 1, juce_argc - 1);
- }
-
- int JUCEApplicationBase::main (int argc, const char* argv[], void* customDelegate)
- {
- JUCE_AUTORELEASEPOOL
- {
- juce_argc = argc;
- juce_argv = argv;
-
- #if JUCE_MAC
- initialiseNSApplication();
- #endif
-
- #if JUCE_IOS
- return juce_iOSMain (argc, argv, customDelegate);
- #else
- ignoreUnused (customDelegate);
-
- return JUCEApplicationBase::main();
- #endif
- }
- }
-
- #endif
-
- //==============================================================================
- int JUCEApplicationBase::main()
- {
- ScopedJuceInitialiser_GUI libraryInitialiser;
- jassert (createInstance != nullptr);
-
- const ScopedPointer<JUCEApplicationBase> app (createInstance());
- jassert (app != nullptr);
-
- if (! app->initialiseApp())
- return app->shutdownApp();
-
- JUCE_TRY
- {
- // loop until a quit message is received..
- MessageManager::getInstance()->runDispatchLoop();
- }
- JUCE_CATCH_EXCEPTION
-
- return app->shutdownApp();
- }
-
- #endif
-
- //==============================================================================
- bool JUCEApplicationBase::initialiseApp()
- {
- #if JUCE_HANDLE_MULTIPLE_INSTANCES
- if ((! moreThanOneInstanceAllowed()) && sendCommandLineToPreexistingInstance())
- {
- DBG ("Another instance is running - quitting...");
- return false;
- }
- #endif
-
- #if JUCE_WINDOWS && JUCE_STANDALONE_APPLICATION && (! defined (_CONSOLE)) && (! JUCE_MINGW)
- if (AttachConsole (ATTACH_PARENT_PROCESS) != 0)
- {
- // if we've launched a GUI app from cmd.exe or PowerShell, we need this to enable printf etc.
- // However, only reassign stdout, stderr, stdin if they have not been already opened by
- // a redirect or similar.
- FILE* ignore;
-
- if (_fileno(stdout) < 0) freopen_s (&ignore, "CONOUT$", "w", stdout);
- if (_fileno(stderr) < 0) freopen_s (&ignore, "CONOUT$", "w", stderr);
- if (_fileno(stdin) < 0) freopen_s (&ignore, "CONIN$", "r", stdin);
- }
- #endif
-
- // let the app do its setting-up..
- initialise (getCommandLineParameters());
-
- stillInitialising = false;
-
- if (MessageManager::getInstance()->hasStopMessageBeenSent())
- return false;
-
- #if JUCE_HANDLE_MULTIPLE_INSTANCES
- if (multipleInstanceHandler != nullptr)
- MessageManager::getInstance()->registerBroadcastListener (multipleInstanceHandler);
- #endif
-
- return true;
- }
-
- int JUCEApplicationBase::shutdownApp()
- {
- jassert (JUCEApplicationBase::getInstance() == this);
-
- #if JUCE_HANDLE_MULTIPLE_INSTANCES
- if (multipleInstanceHandler != nullptr)
- MessageManager::getInstance()->deregisterBroadcastListener (multipleInstanceHandler);
- #endif
-
- JUCE_TRY
- {
- // give the app a chance to clean up..
- shutdown();
- }
- JUCE_CATCH_EXCEPTION
-
- multipleInstanceHandler = nullptr;
- return getApplicationReturnValue();
- }
|