VST2: Consolidate support methods (close, unload)

Properly unload linux VST2 plugins and fix Mac VST2
bundle unloading - do not use dlclose():

CFBundleRef is reference counted, so we need to retain
a reference. Previously it went out of scope at the end
of mac_vst_load().
This commit is contained in:
Robin Gareus 2021-06-30 01:10:47 +02:00
parent ef06f01c7b
commit fcd04cd27a
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
3 changed files with 59 additions and 67 deletions

View File

@ -25,6 +25,23 @@
#include "ardour/libardour_visibility.h"
#include "ardour/vestige/vestige.h"
#ifdef MACVST_SUPPORT
#include <Carbon/Carbon.h>
/* fix up stupid apple macros */
#undef check
#undef require
#undef verify
#ifdef YES
#undef YES
#endif
#ifdef NO
#undef NO
#endif
#endif
struct LIBARDOUR_API _VSTKey
{
/** virtual-key code, or 0 if this _VSTFXKey is a `character' key */
@ -62,16 +79,17 @@ typedef AEffect * (* main_entry_t) (audioMasterCallback);
struct LIBARDOUR_API _VSTHandle
{
void* dll;
#ifdef MACVST_SUPPORT
CFBundleRef bundleRef;
CFBundleRefNum res_file_id;
#else
void* dll;
#endif
char* name;
char* path;
main_entry_t main_entry;
int plugincnt;
#ifdef MACVST_SUPPORT
int32_t res_file_id;
#endif
};
typedef struct _VSTHandle VSTHandle;

View File

@ -267,6 +267,7 @@ vstfx_unload (VSTHandle* fhandle)
if (fhandle->name)
{
free (fhandle->name);
fhandle->name = 0;
}
/*Don't need the plugin handle any more*/
@ -339,30 +340,19 @@ void vstfx_close (VSTState* vstfx)
vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
}
if (vstfx->handle->plugincnt)
if (vstfx->handle->plugincnt) {
vstfx->handle->plugincnt--;
/*vstfx_unload will unload the dll if the instance count allows -
we need to do this because some plugins keep their own instance count
and (JUCE) manages the plugin UI in its own thread. When the plugins
internal instance count reaches zero, JUCE stops the UI thread and won't
restart it until the next time the library is loaded. If we don't unload
the lib JUCE will never restart*/
if (vstfx->handle->plugincnt)
{
return;
}
/*Valid plugin loaded - so we can unload it and 0 the pointer
to it. We can't free the handle here because we don't know what else
might need it. It should be / is freed when the plugin is deleted*/
/* vstfx_unload will unload the dll if the instance count allows -
* we need to do this because some plugins keep their own instance count
* and (JUCE) manages the plugin UI in its own thread. When the plugins
* internal instance count reaches zero, JUCE stops the UI thread and won't
* restart it until the next time the library is loaded. If we don't unload
* the lib JUCE will never restart
*/
vstfx_unload (vstfx->handle);
if (vstfx->handle->dll)
{
dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
vstfx->handle->dll = 0;
}
free(vstfx);
}

View File

@ -39,8 +39,6 @@
#include "pbd/i18n.h"
#include <Carbon/Carbon.h>
/*Simple error handler stuff for VSTFX*/
void mac_vst_error (const char *fmt, ...)
@ -96,34 +94,34 @@ mac_vst_load (const char *path)
fhandle = mac_vst_handle_new ();
fhandle->dll = NULL;
fhandle->bundleRef = 0;
CFURLRef url;
if (!(url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*)path, (CFIndex) strlen (path), true))) {
return 0;
}
CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url);
fhandle->bundleRef = CFBundleCreate (kCFAllocatorDefault, url);
CFRelease (url);
if (bundleRef == 0) {
if (fhandle->bundleRef == 0) {
free (fhandle);
return 0;
}
if (!CFBundleLoadExecutable (bundleRef)) {
CFRelease (bundleRef);
if (!CFBundleLoadExecutable (fhandle->bundleRef)) {
free (fhandle);
return 0;
}
fhandle->name = strdup (path);
fhandle->dll = (void*) &bundleRef;
fhandle->main_entry = (main_entry_t)
CFBundleGetFunctionPointerForName (bundleRef, CFSTR("main_macho"));
CFBundleGetFunctionPointerForName (fhandle->bundleRef, CFSTR("main_macho"));
if (!fhandle->main_entry) {
fhandle->main_entry = (main_entry_t)
CFBundleGetFunctionPointerForName (bundleRef, CFSTR("VSTPluginMain"));
CFBundleGetFunctionPointerForName (fhandle->bundleRef, CFSTR("VSTPluginMain"));
}
if (fhandle->main_entry == 0) {
@ -131,7 +129,7 @@ mac_vst_load (const char *path)
return 0;
}
fhandle->res_file_id = CFBundleOpenBundleResourceMap (bundleRef);
fhandle->res_file_id = CFBundleOpenBundleResourceMap (fhandle->bundleRef);
/*return the handle of the plugin*/
return fhandle;
@ -144,25 +142,22 @@ mac_vst_unload (VSTHandle* fhandle)
{
if (fhandle->plugincnt)
{
/*Still have plugin instances - can't unload the library
- actually dlclose keeps an instance count anyway*/
/*Still have plugin instances - can't unload the library */
return -1;
}
/*Valid plugin loaded?*/
if (fhandle->dll)
if (fhandle->bundleRef)
{
CFBundleRef* bundleRefPtr = (CFBundleRef*) fhandle->dll;
CFBundleCloseBundleResourceMap (*bundleRefPtr, (CFBundleRefNum)fhandle->res_file_id);
CFRelease (*bundleRefPtr);
fhandle->dll = 0;
CFBundleCloseBundleResourceMap (fhandle->bundleRef, fhandle->res_file_id);
fhandle->bundleRef = 0;
}
if (fhandle->name)
{
free (fhandle->name);
fhandle->name = 0;
}
/*Don't need the plugin handle any more*/
@ -238,31 +233,20 @@ void mac_vst_close (VSTState* mac_vst)
mac_vst->plugin->dispatcher (mac_vst->plugin, effClose, 0, 0, 0, 0);
}
if (mac_vst->handle->plugincnt)
if (mac_vst->handle->plugincnt) {
mac_vst->handle->plugincnt--;
/*mac_vst_unload will unload the dll if the instance count allows -
we need to do this because some plugins keep their own instance count
and (JUCE) manages the plugin UI in its own thread. When the plugins
internal instance count reaches zero, JUCE stops the UI thread and won't
restart it until the next time the library is loaded. If we don't unload
the lib JUCE will never restart*/
if (mac_vst->handle->plugincnt)
{
return;
}
/*Valid plugin loaded - so we can unload it and 0 the pointer
to it. We can't free the handle here because we don't know what else
might need it. It should be / is freed when the plugin is deleted*/
/* mac_vst_unload will unload the dll if the instance count allows -
* we need to do this because some plugins keep their own instance count
* and (JUCE) manages the plugin UI in its own thread. When the plugins
* internal instance count reaches zero, JUCE stops the UI thread and won't
* restart it until the next time the library is loaded. If we don't unload
* the lib JUCE will never restart
*/
mac_vst_unload (mac_vst->handle);
if (mac_vst->handle->dll)
{
dlclose (mac_vst->handle->dll); //dlclose keeps its own reference count
mac_vst->handle->dll = 0;
}
free (mac_vst);
}