- Library code update
- project update (added Eigen) git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@94 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -25,12 +25,11 @@
|
||||
class ActionBroadcaster::ActionMessage : public MessageManager::MessageBase
|
||||
{
|
||||
public:
|
||||
ActionMessage (const ActionBroadcaster* const broadcaster_,
|
||||
const String& messageText,
|
||||
ActionListener* const listener_) noexcept
|
||||
: broadcaster (const_cast <ActionBroadcaster*> (broadcaster_)),
|
||||
ActionMessage (const ActionBroadcaster* ab,
|
||||
const String& messageText, ActionListener* l) noexcept
|
||||
: broadcaster (const_cast<ActionBroadcaster*> (ab)),
|
||||
message (messageText),
|
||||
listener (listener_)
|
||||
listener (l)
|
||||
{}
|
||||
|
||||
void messageCallback() override
|
||||
|
||||
@@ -61,7 +61,9 @@ AsyncUpdater::~AsyncUpdater()
|
||||
void AsyncUpdater::triggerAsyncUpdate()
|
||||
{
|
||||
if (activeMessage->shouldDeliver.compareAndSetBool (1, 0))
|
||||
activeMessage->post();
|
||||
if (! activeMessage->post())
|
||||
cancelPendingUpdate(); // if the message queue fails, this avoids getting
|
||||
// trapped waiting for the message to arrive
|
||||
}
|
||||
|
||||
void AsyncUpdater::cancelPendingUpdate() noexcept
|
||||
|
||||
@@ -68,8 +68,8 @@ public:
|
||||
callback happens, this will cancel the handleAsyncUpdate() callback.
|
||||
|
||||
Note that this method simply cancels the next callback - if a callback is already
|
||||
in progress on a different thread, this won't block until it finishes, so there's
|
||||
no guarantee that the callback isn't still running when you return from
|
||||
in progress on a different thread, this won't block until the callback finishes, so
|
||||
there's no guarantee that the callback isn't still running when the method returns.
|
||||
*/
|
||||
void cancelPendingUpdate() noexcept;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ enum { magicMastSlaveConnectionHeader = 0x712baf04 };
|
||||
static const char* startMessage = "__ipc_st";
|
||||
static const char* killMessage = "__ipc_k_";
|
||||
static const char* pingMessage = "__ipc_p_";
|
||||
enum { specialMessageSize = 8 };
|
||||
enum { specialMessageSize = 8, defaultTimeoutMs = 8000 };
|
||||
|
||||
static String getCommandLinePrefix (const String& commandLineUniqueID)
|
||||
{
|
||||
@@ -40,7 +40,7 @@ static String getCommandLinePrefix (const String& commandLineUniqueID)
|
||||
struct ChildProcessPingThread : public Thread,
|
||||
private AsyncUpdater
|
||||
{
|
||||
ChildProcessPingThread() : Thread ("IPC ping"), timeoutMs (8000)
|
||||
ChildProcessPingThread (int timeout) : Thread ("IPC ping"), timeoutMs (timeout)
|
||||
{
|
||||
pingReceived();
|
||||
}
|
||||
@@ -84,8 +84,10 @@ private:
|
||||
struct ChildProcessMaster::Connection : public InterprocessConnection,
|
||||
private ChildProcessPingThread
|
||||
{
|
||||
Connection (ChildProcessMaster& m, const String& pipeName)
|
||||
: InterprocessConnection (false, magicMastSlaveConnectionHeader), owner (m)
|
||||
Connection (ChildProcessMaster& m, const String& pipeName, int timeout)
|
||||
: InterprocessConnection (false, magicMastSlaveConnectionHeader),
|
||||
ChildProcessPingThread (timeout),
|
||||
owner (m)
|
||||
{
|
||||
if (createPipe (pipeName, timeoutMs))
|
||||
startThread (4);
|
||||
@@ -140,7 +142,7 @@ bool ChildProcessMaster::sendMessageToSlave (const MemoryBlock& mb)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID)
|
||||
bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID, int timeoutMs)
|
||||
{
|
||||
connection = nullptr;
|
||||
jassert (childProcess.kill());
|
||||
@@ -153,7 +155,7 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin
|
||||
|
||||
if (childProcess.start (args))
|
||||
{
|
||||
connection = new Connection (*this, pipeName);
|
||||
connection = new Connection (*this, pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs);
|
||||
|
||||
if (connection->isConnected())
|
||||
{
|
||||
@@ -171,8 +173,10 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin
|
||||
struct ChildProcessSlave::Connection : public InterprocessConnection,
|
||||
private ChildProcessPingThread
|
||||
{
|
||||
Connection (ChildProcessSlave& p, const String& pipeName)
|
||||
: InterprocessConnection (false, magicMastSlaveConnectionHeader), owner (p)
|
||||
Connection (ChildProcessSlave& p, const String& pipeName, int timeout)
|
||||
: InterprocessConnection (false, magicMastSlaveConnectionHeader),
|
||||
ChildProcessPingThread (timeout),
|
||||
owner (p)
|
||||
{
|
||||
connectToPipe (pipeName, timeoutMs);
|
||||
startThread (4);
|
||||
@@ -237,7 +241,8 @@ bool ChildProcessSlave::sendMessageToMaster (const MemoryBlock& mb)
|
||||
}
|
||||
|
||||
bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine,
|
||||
const String& commandLineUniqueID)
|
||||
const String& commandLineUniqueID,
|
||||
int timeoutMs)
|
||||
{
|
||||
String prefix (getCommandLinePrefix (commandLineUniqueID));
|
||||
|
||||
@@ -248,7 +253,7 @@ bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine,
|
||||
|
||||
if (pipeName.isNotEmpty())
|
||||
{
|
||||
connection = new Connection (*this, pipeName);
|
||||
connection = new Connection (*this, pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs);
|
||||
|
||||
if (! connection->isConnected())
|
||||
connection = nullptr;
|
||||
|
||||
@@ -64,10 +64,16 @@ public:
|
||||
The commandLineUniqueID should be a short alphanumeric identifier (no spaces!)
|
||||
that matches the string passed to ChildProcessMaster::launchSlaveProcess().
|
||||
|
||||
The timeoutMs parameter lets you specify how long the child process is allowed
|
||||
to run without receiving a ping from the master before the master is considered to
|
||||
have died, and handleConnectionLost() will be called. Passing <= 0 for this timeout
|
||||
makes it use a default value.
|
||||
|
||||
Returns true if the command-line matches and the connection is made successfully.
|
||||
*/
|
||||
bool initialiseFromCommandLine (const String& commandLine,
|
||||
const String& commandLineUniqueID);
|
||||
const String& commandLineUniqueID,
|
||||
int timeoutMs = 0);
|
||||
|
||||
//==============================================================================
|
||||
/** This will be called to deliver messages from the master process.
|
||||
@@ -141,11 +147,17 @@ public:
|
||||
that gets launched must respond by calling ChildProcessSlave::initialiseFromCommandLine()
|
||||
in its startup code, and must use a matching ID to commandLineUniqueID.
|
||||
|
||||
The timeoutMs parameter lets you specify how long the child process is allowed
|
||||
to go without sending a ping before it is considered to have died and
|
||||
handleConnectionLost() will be called. Passing <= 0 for this timeout makes
|
||||
it use a default value.
|
||||
|
||||
If this all works, the method returns true, and you can begin sending and
|
||||
receiving messages with the slave process.
|
||||
*/
|
||||
bool launchSlaveProcess (const File& executableToLaunch,
|
||||
const String& commandLineUniqueID);
|
||||
const String& commandLineUniqueID,
|
||||
int timeoutMs = 0);
|
||||
|
||||
/** This will be called to deliver a message from the slave process.
|
||||
The call will probably be made on a background thread, so be careful with your thread-safety!
|
||||
|
||||
@@ -31,7 +31,7 @@ struct InterprocessConnection::ConnectionThread : public Thread
|
||||
private:
|
||||
InterprocessConnection& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread);
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
@@ -69,11 +69,9 @@ bool InterprocessConnection::connectToSocket (const String& hostName,
|
||||
thread->startThread();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
socket = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
socket = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InterprocessConnection::connectToPipe (const String& pipeName, const int timeoutMs)
|
||||
@@ -143,41 +141,43 @@ bool InterprocessConnection::isConnected() const
|
||||
|
||||
String InterprocessConnection::getConnectedHostName() const
|
||||
{
|
||||
if (pipe != nullptr)
|
||||
return "localhost";
|
||||
|
||||
if (socket != nullptr)
|
||||
{
|
||||
if (! socket->isLocal())
|
||||
return socket->getHostName();
|
||||
const ScopedLock sl (pipeAndSocketLock);
|
||||
|
||||
return "localhost";
|
||||
if (pipe == nullptr && socket == nullptr)
|
||||
return String();
|
||||
|
||||
if (socket != nullptr && ! socket->isLocal())
|
||||
return socket->getHostName();
|
||||
}
|
||||
|
||||
return String();
|
||||
return IPAddress::local().toString();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool InterprocessConnection::sendMessage (const MemoryBlock& message)
|
||||
{
|
||||
uint32 messageHeader[2];
|
||||
messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader);
|
||||
messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize());
|
||||
uint32 messageHeader[2] = { ByteOrder::swapIfBigEndian (magicMessageHeader),
|
||||
ByteOrder::swapIfBigEndian ((uint32) message.getSize()) };
|
||||
|
||||
MemoryBlock messageData (sizeof (messageHeader) + message.getSize());
|
||||
messageData.copyFrom (messageHeader, 0, sizeof (messageHeader));
|
||||
messageData.copyFrom (message.getData(), sizeof (messageHeader), message.getSize());
|
||||
|
||||
int bytesWritten = 0;
|
||||
return writeData (messageData.getData(), (int) messageData.getSize()) == (int) messageData.getSize();
|
||||
}
|
||||
|
||||
int InterprocessConnection::writeData (void* data, int dataSize)
|
||||
{
|
||||
const ScopedLock sl (pipeAndSocketLock);
|
||||
|
||||
if (socket != nullptr)
|
||||
bytesWritten = socket->write (messageData.getData(), (int) messageData.getSize());
|
||||
else if (pipe != nullptr)
|
||||
bytesWritten = pipe->write (messageData.getData(), (int) messageData.getSize(), pipeReceiveMessageTimeout);
|
||||
return socket->write (data, dataSize);
|
||||
|
||||
return bytesWritten == (int) messageData.getSize();
|
||||
if (pipe != nullptr)
|
||||
return pipe->write (data, dataSize, pipeReceiveMessageTimeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
@@ -201,6 +201,7 @@ private:
|
||||
friend struct ContainerDeletePolicy<ConnectionThread>;
|
||||
ScopedPointer<ConnectionThread> thread;
|
||||
void runThread();
|
||||
int writeData (void*, int);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection)
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "juce_events",
|
||||
"name": "JUCE message and event handling classes",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.8",
|
||||
"description": "Classes for running an application's main event loop and sending/receiving messages, timers, etc.",
|
||||
"website": "http://www.juce.com/juce",
|
||||
"license": "GPL/Commercial",
|
||||
|
||||
@@ -138,7 +138,7 @@ String JUCEApplicationBase::getCommandLineParameters() { return String(
|
||||
|
||||
#else
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
#if JUCE_WINDOWS && ! defined (_CONSOLE)
|
||||
|
||||
String JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameters()
|
||||
{
|
||||
@@ -171,8 +171,13 @@ StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray()
|
||||
extern void initialiseNSApplication();
|
||||
#endif
|
||||
|
||||
extern const char* const* juce_argv; // declared in juce_core
|
||||
extern int juce_argc;
|
||||
#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()
|
||||
{
|
||||
@@ -227,7 +232,7 @@ int JUCEApplicationBase::main()
|
||||
jassert (app != nullptr);
|
||||
|
||||
if (! app->initialiseApp())
|
||||
return 0;
|
||||
return app->getApplicationReturnValue();
|
||||
|
||||
JUCE_TRY
|
||||
{
|
||||
|
||||
@@ -50,24 +50,24 @@
|
||||
MyJUCEApp() {}
|
||||
~MyJUCEApp() {}
|
||||
|
||||
void initialise (const String& commandLine)
|
||||
void initialise (const String& commandLine) override
|
||||
{
|
||||
myMainWindow = new MyApplicationWindow();
|
||||
myMainWindow->setBounds (100, 100, 400, 500);
|
||||
myMainWindow->setVisible (true);
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
void shutdown() override
|
||||
{
|
||||
myMainWindow = nullptr;
|
||||
}
|
||||
|
||||
const String getApplicationName()
|
||||
const String getApplicationName() override
|
||||
{
|
||||
return "Super JUCE-o-matic";
|
||||
}
|
||||
|
||||
const String getApplicationVersion()
|
||||
const String getApplicationVersion() override
|
||||
{
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
@@ -55,13 +55,17 @@ JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI();
|
||||
/** A utility object that helps you initialise and shutdown Juce correctly
|
||||
using an RAII pattern.
|
||||
|
||||
When an instance of this class is created, it calls initialiseJuce_GUI(),
|
||||
and when it's deleted, it calls shutdownJuce_GUI(), which lets you easily
|
||||
make sure that these functions are matched correctly.
|
||||
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
|
||||
{
|
||||
@@ -88,18 +92,12 @@ public:
|
||||
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
|
||||
|
||||
#else
|
||||
#if JUCE_WINDOWS
|
||||
#if defined (WINAPI) || defined (_WINDOWS_)
|
||||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPSTR, int)
|
||||
#elif defined (_UNICODE)
|
||||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const wchar_t*, int)
|
||||
#else
|
||||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const char*, int)
|
||||
#endif
|
||||
#define JUCE_MAIN_FUNCTION_ARGS
|
||||
#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
|
||||
#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) \
|
||||
|
||||
@@ -66,12 +66,17 @@ void MessageManager::deleteInstance()
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MessageManager::MessageBase::post()
|
||||
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;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -125,6 +130,25 @@ void MessageManager::stopDispatchLoop()
|
||||
|
||||
#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
|
||||
{
|
||||
@@ -158,9 +182,15 @@ void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* cons
|
||||
jassert (! currentThreadHasLockedMessageManager());
|
||||
|
||||
const ReferenceCountedObjectPtr<AsyncFunctionCallback> message (new AsyncFunctionCallback (func, parameter));
|
||||
message->post();
|
||||
message->finished.wait();
|
||||
return message->result;
|
||||
|
||||
if (message->post())
|
||||
{
|
||||
message->finished.wait();
|
||||
return message->result;
|
||||
}
|
||||
|
||||
jassertfalse; // the OS message queue failed to send the message!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -275,7 +305,12 @@ bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob
|
||||
}
|
||||
|
||||
blockingMessage = new BlockingMessage();
|
||||
blockingMessage->post();
|
||||
|
||||
if (! blockingMessage->post())
|
||||
{
|
||||
blockingMessage = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
while (! blockingMessage->lockedEvent.wait (20))
|
||||
{
|
||||
@@ -334,5 +369,7 @@ JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI()
|
||||
}
|
||||
}
|
||||
|
||||
ScopedJuceInitialiser_GUI::ScopedJuceInitialiser_GUI() { initialiseJuce_GUI(); }
|
||||
ScopedJuceInitialiser_GUI::~ScopedJuceInitialiser_GUI() { shutdownJuce_GUI(); }
|
||||
static int numScopedInitInstances = 0;
|
||||
|
||||
ScopedJuceInitialiser_GUI::ScopedJuceInitialiser_GUI() { if (numScopedInitInstances++ == 0) initialiseJuce_GUI(); }
|
||||
ScopedJuceInitialiser_GUI::~ScopedJuceInitialiser_GUI() { if (--numScopedInitInstances == 0) shutdownJuce_GUI(); }
|
||||
|
||||
@@ -91,6 +91,13 @@ public:
|
||||
#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
|
||||
@@ -170,7 +177,7 @@ public:
|
||||
virtual ~MessageBase() {}
|
||||
|
||||
virtual void messageCallback() = 0;
|
||||
void post();
|
||||
bool post();
|
||||
|
||||
typedef ReferenceCountedObjectPtr<MessageBase> Ptr;
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend
|
||||
using namespace WindowsMessageHelpers;
|
||||
MSG m;
|
||||
|
||||
if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, 0))
|
||||
if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, PM_NOREMOVE))
|
||||
return false;
|
||||
|
||||
if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)
|
||||
|
||||
Reference in New Issue
Block a user