1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-15 00:24:19 +00:00

Added Animated App template and examples

This commit is contained in:
Felix Faire 2014-10-29 15:55:23 +00:00
parent fefcf7aca6
commit ff6520a89a
1141 changed files with 438491 additions and 94 deletions

View file

@ -0,0 +1,294 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
JUCEApplicationBase::CreateInstanceFunction JUCEApplicationBase::createInstance = 0;
JUCEApplicationBase* JUCEApplicationBase::appInstance = nullptr;
JUCEApplicationBase::JUCEApplicationBase()
: appReturnValue (0),
stillInitialising (true)
{
jassert (isStandaloneApp() && appInstance == nullptr);
appInstance = this;
}
JUCEApplicationBase::~JUCEApplicationBase()
{
jassert (appInstance == this);
appInstance = nullptr;
}
void JUCEApplicationBase::setApplicationReturnValue (const int newReturnValue) noexcept
{
appReturnValue = newReturnValue;
}
// This is called on the Mac and iOS where the OS doesn't allow the stack to unwind on shutdown..
void JUCEApplicationBase::appWillTerminateByForce()
{
JUCE_AUTORELEASEPOOL
{
{
const ScopedPointer<JUCEApplicationBase> app (appInstance);
if (app != nullptr)
app->shutdownApp();
}
DeletedAtShutdown::deleteAll();
MessageManager::deleteInstance();
}
}
void JUCEApplicationBase::quit()
{
MessageManager::getInstance()->stopDispatchLoop();
}
void JUCEApplicationBase::sendUnhandledException (const std::exception* const e,
const char* const sourceFile,
const int lineNumber)
{
if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
app->unhandledException (e, sourceFile, lineNumber);
}
//==============================================================================
#if ! (JUCE_IOS || JUCE_ANDROID)
#define JUCE_HANDLE_MULTIPLE_INSTANCES 1
#endif
#if JUCE_HANDLE_MULTIPLE_INSTANCES
struct JUCEApplicationBase::MultipleInstanceHandler : public ActionListener
{
public:
MultipleInstanceHandler (const String& appName)
: appLock ("juceAppLock_" + appName)
{
}
bool sendCommandLineToPreexistingInstance()
{
if (appLock.enter (0))
return false;
JUCEApplicationBase* const app = JUCEApplicationBase::getInstance();
jassert (app != nullptr);
MessageManager::broadcastMessage (app->getApplicationName()
+ "/" + app->getCommandLineParameters());
return true;
}
void actionListenerCallback (const String& message) override
{
if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
{
const String appName (app->getApplicationName());
if (message.startsWith (appName + "/"))
app->anotherInstanceStarted (message.substring (appName.length() + 1));
}
}
private:
InterProcessLock appLock;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultipleInstanceHandler)
};
bool JUCEApplicationBase::sendCommandLineToPreexistingInstance()
{
jassert (multipleInstanceHandler == nullptr); // this must only be called once!
multipleInstanceHandler = new MultipleInstanceHandler (getApplicationName());
return multipleInstanceHandler->sendCommandLineToPreexistingInstance();
}
#else
struct JUCEApplicationBase::MultipleInstanceHandler {};
#endif
//==============================================================================
#if JUCE_ANDROID
StringArray JUCEApplicationBase::getCommandLineParameterArray() { return StringArray(); }
String JUCEApplicationBase::getCommandLineParameters() { return String(); }
#else
#if JUCE_WINDOWS && ! defined (_CONSOLE)
String JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameters()
{
return CharacterFunctions::findEndOfToken (CharPointer_UTF16 (GetCommandLineW()),
CharPointer_UTF16 (L" "),
CharPointer_UTF16 (L"\"")).findEndOfWhitespace();
}
StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray()
{
StringArray s;
int argc = 0;
if (LPWSTR* const argv = CommandLineToArgvW (GetCommandLineW(), &argc))
{
s = StringArray (argv + 1, argc - 1);
LocalFree (argv);
}
return s;
}
#else
#if JUCE_IOS
extern int juce_iOSMain (int argc, const char* argv[]);
#endif
#if JUCE_MAC
extern void initialiseNSApplication();
#endif
#if JUCE_WINDOWS
const char* const* juce_argv = nullptr;
int juce_argc = 0;
#else
extern const char* const* juce_argv; // declared in juce_core
extern int juce_argc;
#endif
String JUCEApplicationBase::getCommandLineParameters()
{
String argString;
for (int i = 1; i < juce_argc; ++i)
{
String arg (juce_argv[i]);
if (arg.containsChar (' ') && ! arg.isQuotedString())
arg = arg.quoted ('"');
argString << arg << ' ';
}
return argString.trim();
}
StringArray JUCEApplicationBase::getCommandLineParameterArray()
{
return StringArray (juce_argv + 1, juce_argc - 1);
}
int JUCEApplicationBase::main (int argc, const char* argv[])
{
JUCE_AUTORELEASEPOOL
{
juce_argc = argc;
juce_argv = argv;
#if JUCE_MAC
initialiseNSApplication();
#endif
#if JUCE_IOS
return juce_iOSMain (argc, argv);
#else
return JUCEApplicationBase::main();
#endif
}
}
#endif
//==============================================================================
int JUCEApplicationBase::main()
{
ScopedJuceInitialiser_GUI libraryInitialiser;
jassert (createInstance != nullptr);
const ScopedPointer<JUCEApplicationBase> app (createInstance());
jassert (app != nullptr);
if (! app->initialiseApp())
return app->getApplicationReturnValue();
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
// let the app do its setting-up..
initialise (getCommandLineParameters());
stillInitialising = false;
if (MessageManager::getInstance()->hasStopMessageBeenSent())
return false;
#if JUCE_HANDLE_MULTIPLE_INSTANCES
if (multipleInstanceHandler != nullptr)
MessageManager::getInstance()->registerBroadcastListener (multipleInstanceHandler);
#endif
return true;
}
int JUCEApplicationBase::shutdownApp()
{
jassert (JUCEApplicationBase::getInstance() == this);
#if JUCE_HANDLE_MULTIPLE_INSTANCES
if (multipleInstanceHandler != nullptr)
MessageManager::getInstance()->deregisterBroadcastListener (multipleInstanceHandler);
#endif
JUCE_TRY
{
// give the app a chance to clean up..
shutdown();
}
JUCE_CATCH_EXCEPTION
multipleInstanceHandler = nullptr;
return getApplicationReturnValue();
}

View file

@ -0,0 +1,283 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_APPLICATIONBASE_H_INCLUDED
#define JUCE_APPLICATIONBASE_H_INCLUDED
//==============================================================================
/**
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 = 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:
ScopedPointer<MyApplicationWindow> myMainWindow;
};
// this generates boilerplate code to launch our app class:
START_JUCE_APPLICATION (MyJUCEApp)
@endcode
@see JUCEApplication, START_JUCE_APPLICATION
*/
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 you 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 it 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.
*/
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.
*/
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;
/** 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;
//==============================================================================
/** 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();
typedef JUCEApplicationBase* (*CreateInstanceFunction)();
static CreateInstanceFunction createInstance;
virtual bool initialiseApp();
static void JUCE_CALLTYPE sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber);
bool sendCommandLineToPreexistingInstance();
#endif
private:
//==============================================================================
static JUCEApplicationBase* appInstance;
int appReturnValue;
bool stillInitialising;
struct MultipleInstanceHandler;
friend struct MultipleInstanceHandler;
friend struct ContainerDeletePolicy<MultipleInstanceHandler>;
ScopedPointer<MultipleInstanceHandler> multipleInstanceHandler;
int shutdownApp();
JUCE_DECLARE_NON_COPYABLE (JUCEApplicationBase)
};
#endif // JUCE_APPLICATIONBASE_H_INCLUDED

View file

@ -0,0 +1,73 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_CALLBACKMESSAGE_H_INCLUDED
#define JUCE_CALLBACKMESSAGE_H_INCLUDED
//==============================================================================
/**
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.
@see MessageManager, MessageListener, ActionListener, ChangeListener
*/
class JUCE_API CallbackMessage : public MessageManager::MessageBase
{
public:
//==============================================================================
CallbackMessage() noexcept {}
/** Destructor. */
~CallbackMessage() {}
//==============================================================================
/** 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.
*/
virtual void messageCallback() = 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)
};
#endif // JUCE_CALLBACKMESSAGE_H_INCLUDED

View file

@ -0,0 +1,79 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
static SpinLock deletedAtShutdownLock;
DeletedAtShutdown::DeletedAtShutdown()
{
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
getObjects().add (this);
}
DeletedAtShutdown::~DeletedAtShutdown()
{
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
getObjects().removeFirstMatchingValue (this);
}
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 = getObjects();
}
for (int i = localCopy.size(); --i >= 0;)
{
JUCE_TRY
{
DeletedAtShutdown* deletee = localCopy.getUnchecked(i);
// double-check that it's not already been deleted during another object's destructor.
{
const SpinLock::ScopedLockType sl (deletedAtShutdownLock);
if (! getObjects().contains (deletee))
deletee = nullptr;
}
delete deletee;
}
JUCE_CATCH_EXCEPTION
}
// if no objects got re-created during shutdown, this should have been emptied by their
// destructors
jassert (getObjects().size() == 0);
getObjects().clear(); // just to make sure the array doesn't have any memory still allocated
}
Array <DeletedAtShutdown*>& DeletedAtShutdown::getObjects()
{
static Array <DeletedAtShutdown*> objects;
return objects;
}

View file

@ -0,0 +1,68 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_DELETEDATSHUTDOWN_H_INCLUDED
#define JUCE_DELETEDATSHUTDOWN_H_INCLUDED
//==============================================================================
/**
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.
*/
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:
static Array <DeletedAtShutdown*>& getObjects();
JUCE_DECLARE_NON_COPYABLE (DeletedAtShutdown)
};
#endif // JUCE_DELETEDATSHUTDOWN_H_INCLUDED

View file

@ -0,0 +1,112 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_INITIALISATION_H_INCLUDED
#define JUCE_INITIALISATION_H_INCLUDED
//==============================================================================
/** 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.
*/
class JUCE_API ScopedJuceInitialiser_GUI
{
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.
*/
#ifdef DOXYGEN
#define START_JUCE_APPLICATION(AppClass)
#elif JUCE_ANDROID
#define START_JUCE_APPLICATION(AppClass) \
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
#else
#if JUCE_WINDOWS && ! defined (_CONSOLE)
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int)
#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
#define START_JUCE_APPLICATION(AppClass) \
static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
extern "C" JUCE_MAIN_FUNCTION \
{ \
juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; \
return juce::JUCEApplicationBase::main (JUCE_MAIN_FUNCTION_ARGS); \
}
#endif
#endif // JUCE_INITIALISATION_H_INCLUDED

View file

@ -0,0 +1,65 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_MESSAGE_H_INCLUDED
#define JUCE_MESSAGE_H_INCLUDED
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
*/
class JUCE_API Message : public MessageManager::MessageBase
{
public:
//==============================================================================
/** Creates an uninitialised message. */
Message() noexcept;
~Message();
typedef ReferenceCountedObjectPtr<Message> Ptr;
//==============================================================================
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)
};
#endif // JUCE_MESSAGE_H_INCLUDED

View file

@ -0,0 +1,49 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
Message::Message() noexcept {}
Message::~Message() {}
void Message::messageCallback()
{
if (MessageListener* const r = recipient)
r->handleMessage (*this);
}
MessageListener::MessageListener() noexcept
{
// Are you trying to create a messagelistener before or after juce has been intialised??
jassert (MessageManager::getInstanceWithoutCreating() != nullptr);
}
MessageListener::~MessageListener()
{
masterReference.clear();
}
void MessageListener::postMessage (Message* const message) const
{
message->recipient = const_cast <MessageListener*> (this);
message->post();
}

View file

@ -0,0 +1,72 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_MESSAGELISTENER_H_INCLUDED
#define JUCE_MESSAGELISTENER_H_INCLUDED
//==============================================================================
/**
MessageListener subclasses can post and receive Message objects.
@see Message, MessageManager, ActionListener, ChangeListener
*/
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>;
};
#endif // JUCE_MESSAGELISTENER_H_INCLUDED

View file

@ -0,0 +1,375 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
MessageManager::MessageManager() noexcept
: quitMessagePosted (false),
quitMessageReceived (false),
messageThreadId (Thread::getCurrentThreadId()),
threadWithLock (0)
{
if (JUCEApplicationBase::isStandaloneApp())
Thread::setCurrentThreadName ("Juce Message Thread");
}
MessageManager::~MessageManager() noexcept
{
broadcaster = nullptr;
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()
{
MessageManager* const mm = MessageManager::instance;
if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this))
{
Ptr deleter (this); // (this will delete messages that were just created with a 0 ref count)
return false;
}
return true;
}
//==============================================================================
#if JUCE_MODAL_LOOPS_PERMITTED && ! (JUCE_MAC || JUCE_IOS)
void MessageManager::runDispatchLoop()
{
runDispatchLoopUntil (-1);
}
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
{
jassert (isThisTheMessageThread()); // must only be called by the message thread
const int64 endTime = Time::currentTimeMillis() + millisecondsToRunFor;
while (! quitMessageReceived)
{
JUCE_TRY
{
if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
Thread::sleep (1);
}
JUCE_CATCH_EXCEPTION
if (millisecondsToRunFor >= 0 && Time::currentTimeMillis() >= endTime)
break;
}
return ! quitMessageReceived;
}
class MessageManager::QuitMessage : public MessageManager::MessageBase
{
public:
QuitMessage() {}
void messageCallback() override
{
if (MessageManager* const mm = MessageManager::instance)
mm->quitMessageReceived = true;
}
JUCE_DECLARE_NON_COPYABLE (QuitMessage)
};
void MessageManager::stopDispatchLoop()
{
(new QuitMessage())->post();
quitMessagePosted = true;
}
#endif
//==============================================================================
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
struct AsyncFunction : private MessageManager::MessageBase
{
AsyncFunction (std::function<void(void)> f) : fn (f) { post(); }
private:
std::function<void(void)> fn;
void messageCallback() override { fn(); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncFunction)
};
void MessageManager::callAsync (std::function<void(void)> f)
{
new AsyncFunction (f);
}
#endif
//==============================================================================
class AsyncFunctionCallback : public MessageManager::MessageBase
{
public:
AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param)
: result (nullptr), func (f), parameter (param)
{}
void messageCallback() override
{
result = (*func) (parameter);
finished.signal();
}
WaitableEvent finished;
void* volatile result;
private:
MessageCallbackFunction* const func;
void* const parameter;
JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCallback)
};
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* const func, void* const 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;
}
jassertfalse; // the OS message queue failed to send the message!
return nullptr;
}
//==============================================================================
void MessageManager::deliverBroadcastMessage (const String& value)
{
if (broadcaster != nullptr)
broadcaster->sendActionMessage (value);
}
void MessageManager::registerBroadcastListener (ActionListener* const listener)
{
if (broadcaster == nullptr)
broadcaster = 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()
{
const Thread::ThreadID thisThread = Thread::getCurrentThreadId();
if (messageThreadId != thisThread)
{
messageThreadId = thisThread;
// This is needed on windows to make sure the message window is created by this thread
doPlatformSpecificShutdown();
doPlatformSpecificInitialisation();
}
}
bool MessageManager::currentThreadHasLockedMessageManager() const noexcept
{
const Thread::ThreadID thisThread = Thread::getCurrentThreadId();
return thisThread == messageThreadId || thisThread == threadWithLock;
}
//==============================================================================
//==============================================================================
/* 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).
*/
class MessageManagerLock::BlockingMessage : public MessageManager::MessageBase
{
public:
BlockingMessage() noexcept {}
void messageCallback() override
{
lockedEvent.signal();
releaseEvent.wait();
}
WaitableEvent lockedEvent, releaseEvent;
JUCE_DECLARE_NON_COPYABLE (BlockingMessage)
};
//==============================================================================
MessageManagerLock::MessageManagerLock (Thread* const threadToCheck)
: blockingMessage(), locked (attemptLock (threadToCheck, nullptr))
{
}
MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal)
: blockingMessage(), locked (attemptLock (nullptr, jobToCheckForExitSignal))
{
}
bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob* const job)
{
MessageManager* const mm = MessageManager::instance;
if (mm == nullptr)
return false;
if (mm->currentThreadHasLockedMessageManager())
return true;
if (threadToCheck == nullptr && job == nullptr)
{
mm->lockingLock.enter();
}
else
{
while (! mm->lockingLock.tryEnter())
{
if ((threadToCheck != nullptr && threadToCheck->threadShouldExit())
|| (job != nullptr && job->shouldExit()))
return false;
Thread::yield();
}
}
blockingMessage = new BlockingMessage();
if (! blockingMessage->post())
{
blockingMessage = nullptr;
return false;
}
while (! blockingMessage->lockedEvent.wait (20))
{
if ((threadToCheck != nullptr && threadToCheck->threadShouldExit())
|| (job != nullptr && job->shouldExit()))
{
blockingMessage->releaseEvent.signal();
blockingMessage = nullptr;
mm->lockingLock.exit();
return false;
}
}
jassert (mm->threadWithLock == 0);
mm->threadWithLock = Thread::getCurrentThreadId();
return true;
}
MessageManagerLock::~MessageManagerLock() noexcept
{
if (blockingMessage != nullptr)
{
MessageManager* const mm = MessageManager::instance;
jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager());
blockingMessage->releaseEvent.signal();
blockingMessage = nullptr;
if (mm != nullptr)
{
mm->threadWithLock = 0;
mm->lockingLock.exit();
}
}
}
//==============================================================================
JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI();
JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI()
{
JUCE_AUTORELEASEPOOL
{
MessageManager::getInstance();
}
}
JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI();
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(); }

View file

@ -0,0 +1,335 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_MESSAGEMANAGER_H_INCLUDED
#define JUCE_MESSAGEMANAGER_H_INCLUDED
class MessageManagerLock;
class ThreadPoolJob;
class ActionListener;
class ActionBroadcaster;
//==============================================================================
/** See MessageManager::callFunctionOnMessageThread() for use of this function type
*/
typedef void* (MessageCallbackFunction) (void* userData);
//==============================================================================
/**
This class is in charge of the application's event-dispatch loop.
@see Message, CallbackMessage, MessageManagerLock, JUCEApplication, JUCEApplicationBase
*/
class JUCE_API MessageManager
{
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; }
#if JUCE_MODAL_LOOPS_PERMITTED || DOXYGEN
/** 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
//==============================================================================
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
/** Asynchronously invokes a function or C++11 lambda on the message thread.
Internally this uses the CallbackMessage class to invoke the callback.
*/
static void callAsync (std::function<void(void)>);
#endif
/** 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;
//==============================================================================
/** 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() noexcept {}
virtual ~MessageBase() {}
virtual void messageCallback() = 0;
bool post();
typedef ReferenceCountedObjectPtr<MessageBase> Ptr;
JUCE_DECLARE_NON_COPYABLE (MessageBase)
};
//==============================================================================
#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;
ScopedPointer <ActionBroadcaster> broadcaster;
bool quitMessagePosted, quitMessageReceived;
Thread::ThreadID messageThreadId;
Thread::ThreadID volatile threadWithLock;
CriticalSection lockingLock;
static bool postMessageToSystemQueue (MessageBase*);
static void* exitModalLoopCallback (void*);
static void doPlatformSpecificInitialisation();
static void doPlatformSpecificShutdown();
static bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages);
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!
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
*/
class JUCE_API MessageManagerLock
{
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() noexcept;
//==============================================================================
/** 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:
class BlockingMessage;
friend class ReferenceCountedObjectPtr<BlockingMessage>;
ReferenceCountedObjectPtr<BlockingMessage> blockingMessage;
bool locked;
bool attemptLock (Thread*, ThreadPoolJob*);
JUCE_DECLARE_NON_COPYABLE (MessageManagerLock)
};
#endif // JUCE_MESSAGEMANAGER_H_INCLUDED

View file

@ -0,0 +1,59 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_MOUNTEDVOLUMELISTCHANGEDETECTOR_H_INCLUDED
#define JUCE_MOUNTEDVOLUMELISTCHANGEDETECTOR_H_INCLUDED
#if JUCE_MAC || JUCE_WINDOWS || defined (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()
*/
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)
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MountedVolumeListChangeDetector)
};
#endif
#endif // JUCE_MOUNTEDVOLUMELISTCHANGEDETECTOR_H_INCLUDED

View file

@ -0,0 +1,42 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_NOTIFICATIONTYPE_H_INCLUDED
#define JUCE_NOTIFICATIONTYPE_H_INCLUDED
//==============================================================================
/**
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. */
};
#endif // JUCE_NOTIFICATIONTYPE_H_INCLUDED