From: Paul Davis Date: Thu, 19 Feb 2009 14:01:59 +0000 (+0000) Subject: working VST support with VeSTige header and new FST code X-Git-Tag: 2.8.16~942 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=7885988df9c4a7690424952d9e8557fc87f3ae18;hp=ef4e7d7b4c318de046cf91ec93dfbda3eb557bf0;p=ardour.git working VST support with VeSTige header and new FST code git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@4637 d708f5d6-7413-0410-9779-e7cbd77b26cf --- diff --git a/SConstruct b/SConstruct index 1565768c0b..ebeb065ed8 100644 --- a/SConstruct +++ b/SConstruct @@ -394,28 +394,6 @@ tarball_bld = Builder (action = tarballer, env.Append (BUILDERS = {'Distribute' : dist_bld}) env.Append (BUILDERS = {'Tarball' : tarball_bld}) -# -# Make sure they know what they are doing -# - -if env['VST']: - if os.path.isfile('.personal_use_only'): - print "Enabling VST support. Note that distributing a VST-enabled ardour\nis a violation of several different licences.\nBuild with VST=false if you intend to distribute ardour to others." - else: - sys.stdout.write ("Are you building Ardour for personal use (rather than distribution to others)? [no]: ") - answer = sys.stdin.readline () - answer = answer.rstrip().strip() - if answer == "yes" or answer == "y": - fh = open('.personal_use_only', 'w') - fh.close() - print "OK, VST support will be enabled" - else: - print 'You cannot build Ardour with VST support for distribution to others.\nIt is a violation of several different licenses. Build with VST=false.' - sys.exit (-1); -else: - if os.path.isfile('.personal_use_only'): - os.remove('.personal_use_only') - #################### # push environment #################### diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index d9738e9dc0..5d79cf038d 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -248,10 +248,14 @@ sigpipe_handler (int sig) } #ifdef VST_SUPPORT + +extern int gui_init (int* argc, char** argv[]); + /* this is called from the entry point of a wine-compiled executable that is linked against gtk2_ardour built as a shared library. */ + extern "C" { int ardour_main (int argc, char *argv[]) #else @@ -267,6 +271,13 @@ int main (int argc, char* argv[]) Glib::thread_init(); gtk_set_locale (); +#ifdef VST_SUPPORT + /* this does some magic that is needed to make GTK and Wine's own + X11 client interact properly. + */ + gui_init (&argc, &argv); +#endif + (void) bindtextdomain (PACKAGE, localedir); /* our i18n translations are all in UTF-8, so make sure that even if the user locale doesn't specify UTF-8, diff --git a/gtk2_ardour/vst_pluginui.cc b/gtk2_ardour/vst_pluginui.cc index 6fee847123..6e39a0ba70 100644 --- a/gtk2_ardour/vst_pluginui.cc +++ b/gtk2_ardour/vst_pluginui.cc @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -76,6 +77,8 @@ VSTPluginUI::package (Gtk::Window& win) socket.add_id (fst_get_XID (vst->fst())); + fst_move_window_into_view (vst->fst()); + return 0; } @@ -118,3 +121,28 @@ VSTPluginUI::configure_handler (GdkEventConfigure* ev, Gtk::Socket *socket) return false; } +typedef int (*error_handler_t)( Display *, XErrorEvent *); +static Display *the_gtk_display; +static error_handler_t wine_error_handler; +static error_handler_t gtk_error_handler; + +static int +fst_xerror_handler( Display *disp, XErrorEvent *ev ) +{ + if (disp == the_gtk_display) { + printf ("relaying error to gtk\n"); + return gtk_error_handler (disp, ev); + } else { + printf( "relaying error to wine\n" ); + return wine_error_handler (disp, ev); + } +} + +void +gui_init (int *argc, char **argv[]) +{ + wine_error_handler = XSetErrorHandler (NULL); + gtk_init (argc, argv); + the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default()); + gtk_error_handler = XSetErrorHandler( fst_xerror_handler ); +} diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index ffaf87477a..cba634ccbf 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -32,9 +32,6 @@ #include #include #include -#ifdef VST_SUPPORT -#include -#endif #include diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 8e6b53095b..9ae697fd3b 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -330,15 +330,15 @@ ARDOUR::init (bool use_vst, bool try_optimization) #endif #ifdef VST_SUPPORT - if (Config->get_use_vst() && fst_init ()) { - return -1; + if (Config->get_use_vst() && fst_init (0)) { + return -1; } #endif #ifdef HAVE_AUDIOUNITS AUPluginInfo::load_cached_info (); #endif - + /* Make VAMP look in our library ahead of anything else */ char *p = getenv ("VAMP_PATH"); diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index d059f48acd..fc1cf8e9d1 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -522,7 +522,7 @@ PluginManager::vst_discover (string path) info->unique_id = buf; info->category = "VST"; info->path = path; - // need to set info->creator but FST doesn't provide it + info->creator = finfo->creator; info->index = 0; info->n_inputs = finfo->numInputs; info->n_outputs = finfo->numOutputs; diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc index 16233feba2..7c5daddd6f 100644 --- a/libs/ardour/session_vst.cc +++ b/libs/ardour/session_vst.cc @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -52,7 +52,7 @@ long Session::vst_callback (AEffect* effect, SHOW_CALLBACK ("am callback, opcode = %d", opcode); if (effect && effect->user) { - plug = static_cast (effect->user); + plug = (VSTPlugin*) (effect->user); session = &plug->session(); } else { plug = 0; diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index c30af3b3dc..7db67cdfbb 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -41,8 +41,6 @@ #include #include -#include - #include #include #include @@ -145,14 +143,14 @@ VSTPlugin::get_state() XMLNode *root = new XMLNode (state_node_name()); LocaleGuard lg (X_("POSIX")); - if (_plugin->flags & effFlagsProgramChunks) { + if (_plugin->flags & 32 /* effFlagsProgramChunks */) { /* fetch the current chunk */ void* data; long data_size; - if ((data_size = _plugin->dispatcher (_plugin, effGetChunk, 0, 0, &data, false)) == 0) { + if ((data_size = _plugin->dispatcher (_plugin, 23 /* effGetChunk */, 0, 0, &data, false)) == 0) { return *root; } @@ -205,6 +203,7 @@ VSTPlugin::get_state() } root->add_child_nocopy (*parameters); + } return *root; @@ -256,6 +255,7 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) 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) { @@ -291,6 +291,7 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) desc.logarithmic = false; desc.sr_dependent = false; desc.label = prop.label; +#endif } else { @@ -319,7 +320,8 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) bool VSTPlugin::load_preset (string name) { - if (_plugin->flags & effFlagsProgramChunks) { + + if (_plugin->flags & 32 /* effFlagsProgramChunks */) { error << _("no support for presets using chunks at this time") << endmsg; return false; @@ -330,11 +332,12 @@ VSTPlugin::load_preset (string name) bool VSTPlugin::save_preset (string name) { - if (_plugin->flags & effFlagsProgramChunks) { + if (_plugin->flags & 32 /* effFlagsProgramChunks */) { error << _("no support for presets using chunks at this time") << endmsg; return false; } + return Plugin::save_preset (name, "vst"); } @@ -349,7 +352,11 @@ VSTPlugin::describe_parameter (uint32_t param) nframes_t VSTPlugin::latency () const { - return _plugin->initialDelay; +#ifdef VESTIGE_HEADER + return *((nframes_t *) (((char *) &_plugin->flags) + 12)); /* initialDelay */ +#else + return 0; +#endif } set @@ -412,7 +419,11 @@ string VSTPlugin::unique_id() const { char buf[32]; +#ifdef VESTIGE_HEADER + snprintf (buf, sizeof (buf), "%d", *((int32_t*) &_plugin->unused_id)); +#else snprintf (buf, sizeof (buf), "%d", _plugin->uniqueID); +#endif return string (buf); } @@ -450,11 +461,9 @@ VSTPlugin::has_editor () const void VSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const { - char lab[9]; char *first_nonws; - _plugin->dispatcher (_plugin, effGetParamLabel, param, 0, lab, 0); - _plugin->dispatcher (_plugin, effGetParamDisplay, param, 0, buf, 0); + _plugin->dispatcher (_plugin, 7 /* effGetParamDisplay */, param, 0, buf, 0); if (buf[0] == '\0') { return; diff --git a/libs/fst/SConscript b/libs/fst/SConscript index 576283d73c..92c7504257 100644 --- a/libs/fst/SConscript +++ b/libs/fst/SConscript @@ -7,46 +7,18 @@ import glob fst_src = glob.glob('*.c') -Import('env install_prefix') +Import('env install_prefix libraries') fst = env.Clone(CC="winegcc") fst.Append (CPPPATH=".") +fst.Merge ([libraries['glib2']]) if fst['VST']: - vst_dir = Dir ('libs/vst') - vst_sdk_dir = Dir ('vstsdk2.3') - # - # if it exists, try to use the Steinberg zip package - # - vst_sdk_zip = File ('vstsdk2.3.zip') - - if os.access (vst_sdk_zip.abspath, os.F_OK): - print 'VST package discovered.' - elif os.access ('vst_sdk2_3.zip', os.F_OK): - # - # add a build target that unpacks the zip package the Steinberg "meta" zip package - # - vst_meta_zip = fst.Command (vst_sdk_zip, 'vst_sdk2_3.zip', "unzip -o -d ${TARGET.dir} $SOURCES vstsdk2.3.zip" ) - print 'VST meta-package discovered.' - else: - if os.access ('vstsdk2.3.zip', os.F_OK) != 1: - print 'Did not find vst_sdk2_3.zip or vstsdk2.3.zip in libs/fst.' - print 'Make sure the correct file is in the correct location and correctly named.' - print 'Please see http://ardour.org/building_vst_support for more information.' - sys.exit (1) - - vst_headers = fst.Command ([ 'vst/aeffectx.h', 'vst/AEffect.h' ], vst_sdk_zip, [ - "unzip -qq -d ${SOURCE.dir} -o $SOURCE", - Delete ('$TARGET.dir'), - Copy ('${TARGET.dir}', 'libs/fst/vstsdk2.3/source/common'), - "sed -i '/struct VstFileType\|struct VstFileSelect/,/};/d' $TARGET" - ]) - a = fst.Object ('fst', 'fst.c') b = fst.Object ('fstinfofile', 'fstinfofile.c') c = fst.Object ('vstwin', 'vstwin.c') d = fst.Object ('vsti', 'vsti.c') - Default([vst_headers,a,b,c,d]) + Default([a,b,c,d]) env.Alias('tarball', env.Distribute (env['DISTTREE'], fst_src + ['SConscript', diff --git a/libs/fst/fst.c b/libs/fst/fst.c index 85473578d2..cbee5de52a 100644 --- a/libs/fst/fst.c +++ b/libs/fst/fst.c @@ -3,15 +3,6 @@ #include "fst.h" - -void -default_fst_error_callback (const char *desc) -{ - fprintf(stderr, "%s\n", desc); -} - -void (*fst_error_callback)(const char *desc) = &default_fst_error_callback; - void fst_error (const char *fmt, ...) { @@ -24,4 +15,10 @@ fst_error (const char *fmt, ...) va_end (ap); } +void +default_fst_error_callback (const char *desc) +{ + fprintf(stderr, "%s\n", desc); +} +void (*fst_error_callback)(const char *desc) = &default_fst_error_callback; diff --git a/libs/fst/fst.h b/libs/fst/fst.h index 493cb2e572..2a0130667a 100644 --- a/libs/fst/fst.h +++ b/libs/fst/fst.h @@ -8,22 +8,28 @@ /** * Display FST error message. * - * @param fmt printf-style formatting specification + * Set via fst_set_error_function(), otherwise a FST-provided + * default will print @a msg (plus a newline) to stderr. + * + * @param msg error message text (no newline at end). */ -extern void fst_error (const char *fmt, ...); +extern void (*fst_error_callback)(const char *msg); /** * Set the @ref fst_error_callback for error message display. * * The FST library provides two built-in callbacks for this purpose: - * default_fst_error_callback(). - * - * The default will print the message (plus a newline) to stderr. - * + * default_fst_error_callback() and silent_fst_error_callback(). */ void fst_set_error_function (void (*func)(const char *)); -#include +void fst_error (const char *fmt, ...); + +#define VESTIGE_HEADER + +#ifdef VESTIGE_HEADER +#include +#endif typedef struct _FST FST; typedef struct _FSTHandle FSTHandle; @@ -32,6 +38,7 @@ typedef struct _FSTInfo FSTInfo; struct _FSTInfo { char *name; + char *creator; int UniqueID; char *Category; @@ -50,30 +57,46 @@ struct _FSTInfo char **ParamLabels; }; +typedef struct AEffect * (*main_entry_t)(audioMasterCallback); + struct _FSTHandle { void* dll; char* name; char* nameptr; /* ptr returned from strdup() etc. */ - AEffect* (*main_entry)(audioMasterCallback); + //struct AEffect* (*main_entry)(audioMasterCallback); + main_entry_t main_entry; int plugincnt; }; struct _FST { - AEffect* plugin; + struct AEffect* plugin; void* window; /* win32 HWND */ int xid; /* X11 XWindow */ FSTHandle* handle; int width; int height; + int wantIdle; int destroy; - struct _FST* next; + int want_program; + float *want_params; + float *set_params; + + int dispatcher_wantcall; + int dispatcher_opcode; + int dispatcher_index; + int dispatcher_val; + void * dispatcher_ptr; + float dispatcher_opt; + int dispatcher_retval; + struct _FST* next; pthread_mutex_t lock; pthread_cond_t window_status_change; + pthread_cond_t plugin_dispatcher_called; int been_activated; }; @@ -81,8 +104,7 @@ struct _FST extern "C" { #endif -extern int fst_init (); -extern void fst_finish (); +extern int fst_init (void* possible_hmodule); extern FSTHandle* fst_load (const char*); extern int fst_unload (FSTHandle*); @@ -90,17 +112,26 @@ extern int fst_unload (FSTHandle*); extern FST* fst_instantiate (FSTHandle*, audioMasterCallback amc, void* userptr); extern void fst_close (FST*); -extern void fst_event_loop_remove_plugin (FST* fst); -extern void fst_event_loop_add_plugin (FST* fst); - +extern int fst_create_editor (FST* fst); extern int fst_run_editor (FST*); extern void fst_destroy_editor (FST*); extern int fst_get_XID (FST*); +extern void fst_move_window_into_view (FST*); -extern void fst_signal_handler (int sig, siginfo_t* info, void* context); +extern FSTInfo *fst_get_info (char *dllpathname); +extern void fst_free_info (FSTInfo *info); +extern void fst_event_loop_remove_plugin (FST* fst); +extern int fst_call_dispatcher(FST *fst, int opcode, int index, int val, void *ptr, float opt ); -extern FSTInfo *fst_get_info( char *dllpathname ); -extern void fst_free_info( FSTInfo *info ); +/** + * Load a plugin state from a file. + */ +extern int fst_load_state (FST * fst, char * filename); + +/** + * Save a plugin state to a file. + */ +extern int fst_save_state (FST * fst, char * filename); #ifdef __cplusplus } diff --git a/libs/fst/fstinfofile.c b/libs/fst/fstinfofile.c index 7b0c69d015..2d7fb2fa6a 100644 --- a/libs/fst/fstinfofile.c +++ b/libs/fst/fstinfofile.c @@ -1,15 +1,13 @@ - #include "fst.h" -#include "vst/aeffectx.h" #include #include #include +#include #include #include #include -#include #define MAX_STRING_LEN 256 @@ -49,6 +47,7 @@ static FSTInfo *load_fst_info_file( char *filename ) { } 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; @@ -96,6 +95,7 @@ static int save_fst_info_file( FSTInfo *info, char *filename ) { } 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 ); @@ -123,7 +123,7 @@ static char *fst_dllpath_to_infopath( char *dllpath ) { if( strstr( dllpath, ".dll" ) == NULL ) return NULL; retval = strdup( dllpath ); - sprintf( retval + strlen(retval) - 4, ".fst" ); + sprintf( retval + strlen(retval) - 4, ".fsi" ); return retval; } @@ -144,7 +144,7 @@ static int fst_info_file_is_valid( char *dllpath ) { } static int fst_can_midi( FST *fst ) { - AEffect *plugin = fst->plugin; + struct AEffect *plugin = fst->plugin; int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f); if (vst_version >= 2) { @@ -160,8 +160,9 @@ static int fst_can_midi( FST *fst ) { } static FSTInfo *fst_info_from_plugin( FST *fst ) { FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) ); - AEffect *plugin; + struct AEffect *plugin; int i; + char creator[65]; if( ! fst ) { fst_error( "fst is NULL\n" ); @@ -174,7 +175,19 @@ static FSTInfo *fst_info_from_plugin( FST *fst ) { 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); + } + +#ifdef VESTIGE_HEADER + info->UniqueID = *((int32_t *) &plugin->unused_id); +#else info->UniqueID = plugin->uniqueID; +#endif + info->Category = strdup( "None" ); // FIXME: info->numInputs = plugin->numInputs; info->numOutputs = plugin->numOutputs; @@ -188,22 +201,20 @@ static FSTInfo *fst_info_from_plugin( FST *fst ) { for( i=0; inumParams; i++ ) { char name[20]; char label[9]; - plugin->dispatcher (plugin, - effGetParamName, - i, 0, name, 0); - - plugin->dispatcher (plugin, - effGetParamLabel, - i, 0, label, 0); - + 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 long simple_master_callback( AEffect *fx, long opcode, long index, long value, void *ptr, float opt ) { +static long simple_master_callback( struct AEffect *fx, long opcode, long index, long value, void *ptr, float opt ) { if( opcode == audioMasterVersion ) return 2; else @@ -227,9 +238,7 @@ FSTInfo *fst_get_info( char *dllpath ) { FSTInfo *info; char *fstpath; - if( !(h = fst_load( dllpath )) ) { - return NULL; - } + if( !(h = fst_load( dllpath )) ) return NULL; if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) { fst_unload( h ); fst_error( "instantiate failed\n" ); @@ -261,6 +270,7 @@ void fst_free_info( FSTInfo *info ) { free( info->ParamLabels[i] ); } free( info->name ); + free( info->creator ); free( info->Category ); free( info ); } diff --git a/libs/fst/jackvst.h b/libs/fst/jackvst.h index abb9e22e12..31e34f55b9 100644 --- a/libs/fst/jackvst.h +++ b/libs/fst/jackvst.h @@ -1,8 +1,8 @@ #ifndef __jack_vst_h__ #define __jack_vst_h__ -#include -#include +#include +#include #include #include #include @@ -16,15 +16,24 @@ struct _JackVST { FST* 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; + + int midi_map[128]; + volatile int midi_learn; + volatile int midi_learn_CC; + volatile int midi_learn_PARAM; int resume_called; + /* For VST/i support */ + int want_midi; pthread_t midi_thread; snd_seq_t* seq; int midiquit; @@ -32,4 +41,6 @@ struct _JackVST { struct VstEvents* events; }; +#define MIDI_EVENT_MAX 1024 + #endif /* __jack_vst_h__ */ diff --git a/libs/fst/vestige/aeffectx.h b/libs/fst/vestige/aeffectx.h new file mode 100644 index 0000000000..790c93e6dc --- /dev/null +++ b/libs/fst/vestige/aeffectx.h @@ -0,0 +1,288 @@ +/* + * aeffectx.h - simple header to allow VeSTige compilation and eventually work + * + * Copyright (c) 2006 Javier Serrano Polo + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef _AEFFECTX_H +#define _AEFFECTX_H + + +#define audioMasterAutomate 0 +#define audioMasterVersion 1 +#define audioMasterCurrentId 2 +#define audioMasterIdle 3 +#define audioMasterPinConnected 4 +// unsupported? 5 +#define audioMasterWantMidi 6 +#define audioMasterGetTime 7 +#define audioMasterProcessEvents 8 +#define audioMasterSetTime 9 +#define audioMasterTempoAt 10 +#define audioMasterGetNumAutomatableParameters 11 +#define audioMasterGetParameterQuantization 12 +#define audioMasterIOChanged 13 +#define audioMasterNeedIdle 14 +#define audioMasterSizeWindow 15 +#define audioMasterGetSampleRate 16 +#define audioMasterGetBlockSize 17 +#define audioMasterGetInputLatency 18 +#define audioMasterGetOutputLatency 19 +#define audioMasterGetPreviousPlug 20 +#define audioMasterGetNextPlug 21 +#define audioMasterWillReplaceOrAccumulate 22 +#define audioMasterGetCurrentProcessLevel 23 +#define audioMasterGetAutomationState 24 +#define audioMasterOfflineStart 25 +#define audioMasterOfflineRead 26 +#define audioMasterOfflineWrite 27 +#define audioMasterOfflineGetCurrentPass 28 +#define audioMasterOfflineGetCurrentMetaPass 29 +#define audioMasterSetOutputSampleRate 30 +// unsupported? 31 +#define audioMasterGetSpeakerArrangement 31 // deprecated in 2.4? +#define audioMasterGetVendorString 32 +#define audioMasterGetProductString 33 +#define audioMasterGetVendorVersion 34 +#define audioMasterVendorSpecific 35 +#define audioMasterSetIcon 36 +#define audioMasterCanDo 37 +#define audioMasterGetLanguage 38 +#define audioMasterOpenWindow 39 +#define audioMasterCloseWindow 40 +#define audioMasterGetDirectory 41 +#define audioMasterUpdateDisplay 42 +#define audioMasterBeginEdit 43 +#define audioMasterEndEdit 44 +#define audioMasterOpenFileSelector 45 +#define audioMasterCloseFileSelector 46// currently unused +#define audioMasterEditFile 47// currently unused +#define audioMasterGetChunkFile 48// currently unused +#define audioMasterGetInputSpeakerArrangement 49 // currently unused + +#define effFlagsHasEditor 1 +// very likely +#define effFlagsCanReplacing (1 << 4) +// currently unused +#define effFlagsIsSynth (1 << 8) + +#define effOpen 0 +//currently unused +#define effClose 1 +// currently unused +#define effSetProgram 2 +// currently unused +#define effGetProgram 3 +// currently unused +#define effGetProgramName 5 +#define effGetParamLabel 6 +// currently unused +#define effGetParamName 8 +// this is a guess +#define effSetSampleRate 10 +#define effSetBlockSize 11 +#define effMainsChanged 12 +#define effEditGetRect 13 +#define effEditOpen 14 +#define effEditClose 15 +#define effEditIdle 19 +#define effProcessEvents 25 +#define effGetEffectName 45 +// missing +#define effGetParameterProperties 47 +#define effGetVendorString 47 +#define effGetProductString 48 +#define effGetVendorVersion 49 +// currently unused +#define effCanDo 51 +// currently unused +#define effGetVstVersion 58 + +#ifdef WORDS_BIGENDIAN +// "VstP" +#define kEffectMagic 0x50747356 +#else +// "PtsV" +#define kEffectMagic 0x56737450 +#endif + +#define kVstLangEnglish 1 +#define kVstMidiType 1 +#define kVstTransportPlaying (1 << 1) +#define kVstParameterUsesFloatStep (1 << 2) +#define kVstTempoValid (1 << 10) +#define kVstBarsValid (1 << 11) +#define kVstTransportChanged 1 + +typedef struct VstMidiEvent +{ + // 00 + int type; + // 04 + int byteSize; + // 08 + int deltaFrames; + // 0c? + int flags; + // 10? + int noteLength; + // 14? + int noteOffset; + // 18 + char midiData[4]; + // 1c? + char detune; + // 1d? + char noteOffVelocity; + // 1e? + char reserved1; + // 1f? + char reserved2; + +} VstMidiEvent; + + + + +typedef struct VstEvent +{ + char dump[sizeof( VstMidiEvent )]; + +} VstEvent ; + + + + +typedef struct VstEvents +{ + // 00 + int numEvents; + // 04 + int reserved; + // 08 + VstEvent * events[]; +} VstEvents; + + + + +// Not finished, neither really used +typedef struct VstParameterProperties +{ + float stepFloat; + char label[64]; + int flags; + int minInteger; + int maxInteger; + int stepInteger; + char shortLabel[8]; + int category; + char categoryLabel[24]; + char empty[128]; + +} VstParameterProperties; + + + + +typedef struct AEffect +{ + // Never use c++!!! + // 00-03 + int magic; + // dispatcher 04-07 + int (* dispatcher)( struct AEffect * , int , int , int , void * , float ); + // process, quite sure 08-0b + void (* process)( struct AEffect * , float * * , float * * , int ); + // setParameter 0c-0f + void (* setParameter)( struct AEffect * , int , float ); + // getParameter 10-13 + float (* getParameter)( struct AEffect * , int ); + // programs 14-17 + int numPrograms; + // Params 18-1b + int numParams; + // Input 1c-1f + int numInputs; + // Output 20-23 + int numOutputs; + // flags 24-27 + int flags; + // Fill somewhere 28-2b + void * user; + // Zeroes 2c-2f 30-33 34-37 38-3b + char empty3[4 + 4 + 4 + 4]; + // 1.0f 3c-3f + float unkown_float; + // An object? pointer 40-43 + char empty4[4]; + // Zeroes 44-47 + char empty5[4]; + // Id 48-4b + char unused_id[4]; + // Don't know 4c-4f + char unknown1[4]; + // processReplacing 50-53 + void (* processReplacing)( struct AEffect * , float * * , float * * , int ); + + int uniqueID; + +} AEffect; + + + + +typedef struct VstTimeInfo +{ + // 00 + double samplePos; + // 08 + double sampleRate; + // unconfirmed 10 18 + char empty1[8 + 8]; + // 20? + double tempo; + // unconfirmed 28 30 38 + char empty2[8 + 8 + 8]; + // 40? + int timeSigNumerator; + // 44? + int timeSigDenominator; + // unconfirmed 48 4c 50 + char empty3[4 + 4 + 4]; + // 54 + int flags; + +} VstTimeInfo; + + + + +typedef long int (* audioMasterCallback)( AEffect * , long int , long int , + long int , void * , float ); +// we don't use it, may be noise +#define VSTCALLBACK + + + + +#endif diff --git a/libs/fst/vsti.c b/libs/fst/vsti.c index f6d8725ddf..6a64f9c5e4 100644 --- a/libs/fst/vsti.c +++ b/libs/fst/vsti.c @@ -30,7 +30,9 @@ #include #include #include -#include +#include +#include +#include snd_seq_t * create_sequencer (const char* client_name, bool isinput) @@ -74,7 +76,7 @@ queue_midi (JackVST *jvst, int val1, int val2, int val3) return; } - pevent = (struct VstMidiEevent *) vec[0].buf; + pevent = (struct VstMidiEvent *) vec[0].buf; // printf("note: %d\n",note); @@ -104,6 +106,13 @@ void *midireceiver(void *arg) 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); diff --git a/libs/fst/vstwin.c b/libs/fst/vstwin.c index 55061c2b72..fc9ac0c999 100644 --- a/libs/fst/vstwin.c +++ b/libs/fst/vstwin.c @@ -5,14 +5,12 @@ #include #include #include - -//#include -//#include -//#include -//#include +#include #include "fst.h" +#include +#include struct ERect{ short top; @@ -21,138 +19,28 @@ struct ERect{ short right; }; -static pthread_mutex_t plugin_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t plugin_mutex; static FST* fst_first = NULL; +const char magic[] = "FST Plugin State v002"; DWORD gui_thread_id = 0; -static char* message_name (int message) -{ - switch (message) { - case 0x0000: - return "WM_NULL"; - - case 0x0001: - return "WM_CREATE"; - - case 0x0002: - return "WM_DESTROY"; - - case 0x0003: - return "WM_MOVE"; - - case 0x0004: - return "WM_SIZEWAIT"; - - case 0x0005: - return "WM_SIZE"; - - case 0x0006: - return "WM_ACTIVATE"; - - case 0x0007: - return "WM_SETFOCUS"; - - case 0x0008: - return "WM_KILLFOCUS"; - - case 0x0009: - return "WM_SETVISIBLE"; - - case 0x000a: - return "WM_ENABLE"; - - case 0x000b: - return "WM_SETREDRAW"; - - case 0x000c: - return "WM_SETTEXT"; - - case 0x000d: - return "WM_GETTEXT"; - - case 0x000e: - return "WM_GETTEXTLENGTH"; - - case 0x000f: - return "WM_PAINT"; - - case 0x0010: - return "WM_CLOSE"; - - case 0x0011: - return "WM_QUERYENDSESSION"; - - case 0x0012: - return "WM_QUIT"; +extern boolean g_quit; - case 0x0013: - return "WM_QUERYOPEN"; - case 0x0014: - return "WM_ERASEBKGND"; - case 0x0015: - return "WM_SYSCOLORCHANGE"; - case 0x0016: - return "WM_ENDSESSION"; +#define DELAYED_WINDOW 1 - case 0x0017: - return "WM_SYSTEMERROR"; - case 0x0018: - return "WM_SHOWWINDOW"; - - case 0x0019: - return "WM_CTLCOLOR"; - - case 0x001a: - return "WM_WININICHANGE"; - - case 0x001b: - return "WM_DEVMODECHANGE"; - - case 0x001c: - return "WM_ACTIVATEAPP"; - - case 0x001d: - return "WM_FONTCHANGE"; - - case 0x001e: - return "WM_TIMECHANGE"; - - case 0x001f: - return "WM_CANCELMODE"; - - case 0x0020: - return "WM_SETCURSOR"; - - case 0x0021: - return "WM_MOUSEACTIVATE"; - - case 0x0022: - return "WM_CHILDACTIVATE"; - - case 0x0023: - return "WM_QUEUESYNC"; - - case 0x0024: - return "WM_GETMINMAXINFO"; - - default: - break; - } - return "--- OTHER ---"; -} - static LRESULT WINAPI my_window_proc (HWND w, UINT msg, WPARAM wp, LPARAM lp) { - FST* fst; + FST* fst=NULL; + LRESULT result; // if (msg != WM_TIMER) { -// fst_error ("window callback handler, msg = 0x%x (%s) win=%p\n", msg, message_name (msg), w); +// fst_error ("window callback handler, msg = 0x%x win=%p\n", msg, w); // } switch (msg) { @@ -161,39 +49,57 @@ my_window_proc (HWND w, UINT msg, WPARAM wp, LPARAM lp) break; case WM_CLOSE: + //printf("wtf.\n" ); PostQuitMessage (0); - case WM_DESTROY: case WM_NCDESTROY: /* we should never get these */ //return 0; break; - +#if 0 case WM_PAINT: - if ((fst = GetPropA (w, "fst_ptr")) != NULL) { - if (fst->window && !fst->been_activated) { - fst->been_activated = TRUE; - pthread_cond_signal (&fst->window_status_change); - pthread_mutex_unlock (&fst->lock); + if ((fst = GetPropA (w, "fst_ptr")) != NULL) { + if (fst->window && !fst->been_activated) { + fst->been_activated = TRUE; + pthread_cond_signal (&fst->window_status_change); + pthread_mutex_unlock (&fst->lock); + } } - } break; +#endif + +#if 0 + case WM_TIMER: + fst = GetPropA( w, "fst_ptr" ); + if( !fst ) { + printf( "Timer without fst_ptr Prop :(\n" ); + return 0; + } + + fst->plugin->dispatcher(fst->plugin, effEditIdle, 0, 0, NULL, 0.0f); + if( fst->wantIdle ) + fst->plugin->dispatcher(fst->plugin, 53, 0, 0, NULL, 0.0f); + return 0; +#endif + + default: break; } return DefWindowProcA (w, msg, wp, lp ); + //return 0; } static FST* fst_new () { FST* fst = (FST*) calloc (1, sizeof (FST)); - pthread_mutex_init (&fst->lock, NULL); pthread_cond_init (&fst->window_status_change, NULL); - + pthread_cond_init (&fst->plugin_dispatcher_called, NULL); + fst->want_program = -1; return fst; } @@ -204,102 +110,11 @@ fst_handle_new () return fst; } -int -fst_create_editor (FST* fst) -{ - HMODULE hInst; - HWND window; - - /* "guard point" to trap errors that occur during plugin loading */ - - /* Note: fst->lock is held while this function is called */ - - if (!(fst->plugin->flags & effFlagsHasEditor)) { - fst_error ("Plugin \"%s\" has no editor", fst->handle->name); - return -1; - } - - if ((hInst = GetModuleHandleA (NULL)) == NULL) { - fst_error ("can't get module handle"); - return 1; - } - -// if ((window = CreateWindowExA (WS_EX_TOOLWINDOW | WS_EX_TRAYWINDOW, "FST", fst->handle->name, - if ((window = CreateWindowExA (0, "FST", fst->handle->name, - (WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX), - 0, 0, 1, 1, - NULL, NULL, - hInst, - NULL)) == NULL) { - fst_error ("cannot create editor window"); - return 1; - } - - if (!SetPropA (window, "fst_ptr", fst)) { - fst_error ("cannot set fst_ptr on window"); - } - - fst->window = window; - fst->xid = (int) GetPropA (window, "__wine_x11_whole_window"); - - { - struct ERect* er; - - ShowWindow (fst->window, SW_SHOW); - - fst->plugin->dispatcher (fst->plugin, effEditOpen, 0, 0, fst->window, 0 ); - fst->plugin->dispatcher (fst->plugin, effEditGetRect, 0, 0, &er, 0 ); - - fst->width = er->right-er->left; - fst->height = er->bottom-er->top; - - SetWindowPos (fst->window, 0, 0, 0, er->right-er->left+8, er->bottom-er->top+26, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER); - } - - return 0; -} - -void -fst_destroy_editor (FST* fst) -{ - pthread_mutex_lock (&fst->lock); - if (fst->window) { - fst->destroy = TRUE; - if (!PostThreadMessageA (gui_thread_id, WM_USER, 0, 0)) { - fst_error ("could not post message to gui thread"); - } - pthread_cond_wait (&fst->window_status_change, &fst->lock); - - } - pthread_mutex_unlock (&fst->lock); -} - -void -fst_event_loop_remove_plugin (FST* fst) -{ - FST* p; - FST* prev; - - for (p = fst_first, prev = NULL; p->next; prev = p, p = p->next) { - if (p == fst) { - if (prev) { - prev->next = p->next; - } - } - } - - if (fst_first == fst) { - fst_first = fst_first->next; - } - -} - -void debreak( void ) { printf( "debreak\n" ); } - DWORD WINAPI gui_event_loop (LPVOID param) { MSG msg; FST* fst; + char c; HMODULE hInst; HWND window; @@ -314,29 +129,19 @@ DWORD WINAPI gui_event_loop (LPVOID param) if ((window = CreateWindowExA (0, "FST", "dummy", WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, + 9999, 9999, + 1, 1, NULL, NULL, hInst, NULL )) == NULL) { fst_error ("cannot create dummy timer window"); } - if (!SetTimer (window, 1000, 100, NULL)) { + if (!SetTimer (window, 1000, 20, NULL)) { fst_error ("cannot set timer on dummy window"); } - while (1) { - - GetMessageA (&msg, NULL, 0,0); - - if (msg.message == WM_SYSTEMERROR) { - /* sent when this thread is supposed to exist */ - break; - } - - if (msg.message == WM_KEYDOWN) debreak(); - + while (GetMessageA (&msg, NULL, 0,0)) { TranslateMessage( &msg ); DispatchMessageA (&msg); @@ -344,7 +149,7 @@ DWORD WINAPI gui_event_loop (LPVOID param) and run idle callbacks */ - if( msg.message == WM_TIMER ) { + if( msg.message == WM_TIMER ) { pthread_mutex_lock (&plugin_mutex); again: for (fst = fst_first; fst; fst = fst->next) { @@ -366,6 +171,7 @@ again: if (fst->window == NULL) { pthread_mutex_lock (&fst->lock); + fst_error ("Creating window for FST plugin %s", fst->handle->name); if (fst_create_editor (fst)) { fst_error ("cannot create editor for plugin %s", fst->handle->name); fst_event_loop_remove_plugin (fst); @@ -373,28 +179,66 @@ again: pthread_mutex_unlock (&fst->lock); goto again; } - /* condition/unlock handled when we receive WM_ACTIVATE */ + /* condition/unlock: it was signalled & unlocked in fst_create_editor() */ + } + if(fst->want_program != -1 ) { + fst->plugin->dispatcher (fst->plugin, effSetProgram, 0, fst->want_program, NULL, 0); + fst->want_program = -1; + } + + if(fst->dispatcher_wantcall) { + + pthread_mutex_lock (&fst->lock); + fst->dispatcher_retval = fst->plugin->dispatcher( fst->plugin, fst->dispatcher_opcode, + fst->dispatcher_index, + fst->dispatcher_val, + fst->dispatcher_ptr, + fst->dispatcher_opt ); + fst->dispatcher_wantcall = 0; + pthread_cond_signal (&fst->plugin_dispatcher_called); + pthread_mutex_unlock (&fst->lock); } + pthread_mutex_lock (&fst->lock); fst->plugin->dispatcher (fst->plugin, effEditIdle, 0, 0, NULL, 0); + if( fst->wantIdle ) { + fst->plugin->dispatcher (fst->plugin, 53, 0, 0, NULL, 0); + } + pthread_mutex_unlock (&fst->lock); } pthread_mutex_unlock (&plugin_mutex); } } - fst_error ("FST GUI event loop has quit!"); + fprintf (stderr, "VST GUI EVENT LOOP THREAD EXIT\n"); return 0; } int -fst_init () +fst_init (void* possible_hmodule) { - WNDCLASSA wc; + WNDCLASSEX wclass; HMODULE hInst; - - if ((hInst = GetModuleHandleA (NULL)) == NULL) { - fst_error ("can't get module handle"); - return -1; + + if (possible_hmodule) { + hInst = (HMODULE) possible_hmodule; + } else if ((hInst = GetModuleHandleA (NULL)) == NULL) { + fst_error ("can't get module handle"); + return -1; } + wclass.cbSize = sizeof(WNDCLASSEX); + wclass.style = 0; + wclass.lpfnWndProc = my_window_proc; + wclass.cbClsExtra = 0; + wclass.cbWndExtra = 0; + wclass.hInstance = hInst; + wclass.hIcon = LoadIcon(hInst, "FST"); + wclass.hCursor = LoadCursor(0, IDI_APPLICATION); +// wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wclass.lpszMenuName = "MENU_FST"; + wclass.lpszClassName = "FST"; + wclass.hIconSm = 0; + +#if 0 wc.style = 0; wc.lpfnWndProc = my_window_proc; wc.cbClsExtra = 0; @@ -403,32 +247,28 @@ fst_init () wc.hIcon = LoadIconA( hInst, "FST"); wc.hCursor = LoadCursorA( NULL, IDI_APPLICATION ); wc.hbrBackground = GetStockObject( BLACK_BRUSH ); - wc.lpszMenuName = "MENU_FST"; + wc.lpszMenuName = "FSTMENU"; wc.lpszClassName = "FST"; + //wc.hIconSm = 0; +#endif - if (!RegisterClassA(&wc)){ - return 1; + if (!RegisterClassExA(&wclass)){ + printf( "Class register failed :(\n" ); + return -1; } + fst_error ("Startup win32 GUI thread\n"); + if (CreateThread (NULL, 0, gui_event_loop, NULL, 0, NULL) == NULL) { fst_error ("could not create new thread proxy"); return -1; } - return 0; } -void -fst_finish () -{ - PostThreadMessageA (gui_thread_id, WM_SYSTEMERROR, 0, 0); -} - int fst_run_editor (FST* fst) { - /* Add the FST to the list of all that should be handled by the GUI thread */ - pthread_mutex_lock (&plugin_mutex); if (fst_first == NULL) { @@ -441,11 +281,6 @@ fst_run_editor (FST* fst) p->next = fst; } - if (!PostThreadMessageA (gui_thread_id, WM_USER, 0, 0)) { - fst_error ("could not post message to gui thread"); - return -1; - } - pthread_mutex_unlock (&plugin_mutex); /* wait for the plugin editor window to be created (or not) */ @@ -457,17 +292,196 @@ fst_run_editor (FST* fst) pthread_mutex_unlock (&fst->lock); if (!fst->window) { - fst_error ("no window created for VST plugin editor"); return -1; } return 0; } +int +fst_call_dispatcher (FST *fst, int opcode, int index, int val, void *ptr, float opt) +{ + pthread_mutex_lock (&fst->lock); + fst->dispatcher_opcode = opcode; + fst->dispatcher_index = index; + fst->dispatcher_val = val; + fst->dispatcher_ptr = ptr; + fst->dispatcher_opt = opt; + fst->dispatcher_wantcall = 1; + + pthread_cond_wait (&fst->plugin_dispatcher_called, &fst->lock); + pthread_mutex_unlock (&fst->lock); + + return fst->dispatcher_retval; +} + +int +fst_create_editor (FST* fst) +{ + HMODULE hInst; + char class[20]; + HWND window; + struct ERect* er; + + /* "guard point" to trap errors that occur during plugin loading */ + + /* Note: fst->lock is held while this function is called */ + + if (!(fst->plugin->flags & effFlagsHasEditor)) { + fst_error ("Plugin \"%s\" has no editor", fst->handle->name); + return -1; + } + + if ((hInst = GetModuleHandleA (NULL)) == NULL) { + fst_error ("can't get module handle"); + return 1; + } + +// if ((window = CreateWindowExA (WS_EX_TOOLWINDOW | WS_EX_TRAYWINDOW, "FST", fst->handle->name, + if ((window = CreateWindowExA (0, "FST", fst->handle->name, + (WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX), +// (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX), + 9999,9999,1,1, +// CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, + hInst, + NULL)) == NULL) { + fst_error ("cannot create editor window"); + return 1; + } + + if (!SetPropA (window, "fst_ptr", fst)) { + fst_error ("cannot set fst_ptr on window"); + } + + fst->window = window; +// fst->xid = (int) GetPropA (window, "__wine_x11_whole_window"); + + + //printf( "effEditOpen......\n" ); + fst->plugin->dispatcher (fst->plugin, effEditOpen, 0, 0, fst->window, 0 ); + fst->plugin->dispatcher (fst->plugin, effEditGetRect, 0, 0, &er, 0 ); + + fst->width = er->right-er->left; + fst->height = er->bottom-er->top; + //printf( "get rect ses... %d,%d\n", fst->width, fst->height ); + + //SetWindowPos (fst->window, 0, 9999, 9999, er->right-er->left+8, er->bottom-er->top+26, 0); + SetWindowPos (fst->window, 0, 9999, 9999, 2, 2, 0); + ShowWindow (fst->window, SW_SHOWNA); + //SetWindowPos (fst->window, 0, 0, 0, er->right-er->left+8, er->bottom-er->top+26, SWP_NOMOVE|SWP_NOZORDER); + + fst->xid = (int) GetPropA (window, "__wine_x11_whole_window"); + printf( "And xid = %x\n", fst->xid ); + fst->been_activated = TRUE; + printf ("Signalling window ready\n"); + pthread_cond_signal (&fst->window_status_change); + pthread_mutex_unlock (&fst->lock); + + return 0; +} + +void +fst_move_window_into_view (FST* fst) +{ + if (fst->window) { + SetWindowPos (fst->window, 0, 0, 0, fst->width, fst->height+24, 0); + ShowWindow (fst->window, SW_SHOWNA); + } +} + +void +fst_destroy_editor (FST* fst) +{ + FST* p; + FST* prev; + + pthread_mutex_lock (&fst->lock); + if (fst->window) { + fst->destroy = TRUE; + //if (!PostThreadMessageA (gui_thread_id, WM_USER, 0, 0)) { + //if (!PostThreadMessageA (gui_thread_id, WM_QUIT, 0, 0)) { + // fst_error ("could not post message to gui thread"); + //} + pthread_cond_wait (&fst->window_status_change, &fst->lock); + + } + pthread_mutex_unlock (&fst->lock); +} + +void +fst_event_loop_remove_plugin (FST* fst) +{ + FST* p; + FST* prev; + + for (p = fst_first, prev = NULL; p->next; prev = p, p = p->next) { + if (p == fst) { + if (prev) { + prev->next = p->next; + } + } + } + + if (fst_first == fst) { + fst_first = fst_first->next; + } + +} + +HMODULE +fst_load_vst_library(const char * path) +{ + HMODULE dll; + char * full_path; + char * envdup; + char * vst_path; + size_t len1; + size_t len2; + + if ((dll = LoadLibraryA (path)) != NULL) { + return dll; + } + + envdup = getenv ("VST_PATH"); + if (envdup == NULL) { + return NULL; + } + + envdup = strdup (envdup); + if (envdup == NULL) { + fst_error ("strdup failed"); + return NULL; + } + + len2 = strlen(path); + + vst_path = strtok (envdup, ":"); + while (vst_path != NULL) { + fst_error ("\"%s\"", vst_path); + len1 = strlen(vst_path); + full_path = malloc (len1 + 1 + len2 + 1); + memcpy(full_path, vst_path, len1); + full_path[len1] = '/'; + memcpy(full_path + len1 + 1, path, len2); + full_path[len1 + 1 + len2] = '\0'; + + if ((dll = LoadLibraryA (full_path)) != NULL) { + break; + } + + vst_path = strtok (NULL, ":"); + } + + free(envdup); + + return dll; +} + FSTHandle* fst_load (const char *path) { - char* buf; + char* buf, *buf2; FSTHandle* fhandle; char* period; @@ -509,14 +523,12 @@ fst_load (const char *path) *period = '\0'; } - if ((fhandle->dll = LoadLibraryA (buf)) == NULL) { + if ((fhandle->dll = fst_load_vst_library (buf)) == NULL) { fst_unload (fhandle); return NULL; } - typedef AEffect* (*entryFunctionType)(audioMasterCallback); - - if ((fhandle->main_entry = (entryFunctionType) GetProcAddress (fhandle->dll, "main")) == NULL) { + if ((fhandle->main_entry = (main_entry_t) GetProcAddress (fhandle->dll, "main")) == NULL) { fst_unload (fhandle); return NULL; } @@ -574,6 +586,7 @@ fst_instantiate (FSTHandle* fhandle, audioMasterCallback amc, void* userptr) //fst->plugin->dispatcher (fst->plugin, effMainsChanged, 0, 0, NULL, 0); fst->handle->plugincnt++; + fst->wantIdle = 0; return fst; } @@ -596,3 +609,203 @@ fst_get_XID (FST* fst) { return fst->xid; } + +float htonf (float v) +{ + float result; + char * fin = (char*)&v; + char * fout = (char*)&result; + fout[0] = fin[3]; + fout[1] = fin[2]; + fout[2] = fin[1]; + fout[3] = fin[0]; + return result; +} + +#if 0 +int fst_load_state (FST * fst, char * filename) +{ + FILE * f = fopen (filename, "rb"); + if (f) { + char testMagic[sizeof (magic)]; + fread (&testMagic, sizeof (magic), 1, f); + if (strcmp (testMagic, magic)) { + printf ("File corrupt\n"); + return FALSE; + } + + char productString[64]; + char vendorString[64]; + char effectName[64]; + char testString[64]; + unsigned length; + int success; + + fread (&length, sizeof (unsigned), 1, f); + length = htonl (length); + fread (productString, length, 1, f); + productString[length] = 0; + printf ("Product string: %s\n", productString); + + success = fst_call_dispatcher( fst, effGetProductString, 0, 0, testString, 0 ); + if (success == 1) { + if (strcmp (testString, productString) != 0) { + printf ("Product string mismatch! Plugin has: %s\n", testString); + fclose (f); + return FALSE; + } + } else if (length != 0) { + printf ("Product string mismatch! Plugin has none.\n", testString); + fclose (f); + return FALSE; + } + + fread (&length, sizeof (unsigned), 1, f); + length = htonl (length); + fread (effectName, length, 1, f); + effectName[length] = 0; + printf ("Effect name: %s\n", effectName); + + success = fst_call_dispatcher( fst, effGetEffectName, 0, 0, testString, 0 ); + if (success == 1) { + if (strcmp (testString, effectName) != 0) { + printf ("Effect name mismatch! Plugin has: %s\n", testString); + fclose (f); + return FALSE; + } + } else if (length != 0) { + printf ("Effect name mismatch! Plugin has none.\n", testString); + fclose (f); + return FALSE; + } + + fread (&length, sizeof (unsigned), 1, f); + length = htonl (length); + fread (vendorString, length, 1, f); + vendorString[length] = 0; + printf ("Vendor string: %s\n", vendorString); + + success = fst_call_dispatcher( fst, effGetVendorString, 0, 0, testString, 0 ); + if (success == 1) { + if (strcmp (testString, vendorString) != 0) { + printf ("Vendor string mismatch! Plugin has: %s\n", testString); + fclose (f); + return FALSE; + } + } else if (length != 0) { + printf ("Vendor string mismatch! Plugin has none.\n", testString); + fclose (f); + return FALSE; + } + + int numParam; + unsigned i; + fread (&numParam, sizeof (int), 1, f); + numParam = htonl (numParam); + for (i = 0; i < numParam; ++i) { + float val; + fread (&val, sizeof (float), 1, f); + val = htonf (val); + + pthread_mutex_lock( &fst->lock ); + fst->plugin->setParameter( fst->plugin, i, val ); + pthread_mutex_unlock( &fst->lock ); + } + + int bytelen; + fread (&bytelen, sizeof (int), 1, f); + bytelen = htonl (bytelen); + if (bytelen) { + char * buf = malloc (bytelen); + fread (buf, bytelen, 1, f); + + fst_call_dispatcher( fst, 24, 0, bytelen, buf, 0 ); + free (buf); + } + } else { + printf ("Could not open state file\n"); + return FALSE; + } + return TRUE; + +} +#endif + +int fst_save_state (FST * fst, char * filename) +{ + FILE * f = fopen (filename, "wb"); + if (f) { + int bytelen; + int numParams = fst->plugin->numParams; + unsigned i; + char productString[64]; + char effectName[64]; + char vendorString[64]; + int success; + unsigned length; + + // write header + fprintf( f, "\n" ); + + success = fst_call_dispatcher( fst, effGetProductString, 0, 0, productString, 0 ); + if( success == 1 ) { + fprintf (f, " \n", productString); + } else { + printf ("No product string\n"); + } + + success = fst_call_dispatcher( fst, effGetEffectName, 0, 0, effectName, 0 ); + if( success == 1 ) { + fprintf (f, " \n", effectName); + printf ("Effect name: %s\n", effectName); + } else { + printf ("No effect name\n"); + } + + success = fst_call_dispatcher( fst, effGetVendorString, 0, 0, vendorString, 0 ); + if( success == 1 ) { + fprintf (f, " \n", vendorString); + printf ("Vendor string: %s\n", vendorString); + } else { + printf ("No vendor string\n"); + } + + + if( fst->plugin->flags & 32 ) { + numParams = 0; + } + + for( i=0; ilock ); + val = fst->plugin->getParameter( fst->plugin, i ); + pthread_mutex_unlock( &fst->lock ); + fprintf( f, " \n", i, val ); + } + + if( fst->plugin->flags & 32 ) { + printf( "getting chunk...\n" ); + void * chunk; + bytelen = fst_call_dispatcher( fst, 23, 0, 0, &chunk, 0 ); + printf( "got tha chunk..\n" ); + if( bytelen ) { + if( bytelen < 0 ) { + printf( "Chunke len < 0 !!! Not saving chunk.\n" ); + } else { + char *encoded = g_base64_encode( chunk, bytelen ); + fprintf( f, " \n %s\n \n", bytelen, encoded ); + g_free( encoded ); + } + } + } + + fprintf( f, "\n" ); + fclose( f ); + } else { + printf ("Could not open state file\n"); + return FALSE; + } + return TRUE; +} + diff --git a/vst/ardevst b/vst/ardevst index cc21cde05b..c040dbbacf 100755 --- a/vst/ardevst +++ b/vst/ardevst @@ -1,5 +1,6 @@ #!/bin/sh -export ARDOUR_PATH=../gtk2_ardour/icons:../gtk2_ardour/pixmaps:../gtk2_ardour -export LD_LIBRARY_PATH=../gtk2_ardour:../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:../libs/appleutility:../libs/rubberband:../libs/vamp-sdk:$LD_LIBRARY_PATH -export GTK_PATH=$PWD/../libs/clearlooks:~/.ardour2 -exec wine ./ardour_vst.exe.so "$@" + +. ../gtk2_ardour/ardev_common.sh + +export LD_LIBRARY_PATH=gtk2_ardour:$LD_LIBRARY_PATH +exec wine ./vst/ardour_vst.exe.so "$@" diff --git a/vst/winmain.c b/vst/winmain.c index c2ad5fc6bd..3721932cd7 100644 --- a/vst/winmain.c +++ b/vst/winmain.c @@ -1,17 +1,12 @@ #include #include #include +#include extern int ardour_main(int argc, char* argv[]); int main (int argc, char* argv[]) { - // call the user specified main function - - int result = ardour_main(argc, argv); - printf ("main returned %d\n", result); - - return result; - + return ardour_main(argc, argv); }