diff --git a/src/effects/VST/VSTEffect.cpp b/src/effects/VST/VSTEffect.cpp index 036c59a9d..c1dbaa245 100644 --- a/src/effects/VST/VSTEffect.cpp +++ b/src/effects/VST/VSTEffect.cpp @@ -1043,6 +1043,30 @@ intptr_t VSTEffect::AudioMaster(AEffect * effect, return 0; } +#if !defined(__WXMSW__) +void VSTEffect::ModuleDeleter::operator() (void* p) const +{ + if (p) + dlclose(p); +} +#endif + +#if defined(__WXMAC__) +void VSTEffect::BundleDeleter::operator() (void* p) const +{ + if (p) + CFRelease(static_cast(p)); +} + +void VSTEffect::ResourceDeleter::operator() (void *p) const +{ + if (mpHandle) { + int resource = (int)p; + CFBundleCloseBundleResourceMap(mpHandle->get(), resource); + } +} +#endif + VSTEffect::VSTEffect(const wxString & path, VSTEffect *master) : mPath(path), mMaster(master) @@ -1052,7 +1076,7 @@ VSTEffect::VSTEffect(const wxString & path, VSTEffect *master) mAEffect = NULL; mDialog = NULL; - mTimer = new VSTEffectTimer(this); + mTimer = std::make_unique(this); mTimerGuard = 0; mInteractive = false; @@ -1986,10 +2010,9 @@ bool VSTEffect::Load() #if defined(__WXMAC__) // Start clean - mBundleRef = NULL; + mBundleRef.reset(); - // Don't really know what this should be initialize to - mResource = -1; + mResource = ResourceHandle{}; // Convert the path to a CFSTring wxCFStringRef path(realPath); @@ -1997,33 +2020,30 @@ bool VSTEffect::Load() // Convert the path to a URL CFURLRef urlRef = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, - path, - kCFURLPOSIXPathStyle, - true); + path, + kCFURLPOSIXPathStyle, + true); if (urlRef == NULL) { return false; } // Create the bundle using the URL - CFBundleRef bundleRef = CFBundleCreate(kCFAllocatorDefault, urlRef); + BundleHandle bundleRef{ CFBundleCreate(kCFAllocatorDefault, urlRef) }; // Done with the URL CFRelease(urlRef); // Bail if the bundle wasn't created - if (bundleRef == NULL) + if (!bundleRef) { return false; } // Retrieve a reference to the executable - CFURLRef exeRef = CFBundleCopyExecutableURL(bundleRef); - if (exeRef == NULL) - { - CFRelease(bundleRef); + CFURLRef exeRef = CFBundleCopyExecutableURL(bundleRef.get()); + if (!exeRef) return false; - } // Convert back to path UInt8 exePath[PLATFORM_MAX_PATH]; @@ -2034,43 +2054,39 @@ bool VSTEffect::Load() // Bail if we couldn't resolve the executable path if (good == FALSE) - { - CFRelease(bundleRef); return false; - } // Attempt to open it - mModule = dlopen((char *) exePath, RTLD_NOW | RTLD_LOCAL); - if (mModule == NULL) - { - CFRelease(bundleRef); + mModule.reset((char*)dlopen((char *) exePath, RTLD_NOW | RTLD_LOCAL)); + if (!mModule) return false; - } // Try to locate the NEW plugin entry point - pluginMain = (vstPluginMain) dlsym(mModule, "VSTPluginMain"); + pluginMain = (vstPluginMain) dlsym(mModule.get(), "VSTPluginMain"); // If not found, try finding the old entry point if (pluginMain == NULL) { - pluginMain = (vstPluginMain) dlsym(mModule, "main_macho"); + pluginMain = (vstPluginMain) dlsym(mModule.get(), "main_macho"); } // Must not be a VST plugin if (pluginMain == NULL) { - dlclose(mModule); - mModule = NULL; - CFRelease(bundleRef); + mModule.reset(); return false; } // Need to keep the bundle reference around so we can map the // resources. - mBundleRef = bundleRef; + mBundleRef = std::move(bundleRef); // Open the resource map ... some plugins (like GRM Tools) need this. - mResource = (int) CFBundleOpenBundleResourceMap(bundleRef); + mResource = ResourceHandle { + reinterpret_cast( + CFBundleOpenBundleResourceMap(mBundleRef.get())), + ResourceDeleter{&mBundleRef} + }; #elif defined(__WXMSW__) @@ -2078,18 +2094,13 @@ bool VSTEffect::Load() wxLogNull nolog; // Try to load the library - wxDynamicLibrary *lib = new wxDynamicLibrary(realPath); + auto lib = std::make_unique(realPath); if (!lib) - { return false; - } // Bail if it wasn't successful if (!lib->IsLoaded()) - { - delete lib; return false; - } // Try to find the entry point, while suppressing error messages pluginMain = (vstPluginMain) lib->GetSymbol(wxT("VSTPluginMain")); @@ -2097,14 +2108,11 @@ bool VSTEffect::Load() { pluginMain = (vstPluginMain) lib->GetSymbol(wxT("main")); if (pluginMain == NULL) - { - delete lib; return false; - } } // Save the library reference - mModule = lib; + mModule = std::move(lib); } #else @@ -2128,26 +2136,26 @@ bool VSTEffect::Load() #ifndef RTLD_DEEPBIND #define RTLD_DEEPBIND 0 #endif - void *lib = dlopen((const char *)wxString(realPath).ToUTF8(), RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND); + ModuleHandle lib { + (char*) dlopen((const char *)wxString(realPath).ToUTF8(), + RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND) + }; if (!lib) { return false; } // Try to find the entry point, while suppressing error messages - pluginMain = (vstPluginMain) dlsym(lib, "VSTPluginMain"); + pluginMain = (vstPluginMain) dlsym(lib.get(), "VSTPluginMain"); if (pluginMain == NULL) { - pluginMain = (vstPluginMain) dlsym(lib, "main"); + pluginMain = (vstPluginMain) dlsym(lib.get(), "main"); if (pluginMain == NULL) - { - dlclose(lib); return false; - } } // Save the library reference - mModule = lib; + mModule = std::move(lib); #endif @@ -2267,13 +2275,6 @@ void VSTEffect::Unload() CloseUI(); } - if (mTimer) - { - mTimer->Stop(); - delete mTimer; - mTimer = NULL; - } - if (mAEffect) { // Turn the power off @@ -2287,32 +2288,11 @@ void VSTEffect::Unload() if (mModule) { #if defined(__WXMAC__) - - if (mResource != -1) - { - CFBundleCloseBundleResourceMap((CFBundleRef) mBundleRef, mResource); - mResource = -1; - } - - if (mBundleRef != NULL) - { - CFRelease((CFBundleRef) mBundleRef); - mBundleRef = NULL; - } - - dlclose(mModule); - -#elif defined(__WXMSW__) - - delete (wxDynamicLibrary *) mModule; - -#else - - dlclose(mModule); - + mResource = ResourceHandle{}; + mBundleRef.reset(); #endif - mModule = NULL; + mModule.reset(); mAEffect = NULL; } } diff --git a/src/effects/VST/VSTEffect.h b/src/effects/VST/VSTEffect.h index 2bb2419a3..6bae149ce 100644 --- a/src/effects/VST/VSTEffect.h +++ b/src/effects/VST/VSTEffect.h @@ -49,6 +49,11 @@ typedef AEffect *(*vstPluginMain)(audioMasterCallback audioMaster); class VSTEffectTimer; class VSTEffectDialog; class VSTEffect; +class wxDynamicLibrary; + +#if defined(__WXMAC__) +struct __CFBundle; +#endif /////////////////////////////////////////////////////////////////////////////// // @@ -244,6 +249,16 @@ private: void callSetChunk(bool isPgm, int len, void *buf, VstPatchChunkInfo *info); private: + // Define a manager class for a handle to a module +#if defined(__WXMSW__) + using ModuleHandle = std::unique_ptr; +#else + struct ModuleDeleter { + void operator() (void*) const; + }; + using ModuleHandle = std::unique_ptr < char, ModuleDeleter > ; +#endif + EffectHostInterface *mHost; PluginID mID; wxString mPath; @@ -265,11 +280,32 @@ private: bool mReady; + ModuleHandle mModule; + #if defined(__WXMAC__) - void *mBundleRef; // Cheating a little ... type is really CFBundle - int mResource; // Cheating a little ... type is really CFBundle + // These members must be ordered after mModule + + struct BundleDeleter { + void operator() (void*) const; + }; + using BundleHandle = std::unique_ptr< + __CFBundle, BundleDeleter + >; + + BundleHandle mBundleRef; + + struct ResourceDeleter { + const BundleHandle *mpHandle; + ResourceDeleter(const BundleHandle *pHandle = nullptr) + : mpHandle(pHandle) {} + void operator() (void*) const; + }; + using ResourceHandle = std::unique_ptr< + char, ResourceDeleter + >; + ResourceHandle mResource; #endif - void *mModule; + AEffect *mAEffect; VstTimeInfo mTimeInfo; @@ -286,7 +322,7 @@ private: wxCRIT_SECT_DECLARE_MEMBER(mDispatcherLock); - VSTEffectTimer *mTimer; + std::unique_ptr mTimer; int mTimerGuard; // Realtime processing diff --git a/src/effects/audiounits/AudioUnitEffect.cpp b/src/effects/audiounits/AudioUnitEffect.cpp index 92ea6542f..1d9272702 100644 --- a/src/effects/audiounits/AudioUnitEffect.cpp +++ b/src/effects/audiounits/AudioUnitEffect.cpp @@ -1346,36 +1346,28 @@ bool AudioUnitEffect::RealtimeInitialize() bool AudioUnitEffect::RealtimeAddProcessor(int numChannels, float sampleRate) { - AudioUnitEffect *slave = new AudioUnitEffect(mPath, mName, mComponent, this); + auto slave = make_movable(mPath, mName, mComponent, this); if (!slave->SetHost(NULL)) - { - delete slave; return false; - } slave->SetBlockSize(mBlockSize); slave->SetChannelCount(numChannels); slave->SetSampleRate(sampleRate); if (!CopyParameters(mUnit, slave->mUnit)) - { - delete slave; return false; - } - mSlaves.Add(slave); + auto pSlave = slave.get(); + mSlaves.push_back(std::move(slave)); - return slave->ProcessInitialize(0); + return pSlave->ProcessInitialize(0); } bool AudioUnitEffect::RealtimeFinalize() { - for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++) - { + for (size_t i = 0, cnt = mSlaves.size(); i < cnt; i++) mSlaves[i]->ProcessFinalize(); - delete mSlaves[i]; - } - mSlaves.Clear(); + mSlaves.clear(); for (int i = 0; i < mAudioIns; i++) { @@ -2184,10 +2176,8 @@ void AudioUnitEffect::EventListener(const AudioUnitEvent *inEvent, else { // We're the master, so propogate - for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++) - { + for (size_t i = 0, cnt = mSlaves.size(); i < cnt; i++) mSlaves[i]->EventListener(inEvent, inParameterValue); - } } } diff --git a/src/effects/audiounits/AudioUnitEffect.h b/src/effects/audiounits/AudioUnitEffect.h index 2500a27dc..ffcf1cdfe 100644 --- a/src/effects/audiounits/AudioUnitEffect.h +++ b/src/effects/audiounits/AudioUnitEffect.h @@ -14,6 +14,8 @@ #if USE_AUDIO_UNITS +#include "../../MemoryX.h" +#include #include #include @@ -31,7 +33,7 @@ class AudioUnitEffect; -WX_DEFINE_ARRAY_PTR(AudioUnitEffect *, AudioUnitEffectArray); +using AudioUnitEffectArray = std::vector>; class AudioUnitEffectExportDialog; class AudioUnitEffectImportDialog; diff --git a/src/effects/lv2/LV2Effect.cpp b/src/effects/lv2/LV2Effect.cpp index 2186a64aa..76377064b 100644 --- a/src/effects/lv2/LV2Effect.cpp +++ b/src/effects/lv2/LV2Effect.cpp @@ -124,7 +124,7 @@ void LV2EffectMeter::OnErase(wxEraseEvent & WXUNUSED(evt)) void LV2EffectMeter::OnPaint(wxPaintEvent & WXUNUSED(evt)) { - wxDC *dc = wxAutoBufferedPaintDCFactory(this); + std::unique_ptr dc{ wxAutoBufferedPaintDCFactory(this) }; // Cache some metrics wxRect r = GetClientRect(); @@ -153,8 +153,6 @@ void LV2EffectMeter::OnPaint(wxPaintEvent & WXUNUSED(evt)) dc->DrawRectangle(x, y, (w * (val / fabs(mCtrl.mMax - mCtrl.mMin))), h); mLastValue = mCtrl.mVal; - - delete dc; } void LV2EffectMeter::OnSize(wxSizeEvent & WXUNUSED(evt)) @@ -1461,8 +1459,10 @@ bool LV2Effect::BuildFancy() } // Use a panel to host the plugins GUI - mContainer = safenew wxPanelWrapper(mParent, wxID_ANY); - if (!mContainer) + // container is owned by mParent, but we may destroy it if there are + // any errors before completing the build of UI. + auto container = std::make_unique(mParent, wxID_ANY); + if (!container) { lilv_uis_free(uis); return false; @@ -1476,30 +1476,29 @@ bool LV2Effect::BuildFancy() auto hs = std::make_unique(wxHORIZONTAL); if (hs) { - si = hs->Add(mContainer, 1, wxCENTER | wxEXPAND); + si = hs->Add(container.get(), 1, wxCENTER | wxEXPAND); vs->Add(hs.release(), 0, wxCENTER); } } if (!si) { - delete mContainer; lilv_uis_free(uis); return false; } #if defined(__WXGTK__) // Make sure the parent has a window - if (!gtk_widget_get_window(GTK_WIDGET(mContainer->m_wxwindow))) + if (!gtk_widget_get_window(GTK_WIDGET(container->m_wxwindow))) { - gtk_widget_realize(GTK_WIDGET(mContainer->m_wxwindow)); + gtk_widget_realize(GTK_WIDGET(container->m_wxwindow)); } - mParentFeature->data = GTK_WIDGET(mContainer->GetHandle()); + mParentFeature->data = GTK_WIDGET(container->GetHandle()); #elif defined(__WXMSW__) - mParentFeature->data = mContainer->GetHandle(); + mParentFeature->data = container->GetHandle(); #elif defined(__WXMAC__) - mParentFeature->data = mContainer->GetHandle(); + mParentFeature->data = container->GetHandle(); #endif mInstanceAccessFeature->data = lilv_instance_get_handle(mMaster); @@ -1509,7 +1508,6 @@ bool LV2Effect::BuildFancy() mSuilHost = suil_host_new(LV2Effect::suil_write_func, NULL, NULL, NULL); if (!mSuilHost) { - delete mContainer; lilv_uis_free(uis); return false; } @@ -1532,7 +1530,6 @@ bool LV2Effect::BuildFancy() suil_host_free(mSuilHost); mSuilHost = NULL; - delete mContainer; return false; } @@ -1545,7 +1542,7 @@ bool LV2Effect::BuildFancy() gtk_widget_set_size_request(widget, 1, 1); gtk_widget_set_size_request(widget, sz.width, sz.height); - wxPizza *pizza = WX_PIZZA(mContainer->m_wxwindow); + wxPizza *pizza = WX_PIZZA(container->m_wxwindow); pizza->put(widget, 0, //gtk_pizza_get_xoffset(pizza), 0, //gtk_pizza_get_yoffset(pizza), @@ -1565,6 +1562,8 @@ bool LV2Effect::BuildFancy() #endif mParent->SetSizerAndFit(vs.release()); + // mParent will guarantee release of the container now. + container.release(); } mIdleFeature = (const LV2UI_Idle_Interface *) diff --git a/src/effects/lv2/LV2Effect.h b/src/effects/lv2/LV2Effect.h index bc5cf0e96..9b122f1a1 100644 --- a/src/effects/lv2/LV2Effect.h +++ b/src/effects/lv2/LV2Effect.h @@ -285,7 +285,6 @@ private: EffectUIHostInterface *mUIHost; bool mUseGUI; - wxWindow *mContainer; char **mURIMap; int mNumURIMap; diff --git a/src/effects/vamp/LoadVamp.cpp b/src/effects/vamp/LoadVamp.cpp index c0bfaf5f7..090a62401 100644 --- a/src/effects/vamp/LoadVamp.cpp +++ b/src/effects/vamp/LoadVamp.cpp @@ -132,7 +132,7 @@ wxArrayString VampEffectsModule::FindPlugins(PluginManagerInterface & WXUNUSED(p for (PluginLoader::PluginKeyList::iterator i = keys.begin(); i != keys.end(); ++i) { - Plugin *vp = PluginLoader::getInstance()->loadPlugin(*i, 48000); // rate doesn't matter here + std::unique_ptr vp{ PluginLoader::getInstance()->loadPlugin(*i, 48000) }; // rate doesn't matter here if (!vp) { continue; @@ -194,8 +194,6 @@ wxArrayString VampEffectsModule::FindPlugins(PluginManagerInterface & WXUNUSED(p ++output; } - - delete vp; } return names; @@ -206,10 +204,10 @@ bool VampEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxStri int output; bool hasParameters; - Plugin *vp = FindPlugin(path, output, hasParameters); + auto vp = FindPlugin(path, output, hasParameters); if (vp) { - VampEffect effect(vp, path, output, hasParameters); + VampEffect effect(std::move(vp), path, output, hasParameters); pm.RegisterPlugin(this, &effect); return true; @@ -223,14 +221,8 @@ bool VampEffectsModule::IsPluginValid(const wxString & path) int output; bool hasParameters; - Plugin *vp = FindPlugin(path, output, hasParameters); - if (vp) - { - delete vp; - return true; - } - - return false; + auto vp = FindPlugin(path, output, hasParameters); + return bool(vp); } IdentInterface *VampEffectsModule::CreateInstance(const wxString & path) @@ -239,11 +231,11 @@ IdentInterface *VampEffectsModule::CreateInstance(const wxString & path) int output; bool hasParameters; - Plugin *vp = FindPlugin(path, output, hasParameters); + auto vp = FindPlugin(path, output, hasParameters); if (vp) { // Safety of this depends on complementary calls to DeleteInstance on the module manager side. - return safenew VampEffect(vp, path, output, hasParameters); + return safenew VampEffect(std::move(vp), path, output, hasParameters); } return NULL; @@ -258,13 +250,13 @@ void VampEffectsModule::DeleteInstance(IdentInterface *instance) // VampEffectsModule implementation -Plugin *VampEffectsModule::FindPlugin(const wxString & path, +std::unique_ptr VampEffectsModule::FindPlugin(const wxString & path, int & output, bool & hasParameters) { PluginLoader::PluginKey key = path.BeforeLast(wxT('/')).ToUTF8().data(); - Plugin *vp = PluginLoader::getInstance()->loadPlugin(key, 48000); // rate doesn't matter here + std::unique_ptr vp{ PluginLoader::getInstance()->loadPlugin(key, 48000) }; // rate doesn't matter here if (!vp) { return nullptr; @@ -331,9 +323,7 @@ Plugin *VampEffectsModule::FindPlugin(const wxString & path, ++output; } - delete vp; - - return NULL; + return {}; } #endif diff --git a/src/effects/vamp/LoadVamp.h b/src/effects/vamp/LoadVamp.h index 3f8126c0b..490f2bf5f 100644 --- a/src/effects/vamp/LoadVamp.h +++ b/src/effects/vamp/LoadVamp.h @@ -54,7 +54,7 @@ public: private: // VampEffectModule implementation - Vamp::Plugin *FindPlugin(const wxString & wpath, + std::unique_ptr FindPlugin(const wxString & wpath, int & output, bool & hasParameters); diff --git a/src/effects/vamp/VampEffect.cpp b/src/effects/vamp/VampEffect.cpp index 8e6caa984..22e156386 100644 --- a/src/effects/vamp/VampEffect.cpp +++ b/src/effects/vamp/VampEffect.cpp @@ -69,11 +69,11 @@ BEGIN_EVENT_TABLE(VampEffect, wxEvtHandler) EVT_CHOICE(wxID_ANY, VampEffect::OnChoice) END_EVENT_TABLE() -VampEffect::VampEffect(Vamp::Plugin *plugin, +VampEffect::VampEffect(std::unique_ptr &&plugin, const wxString & path, int output, bool hasParameters) -: mPlugin(plugin), +: mPlugin(std::move(plugin)), mPath(path), mOutput(output), mHasParameters(hasParameters), @@ -92,11 +92,6 @@ VampEffect::VampEffect(Vamp::Plugin *plugin, VampEffect::~VampEffect() { - if (mPlugin) - { - delete mPlugin; - } - if (mValues) { delete [] mValues; @@ -381,14 +376,7 @@ bool VampEffect::Init() // The plugin must be reloaded to allow changing parameters Vamp::HostExt::PluginLoader *loader = Vamp::HostExt::PluginLoader::getInstance(); - - if (mPlugin) - { - delete mPlugin; - mPlugin = NULL; - } - - mPlugin = loader->loadPlugin(mKey, mRate, Vamp::HostExt::PluginLoader::ADAPT_ALL); + mPlugin.reset(loader->loadPlugin(mKey, mRate, Vamp::HostExt::PluginLoader::ADAPT_ALL)); if (!mPlugin) { wxMessageBox(_("Sorry, failed to load Vamp Plug-in.")); @@ -584,8 +572,7 @@ bool VampEffect::Process() void VampEffect::End() { - delete mPlugin; - mPlugin = 0; + mPlugin.reset(); } void VampEffect::PopulateOrExchange(ShuttleGui & S) diff --git a/src/effects/vamp/VampEffect.h b/src/effects/vamp/VampEffect.h index a0ffa3874..e5f6652f7 100644 --- a/src/effects/vamp/VampEffect.h +++ b/src/effects/vamp/VampEffect.h @@ -35,7 +35,7 @@ class LabelTrack; class VampEffect final : public Effect { public: - VampEffect(Vamp::Plugin *plugin, + VampEffect(std::unique_ptr &&plugin, const wxString & path, int output, bool hasParameters); @@ -85,7 +85,7 @@ private: void OnTextCtrl(wxCommandEvent & evt); private: - Vamp::Plugin *mPlugin; + std::unique_ptr mPlugin; wxString mPath; int mOutput; bool mHasParameters;