git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
332
deps/juce/modules/juce_events/messages/juce_ApplicationBase.cpp
vendored
Normal file
332
deps/juce/modules/juce_events/messages/juce_ApplicationBase.cpp
vendored
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
JUCEApplicationBase::CreateInstanceFunction JUCEApplicationBase::createInstance = nullptr;
|
||||
JUCEApplicationBase* JUCEApplicationBase::appInstance = nullptr;
|
||||
|
||||
#if JUCE_IOS
|
||||
void* JUCEApplicationBase::iOSCustomDelegate = nullptr;
|
||||
#endif
|
||||
|
||||
JUCEApplicationBase::JUCEApplicationBase()
|
||||
{
|
||||
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 std::unique_ptr<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 (auto* app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
// If you hit this assertion then the __FILE__ macro is providing a
|
||||
// relative path instead of an absolute path. On Windows this will be
|
||||
// a path relative to the build directory rather than the currently
|
||||
// running application. To fix this you must compile with the /FC flag.
|
||||
jassert (File::isAbsolutePath (sourceFile));
|
||||
|
||||
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
|
||||
{
|
||||
MultipleInstanceHandler (const String& appName)
|
||||
: appLock ("juceAppLock_" + appName)
|
||||
{
|
||||
}
|
||||
|
||||
bool sendCommandLineToPreexistingInstance()
|
||||
{
|
||||
if (appLock.enter (0))
|
||||
return false;
|
||||
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
MessageManager::broadcastMessage (app->getApplicationName() + "/" + app->getCommandLineParameters());
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void actionListenerCallback (const String& message) override
|
||||
{
|
||||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
{
|
||||
auto 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.reset (new MultipleInstanceHandler (getApplicationName()));
|
||||
return multipleInstanceHandler->sendCommandLineToPreexistingInstance();
|
||||
}
|
||||
|
||||
#else
|
||||
struct JUCEApplicationBase::MultipleInstanceHandler {};
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_ANDROID
|
||||
|
||||
StringArray JUCEApplicationBase::getCommandLineParameterArray() { return {}; }
|
||||
String JUCEApplicationBase::getCommandLineParameters() { return {}; }
|
||||
|
||||
#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 (auto argv = CommandLineToArgvW (GetCommandLineW(), &argc))
|
||||
{
|
||||
s = StringArray (argv + 1, argc - 1);
|
||||
LocalFree (argv);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if JUCE_IOS && JUCE_MODULE_AVAILABLE_juce_gui_basics
|
||||
extern int juce_iOSMain (int argc, const char* argv[], void* classPtr);
|
||||
#endif
|
||||
|
||||
#if JUCE_MAC
|
||||
extern void initialiseNSApplication();
|
||||
#endif
|
||||
|
||||
#if (JUCE_LINUX || JUCE_BSD) && JUCE_MODULE_AVAILABLE_juce_gui_extra && (! defined(JUCE_WEB_BROWSER) || JUCE_WEB_BROWSER)
|
||||
extern int juce_gtkWebkitMain (int argc, const char* argv[]);
|
||||
#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 { CharPointer_UTF8 (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[])
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
juce_argc = argc;
|
||||
juce_argv = argv;
|
||||
|
||||
#if JUCE_MAC
|
||||
initialiseNSApplication();
|
||||
#endif
|
||||
|
||||
#if (JUCE_LINUX || JUCE_BSD) && JUCE_MODULE_AVAILABLE_juce_gui_extra && (! defined(JUCE_WEB_BROWSER) || JUCE_WEB_BROWSER)
|
||||
if (argc >= 2 && String (argv[1]) == "--juce-gtkwebkitfork-child")
|
||||
return juce_gtkWebkitMain (argc, argv);
|
||||
#endif
|
||||
|
||||
#if JUCE_IOS && JUCE_MODULE_AVAILABLE_juce_gui_basics
|
||||
return juce_iOSMain (argc, argv, iOSCustomDelegate);
|
||||
#else
|
||||
|
||||
return JUCEApplicationBase::main();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
int JUCEApplicationBase::main()
|
||||
{
|
||||
ScopedJuceInitialiser_GUI libraryInitialiser;
|
||||
jassert (createInstance != nullptr);
|
||||
|
||||
const std::unique_ptr<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 (auto* mih = multipleInstanceHandler.get())
|
||||
MessageManager::getInstance()->registerBroadcastListener (mih);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int JUCEApplicationBase::shutdownApp()
|
||||
{
|
||||
jassert (JUCEApplicationBase::getInstance() == this);
|
||||
|
||||
#if JUCE_HANDLE_MULTIPLE_INSTANCES
|
||||
if (auto* mih = multipleInstanceHandler.get())
|
||||
MessageManager::getInstance()->deregisterBroadcastListener (mih);
|
||||
#endif
|
||||
|
||||
JUCE_TRY
|
||||
{
|
||||
// give the app a chance to clean up..
|
||||
shutdown();
|
||||
}
|
||||
JUCE_CATCH_EXCEPTION
|
||||
|
||||
multipleInstanceHandler.reset();
|
||||
return getApplicationReturnValue();
|
||||
}
|
||||
|
||||
} // namespace juce
|
348
deps/juce/modules/juce_events/messages/juce_ApplicationBase.h
vendored
Normal file
348
deps/juce/modules/juce_events/messages/juce_ApplicationBase.h
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Abstract base class for application classes.
|
||||
|
||||
Note that in the juce_gui_basics module, there's a utility class JUCEApplication
|
||||
which derives from JUCEApplicationBase, and takes care of a few chores. Most
|
||||
of the time you'll want to derive your class from JUCEApplication rather than
|
||||
using JUCEApplicationBase directly, but if you're not using the juce_gui_basics
|
||||
module then you might need to go straight to this base class.
|
||||
|
||||
Any application that wants to run an event loop must declare a subclass of
|
||||
JUCEApplicationBase, and implement its various pure virtual methods.
|
||||
|
||||
It then needs to use the START_JUCE_APPLICATION macro somewhere in a CPP file
|
||||
to declare an instance of this class and generate suitable platform-specific
|
||||
boilerplate code to launch the app.
|
||||
|
||||
e.g. @code
|
||||
class MyJUCEApp : public JUCEApplication
|
||||
{
|
||||
public:
|
||||
MyJUCEApp() {}
|
||||
~MyJUCEApp() {}
|
||||
|
||||
void initialise (const String& commandLine) override
|
||||
{
|
||||
myMainWindow.reset (new MyApplicationWindow());
|
||||
myMainWindow->setBounds (100, 100, 400, 500);
|
||||
myMainWindow->setVisible (true);
|
||||
}
|
||||
|
||||
void shutdown() override
|
||||
{
|
||||
myMainWindow = nullptr;
|
||||
}
|
||||
|
||||
const String getApplicationName() override
|
||||
{
|
||||
return "Super JUCE-o-matic";
|
||||
}
|
||||
|
||||
const String getApplicationVersion() override
|
||||
{
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<MyApplicationWindow> myMainWindow;
|
||||
};
|
||||
|
||||
// this generates boilerplate code to launch our app class:
|
||||
START_JUCE_APPLICATION (MyJUCEApp)
|
||||
@endcode
|
||||
|
||||
@see JUCEApplication, START_JUCE_APPLICATION
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API JUCEApplicationBase
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
JUCEApplicationBase();
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~JUCEApplicationBase();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the global instance of the application object that's running. */
|
||||
static JUCEApplicationBase* getInstance() noexcept { return appInstance; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the application's name. */
|
||||
virtual const String getApplicationName() = 0;
|
||||
|
||||
/** Returns the application's version number. */
|
||||
virtual const String getApplicationVersion() = 0;
|
||||
|
||||
/** Checks whether multiple instances of the app are allowed.
|
||||
|
||||
If your application class returns true for this, more than one instance is
|
||||
permitted to run (except on the Mac where this isn't possible).
|
||||
|
||||
If it's false, the second instance won't start, but you will still get a
|
||||
callback to anotherInstanceStarted() to tell you about this - which
|
||||
gives you a chance to react to what the user was trying to do.
|
||||
|
||||
@see anotherInstanceStarted
|
||||
*/
|
||||
virtual bool moreThanOneInstanceAllowed() = 0;
|
||||
|
||||
/** Called when the application starts.
|
||||
|
||||
This will be called once to let the application do whatever initialisation
|
||||
it needs, create its windows, etc.
|
||||
|
||||
After the method returns, the normal event-dispatch loop will be run,
|
||||
until the quit() method is called, at which point the shutdown()
|
||||
method will be called to let the application clear up anything it needs
|
||||
to delete.
|
||||
|
||||
If during the initialise() method, the application decides not to start-up
|
||||
after all, it can just call the quit() method and the event loop won't be run.
|
||||
|
||||
@param commandLineParameters the line passed in does not include the name of
|
||||
the executable, just the parameter list. To get the
|
||||
parameters as an array, you can call
|
||||
JUCEApplication::getCommandLineParameters()
|
||||
@see shutdown, quit
|
||||
*/
|
||||
virtual void initialise (const String& commandLineParameters) = 0;
|
||||
|
||||
/* Called to allow the application to clear up before exiting.
|
||||
|
||||
After JUCEApplication::quit() has been called, the event-dispatch loop will
|
||||
terminate, and this method will get called to allow the app to sort itself
|
||||
out.
|
||||
|
||||
Be careful that nothing happens in this method that might rely on messages
|
||||
being sent, or any kind of window activity, because the message loop is no
|
||||
longer running at this point.
|
||||
|
||||
@see DeletedAtShutdown
|
||||
*/
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
/** Indicates that the user has tried to start up another instance of the app.
|
||||
|
||||
This will get called even if moreThanOneInstanceAllowed() is false.
|
||||
It is currently only implemented on Windows and Mac.
|
||||
|
||||
@see moreThanOneInstanceAllowed
|
||||
*/
|
||||
virtual void anotherInstanceStarted (const String& commandLine) = 0;
|
||||
|
||||
/** Called when the operating system is trying to close the application.
|
||||
|
||||
The default implementation of this method is to call quit(), but it may
|
||||
be overloaded to ignore the request or do some other special behaviour
|
||||
instead. For example, you might want to offer the user the chance to save
|
||||
their changes before quitting, and give them the chance to cancel.
|
||||
|
||||
If you want to send a quit signal to your app, this is the correct method
|
||||
to call, because it means that requests that come from the system get handled
|
||||
in the same way as those from your own application code. So e.g. you'd
|
||||
call this method from a "quit" item on a menu bar.
|
||||
*/
|
||||
virtual void systemRequestedQuit() = 0;
|
||||
|
||||
/** This method is called when the application is being put into background mode
|
||||
by the operating system.
|
||||
*/
|
||||
virtual void suspended() = 0;
|
||||
|
||||
/** This method is called when the application is being woken from background mode
|
||||
by the operating system.
|
||||
*/
|
||||
virtual void resumed() = 0;
|
||||
|
||||
/** This method is called when the application (generally on android) is started
|
||||
*/
|
||||
virtual void started() {}
|
||||
|
||||
/** This method is called when the application (generally on android) is stopped
|
||||
*/
|
||||
virtual void stopped() {}
|
||||
|
||||
/** If any unhandled exceptions make it through to the message dispatch loop, this
|
||||
callback will be triggered, in case you want to log them or do some other
|
||||
type of error-handling.
|
||||
|
||||
If the type of exception is derived from the std::exception class, the pointer
|
||||
passed-in will be valid. If the exception is of unknown type, this pointer
|
||||
will be null.
|
||||
*/
|
||||
virtual void unhandledException (const std::exception*,
|
||||
const String& sourceFilename,
|
||||
int lineNumber) = 0;
|
||||
|
||||
/** Called by the operating system to indicate that you should reduce your memory
|
||||
footprint.
|
||||
|
||||
You should override this method to free up some memory gracefully, if possible,
|
||||
otherwise the host may forcibly kill your app.
|
||||
|
||||
At the moment this method is only called on iOS.
|
||||
*/
|
||||
virtual void memoryWarningReceived() { jassertfalse; }
|
||||
|
||||
/** Called by the operating system when a custom file type was opened. You are expected
|
||||
* to return true if you handled the URL.
|
||||
|
||||
At the moment this method is only called on iOS.
|
||||
*/
|
||||
virtual void urlOpened(const URL& url) { }
|
||||
|
||||
//==============================================================================
|
||||
/** This will be called when the back button on a device is pressed. The return value
|
||||
should be used to indicate whether the back button event has been handled by
|
||||
the application, for example if you want to implement custom navigation instead
|
||||
of the standard behaviour on Android.
|
||||
|
||||
This is currently only implemented on Android devices.
|
||||
|
||||
@returns true if the event has been handled, or false if the default OS
|
||||
behaviour should happen
|
||||
*/
|
||||
virtual bool backButtonPressed() { return false; }
|
||||
|
||||
//==============================================================================
|
||||
/** Signals that the main message loop should stop and the application should terminate.
|
||||
|
||||
This isn't synchronous, it just posts a quit message to the main queue, and
|
||||
when this message arrives, the message loop will stop, the shutdown() method
|
||||
will be called, and the app will exit.
|
||||
|
||||
Note that this will cause an unconditional quit to happen, so if you need an
|
||||
extra level before this, e.g. to give the user the chance to save their work
|
||||
and maybe cancel the quit, you'll need to handle this in the systemRequestedQuit()
|
||||
method - see that method's help for more info.
|
||||
|
||||
@see MessageManager
|
||||
*/
|
||||
static void quit();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the application's command line parameters as a set of strings.
|
||||
@see getCommandLineParameters
|
||||
*/
|
||||
static StringArray JUCE_CALLTYPE getCommandLineParameterArray();
|
||||
|
||||
/** Returns the application's command line parameters as a single string.
|
||||
@see getCommandLineParameterArray
|
||||
*/
|
||||
static String JUCE_CALLTYPE getCommandLineParameters();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the value that should be returned as the application's exit code when the
|
||||
app quits.
|
||||
|
||||
This is the value that's returned by the main() function. Normally you'd leave this
|
||||
as 0 unless you want to indicate an error code.
|
||||
|
||||
@see getApplicationReturnValue
|
||||
*/
|
||||
void setApplicationReturnValue (int newReturnValue) noexcept;
|
||||
|
||||
/** Returns the value that has been set as the application's exit code.
|
||||
@see setApplicationReturnValue
|
||||
*/
|
||||
int getApplicationReturnValue() const noexcept { return appReturnValue; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if this executable is running as an app (as opposed to being a plugin
|
||||
or other kind of shared library. */
|
||||
static bool isStandaloneApp() noexcept { return createInstance != nullptr; }
|
||||
|
||||
/** Returns true if the application hasn't yet completed its initialise() method
|
||||
and entered the main event loop.
|
||||
|
||||
This is handy for things like splash screens to know when the app's up-and-running
|
||||
properly.
|
||||
*/
|
||||
bool isInitialising() const noexcept { return stillInitialising; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#ifndef DOXYGEN
|
||||
// The following methods are for internal use only...
|
||||
static int main();
|
||||
static int main (int argc, const char* argv[]);
|
||||
|
||||
static void appWillTerminateByForce();
|
||||
using CreateInstanceFunction = JUCEApplicationBase* (*)();
|
||||
static CreateInstanceFunction createInstance;
|
||||
|
||||
#if JUCE_IOS
|
||||
static void* iOSCustomDelegate;
|
||||
#endif
|
||||
|
||||
virtual bool initialiseApp();
|
||||
int shutdownApp();
|
||||
static void JUCE_CALLTYPE sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber);
|
||||
bool sendCommandLineToPreexistingInstance();
|
||||
#endif
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
static JUCEApplicationBase* appInstance;
|
||||
int appReturnValue = 0;
|
||||
bool stillInitialising = true;
|
||||
|
||||
struct MultipleInstanceHandler;
|
||||
std::unique_ptr<MultipleInstanceHandler> multipleInstanceHandler;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (JUCEApplicationBase)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS || DOXYGEN
|
||||
|
||||
/** The JUCE_TRY/JUCE_CATCH_EXCEPTION wrappers can be used to pass any uncaught exceptions to
|
||||
the JUCEApplicationBase::sendUnhandledException() method.
|
||||
This functionality can be enabled with the JUCE_CATCH_UNHANDLED_EXCEPTIONS macro.
|
||||
*/
|
||||
#define JUCE_TRY try
|
||||
|
||||
/** The JUCE_TRY/JUCE_CATCH_EXCEPTION wrappers can be used to pass any uncaught exceptions to
|
||||
the JUCEApplicationBase::sendUnhandledException() method.
|
||||
This functionality can be enabled with the JUCE_CATCH_UNHANDLED_EXCEPTIONS macro.
|
||||
*/
|
||||
#define JUCE_CATCH_EXCEPTION \
|
||||
catch (const std::exception& e) { juce::JUCEApplicationBase::sendUnhandledException (&e, __FILE__, __LINE__); } \
|
||||
catch (...) { juce::JUCEApplicationBase::sendUnhandledException (nullptr, __FILE__, __LINE__); }
|
||||
|
||||
#else
|
||||
#define JUCE_TRY
|
||||
#define JUCE_CATCH_EXCEPTION
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
74
deps/juce/modules/juce_events/messages/juce_CallbackMessage.h
vendored
Normal file
74
deps/juce/modules/juce_events/messages/juce_CallbackMessage.h
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A message that invokes a callback method when it gets delivered.
|
||||
|
||||
You can use this class to fire off actions that you want to be performed later
|
||||
on the message thread.
|
||||
|
||||
To use it, create a subclass of CallbackMessage which implements the messageCallback()
|
||||
method, then call post() to dispatch it. The event thread will then invoke your
|
||||
messageCallback() method later on, and will automatically delete the message object
|
||||
afterwards.
|
||||
|
||||
Always create a new instance of a CallbackMessage on the heap, as it will be
|
||||
deleted automatically after the message has been delivered.
|
||||
|
||||
Note that this class was essential back in the days before C++11, but in modern
|
||||
times you may prefer to use MessageManager::callAsync() with a lambda.
|
||||
|
||||
@see MessageManager::callAsync, MessageListener, ActionListener, ChangeListener
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API CallbackMessage : public MessageManager::MessageBase
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
CallbackMessage() = default;
|
||||
|
||||
/** Destructor. */
|
||||
~CallbackMessage() override = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Called when the message is delivered.
|
||||
|
||||
You should implement this method and make it do whatever action you want
|
||||
to perform.
|
||||
|
||||
Note that like all other messages, this object will be deleted immediately
|
||||
after this method has been invoked.
|
||||
*/
|
||||
void messageCallback() override = 0;
|
||||
|
||||
private:
|
||||
// Avoid the leak-detector because for plugins, the host can unload our DLL with undelivered
|
||||
// messages still in the system event queue. These aren't harmful, but can cause annoying assertions.
|
||||
JUCE_DECLARE_NON_COPYABLE (CallbackMessage)
|
||||
};
|
||||
|
||||
} // namespace juce
|
89
deps/juce/modules/juce_events/messages/juce_DeletedAtShutdown.cpp
vendored
Normal file
89
deps/juce/modules/juce_events/messages/juce_DeletedAtShutdown.cpp
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
static SpinLock deletedAtShutdownLock; // use a spin lock because it can be statically initialised
|
||||
|
||||
static Array<DeletedAtShutdown*>& getDeletedAtShutdownObjects()
|
||||
{
|
||||
static Array<DeletedAtShutdown*> objects;
|
||||
return objects;
|
||||
}
|
||||
|
||||
DeletedAtShutdown::DeletedAtShutdown()
|
||||
{
|
||||
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
|
||||
getDeletedAtShutdownObjects().add (this);
|
||||
}
|
||||
|
||||
DeletedAtShutdown::~DeletedAtShutdown()
|
||||
{
|
||||
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
|
||||
getDeletedAtShutdownObjects().removeFirstMatchingValue (this);
|
||||
}
|
||||
|
||||
// Disable unreachable code warning, in case the compiler manages to figure out that
|
||||
// you have no classes of DeletedAtShutdown that could throw an exception in their destructor.
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
|
||||
|
||||
void DeletedAtShutdown::deleteAll()
|
||||
{
|
||||
// make a local copy of the array, so it can't get into a loop if something
|
||||
// creates another DeletedAtShutdown object during its destructor.
|
||||
Array<DeletedAtShutdown*> localCopy;
|
||||
|
||||
{
|
||||
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
|
||||
localCopy = getDeletedAtShutdownObjects();
|
||||
}
|
||||
|
||||
for (int i = localCopy.size(); --i >= 0;)
|
||||
{
|
||||
JUCE_TRY
|
||||
{
|
||||
auto* deletee = localCopy.getUnchecked(i);
|
||||
|
||||
// double-check that it's not already been deleted during another object's destructor.
|
||||
{
|
||||
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
|
||||
|
||||
if (! getDeletedAtShutdownObjects().contains (deletee))
|
||||
deletee = nullptr;
|
||||
}
|
||||
|
||||
delete deletee;
|
||||
}
|
||||
JUCE_CATCH_EXCEPTION
|
||||
}
|
||||
|
||||
// if this fails, then it's likely that some new DeletedAtShutdown objects were
|
||||
// created while executing the destructors of the other ones.
|
||||
jassert (getDeletedAtShutdownObjects().isEmpty());
|
||||
|
||||
getDeletedAtShutdownObjects().clear(); // just to make sure the array doesn't have any memory still allocated
|
||||
}
|
||||
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
|
||||
} // namespace juce
|
65
deps/juce/modules/juce_events/messages/juce_DeletedAtShutdown.h
vendored
Normal file
65
deps/juce/modules/juce_events/messages/juce_DeletedAtShutdown.h
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Classes derived from this will be automatically deleted when the application exits.
|
||||
|
||||
After JUCEApplicationBase::shutdown() has been called, any objects derived from
|
||||
DeletedAtShutdown which are still in existence will be deleted in the reverse
|
||||
order to that in which they were created.
|
||||
|
||||
So if you've got a singleton and don't want to have to explicitly delete it, just
|
||||
inherit from this and it'll be taken care of.
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API DeletedAtShutdown
|
||||
{
|
||||
protected:
|
||||
/** Creates a DeletedAtShutdown object. */
|
||||
DeletedAtShutdown();
|
||||
|
||||
/** Destructor.
|
||||
|
||||
It's ok to delete these objects explicitly - it's only the ones left
|
||||
dangling at the end that will be deleted automatically.
|
||||
*/
|
||||
virtual ~DeletedAtShutdown();
|
||||
|
||||
|
||||
public:
|
||||
/** Deletes all extant objects.
|
||||
|
||||
This shouldn't be used by applications, as it's called automatically
|
||||
in the shutdown code of the JUCEApplicationBase class.
|
||||
*/
|
||||
static void deleteAll();
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (DeletedAtShutdown)
|
||||
};
|
||||
|
||||
} // namespace juce
|
213
deps/juce/modules/juce_events/messages/juce_Initialisation.h
vendored
Normal file
213
deps/juce/modules/juce_events/messages/juce_Initialisation.h
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises JUCE's GUI classes.
|
||||
|
||||
If you're embedding JUCE into an application that uses its own event-loop rather
|
||||
than using the START_JUCE_APPLICATION macro, call this function before making any
|
||||
JUCE calls, to make sure things are initialised correctly.
|
||||
|
||||
Note that if you're creating a JUCE DLL for Windows, you may also need to call the
|
||||
Process::setCurrentModuleInstanceHandle() method.
|
||||
|
||||
@see shutdownJuce_GUI()
|
||||
*/
|
||||
JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI();
|
||||
|
||||
/** Clears up any static data being used by JUCE's GUI classes.
|
||||
|
||||
If you're embedding JUCE into an application that uses its own event-loop rather
|
||||
than using the START_JUCE_APPLICATION macro, call this function in your shutdown
|
||||
code to clean up any JUCE objects that might be lying around.
|
||||
|
||||
@see initialiseJuce_GUI()
|
||||
*/
|
||||
JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI();
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** A utility object that helps you initialise and shutdown JUCE correctly
|
||||
using an RAII pattern.
|
||||
|
||||
When the first instance of this class is created, it calls initialiseJuce_GUI(),
|
||||
and when the last instance is deleted, it calls shutdownJuce_GUI(), so that you
|
||||
can easily be sure that as long as at least one instance of the class exists, the
|
||||
library will be initialised.
|
||||
|
||||
This class is particularly handy to use at the beginning of a console app's
|
||||
main() function, because it'll take care of shutting down whenever you return
|
||||
from the main() call.
|
||||
|
||||
Be careful with your threading though - to be safe, you should always make sure
|
||||
that these objects are created and deleted on the message thread.
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API ScopedJuceInitialiser_GUI final
|
||||
{
|
||||
public:
|
||||
/** The constructor simply calls initialiseJuce_GUI(). */
|
||||
ScopedJuceInitialiser_GUI();
|
||||
|
||||
/** The destructor simply calls shutdownJuce_GUI(). */
|
||||
~ScopedJuceInitialiser_GUI();
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
To start a JUCE app, use this macro: START_JUCE_APPLICATION (AppSubClass) where
|
||||
AppSubClass is the name of a class derived from JUCEApplication or JUCEApplicationBase.
|
||||
|
||||
See the JUCEApplication and JUCEApplicationBase class documentation for more details.
|
||||
*/
|
||||
#if DOXYGEN
|
||||
#define START_JUCE_APPLICATION(AppClass)
|
||||
#else
|
||||
#if JUCE_WINDOWS && ! defined (_CONSOLE)
|
||||
#define JUCE_MAIN_FUNCTION \
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (28251) \
|
||||
int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int) \
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
#define JUCE_MAIN_FUNCTION_ARGS
|
||||
#else
|
||||
#define JUCE_MAIN_FUNCTION int main (int argc, char* argv[])
|
||||
#define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv
|
||||
#endif
|
||||
|
||||
#if JUCE_IOS
|
||||
|
||||
#define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes") \
|
||||
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
|
||||
void* juce_GetIOSCustomDelegateClass() { return nullptr; } \
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
#define JUCE_CREATE_APPLICATION_DEFINE_CUSTOM_DELEGATE(AppClass, DelegateClass) \
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes") \
|
||||
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
|
||||
void* juce_GetIOSCustomDelegateClass() { return [DelegateClass class]; } \
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
#define JUCE_MAIN_FUNCTION_DEFINITION \
|
||||
extern "C" JUCE_MAIN_FUNCTION \
|
||||
{ \
|
||||
juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; \
|
||||
juce::JUCEApplicationBase::iOSCustomDelegate = juce_GetIOSCustomDelegateClass(); \
|
||||
return juce::JUCEApplicationBase::main (JUCE_MAIN_FUNCTION_ARGS); \
|
||||
}
|
||||
|
||||
#elif JUCE_ANDROID
|
||||
|
||||
#define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
|
||||
extern "C" juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
|
||||
|
||||
#define JUCE_MAIN_FUNCTION_DEFINITION
|
||||
|
||||
#else
|
||||
|
||||
#define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
|
||||
juce::JUCEApplicationBase* juce_CreateApplication(); \
|
||||
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
|
||||
|
||||
#define JUCE_MAIN_FUNCTION_DEFINITION \
|
||||
extern "C" JUCE_MAIN_FUNCTION \
|
||||
{ \
|
||||
juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; \
|
||||
return juce::JUCEApplicationBase::main (JUCE_MAIN_FUNCTION_ARGS); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if JucePlugin_Build_Standalone
|
||||
#if JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP
|
||||
#define START_JUCE_APPLICATION(AppClass) JUCE_CREATE_APPLICATION_DEFINE(AppClass)
|
||||
#if JUCE_IOS
|
||||
#define START_JUCE_APPLICATION_WITH_CUSTOM_DELEGATE(AppClass, DelegateClass) JUCE_CREATE_APPLICATION_DEFINE_CUSTOM_DELEGATE(AppClass, DelegateClass)
|
||||
#endif
|
||||
#else
|
||||
#define START_JUCE_APPLICATION(AppClass) static_assert(false, "You are trying to use START_JUCE_APPLICATION in an audio plug-in. Define JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1 if you want to use a custom standalone target app.");
|
||||
#if JUCE_IOS
|
||||
#define START_JUCE_APPLICATION_WITH_CUSTOM_DELEGATE(AppClass, DelegateClass) static_assert(false, "You are trying to use START_JUCE_APPLICATION in an audio plug-in. Define JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1 if you want to use a custom standalone target app.");
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define START_JUCE_APPLICATION(AppClass) \
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes") \
|
||||
JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
|
||||
JUCE_MAIN_FUNCTION_DEFINITION \
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
#if JUCE_IOS
|
||||
/**
|
||||
You can instruct JUCE to use a custom iOS app delegate class instead of JUCE's default
|
||||
app delegate. For JUCE to work you must pass all messages to JUCE's internal app delegate.
|
||||
Below is an example of minimal forwarding custom delegate. Note that you are at your own
|
||||
risk if you decide to use your own delegate and subtle, hard to debug bugs may occur.
|
||||
|
||||
@interface MyCustomDelegate : NSObject <UIApplicationDelegate> { NSObject<UIApplicationDelegate>* juceDelegate; } @end
|
||||
|
||||
@implementation MyCustomDelegate
|
||||
|
||||
-(id) init
|
||||
{
|
||||
self = [super init];
|
||||
juceDelegate = reinterpret_cast<NSObject<UIApplicationDelegate>*> ([[NSClassFromString (@"JuceAppStartupDelegate") alloc] init]);
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) dealloc
|
||||
{
|
||||
[juceDelegate release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) forwardInvocation: (NSInvocation*) anInvocation
|
||||
{
|
||||
if (juceDelegate != nullptr && [juceDelegate respondsToSelector: [anInvocation selector]])
|
||||
[anInvocation invokeWithTarget: juceDelegate];
|
||||
else
|
||||
[super forwardInvocation: anInvocation];
|
||||
}
|
||||
|
||||
-(BOOL) respondsToSelector: (SEL) aSelector
|
||||
{
|
||||
if (juceDelegate != nullptr && [juceDelegate respondsToSelector: aSelector])
|
||||
return YES;
|
||||
|
||||
return [super respondsToSelector: aSelector];
|
||||
}
|
||||
@end
|
||||
*/
|
||||
#define START_JUCE_APPLICATION_WITH_CUSTOM_DELEGATE(AppClass, DelegateClass) \
|
||||
JUCE_CREATE_APPLICATION_DEFINE_CUSTOM_DELEGATE(AppClass, DelegateClass) \
|
||||
JUCE_MAIN_FUNCTION_DEFINITION
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
64
deps/juce/modules/juce_events/messages/juce_Message.h
vendored
Normal file
64
deps/juce/modules/juce_events/messages/juce_Message.h
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
class MessageListener;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** The base class for objects that can be sent to a MessageListener.
|
||||
|
||||
If you want to send a message that carries some kind of custom data, just
|
||||
create a subclass of Message with some appropriate member variables to hold
|
||||
your data.
|
||||
|
||||
Always create a new instance of a Message object on the heap, as it will be
|
||||
deleted automatically after the message has been delivered.
|
||||
|
||||
@see MessageListener, MessageManager, ActionListener, ChangeListener
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API Message : public MessageManager::MessageBase
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an uninitialised message. */
|
||||
Message() noexcept;
|
||||
~Message() override;
|
||||
|
||||
using Ptr = ReferenceCountedObjectPtr<Message>;
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
friend class MessageListener;
|
||||
WeakReference<MessageListener> recipient;
|
||||
void messageCallback() override;
|
||||
|
||||
// Avoid the leak-detector because for plugins, the host can unload our DLL with undelivered
|
||||
// messages still in the system event queue. These aren't harmful, but can cause annoying assertions.
|
||||
JUCE_DECLARE_NON_COPYABLE (Message)
|
||||
};
|
||||
|
||||
} // namespace juce
|
52
deps/juce/modules/juce_events/messages/juce_MessageListener.cpp
vendored
Normal file
52
deps/juce/modules/juce_events/messages/juce_MessageListener.cpp
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
Message::Message() noexcept {}
|
||||
Message::~Message() {}
|
||||
|
||||
void Message::messageCallback()
|
||||
{
|
||||
if (auto* r = recipient.get())
|
||||
r->handleMessage (*this);
|
||||
}
|
||||
|
||||
MessageListener::MessageListener() noexcept
|
||||
{
|
||||
// Are you trying to create a messagelistener before or after juce has been initialised??
|
||||
JUCE_ASSERT_MESSAGE_MANAGER_EXISTS
|
||||
}
|
||||
|
||||
MessageListener::~MessageListener()
|
||||
{
|
||||
masterReference.clear();
|
||||
}
|
||||
|
||||
void MessageListener::postMessage (Message* const message) const
|
||||
{
|
||||
message->recipient = const_cast<MessageListener*> (this);
|
||||
message->post();
|
||||
}
|
||||
|
||||
} // namespace juce
|
70
deps/juce/modules/juce_events/messages/juce_MessageListener.h
vendored
Normal file
70
deps/juce/modules/juce_events/messages/juce_MessageListener.h
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
MessageListener subclasses can post and receive Message objects.
|
||||
|
||||
@see Message, MessageManager, ActionListener, ChangeListener
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API MessageListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MessageListener() noexcept;
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~MessageListener();
|
||||
|
||||
//==============================================================================
|
||||
/** This is the callback method that receives incoming messages.
|
||||
|
||||
This is called by the MessageManager from its dispatch loop.
|
||||
|
||||
@see postMessage
|
||||
*/
|
||||
virtual void handleMessage (const Message& message) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Sends a message to the message queue, for asynchronous delivery to this listener
|
||||
later on.
|
||||
|
||||
This method can be called safely by any thread.
|
||||
|
||||
@param message the message object to send - this will be deleted
|
||||
automatically by the message queue, so make sure it's
|
||||
allocated on the heap, not the stack!
|
||||
@see handleMessage
|
||||
*/
|
||||
void postMessage (Message* message) const;
|
||||
|
||||
private:
|
||||
WeakReference<MessageListener>::Master masterReference;
|
||||
friend class WeakReference<MessageListener>;
|
||||
};
|
||||
|
||||
} // namespace juce
|
483
deps/juce/modules/juce_events/messages/juce_MessageManager.cpp
vendored
Normal file
483
deps/juce/modules/juce_events/messages/juce_MessageManager.cpp
vendored
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
MessageManager::MessageManager() noexcept
|
||||
: messageThreadId (Thread::getCurrentThreadId())
|
||||
{
|
||||
if (JUCEApplicationBase::isStandaloneApp())
|
||||
Thread::setCurrentThreadName ("JUCE Message Thread");
|
||||
}
|
||||
|
||||
MessageManager::~MessageManager() noexcept
|
||||
{
|
||||
broadcaster.reset();
|
||||
|
||||
doPlatformSpecificShutdown();
|
||||
|
||||
jassert (instance == this);
|
||||
instance = nullptr; // do this last in case this instance is still needed by doPlatformSpecificShutdown()
|
||||
}
|
||||
|
||||
MessageManager* MessageManager::instance = nullptr;
|
||||
|
||||
MessageManager* MessageManager::getInstance()
|
||||
{
|
||||
if (instance == nullptr)
|
||||
{
|
||||
instance = new MessageManager();
|
||||
doPlatformSpecificInitialisation();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
MessageManager* MessageManager::getInstanceWithoutCreating() noexcept
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
void MessageManager::deleteInstance()
|
||||
{
|
||||
deleteAndZero (instance);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool MessageManager::MessageBase::post()
|
||||
{
|
||||
auto* mm = MessageManager::instance;
|
||||
|
||||
if (mm == nullptr || mm->quitMessagePosted.get() != 0 || ! postMessageToSystemQueue (this))
|
||||
{
|
||||
Ptr deleter (this); // (this will delete messages that were just created with a 0 ref count)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if ! (JUCE_MAC || JUCE_IOS || JUCE_ANDROID)
|
||||
// implemented in platform-specific code (juce_linux_Messaging.cpp and juce_win32_Messaging.cpp)
|
||||
bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages);
|
||||
|
||||
class MessageManager::QuitMessage : public MessageManager::MessageBase
|
||||
{
|
||||
public:
|
||||
QuitMessage() {}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
if (auto* mm = MessageManager::instance)
|
||||
mm->quitMessageReceived = true;
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (QuitMessage)
|
||||
};
|
||||
|
||||
void MessageManager::runDispatchLoop()
|
||||
{
|
||||
jassert (isThisTheMessageThread()); // must only be called by the message thread
|
||||
|
||||
while (quitMessageReceived.get() == 0)
|
||||
{
|
||||
JUCE_TRY
|
||||
{
|
||||
if (! dispatchNextMessageOnSystemQueue (false))
|
||||
Thread::sleep (1);
|
||||
}
|
||||
JUCE_CATCH_EXCEPTION
|
||||
}
|
||||
}
|
||||
|
||||
void MessageManager::stopDispatchLoop()
|
||||
{
|
||||
(new QuitMessage())->post();
|
||||
quitMessagePosted = true;
|
||||
}
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
|
||||
{
|
||||
jassert (isThisTheMessageThread()); // must only be called by the message thread
|
||||
|
||||
auto endTime = Time::currentTimeMillis() + millisecondsToRunFor;
|
||||
|
||||
while (quitMessageReceived.get() == 0)
|
||||
{
|
||||
JUCE_TRY
|
||||
{
|
||||
if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
|
||||
Thread::sleep (1);
|
||||
}
|
||||
JUCE_CATCH_EXCEPTION
|
||||
|
||||
if (millisecondsToRunFor >= 0 && Time::currentTimeMillis() >= endTime)
|
||||
break;
|
||||
}
|
||||
|
||||
return quitMessageReceived.get() == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
class AsyncFunctionCallback : public MessageManager::MessageBase
|
||||
{
|
||||
public:
|
||||
AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param)
|
||||
: func (f), parameter (param)
|
||||
{}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
result = (*func) (parameter);
|
||||
finished.signal();
|
||||
}
|
||||
|
||||
WaitableEvent finished;
|
||||
std::atomic<void*> result { nullptr };
|
||||
|
||||
private:
|
||||
MessageCallbackFunction* const func;
|
||||
void* const parameter;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCallback)
|
||||
};
|
||||
|
||||
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* func, void* parameter)
|
||||
{
|
||||
if (isThisTheMessageThread())
|
||||
return func (parameter);
|
||||
|
||||
// If this thread has the message manager locked, then this will deadlock!
|
||||
jassert (! currentThreadHasLockedMessageManager());
|
||||
|
||||
const ReferenceCountedObjectPtr<AsyncFunctionCallback> message (new AsyncFunctionCallback (func, parameter));
|
||||
|
||||
if (message->post())
|
||||
{
|
||||
message->finished.wait();
|
||||
return message->result.load();
|
||||
}
|
||||
|
||||
jassertfalse; // the OS message queue failed to send the message!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MessageManager::callAsync (std::function<void()> fn)
|
||||
{
|
||||
struct AsyncCallInvoker : public MessageBase
|
||||
{
|
||||
AsyncCallInvoker (std::function<void()> f) : callback (std::move (f)) {}
|
||||
void messageCallback() override { callback(); }
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
return (new AsyncCallInvoker (std::move (fn)))->post();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MessageManager::deliverBroadcastMessage (const String& value)
|
||||
{
|
||||
if (broadcaster != nullptr)
|
||||
broadcaster->sendActionMessage (value);
|
||||
}
|
||||
|
||||
void MessageManager::registerBroadcastListener (ActionListener* const listener)
|
||||
{
|
||||
if (broadcaster == nullptr)
|
||||
broadcaster.reset (new ActionBroadcaster());
|
||||
|
||||
broadcaster->addActionListener (listener);
|
||||
}
|
||||
|
||||
void MessageManager::deregisterBroadcastListener (ActionListener* const listener)
|
||||
{
|
||||
if (broadcaster != nullptr)
|
||||
broadcaster->removeActionListener (listener);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool MessageManager::isThisTheMessageThread() const noexcept
|
||||
{
|
||||
return Thread::getCurrentThreadId() == messageThreadId;
|
||||
}
|
||||
|
||||
void MessageManager::setCurrentThreadAsMessageThread()
|
||||
{
|
||||
auto thisThread = Thread::getCurrentThreadId();
|
||||
|
||||
if (messageThreadId != thisThread)
|
||||
{
|
||||
messageThreadId = thisThread;
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
// This is needed on windows to make sure the message window is created by this thread
|
||||
doPlatformSpecificShutdown();
|
||||
doPlatformSpecificInitialisation();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageManager::currentThreadHasLockedMessageManager() const noexcept
|
||||
{
|
||||
auto thisThread = Thread::getCurrentThreadId();
|
||||
return thisThread == messageThreadId || thisThread == threadWithLock.get();
|
||||
}
|
||||
|
||||
bool MessageManager::existsAndIsLockedByCurrentThread() noexcept
|
||||
{
|
||||
if (auto i = getInstanceWithoutCreating())
|
||||
return i->currentThreadHasLockedMessageManager();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MessageManager::existsAndIsCurrentThread() noexcept
|
||||
{
|
||||
if (auto i = getInstanceWithoutCreating())
|
||||
return i->isThisTheMessageThread();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
/* The only safe way to lock the message thread while another thread does
|
||||
some work is by posting a special message, whose purpose is to tie up the event
|
||||
loop until the other thread has finished its business.
|
||||
|
||||
Any other approach can get horribly deadlocked if the OS uses its own hidden locks which
|
||||
get locked before making an event callback, because if the same OS lock gets indirectly
|
||||
accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens
|
||||
in Cocoa).
|
||||
*/
|
||||
struct MessageManager::Lock::BlockingMessage : public MessageManager::MessageBase
|
||||
{
|
||||
BlockingMessage (const MessageManager::Lock* parent) noexcept
|
||||
: owner (parent)
|
||||
{}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
{
|
||||
ScopedLock lock (ownerCriticalSection);
|
||||
|
||||
if (auto* o = owner.get())
|
||||
o->messageCallback();
|
||||
}
|
||||
|
||||
releaseEvent.wait();
|
||||
}
|
||||
|
||||
CriticalSection ownerCriticalSection;
|
||||
Atomic<const MessageManager::Lock*> owner;
|
||||
WaitableEvent releaseEvent;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (BlockingMessage)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
MessageManager::Lock::Lock() {}
|
||||
MessageManager::Lock::~Lock() { exit(); }
|
||||
void MessageManager::Lock::enter() const noexcept { tryAcquire (true); }
|
||||
bool MessageManager::Lock::tryEnter() const noexcept { return tryAcquire (false); }
|
||||
|
||||
bool MessageManager::Lock::tryAcquire (bool lockIsMandatory) const noexcept
|
||||
{
|
||||
auto* mm = MessageManager::instance;
|
||||
|
||||
if (mm == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! lockIsMandatory && (abortWait.get() != 0))
|
||||
{
|
||||
abortWait.set (0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mm->currentThreadHasLockedMessageManager())
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
blockingMessage = *new BlockingMessage (this);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
jassert (! lockIsMandatory);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! blockingMessage->post())
|
||||
{
|
||||
// post of message failed while trying to get the lock
|
||||
jassert (! lockIsMandatory);
|
||||
blockingMessage = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
while (abortWait.get() == 0)
|
||||
lockedEvent.wait (-1);
|
||||
|
||||
abortWait.set (0);
|
||||
|
||||
if (lockGained.get() != 0)
|
||||
{
|
||||
mm->threadWithLock = Thread::getCurrentThreadId();
|
||||
return true;
|
||||
}
|
||||
|
||||
} while (lockIsMandatory);
|
||||
|
||||
// we didn't get the lock
|
||||
blockingMessage->releaseEvent.signal();
|
||||
|
||||
{
|
||||
ScopedLock lock (blockingMessage->ownerCriticalSection);
|
||||
|
||||
lockGained.set (0);
|
||||
blockingMessage->owner.set (nullptr);
|
||||
}
|
||||
|
||||
blockingMessage = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MessageManager::Lock::exit() const noexcept
|
||||
{
|
||||
if (lockGained.compareAndSetBool (false, true))
|
||||
{
|
||||
auto* mm = MessageManager::instance;
|
||||
|
||||
jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager());
|
||||
lockGained.set (0);
|
||||
|
||||
if (mm != nullptr)
|
||||
mm->threadWithLock = {};
|
||||
|
||||
if (blockingMessage != nullptr)
|
||||
{
|
||||
blockingMessage->releaseEvent.signal();
|
||||
blockingMessage = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageManager::Lock::messageCallback() const
|
||||
{
|
||||
lockGained.set (1);
|
||||
abort();
|
||||
}
|
||||
|
||||
void MessageManager::Lock::abort() const noexcept
|
||||
{
|
||||
abortWait.set (1);
|
||||
lockedEvent.signal();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MessageManagerLock::MessageManagerLock (Thread* threadToCheck)
|
||||
: locked (attemptLock (threadToCheck, nullptr))
|
||||
{}
|
||||
|
||||
MessageManagerLock::MessageManagerLock (ThreadPoolJob* jobToCheck)
|
||||
: locked (attemptLock (nullptr, jobToCheck))
|
||||
{}
|
||||
|
||||
bool MessageManagerLock::attemptLock (Thread* threadToCheck, ThreadPoolJob* jobToCheck)
|
||||
{
|
||||
jassert (threadToCheck == nullptr || jobToCheck == nullptr);
|
||||
|
||||
if (threadToCheck != nullptr)
|
||||
threadToCheck->addListener (this);
|
||||
|
||||
if (jobToCheck != nullptr)
|
||||
jobToCheck->addListener (this);
|
||||
|
||||
// tryEnter may have a spurious abort (return false) so keep checking the condition
|
||||
while ((threadToCheck == nullptr || ! threadToCheck->threadShouldExit())
|
||||
&& (jobToCheck == nullptr || ! jobToCheck->shouldExit()))
|
||||
{
|
||||
if (mmLock.tryEnter())
|
||||
break;
|
||||
}
|
||||
|
||||
if (threadToCheck != nullptr)
|
||||
{
|
||||
threadToCheck->removeListener (this);
|
||||
|
||||
if (threadToCheck->threadShouldExit())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (jobToCheck != nullptr)
|
||||
{
|
||||
jobToCheck->removeListener (this);
|
||||
|
||||
if (jobToCheck->shouldExit())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageManagerLock::~MessageManagerLock() { mmLock.exit(); }
|
||||
|
||||
void MessageManagerLock::exitSignalSent()
|
||||
{
|
||||
mmLock.abort();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI()
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
MessageManager::getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI()
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
DeletedAtShutdown::deleteAll();
|
||||
MessageManager::deleteInstance();
|
||||
}
|
||||
}
|
||||
|
||||
static int numScopedInitInstances = 0;
|
||||
|
||||
ScopedJuceInitialiser_GUI::ScopedJuceInitialiser_GUI() { if (numScopedInitInstances++ == 0) initialiseJuce_GUI(); }
|
||||
ScopedJuceInitialiser_GUI::~ScopedJuceInitialiser_GUI() { if (--numScopedInitInstances == 0) shutdownJuce_GUI(); }
|
||||
|
||||
} // namespace juce
|
483
deps/juce/modules/juce_events/messages/juce_MessageManager.h
vendored
Normal file
483
deps/juce/modules/juce_events/messages/juce_MessageManager.h
vendored
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
class MessageManagerLock;
|
||||
class ThreadPoolJob;
|
||||
class ActionListener;
|
||||
class ActionBroadcaster;
|
||||
|
||||
//==============================================================================
|
||||
/** See MessageManager::callFunctionOnMessageThread() for use of this function type. */
|
||||
using MessageCallbackFunction = void* (void* userData);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This class is in charge of the application's event-dispatch loop.
|
||||
|
||||
@see Message, CallbackMessage, MessageManagerLock, JUCEApplication, JUCEApplicationBase
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API MessageManager final
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Returns the global instance of the MessageManager. */
|
||||
static MessageManager* getInstance();
|
||||
|
||||
/** Returns the global instance of the MessageManager, or nullptr if it doesn't exist. */
|
||||
static MessageManager* getInstanceWithoutCreating() noexcept;
|
||||
|
||||
/** Deletes the global MessageManager instance.
|
||||
Does nothing if no instance had been created.
|
||||
*/
|
||||
static void deleteInstance();
|
||||
|
||||
//==============================================================================
|
||||
/** Runs the event dispatch loop until a stop message is posted.
|
||||
|
||||
This method is only intended to be run by the application's startup routine,
|
||||
as it blocks, and will only return after the stopDispatchLoop() method has been used.
|
||||
|
||||
@see stopDispatchLoop
|
||||
*/
|
||||
void runDispatchLoop();
|
||||
|
||||
/** Sends a signal that the dispatch loop should terminate.
|
||||
|
||||
After this is called, the runDispatchLoop() or runDispatchLoopUntil() methods
|
||||
will be interrupted and will return.
|
||||
|
||||
@see runDispatchLoop
|
||||
*/
|
||||
void stopDispatchLoop();
|
||||
|
||||
/** Returns true if the stopDispatchLoop() method has been called.
|
||||
*/
|
||||
bool hasStopMessageBeenSent() const noexcept { return quitMessagePosted.get() != 0; }
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
/** Synchronously dispatches messages until a given time has elapsed.
|
||||
|
||||
Returns false if a quit message has been posted by a call to stopDispatchLoop(),
|
||||
otherwise returns true.
|
||||
*/
|
||||
bool runDispatchLoopUntil (int millisecondsToRunFor);
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** Asynchronously invokes a function or C++11 lambda on the message thread.
|
||||
|
||||
@returns true if the message was successfully posted to the message queue,
|
||||
or false otherwise.
|
||||
*/
|
||||
static bool callAsync (std::function<void()> functionToCall);
|
||||
|
||||
/** Calls a function using the message-thread.
|
||||
|
||||
This can be used by any thread to cause this function to be called-back
|
||||
by the message thread. If it's the message-thread that's calling this method,
|
||||
then the function will just be called; if another thread is calling, a message
|
||||
will be posted to the queue, and this method will block until that message
|
||||
is delivered, the function is called, and the result is returned.
|
||||
|
||||
Be careful not to cause any deadlocks with this! It's easy to do - e.g. if the caller
|
||||
thread has a critical section locked, which an unrelated message callback then tries to lock
|
||||
before the message thread gets round to processing this callback.
|
||||
|
||||
@param callback the function to call - its signature must be @code
|
||||
void* myCallbackFunction (void*) @endcode
|
||||
@param userData a user-defined pointer that will be passed to the function that gets called
|
||||
@returns the value that the callback function returns.
|
||||
@see MessageManagerLock
|
||||
*/
|
||||
void* callFunctionOnMessageThread (MessageCallbackFunction* callback, void* userData);
|
||||
|
||||
/** Returns true if the caller-thread is the message thread. */
|
||||
bool isThisTheMessageThread() const noexcept;
|
||||
|
||||
/** Called to tell the manager that the current thread is the one that's running the dispatch loop.
|
||||
|
||||
(Best to ignore this method unless you really know what you're doing..)
|
||||
@see getCurrentMessageThread
|
||||
*/
|
||||
void setCurrentThreadAsMessageThread();
|
||||
|
||||
/** Returns the ID of the current message thread, as set by setCurrentThreadAsMessageThread().
|
||||
|
||||
(Best to ignore this method unless you really know what you're doing..)
|
||||
@see setCurrentThreadAsMessageThread
|
||||
*/
|
||||
Thread::ThreadID getCurrentMessageThread() const noexcept { return messageThreadId; }
|
||||
|
||||
/** Returns true if the caller thread has currently got the message manager locked.
|
||||
|
||||
see the MessageManagerLock class for more info about this.
|
||||
|
||||
This will be true if the caller is the message thread, because that automatically
|
||||
gains a lock while a message is being dispatched.
|
||||
*/
|
||||
bool currentThreadHasLockedMessageManager() const noexcept;
|
||||
|
||||
/** Returns true if there's an instance of the MessageManager, and if the current thread
|
||||
has the lock on it.
|
||||
*/
|
||||
static bool existsAndIsLockedByCurrentThread() noexcept;
|
||||
|
||||
/** Returns true if there's an instance of the MessageManager, and if the current thread
|
||||
is running it.
|
||||
*/
|
||||
static bool existsAndIsCurrentThread() noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Sends a message to all other JUCE applications that are running.
|
||||
|
||||
@param messageText the string that will be passed to the actionListenerCallback()
|
||||
method of the broadcast listeners in the other app.
|
||||
@see registerBroadcastListener, ActionListener
|
||||
*/
|
||||
static void broadcastMessage (const String& messageText);
|
||||
|
||||
/** Registers a listener to get told about broadcast messages.
|
||||
|
||||
The actionListenerCallback() callback's string parameter
|
||||
is the message passed into broadcastMessage().
|
||||
|
||||
@see broadcastMessage
|
||||
*/
|
||||
void registerBroadcastListener (ActionListener* listener);
|
||||
|
||||
/** Deregisters a broadcast listener. */
|
||||
void deregisterBroadcastListener (ActionListener* listener);
|
||||
|
||||
//==============================================================================
|
||||
/** Internal class used as the base class for all message objects.
|
||||
You shouldn't need to use this directly - see the CallbackMessage or Message
|
||||
classes instead.
|
||||
*/
|
||||
class JUCE_API MessageBase : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
MessageBase() = default;
|
||||
~MessageBase() override = default;
|
||||
|
||||
virtual void messageCallback() = 0;
|
||||
bool post();
|
||||
|
||||
using Ptr = ReferenceCountedObjectPtr<MessageBase>;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (MessageBase)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** A lock you can use to lock the message manager. You can use this class with
|
||||
the RAII-based ScopedLock classes.
|
||||
*/
|
||||
class JUCE_API Lock
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Creates a new critical section to exclusively access methods which can
|
||||
only be called when the message manager is locked.
|
||||
|
||||
Unlike CrititcalSection, multiple instances of this lock class provide
|
||||
exclusive access to a single resource - the MessageManager.
|
||||
*/
|
||||
Lock();
|
||||
|
||||
/** Destructor. */
|
||||
~Lock();
|
||||
|
||||
/** Acquires the message manager lock.
|
||||
|
||||
If the caller thread already has exclusive access to the MessageManager, this method
|
||||
will return immediately.
|
||||
If another thread is currently using the MessageManager, this will wait until that
|
||||
thread releases the lock to the MessageManager.
|
||||
|
||||
This call will only exit if the lock was acquired by this thread. Calling abort while
|
||||
a thread is waiting for enter to finish, will have no effect.
|
||||
|
||||
@see exit, abort
|
||||
*/
|
||||
void enter() const noexcept;
|
||||
|
||||
/** Attempts to lock the message manager and exits if abort is called.
|
||||
|
||||
This method behaves identically to enter, except that it will abort waiting for
|
||||
the lock if the abort method is called.
|
||||
|
||||
Unlike other JUCE critical sections, this method **will** block waiting for the lock.
|
||||
|
||||
To ensure predictable behaviour, you should re-check your abort condition if tryEnter
|
||||
returns false.
|
||||
|
||||
This method can be used if you want to do some work while waiting for the
|
||||
MessageManagerLock:
|
||||
|
||||
void doWorkWhileWaitingForMessageManagerLock()
|
||||
{
|
||||
MessageManager::Lock::ScopedTryLockType mmLock (messageManagerLock);
|
||||
|
||||
while (! mmLock.isLocked())
|
||||
{
|
||||
while (workQueue.size() > 0)
|
||||
{
|
||||
auto work = workQueue.pop();
|
||||
doSomeWork (work);
|
||||
}
|
||||
|
||||
// this will block until we either have the lock or there is work
|
||||
mmLock.retryLock();
|
||||
}
|
||||
|
||||
// we have the mmlock
|
||||
// do some message manager stuff like resizing and painting components
|
||||
}
|
||||
|
||||
// called from another thread
|
||||
void addWorkToDo (Work work)
|
||||
{
|
||||
queue.push (work);
|
||||
messageManagerLock.abort();
|
||||
}
|
||||
|
||||
@returns false if waiting for a lock was aborted, true if the lock was acquired.
|
||||
@see enter, abort, ScopedTryLock
|
||||
*/
|
||||
bool tryEnter() const noexcept;
|
||||
|
||||
/** Releases the message manager lock.
|
||||
@see enter, ScopedLock
|
||||
*/
|
||||
void exit() const noexcept;
|
||||
|
||||
/** Unblocks a thread which is waiting in tryEnter
|
||||
Call this method if you want to unblock a thread which is waiting for the
|
||||
MessageManager lock in tryEnter.
|
||||
This method does not have any effect on a thread waiting for a lock in enter.
|
||||
@see tryEnter
|
||||
*/
|
||||
void abort() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Provides the type of scoped lock to use with a CriticalSection. */
|
||||
using ScopedLockType = GenericScopedLock<Lock>;
|
||||
|
||||
/** Provides the type of scoped unlocker to use with a CriticalSection. */
|
||||
using ScopedUnlockType = GenericScopedUnlock<Lock>;
|
||||
|
||||
/** Provides the type of scoped try-locker to use with a CriticalSection. */
|
||||
using ScopedTryLockType = GenericScopedTryLock<Lock>;
|
||||
|
||||
private:
|
||||
struct BlockingMessage;
|
||||
friend class ReferenceCountedObjectPtr<BlockingMessage>;
|
||||
|
||||
bool tryAcquire (bool) const noexcept;
|
||||
void messageCallback() const;
|
||||
|
||||
//==============================================================================
|
||||
mutable ReferenceCountedObjectPtr<BlockingMessage> blockingMessage;
|
||||
WaitableEvent lockedEvent;
|
||||
mutable Atomic<int> abortWait, lockGained;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#ifndef DOXYGEN
|
||||
// Internal methods - do not use!
|
||||
void deliverBroadcastMessage (const String&);
|
||||
~MessageManager() noexcept;
|
||||
#endif
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
MessageManager() noexcept;
|
||||
|
||||
static MessageManager* instance;
|
||||
|
||||
friend class MessageBase;
|
||||
class QuitMessage;
|
||||
friend class QuitMessage;
|
||||
friend class MessageManagerLock;
|
||||
|
||||
std::unique_ptr<ActionBroadcaster> broadcaster;
|
||||
Atomic<int> quitMessagePosted { 0 }, quitMessageReceived { 0 };
|
||||
Thread::ThreadID messageThreadId;
|
||||
Atomic<Thread::ThreadID> threadWithLock;
|
||||
|
||||
static bool postMessageToSystemQueue (MessageBase*);
|
||||
static void* exitModalLoopCallback (void*);
|
||||
static void doPlatformSpecificInitialisation();
|
||||
static void doPlatformSpecificShutdown();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageManager)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Used to make sure that the calling thread has exclusive access to the message loop.
|
||||
|
||||
Because it's not thread-safe to call any of the Component or other UI classes
|
||||
from threads other than the message thread, one of these objects can be used to
|
||||
lock the message loop and allow this to be done. The message thread will be
|
||||
suspended for the lifetime of the MessageManagerLock object, so create one on
|
||||
the stack like this: @code
|
||||
void MyThread::run()
|
||||
{
|
||||
someData = 1234;
|
||||
|
||||
const MessageManagerLock mmLock;
|
||||
// the event loop will now be locked so it's safe to make a few calls..
|
||||
|
||||
myComponent->setBounds (newBounds);
|
||||
myComponent->repaint();
|
||||
|
||||
// ..the event loop will now be unlocked as the MessageManagerLock goes out of scope
|
||||
}
|
||||
@endcode
|
||||
|
||||
Obviously be careful not to create one of these and leave it lying around, or
|
||||
your app will grind to a halt!
|
||||
|
||||
MessageManagerLocks are re-entrant, so can be safely nested if the current thread
|
||||
already has the lock.
|
||||
|
||||
Another caveat is that using this in conjunction with other CriticalSections
|
||||
can create lots of interesting ways of producing a deadlock! In particular, if
|
||||
your message thread calls stopThread() for a thread that uses these locks,
|
||||
you'll get an (occasional) deadlock..
|
||||
|
||||
@see MessageManager, MessageManager::currentThreadHasLockedMessageManager
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API MessageManagerLock : private Thread::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Tries to acquire a lock on the message manager.
|
||||
|
||||
The constructor attempts to gain a lock on the message loop, and the lock will be
|
||||
kept for the lifetime of this object.
|
||||
|
||||
Optionally, you can pass a thread object here, and while waiting to obtain the lock,
|
||||
this method will keep checking whether the thread has been given the
|
||||
Thread::signalThreadShouldExit() signal. If this happens, then it will return
|
||||
without gaining the lock. If you pass a thread, you must check whether the lock was
|
||||
successful by calling lockWasGained(). If this is false, your thread is being told to
|
||||
die, so you should take evasive action.
|
||||
|
||||
If you pass nullptr for the thread object, it will wait indefinitely for the lock - be
|
||||
careful when doing this, because it's very easy to deadlock if your message thread
|
||||
attempts to call stopThread() on a thread just as that thread attempts to get the
|
||||
message lock.
|
||||
|
||||
If the calling thread already has the lock, nothing will be done, so it's safe and
|
||||
quick to use these locks recursively.
|
||||
|
||||
E.g.
|
||||
@code
|
||||
void run()
|
||||
{
|
||||
...
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
MessageManagerLock mml (Thread::getCurrentThread());
|
||||
|
||||
if (! mml.lockWasGained())
|
||||
return; // another thread is trying to kill us!
|
||||
|
||||
..do some locked stuff here..
|
||||
}
|
||||
|
||||
..and now the MM is now unlocked..
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
MessageManagerLock (Thread* threadToCheckForExitSignal = nullptr);
|
||||
|
||||
//==============================================================================
|
||||
/** This has the same behaviour as the other constructor, but takes a ThreadPoolJob
|
||||
instead of a thread.
|
||||
|
||||
See the MessageManagerLock (Thread*) constructor for details on how this works.
|
||||
*/
|
||||
MessageManagerLock (ThreadPoolJob* jobToCheckForExitSignal);
|
||||
|
||||
//==============================================================================
|
||||
/** Releases the current thread's lock on the message manager.
|
||||
|
||||
Make sure this object is created and deleted by the same thread,
|
||||
otherwise there are no guarantees what will happen!
|
||||
*/
|
||||
~MessageManagerLock() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the lock was successfully acquired.
|
||||
(See the constructor that takes a Thread for more info).
|
||||
*/
|
||||
bool lockWasGained() const noexcept { return locked; }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
MessageManager::Lock mmLock;
|
||||
bool locked;
|
||||
|
||||
//==============================================================================
|
||||
bool attemptLock (Thread*, ThreadPoolJob*);
|
||||
void exitSignalSent() override;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (MessageManagerLock)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** This macro is used to catch unsafe use of functions which expect to only be called
|
||||
on the message thread, or when a MessageManagerLock is in place.
|
||||
It will also fail if you try to use the function before the message manager has been
|
||||
created, which could happen if you accidentally invoke it during a static constructor.
|
||||
*/
|
||||
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED \
|
||||
jassert (juce::MessageManager::existsAndIsLockedByCurrentThread());
|
||||
|
||||
/** This macro is used to catch unsafe use of functions which expect to only be called
|
||||
on the message thread.
|
||||
It will also fail if you try to use the function before the message manager has been
|
||||
created, which could happen if you accidentally invoke it during a static constructor.
|
||||
*/
|
||||
#define JUCE_ASSERT_MESSAGE_THREAD \
|
||||
jassert (juce::MessageManager::existsAndIsCurrentThread());
|
||||
|
||||
/** This macro is used to catch unsafe use of functions which expect to not be called
|
||||
outside the lifetime of the MessageManager.
|
||||
*/
|
||||
#define JUCE_ASSERT_MESSAGE_MANAGER_EXISTS \
|
||||
jassert (juce::MessageManager::getInstanceWithoutCreating() != nullptr);
|
||||
|
||||
|
||||
} // namespace juce
|
58
deps/juce/modules/juce_events/messages/juce_MountedVolumeListChangeDetector.h
vendored
Normal file
58
deps/juce/modules/juce_events/messages/juce_MountedVolumeListChangeDetector.h
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_MAC || JUCE_WINDOWS || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An instance of this class will provide callbacks when drives are
|
||||
mounted or unmounted on the system.
|
||||
|
||||
Just inherit from this class and implement the pure virtual method
|
||||
to get the callbacks, there's no need to do anything else.
|
||||
|
||||
@see File::findFileSystemRoots()
|
||||
|
||||
@tags{Events}
|
||||
*/
|
||||
class JUCE_API MountedVolumeListChangeDetector
|
||||
{
|
||||
public:
|
||||
MountedVolumeListChangeDetector();
|
||||
virtual ~MountedVolumeListChangeDetector();
|
||||
|
||||
/** This method is called when a volume is mounted or unmounted. */
|
||||
virtual void mountedVolumeListChanged() = 0;
|
||||
|
||||
private:
|
||||
JUCE_PUBLIC_IN_DLL_BUILD (struct Pimpl)
|
||||
std::unique_ptr<Pimpl> pimpl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MountedVolumeListChangeDetector)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
39
deps/juce/modules/juce_events/messages/juce_NotificationType.h
vendored
Normal file
39
deps/juce/modules/juce_events/messages/juce_NotificationType.h
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
These enums are used in various classes to indicate whether a notification
|
||||
event should be sent out.
|
||||
*/
|
||||
enum NotificationType
|
||||
{
|
||||
dontSendNotification = 0, /**< No notification message should be sent. */
|
||||
sendNotification = 1, /**< Requests a notification message, either synchronous or not. */
|
||||
sendNotificationSync, /**< Requests a synchronous notification. */
|
||||
sendNotificationAsync, /**< Requests an asynchronous notification. */
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user