|
|
|
@@ -16344,6 +16344,7 @@ bool JUCEApplication::initialiseApp (String& commandLine) |
|
|
|
|
|
|
|
initialiseJuce_GUI(); |
|
|
|
|
|
|
|
#if ! JUCE_IPHONE |
|
|
|
jassert (appLock == 0); // initialiseApp must only be called once! |
|
|
|
|
|
|
|
if (! moreThanOneInstanceAllowed()) |
|
|
|
@@ -16361,6 +16362,7 @@ bool JUCEApplication::initialiseApp (String& commandLine) |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
// let the app do its setting-up.. |
|
|
|
initialise (commandLineParameters); |
|
|
|
@@ -16439,9 +16441,9 @@ int JUCEApplication::main (int argc, char* argv[], |
|
|
|
return juce_IPhoneMain (argc, argv, newApp); |
|
|
|
#else |
|
|
|
|
|
|
|
#if JUCE_MAC |
|
|
|
#if JUCE_MAC |
|
|
|
const ScopedAutoReleasePool pool; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
String cmd; |
|
|
|
for (int i = 1; i < argc; ++i) |
|
|
|
@@ -37105,9 +37107,12 @@ void MessageManager::deliverMessage (void* message) |
|
|
|
{ |
|
|
|
quitMessageReceived = true; |
|
|
|
} |
|
|
|
else if (dynamic_cast <CallbackMessage*> (m) != 0) |
|
|
|
else |
|
|
|
{ |
|
|
|
(dynamic_cast <CallbackMessage*> (m))->messageCallback(); |
|
|
|
CallbackMessage* const cm = dynamic_cast <CallbackMessage*> (m); |
|
|
|
|
|
|
|
if (cm != 0) |
|
|
|
cm->messageCallback(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -51370,6 +51375,9 @@ public: |
|
|
|
atom->getText (passwordCharacter), |
|
|
|
atomX, 0.0f); |
|
|
|
|
|
|
|
if (indexToFind - indexInText >= g.getNumGlyphs()) |
|
|
|
return atomRight; |
|
|
|
|
|
|
|
return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft()); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -51387,7 +51395,7 @@ public: |
|
|
|
atomX, 0.0f); |
|
|
|
|
|
|
|
int j; |
|
|
|
for (j = 0; j < atom->numChars; ++j) |
|
|
|
for (j = 0; j < g.getNumGlyphs(); ++j) |
|
|
|
if ((g.getGlyph(j).getLeft() + g.getGlyph(j).getRight()) / 2 > xToFind) |
|
|
|
break; |
|
|
|
|
|
|
|
@@ -86573,7 +86581,7 @@ void GlyphArrangement::addGlyphArrangement (const GlyphArrangement& other) throw |
|
|
|
|
|
|
|
void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) throw() |
|
|
|
{ |
|
|
|
glyphs.removeRange (startIndex, num); |
|
|
|
glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : num); |
|
|
|
} |
|
|
|
|
|
|
|
void GlyphArrangement::addLineOfText (const Font& font, |
|
|
|
@@ -86635,22 +86643,13 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, |
|
|
|
|
|
|
|
void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) throw() |
|
|
|
{ |
|
|
|
//const TypefaceGlyphInfo* const dotGlyph = font.getTypeface()->getGlyph (T('.')); |
|
|
|
|
|
|
|
if (/*dotGlyph != 0 &&*/ glyphs.size() > 0) |
|
|
|
if (glyphs.size() > 0) |
|
|
|
{ |
|
|
|
//PositionedGlyph* glyph = glyphs.getLast(); |
|
|
|
//const float fontHeight = glyph->font.getHeight(); |
|
|
|
//const float fontHorizontalScale = glyph->font.getHorizontalScale(); |
|
|
|
|
|
|
|
Array<int> dotGlyphs; |
|
|
|
Array<float> dotXs; |
|
|
|
font.getGlyphPositions (T(".."), dotGlyphs, dotXs); |
|
|
|
|
|
|
|
const float dx = dotXs[1]; |
|
|
|
//fontHeight * fontHorizontalScale |
|
|
|
// * (font.getExtraKerningFactor() + dotGlyph->getHorizontalSpacing (T('.'))); |
|
|
|
|
|
|
|
float xOffset = 0.0f, yOffset = 0.0f; |
|
|
|
|
|
|
|
for (int dotPos = 3; --dotPos >= 0 && glyphs.size() > 0;) |
|
|
|
@@ -86971,7 +86970,7 @@ void GlyphArrangement::addFittedText (const Font& f, |
|
|
|
|
|
|
|
if (startIndex < glyphs.size()) |
|
|
|
{ |
|
|
|
glyphs.removeRange (startIndex, glyphs.size()); |
|
|
|
removeRangeOfGlyphs (startIndex, -1); |
|
|
|
|
|
|
|
if (startIndex - originalStartIndex > 4) |
|
|
|
{ |
|
|
|
@@ -88108,8 +88107,8 @@ const AffineTransform AffineTransform::rotation (const float angle, |
|
|
|
const AffineTransform AffineTransform::scaled (const float factorX, |
|
|
|
const float factorY) const throw() |
|
|
|
{ |
|
|
|
return followedBy (factorX, 0, 0, |
|
|
|
0, factorY, 0); |
|
|
|
return AffineTransform (factorX * mat00, factorX * mat01, factorX * mat02, |
|
|
|
factorY * mat10, factorY * mat11, factorY * mat12); |
|
|
|
} |
|
|
|
|
|
|
|
const AffineTransform AffineTransform::scale (const float factorX, |
|
|
|
@@ -234768,6 +234767,10 @@ END_JUCE_NAMESPACE |
|
|
|
|
|
|
|
BEGIN_JUCE_NAMESPACE |
|
|
|
|
|
|
|
#if JUCE_USE_CDBURNER |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
#define JUCE_INCLUDED_FILE 1 |
|
|
|
|
|
|
|
// Now include the actual code files.. |
|
|
|
@@ -251372,8 +251375,6 @@ WaitableEvent::~WaitableEvent() throw() |
|
|
|
bool WaitableEvent::wait (const int timeOutMillisecs) const throw() |
|
|
|
{ |
|
|
|
EventStruct* const es = (EventStruct*) internal; |
|
|
|
|
|
|
|
bool ok = true; |
|
|
|
pthread_mutex_lock (&es->mutex); |
|
|
|
|
|
|
|
if (timeOutMillisecs < 0) |
|
|
|
@@ -251400,16 +251401,15 @@ bool WaitableEvent::wait (const int timeOutMillisecs) const throw() |
|
|
|
|
|
|
|
if (pthread_cond_timedwait (&es->condition, &es->mutex, &time) == ETIMEDOUT) |
|
|
|
{ |
|
|
|
ok = false; |
|
|
|
break; |
|
|
|
pthread_mutex_unlock (&es->mutex); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
es->triggered = false; |
|
|
|
|
|
|
|
pthread_mutex_unlock (&es->mutex); |
|
|
|
return ok; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
void WaitableEvent::signal() const throw() |
|
|
|
@@ -253515,7 +253515,7 @@ void MessageManager::doPlatformSpecificShutdown() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool juce_postMessageToSystemQueue (void* message) |
|
|
|
bool juce_postMessageToSystemQueue (Message* message) |
|
|
|
{ |
|
|
|
if (errorCondition) |
|
|
|
return false; |
|
|
|
@@ -260845,8 +260845,6 @@ WaitableEvent::~WaitableEvent() throw() |
|
|
|
bool WaitableEvent::wait (const int timeOutMillisecs) const throw() |
|
|
|
{ |
|
|
|
EventStruct* const es = (EventStruct*) internal; |
|
|
|
|
|
|
|
bool ok = true; |
|
|
|
pthread_mutex_lock (&es->mutex); |
|
|
|
|
|
|
|
if (timeOutMillisecs < 0) |
|
|
|
@@ -260873,16 +260871,15 @@ bool WaitableEvent::wait (const int timeOutMillisecs) const throw() |
|
|
|
|
|
|
|
if (pthread_cond_timedwait (&es->condition, &es->mutex, &time) == ETIMEDOUT) |
|
|
|
{ |
|
|
|
ok = false; |
|
|
|
break; |
|
|
|
pthread_mutex_unlock (&es->mutex); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
es->triggered = false; |
|
|
|
|
|
|
|
pthread_mutex_unlock (&es->mutex); |
|
|
|
return ok; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
void WaitableEvent::signal() const throw() |
|
|
|
@@ -261790,10 +261787,9 @@ END_JUCE_NAMESPACE |
|
|
|
- (void) applicationDidFinishLaunching: (UIApplication*) application |
|
|
|
{ |
|
|
|
String dummy; |
|
|
|
|
|
|
|
if (! juce_intialisingApp->initialiseApp (dummy)) |
|
|
|
{ |
|
|
|
// (should quit) |
|
|
|
} |
|
|
|
exit (0); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) applicationWillResignActive: (UIApplication*) application |
|
|
|
@@ -263076,7 +263072,7 @@ public: |
|
|
|
|
|
|
|
void drawHorizontalLine (const int y, double left, double right) |
|
|
|
{ |
|
|
|
CGContextFillRect (context, CGRectMake (left, y, right - left, 1.0f)); |
|
|
|
CGContextFillRect (context, CGRectMake (left, flipHeight - (y + 1.0f), right - left, 1.0f)); |
|
|
|
} |
|
|
|
|
|
|
|
void setFont (const Font& newFont) |
|
|
|
@@ -263470,7 +263466,7 @@ public: |
|
|
|
|
|
|
|
UIWindow* window; |
|
|
|
JuceUIView* view; |
|
|
|
bool isSharedWindow, fullScreen; |
|
|
|
bool isSharedWindow, fullScreen, insideDrawRect; |
|
|
|
}; |
|
|
|
|
|
|
|
END_JUCE_NAMESPACE |
|
|
|
@@ -263673,7 +263669,8 @@ UIViewComponentPeer::UIViewComponentPeer (Component* const component, |
|
|
|
window (0), |
|
|
|
view (0), |
|
|
|
isSharedWindow (viewToAttachTo != 0), |
|
|
|
fullScreen (false) |
|
|
|
fullScreen (false), |
|
|
|
insideDrawRect (false) |
|
|
|
{ |
|
|
|
CGRect r; |
|
|
|
r.origin.x = 0; |
|
|
|
@@ -264058,7 +264055,10 @@ void UIViewComponentPeer::drawRect (CGRect r) |
|
|
|
|
|
|
|
CGContextConcatCTM (cg, CGAffineTransformMake (1, 0, 0, -1, 0, view.bounds.size.height)); |
|
|
|
CoreGraphicsContext g (cg, view.bounds.size.height); |
|
|
|
|
|
|
|
insideDrawRect = true; |
|
|
|
handlePaint (g); |
|
|
|
insideDrawRect = false; |
|
|
|
} |
|
|
|
|
|
|
|
bool UIViewComponentPeer::canBecomeKeyWindow() |
|
|
|
@@ -264084,19 +264084,33 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
void UIViewComponentPeer::repaint (int x, int y, int w, int h) |
|
|
|
class AsyncRepaintMessage : public CallbackMessage |
|
|
|
{ |
|
|
|
CGRect r = CGRectMake ((float) x, (float) y, (float) w, (float) h); |
|
|
|
public: |
|
|
|
UIViewComponentPeer* const peer; |
|
|
|
const Rectangle rect; |
|
|
|
|
|
|
|
if (! MessageManager::getInstance()->isThisTheMessageThread()) |
|
|
|
AsyncRepaintMessage (UIViewComponentPeer* const peer_, const Rectangle& rect_) |
|
|
|
: peer (peer_), rect (rect_) |
|
|
|
{ |
|
|
|
[view performSelectorOnMainThread: @selector (asyncRepaint:) |
|
|
|
withObject: [NSData dataWithBytes: &r length: sizeof (r)] |
|
|
|
waitUntilDone: NO]; |
|
|
|
} |
|
|
|
|
|
|
|
void messageCallback() |
|
|
|
{ |
|
|
|
if (ComponentPeer::isValidPeer (peer)) |
|
|
|
peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
void UIViewComponentPeer::repaint (int x, int y, int w, int h) |
|
|
|
{ |
|
|
|
if (insideDrawRect || ! MessageManager::getInstance()->isThisTheMessageThread()) |
|
|
|
{ |
|
|
|
(new AsyncRepaintMessage (this, Rectangle (x, y, w, h)))->post(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
[view setNeedsDisplayInRect: r]; |
|
|
|
[view setNeedsDisplayInRect: CGRectMake ((float) x, (float) y, (float) w, (float) h)]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -264199,83 +264213,11 @@ struct CallbackMessagePayload |
|
|
|
bool volatile hasBeenExecuted; |
|
|
|
}; |
|
|
|
|
|
|
|
/* When you use multiple DLLs which share similarly-named obj-c classes - like |
|
|
|
for example having more than one juce plugin loaded into a host, then when a |
|
|
|
method is called, the actual code that runs might actually be in a different module |
|
|
|
than the one you expect... So any calls to library functions or statics that are |
|
|
|
made inside obj-c methods will probably end up getting executed in a different DLL's |
|
|
|
memory space. Not a great thing to happen - this obviously leads to bizarre crashes. |
|
|
|
|
|
|
|
To work around this insanity, I'm only allowing obj-c methods to make calls to |
|
|
|
virtual methods of an object that's known to live inside the right module's space. |
|
|
|
*/ |
|
|
|
class AppDelegateRedirector |
|
|
|
{ |
|
|
|
public: |
|
|
|
AppDelegateRedirector() {} |
|
|
|
virtual ~AppDelegateRedirector() {} |
|
|
|
|
|
|
|
virtual BOOL openFile (const NSString* filename) |
|
|
|
{ |
|
|
|
if (JUCEApplication::getInstance() != 0) |
|
|
|
{ |
|
|
|
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename)); |
|
|
|
return YES; |
|
|
|
} |
|
|
|
|
|
|
|
return NO; |
|
|
|
} |
|
|
|
|
|
|
|
virtual void openFiles (NSArray* filenames) |
|
|
|
{ |
|
|
|
StringArray files; |
|
|
|
for (unsigned int i = 0; i < [filenames count]; ++i) |
|
|
|
files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); |
|
|
|
|
|
|
|
if (files.size() > 0 && JUCEApplication::getInstance() != 0) |
|
|
|
{ |
|
|
|
JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" "))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
virtual void focusChanged() |
|
|
|
{ |
|
|
|
juce_HandleProcessFocusChange(); |
|
|
|
} |
|
|
|
|
|
|
|
virtual void deliverMessage (void* message) |
|
|
|
{ |
|
|
|
// no need for an mm lock here - deliverMessage locks it |
|
|
|
MessageManager::getInstance()->deliverMessage (message); |
|
|
|
} |
|
|
|
|
|
|
|
virtual void performCallback (CallbackMessagePayload* pl) |
|
|
|
{ |
|
|
|
pl->result = (*pl->function) (pl->parameter); |
|
|
|
pl->hasBeenExecuted = true; |
|
|
|
} |
|
|
|
|
|
|
|
virtual void deleteSelf() |
|
|
|
{ |
|
|
|
delete this; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
END_JUCE_NAMESPACE |
|
|
|
using namespace JUCE_NAMESPACE; |
|
|
|
|
|
|
|
#define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) |
|
|
|
|
|
|
|
static int numPendingMessages = 0; |
|
|
|
|
|
|
|
@interface JuceAppDelegate : NSObject <UIApplicationDelegate> |
|
|
|
{ |
|
|
|
@private |
|
|
|
id oldDelegate; |
|
|
|
AppDelegateRedirector* redirector; |
|
|
|
|
|
|
|
@public |
|
|
|
bool flushingMessages; |
|
|
|
} |
|
|
|
|
|
|
|
- (JuceAppDelegate*) init; |
|
|
|
@@ -264286,7 +264228,6 @@ static int numPendingMessages = 0; |
|
|
|
- (void) applicationWillUnhide: (NSNotification*) aNotification; |
|
|
|
- (void) customEvent: (id) data; |
|
|
|
- (void) performCallback: (id) info; |
|
|
|
- (void) dummyMethod; |
|
|
|
@end |
|
|
|
|
|
|
|
@implementation JuceAppDelegate |
|
|
|
@@ -264295,11 +264236,6 @@ static int numPendingMessages = 0; |
|
|
|
{ |
|
|
|
[super init]; |
|
|
|
|
|
|
|
redirector = new AppDelegateRedirector(); |
|
|
|
numPendingMessages = 0; |
|
|
|
flushingMessages = false; |
|
|
|
|
|
|
|
oldDelegate = [[UIApplication sharedApplication] delegate]; |
|
|
|
[[UIApplication sharedApplication] setDelegate: self]; |
|
|
|
|
|
|
|
return self; |
|
|
|
@@ -264307,44 +264243,45 @@ static int numPendingMessages = 0; |
|
|
|
|
|
|
|
- (void) dealloc |
|
|
|
{ |
|
|
|
if (oldDelegate != 0) |
|
|
|
[[UIApplication sharedApplication] setDelegate: oldDelegate]; |
|
|
|
|
|
|
|
redirector->deleteSelf(); |
|
|
|
[[UIApplication sharedApplication] setDelegate: nil]; |
|
|
|
[super dealloc]; |
|
|
|
} |
|
|
|
|
|
|
|
- (BOOL) application: (UIApplication*) application handleOpenURL: (NSURL*) url |
|
|
|
{ |
|
|
|
return redirector->openFile ([url absoluteString]); |
|
|
|
if (JUCEApplication::getInstance() != 0) |
|
|
|
{ |
|
|
|
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce ([url absoluteString])); |
|
|
|
return YES; |
|
|
|
} |
|
|
|
|
|
|
|
return NO; |
|
|
|
} |
|
|
|
|
|
|
|
- (void) applicationDidBecomeActive: (NSNotification*) aNotification |
|
|
|
{ |
|
|
|
redirector->focusChanged(); |
|
|
|
juce_HandleProcessFocusChange(); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) applicationDidResignActive: (NSNotification*) aNotification |
|
|
|
{ |
|
|
|
redirector->focusChanged(); |
|
|
|
juce_HandleProcessFocusChange(); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) applicationWillUnhide: (NSNotification*) aNotification |
|
|
|
{ |
|
|
|
redirector->focusChanged(); |
|
|
|
juce_HandleProcessFocusChange(); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) customEvent: (id) n |
|
|
|
{ |
|
|
|
atomicDecrement (numPendingMessages); |
|
|
|
|
|
|
|
NSData* data = (NSData*) n; |
|
|
|
void* message = 0; |
|
|
|
[data getBytes: &message length: sizeof (message)]; |
|
|
|
[data release]; |
|
|
|
|
|
|
|
if (message != 0 && ! flushingMessages) |
|
|
|
redirector->deliverMessage (message); |
|
|
|
if (message != 0) |
|
|
|
MessageManager::getInstance()->deliverMessage (message); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) performCallback: (id) info |
|
|
|
@@ -264354,7 +264291,10 @@ static int numPendingMessages = 0; |
|
|
|
CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; |
|
|
|
|
|
|
|
if (pl != 0) |
|
|
|
redirector->performCallback (pl); |
|
|
|
{ |
|
|
|
pl->result = (*pl->function) (pl->parameter); |
|
|
|
pl->hasBeenExecuted = true; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@@ -264362,8 +264302,6 @@ static int numPendingMessages = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
- (void) dummyMethod {} // (used as a way of running a dummy thread) |
|
|
|
|
|
|
|
@end |
|
|
|
|
|
|
|
BEGIN_JUCE_NAMESPACE |
|
|
|
@@ -264373,7 +264311,6 @@ static JuceAppDelegate* juceAppDelegate = 0; |
|
|
|
void MessageManager::runDispatchLoop() |
|
|
|
{ |
|
|
|
jassert (isThisTheMessageThread()); // must only be called by the message thread |
|
|
|
|
|
|
|
runDispatchLoopUntil (-1); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -264406,30 +264343,61 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) |
|
|
|
return ! quitMessagePosted; |
|
|
|
} |
|
|
|
|
|
|
|
static CFRunLoopTimerRef messageTimer = 0; |
|
|
|
static Array <void*, CriticalSection>* pendingMessages = 0; |
|
|
|
|
|
|
|
static void timerCallback (CFRunLoopTimerRef, void*) |
|
|
|
{ |
|
|
|
if (pendingMessages != 0) |
|
|
|
{ |
|
|
|
const int numToDispatch = jmin (4, pendingMessages->size()); |
|
|
|
|
|
|
|
for (int i = 0; i < numToDispatch; ++i) |
|
|
|
{ |
|
|
|
void* const nextMessage = (*pendingMessages)[i]; |
|
|
|
|
|
|
|
if (nextMessage != 0) |
|
|
|
MessageManager::getInstance()->deliverMessage (nextMessage); |
|
|
|
} |
|
|
|
|
|
|
|
pendingMessages->removeRange (0, numToDispatch); |
|
|
|
|
|
|
|
if (pendingMessages->size() > 0) |
|
|
|
CFRunLoopTimerSetNextFireDate (messageTimer, CFAbsoluteTimeGetCurrent() - 0.5); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void MessageManager::doPlatformSpecificInitialisation() |
|
|
|
{ |
|
|
|
pendingMessages = new Array <void*, CriticalSection>(); |
|
|
|
|
|
|
|
messageTimer = CFRunLoopTimerCreate (kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 60.0, 60.0, |
|
|
|
0, 0, timerCallback, 0); |
|
|
|
|
|
|
|
CFRunLoopAddTimer (CFRunLoopGetMain(), messageTimer, kCFRunLoopCommonModes); |
|
|
|
|
|
|
|
if (juceAppDelegate == 0) |
|
|
|
juceAppDelegate = [[JuceAppDelegate alloc] init]; |
|
|
|
} |
|
|
|
|
|
|
|
void MessageManager::doPlatformSpecificShutdown() |
|
|
|
{ |
|
|
|
if (juceAppDelegate != 0) |
|
|
|
{ |
|
|
|
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; |
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver: juceAppDelegate]; |
|
|
|
CFRunLoopTimerInvalidate (messageTimer); |
|
|
|
CFRunLoopRemoveTimer (CFRunLoopGetMain(), messageTimer, kCFRunLoopCommonModes); |
|
|
|
CFRelease (messageTimer); |
|
|
|
messageTimer = 0; |
|
|
|
|
|
|
|
// Annoyingly, cancelPerformSelectorsWithTarget can't actually cancel the messages |
|
|
|
// sent by performSelectorOnMainThread, so need to manually flush these before quitting.. |
|
|
|
juceAppDelegate->flushingMessages = true; |
|
|
|
if (pendingMessages != 0) |
|
|
|
{ |
|
|
|
while (pendingMessages->size() > 0) |
|
|
|
delete ((Message*) pendingMessages->remove(0)); |
|
|
|
|
|
|
|
for (int i = 100; --i >= 0 && numPendingMessages > 0;) |
|
|
|
{ |
|
|
|
const ScopedAutoReleasePool pool; |
|
|
|
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode |
|
|
|
beforeDate: [NSDate dateWithTimeIntervalSinceNow: 5 * 0.001]]; |
|
|
|
} |
|
|
|
deleteAndZero (pendingMessages); |
|
|
|
} |
|
|
|
|
|
|
|
if (juceAppDelegate != 0) |
|
|
|
{ |
|
|
|
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; |
|
|
|
[juceAppDelegate release]; |
|
|
|
juceAppDelegate = 0; |
|
|
|
} |
|
|
|
@@ -264437,11 +264405,12 @@ void MessageManager::doPlatformSpecificShutdown() |
|
|
|
|
|
|
|
bool juce_postMessageToSystemQueue (void* message) |
|
|
|
{ |
|
|
|
atomicIncrement (numPendingMessages); |
|
|
|
if (pendingMessages != 0) |
|
|
|
{ |
|
|
|
pendingMessages->add (message); |
|
|
|
CFRunLoopTimerSetNextFireDate (messageTimer, CFAbsoluteTimeGetCurrent() - 1.0); |
|
|
|
} |
|
|
|
|
|
|
|
[juceAppDelegate performSelectorOnMainThread: @selector (customEvent:) |
|
|
|
withObject: (id) [[NSData alloc] initWithBytes: &message length: (int) sizeof (message)] |
|
|
|
waitUntilDone: NO]; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -265795,7 +265764,7 @@ private: |
|
|
|
|
|
|
|
void interruptionListener (UInt32 inInterruption) |
|
|
|
{ |
|
|
|
if (inInterruption == kAudioSessionBeginInterruption) |
|
|
|
/*if (inInterruption == kAudioSessionBeginInterruption) |
|
|
|
{ |
|
|
|
isRunning = false; |
|
|
|
AudioOutputUnitStop (audioUnit); |
|
|
|
@@ -265808,7 +265777,7 @@ private: |
|
|
|
isRunning = true; |
|
|
|
propertyChanged (0, 0, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
if (inInterruption == kAudioSessionEndInterruption) |
|
|
|
{ |
|
|
|
@@ -267529,7 +267498,7 @@ public: |
|
|
|
|
|
|
|
void drawHorizontalLine (const int y, double left, double right) |
|
|
|
{ |
|
|
|
CGContextFillRect (context, CGRectMake (left, y, right - left, 1.0f)); |
|
|
|
CGContextFillRect (context, CGRectMake (left, flipHeight - (y + 1.0f), right - left, 1.0f)); |
|
|
|
} |
|
|
|
|
|
|
|
void setFont (const Font& newFont) |
|
|
|
@@ -269305,20 +269274,34 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void NSViewComponentPeer::repaint (int x, int y, int w, int h) |
|
|
|
class AsyncRepaintMessage : public CallbackMessage |
|
|
|
{ |
|
|
|
NSRect r = NSMakeRect ((float) x, (float) ([view frame].size.height - (y + h)), |
|
|
|
(float) w, (float) h); |
|
|
|
public: |
|
|
|
NSViewComponentPeer* const peer; |
|
|
|
const Rectangle rect; |
|
|
|
|
|
|
|
AsyncRepaintMessage (NSViewComponentPeer* const peer_, const Rectangle& rect_) |
|
|
|
: peer (peer_), rect (rect_) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
void messageCallback() |
|
|
|
{ |
|
|
|
if (ComponentPeer::isValidPeer (peer)) |
|
|
|
peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
void NSViewComponentPeer::repaint (int x, int y, int w, int h) |
|
|
|
{ |
|
|
|
if (insideDrawRect) |
|
|
|
{ |
|
|
|
[view performSelectorOnMainThread: @selector (asyncRepaint:) |
|
|
|
withObject: [NSData dataWithBytes: &r length: sizeof (r)] |
|
|
|
waitUntilDone: NO]; |
|
|
|
(new AsyncRepaintMessage (this, Rectangle (x, y, w, h)))->post(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
[view setNeedsDisplayInRect: r]; |
|
|
|
[view setNeedsDisplayInRect: NSMakeRect ((float) x, (float) ([view frame].size.height - (y + h)), |
|
|
|
(float) w, (float) h)]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -271625,8 +271608,36 @@ struct CallbackMessagePayload |
|
|
|
class AppDelegateRedirector |
|
|
|
{ |
|
|
|
public: |
|
|
|
AppDelegateRedirector() {} |
|
|
|
virtual ~AppDelegateRedirector() {} |
|
|
|
AppDelegateRedirector() |
|
|
|
{ |
|
|
|
CFRunLoopTimerContext context; |
|
|
|
zerostruct (context); |
|
|
|
context.info = this; |
|
|
|
|
|
|
|
timer = CFRunLoopTimerCreate (kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 60.0, 60.0, 0, 0, |
|
|
|
AppDelegateRedirector::timerCallbackStatic, &context); |
|
|
|
|
|
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 |
|
|
|
CFRunLoopAddTimer (CFRunLoopGetMain(), timer, kCFRunLoopCommonModes); |
|
|
|
#else |
|
|
|
CFRunLoopAddTimer (CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
virtual ~AppDelegateRedirector() |
|
|
|
{ |
|
|
|
CFRunLoopTimerInvalidate (timer); |
|
|
|
|
|
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 |
|
|
|
CFRunLoopRemoveTimer (CFRunLoopGetMain(), timer, kCFRunLoopCommonModes); |
|
|
|
#else |
|
|
|
CFRunLoopRemoveTimer (CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); |
|
|
|
#endif |
|
|
|
CFRelease (timer); |
|
|
|
|
|
|
|
while (messages.size() > 0) |
|
|
|
delete ((Message*) messages.remove(0)); |
|
|
|
} |
|
|
|
|
|
|
|
virtual NSApplicationTerminateReply shouldTerminate() |
|
|
|
{ |
|
|
|
@@ -271667,12 +271678,6 @@ public: |
|
|
|
juce_HandleProcessFocusChange(); |
|
|
|
} |
|
|
|
|
|
|
|
virtual void deliverMessage (void* message) |
|
|
|
{ |
|
|
|
// no need for an mm lock here - deliverMessage locks it |
|
|
|
MessageManager::getInstance()->deliverMessage (message); |
|
|
|
} |
|
|
|
|
|
|
|
virtual void performCallback (CallbackMessagePayload* pl) |
|
|
|
{ |
|
|
|
pl->result = (*pl->function) (pl->parameter); |
|
|
|
@@ -271683,6 +271688,39 @@ public: |
|
|
|
{ |
|
|
|
delete this; |
|
|
|
} |
|
|
|
|
|
|
|
void postMessage (void* m) throw() |
|
|
|
{ |
|
|
|
messages.add (m); |
|
|
|
CFRunLoopTimerSetNextFireDate (timer, CFAbsoluteTimeGetCurrent() - 0.5); |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
CFRunLoopTimerRef timer; |
|
|
|
Array <void*, CriticalSection> messages; |
|
|
|
|
|
|
|
void timerCallback() throw() |
|
|
|
{ |
|
|
|
const int numToDispatch = jmin (4, messages.size()); |
|
|
|
|
|
|
|
for (int i = 0; i < numToDispatch; ++i) |
|
|
|
{ |
|
|
|
void* const nextMessage = messages[i]; |
|
|
|
|
|
|
|
if (nextMessage != 0) |
|
|
|
MessageManager::getInstance()->deliverMessage (nextMessage); |
|
|
|
} |
|
|
|
|
|
|
|
messages.removeRange (0, numToDispatch); |
|
|
|
|
|
|
|
if (messages.size() > 0) |
|
|
|
CFRunLoopTimerSetNextFireDate (timer, CFAbsoluteTimeGetCurrent() - 0.5); |
|
|
|
} |
|
|
|
|
|
|
|
static void timerCallbackStatic (CFRunLoopTimerRef, void* info) |
|
|
|
{ |
|
|
|
((AppDelegateRedirector*) info)->timerCallback(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
END_JUCE_NAMESPACE |
|
|
|
@@ -271690,17 +271728,13 @@ using namespace JUCE_NAMESPACE; |
|
|
|
|
|
|
|
#define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) |
|
|
|
|
|
|
|
static int numPendingMessages = 0; |
|
|
|
|
|
|
|
@interface JuceAppDelegate : NSObject |
|
|
|
{ |
|
|
|
@private |
|
|
|
id oldDelegate; |
|
|
|
AppDelegateRedirector* redirector; |
|
|
|
NSTimer* messageTimer; |
|
|
|
|
|
|
|
@public |
|
|
|
bool flushingMessages; |
|
|
|
AppDelegateRedirector* redirector; |
|
|
|
} |
|
|
|
|
|
|
|
- (JuceAppDelegate*) init; |
|
|
|
@@ -271711,7 +271745,6 @@ static int numPendingMessages = 0; |
|
|
|
- (void) applicationDidBecomeActive: (NSNotification*) aNotification; |
|
|
|
- (void) applicationDidResignActive: (NSNotification*) aNotification; |
|
|
|
- (void) applicationWillUnhide: (NSNotification*) aNotification; |
|
|
|
- (void) customEvent: (id) data; |
|
|
|
- (void) performCallback: (id) info; |
|
|
|
- (void) dummyMethod; |
|
|
|
@end |
|
|
|
@@ -271723,8 +271756,6 @@ static int numPendingMessages = 0; |
|
|
|
[super init]; |
|
|
|
|
|
|
|
redirector = new AppDelegateRedirector(); |
|
|
|
numPendingMessages = 0; |
|
|
|
flushingMessages = false; |
|
|
|
|
|
|
|
NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; |
|
|
|
|
|
|
|
@@ -271788,19 +271819,6 @@ static int numPendingMessages = 0; |
|
|
|
redirector->focusChanged(); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) customEvent: (id) n |
|
|
|
{ |
|
|
|
atomicDecrement (numPendingMessages); |
|
|
|
|
|
|
|
NSData* data = (NSData*) n; |
|
|
|
void* message = 0; |
|
|
|
[data getBytes: &message length: sizeof (message)]; |
|
|
|
[data release]; |
|
|
|
|
|
|
|
if (message != 0 && ! flushingMessages) |
|
|
|
redirector->deliverMessage (message); |
|
|
|
} |
|
|
|
|
|
|
|
- (void) performCallback: (id) info |
|
|
|
{ |
|
|
|
if ([info isKindOfClass: [NSData class]]) |
|
|
|
@@ -271977,18 +271995,6 @@ void MessageManager::doPlatformSpecificShutdown() |
|
|
|
{ |
|
|
|
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; |
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver: juceAppDelegate]; |
|
|
|
|
|
|
|
// Annoyingly, cancelPerformSelectorsWithTarget can't actually cancel the messages |
|
|
|
// sent by performSelectorOnMainThread, so need to manually flush these before quitting.. |
|
|
|
juceAppDelegate->flushingMessages = true; |
|
|
|
|
|
|
|
for (int i = 100; --i >= 0 && numPendingMessages > 0;) |
|
|
|
{ |
|
|
|
const ScopedAutoReleasePool pool; |
|
|
|
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode |
|
|
|
beforeDate: [NSDate dateWithTimeIntervalSinceNow: 5 * 0.001]]; |
|
|
|
} |
|
|
|
|
|
|
|
[juceAppDelegate release]; |
|
|
|
juceAppDelegate = 0; |
|
|
|
} |
|
|
|
@@ -271996,11 +272002,7 @@ void MessageManager::doPlatformSpecificShutdown() |
|
|
|
|
|
|
|
bool juce_postMessageToSystemQueue (void* message) |
|
|
|
{ |
|
|
|
atomicIncrement (numPendingMessages); |
|
|
|
|
|
|
|
[juceAppDelegate performSelectorOnMainThread: @selector (customEvent:) |
|
|
|
withObject: (id) [[NSData alloc] initWithBytes: &message length: (int) sizeof (message)] |
|
|
|
waitUntilDone: NO]; |
|
|
|
juceAppDelegate->redirector->postMessage (message); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|