1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/src/juce_appframework/application/juce_Application.cpp
2007-07-13 11:11:55 +00:00

351 lines
9.6 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../juce_core/basics/juce_StandardHeader.h"
#if JUCE_MSVC
#pragma warning (push)
#pragma warning (disable: 4245 4514 4100)
#include <crtdbg.h>
#pragma warning (pop)
#endif
BEGIN_JUCE_NAMESPACE
#include "juce_Application.h"
#include "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 "../../juce_core/basics/juce_Time.h"
#include "../../juce_core/basics/juce_Initialisation.h"
#include "../../juce_core/threads/juce_Process.h"
#include "../../juce_core/threads/juce_InterProcessLock.h"
void juce_setCurrentExecutableFileName (const String& filename) throw();
void juce_setCurrentThreadName (const String& name) throw();
static JUCEApplication* appInstance = 0;
//==============================================================================
JUCEApplication::JUCEApplication()
: stillInitialising (true)
{
}
JUCEApplication::~JUCEApplication()
{
}
JUCEApplication* JUCEApplication::getInstance()
{
return appInstance;
}
bool JUCEApplication::isInitialising() const
{
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 (const bool useMaximumForce)
{
MessageManager::getInstance()->postQuitMessage (useMaximumForce);
}
//==============================================================================
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 <CommandID>& commands)
{
commands.add (StandardApplicationCommandIDs::quit);
}
void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
{
if (commandID == StandardApplicationCommandIDs::quit)
{
result.setInfo ("Quit",
"Quits the application",
"Application",
0);
result.defaultKeypresses.add (KeyPress (T('q'), ModifierKeys::commandModifier, 0));
}
}
bool JUCEApplication::perform (const InvocationInfo& info)
{
if (info.commandID == StandardApplicationCommandIDs::quit)
{
systemRequestedQuit();
return true;
}
return false;
}
//==============================================================================
// used as a listener object later on..
class NewAppListener : public ActionListener
{
public:
void actionListenerCallback (const String& message)
{
if (message.startsWith (appInstance->getApplicationName() + T("/")))
{
appInstance->anotherInstanceStarted (message.fromFirstOccurrenceOf (T("/"),
false, false));
}
}
};
int JUCEApplication::main (String& commandLine, JUCEApplication* const app)
{
jassert (appInstance == 0);
appInstance = app;
bool useForce = true;
initialiseJuce_GUI();
InterProcessLock* appLock = 0;
if (! app->moreThanOneInstanceAllowed())
{
appLock = new InterProcessLock ("juceAppLock_" + app->getApplicationName());
if (! appLock->enter(0))
{
MessageManager::broadcastMessage (app->getApplicationName()
+ T("/") + commandLine);
delete appInstance;
appInstance = 0;
commandLine = String::empty;
DBG ("Another instance is running - quitting...");
return 0;
}
}
JUCE_TRY
{
juce_setCurrentThreadName ("Juce Message Thread");
// let the app do its setting-up..
app->initialise (commandLine.trim());
commandLine = String::empty;
// register for broadcast new app messages
NewAppListener* const newAppListener = new NewAppListener();
MessageManager::getInstance()->registerBroadcastListener (newAppListener);
app->stillInitialising = false;
// now loop until a quit message is received..
useForce = MessageManager::getInstance()->runDispatchLoop();
delete newAppListener;
if (appLock != 0)
{
appLock->exit();
delete appLock;
}
}
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
catch (const std::exception& e)
{
app->unhandledException (&e, __FILE__, __LINE__);
}
catch (...)
{
app->unhandledException (0, __FILE__, __LINE__);
}
#endif
shutdownAppAndClearUp (useForce);
return 0;
}
void JUCEApplication::shutdownAppAndClearUp (bool useMaximumForce)
{
jassert (appInstance != 0);
JUCEApplication* const app = appInstance;
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();
appInstance = 0;
delete app;
}
JUCE_CATCH_ALL_ASSERT
if (useMaximumForce)
{
Process::terminate();
}
reentrancyCheck = false;
}
}
int JUCEApplication::main (int argc, char* argv[],
JUCEApplication* const newApp)
{
juce_setCurrentExecutableFileName (argv[0]);
String cmd;
for (int i = 1; i < argc; ++i)
cmd << argv[i] << T(' ');
return JUCEApplication::main (cmd, newApp);
}
//==============================================================================
static bool juceInitialisedGUI = false;
void JUCE_PUBLIC_FUNCTION initialiseJuce_GUI()
{
if (! juceInitialisedGUI)
{
juceInitialisedGUI = true;
initialiseJuce_NonGUI();
MessageManager::getInstance();
Font::initialiseDefaultFontNames();
LookAndFeel::setDefaultLookAndFeel (0);
#if JUCE_WIN32 && 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 <Button*> (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)
{
DeletedAtShutdown::deleteAll();
LookAndFeel::clearDefaultLookAndFeel();
shutdownJuce_NonGUI();
juceInitialisedGUI = false;
}
}
END_JUCE_NAMESPACE