1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-23 01:44:22 +00:00
JUCE/src/native/mac/juce_iphone_MessageManager.mm
2009-11-26 21:25:45 +00:00

281 lines
7.9 KiB
Text

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online 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.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#if JUCE_INCLUDED_FILE
struct CallbackMessagePayload
{
MessageCallbackFunction* function;
void* parameter;
void* volatile result;
bool volatile hasBeenExecuted;
};
END_JUCE_NAMESPACE
using namespace JUCE_NAMESPACE;
@interface JuceAppDelegate : NSObject <UIApplicationDelegate>
{
}
- (JuceAppDelegate*) init;
- (void) dealloc;
- (BOOL) application: (UIApplication*) application handleOpenURL: (NSURL*) url;
- (void) applicationDidBecomeActive: (NSNotification*) aNotification;
- (void) applicationDidResignActive: (NSNotification*) aNotification;
- (void) applicationWillUnhide: (NSNotification*) aNotification;
- (void) customEvent: (id) data;
- (void) performCallback: (id) info;
@end
@implementation JuceAppDelegate
- (JuceAppDelegate*) init
{
[super init];
[[UIApplication sharedApplication] setDelegate: self];
return self;
}
- (void) dealloc
{
[[UIApplication sharedApplication] setDelegate: nil];
[super dealloc];
}
- (BOOL) application: (UIApplication*) application handleOpenURL: (NSURL*) url
{
if (JUCEApplication::getInstance() != 0)
{
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce ([url absoluteString]));
return YES;
}
return NO;
}
- (void) applicationDidBecomeActive: (NSNotification*) aNotification
{
juce_HandleProcessFocusChange();
}
- (void) applicationDidResignActive: (NSNotification*) aNotification
{
juce_HandleProcessFocusChange();
}
- (void) applicationWillUnhide: (NSNotification*) aNotification
{
juce_HandleProcessFocusChange();
}
- (void) customEvent: (id) n
{
NSData* data = (NSData*) n;
void* message = 0;
[data getBytes: &message length: sizeof (message)];
[data release];
if (message != 0)
MessageManager::getInstance()->deliverMessage (message);
}
- (void) performCallback: (id) info
{
if ([info isKindOfClass: [NSData class]])
{
CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes];
if (pl != 0)
{
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
}
else
{
jassertfalse // should never get here!
}
}
@end
BEGIN_JUCE_NAMESPACE
static JuceAppDelegate* juceAppDelegate = 0;
void MessageManager::runDispatchLoop()
{
jassert (isThisTheMessageThread()); // must only be called by the message thread
runDispatchLoopUntil (-1);
}
static const int quitMessageId = 0xfffff321;
void MessageManager::stopDispatchLoop()
{
exit (0); // iPhone apps get no mercy..
}
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
{
const ScopedAutoReleasePool pool;
jassert (isThisTheMessageThread()); // must only be called by the message thread
uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor;
NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow: millisecondsToRunFor * 0.001];
while (! quitMessagePosted)
{
const ScopedAutoReleasePool pool;
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
beforeDate: endDate];
if (millisecondsToRunFor >= 0 && Time::getMillisecondCounter() >= endTime)
break;
}
return ! quitMessagePosted;
}
//==============================================================================
static CFRunLoopRef runLoop = 0;
static CFRunLoopSourceRef runLoopSource = 0;
static Array <void*, CriticalSection>* pendingMessages = 0;
static void runLoopSourceCallback (void*)
{
if (pendingMessages != 0)
{
int numDispatched = 0;
do
{
void* const nextMessage = pendingMessages->remove (0);
if (nextMessage == 0)
return;
const ScopedAutoReleasePool pool;
MessageManager::getInstance()->deliverMessage (nextMessage);
} while (++numDispatched <= 4);
CFRunLoopSourceSignal (runLoopSource);
CFRunLoopWakeUp (runLoop);
}
}
void MessageManager::doPlatformSpecificInitialisation()
{
pendingMessages = new Array <void*, CriticalSection>();
runLoop = CFRunLoopGetCurrent();
CFRunLoopSourceContext sourceContext;
zerostruct (sourceContext);
sourceContext.perform = runLoopSourceCallback;
runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext);
CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopCommonModes);
if (juceAppDelegate == 0)
juceAppDelegate = [[JuceAppDelegate alloc] init];
}
void MessageManager::doPlatformSpecificShutdown()
{
CFRunLoopSourceInvalidate (runLoopSource);
CFRelease (runLoopSource);
runLoopSource = 0;
if (pendingMessages != 0)
{
while (pendingMessages->size() > 0)
delete ((Message*) pendingMessages->remove(0));
deleteAndZero (pendingMessages);
}
if (juceAppDelegate != 0)
{
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate];
[juceAppDelegate release];
juceAppDelegate = 0;
}
}
bool juce_postMessageToSystemQueue (void* message)
{
if (pendingMessages != 0)
{
pendingMessages->add (message);
CFRunLoopSourceSignal (runLoopSource);
CFRunLoopWakeUp (runLoop);
}
return true;
}
void MessageManager::broadcastMessage (const String& value) throw()
{
}
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* data)
{
if (isThisTheMessageThread())
{
return (*callback) (data);
}
else
{
// If a thread has a MessageManagerLock and then tries to call this method, it'll
// deadlock because the message manager is blocked from running, so can never
// call your function..
jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager());
const ScopedAutoReleasePool pool;
CallbackMessagePayload cmp;
cmp.function = callback;
cmp.parameter = data;
cmp.result = 0;
cmp.hasBeenExecuted = false;
[juceAppDelegate performSelectorOnMainThread: @selector (performCallback:)
withObject: [NSData dataWithBytesNoCopy: &cmp
length: sizeof (cmp)
freeWhenDone: NO]
waitUntilDone: YES];
return cmp.result;
}
}
#endif