Push most of LXVSTPlugin and WindowsVSTPlugin up to VSTPlugin parent.

git-svn-id: svn://localhost/ardour2/branches/3.0@10773 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2011-11-22 15:14:41 +00:00
parent 84f2049023
commit d1226a8628
9 changed files with 68 additions and 1574 deletions

View File

@ -45,10 +45,10 @@ LXVSTPluginUI::LXVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_
{ {
create_preset_store (); create_preset_store ();
vstfx_run_editor (lxvst->vstfx()); vstfx_run_editor (lxvst->state ());
if (lxvst->vstfx()->current_program != -1) { if (lxvst->state()->current_program != -1) {
lxvst_preset_combo.set_active (lxvst->vstfx()->current_program); lxvst_preset_combo.set_active (lxvst->state()->current_program);
} else { } else {
lxvst_preset_combo.set_active (0); lxvst_preset_combo.set_active (0);
} }
@ -104,17 +104,17 @@ LXVSTPluginUI::resize_callback()
/*We could maybe use this to resize the plugin GTK parent window /*We could maybe use this to resize the plugin GTK parent window
if required*/ if required*/
if(lxvst->vstfx()->want_resize) if (lxvst->state()->want_resize) {
{ int new_height = lxvst->state()->height;
int new_height = lxvst->vstfx()->height; int new_width = lxvst->state()->width;
int new_width = lxvst->vstfx()->width;
void* gtk_parent_window = lxvst->vstfx()->extra_data; void* gtk_parent_window = lxvst->state()->extra_data;
if(gtk_parent_window) if (gtk_parent_window) {
((Gtk::Window*)gtk_parent_window)->resize(new_width, new_height + LXVST_H_FIDDLE); ((Gtk::Window*)gtk_parent_window)->resize(new_width, new_height + LXVST_H_FIDDLE);
}
lxvst->vstfx()->want_resize = 0; lxvst->state()->want_resize = 0;
} }
} }
@ -130,7 +130,7 @@ LXVSTPluginUI::preset_chosen ()
{ {
// we can't dispatch directly here, too many plugins only expects one GUI thread. // we can't dispatch directly here, too many plugins only expects one GUI thread.
lxvst->vstfx()->want_program = lxvst_preset_combo.get_active_row_number (); lxvst->state()->want_program = lxvst_preset_combo.get_active_row_number ();
socket.grab_focus (); socket.grab_focus ();
} }
@ -144,13 +144,13 @@ LXVSTPluginUI::get_preferred_height ()
and we can't realise it until we have told it how big we would like it to be and we can't realise it until we have told it how big we would like it to be
which we can't do until it is realised etc*/ which we can't do until it is realised etc*/
return (lxvst->vstfx()->height) + LXVST_H_FIDDLE; //May not be 40 for all screen res etc return (lxvst->state()->height) + LXVST_H_FIDDLE; //May not be 40 for all screen res etc
} }
int int
LXVSTPluginUI::get_preferred_width () LXVSTPluginUI::get_preferred_width ()
{ {
return lxvst->vstfx()->width; return lxvst->state()->width;
} }
int int
@ -167,12 +167,12 @@ LXVSTPluginUI::package (Gtk::Window& win)
/* this assumes that the window's owner understands the XEmbed protocol. */ /* this assumes that the window's owner understands the XEmbed protocol. */
socket.add_id (vstfx_get_XID (lxvst->vstfx())); socket.add_id (vstfx_get_XID (lxvst->state ()));
vstfx_move_window_into_view (lxvst->vstfx()); vstfx_move_window_into_view (lxvst->state ());
lxvst->vstfx()->extra_data = (void*)(&win); lxvst->state()->extra_data = (void*)(&win);
lxvst->vstfx()->want_resize = 0; lxvst->state()->want_resize = 0;
return 0; return 0;
} }
@ -226,7 +226,7 @@ LXVSTPluginUI::forward_key_event (GdkEventKey* ev)
void void
LXVSTPluginUI::create_preset_store () LXVSTPluginUI::create_preset_store ()
{ {
VSTState* vstfx = lxvst->vstfx(); VSTState* vstfx = lxvst->state ();
int vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, NULL, 0.0f); int vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, NULL, 0.0f);

View File

@ -35,7 +35,7 @@ WindowsVSTPluginUI::WindowsVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boos
: PlugUIBase (pi), : PlugUIBase (pi),
vst (vp) vst (vp)
{ {
fst_run_editor (vst->fst()); fst_run_editor (vst->state());
preset_box.set_spacing (6); preset_box.set_spacing (6);
preset_box.set_border_width (6); preset_box.set_border_width (6);
@ -69,13 +69,13 @@ WindowsVSTPluginUI::preset_selected ()
int int
WindowsVSTPluginUI::get_preferred_height () WindowsVSTPluginUI::get_preferred_height ()
{ {
return vst->fst()->height; return vst->state()->height;
} }
int int
WindowsVSTPluginUI::get_preferred_width () WindowsVSTPluginUI::get_preferred_width ()
{ {
return vst->fst()->width; return vst->state()->width;
} }
int int
@ -89,9 +89,9 @@ WindowsVSTPluginUI::package (Gtk::Window& win)
this assumes that the window's owner understands the XEmbed protocol. this assumes that the window's owner understands the XEmbed protocol.
*/ */
socket.add_id (fst_get_XID (vst->fst())); socket.add_id (fst_get_XID (vst->state ()));
fst_move_window_into_view (vst->fst()); fst_move_window_into_view (vst->state ());
return 0; return 0;
} }
@ -140,7 +140,7 @@ WindowsVSTPluginUI::forward_key_event (GdkEventKey* ev)
{ {
if (ev->type == GDK_KEY_PRESS) { if (ev->type == GDK_KEY_PRESS) {
VSTState* fst = vst->fst (); VSTState* fst = vst->state ();
pthread_mutex_lock (&fst->lock); pthread_mutex_lock (&fst->lock);
if (fst->n_pending_keys == (sizeof (fst->pending_keys) * sizeof (VSTKey))) { if (fst->n_pending_keys == (sizeof (fst->pending_keys) * sizeof (VSTKey))) {
@ -204,6 +204,6 @@ windows_vst_gui_init (int *argc, char **argv[])
wine_error_handler = XSetErrorHandler (NULL); wine_error_handler = XSetErrorHandler (NULL);
gtk_init (argc, argv); gtk_init (argc, argv);
the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default()); the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default());
gtk_error_handler = XSetErrorHandler( fst_xerror_handler ); gtk_error_handler = XSetErrorHandler (fst_xerror_handler);
} }

View File

@ -20,92 +20,24 @@
#ifndef __ardour_lxvst_plugin_h__ #ifndef __ardour_lxvst_plugin_h__
#define __ardour_lxvst_plugin_h__ #define __ardour_lxvst_plugin_h__
#include <list> #include "ardour/vst_plugin.h"
#include <map>
#include <set>
#include <vector>
#include <string>
#include <dlfcn.h>
#include "pbd/stateful.h"
#include "ardour/plugin.h"
struct _VSTHandle; struct _VSTHandle;
struct _VSTState;
typedef struct _VSTHandle VSTHandle; typedef struct _VSTHandle VSTHandle;
typedef struct _VSTState VSTState;
struct _AEffect;
typedef struct _AEffect AEffect;
namespace ARDOUR { namespace ARDOUR {
class AudioEngine; class AudioEngine;
class Session; class Session;
class LXVSTPlugin : public ARDOUR::Plugin class LXVSTPlugin : public VSTPlugin
{ {
public: public:
LXVSTPlugin (ARDOUR::AudioEngine&, ARDOUR::Session&, VSTHandle *); LXVSTPlugin (AudioEngine &, Session &, VSTHandle *);
LXVSTPlugin (const LXVSTPlugin &); LXVSTPlugin (const LXVSTPlugin &);
~LXVSTPlugin (); ~LXVSTPlugin ();
/* Plugin interface */ std::string state_node_name () const { return "lxvst"; }
std::string unique_id() const;
const char * label() const;
const char * name() const;
const char * maker() const;
uint32_t parameter_count() const;
float default_value (uint32_t port);
framecnt_t signal_latency() const;
void set_parameter (uint32_t port, float val);
float get_parameter (uint32_t port) const;
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
std::set<Evoral::Parameter> automatable() const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;
void activate ();
void deactivate ();
int set_block_size (pframes_t);
int connect_and_run (BufferSet&,
ChanMapping in, ChanMapping out,
pframes_t nframes, framecnt_t offset);
std::string describe_parameter (Evoral::Parameter);
std::string state_node_name() const { return "lxvst"; }
void print_parameter (uint32_t, char*, uint32_t len) const;
bool parameter_is_audio(uint32_t) const { return false; }
bool parameter_is_control(uint32_t) const { return true; }
bool parameter_is_input(uint32_t) const { return true; }
bool parameter_is_output(uint32_t) const { return false; }
bool load_preset (PresetRecord);
int first_user_preset_index () const;
bool has_editor () const;
int set_state (XMLNode const &, int);
AEffect * plugin () const { return _plugin; }
VSTState * vstfx () const { return _vstfx; }
private:
void do_remove_preset (std::string name);
std::string do_save_preset (std::string name);
gchar* get_chunk (bool) const;
int set_chunk (gchar const *, bool);
XMLTree * presets_tree () const;
std::string presets_file () const;
void find_presets ();
bool load_user_preset (PresetRecord);
bool load_plugin_preset (PresetRecord);
void add_state (XMLNode *) const;
VSTHandle * handle;
VSTState * _vstfx;
AEffect * _plugin;
bool been_resumed;
}; };
class LXVSTPluginInfo : public PluginInfo class LXVSTPluginInfo : public PluginInfo
@ -117,8 +49,6 @@ class LXVSTPluginInfo : public PluginInfo
PluginPtr load (Session& session); PluginPtr load (Session& session);
}; };
typedef boost::shared_ptr<LXVSTPluginInfo> LXVSTPluginInfoPtr;
} // namespace ARDOUR } // namespace ARDOUR
#endif /* __ardour_lxvst_plugin_h__ */ #endif /* __ardour_lxvst_plugin_h__ */

View File

@ -20,105 +20,35 @@
#ifndef __ardour_windows_vst_plugin_h__ #ifndef __ardour_windows_vst_plugin_h__
#define __ardour_windows_vst_plugin_h__ #define __ardour_windows_vst_plugin_h__
#include <list> #include "ardour/vst_plugin.h"
#include <map>
#include <set>
#include <vector>
#include <string>
#include <dlfcn.h>
#include "pbd/stateful.h"
#include "ardour/plugin.h"
struct _VSTState;
typedef struct _VSTState VSTState;
struct _AEffect;
typedef struct _AEffect AEffect;
struct _VSTHandle; struct _VSTHandle;
typedef struct _VSTHandle VSTHandle; typedef struct _VSTHandle VSTHandle;
namespace ARDOUR { namespace ARDOUR {
class AudioEngine; class AudioEngine;
class Session; class Session;
class WindowsVSTPlugin : public ARDOUR::Plugin class WindowsVSTPlugin : public VSTPlugin
{ {
public: public:
WindowsVSTPlugin (ARDOUR::AudioEngine&, ARDOUR::Session&, VSTHandle *); WindowsVSTPlugin (AudioEngine &, Session &, VSTHandle *);
WindowsVSTPlugin (const WindowsVSTPlugin &); WindowsVSTPlugin (const WindowsVSTPlugin &);
~WindowsVSTPlugin (); ~WindowsVSTPlugin ();
/* Plugin interface */ std::string state_node_name () const { return "windows-vst"; }
std::string unique_id() const;
const char * label() const;
const char * name() const;
const char * maker() const;
uint32_t parameter_count() const;
float default_value (uint32_t port);
framecnt_t signal_latency() const;
void set_parameter (uint32_t port, float val);
float get_parameter (uint32_t port) const;
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
std::set<Evoral::Parameter> automatable() const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;
void activate ();
void deactivate ();
int set_block_size (pframes_t);
int connect_and_run (BufferSet&,
ChanMapping in, ChanMapping out,
pframes_t nframes, framecnt_t offset);
std::string describe_parameter (Evoral::Parameter);
std::string state_node_name() const { return "windows-vst"; }
void print_parameter (uint32_t, char*, uint32_t len) const;
bool parameter_is_audio(uint32_t i) const { return false; }
bool parameter_is_control(uint32_t i) const { return true; }
bool parameter_is_input(uint32_t i) const { return true; }
bool parameter_is_output(uint32_t i) const { return false; }
bool load_preset (PresetRecord);
int first_user_preset_index () const;
bool has_editor () const;
int set_state (XMLNode const &, int);
AEffect * plugin () const { return _plugin; }
VSTState * fst () const { return _fst; }
private:
void do_remove_preset (std::string name);
std::string do_save_preset (std::string name);
gchar* get_chunk (bool) const;
int set_chunk (gchar const *, bool);
XMLTree * presets_tree () const;
std::string presets_file () const;
void find_presets ();
bool load_user_preset (PresetRecord);
bool load_plugin_preset (PresetRecord);
void add_state (XMLNode *) const;
VSTHandle* handle;
VSTState* _fst;
AEffect* _plugin;
bool been_resumed;
}; };
class WindowsVSTPluginInfo : public PluginInfo class WindowsVSTPluginInfo : public PluginInfo
{ {
public: public:
WindowsVSTPluginInfo (); WindowsVSTPluginInfo ();
~WindowsVSTPluginInfo () {} ~WindowsVSTPluginInfo () {}
PluginPtr load (Session& session); PluginPtr load (Session& session);
}; };
typedef boost::shared_ptr<WindowsVSTPluginInfo> WindowsVSTPluginInfoPtr;
} // namespace ARDOUR } // namespace ARDOUR
#endif /* __ardour_vst_plugin_h__ */ #endif /* __ardour_vst_plugin_h__ */

View File

@ -17,616 +17,44 @@
*/ */
/**********************************************************************/ #include "ardour/vstfx.h"
/*Native linuxVST (LXVST) variant of vst_plugin.cc etc */
/**********************************************************************/
#include <algorithm>
#include <vector>
#include <string>
#include <cctype>
#include <cstdlib>
#include <cstdio> // so libraptor doesn't complain
#include <cmath>
#include <dirent.h>
#include <cstring> // for memmove
#include <sys/stat.h>
#include <cerrno>
#include <glibmm/miscutils.h>
#include <lrdf.h>
/*Include for the new native vst engine - vstfx.h*/
#include <stdint.h>
#include <ardour/vstfx.h>
#include "pbd/compose.h"
#include "pbd/error.h"
#include "pbd/pathscanner.h"
#include "pbd/xml++.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/lxvst_plugin.h" #include "ardour/lxvst_plugin.h"
#include "ardour/buffer_set.h"
#include "ardour/audio_buffer.h"
#include "ardour/midi_buffer.h"
#include "pbd/stl_delete.h"
#include "i18n.h" #include "i18n.h"
#include <locale.h>
using namespace std; using namespace std;
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
using std::min;
using std::max;
LXVSTPlugin::LXVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h) LXVSTPlugin::LXVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h)
: Plugin (e, session) : VSTPlugin (e, session, h)
{ {
handle = h; /* Instantiate the plugin and return a VSTState* */
/*Instantiate the plugin and return a VSTFX* */ if ((_state = vstfx_instantiate (_handle, Session::lxvst_callback, this)) == 0) {
if ((_vstfx = vstfx_instantiate (handle, Session::lxvst_callback, this)) == 0) {
throw failed_constructor(); throw failed_constructor();
} }
/* Call into vstfx to get a pointer to the instance of the VST plugin*/ set_plugin (_state->plugin);
_plugin = _vstfx->plugin;
_plugin->user = this;
/* set rate and blocksize */
_plugin->dispatcher (_plugin, effSetSampleRate, 0, 0, NULL, (float) session.frame_rate());
_plugin->dispatcher (_plugin, effSetBlockSize, 0, session.get_block_size(), NULL, 0.0f);
/* set program to zero */
_plugin->dispatcher (_plugin, effSetProgram, 0, 0, NULL, 0.0f);
// Plugin::setup_controls ();
} }
LXVSTPlugin::LXVSTPlugin (const LXVSTPlugin &other) LXVSTPlugin::LXVSTPlugin (const LXVSTPlugin &other)
: Plugin (other) : VSTPlugin (other)
{ {
handle = other.handle; _handle = other._handle;
if ((_vstfx = vstfx_instantiate (handle, Session::lxvst_callback, this)) == 0) { if ((_state = vstfx_instantiate (_handle, Session::lxvst_callback, this)) == 0) {
throw failed_constructor(); throw failed_constructor();
} }
_plugin = _vstfx->plugin; _plugin = _state->plugin;
// Plugin::setup_controls (); // Plugin::setup_controls ();
} }
LXVSTPlugin::~LXVSTPlugin () LXVSTPlugin::~LXVSTPlugin ()
{ {
deactivate (); vstfx_close (_state);
vstfx_close (_vstfx);
}
int
LXVSTPlugin::set_block_size (pframes_t nframes)
{
deactivate ();
_plugin->dispatcher (_plugin, effSetBlockSize, 0, nframes, NULL, 0.0f);
activate ();
return 0;
}
float
LXVSTPlugin::default_value (uint32_t)
{
return 0;
}
void
LXVSTPlugin::set_parameter (uint32_t which, float val)
{
_plugin->setParameter (_plugin, which, val);
if (_vstfx->want_program == -1 && _vstfx->want_chunk == 0) {
/* Heinous hack: Plugin::set_parameter below updates the `modified' status of the
current preset, but if _vstfx->want_program is not -1 then there is a preset
setup pending or in progress, which we don't want any `modified' updates
to happen for. So we only do this if _vstfx->want_program is -1.
*/
Plugin::set_parameter (which, val);
}
}
float
LXVSTPlugin::get_parameter (uint32_t which) const
{
return _plugin->getParameter (_plugin, which);
}
uint32_t
LXVSTPlugin::nth_parameter (uint32_t n, bool& ok) const
{
ok = true;
return n;
}
/** Get VST chunk as base64-encoded data.
* @param single true for single program, false for all programs.
* @return 0-terminated base64-encoded data; must be passed to g_free () by caller.
*/
gchar *LXVSTPlugin::get_chunk (bool single) const
{
guchar* data;
int32_t data_size = _plugin->dispatcher (_plugin, 23 /* effGetChunk */, single ? 1 : 0, 0, &data, 0);
if (data_size == 0) {
return 0;
}
return g_base64_encode (data, data_size);
}
/** Set VST chunk from base64-encoded data.
* @param 0-terminated base64-encoded data.
* @param single true for single program, false for all programs.
* @return 0 on success, non-0 on failure
*/
int
LXVSTPlugin::set_chunk (gchar const * data, bool single)
{
gsize size = 0;
guchar* raw_data = g_base64_decode (data, &size);
int const r = _plugin->dispatcher (_plugin, 24 /* effSetChunk */, single ? 1 : 0, size, raw_data, 0);
g_free (raw_data);
return r;
}
void
LXVSTPlugin::add_state (XMLNode* root) const
{
LocaleGuard lg (X_("POSIX"));
if (_vstfx->current_program != -1) {
char buf[32];
snprintf (buf, sizeof (buf), "%d", _vstfx->current_program);
root->add_property ("current-program", buf);
}
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
gchar* data = get_chunk (false);
if (data == 0) {
return;
}
/* store information */
XMLNode* chunk_node = new XMLNode (X_("chunk"));
chunk_node->add_content (data);
g_free (data);
root->add_child_nocopy (*chunk_node);
} else {
XMLNode* parameters = new XMLNode ("parameters");
for (int32_t n = 0; n < _plugin->numParams; ++n) {
char index[64];
char val[32];
snprintf (index, sizeof (index), "param_%d", n);
snprintf (val, sizeof (val), "%.12g", _plugin->getParameter (_plugin, n));
parameters->add_property (index, val);
}
root->add_child_nocopy (*parameters);
}
}
int
LXVSTPlugin::set_state (const XMLNode& node, int version)
{
LocaleGuard lg (X_("POSIX"));
if (node.name() != state_node_name()) {
error << _("Bad node sent to VSTPlugin::set_state") << endmsg;
return 0;
}
const XMLProperty* prop;
if ((prop = node.property ("current-program")) != 0) {
_vstfx->want_program = atoi (prop->value().c_str());
}
XMLNode* child;
int ret = -1;
if ((child = find_named_node (node, X_("chunk"))) != 0) {
XMLPropertyList::const_iterator i;
XMLNodeList::const_iterator n;
for (n = child->children ().begin (); n != child->children ().end (); ++n) {
if ((*n)->is_content ()) {
/* XXX: this may be dubious for the same reasons that we delay
execution of load_preset.
*/
ret = set_chunk ((*n)->content().c_str(), false);
}
}
} else if ((child = find_named_node (node, X_("parameters"))) != 0) {
XMLPropertyList::const_iterator i;
for (i = child->properties().begin(); i != child->properties().end(); ++i) {
int32_t param;
float val;
sscanf ((*i)->name().c_str(), "param-%d", &param); //This was param_%d (from vst_plugin) which caused all sorts of odd behaviour
sscanf ((*i)->value().c_str(), "%f", &val);
_plugin->setParameter (_plugin, param, val);
}
/* program number is not knowable */
_vstfx->current_program = -1;
ret = 0;
}
Plugin::set_state (node, version);
return ret;
}
int
LXVSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
{
desc.min_unbound = false;
desc.max_unbound = false;
/* old style */
char label[64];
label[0] = '\0';
_plugin->dispatcher (_plugin, effGetParamName, which, 0, label, 0);
desc.label = label;
desc.integer_step = false;
desc.lower = 0.0f;
desc.upper = 1.0f;
desc.step = 0.01f;
desc.smallstep = 0.005f;
desc.largestep = 0.1f;
desc.toggled = false;
desc.logarithmic = false;
desc.sr_dependent = false;
return 0;
}
bool
LXVSTPlugin::load_preset (PresetRecord r)
{
bool s;
if (r.user) {
s = load_user_preset (r);
}
else {
s = load_plugin_preset (r);
}
if (s) {
Plugin::load_preset (r);
}
return s;
}
bool
LXVSTPlugin::load_plugin_preset (PresetRecord r)
{
/* This is a plugin-provided preset.
We can't dispatch directly here; too many plugins expects only one GUI thread.
*/
/* Extract the index of this preset from the URI */
int id;
int index;
#ifndef NDEBUG
int const p = sscanf (r.uri.c_str(), "VST:%d:%d", &id, &index);
assert (p == 2);
#else
sscanf (r.uri.c_str(), "VST:%d:%d", &id, &index);
#endif
_vstfx->want_program = index;
return true;
}
bool
LXVSTPlugin::load_user_preset (PresetRecord r)
{
/* This is a user preset; we load it, and this code also knows about the
non-direct-dispatch thing.
*/
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return false;
}
XMLNode* root = t->root ();
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
XMLProperty* label = (*i)->property (X_("label"));
assert (label);
if (label->value() != r.label) {
continue;
}
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
/* Load a user preset chunk from our XML file and send it via a circuitous route to the plugin */
if (_vstfx->wanted_chunk) {
g_free (_vstfx->wanted_chunk);
}
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j) {
if ((*j)->is_content ()) {
/* we can't dispatch directly here; too many plugins expect only one GUI thread */
gsize size = 0;
guchar* raw_data = g_base64_decode ((*j)->content().c_str(), &size);
_vstfx->wanted_chunk = raw_data;
_vstfx->wanted_chunk_size = size;
_vstfx->want_chunk = 1;
return true;
}
}
return false;
}
else {
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j) {
if ((*j)->name() == X_("Parameter")) {
XMLProperty* index = (*j)->property (X_("index"));
XMLProperty* value = (*j)->property (X_("value"));
assert (index);
assert (value);
set_parameter (atoi (index->value().c_str()), atof (value->value().c_str ()));
}
}
return true;
}
}
return false;
}
string
LXVSTPlugin::do_save_preset (string name)
{
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return "";
}
XMLNode* p = 0;
/* XXX: use of _presets.size() + 1 for the unique ID here is dubious at best */
string const uri = string_compose (X_("VST:%1:%2"), unique_id (), _presets.size() + 1);
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
p = new XMLNode (X_("ChunkPreset"));
p->add_property (X_("uri"), uri);
p->add_property (X_("label"), name);
gchar* data = get_chunk (true);
p->add_content (string (data));
g_free (data);
}
else {
p = new XMLNode (X_("Preset"));
p->add_property (X_("uri"), uri);
p->add_property (X_("label"), name);
for (uint32_t i = 0; i < parameter_count(); ++i) {
if (parameter_is_input (i)) {
XMLNode* c = new XMLNode (X_("Parameter"));
c->add_property (X_("index"), string_compose ("%1", i));
c->add_property (X_("value"), string_compose ("%1", get_parameter (i)));
p->add_child_nocopy (*c);
}
}
}
t->root()->add_child_nocopy (*p);
sys::path f = ARDOUR::user_config_directory ();
f /= "presets";
f /= presets_file ();
t->write (f.to_string ());
return uri;
}
void
LXVSTPlugin::do_remove_preset (string name)
{
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return;
}
t->root()->remove_nodes_and_delete (X_("label"), name);
sys::path f = ARDOUR::user_config_directory ();
f /= "presets";
f /= presets_file ();
t->write (f.to_string ());
}
string
LXVSTPlugin::describe_parameter (Evoral::Parameter param)
{
char name[64] = "Unkown";
_plugin->dispatcher (_plugin, effGetParamName, param.id(), 0, name, 0);
return name;
}
framecnt_t
LXVSTPlugin::signal_latency () const
{
if (_user_latency) {
return _user_latency;
}
return *((int32_t *) (((char *) &_plugin->flags) + 12)); /* initialDelay */
}
set<Evoral::Parameter>
LXVSTPlugin::automatable () const
{
set<Evoral::Parameter> ret;
for (uint32_t i = 0; i < parameter_count(); ++i) {
ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i));
}
return ret;
}
int
LXVSTPlugin::connect_and_run (BufferSet& bufs,
ChanMapping in_map, ChanMapping out_map,
pframes_t nframes, framecnt_t offset)
{
Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset);
float *ins[_plugin->numInputs];
float *outs[_plugin->numOutputs];
int32_t i;
const uint32_t nbufs = bufs.count().n_audio();
int in_index = 0;
for (i = 0; i < (int32_t) _plugin->numInputs; ++i) {
ins[i] = bufs.get_audio(min((uint32_t) in_index, nbufs - 1)).data() + offset;
in_index++;
}
int out_index = 0;
for (i = 0; i < (int32_t) _plugin->numOutputs; ++i) {
outs[i] = bufs.get_audio(min((uint32_t) out_index, nbufs - 1)).data() + offset;
out_index++;
}
if (bufs.count().n_midi() > 0) {
VstEvents* v = bufs.get_vst_midi (0);
_plugin->dispatcher (_plugin, effProcessEvents, 0, 0, v, 0);
}
/* we already know it can support processReplacing */
_plugin->processReplacing (_plugin, ins, outs, nframes);
return 0;
}
void
LXVSTPlugin::deactivate ()
{
_plugin->dispatcher (_plugin, effMainsChanged, 0, 0, NULL, 0.0f);
}
void
LXVSTPlugin::activate ()
{
_plugin->dispatcher (_plugin, effMainsChanged, 0, 1, NULL, 0.0f);
}
string
LXVSTPlugin::unique_id() const
{
char buf[32];
snprintf (buf, sizeof (buf), "%d", _plugin->uniqueID);
return string (buf);
}
const char *
LXVSTPlugin::name () const
{
return handle->name;
}
const char *
LXVSTPlugin::maker () const
{
return _info->creator.c_str();
}
const char *
LXVSTPlugin::label () const
{
return handle->name;
}
uint32_t
LXVSTPlugin::parameter_count() const
{
return _plugin->numParams;
}
bool
LXVSTPlugin::has_editor () const
{
return _plugin->flags & effFlagsHasEditor;
}
void
LXVSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t /*len*/) const
{
char *first_nonws;
_plugin->dispatcher (_plugin, 7 /* effGetParamDisplay */, param, 0, buf, 0);
if (buf[0] == '\0') {
return;
}
first_nonws = buf;
while (*first_nonws && isspace (*first_nonws)) {
first_nonws++;
}
if (*first_nonws == '\0') {
return;
}
memmove (buf, first_nonws, strlen (buf) - (first_nonws - buf) + 1);
} }
PluginPtr PluginPtr
@ -661,92 +89,6 @@ LXVSTPluginInfo::load (Session& session)
} }
} }
void
LXVSTPlugin::find_presets ()
{
/* Built-in presets */
int const vst_version = _plugin->dispatcher (_plugin, effGetVstVersion, 0, 0, NULL, 0);
for (int i = 0; i < _plugin->numPrograms; ++i) {
PresetRecord r (string_compose (X_("LXVST:%1:%2"), unique_id (), i), "", false);
if (vst_version >= 2) {
char buf[256];
if (_plugin->dispatcher (_plugin, 29, i, 0, buf, 0) == 1) {
r.label = buf;
} else {
r.label = string_compose (_("Preset %1"), i);
}
} else {
r.label = string_compose (_("Preset %1"), i);
}
_presets.insert (make_pair (r.uri, r));
}
/* User presets from our XML file */
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t) {
XMLNode* root = t->root ();
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
XMLProperty* uri = (*i)->property (X_("uri"));
XMLProperty* label = (*i)->property (X_("label"));
assert (uri);
assert (label);
PresetRecord r (uri->value(), label->value(), true);
_presets.insert (make_pair (r.uri, r));
}
}
}
/** @return XMLTree with our user presets; could be a new one if no existing
* one was found, or 0 if one was present but badly-formatted.
*/
XMLTree *
LXVSTPlugin::presets_tree () const
{
XMLTree* t = new XMLTree;
sys::path p = ARDOUR::user_config_directory ();
p /= "presets";
if (!is_directory (p)) {
create_directory (p);
}
p /= presets_file ();
if (!exists (p)) {
t->set_root (new XMLNode (X_("LXVSTPresets")));
return t;
}
t->set_filename (p.to_string ());
if (!t->read ()) {
delete t;
return 0;
}
return t;
}
/** @return Index of the first user preset in our lists */
int
LXVSTPlugin::first_user_preset_index () const
{
return _plugin->numPrograms;
}
string LXVSTPlugin::presets_file () const
{
return string_compose ("lxvst-%1", unique_id ());
}
LXVSTPluginInfo::LXVSTPluginInfo() LXVSTPluginInfo::LXVSTPluginInfo()
{ {
type = ARDOUR::LXVST; type = ARDOUR::LXVST;

View File

@ -25,12 +25,12 @@
#include <stdbool.h> #include <stdbool.h>
#include <cstdio> #include <cstdio>
#include <stdint.h> #include <stdint.h>
#include <ardour/vstfx.h> #include "ardour/vstfx.h"
#include <ardour/vestige/aeffectx.h> #include "ardour/vestige/aeffectx.h"
#include <ardour/session.h> #include "ardour/session.h"
#include <ardour/tempo.h> #include "ardour/tempo.h"
#include <ardour/lxvst_plugin.h> #include "ardour/lxvst_plugin.h"
#include "i18n.h" #include "i18n.h"
@ -191,7 +191,7 @@ intptr_t Session::lxvst_callback (AEffect* effect,
SHOW_CALLBACK ("amc: audioMasterNeedIdle\n"); SHOW_CALLBACK ("amc: audioMasterNeedIdle\n");
// plug needs idle calls (outside its editor window) // plug needs idle calls (outside its editor window)
if (plug) { if (plug) {
plug->vstfx()->wantIdle = 1; plug->state()->wantIdle = 1;
} }
return 0; return 0;

View File

@ -185,7 +185,7 @@ intptr_t Session::vst_callback (
SHOW_CALLBACK ("amc: audioMasterNeedIdle\n"); SHOW_CALLBACK ("amc: audioMasterNeedIdle\n");
// plug needs idle calls (outside its editor window) // plug needs idle calls (outside its editor window)
if (plug) { if (plug) {
plug->fst()->wantIdle = 1; plug->state()->wantIdle = 1;
} }
return 0; return 0;

View File

@ -17,663 +17,42 @@
*/ */
#include <algorithm> #include "fst.h"
#include <vector>
#include <string>
#include <cctype>
#include <cstdlib>
#include <cstdio> // so libraptor doesn't complain
#include <cmath>
#include <dirent.h>
#include <cstring> // for memmove
#include <sys/stat.h>
#include <cerrno>
#include <glibmm/miscutils.h>
#include <lrdf.h>
#include <fst.h>
#include "pbd/compose.h"
#include "pbd/error.h"
#include "pbd/pathscanner.h"
#include "pbd/xml++.h"
#include <fst.h>
#include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/windows_vst_plugin.h" #include "ardour/windows_vst_plugin.h"
#include "ardour/buffer_set.h" #include "ardour/session.h"
#include "ardour/audio_buffer.h"
#include "ardour/midi_buffer.h"
#include "pbd/stl_delete.h"
#include "i18n.h" #include "i18n.h"
#include <locale.h>
using namespace std; using namespace std;
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
using std::min;
using std::max;
WindowsVSTPlugin::WindowsVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h) WindowsVSTPlugin::WindowsVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h)
: Plugin (e, session) : VSTPlugin (e, session, h)
{ {
handle = h; if ((_state = fst_instantiate (_handle, Session::vst_callback, this)) == 0) {
if ((_fst = fst_instantiate (handle, Session::vst_callback, this)) == 0) {
throw failed_constructor(); throw failed_constructor();
} }
_plugin = _fst->plugin; set_plugin (_state->plugin);
_plugin->user = this;
/* set rate and blocksize */
_plugin->dispatcher (_plugin, effSetSampleRate, 0, 0, NULL,
(float) session.frame_rate());
_plugin->dispatcher (_plugin, effSetBlockSize, 0,
session.get_block_size(), NULL, 0.0f);
/* set program to zero */
_plugin->dispatcher (_plugin, effSetProgram, 0, 0, NULL, 0.0f);
// Plugin::setup_controls ();
} }
WindowsVSTPlugin::WindowsVSTPlugin (const WindowsVSTPlugin &other) WindowsVSTPlugin::WindowsVSTPlugin (const WindowsVSTPlugin &other)
: Plugin (other) : VSTPlugin (other)
{ {
handle = other.handle; _handle = other._handle;
if ((_fst = fst_instantiate (handle, Session::vst_callback, this)) == 0) { if ((_state = fst_instantiate (_handle, Session::vst_callback, this)) == 0) {
throw failed_constructor(); throw failed_constructor();
} }
_plugin = _fst->plugin;
_plugin = _state->plugin;
// Plugin::setup_controls ();
} }
WindowsVSTPlugin::~WindowsVSTPlugin () WindowsVSTPlugin::~WindowsVSTPlugin ()
{ {
deactivate (); fst_close (_state);
fst_close (_fst);
}
int
WindowsVSTPlugin::set_block_size (pframes_t nframes)
{
deactivate ();
_plugin->dispatcher (_plugin, effSetBlockSize, 0, nframes, NULL, 0.0f);
activate ();
return 0;
}
float
WindowsVSTPlugin::default_value (uint32_t port)
{
return 0;
}
void
WindowsVSTPlugin::set_parameter (uint32_t which, float val)
{
_plugin->setParameter (_plugin, which, val);
if (_fst->want_program == -1 && _fst->want_chunk == 0) {
/* Heinous hack: Plugin::set_parameter below updates the `modified' status of the
current preset, but if _fst->want_program is not -1 then there is a preset
setup pending or in progress, which we don't want any `modified' updates
to happen for. So we only do this if _fst->want_program is -1.
*/
Plugin::set_parameter (which, val);
}
}
float
WindowsVSTPlugin::get_parameter (uint32_t which) const
{
return _plugin->getParameter (_plugin, which);
}
uint32_t
WindowsVSTPlugin::nth_parameter (uint32_t n, bool& ok) const
{
ok = true;
return n;
}
/** Get VST chunk as base64-encoded data.
* @param single true for single program, false for all programs.
* @return 0-terminated base64-encoded data; must be passed to g_free () by caller.
*/
gchar *
WindowsVSTPlugin::get_chunk (bool single) const
{
guchar* data;
int32_t data_size = _plugin->dispatcher (_plugin, 23 /* effGetChunk */, single ? 1 : 0, 0, &data, 0);
if (data_size == 0) {
return 0;
}
return g_base64_encode (data, data_size);
}
/** Set VST chunk from base64-encoded data.
* @param 0-terminated base64-encoded data.
* @param single true for single program, false for all programs.
* @return 0 on success, non-0 on failure
*/
int
WindowsVSTPlugin::set_chunk (gchar const * data, bool single)
{
gsize size = 0;
guchar* raw_data = g_base64_decode (data, &size);
int const r = _plugin->dispatcher (_plugin, 24 /* effSetChunk */, single ? 1 : 0, size, raw_data, 0);
g_free (raw_data);
return r;
}
void
WindowsVSTPlugin::add_state (XMLNode* root) const
{
LocaleGuard lg (X_("POSIX"));
if (_fst->current_program != -1) {
char buf[32];
snprintf (buf, sizeof (buf), "%d", _fst->current_program);
root->add_property ("current-program", buf);
}
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
gchar* data = get_chunk (false);
if (data == 0) {
return;
}
/* store information */
XMLNode* chunk_node = new XMLNode (X_("chunk"));
chunk_node->add_content (data);
g_free (data);
root->add_child_nocopy (*chunk_node);
} else {
XMLNode* parameters = new XMLNode ("parameters");
for (int32_t n = 0; n < _plugin->numParams; ++n) {
char index[64];
char val[32];
snprintf (index, sizeof (index), "param_%d", n);
snprintf (val, sizeof (val), "%.12g", _plugin->getParameter (_plugin, n));
parameters->add_property (index, val);
}
root->add_child_nocopy (*parameters);
}
}
int
WindowsVSTPlugin::set_state (const XMLNode& node, int version)
{
LocaleGuard lg (X_("POSIX"));
if (node.name() != state_node_name()) {
error << _("Bad node sent to WindowsVSTPlugin::set_state") << endmsg;
return 0;
}
const XMLProperty* prop;
if ((prop = node.property ("current-program")) != 0) {
_fst->want_program = atoi (prop->value().c_str());
}
XMLNode* child;
int ret = -1;
if ((child = find_named_node (node, X_("chunk"))) != 0) {
XMLPropertyList::const_iterator i;
XMLNodeList::const_iterator n;
int ret = -1;
for (n = child->children ().begin (); n != child->children ().end (); ++n) {
if ((*n)->is_content ()) {
/* XXX: this may be dubious for the same reasons that we delay
execution of load_preset.
*/
ret = set_chunk ((*n)->content().c_str(), false);
}
}
} else if ((child = find_named_node (node, X_("parameters"))) != 0) {
XMLPropertyList::const_iterator i;
for (i = child->properties().begin(); i != child->properties().end(); ++i) {
int32_t param;
float val;
sscanf ((*i)->name().c_str(), "param_%d", &param);
sscanf ((*i)->value().c_str(), "%f", &val);
_plugin->setParameter (_plugin, param, val);
}
/* program number is not knowable */
_fst->current_program = -1;
ret = 0;
}
Plugin::set_state (node, version);
return ret;
}
int
WindowsVSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
{
VstParameterProperties prop;
desc.min_unbound = false;
desc.max_unbound = false;
prop.flags = 0;
if (_plugin->dispatcher (_plugin, effGetParameterProperties, which, 0, &prop, 0)) {
#ifdef VESTIGE_COMPLETE
/* i have yet to find or hear of a VST plugin that uses this */
if (prop.flags & kVstParameterUsesIntegerMinMax) {
desc.lower = prop.minInteger;
desc.upper = prop.maxInteger;
} else {
desc.lower = 0;
desc.upper = 1.0;
}
if (prop.flags & kVstParameterUsesIntStep) {
desc.step = prop.stepInteger;
desc.smallstep = prop.stepInteger;
desc.largestep = prop.stepInteger;
} else if (prop.flags & kVstParameterUsesFloatStep) {
desc.step = prop.stepFloat;
desc.smallstep = prop.smallStepFloat;
desc.largestep = prop.largeStepFloat;
} else {
float range = desc.upper - desc.lower;
desc.step = range / 100.0f;
desc.smallstep = desc.step / 2.0f;
desc.largestep = desc.step * 10.0f;
}
desc.toggled = prop.flags & kVstParameterIsSwitch;
desc.logarithmic = false;
desc.sr_dependent = false;
desc.label = prop.label;
#endif
} else {
/* old style */
char label[64];
label[0] = '\0';
_plugin->dispatcher (_plugin, effGetParamName, which, 0, label, 0);
desc.label = label;
desc.integer_step = false;
desc.lower = 0.0f;
desc.upper = 1.0f;
desc.step = 0.01f;
desc.smallstep = 0.005f;
desc.largestep = 0.1f;
desc.toggled = false;
desc.logarithmic = false;
desc.sr_dependent = false;
}
return 0;
}
bool
WindowsVSTPlugin::load_preset (PresetRecord r)
{
bool s;
if (r.user) {
s = load_user_preset (r);
} else {
s = load_plugin_preset (r);
}
if (s) {
Plugin::load_preset (r);
}
return s;
}
bool
WindowsVSTPlugin::load_plugin_preset (PresetRecord r)
{
/* This is a plugin-provided preset.
We can't dispatch directly here; too many plugins expects only one GUI thread.
*/
/* Extract the index of this preset from the URI */
int id;
int index;
int const p = sscanf (r.uri.c_str(), "VST:%d:%d", &id, &index);
assert (p == 2);
_fst->want_program = index;
return true;
}
bool
WindowsVSTPlugin::load_user_preset (PresetRecord r)
{
/* This is a user preset; we load it, and this code also knows about the
non-direct-dispatch thing.
*/
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return false;
}
XMLNode* root = t->root ();
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
XMLProperty* uri = (*i)->property (X_("uri"));
XMLProperty* label = (*i)->property (X_("label"));
assert (uri);
assert (label);
if (label->value() != r.label) {
continue;
}
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
/* Load a user preset chunk from our XML file and send it via a circuitous route to the plugin */
if (_fst->wanted_chunk) {
g_free (_fst->wanted_chunk);
}
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j) {
if ((*j)->is_content ()) {
/* we can't dispatch directly here; too many plugins expect only one GUI thread */
gsize size = 0;
guchar* raw_data = g_base64_decode ((*j)->content().c_str(), &size);
_fst->wanted_chunk = raw_data;
_fst->wanted_chunk_size = size;
_fst->want_chunk = 1;
return true;
}
}
return false;
} else {
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j) {
if ((*j)->name() == X_("Parameter")) {
XMLProperty* index = (*j)->property (X_("index"));
XMLProperty* value = (*j)->property (X_("value"));
assert (index);
assert (value);
set_parameter (atoi (index->value().c_str()), atof (value->value().c_str ()));
}
}
return true;
}
}
return false;
}
string
WindowsVSTPlugin::do_save_preset (string name)
{
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return "";
}
XMLNode* p = 0;
/* XXX: use of _presets.size() + 1 for the unique ID here is dubious at best */
string const uri = string_compose (X_("VST:%1:%2"), unique_id (), _presets.size() + 1);
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
p = new XMLNode (X_("ChunkPreset"));
p->add_property (X_("uri"), uri);
p->add_property (X_("label"), name);
gchar* data = get_chunk (true);
p->add_content (string (data));
g_free (data);
} else {
p = new XMLNode (X_("Preset"));
p->add_property (X_("uri"), uri);
p->add_property (X_("label"), name);
for (uint32_t i = 0; i < parameter_count(); ++i) {
if (parameter_is_input (i)) {
XMLNode* c = new XMLNode (X_("Parameter"));
c->add_property (X_("index"), string_compose ("%1", i));
c->add_property (X_("value"), string_compose ("%1", get_parameter (i)));
p->add_child_nocopy (*c);
}
}
}
t->root()->add_child_nocopy (*p);
sys::path f = ARDOUR::user_config_directory ();
f /= "presets";
f /= presets_file ();
t->write (f.to_string ());
return uri;
}
void
WindowsVSTPlugin::do_remove_preset (string name)
{
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return;
}
t->root()->remove_nodes_and_delete (X_("label"), name);
sys::path f = ARDOUR::user_config_directory ();
f /= "presets";
f /= presets_file ();
t->write (f.to_string ());
}
string
WindowsVSTPlugin::describe_parameter (Evoral::Parameter param)
{
char name[64];
_plugin->dispatcher (_plugin, effGetParamName, param.id(), 0, name, 0);
return name;
}
framecnt_t
WindowsVSTPlugin::signal_latency () const
{
if (_user_latency) {
return _user_latency;
}
return *((framecnt_t *) (((char *) &_plugin->flags) + 12)); /* initialDelay */
}
set<Evoral::Parameter>
WindowsVSTPlugin::automatable () const
{
set<Evoral::Parameter> ret;
for (uint32_t i = 0; i < parameter_count(); ++i){
ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i));
}
return ret;
}
int
WindowsVSTPlugin::connect_and_run (BufferSet& bufs,
ChanMapping in_map, ChanMapping out_map,
pframes_t nframes, framecnt_t offset)
{
Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset);
float *ins[_plugin->numInputs];
float *outs[_plugin->numOutputs];
int32_t i;
const uint32_t nbufs = bufs.count().n_audio();
int in_index = 0;
for (i = 0; i < (int32_t) _plugin->numInputs; ++i) {
ins[i] = bufs.get_audio(min((uint32_t) in_index, nbufs - 1)).data() + offset;
in_index++;
}
int out_index = 0;
for (i = 0; i < (int32_t) _plugin->numOutputs; ++i) {
outs[i] = bufs.get_audio(min((uint32_t) out_index, nbufs - 1)).data() + offset;
/* unbelievably, several VST plugins still rely on Cubase
behaviour and do not silence the buffer in processReplacing
when they have no output.
*/
// memset (outs[i], 0, sizeof (Sample) * nframes);
out_index++;
}
if (bufs.count().n_midi() > 0) {
VstEvents* v = bufs.get_vst_midi (0);
_plugin->dispatcher (_plugin, effProcessEvents, 0, 0, v, 0);
}
/* we already know it can support processReplacing */
_plugin->processReplacing (_plugin, ins, outs, nframes);
return 0;
}
void
WindowsVSTPlugin::deactivate ()
{
_plugin->dispatcher (_plugin, effMainsChanged, 0, 0, NULL, 0.0f);
}
void
WindowsVSTPlugin::activate ()
{
_plugin->dispatcher (_plugin, effMainsChanged, 0, 1, NULL, 0.0f);
}
string
WindowsVSTPlugin::unique_id() const
{
char buf[32];
snprintf (buf, sizeof (buf), "%d", *((int32_t*) &_plugin->uniqueID));
return string (buf);
}
const char *
WindowsVSTPlugin::name () const
{
return handle->name;
}
const char *
WindowsVSTPlugin::maker () const
{
return _info->creator.c_str();
}
const char *
WindowsVSTPlugin::label () const
{
return handle->name;
}
uint32_t
WindowsVSTPlugin::parameter_count() const
{
return _plugin->numParams;
}
bool
WindowsVSTPlugin::has_editor () const
{
return _plugin->flags & effFlagsHasEditor;
}
void
WindowsVSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
{
char *first_nonws;
_plugin->dispatcher (_plugin, 7 /* effGetParamDisplay */, param, 0, buf, 0);
if (buf[0] == '\0') {
return;
}
first_nonws = buf;
while (*first_nonws && isspace (*first_nonws)) {
first_nonws++;
}
if (*first_nonws == '\0') {
return;
}
memmove (buf, first_nonws, strlen (buf) - (first_nonws - buf) + 1);
} }
PluginPtr PluginPtr
@ -687,7 +66,7 @@ WindowsVSTPluginInfo::load (Session& session)
handle = fst_load(path.c_str()); handle = fst_load(path.c_str());
if ( (int)handle == -1) { if ((int) handle == -1) {
error << string_compose(_("VST: cannot load module from \"%1\""), path) << endmsg; error << string_compose(_("VST: cannot load module from \"%1\""), path) << endmsg;
} else { } else {
plugin.reset (new WindowsVSTPlugin (session.engine(), session, handle)); plugin.reset (new WindowsVSTPlugin (session.engine(), session, handle));
@ -706,94 +85,6 @@ WindowsVSTPluginInfo::load (Session& session)
} }
} }
void
WindowsVSTPlugin::find_presets ()
{
/* Built-in presets */
int const vst_version = _plugin->dispatcher (_plugin, effGetVstVersion, 0, 0, NULL, 0);
for (int i = 0; i < _plugin->numPrograms; ++i) {
PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "", false);
if (vst_version >= 2) {
char buf[256];
if (_plugin->dispatcher (_plugin, 29, i, 0, buf, 0) == 1) {
r.label = buf;
} else {
r.label = string_compose (_("Preset %1"), i);
}
} else {
r.label = string_compose (_("Preset %1"), i);
}
_presets.insert (make_pair (r.uri, r));
}
/* User presets from our XML file */
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t) {
XMLNode* root = t->root ();
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
XMLProperty* uri = (*i)->property (X_("uri"));
XMLProperty* label = (*i)->property (X_("label"));
assert (uri);
assert (label);
PresetRecord r (uri->value(), label->value(), true);
_presets.insert (make_pair (r.uri, r));
}
}
}
/** @return XMLTree with our user presets; could be a new one if no existing
* one was found, or 0 if one was present but badly-formatted.
*/
XMLTree *
WindowsVSTPlugin::presets_tree () const
{
XMLTree* t = new XMLTree;
sys::path p = ARDOUR::user_config_directory ();
p /= "presets";
if (!is_directory (p)) {
create_directory (p);
}
p /= presets_file ();
if (!exists (p)) {
t->set_root (new XMLNode (X_("WindowsVSTPresets")));
return t;
}
t->set_filename (p.to_string ());
if (!t->read ()) {
delete t;
return 0;
}
return t;
}
/** @return Index of the first user preset in our lists */
int
WindowsVSTPlugin::first_user_preset_index () const
{
return _plugin->numPrograms;
}
string
WindowsVSTPlugin::presets_file () const
{
return string_compose ("vst-%1", unique_id ());
}
WindowsVSTPluginInfo::WindowsVSTPluginInfo() WindowsVSTPluginInfo::WindowsVSTPluginInfo()
{ {
type = ARDOUR::Windows_VST; type = ARDOUR::Windows_VST;

View File

@ -217,7 +217,8 @@ libardour_sources = [
'unknown_processor.cc', 'unknown_processor.cc',
'user_bundle.cc', 'user_bundle.cc',
'utils.cc', 'utils.cc',
'version.cc' 'version.cc',
'vst_plugin.cc'
] ]
def flac_supported(): def flac_supported():