diff options
author | Robin Gareus <robin@gareus.org> | 2014-02-23 21:11:53 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2014-02-23 21:11:53 +0100 |
commit | 2e0c98c48903c67fcef7abd77a7c53f3f2d41e2f (patch) | |
tree | 5385a3ce65c4dcc1080d5ff91b5da6fcb934d876 /libs/ardour | |
parent | fac93f7a82833b094c36164d733bb3c352a7223e (diff) |
remaining bits for VST-shell plugin support ..and more VST rework
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/lxvst_plugin.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/vestige/aeffectx.h | 59 | ||||
-rw-r--r-- | libs/ardour/ardour/vst_info_file.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/windows_vst_plugin.h | 2 | ||||
-rw-r--r-- | libs/ardour/lxvst_plugin.cc | 9 | ||||
-rw-r--r-- | libs/ardour/vst_info_file.cc | 336 | ||||
-rw-r--r-- | libs/ardour/windows_vst_plugin.cc | 6 |
7 files changed, 292 insertions, 123 deletions
diff --git a/libs/ardour/ardour/lxvst_plugin.h b/libs/ardour/ardour/lxvst_plugin.h index f1a50b2f30..cc6f507144 100644 --- a/libs/ardour/ardour/lxvst_plugin.h +++ b/libs/ardour/ardour/lxvst_plugin.h @@ -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 (); diff --git a/libs/ardour/ardour/vestige/aeffectx.h b/libs/ardour/ardour/vestige/aeffectx.h index 2dca9f26be..5b7d69c411 100644 --- a/libs/ardour/ardour/vestige/aeffectx.h +++ b/libs/ardour/ardour/vestige/aeffectx.h @@ -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; diff --git a/libs/ardour/ardour/vst_info_file.h b/libs/ardour/ardour/vst_info_file.h index ac7167bc90..21e9d19c65 100644 --- a/libs/ardour/ardour/vst_info_file.h +++ b/libs/ardour/ardour/vst_info_file.h @@ -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 diff --git a/libs/ardour/ardour/windows_vst_plugin.h b/libs/ardour/ardour/windows_vst_plugin.h index ee4850dc05..17b72ac8da 100644 --- a/libs/ardour/ardour/windows_vst_plugin.h +++ b/libs/ardour/ardour/windows_vst_plugin.h @@ -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 (); diff --git a/libs/ardour/lxvst_plugin.cc b/libs/ardour/lxvst_plugin.cc index 6e30e0c443..c3074d65ad 100644 --- a/libs/ardour/lxvst_plugin.cc +++ b/libs/ardour/lxvst_plugin.cc @@ -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 { diff --git a/libs/ardour/vst_info_file.cc b/libs/ardour/vst_info_file.cc index 50d94850d6..7b9b0855bd 100644 --- a/libs/ardour/vst_info_file.cc +++ b/libs/ardour/vst_info_file.cc @@ -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) { @@ -85,6 +102,22 @@ read_int (FILE* fp, int* n) } 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) { for (vector<VSTInfo *>::iterator i = infos->begin(); i != infos->end(); ++i) { @@ -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,94 +582,70 @@ vstfx_get_info_from_file(char* dllpath, vector<VSTInfo*> *infos) return rv; } -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); -} - -void -vstfx_free_info_list (vector<VSTInfo *> *infos) -{ - for (vector<VSTInfo *>::iterator i = infos->begin(); i != infos->end(); ++i) { - vstfx_free_info(*i); - } - delete 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) +static bool +vstfx_instantiate_and_get_info_lx ( + const char* dllpath, vector<VSTInfo*> *infos, int uniqueID) { - 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; + return false; } + 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 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; + return false; } - VSTInfo* info = vstfx_info_from_plugin (vstfx); - infos->push_back(info); //XXX + vstfx_current_loading_id = 0; - vstfx_write_info_file (infofile, infos); - fclose (infofile); + vstfx_info_from_plugin(dllpath, vstfx, infos, 2); vstfx_close (vstfx); vstfx_unload (h); - return infos; + return true; } #endif #ifdef WINDOWS_VST_SUPPORT -#include <fst.h> - -vector<VSTInfo *> * -vstfx_get_info_fst (char* dllpath) +static bool +vstfx_instantiate_and_get_info_fst ( + const char* dllpath, vector<VSTInfo*> *infos, int uniqueID) { - FILE* infofile; 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 @@ -555,34 +656,59 @@ vstfx_get_info_fst (char* dllpath) return infos; } - if(!(h = fst_load(dllpath))) { - PBD::warning << "Cannot get VST information from " << dllpath << ": load failed." << 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(!(vstfx = fst_instantiate(h, simple_master_callback, 0))) { - fst_unload(&h); - PBD::warning << "Cannot get VST information from " << dllpath << ": instantiation failed." << endmsg; + if (!ok) { + PBD::warning << "Cannot get VST information for " << dllpath << "." << endmsg; return infos; } - infofile = vstfx_infofile_for_write (dllpath); + // TODO un-blacklist + 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; + 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; +} - VSTInfo* info = vstfx_info_from_plugin(vstfx); - infos->push_back(info); //XXX +/* *** public API *** */ - vstfx_write_info_file (infofile, infos); - fclose (infofile); +void +vstfx_free_info_list (vector<VSTInfo *> *infos) +{ + for (vector<VSTInfo *>::iterator i = infos->begin(); i != infos->end(); ++i) { + vstfx_free_info(*i); + } + delete infos; +} - fst_close(vstfx); - //fst_unload(&h); // XXX -> fst_close() - return infos; +#ifdef LXVST_SUPPORT +vector<VSTInfo *> * +vstfx_get_info_lx (char* dllpath) +{ + return vstfx_get_info(dllpath, 2); +} +#endif + +#ifdef WINDOWS_VST_SUPPORT +vector<VSTInfo *> * +vstfx_get_info_fst (char* dllpath) +{ + return vstfx_get_info(dllpath, 1); } #endif diff --git a/libs/ardour/windows_vst_plugin.cc b/libs/ardour/windows_vst_plugin.cc index e8afb67c1d..03170e0d04 100644 --- a/libs/ardour/windows_vst_plugin.cc +++ b/libs/ardour/windows_vst_plugin.cc @@ -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; |