From 9ffd554aa3e0b44dab3560ad93639e7532d0b297 Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 24 Aug 2009 15:15:44 +0000 Subject: [PATCH] Made the AU wrapper more robust against crashes when the UI and plugin are deleted in the wrong order. --- .../wrapper/AU/juce_AU_Wrapper.mm | 88 +++++++++++++------ .../wrapper/VST/juce_VST_Wrapper.mm | 2 +- .../wrapper/juce_NPAPI_GlueCode.cpp | 8 +- 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm index 13ff201550..55bfb74d8e 100644 --- a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm +++ b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm @@ -67,9 +67,17 @@ static const int numChannelConfigs = numElementsInArray (channelConfigs); extern AudioProcessor* JUCE_CALLTYPE createPluginFilter(); //============================================================================== -#define CONCAT_MACRO(Part1, Part2) Part1 ## Part2 -#define JuceUICreationClass CONCAT_MACRO (JucePlugin_AUExportPrefix, _UICreationClass) +#define appendMacro1(a, b, c, d) a ## _ ## b ## _ ## c ## _ ## d +#define appendMacro2(a, b, c, d) appendMacro1(a, b, c, d) +#define MakeObjCClassName(rootName) appendMacro2 (rootName, JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JucePlugin_AUExportPrefix) +#define JuceUICreationClass MakeObjCClassName(JuceUICreationClass) +#define JuceUIViewClass MakeObjCClassName(JuceUIViewClass) + +class JuceAU; +class EditorCompHolder; + +//============================================================================== @interface JuceUICreationClass : NSObject { } @@ -82,6 +90,25 @@ extern AudioProcessor* JUCE_CALLTYPE createPluginFilter(); withSize: (NSSize) inPreferredSize; @end +//============================================================================== +@interface JuceUIViewClass : NSView +{ + AudioProcessor* filter; + JuceAU* au; + EditorCompHolder* editorComp; +} + +- (JuceUIViewClass*) initWithFilter: (AudioProcessor*) filter + withAU: (JuceAU*) au + withComponent: (AudioProcessorEditor*) editorComp; +- (void) dealloc; +- (void) viewDidMoveToWindow; +- (BOOL) mouseDownCanMoveWindow; +- (void) filterBeingDeleted: (JuceAU*) au_; +- (void) deleteEditor; + +@end + //============================================================================== class JuceAU : public JuceAUBaseClass, @@ -128,6 +155,9 @@ public: ~JuceAU() { + for (int i = activeUIs.size(); --i >= 0;) + [((JuceUIViewClass*) activeUIs.getUnchecked(i)) filterBeingDeleted: this]; + delete juceFilter; juceFilter = 0; @@ -959,22 +989,6 @@ public: }; //============================================================================== -@interface JuceUIViewClass : NSView -{ - AudioProcessor* filter; - JuceAU* au; - EditorCompHolder* editorComp; -} - -- (JuceUIViewClass*) initWithFilter: (AudioProcessor*) filter - withAU: (JuceAU*) au - withComponent: (AudioProcessorEditor*) editorComp; -- (void) dealloc; -- (void) viewDidMoveToWindow; -- (BOOL) mouseDownCanMoveWindow; - -@end - @implementation JuceUIViewClass - (JuceUIViewClass*) initWithFilter: (AudioProcessor*) filter_ @@ -1003,14 +1017,7 @@ public: // is trying to delete our plugin.. jassert (Component::getCurrentlyModalComponent() == 0); - if (editorComp != 0 && editorComp->isValidComponent()) - { - if (editorComp->getChildComponent(0) != 0) - if (activePlugins.contains ((void*) filter)) // plugin may have been deleted before the UI - filter->editorBeingDeleted ((AudioProcessorEditor*) editorComp->getChildComponent(0)); - - deleteAndZero (editorComp); - } + [self deleteEditor]; jassert (activeUIs.contains (self)); activeUIs.removeValue (self); @@ -1036,8 +1043,29 @@ public: return NO; } +- (void) deleteEditor +{ + if (editorComp != 0 && editorComp->isValidComponent()) + { + if (editorComp->getChildComponent(0) != 0) + if (activePlugins.contains ((void*) au)) // plugin may have been deleted before the UI + filter->editorBeingDeleted ((AudioProcessorEditor*) editorComp->getChildComponent(0)); + + deleteAndZero (editorComp); + } + + editorComp = 0; +} + +- (void) filterBeingDeleted: (JuceAU*) au_ +{ + if (au_ == au) + [self deleteEditor]; +} + @end +//============================================================================== @implementation JuceUICreationClass - (JuceUICreationClass*) init @@ -1164,6 +1192,14 @@ private: juceFilter->editorBeingDeleted ((AudioProcessorEditor*) windowComp->getChildComponent(0)); deleteAndZero (windowComp); + + // The event loop needs to be run between closing the window and deleting the plugin, + // presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes + // in Reaper when you delete the plugin with its window open. + // (Doing it this way rather than using a single longer timout means that we can guarantee + // how many messages will be dispatched, which seems to be vital in Reaper) + for (int i = 20; --i >= 0;) + MessageManager::getInstance()->runDispatchLoopUntil (1); } //============================================================================== diff --git a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.mm b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.mm index 676ffc8613..bd94788c8d 100644 --- a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.mm +++ b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.mm @@ -146,7 +146,7 @@ void detachComponentFromWindowRef (Component* comp, void* nsWindow) // The event loop needs to be run between closing the window and deleting the plugin, // presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes // in Live and Reaper when you delete the plugin with its window open. - // (Doing it this way rather than using a single longer timout means that w can guarantee + // (Doing it this way rather than using a single longer timout means that we can guarantee // how many messages will be dispatched, which seems to be vital in Reaper) for (int i = 20; --i >= 0;) MessageManager::getInstance()->runDispatchLoopUntil (1); diff --git a/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp b/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp index a03da4bf25..f421d4ab6a 100644 --- a/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp +++ b/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp @@ -346,7 +346,7 @@ private: case WM_WINDOWPOSCHANGING: if ((((WINDOWPOS*) lParam)->flags & SWP_NOSIZE) == 0) { - BrowserPluginHolderComponent* const comp = (BrowserPluginHolderComponent*) GetWindowLong (hWnd, GWL_USERDATA); + BrowserPluginHolderComponent* const comp = (BrowserPluginHolderComponent*) GetWindowLongPtr (hWnd, GWL_USERDATA); comp->resizeToParentWindow(); } break; @@ -383,14 +383,14 @@ public: HWND ourHWND = (HWND) getWindowHandle(); SetParent (ourHWND, parentHWND); - DWORD val = GetWindowLong (ourHWND, GWL_STYLE); + DWORD val = GetWindowLongPtr (ourHWND, GWL_STYLE); val = (val & ~WS_POPUP) | WS_CHILD; - SetWindowLong (ourHWND, GWL_STYLE, val); + SetWindowLongPtr (ourHWND, GWL_STYLE, val); setVisible (true); oldWinProc = SubclassWindow (parentHWND, (WNDPROC) interceptingWinProc); - SetWindowLong (parentHWND, GWL_USERDATA, (LONG) this); + SetWindowLongPtr (parentHWND, GWL_USERDATA, (LONG_PTR) this); resizeToParentWindow(); }