| @@ -120,13 +120,13 @@ using namespace JUCE_NAMESPACE; | |||||
| #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | ||||
| static int numPendingMessages = 0; | static int numPendingMessages = 0; | ||||
| static bool flushingMessages = false; | |||||
| @interface JuceAppDelegate : NSObject | @interface JuceAppDelegate : NSObject | ||||
| { | { | ||||
| @private | @private | ||||
| id oldDelegate; | id oldDelegate; | ||||
| AppDelegateRedirector* redirector; | AppDelegateRedirector* redirector; | ||||
| bool flushingMessages; | |||||
| } | } | ||||
| - (JuceAppDelegate*) init; | - (JuceAppDelegate*) init; | ||||
| @@ -218,6 +218,7 @@ static bool flushingMessages = false; | |||||
| - (void) customEvent: (id) n | - (void) customEvent: (id) n | ||||
| { | { | ||||
| atomicDecrement (numPendingMessages); | atomicDecrement (numPendingMessages); | ||||
| [self release]; | |||||
| NSData* data = (NSData*) n; | NSData* data = (NSData*) n; | ||||
| void* message = 0; | void* message = 0; | ||||
| @@ -398,23 +399,27 @@ void MessageManager::doPlatformSpecificInitialisation() | |||||
| void MessageManager::doPlatformSpecificShutdown() | 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.. | |||||
| flushingMessages = true; | |||||
| if (JUCEApplication::getInstance() != 0) // (must avoid blocking here when running as a plugin) | |||||
| for (int i = 100; --i >= 0 && numPendingMessages > 0;) | |||||
| getInstance()->runDispatchLoopUntil (10); | |||||
| [juceAppDelegate release]; | |||||
| juceAppDelegate = 0; | |||||
| if (juceAppDelegate != 0) | |||||
| { | |||||
| [[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; | |||||
| if (JUCEApplication::getInstance() != 0) // (must avoid blocking here when running as a plugin) | |||||
| for (int i = 100; --i >= 0 && numPendingMessages > 0;) | |||||
| getInstance()->runDispatchLoopUntil (10); | |||||
| [juceAppDelegate release]; | |||||
| juceAppDelegate = 0; | |||||
| } | |||||
| } | } | ||||
| bool juce_postMessageToSystemQueue (void* message) | bool juce_postMessageToSystemQueue (void* message) | ||||
| { | { | ||||
| atomicIncrement (numPendingMessages); | atomicIncrement (numPendingMessages); | ||||
| [juceAppDelegate retain]; | |||||
| [juceAppDelegate performSelectorOnMainThread: @selector (customEvent:) | [juceAppDelegate performSelectorOnMainThread: @selector (customEvent:) | ||||
| withObject: (id) [[NSData alloc] initWithBytes: &message | withObject: (id) [[NSData alloc] initWithBytes: &message | ||||
| @@ -1193,6 +1193,7 @@ private: | |||||
| #if ! JucePlugin_EditorRequiresKeyboardFocus | #if ! JucePlugin_EditorRequiresKeyboardFocus | ||||
| addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses); | addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses); | ||||
| setWantsKeyboardFocus (false); | setWantsKeyboardFocus (false); | ||||
| setComponentProperty ("juce_disallowFocus", true); | |||||
| #else | #else | ||||
| addToDesktop (ComponentPeer::windowIsTemporary); | addToDesktop (ComponentPeer::windowIsTemporary); | ||||
| setWantsKeyboardFocus (true); | setWantsKeyboardFocus (true); | ||||
| @@ -118,7 +118,7 @@ NPError NP_GetValue (void* future, NPPVariable variable, void* value) | |||||
| NPError OSCALL NP_GetEntryPoints (NPPluginFuncs* funcs) | NPError OSCALL NP_GetEntryPoints (NPPluginFuncs* funcs) | ||||
| { | { | ||||
| #if JUCE_WIN32 | #if JUCE_WIN32 | ||||
| #pragma EXPORTED_FUNCTION | |||||
| #pragma EXPORTED_FUNCTION | |||||
| #endif | #endif | ||||
| log ("NP_GetEntryPoints"); | log ("NP_GetEntryPoints"); | ||||
| @@ -157,7 +157,7 @@ NPError OSCALL NP_Initialize (NPNetscapeFuncs* funcs | |||||
| ) | ) | ||||
| { | { | ||||
| #if JUCE_WIN32 | #if JUCE_WIN32 | ||||
| #pragma EXPORTED_FUNCTION | |||||
| #pragma EXPORTED_FUNCTION | |||||
| #endif | #endif | ||||
| log ("NP_Initialize"); | log ("NP_Initialize"); | ||||
| @@ -167,51 +167,8 @@ NPError OSCALL NP_Initialize (NPNetscapeFuncs* funcs | |||||
| if (((funcs->version >> 8) & 0xff) > NP_VERSION_MAJOR) | if (((funcs->version >> 8) & 0xff) > NP_VERSION_MAJOR) | ||||
| return NPERR_INCOMPATIBLE_VERSION_ERROR; | return NPERR_INCOMPATIBLE_VERSION_ERROR; | ||||
| if (funcs->size < sizeof (NPNetscapeFuncs)) | |||||
| return NPERR_INVALID_FUNCTABLE_ERROR; | |||||
| browser.size = funcs->size; | |||||
| browser.version = funcs->version; | |||||
| browser.geturlnotify = funcs->geturlnotify; | |||||
| browser.geturl = funcs->geturl; | |||||
| browser.posturlnotify = funcs->posturlnotify; | |||||
| browser.posturl = funcs->posturl; | |||||
| browser.requestread = funcs->requestread; | |||||
| browser.newstream = funcs->newstream; | |||||
| browser.write = funcs->write; | |||||
| browser.destroystream = funcs->destroystream; | |||||
| browser.status = funcs->status; | |||||
| browser.uagent = funcs->uagent; | |||||
| browser.memalloc = funcs->memalloc; | |||||
| browser.memfree = funcs->memfree; | |||||
| browser.memflush = funcs->memflush; | |||||
| browser.reloadplugins = funcs->reloadplugins; | |||||
| browser.getJavaEnv = funcs->getJavaEnv; | |||||
| browser.getJavaPeer = funcs->getJavaPeer; | |||||
| browser.getvalue = funcs->getvalue; | |||||
| browser.setvalue = funcs->setvalue; | |||||
| browser.invalidaterect = funcs->invalidaterect; | |||||
| browser.invalidateregion = funcs->invalidateregion; | |||||
| browser.forceredraw = funcs->forceredraw; | |||||
| browser.getstringidentifier = funcs->getstringidentifier; | |||||
| browser.getstringidentifiers = funcs->getstringidentifiers; | |||||
| browser.getintidentifier = funcs->getintidentifier; | |||||
| browser.identifierisstring = funcs->identifierisstring; | |||||
| browser.utf8fromidentifier = funcs->utf8fromidentifier; | |||||
| browser.intfromidentifier = funcs->intfromidentifier; | |||||
| browser.createobject = funcs->createobject; | |||||
| browser.retainobject = funcs->retainobject; | |||||
| browser.releaseobject = funcs->releaseobject; | |||||
| browser.invoke = funcs->invoke; | |||||
| browser.invokeDefault = funcs->invokeDefault; | |||||
| browser.evaluate = funcs->evaluate; | |||||
| browser.getproperty = funcs->getproperty; | |||||
| browser.setproperty = funcs->setproperty; | |||||
| browser.removeproperty = funcs->removeproperty; | |||||
| browser.hasproperty = funcs->hasproperty; | |||||
| browser.hasmethod = funcs->hasmethod; | |||||
| browser.releasevariantvalue = funcs->releasevariantvalue; | |||||
| browser.setexception = funcs->setexception; | |||||
| zerostruct (browser); | |||||
| memcpy (&browser, funcs, jmin (funcs->size, sizeof (browser))); | |||||
| #ifdef XP_UNIX | #ifdef XP_UNIX | ||||
| pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; | pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; | ||||
| @@ -239,7 +196,7 @@ NPError OSCALL NP_Initialize (NPNetscapeFuncs* funcs | |||||
| NPError OSCALL NP_Shutdown() | NPError OSCALL NP_Shutdown() | ||||
| { | { | ||||
| #if JUCE_WIN32 | #if JUCE_WIN32 | ||||
| #pragma EXPORTED_FUNCTION | |||||
| #pragma EXPORTED_FUNCTION | |||||
| #endif | #endif | ||||
| log ("NP_Shutdown"); | log ("NP_Shutdown"); | ||||
| @@ -866,11 +823,14 @@ static void createNPVariantFromValue (NPP npp, NPVariant& out, const var& v) | |||||
| else if (v.isDouble()) | else if (v.isDouble()) | ||||
| DOUBLE_TO_NPVARIANT ((double) v, out); | DOUBLE_TO_NPVARIANT ((double) v, out); | ||||
| else if (v.isString()) | else if (v.isString()) | ||||
| #if JUCE_MAC | |||||
| STRINGZ_TO_NPVARIANT (strdup (v.toString().toUTF8()), out); | |||||
| #else | |||||
| STRINGZ_TO_NPVARIANT (_strdup (v.toString().toUTF8()), out); | |||||
| #endif | |||||
| { | |||||
| const String s (v.toString()); | |||||
| const char* const utf8 = s.toUTF8(); | |||||
| const int utf8Len = strlen (utf8) + 1; | |||||
| char* const stringCopy = (char*) browser.memalloc (utf8Len); | |||||
| memcpy (stringCopy, utf8, utf8Len); | |||||
| STRINGZ_TO_NPVARIANT (stringCopy, out); | |||||
| } | |||||
| else if (v.isObject()) | else if (v.isObject()) | ||||
| OBJECT_TO_NPVARIANT (NPObjectWrappingDynamicObject::create (npp, v), out); | OBJECT_TO_NPVARIANT (NPObjectWrappingDynamicObject::create (npp, v), out); | ||||
| else | else | ||||
| @@ -272262,13 +272262,13 @@ using namespace JUCE_NAMESPACE; | |||||
| #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | ||||
| static int numPendingMessages = 0; | static int numPendingMessages = 0; | ||||
| static bool flushingMessages = false; | |||||
| @interface JuceAppDelegate : NSObject | @interface JuceAppDelegate : NSObject | ||||
| { | { | ||||
| @private | @private | ||||
| id oldDelegate; | id oldDelegate; | ||||
| AppDelegateRedirector* redirector; | AppDelegateRedirector* redirector; | ||||
| bool flushingMessages; | |||||
| } | } | ||||
| - (JuceAppDelegate*) init; | - (JuceAppDelegate*) init; | ||||
| @@ -272360,6 +272360,7 @@ static bool flushingMessages = false; | |||||
| - (void) customEvent: (id) n | - (void) customEvent: (id) n | ||||
| { | { | ||||
| atomicDecrement (numPendingMessages); | atomicDecrement (numPendingMessages); | ||||
| [self release]; | |||||
| NSData* data = (NSData*) n; | NSData* data = (NSData*) n; | ||||
| void* message = 0; | void* message = 0; | ||||
| @@ -272539,23 +272540,27 @@ void MessageManager::doPlatformSpecificInitialisation() | |||||
| void MessageManager::doPlatformSpecificShutdown() | void MessageManager::doPlatformSpecificShutdown() | ||||
| { | { | ||||
| [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; | |||||
| [[NSNotificationCenter defaultCenter] removeObserver: juceAppDelegate]; | |||||
| if (juceAppDelegate != 0) | |||||
| { | |||||
| [[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.. | |||||
| flushingMessages = true; | |||||
| if (JUCEApplication::getInstance() != 0) // (must avoid blocking here when running as a plugin) | |||||
| for (int i = 100; --i >= 0 && numPendingMessages > 0;) | |||||
| getInstance()->runDispatchLoopUntil (10); | |||||
| // Annoyingly, cancelPerformSelectorsWithTarget can't actually cancel the messages | |||||
| // sent by performSelectorOnMainThread, so need to manually flush these before quitting.. | |||||
| juceAppDelegate->flushingMessages = true; | |||||
| if (JUCEApplication::getInstance() != 0) // (must avoid blocking here when running as a plugin) | |||||
| for (int i = 100; --i >= 0 && numPendingMessages > 0;) | |||||
| getInstance()->runDispatchLoopUntil (10); | |||||
| [juceAppDelegate release]; | |||||
| juceAppDelegate = 0; | |||||
| [juceAppDelegate release]; | |||||
| juceAppDelegate = 0; | |||||
| } | |||||
| } | } | ||||
| bool juce_postMessageToSystemQueue (void* message) | bool juce_postMessageToSystemQueue (void* message) | ||||
| { | { | ||||
| atomicIncrement (numPendingMessages); | atomicIncrement (numPendingMessages); | ||||
| [juceAppDelegate retain]; | |||||
| [juceAppDelegate performSelectorOnMainThread: @selector (customEvent:) | [juceAppDelegate performSelectorOnMainThread: @selector (customEvent:) | ||||
| withObject: (id) [[NSData alloc] initWithBytes: &message | withObject: (id) [[NSData alloc] initWithBytes: &message | ||||
| @@ -34533,7 +34533,18 @@ public: | |||||
| /** Returns the currently-active audio device. */ | /** Returns the currently-active audio device. */ | ||||
| AudioIODevice* getCurrentAudioDevice() const throw() { return currentAudioDevice; } | AudioIODevice* getCurrentAudioDevice() const throw() { return currentAudioDevice; } | ||||
| /** Returns the type of audio device currently in use. | |||||
| @see setCurrentAudioDeviceType | |||||
| */ | |||||
| const String getCurrentAudioDeviceType() const throw() { return currentDeviceType; } | const String getCurrentAudioDeviceType() const throw() { return currentDeviceType; } | ||||
| /** Changes the class of audio device being used. | |||||
| This switches between, e.g. ASIO and DirectSound. On the Mac you probably won't ever call | |||||
| this because there's only one type: CoreAudio. | |||||
| For a list of types, see getAvailableDeviceTypes(). | |||||
| */ | |||||
| void setCurrentAudioDeviceType (const String& type, | void setCurrentAudioDeviceType (const String& type, | ||||
| const bool treatAsChosenDevice); | const bool treatAsChosenDevice); | ||||
| @@ -34657,7 +34668,7 @@ public: | |||||
| */ | */ | ||||
| MidiOutput* getDefaultMidiOutput() const throw() { return defaultMidiOutput; } | MidiOutput* getDefaultMidiOutput() const throw() { return defaultMidiOutput; } | ||||
| /** | |||||
| /** Returns a list of the types of device supported. | |||||
| */ | */ | ||||
| const OwnedArray <AudioIODeviceType>& getAvailableDeviceTypes(); | const OwnedArray <AudioIODeviceType>& getAvailableDeviceTypes(); | ||||
| @@ -225,7 +225,18 @@ public: | |||||
| /** Returns the currently-active audio device. */ | /** Returns the currently-active audio device. */ | ||||
| AudioIODevice* getCurrentAudioDevice() const throw() { return currentAudioDevice; } | AudioIODevice* getCurrentAudioDevice() const throw() { return currentAudioDevice; } | ||||
| /** Returns the type of audio device currently in use. | |||||
| @see setCurrentAudioDeviceType | |||||
| */ | |||||
| const String getCurrentAudioDeviceType() const throw() { return currentDeviceType; } | const String getCurrentAudioDeviceType() const throw() { return currentDeviceType; } | ||||
| /** Changes the class of audio device being used. | |||||
| This switches between, e.g. ASIO and DirectSound. On the Mac you probably won't ever call | |||||
| this because there's only one type: CoreAudio. | |||||
| For a list of types, see getAvailableDeviceTypes(). | |||||
| */ | |||||
| void setCurrentAudioDeviceType (const String& type, | void setCurrentAudioDeviceType (const String& type, | ||||
| const bool treatAsChosenDevice); | const bool treatAsChosenDevice); | ||||
| @@ -353,7 +364,7 @@ public: | |||||
| */ | */ | ||||
| MidiOutput* getDefaultMidiOutput() const throw() { return defaultMidiOutput; } | MidiOutput* getDefaultMidiOutput() const throw() { return defaultMidiOutput; } | ||||
| /** | |||||
| /** Returns a list of the types of device supported. | |||||
| */ | */ | ||||
| const OwnedArray <AudioIODeviceType>& getAvailableDeviceTypes(); | const OwnedArray <AudioIODeviceType>& getAvailableDeviceTypes(); | ||||