obj = bld (features = 'cxx c cxxprogram wine')
obj.source = (
'../libs/fst/fst.c',
- '../libs/fst/fstinfofile.c',
- '../libs/fst/vsti.c',
'../libs/fst/vstwin.c',
'../vst/winmain.c',
)
LIBARDOUR_API extern int vstfx_run_editor (VSTState *);
LIBARDOUR_API extern void vstfx_destroy_editor (VSTState *);
-LIBARDOUR_API extern VSTInfo * vstfx_get_info (char *);
-LIBARDOUR_API extern void vstfx_free_info (VSTInfo *);
LIBARDOUR_API extern void vstfx_event_loop_remove_plugin (VSTState *);
LIBARDOUR_API extern int vstfx_call_dispatcher (VSTState *, int, int, int, void *, float);
LIBARDOUR_API extern bool vstfx_save_state (VSTState* vstfx, char * filename);
-
#endif /* __vstfx_h__ */
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Paul Davis
+ Author: Robin Gareus <robin@gareus.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __vst_info_file_h__
+#define __vst_info_file_h__
+
+#include "ardour/libardour_visibility.h"
+#include "ardour/vst_types.h"
+
+LIBARDOUR_API extern void vstfx_free_info (VSTInfo *);
+
+#ifdef LXVST_SUPPORT
+LIBARDOUR_API extern VSTInfo * vstfx_get_info_lx (char *);
+#endif
+
+#ifdef WINDOWS_VST_SUPPORT
+LIBARDOUR_API extern VSTInfo * vstfx_get_info_fst (char *);
+#endif
+
+#endif /* __vstfx_h__ */
+
+++ /dev/null
-/*
- Copyright (C) 2012 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file libs/ardour/vst_info_file.cc
- * @brief Code to manage info files containing cached information about a plugin.
- * e.g. its name, creator etc.
- */
-
-#include <iostream>
-#include <cassert>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <libgen.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glibmm.h>
-
-#include "pbd/error.h"
-
-#include "ardour/linux_vst_support.h"
-
-#define MAX_STRING_LEN 256
-
-using namespace std;
-
-static char *
-read_string (FILE *fp)
-{
- char buf[MAX_STRING_LEN];
-
- if (!fgets (buf, MAX_STRING_LEN, fp)) {
- return 0;
- }
-
- if (strlen(buf) < MAX_STRING_LEN) {
- if (strlen (buf)) {
- buf[strlen(buf)-1] = 0;
- }
- return strdup (buf);
- } else {
- return 0;
- }
-}
-
-/** Read an integer value from a line in fp into n,
- * @return true on failure, false on success.
- */
-static bool
-read_int (FILE* fp, int* n)
-{
- char buf[MAX_STRING_LEN];
-
- char* p = fgets (buf, MAX_STRING_LEN, fp);
- if (p == 0) {
- return true;
- }
-
- return (sscanf (p, "%d", n) != 1);
-}
-
-static VSTInfo *
-load_vstfx_info_file (FILE* fp)
-{
- VSTInfo *info;
-
- if ((info = (VSTInfo*) malloc (sizeof (VSTInfo))) == 0) {
- return 0;
- }
-
- if ((info->name = read_string(fp)) == 0) goto error;
- if ((info->creator = read_string(fp)) == 0) goto error;
- if (read_int (fp, &info->UniqueID)) goto error;
- if ((info->Category = read_string(fp)) == 0) goto error;
- if (read_int (fp, &info->numInputs)) goto error;
- if (read_int (fp, &info->numOutputs)) goto error;
- if (read_int (fp, &info->numParams)) goto error;
- if (read_int (fp, &info->wantMidi)) goto error;
- if (read_int (fp, &info->hasEditor)) goto error;
- if (read_int (fp, &info->canProcessReplacing)) goto error;
-
- if ((info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams)) == 0) {
- goto error;
- }
-
- for (int i = 0; i < info->numParams; ++i) {
- if ((info->ParamNames[i] = read_string(fp)) == 0) goto error;
- }
-
- if ((info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams)) == 0) {
- goto error;
- }
-
- for (int i = 0; i < info->numParams; ++i) {
- if ((info->ParamLabels[i] = read_string(fp)) == 0) goto error;
- }
-
- return info;
-
- error:
- free (info);
- return 0;
-}
-
-static int
-save_vstfx_info_file (VSTInfo *info, FILE* fp)
-{
- assert (info);
- assert (fp);
-
- fprintf (fp, "%s\n", info->name);
- fprintf (fp, "%s\n", info->creator);
- fprintf (fp, "%d\n", info->UniqueID);
- fprintf (fp, "%s\n", info->Category);
- fprintf (fp, "%d\n", info->numInputs);
- fprintf (fp, "%d\n", info->numOutputs);
- fprintf (fp, "%d\n", info->numParams);
- fprintf (fp, "%d\n", info->wantMidi);
- fprintf (fp, "%d\n", info->hasEditor);
- fprintf (fp, "%d\n", info->canProcessReplacing);
-
- for (int i = 0; i < info->numParams; i++) {
- fprintf (fp, "%s\n", info->ParamNames[i]);
- }
-
- for (int i = 0; i < info->numParams; i++) {
- fprintf (fp, "%s\n", info->ParamLabels[i]);
- }
-
- return 0;
-}
-
-static string
-vstfx_infofile_path (char* dllpath, int personal)
-{
- string dir;
- if (personal) {
- dir = Glib::build_filename (Glib::get_home_dir (), ".fst");
-
- /* If the directory doesn't exist, try to create it */
- if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
- if (g_mkdir (dir.c_str (), 0700)) {
- return 0;
- }
- }
-
- } else {
- dir = Glib::path_get_dirname (std::string(dllpath));
- }
-
- stringstream s;
- s << "." << Glib::path_get_basename (dllpath) << ".fsi";
- return Glib::build_filename (dir, s.str ());
-}
-
-static char *
-vstfx_infofile_stat (char *dllpath, struct stat* statbuf, int personal)
-{
- if (strstr (dllpath, ".so" ) == 0) {
- return 0;
- }
-
- string const path = vstfx_infofile_path (dllpath, personal);
-
- if (Glib::file_test (path, Glib::FileTest (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR))) {
-
- /* info file exists in same location as the shared object, so
- check if its current and up to date
- */
-
-
- struct stat dllstat;
-
- if (stat (dllpath, &dllstat) == 0) {
- if (stat (path.c_str(), statbuf) == 0) {
- if (dllstat.st_mtime <= statbuf->st_mtime) {
- /* plugin is older than info file */
- return strdup (path.c_str ());
- }
- }
- }
- }
-
- return 0;
-}
-
-
-static FILE *
-vstfx_infofile_for_read (char* dllpath)
-{
- struct stat own_statbuf;
- struct stat sys_statbuf;
- FILE *rv = NULL;
-
- char* own_info = vstfx_infofile_stat (dllpath, &own_statbuf, 1);
- char* sys_info = vstfx_infofile_stat (dllpath, &sys_statbuf, 0);
-
- if (own_info) {
- if (sys_info) {
- if (own_statbuf.st_mtime <= sys_statbuf.st_mtime) {
- /* system info file is newer, use it */
- rv = g_fopen (sys_info, "rb");
- }
- } else {
- rv = g_fopen (own_info, "rb");
- }
- }
- free(own_info);
- free(sys_info);
-
- return rv;
-}
-
-static FILE *
-vstfx_infofile_create (char* dllpath, int personal)
-{
- if (strstr (dllpath, ".so" ) == 0) {
- return 0;
- }
-
- string const path = vstfx_infofile_path (dllpath, personal);
- return fopen (path.c_str(), "w");
-}
-
-static FILE *
-vstfx_infofile_for_write (char* dllpath)
-{
- FILE* f;
-
- if ((f = vstfx_infofile_create (dllpath, 0)) == 0) {
- f = vstfx_infofile_create (dllpath, 1);
- }
-
- return f;
-}
-
-static
-int vstfx_can_midi (VSTState* vstfx)
-{
- AEffect* plugin = vstfx->plugin;
-
- int const vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, 0, 0.0f);
-
- if (vst_version >= 2) {
- /* should we send it VST events (i.e. MIDI) */
-
- if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0)) {
- return -1;
- }
- }
-
- return false;
-}
-
-static VSTInfo *
-vstfx_info_from_plugin (VSTState* vstfx)
-{
- assert (vstfx);
-
- VSTInfo* info = (VSTInfo*) malloc (sizeof (VSTInfo));
- if (!info) {
- return 0;
- }
-
- /*We need to init the creator because some plugins
- fail to implement getVendorString, and so won't stuff the
- string with any name*/
-
- char creator[65] = "Unknown\0";
-
- AEffect* plugin = vstfx->plugin;
-
- info->name = strdup (vstfx->handle->name);
-
- /*If the plugin doesn't bother to implement GetVendorString we will
- have pre-stuffed the string with 'Unkown' */
-
- plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0);
-
- /*Some plugins DO implement GetVendorString, but DON'T put a name in it
- so if its just a zero length string we replace it with 'Unknown' */
-
- if (strlen(creator) == 0) {
- info->creator = strdup ("Unknown");
- } else {
- info->creator = strdup (creator);
- }
-
- info->UniqueID = plugin->uniqueID;
-
- info->Category = strdup("None"); /* XXX */
- info->numInputs = plugin->numInputs;
- info->numOutputs = plugin->numOutputs;
- info->numParams = plugin->numParams;
- info->wantMidi = vstfx_can_midi(vstfx);
- info->hasEditor = plugin->flags & effFlagsHasEditor ? true : false;
- info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? true : false;
- info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams);
- info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams);
-
- for (int i = 0; i < info->numParams; ++i) {
- char name[64];
- char label[64];
-
- /* Not all plugins give parameters labels as well as names */
-
- strcpy (name, "No Name");
- strcpy (label, "No Label");
-
- plugin->dispatcher (plugin, effGetParamName, i, 0, name, 0);
- info->ParamNames[i] = strdup(name);
-
- //NOTE: 'effGetParamLabel' is no longer defined in vestige headers
- //plugin->dispatcher (plugin, effGetParamLabel, i, 0, label, 0);
- info->ParamLabels[i] = strdup(label);
- }
- return info;
-}
-
-/* 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)
-{
- if (opcode == audioMasterVersion) {
- return 2;
- } else {
- return 0;
- }
-}
-
-/** 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
-*/
-
-VSTInfo *
-vstfx_get_info (char* dllpath)
-{
- FILE* infofile;
- VSTHandle* h;
- VSTState* vstfx;
-
- if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) {
- VSTInfo *info;
- info = load_vstfx_info_file (infofile);
- fclose (infofile);
- if (info == 0) {
- PBD::warning << "Cannot get LinuxVST information form " << dllpath << ": info file load failed." << endmsg;
- }
- return info;
- }
-
- if (!(h = vstfx_load(dllpath))) {
- PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": load failed." << endmsg;
- return 0;
- }
-
- if (!(vstfx = vstfx_instantiate(h, simple_master_callback, 0))) {
- vstfx_unload(h);
- PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": instantiation failed." << endmsg;
- return 0;
- }
-
- 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);
-
- save_vstfx_info_file (info, infofile);
- fclose (infofile);
-
- vstfx_close (vstfx);
- vstfx_unload (h);
-
- return info;
-}
-
-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);
-}
-
-
#endif
#ifdef WINDOWS_VST_SUPPORT
+#include "ardour/vst_info_file.h"
#include "fst.h"
#include "pbd/basename.h"
#include <cstring>
#endif // WINDOWS_VST_SUPPORT
#ifdef LXVST_SUPPORT
+#include "ardour/vst_info_file.h"
#include "ardour/linux_vst_support.h"
#include "pbd/basename.h"
#include <cstring>
VSTInfo* finfo;
char buf[32];
- if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
+ if ((finfo = vstfx_get_info_fst (const_cast<char *> (path.c_str()))) == 0) {
warning << "Cannot get Windows VST information from " << path << endmsg;
return -1;
}
info->type = ARDOUR::Windows_VST;
_windows_vst_plugin_info->push_back (info);
- fst_free_info (finfo);
+ vstfx_free_info(finfo);
return 0;
}
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
- if ((finfo = vstfx_get_info (const_cast<char *> (path.c_str()))) == 0) {
+ if ((finfo = vstfx_get_info_lx (const_cast<char *> (path.c_str()))) == 0) {
return -1;
}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file libs/ardour/vst_info_file.cc
+ * @brief Code to manage info files containing cached information about a plugin.
+ * e.g. its name, creator etc.
+ */
+
+#include <iostream>
+#include <cassert>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glibmm.h>
+
+#include "pbd/error.h"
+
+#include "ardour/linux_vst_support.h"
+#include "ardour/vst_info_file.h"
+
+#define MAX_STRING_LEN 256
+
+using namespace std;
+
+static char *
+read_string (FILE *fp)
+{
+ char buf[MAX_STRING_LEN];
+
+ if (!fgets (buf, MAX_STRING_LEN, fp)) {
+ return 0;
+ }
+
+ if (strlen(buf) < MAX_STRING_LEN) {
+ if (strlen (buf)) {
+ buf[strlen(buf)-1] = 0;
+ }
+ return strdup (buf);
+ } else {
+ return 0;
+ }
+}
+
+/** Read an integer value from a line in fp into n,
+ * @return true on failure, false on success.
+ */
+static bool
+read_int (FILE* fp, int* n)
+{
+ char buf[MAX_STRING_LEN];
+
+ char* p = fgets (buf, MAX_STRING_LEN, fp);
+ if (p == 0) {
+ return true;
+ }
+
+ return (sscanf (p, "%d", n) != 1);
+}
+
+static VSTInfo *
+load_vstfx_info_file (FILE* fp)
+{
+ VSTInfo *info;
+
+ if ((info = (VSTInfo*) malloc (sizeof (VSTInfo))) == 0) {
+ return 0;
+ }
+
+ if ((info->name = read_string(fp)) == 0) goto error;
+ if ((info->creator = read_string(fp)) == 0) goto error;
+ if (read_int (fp, &info->UniqueID)) goto error;
+ if ((info->Category = read_string(fp)) == 0) goto error;
+ if (read_int (fp, &info->numInputs)) goto error;
+ if (read_int (fp, &info->numOutputs)) goto error;
+ if (read_int (fp, &info->numParams)) goto error;
+ if (read_int (fp, &info->wantMidi)) goto error;
+ if (read_int (fp, &info->hasEditor)) goto error;
+ if (read_int (fp, &info->canProcessReplacing)) goto error;
+
+ if ((info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams)) == 0) {
+ goto error;
+ }
+
+ for (int i = 0; i < info->numParams; ++i) {
+ if ((info->ParamNames[i] = read_string(fp)) == 0) goto error;
+ }
+
+ if ((info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams)) == 0) {
+ goto error;
+ }
+
+ for (int i = 0; i < info->numParams; ++i) {
+ if ((info->ParamLabels[i] = read_string(fp)) == 0) goto error;
+ }
+
+ return info;
+
+error:
+ free (info);
+ return 0;
+}
+
+static int
+save_vstfx_info_file (VSTInfo *info, FILE* fp)
+{
+ assert (info);
+ assert (fp);
+
+ fprintf (fp, "%s\n", info->name);
+ fprintf (fp, "%s\n", info->creator);
+ fprintf (fp, "%d\n", info->UniqueID);
+ fprintf (fp, "%s\n", info->Category);
+ fprintf (fp, "%d\n", info->numInputs);
+ fprintf (fp, "%d\n", info->numOutputs);
+ fprintf (fp, "%d\n", info->numParams);
+ fprintf (fp, "%d\n", info->wantMidi);
+ fprintf (fp, "%d\n", info->hasEditor);
+ fprintf (fp, "%d\n", info->canProcessReplacing);
+
+ for (int i = 0; i < info->numParams; i++) {
+ fprintf (fp, "%s\n", info->ParamNames[i]);
+ }
+
+ for (int i = 0; i < info->numParams; i++) {
+ fprintf (fp, "%s\n", info->ParamLabels[i]);
+ }
+
+ return 0;
+}
+
+static string
+vstfx_infofile_path (char* dllpath, int personal)
+{
+ string dir;
+ if (personal) {
+ dir = Glib::build_filename (Glib::get_home_dir (), ".fst");
+
+ /* If the directory doesn't exist, try to create it */
+ if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
+ if (g_mkdir (dir.c_str (), 0700)) {
+ return 0;
+ }
+ }
+
+ } else {
+ dir = Glib::path_get_dirname (std::string(dllpath));
+ }
+
+ stringstream s;
+ s << "." << Glib::path_get_basename (dllpath) << ".fsi";
+ return Glib::build_filename (dir, s.str ());
+}
+
+static char *
+vstfx_infofile_stat (char *dllpath, struct stat* statbuf, int personal)
+{
+ if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) {
+ return 0;
+ }
+
+ string const path = vstfx_infofile_path (dllpath, personal);
+
+ if (Glib::file_test (path, Glib::FileTest (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR))) {
+
+ /* info file exists in same location as the shared object, so
+ check if its current and up to date
+ */
+
+
+ struct stat dllstat;
+
+ if (stat (dllpath, &dllstat) == 0) {
+ if (stat (path.c_str(), statbuf) == 0) {
+ if (dllstat.st_mtime <= statbuf->st_mtime) {
+ /* plugin is older than info file */
+ return strdup (path.c_str ());
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static FILE *
+vstfx_infofile_for_read (char* dllpath)
+{
+ struct stat own_statbuf;
+ struct stat sys_statbuf;
+ FILE *rv = NULL;
+
+ char* own_info = vstfx_infofile_stat (dllpath, &own_statbuf, 1);
+ char* sys_info = vstfx_infofile_stat (dllpath, &sys_statbuf, 0);
+
+ if (own_info) {
+ if (sys_info) {
+ if (own_statbuf.st_mtime <= sys_statbuf.st_mtime) {
+ /* system info file is newer, use it */
+ rv = g_fopen (sys_info, "rb");
+ }
+ } else {
+ rv = g_fopen (own_info, "rb");
+ }
+ } else if (sys_info) {
+ rv = g_fopen (sys_info, "rb");
+ }
+ free(own_info);
+ free(sys_info);
+
+ return rv;
+}
+
+static FILE *
+vstfx_infofile_create (char* dllpath, int personal)
+{
+ if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) {
+ return 0;
+ }
+
+ string const path = vstfx_infofile_path (dllpath, personal);
+ return fopen (path.c_str(), "w");
+}
+
+static FILE *
+vstfx_infofile_for_write (char* dllpath)
+{
+ FILE* f;
+
+ if ((f = vstfx_infofile_create (dllpath, 0)) == 0) {
+ f = vstfx_infofile_create (dllpath, 1);
+ }
+
+ return f;
+}
+
+static
+int vstfx_can_midi (VSTState* vstfx)
+{
+ AEffect* plugin = vstfx->plugin;
+
+ int const vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, 0, 0.0f);
+
+ if (vst_version >= 2) {
+ /* should we send it VST events (i.e. MIDI) */
+
+ if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0)) {
+ return -1;
+ }
+ }
+
+ return false;
+}
+
+static VSTInfo *
+vstfx_info_from_plugin (VSTState* vstfx)
+{
+ assert (vstfx);
+
+ VSTInfo* info = (VSTInfo*) malloc (sizeof (VSTInfo));
+ if (!info) {
+ return 0;
+ }
+
+ /*We need to init the creator because some plugins
+ fail to implement getVendorString, and so won't stuff the
+ string with any name*/
+
+ char creator[65] = "Unknown\0";
+
+ AEffect* plugin = vstfx->plugin;
+
+ info->name = strdup (vstfx->handle->name);
+
+ /*If the plugin doesn't bother to implement GetVendorString we will
+ have pre-stuffed the string with 'Unkown' */
+
+ plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0);
+
+ /*Some plugins DO implement GetVendorString, but DON'T put a name in it
+ so if its just a zero length string we replace it with 'Unknown' */
+
+ if (strlen(creator) == 0) {
+ info->creator = strdup ("Unknown");
+ } else {
+ info->creator = strdup (creator);
+ }
+
+ info->UniqueID = plugin->uniqueID;
+
+ info->Category = strdup("None"); /* XXX */
+ info->numInputs = plugin->numInputs;
+ info->numOutputs = plugin->numOutputs;
+ info->numParams = plugin->numParams;
+ info->wantMidi = vstfx_can_midi(vstfx);
+ info->hasEditor = plugin->flags & effFlagsHasEditor ? true : false;
+ info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? true : false;
+ info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams);
+ info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams);
+
+ for (int i = 0; i < info->numParams; ++i) {
+ char name[64];
+ char label[64];
+
+ /* Not all plugins give parameters labels as well as names */
+
+ strcpy (name, "No Name");
+ strcpy (label, "No Label");
+
+ plugin->dispatcher (plugin, effGetParamName, i, 0, name, 0);
+ info->ParamNames[i] = strdup(name);
+
+ //NOTE: 'effGetParamLabel' is no longer defined in vestige headers
+ //plugin->dispatcher (plugin, effGetParamLabel, i, 0, label, 0);
+ info->ParamLabels[i] = strdup(label);
+ }
+ return info;
+}
+
+/* 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)
+{
+ if (opcode == audioMasterVersion) {
+ return 2;
+ } else {
+ return 0;
+ }
+}
+
+static VSTInfo *
+vstfx_get_info_from_file(char* dllpath, bool &found)
+{
+ FILE* infofile;
+ VSTInfo *info = 0;
+ found = false;
+ if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) {
+ found = true;
+ info = load_vstfx_info_file (infofile);
+ fclose (infofile);
+ if (info == 0) {
+ PBD::warning << "Cannot get LinuxVST information form " << dllpath << ": info file load failed." << endmsg;
+ }
+ }
+ return info;
+}
+
+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);
+}
+
+#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
+*/
+
+VSTInfo *
+vstfx_get_info_lx (char* dllpath)
+{
+ FILE* infofile;
+ VSTHandle* h;
+ VSTState* vstfx;
+
+ bool used_cache;
+ VSTInfo* info = vstfx_get_info_from_file(dllpath, used_cache);
+ if (used_cache) {
+ PBD::info << "using cache for LinuxVST plugin '" << dllpath << "'" << endmsg;
+ return info;
+ }
+
+ if (!(h = vstfx_load(dllpath))) {
+ PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": load failed." << endmsg;
+ return 0;
+ }
+
+ if (!(vstfx = vstfx_instantiate(h, simple_master_callback, 0))) {
+ vstfx_unload(h);
+ PBD::warning << "Cannot get LinuxVST information from " << dllpath << ": instantiation failed." << endmsg;
+ return 0;
+ }
+
+ 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;
+ }
+
+ info = vstfx_info_from_plugin (vstfx);
+
+ save_vstfx_info_file (info, infofile);
+ fclose (infofile);
+
+ vstfx_close (vstfx);
+ vstfx_unload (h);
+
+ return info;
+}
+#endif
+
+#ifdef WINDOWS_VST_SUPPORT
+#include <fst.h>
+
+VSTInfo *
+vstfx_get_info_fst (char* dllpath)
+{
+ FILE* infofile;
+ VSTHandle* h;
+ VSTState* vstfx;
+
+ bool used_cache;
+ VSTInfo* info = vstfx_get_info_from_file(dllpath, used_cache);
+ if (used_cache) {
+ PBD::info << "using cache for VST plugin '" << dllpath << "'" << endmsg;
+ return info;
+ }
+
+ if(!(h = fst_load(dllpath))) {
+ PBD::warning << "Cannot get VST information from " << dllpath << ": load failed." << endmsg;
+ return 0;
+ }
+
+ if(!(vstfx = fst_instantiate(h, simple_master_callback, 0))) {
+ fst_unload(&h);
+ PBD::warning << "Cannot get VST information from " << dllpath << ": instantiation failed." << endmsg;
+ return 0;
+ }
+
+ 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;
+ }
+
+ info = vstfx_info_from_plugin(vstfx);
+ save_vstfx_info_file (info, infofile);
+ fclose (infofile);
+
+ fst_close(vstfx);
+ //fst_unload(&h); // XXX -> fst_close()
+
+ return info;
+}
+#endif
obj.source += [ 'windows_vst_plugin.cc']
obj.includes += [ '../fst' ]
obj.defines += [ 'WINDOWS_VST_SUPPORT' ]
+ if bld.env['build_target'] == 'mingw':
+ obj.source += [ '../fst/vstwin.c']
if bld.is_defined('LXVST_SUPPORT'):
- obj.source += [ 'lxvst_plugin.cc', 'linux_vst_support.cc', 'linux_vst_info_file.cc' ]
+ obj.source += [ 'lxvst_plugin.cc', 'linux_vst_support.cc' ]
obj.defines += [ 'LXVST_SUPPORT' ]
if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT'):
- obj.source += [ 'session_vst.cc', 'vst_plugin.cc' ]
+ obj.source += [ 'session_vst.cc', 'vst_plugin.cc', 'vst_info_file.cc' ]
if bld.is_defined('HAVE_COREAUDIO'):
obj.source += [ 'coreaudiosource.cc', 'caimportable.cc' ]
extern void fst_destroy_editor (VSTState *);
extern void fst_move_window_into_view (VSTState *);
-extern VSTInfo *fst_get_info (char *dllpathname);
-extern void fst_free_info (VSTInfo *info);
extern void fst_event_loop_remove_plugin (VSTState* fst);
extern void fst_start_threading(void);
extern void fst_stop_threading(void);
+++ /dev/null
-#include "fst.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#define MAX_STRING_LEN 256
-
-#define FALSE 0
-#define TRUE !FALSE
-
-extern char * strdup (const char *);
-
-static char *read_string( FILE *fp ) {
- char buf[MAX_STRING_LEN];
-
- fgets( buf, MAX_STRING_LEN, fp );
- if( strlen( buf ) < MAX_STRING_LEN ) {
-
- if( strlen(buf) )
- buf[strlen(buf)-1] = 0;
-
- return strdup( buf );
- } else {
- return NULL;
- }
-}
-
-static VSTInfo *
-load_fst_info_file (char* filename)
-{
- VSTInfo *info = (VSTInfo *) malloc (sizeof (VSTInfo));
- FILE *fp;
- int i;
-
- if (info == NULL) {
- return NULL;
- }
-
- fp = fopen( filename, "r" );
-
- if (fp == NULL) {
- free (info);
- return NULL;
- }
-
- if( (info->name = read_string( fp )) == NULL ) goto error;
- if( (info->creator = read_string( fp )) == NULL ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->UniqueID ) ) goto error;
- if( (info->Category = read_string( fp )) == NULL ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->numInputs ) ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->numOutputs ) ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->numParams ) ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->wantMidi ) ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->hasEditor ) ) goto error;
- if( 1 != fscanf( fp, "%d\n", &info->canProcessReplacing ) ) goto error;
-
- if( (info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
- for( i=0; i<info->numParams; i++ ) {
- if( (info->ParamNames[i] = read_string( fp )) == NULL ) goto error;
- }
- if( (info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
- for( i=0; i<info->numParams; i++ ) {
- if( (info->ParamLabels[i] = read_string( fp )) == NULL ) goto error;
- }
-
-
- fclose( fp );
- return info;
-
-error:
- fclose( fp );
- free( info );
- return NULL;
-}
-
-static int
-save_fst_info_file (VSTInfo* info, char* filename)
-{
- FILE *fp;
- int i;
-
-
- if( info == NULL ) {
- fst_error( "info is NULL\n" );
- return TRUE;
- }
-
- fp = fopen( filename, "w" );
-
- if( fp == NULL ) {
- fst_error( "Cant write info file %s\n", filename );
- return TRUE;
- }
-
- fprintf( fp, "%s\n", info->name );
- fprintf( fp, "%s\n", info->creator );
- fprintf( fp, "%d\n", info->UniqueID );
- fprintf( fp, "%s\n", info->Category );
- fprintf( fp, "%d\n", info->numInputs );
- fprintf( fp, "%d\n", info->numOutputs );
- fprintf( fp, "%d\n", info->numParams );
- fprintf( fp, "%d\n", info->wantMidi );
- fprintf( fp, "%d\n", info->hasEditor );
- fprintf( fp, "%d\n", info->canProcessReplacing );
-
- for( i=0; i<info->numParams; i++ ) {
- fprintf( fp, "%s\n", info->ParamNames[i] );
- }
- for( i=0; i<info->numParams; i++ ) {
- fprintf( fp, "%s\n", info->ParamLabels[i] );
- }
-
-
- fclose( fp );
-
- return FALSE;
-}
-
-static char *fst_dllpath_to_infopath( char *dllpath ) {
- char *retval;
- if( strstr( dllpath, ".dll" ) == NULL ) return NULL;
-
- retval = strdup( dllpath );
- sprintf( retval + strlen(retval) - 4, ".fsi" );
- return retval;
-}
-
-static int fst_info_file_is_valid( char *dllpath ) {
- struct stat dllstat, fststat;
- char *fstpath = fst_dllpath_to_infopath( dllpath );
-
- if( !fstpath ) return FALSE;
-
- if( stat( dllpath, &dllstat ) ){ fst_error( "dll path %s invalid\n", dllpath ); return TRUE; }
- if( stat( fstpath, &fststat ) ) return FALSE;
-
- free( fstpath );
- if( dllstat.st_mtime > fststat.st_mtime )
- return FALSE;
- else
- return TRUE;
-}
-
-static int
-fst_can_midi (VSTState* fst)
-{
- AEffect* plugin = fst->plugin;
- int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
-
- if (vst_version >= 2) {
-
- /* should we send it VST events (i.e. MIDI) */
-
- if ((plugin->flags & effFlagsIsSynth) ||
- (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
- return TRUE;
- }
- return FALSE;
-
-}
-static VSTInfo *
-fst_info_from_plugin (VSTState* fst)
-{
- VSTInfo* info = (VSTInfo *) malloc (sizeof (VSTInfo));
- AEffect* plugin;
- int i;
- char creator[65];
-
- if( ! fst ) {
- fst_error( "fst is NULL\n" );
- return NULL;
- }
-
- if( ! info ) return NULL;
-
- plugin = fst->plugin;
-
-
- info->name = strdup(fst->handle->name );
- plugin->dispatcher (plugin, 47 /* effGetVendorString */, 0, 0, creator, 0);
- if (strlen (creator) == 0) {
- info->creator = strdup ("Unknown");
- } else {
- info->creator = strdup (creator);
- }
-
- info->UniqueID = *((int32_t *) &plugin->uniqueID);
-
- info->Category = strdup( "None" ); // FIXME:
- info->numInputs = plugin->numInputs;
- info->numOutputs = plugin->numOutputs;
- info->numParams = plugin->numParams;
- info->wantMidi = fst_can_midi( fst );
- info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
- info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
-
- info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams );
- info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams );
- for( i=0; i<info->numParams; i++ ) {
- char name[20];
- char label[9];
- plugin->dispatcher (plugin,
- effGetParamName,
- i, 0, name, 0);
- info->ParamNames[i] = strdup( name );
- plugin->dispatcher (plugin,
- 6 /* effGetParamLabel */,
- i, 0, label, 0);
- info->ParamLabels[i] = strdup( label );
- }
- return info;
-}
-
-// most simple one :) could be sufficient....
-static intptr_t
-simple_master_callback (AEffect *fx, int32_t opcode, int32_t index, intptr_t value, void *ptr, float opt)
-{
- if (opcode == audioMasterVersion) {
- return 2;
- } else {
- return 0;
- }
-}
-
-VSTInfo *
-fst_get_info (char* dllpath)
-{
- if( fst_info_file_is_valid( dllpath ) ) {
- VSTInfo *info;
- char *fstpath = fst_dllpath_to_infopath( dllpath );
-
- info = load_fst_info_file( fstpath );
- free( fstpath );
- return info;
-
- } else {
-
- VSTHandle* h;
- VSTState* fst;
- VSTInfo* info;
- char* fstpath;
-
- if( !(h = fst_load( dllpath )) ) return NULL;
- if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) {
- fst_unload( &h );
- fst_error( "instantiate failed\n" );
- return NULL;
- }
- fstpath = fst_dllpath_to_infopath( dllpath );
- if( !fstpath ) {
- fst_close( fst );
- fst_unload( &h );
- fst_error( "get fst filename failed\n" );
- return NULL;
- }
- info = fst_info_from_plugin( fst );
- save_fst_info_file( info, fstpath );
-
- free( fstpath );
- fst_close( fst );
- fst_unload( &h );
- return info;
- }
-}
-
-void
-fst_free_info (VSTInfo *info)
-{
- int i;
-
- for( 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 );
-}
-
-
+++ /dev/null
-#ifndef __jack_vst_h__
-#define __jack_vst_h__
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <jack/jack.h>
-#include <jack/ringbuffer.h>
-#include <fst.h>
-#ifdef HAVE_ALSA
-#include <alsa/asoundlib.h>
-#endif
-
-typedef struct _JackVST JackVST;
-
-struct _JackVST {
- jack_client_t *client;
- VSTHandle * handle;
- VSTState * fst;
- float **ins;
- float **outs;
- jack_port_t *midi_port;
- jack_port_t **inports;
- jack_port_t **outports;
- void* userdata;
- int bypassed;
- int muted;
- int current_program;
-
- /* For VST/i support */
-
- int want_midi;
- pthread_t midi_thread;
-#ifdef HAVE_ALSA
- snd_seq_t* seq;
-#endif
- int midiquit;
- jack_ringbuffer_t* event_queue;
- struct VstEvents* events;
-};
-
-#define MIDI_EVENT_MAX 1024
-
-#endif /* __jack_vst_h__ */
+++ /dev/null
-/*
- * VST instrument support
- *
- * Derived from code that was marked:
- * Copyright (C) Kjetil S. Matheussen 2004 (k.s.matheussen@notam02.no)
- * Alsa-seq midi-code made by looking at the jack-rack source made by Bob Ham.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: vsti.c,v 1.2 2004/04/07 01:56:23 pauld Exp $
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <jackvst.h>
-#include <pthread.h>
-#include <sched.h>
-#include "ardour/vestige/aeffectx.h"
-
-#ifdef HAVE_ALSAMIDIVSTIXXX // not used in ardour 3
-
-snd_seq_t *
-create_sequencer (const char* client_name, bool isinput)
-{
- snd_seq_t * seq;
- int err;
-
- if ((err = snd_seq_open (&seq, "default", SND_SEQ_OPEN_DUPLEX, 0)) != 0) {
- fst_error ("Could not open ALSA sequencer, aborting\n\n%s\n\n"
- "Make sure you have configure ALSA properly and that\n"
- "/proc/asound/seq/clients exists and contains relevant\n"
- "devices (%s).",
- snd_strerror (err));
- return NULL;
- }
-
- snd_seq_set_client_name (seq, client_name);
-
- if ((err = snd_seq_create_simple_port (seq, isinput? "Input" : "Output",
- (isinput? SND_SEQ_PORT_CAP_WRITE: SND_SEQ_PORT_CAP_READ)| SND_SEQ_PORT_CAP_DUPLEX |
- SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_APPLICATION|SND_SEQ_PORT_TYPE_SPECIFIC)) != 0) {
- fst_error ("Could not create ALSA port: %s", snd_strerror (err));
- snd_seq_close(seq);
- return NULL;
- }
-
- return seq;
-}
-
-static void
-queue_midi (JackVST *jvst, int val1, int val2, int val3)
-{
- VstMidiEvent *pevent;
- jack_ringbuffer_data_t vec[2];
-
- jack_ringbuffer_get_write_vector (jvst->event_queue, vec);
-
- if (vec[0].len < sizeof (VstMidiEvent)) {
- fst_error ("event queue has no write space");
- return;
- }
-
- pevent = (VstMidiEvent *) vec[0].buf;
-
- // printf("note: %d\n",note);
-
- pevent->type = kVstMidiType;
- pevent->byteSize = 24;
- pevent->deltaFrames = 0;
- pevent->flags = 0;
- pevent->detune = 0;
- pevent->noteLength = 0;
- pevent->noteOffset = 0;
- pevent->reserved1 = 0;
- pevent->reserved2 = 0;
- pevent->noteOffVelocity = 0;
- pevent->midiData[0] = val1;
- pevent->midiData[1] = val2;
- pevent->midiData[2] = val3;
- pevent->midiData[3] = 0;
-
- //printf("Sending: %x %x %x\n",val1,val2,val3);
-
- jack_ringbuffer_write_advance (jvst->event_queue, sizeof (VstMidiEvent));
-}
-
-void *midireceiver(void *arg)
-{
- snd_seq_event_t *event;
- JackVST *jvst = (JackVST* )arg;
- int val;
-
- struct sched_param scp;
- scp.sched_priority = 50;
-
- // Try to set fifo priority...
- // this works, if we are root or newe sched-cap manegment is used...
- pthread_setschedparam( pthread_self(), SCHED_FIFO, &scp );
-
- while (1) {
-
- snd_seq_event_input (jvst->seq, &event);
-
- if (jvst->midiquit) {
- break;
- }
-
- switch(event->type){
- case SND_SEQ_EVENT_NOTEON:
- queue_midi(jvst,0x90+event->data.note.channel,event->data.note.note,event->data.note.velocity);
- //printf("Noteon, channel: %d note: %d vol: %d\n",event->data.note.channel,event->data.note.note,event->data.note.velocity);
- break;
- case SND_SEQ_EVENT_NOTEOFF:
- queue_midi(jvst,0x80+event->data.note.channel,event->data.note.note,0);
- //printf("Noteoff, channel: %d note: %d vol: %d\n",event->data.note.channel,event->data.note.note,event->data.note.velocity);
- break;
- case SND_SEQ_EVENT_KEYPRESS:
- //printf("Keypress, channel: %d note: %d vol: %d\n",event->data.note.channel,event->data.note.note,event->data.note.velocity);
- queue_midi(jvst,0xa0+event->data.note.channel,event->data.note.note,event->data.note.velocity);
- break;
- case SND_SEQ_EVENT_CONTROLLER:
- queue_midi(jvst,0xb0+event->data.control.channel,event->data.control.param,event->data.control.value);
- //printf("Control: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
- break;
- case SND_SEQ_EVENT_PITCHBEND:
- val=event->data.control.value + 0x2000;
- queue_midi(jvst,0xe0+event->data.control.channel,val&127,val>>7);
- //printf("Pitch: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
- break;
- case SND_SEQ_EVENT_CHANPRESS:
- //printf("chanpress: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
- queue_midi(jvst,0xd0+event->data.control.channel,event->data.control.value,0);
- break;
- case SND_SEQ_EVENT_PGMCHANGE:
- //printf("pgmchange: %d %d %d\n",event->data.control.channel,event->data.control.param,event->data.control.value);
- queue_midi(jvst,0xc0+event->data.control.channel,event->data.control.value,0);
- break;
- default:
- //printf("Unknown type: %d\n",event->type);
- break;
- }
- }
-
- return NULL;
-}
-
-void stop_midireceiver (JackVST *jvst)
-{
- int err;
- snd_seq_event_t event;
- snd_seq_t *seq2 = create_sequencer ("jfstquit", true);
-
- jvst->midiquit = 1;
-
- snd_seq_connect_to (seq2, 0, snd_seq_client_id (jvst->seq),0);
- snd_seq_ev_clear (&event);
- snd_seq_ev_set_direct (&event);
- snd_seq_ev_set_subs (&event);
- snd_seq_ev_set_source (&event, 0);
- snd_seq_ev_set_controller (&event,1,0x80,50);
-
- if ((err = snd_seq_event_output (seq2, &event)) < 0) {
- fst_error ("cannot send stop event to midi thread: %s\n",
- snd_strerror (err));
- }
-
- snd_seq_drain_output (seq2);
- snd_seq_close (seq2);
- pthread_join (jvst->midi_thread,NULL);
- snd_seq_close (jvst->seq);
-}
-#endif
-
-
if (fst->handle->plugincnt && --fst->handle->plugincnt == 0) {
fst->handle->main_entry = NULL;
- fst_unload (&fst->handle);
+ fst_unload (&fst->handle); // XXX
}
}