remaining bits for VST-shell plugin support ..and more VST rework

This commit is contained in:
Robin Gareus
2014-02-23 21:11:53 +01:00
parent fac93f7a82
commit 2e0c98c489
7 changed files with 312 additions and 143 deletions

View File

@@ -33,7 +33,7 @@ class Session;
class LIBARDOUR_API LXVSTPlugin : public VSTPlugin
{
public:
LXVSTPlugin (AudioEngine &, Session &, VSTHandle *);
LXVSTPlugin (AudioEngine &, Session &, VSTHandle *, int unique_id);
LXVSTPlugin (const LXVSTPlugin &);
~LXVSTPlugin ();

View File

@@ -101,6 +101,8 @@
#define effEditIdle 19
#define effEditTop 20
#define effProcessEvents 25
// the next one from http://asseca.com/vst-24-specs/index.html
#define effGetPlugCategory 35
#define effGetEffectName 45
#define effGetVendorString 47
#define effGetProductString 48
@@ -191,21 +193,58 @@ struct _VstEvents
VstEvent * events[];
};
/* constants from http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=3740&sid=183f74631fee71a493316735e2b9f28b */
enum Vestige2StringConstants
{
VestigeMaxNameLen = 64,
VestigeMaxLabelLen = 64,
VestigeMaxShortLabelLen = 8,
VestigeMaxCategLabelLen = 24,
VestigeMaxFileNameLen = 100
};
/* constants from http://asseca.com/vst-24-specs/efGetPlugCategory.html */
enum VstPlugCategory
{
kPlugCategUnknown = 0,
kPlugCategEffect,
kPlugCategSynth,
kPlugCategAnalysis,
kPlugCategMastering,
kPlugCategSpacializer,
kPlugCategRoomFx,
kPlugSurroundFx,
kPlugCategRestoration,
kPlugCategOfflineProcess,
kPlugCategShell,
kPlugCategGenerator,
kPlugCategMaxCount
};
typedef struct _VstEvents VstEvents;
/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
struct _VstParameterProperties
{
float stepFloat;
float smallStepFloat;
float largeStepFloat;
char label[64];
int32_t flags;
int32_t minInteger;
int32_t maxInteger;
int32_t stepInteger;
int32_t largeStepInteger;
char shortLabel[8];
float stepFloat; /* float step */
float smallStepFloat; /* small float step */
float largeStepFloat; /* large float step */
char label[VestigeMaxLabelLen]; /* parameter label */
int32_t flags; /* @see VstParameterFlags */
int32_t minInteger; /* integer minimum */
int32_t maxInteger; /* integer maximum */
int32_t stepInteger; /* integer step */
int32_t largeStepInteger; /* large integer step */
char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */
int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */
int16_t category; /* 0: no category, else group index + 1 */
int16_t numParametersInCategory; /* number of parameters in category */
int16_t reserved; /* zero */
char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */
char future[16]; /* reserved for future use */
};
typedef struct _VstParameterProperties VstParameterProperties;

View File

@@ -25,7 +25,6 @@
#include "ardour/vst_types.h"
#include <vector>
LIBARDOUR_API extern void vstfx_free_info (VSTInfo *);
LIBARDOUR_API extern void vstfx_free_info_list (std::vector<VSTInfo *> *infos);
#ifdef LXVST_SUPPORT

View File

@@ -33,7 +33,7 @@ class Session;
class LIBARDOUR_API WindowsVSTPlugin : public VSTPlugin
{
public:
WindowsVSTPlugin (AudioEngine &, Session &, VSTHandle *);
WindowsVSTPlugin (AudioEngine &, Session &, VSTHandle *, int unique_id);
WindowsVSTPlugin (const WindowsVSTPlugin &);
~WindowsVSTPlugin ();

View File

@@ -27,14 +27,16 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
LXVSTPlugin::LXVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h)
LXVSTPlugin::LXVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h, int unique_id)
: VSTPlugin (e, session, h)
{
/* Instantiate the plugin and return a VSTState* */
Session::vst_current_loading_id = unique_id;
if ((_state = vstfx_instantiate (_handle, Session::vst_callback, this)) == 0) {
throw failed_constructor();
}
Session::vst_current_loading_id = 0;
set_plugin (_state->plugin);
}
@@ -44,9 +46,12 @@ LXVSTPlugin::LXVSTPlugin (const LXVSTPlugin &other)
{
_handle = other._handle;
Session::vst_current_loading_id = PBD::atoi(other.unique_id());
if ((_state = vstfx_instantiate (_handle, Session::vst_callback, this)) == 0) {
throw failed_constructor();
}
Session::vst_current_loading_id = 0;
_plugin = _state->plugin;
// Plugin::setup_controls ();
@@ -72,7 +77,7 @@ LXVSTPluginInfo::load (Session& session)
error << string_compose(_("LXVST: cannot load module from \"%1\""), path) << endmsg;
}
else {
plugin.reset (new LXVSTPlugin (session.engine(), session, handle));
plugin.reset (new LXVSTPlugin (session.engine(), session, handle, PBD::atoi(unique_id)));
}
}
else {

View File

@@ -49,6 +49,23 @@
using namespace std;
// TODO: make static parts of this file re-usable for standalone app
// TODO: namespace public API into ARDOUR, ::Session or ::PluginManager
// consolidate vstfx_get_info_lx() and vstfx_get_info_fst()
/* prototypes */
#ifdef WINDOWS_VST_SUPPORT
#include <fst.h>
static bool
vstfx_instantiate_and_get_info_fst (const char* dllpath, vector<VSTInfo*> *infos, int uniqueID);
#endif
#ifdef LXVST_SUPPORT
static bool vstfx_instantiate_and_get_info_lx (const char* dllpath, vector<VSTInfo*> *infos, int uniqueID);
#endif
static int vstfx_current_loading_id = 0;
static char *
read_string (FILE *fp)
{
@@ -84,6 +101,22 @@ read_int (FILE* fp, int* n)
return (sscanf (p, "%d", n) != 1);
}
static void
vstfx_free_info (VSTInfo *info)
{
for (int i = 0; i < info->numParams; i++) {
free (info->ParamNames[i]);
free (info->ParamLabels[i]);
}
free (info->name);
free (info->creator);
free (info->Category);
free (info->ParamNames);
free (info->ParamLabels);
free (info);
}
static void
vstfx_clear_info_list (vector<VSTInfo *> *infos)
{
@@ -212,15 +245,16 @@ vstfx_write_info_file (FILE* fp, vector<VSTInfo *> *infos)
} else if (infos->size() == 1) {
vstfx_write_info_block(fp, infos->front());
} else {
PBD::warning << "Zero plugins in VST." << endmsg; // XXX here?
PBD::error << "Zero plugins in VST." << endmsg; // XXX here? rather make this impossible before if it ain't already.
}
}
static string
vstfx_infofile_path (char* dllpath, int personal)
vstfx_infofile_path (const char* dllpath, int personal)
{
string dir;
if (personal) {
// TODO use XDG_CACHE_HOME
dir = Glib::build_filename (Glib::get_home_dir (), ".fst");
/* If the directory doesn't exist, try to create it */
@@ -240,7 +274,7 @@ vstfx_infofile_path (char* dllpath, int personal)
}
static char *
vstfx_infofile_stat (char *dllpath, struct stat* statbuf, int personal)
vstfx_infofile_stat (const char *dllpath, struct stat* statbuf, int personal)
{
if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) {
return 0;
@@ -272,7 +306,7 @@ vstfx_infofile_stat (char *dllpath, struct stat* statbuf, int personal)
static FILE *
vstfx_infofile_for_read (char* dllpath)
vstfx_infofile_for_read (const char* dllpath)
{
struct stat own_statbuf;
struct stat sys_statbuf;
@@ -300,7 +334,7 @@ vstfx_infofile_for_read (char* dllpath)
}
static FILE *
vstfx_infofile_create (char* dllpath, int personal)
vstfx_infofile_create (const char* dllpath, int personal)
{
if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) {
return 0;
@@ -311,7 +345,7 @@ vstfx_infofile_create (char* dllpath, int personal)
}
static FILE *
vstfx_infofile_for_write (char* dllpath)
vstfx_infofile_for_write (const char* dllpath)
{
FILE* f;
@@ -340,8 +374,8 @@ int vstfx_can_midi (VSTState* vstfx)
return false;
}
static VSTInfo *
vstfx_info_from_plugin (VSTState* vstfx)
static VSTInfo*
vstfx_parse_vst_state (VSTState* vstfx)
{
assert (vstfx);
@@ -374,9 +408,25 @@ vstfx_info_from_plugin (VSTState* vstfx)
info->creator = strdup (creator);
}
switch (plugin->dispatcher (plugin, effGetPlugCategory, 0, 0, 0, 0))
{
case kPlugCategEffect: info->Category = strdup ("Effect"); break;
case kPlugCategSynth: info->Category = strdup ("Synth"); break;
case kPlugCategAnalysis: info->Category = strdup ("Anaylsis"); break;
case kPlugCategMastering: info->Category = strdup ("Mastering"); break;
case kPlugCategSpacializer: info->Category = strdup ("Spacializer"); break;
case kPlugCategRoomFx: info->Category = strdup ("RoomFx"); break;
case kPlugSurroundFx: info->Category = strdup ("SurroundFx"); break;
case kPlugCategRestoration: info->Category = strdup ("Restoration"); break;
case kPlugCategOfflineProcess: info->Category = strdup ("Offline"); break;
case kPlugCategShell: info->Category = strdup ("Shell"); break;
case kPlugCategGenerator: info->Category = strdup ("Generator"); break;
default: info->Category = strdup ("Unknown"); break;
}
info->UniqueID = plugin->uniqueID;
info->Category = strdup("None"); /* XXX */
info->numInputs = plugin->numInputs;
info->numOutputs = plugin->numOutputs;
info->numParams = plugin->numParams;
@@ -405,45 +455,120 @@ vstfx_info_from_plugin (VSTState* vstfx)
return info;
}
static void
vstfx_info_from_plugin (const char *dllpath, VSTState* vstfx, vector<VSTInfo *> *infos, int type)
{
assert(vstfx);
VSTInfo *info;
if ((info = vstfx_parse_vst_state(vstfx))) {
infos->push_back(info);
#if 1
/* If this plugin is a Shell and we are not already inside a shell plugin
* read the info for all of the plugins contained in this shell.
*/
if (!strncmp (info->Category, "Shell", 5)
&& vstfx->handle->plugincnt == 1) {
int id;
vector< pair<int, string> > ids;
AEffect *plugin = vstfx->plugin;
string path = vstfx->handle->path;
do {
char name[65] = "Unknown\0";
id = plugin->dispatcher (plugin, effShellGetNextPlugin, 0, 0, name, 0);
ids.push_back(std::make_pair(id, name));
} while ( id != 0 );
switch(type) {
#ifdef WINDOWS_VST_SUPPORT
case 1: fst_close(vstfx); break;
#endif
#ifdef LXVST_SUPPORT
case 2: vstfx_close (vstfx); break;
#endif
default: assert(0); break;
}
for (vector< pair<int, string> >::iterator x = ids.begin(); x != ids.end(); ++x) {
id = (*x).first;
if (id == 0) continue;
/* recurse vstfx_get_info() */
bool ok;
switch (type) { // TODO use lib ardour's type
#ifdef WINDOWS_VST_SUPPORT
case 1: ok = vstfx_instantiate_and_get_info_fst(dllpath, infos, id); break;
#endif
#ifdef LXVST_SUPPORT
case 2: ok = vstfx_instantiate_and_get_info_lx(dllpath, infos, id); break;
#endif
default: ok = false;
}
if (ok) {
// One shell (some?, all?) does not report the actual plugin name
// even after the shelled plugin has been instantiated.
// Replace the name of the shell with the real name.
info = infos->back();
free (info->name);
if ((*x).second.length() == 0) {
info->name = strdup("Unknown");
}
else {
info->name = strdup ((*x).second.c_str());
}
}
}
} else {
switch(type) {
#ifdef WINDOWS_VST_SUPPORT
case 1: fst_close(vstfx); break;
#endif
#ifdef LXVST_SUPPORT
case 2: vstfx_close (vstfx); break;
#endif
default: assert(0); break;
}
}
#endif
}
}
/* A simple 'dummy' audiomaster callback which should be ok,
we will only be instantiating the plugin in order to get its info
*/
static intptr_t
simple_master_callback (AEffect *, int32_t opcode, int32_t, intptr_t, void *, float)
simple_master_callback (AEffect *, int32_t opcode, int32_t, intptr_t, void *ptr, float)
{
#if 0
static const char* can_do_strings[] = {
X_("supportShell"),
X_("shellCategory")
const char* vstfx_can_do_strings[] = {
"supportShell",
"shellCategory"
};
static const int can_do_string_count = sizeof (can_do_strings) / sizeof (char*);
static int current_loading_id = 0;
#endif
const int vstfx_can_do_string_count = 2;
if (opcode == audioMasterVersion) {
return 2;
}
#if 0
else if (opcode == audioMasterCanDo) {
for (int i = 0; i < can_do_string_count; i++) {
if (! strcmp(can_do_strings[i], (const char*)ptr)) {
for (int i = 0; i < vstfx_can_do_string_count; i++) {
if (! strcmp(vstfx_can_do_strings[i], (const char*)ptr)) {
return 1;
}
}
return 0;
}
else if (opcode == audioMasterCurrentId) {
return current_loading_id;
return vstfx_current_loading_id;
}
#endif
else {
return 0;
}
}
static bool
vstfx_get_info_from_file(char* dllpath, vector<VSTInfo*> *infos)
vstfx_get_info_from_file(const char* dllpath, vector<VSTInfo*> *infos)
{
FILE* infofile;
bool rv = false;
@@ -457,21 +582,111 @@ vstfx_get_info_from_file(char* dllpath, vector<VSTInfo*> *infos)
return rv;
}
void
vstfx_free_info (VSTInfo *info)
#ifdef LXVST_SUPPORT
static bool
vstfx_instantiate_and_get_info_lx (
const char* dllpath, vector<VSTInfo*> *infos, int uniqueID)
{
for (int i = 0; i < info->numParams; i++) {
free (info->ParamNames[i]);
free (info->ParamLabels[i]);
VSTHandle* h;
VSTState* vstfx;
if (!(h = vstfx_load(dllpath))) {
PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": load failed." << endmsg;
return false;
}
free (info->name);
free (info->creator);
free (info->Category);
free (info->ParamNames);
free (info->ParamLabels);
free (info);
vstfx_current_loading_id = uniqueID;
if (!(vstfx = vstfx_instantiate(h, simple_master_callback, 0))) {
vstfx_unload(h);
PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": instantiation failed." << endmsg;
return false;
}
vstfx_current_loading_id = 0;
vstfx_info_from_plugin(dllpath, vstfx, infos, 2);
vstfx_close (vstfx);
vstfx_unload (h);
return true;
}
#endif
#ifdef WINDOWS_VST_SUPPORT
static bool
vstfx_instantiate_and_get_info_fst (
const char* dllpath, vector<VSTInfo*> *infos, int uniqueID)
{
VSTHandle* h;
VSTState* vstfx;
if(!(h = fst_load(dllpath))) {
PBD::warning << "Cannot get VST information from " << dllpath << ": load failed." << endmsg;
return false;
}
vstfx_current_loading_id = uniqueID;
if(!(vstfx = fst_instantiate(h, simple_master_callback, 0))) {
fst_unload(&h);
vstfx_current_loading_id = 0;
PBD::warning << "Cannot get VST information from " << dllpath << ": instantiation failed." << endmsg;
return false;
}
vstfx_current_loading_id = 0;
vstfx_info_from_plugin(dllpath, vstfx, infos, 1);
fst_close(vstfx);
//fst_unload(&h); // XXX -> fst_close()
return true;
}
#endif
static vector<VSTInfo *> *
vstfx_get_info (const char* dllpath, int type)
{
FILE* infofile;
vector<VSTInfo*> *infos = new vector<VSTInfo*>;
// TODO check blacklist
// TODO pre-check file extension ?
if (vstfx_get_info_from_file(dllpath, infos)) {
PBD::info << "using cache for VST plugin '" << dllpath << "'" << endmsg;
return infos;
}
bool ok;
// TODO blacklist (in case instantiat fails)
switch (type) { // TODO use lib ardour's type
#ifdef WINDOWS_VST_SUPPORT
case 1: ok = vstfx_instantiate_and_get_info_fst(dllpath, infos, 0); break;
#endif
#ifdef LXVST_SUPPORT
case 2: ok = vstfx_instantiate_and_get_info_lx(dllpath, infos, 0); break;
#endif
default: ok = false;
}
if (!ok) {
PBD::warning << "Cannot get VST information for " << dllpath << "." << endmsg;
return infos;
}
// TODO un-blacklist
infofile = vstfx_infofile_for_write (dllpath);
if (!infofile) {
PBD::warning << "Cannot cache VST information for " << dllpath << ": cannot create new FST info file." << endmsg;
return infos;
} else {
vstfx_write_info_file (infofile, infos);
fclose (infofile);
}
return infos;
}
/* *** public API *** */
void
vstfx_free_info_list (vector<VSTInfo *> *infos)
@@ -483,106 +698,17 @@ vstfx_free_info_list (vector<VSTInfo *> *infos)
}
#ifdef LXVST_SUPPORT
/** Try to get plugin info - first by looking for a .fsi cache of the
data, and if that doesn't exist, load the plugin, get its data and
then cache it for future ref
*/
vector<VSTInfo *> *
vstfx_get_info_lx (char* dllpath)
{
FILE* infofile;
VSTHandle* h;
VSTState* vstfx;
vector<VSTInfo*> *infos = new vector<VSTInfo*>;
// TODO check blacklist
// TODO pre-check file extension ?
if (vstfx_get_info_from_file(dllpath, infos)) {
PBD::info << "using cache for LinuxVST plugin '" << dllpath << "'" << endmsg;
return infos;
}
if (!(h = vstfx_load(dllpath))) {
PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": load failed." << endmsg;
return infos;
}
if (!(vstfx = vstfx_instantiate(h, simple_master_callback, 0))) {
vstfx_unload(h);
PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": instantiation failed." << endmsg;
return infos;
}
infofile = vstfx_infofile_for_write (dllpath);
if (!infofile) {
vstfx_close(vstfx);
vstfx_unload(h);
PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": cannot create new FST info file." << endmsg;
return 0;
}
VSTInfo* info = vstfx_info_from_plugin (vstfx);
infos->push_back(info); //XXX
vstfx_write_info_file (infofile, infos);
fclose (infofile);
vstfx_close (vstfx);
vstfx_unload (h);
return infos;
return vstfx_get_info(dllpath, 2);
}
#endif
#ifdef WINDOWS_VST_SUPPORT
#include <fst.h>
vector<VSTInfo *> *
vstfx_get_info_fst (char* dllpath)
{
FILE* infofile;
VSTHandle* h;
VSTState* vstfx;
vector<VSTInfo*> *infos = new vector<VSTInfo*>;
// TODO check blacklist
// TODO pre-check file extension ?
if (vstfx_get_info_from_file(dllpath, infos)) {
PBD::info << "using cache for VST plugin '" << dllpath << "'" << endmsg;
return infos;
}
if(!(h = fst_load(dllpath))) {
PBD::warning << "Cannot get VST information from " << dllpath << ": load failed." << endmsg;
return infos;
}
if(!(vstfx = fst_instantiate(h, simple_master_callback, 0))) {
fst_unload(&h);
PBD::warning << "Cannot get VST information from " << dllpath << ": instantiation failed." << endmsg;
return infos;
}
infofile = vstfx_infofile_for_write (dllpath);
if (!infofile) {
fst_close(vstfx);
//fst_unload(&h); // XXX -> fst_close()
PBD::warning << "Cannot get VST information from " << dllpath << ": cannot create new FST info file." << endmsg;
return 0;
}
VSTInfo* info = vstfx_info_from_plugin(vstfx);
infos->push_back(info); //XXX
vstfx_write_info_file (infofile, infos);
fclose (infofile);
fst_close(vstfx);
//fst_unload(&h); // XXX -> fst_close()
return infos;
return vstfx_get_info(dllpath, 1);
}
#endif

View File

@@ -28,10 +28,10 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
WindowsVSTPlugin::WindowsVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h)
WindowsVSTPlugin::WindowsVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h, int unique_id)
: VSTPlugin (e, session, h)
{
Session::vst_current_loading_id = 0; // TODO
Session::vst_current_loading_id = unique_id;
if ((_state = fst_instantiate (_handle, Session::vst_callback, this)) == 0) {
throw failed_constructor();
}
@@ -74,7 +74,7 @@ WindowsVSTPluginInfo::load (Session& session)
if ((int) handle == -1) {
error << string_compose(_("VST: cannot load module from \"%1\""), path) << endmsg;
} else {
plugin.reset (new WindowsVSTPlugin (session.engine(), session, handle));
plugin.reset (new WindowsVSTPlugin (session.engine(), session, handle, PBD::atoi(unique_id)));
}
} else {
error << _("You asked ardour to not use any VST plugins") << endmsg;