Update of /cvsroot/audacity/audacity-src/src/effects/VST In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv16012/src/effects/VST
Modified Files: VSTEffect.cpp VSTEffect.h Log Message: Fix crash at Audacity termination if user clicks the window close button (X). Dialog would be deleted, but wxWidgets didn't know about it so it tried to get rid of it again at termination. And changes the way bundles are loaded on OSX to only use CoreFoundation to get the executable path and the use the dl...() functions to actually load the bundle. This was done since some of the CoreFoundation functions would cause the process to crash if the bundle couldn't be loaded due to missing symbols and such. Index: VSTEffect.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/effects/VST/VSTEffect.cpp,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- VSTEffect.cpp 6 Nov 2009 19:15:29 -0000 1.48 +++ VSTEffect.cpp 14 Nov 2009 10:12:15 -0000 1.49 @@ -34,6 +34,7 @@ #include <wx/utils.h> #if defined(__WXMAC__) +#include <dlfcn.h> #include <wx/mac/private.h> #else #include <wx/dynlib.h> @@ -116,6 +117,8 @@ AEffect *aeffect); virtual ~VSTEffectDialog(); + void RemoveHandler(); + void OnIdle(wxIdleEvent & evt); void OnProgram(wxCommandEvent & evt); @@ -127,6 +130,7 @@ void OnOk(wxCommandEvent & evt); void OnCancel(wxCommandEvent & evt); + void OnClose(wxCloseEvent & evt); void OnPreview(wxCommandEvent & evt); private: @@ -157,6 +161,11 @@ bool mInChunk; wxString mChunk; +#if defined(__WXMAC__) + EventHandlerUPP mHandlerUPP; + EventHandlerRef mHandlerRef; +#endif + DECLARE_EVENT_TABLE() }; @@ -182,6 +191,31 @@ EVT_SLIDER(wxID_ANY, VSTEffectDialog::OnSlider) END_EVENT_TABLE() +#if defined(__WXMAC__) + +// Event handler to capture the window close event +static const EventTypeSpec eventList[] = +{ + {kEventClassWindow, kEventWindowClose}, +}; + +static pascal OSStatus EventHandler(EventHandlerCallRef handler, EventRef event, void *data) +{ + OSStatus result = eventNotHandledErr; + + VSTEffectDialog *dlg = (VSTEffectDialog *)data; + + if (GetEventClass(event) == kEventClassWindow && GetEventKind(event) == kEventWindowClose) { + dlg->RemoveHandler(); + dlg->Close(); + result = noErr; + } + + return result; +} + +#endif + VSTEffectDialog::VSTEffectDialog(wxWindow *parent, const wxString & title, VSTEffect *effect, @@ -194,6 +228,10 @@ mSliders = NULL; mDisplays = NULL; mLabels = NULL; +#if defined(__WXMAC__) + mHandlerUPP = NULL; + mHandlerRef = NULL; +#endif // Determine if the VST editor is supposed to be used or not mGui = (gPrefs->Read(wxT("/VST/GUI"), (long) true) != 0) && @@ -210,6 +248,8 @@ VSTEffectDialog::~VSTEffectDialog() { + RemoveHandler(); + if (mNames) { delete [] mNames; } @@ -227,6 +267,22 @@ } } +void VSTEffectDialog::RemoveHandler() +{ +#if defined(__WXMAC__) + if (mHandlerRef) { + ::RemoveEventHandler(mHandlerRef); + mHandlerRef = NULL; + MacInstallTopLevelWindowEventHandler(); + } + + if (mHandlerUPP) { + DisposeEventHandlerUPP(mHandlerUPP); + mHandlerUPP = NULL; + } +#endif +} + void VSTEffectDialog::BuildFancy() { struct @@ -278,9 +334,22 @@ #if defined(__WXMAC__) HIViewPlaceInSuperviewAt(subview, pos.x, pos.y); - // LL: Some VST effects do not work unless this is done. But, it must be - // done last since proper window sizing will not occur otherwise. + // Some VST effects do not work unless the default handler is removed since + // it captures many of the events that the plugins need. But, it must be + // done last since proper window sizing will not occur otherwise. ::RemoveEventHandler((EventHandlerRef)MacGetEventHandler()); + + // Install a bare minimum handler so we can capture the window close event. If + // it's not captured, we will crash at Audacity termination since the window + // is still on the wxWidgets toplevel window lists, but it's already gone. + mHandlerUPP = NewEventHandlerUPP(EventHandler); + InstallWindowEventHandler(win, + mHandlerUPP, + GetEventTypeCount(eventList), + eventList, + this, + &mHandlerRef); + #elif defined(__WXMSW__) w->SetPosition(pos); w->SetSize(si->GetSize()); @@ -622,6 +691,11 @@ xmlFile.Close(); } +void VSTEffectDialog::OnClose(wxCloseEvent & evt) +{ + EndModal(false); +} + void VSTEffectDialog::OnPreview(wxCommandEvent & evt) { mEffect->Preview(); @@ -1197,7 +1271,10 @@ dlog.CentreOnParent(); dlog.ShowModal(); - return dlog.GetReturnCode() != 0; + bool ret = dlog.GetReturnCode() != 0; + + dlog.Destroy(); + return ret; } bool VSTEffect::Process() @@ -1390,6 +1467,9 @@ mAEffect = NULL; #if defined(__WXMAC__) + // Start clean + mBundleRef = NULL; + // Don't really know what this should be initialize to mResource = -1; @@ -1417,31 +1497,58 @@ return false; } + // Retrieve a reference to the executable + CFURLRef exeRef = CFBundleCopyExecutableURL(bundleRef); + if (exeRef == NULL) { + CFRelease(bundleRef); + return false; + } + + // Convert back to path + UInt8 exePath[PATH_MAX]; + success = CFURLGetFileSystemRepresentation(exeRef, true, exePath, sizeof(exePath)); + + // Done with the executable reference + CFRelease(exeRef); + + // Bail if we couldn't resolve the executable path + if (success == FALSE) { + CFRelease(bundleRef); + return false; + } + + // Attempt to open it + mModule = dlopen((char *) exePath, RTLD_NOW | RTLD_LOCAL); + if (mModule == NULL) { + CFRelease(bundleRef); + return false; + } + // Try to locate the new plugin entry point - pluginMain = (vstPluginMain) - CFBundleGetFunctionPointerForName(bundleRef, - CFSTR("VSTPluginMain")); + pluginMain = (vstPluginMain) dlsym(mModule, "VSTPluginMain"); // If not found, try finding the old entry point if (pluginMain == NULL) { - pluginMain = (vstPluginMain) - CFBundleGetFunctionPointerForName(bundleRef, - CFSTR("main_macho")); + pluginMain = (vstPluginMain) dlsym(mModule, "main_macho"); } // Must not be a VST plugin if (pluginMain == NULL) { + dlclose(mModule); + mModule = NULL; CFRelease(bundleRef); return false; } + // Need to keep the bundle reference around so we can map the + // resources. + mBundleRef = bundleRef; + // Open the resource map ... some plugins (like GRM Tools) need this. mResource = (int) CFBundleOpenBundleResourceMap(bundleRef); - // Save the bundle reference - mModule = bundleRef; - #else + { wxLogNull nolog; @@ -1517,10 +1624,16 @@ if (mModule) { #if defined(__WXMAC__) if (mResource != -1) { - CFBundleCloseBundleResourceMap((CFBundleRef) mModule, mResource); + CFBundleCloseBundleResourceMap((CFBundleRef) mBundleRef, mResource); + mResource = -1; } - CFRelease((CFBundleRef) mModule); + if (mBundleRef != NULL) { + CFRelease((CFBundleRef) mBundleRef); + mBundleRef = NULL; + } + + dlclose(mModule); #else delete (wxDynamicLibrary *) mModule; #endif Index: VSTEffect.h =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/effects/VST/VSTEffect.h,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- VSTEffect.h 3 Aug 2009 17:14:21 -0000 1.19 +++ VSTEffect.h 14 Nov 2009 10:12:15 -0000 1.20 @@ -94,6 +94,8 @@ wxString mPath; #if defined(__WXMAC__) + // Cheating a little ... type is really CFBundle + void *mBundleRef; // Cheating a little ... type is really CFBundleRefNum int mResource; #endif ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Audacity-cvs mailing list Audacity-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/audacity-cvs