Rename linux VST files to be more friendly.
authorCarl Hetherington <carl@carlh.net>
Wed, 23 Nov 2011 19:31:04 +0000 (19:31 +0000)
committerCarl Hetherington <carl@carlh.net>
Wed, 23 Nov 2011 19:31:04 +0000 (19:31 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@10808 d708f5d6-7413-0410-9779-e7cbd77b26cf

14 files changed:
gtk2_ardour/linux_vst_gui_support.cc [new file with mode: 0644]
gtk2_ardour/lxvst_plugin_ui.cc
gtk2_ardour/vstfxwin.cc [deleted file]
gtk2_ardour/wscript
libs/ardour/ardour/vstfx.h [deleted file]
libs/ardour/globals.cc
libs/ardour/linux_vst_info_file.cc [new file with mode: 0644]
libs/ardour/linux_vst_support.cc [new file with mode: 0644]
libs/ardour/lxvst_plugin.cc
libs/ardour/plugin_manager.cc
libs/ardour/test/dummy_lxvst.cc
libs/ardour/vstfx.cc [deleted file]
libs/ardour/vstfxinfofile.cc [deleted file]
libs/ardour/wscript

diff --git a/gtk2_ardour/linux_vst_gui_support.cc b/gtk2_ardour/linux_vst_gui_support.cc
new file mode 100644 (file)
index 0000000..161b649
--- /dev/null
@@ -0,0 +1,759 @@
+/******************************************************************/
+/** VSTFX - An engine based on FST for handling linuxVST plugins **/
+/******************************************************************/
+
+/*This is derived from the original FST (C code) with some tweaks*/
+
+
+/** EDITOR tab stops at 4 **/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <jack/jack.h>
+#include <jack/thread.h>
+#include <libgen.h>
+
+#include <pthread.h>
+#include <signal.h>
+#include <glib.h>
+
+#include "ardour/linux_vst_support.h"
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <pthread.h>
+
+struct ERect{
+    short top;
+    short left;
+    short bottom;
+    short right;
+};
+
+static pthread_mutex_t plugin_mutex;
+
+static VSTState * vstfx_first = NULL;
+
+const char magic[] = "VSTFX Plugin State v002";
+
+int  gui_thread_id = 0;
+static int gui_quit = 0;
+
+/*This will be our connection to X*/
+
+Display* LXVST_XDisplay = NULL;
+
+/*The thread handle for the GUI event loop*/
+
+pthread_t LXVST_gui_event_thread;
+
+/*Util functions to get the value of a property attached to an XWindow*/
+
+bool LXVST_xerror;
+
+int TempErrorHandler(Display *display, XErrorEvent *e)
+{
+       LXVST_xerror = true;
+       
+       return 0;
+}
+
+#ifdef LXVST_32BIT
+
+int getXWindowProperty(Window window, Atom atom)
+{
+       int result = 0;
+       int userSize;
+       unsigned long bytes;
+       unsigned long userCount;
+       unsigned char *data;
+       Atom userType;
+       LXVST_xerror = false;
+       
+       /*Use our own Xerror handler while we're in here - in an
+       attempt to stop the brain dead default Xerror behaviour of
+       qutting the entire application because of e.g. an invalid
+       window ID*/
+       
+       XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler);
+       
+       XGetWindowProperty(     LXVST_XDisplay,                 //The display
+                                               window,                                 //The Window
+                                               atom,                                   //The property
+                                               0,                                              //Offset into the data
+                                               1,                                              //Number of 32Bit chunks of data
+                                               false,                                  //false = don't delete the property
+                                               AnyPropertyType,                //Required property type mask
+                                               &userType,                              //Actual type returned
+                                               &userSize,                              //Actual format returned
+                                               &userCount,                             //Actual number of items stored in the returned data
+                                               &bytes,                                 //Number of bytes remaining if a partial read
+                                               &data);                                 //The actual data read
+                                               
+       if(LXVST_xerror == false && userCount == 1)
+               result = *(int*)data;
+               
+       XSetErrorHandler(olderrorhandler);
+       
+       /*Hopefully this will return zero if the property is not set*/
+       
+       return result;
+}
+
+#endif
+
+#ifdef LXVST_64BIT
+
+/********************************************************************/
+/* This is untested - have no 64Bit plugins which use this          */
+/* system of passing an eventProc address                           */
+/********************************************************************/
+
+long getXWindowProperty(Window window, Atom atom)
+{
+       long result = 0;
+       int userSize;
+       unsigned long bytes;
+       unsigned long userCount;
+       unsigned char *data;
+       Atom userType;
+       LXVST_xerror = false;
+       
+       /*Use our own Xerror handler while we're in here - in an
+       attempt to stop the brain dead default Xerror behaviour of
+       qutting the entire application because of e.g. an invalid
+       window ID*/
+       
+       XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler);
+       
+       XGetWindowProperty(     LXVST_XDisplay, 
+                                               window, 
+                                               atom,
+                                               0,
+                                               2,
+                                               false,
+                                               AnyPropertyType, 
+                                               &userType,
+                                               &userSize,
+                                               &userCount,
+                                               &bytes,
+                                               &data);
+                                               
+       if(LXVST_xerror == false && userCount == 1)
+               result = *(long*)data;
+               
+       XSetErrorHandler(olderrorhandler);
+       
+       /*Hopefully this will return zero if the property is not set*/
+       
+       return result;
+}
+
+#endif
+
+/*The event handler - called from within the main GUI thread to
+dispatch events to any VST UIs which have callbacks stuck to them*/
+
+static void
+dispatch_x_events (XEvent* event, VSTState* vstfx)
+{
+       /*Handle some of the Events we might be interested in*/
+       
+       switch(event->type)
+       {
+               /*Configure event - when the window is resized or first drawn*/
+                       
+               case ConfigureNotify:
+               {
+                       Window window = event->xconfigure.event;
+                       
+                       int width = event->xconfigure.width;
+                       int height = event->xconfigure.height;
+                       
+                       /*If we get a config notify on the parent window XID then we need to see
+                       if the size has been changed - some plugins re-size their UI window e.g.
+                       when opening a preset manager (you might think that should be spawned as a new window...) */
+                       
+                       /*if the size has changed, we flag this so that in lxvst_pluginui.cc we can make the
+                       change to the GTK parent window in ardour, from its UI thread*/ 
+                       
+                       if (window == (Window) (vstfx->linux_window)) {
+                               if (width != vstfx->width || height!=vstfx->height) {
+                                       vstfx->width = width;
+                                       vstfx->height = height;
+                                       vstfx->want_resize = 1;
+                                       
+                                       /*QUIRK : Loomer plugins not only resize the UI but throw it into some random
+                                       position at the same time. We need to re-position the window at the origin of
+                                       the parent window*/
+                                       
+                                       if (vstfx->linux_plugin_ui_window) {
+                                               XMoveWindow (LXVST_XDisplay, vstfx->linux_plugin_ui_window, 0, 0);
+                                       }
+                               }
+                       }
+                       
+                       break;
+                       
+               }
+               
+               /*Reparent Notify - when the plugin UI is reparented into
+               our Host Window we will get an event here... probably... */
+               
+               case ReparentNotify:
+               {
+                       Window ParentWindow = event->xreparent.parent;
+                       
+                       /*If the ParentWindow matches the window for the vstfx instance then
+                       the Child window must be the XID of the pluginUI window created by the
+                       plugin, so we need to see if it has a callback stuck to it, and if so
+                       set that up in the vstfx */
+                       
+                       /***********************************************************/
+                       /* 64Bit --- This mechanism is not 64Bit compatible at the */
+                       /* present time                                            */
+                       /***********************************************************/
+                       
+                       if (ParentWindow == (Window) (vstfx->linux_window)) {
+
+                               Window PluginUIWindowID = event->xreparent.window;
+                               
+                               vstfx->linux_plugin_ui_window = PluginUIWindowID;
+#ifdef LXVST_32BIT
+                               int result = getXWindowProperty(PluginUIWindowID, XInternAtom(LXVST_XDisplay, "_XEventProc", false));
+       
+                               if (result == 0) {
+                                       vstfx->eventProc = NULL;
+                               } else {
+                                       vstfx->eventProc = (void (*) (void* event))result;
+                               }
+#endif
+#ifdef LXVST_64BIT
+                               long result = getXWindowProperty(PluginUIWindowID, XInternAtom(LXVST_XDisplay, "_XEventProc", false));
+       
+                               if(result == 0)
+                                       vstfx->eventProc = NULL;
+                               else
+                                       vstfx->eventProc = (void (*) (void* event))result;
+#endif
+                       }
+                       break;
+               }
+               
+               case ClientMessage:
+               {
+                       Window window = event->xany.window;
+                       Atom message_type = event->xclient.message_type;
+                       
+                       /*The only client message we are interested in is to signal
+                       that the plugin parent window is now valid and can be passed
+                       to effEditOpen when the editor is launched*/
+                       
+                       if (window == (Window) (vstfx->linux_window)) {
+                               char* message = XGetAtomName(LXVST_XDisplay, message_type);
+                               
+                               if (strcmp(message,"LaunchEditor") == 0) {
+                                       if (event->xclient.data.l[0] == 0x0FEEDBAC) {
+                                               vstfx_launch_editor (vstfx);
+                                       }
+                               }
+                               
+                               XFree(message);
+                       }
+                       break;
+               }
+               
+               default:
+                       break;
+       }
+       
+       /* Some VSTs built with toolkits e.g. JUCE will manager their own UI
+       autonomously in the plugin, running the UI in its own thread, so once
+       we have created a parent window for the plugin, its UI takes care of
+       itself.*/
+       
+       /*Other types register a callback as an Xwindow property on the plugin
+       UI window after they create it.  If that is the case, we need to call it
+       here, passing the XEvent into it*/
+       
+       if (vstfx->eventProc == NULL) {
+               return;
+       }
+                               
+       vstfx->eventProc((void*)event);
+}
+
+static void
+maybe_set_program (VSTState* vstfx)
+{
+       if (vstfx->want_program != -1) {
+               if (vstfx->vst_version >= 2) {
+                       vstfx->plugin->dispatcher (vstfx->plugin, 67 /* effBeginSetProgram */, 0, 0, NULL, 0);
+               }
+
+               vstfx->plugin->dispatcher (vstfx->plugin, effSetProgram, 0, vstfx->want_program, NULL, 0);
+               
+               if (vstfx->vst_version >= 2) {
+                       vstfx->plugin->dispatcher (vstfx->plugin, 68 /* effEndSetProgram */, 0, 0, NULL, 0);
+               }
+               
+               vstfx->want_program = -1; 
+       }
+
+       if (vstfx->want_chunk == 1) {
+               vstfx->plugin->dispatcher (vstfx->plugin, 24 /* effSetChunk */, 1, vstfx->wanted_chunk_size, vstfx->wanted_chunk, 0);
+               vstfx->want_chunk = 0;
+       }
+}
+
+/** This is the main gui event loop for the plugin, we also need to pass
+any Xevents to all the UI callbacks plugins 'may' have registered on their
+windows, that is if they don't manage their own UIs **/
+
+void* gui_event_loop (void* ptr)
+{
+       VSTState* vstfx;
+       int LXVST_sched_event_timer = 0;
+       int LXVST_sched_timer_interval = 50; //ms
+       XEvent event;
+       
+       /*The 'Forever' loop - runs the plugin UIs etc - based on the FST gui event loop*/
+       
+       while (!gui_quit)
+       {
+               /* handle window creation requests, destroy requests, 
+                  and run idle callbacks */
+
+               /*Look at the XEvent queue - if there are any XEvents we need to handle them,
+               including passing them to all the plugin (eventProcs) we are currently managing*/
+               
+               if(LXVST_XDisplay)
+               {
+                       /*See if there are any events in the queue*/
+               
+                       int num_events = XPending(LXVST_XDisplay);
+                       
+                       /*process them if there are any*/
+               
+                       while(num_events)
+                       {
+                               XNextEvent(LXVST_XDisplay, &event);
+                               
+                               /*Call dispatch events, with the event, for each plugin in the linked list*/
+                               
+                               for (vstfx = vstfx_first; vstfx; vstfx = vstfx->next)
+                               {       
+                                       pthread_mutex_lock(&vstfx->lock);
+                                       
+                                       dispatch_x_events(&event, vstfx);
+                                       
+                                       pthread_mutex_unlock(&vstfx->lock);
+                               }
+                               
+                               num_events--;
+                       }
+               }
+
+               /*We don't want to use all the CPU.. */
+
+               usleep(1000);
+               
+               LXVST_sched_event_timer++;
+               
+               LXVST_sched_event_timer = LXVST_sched_event_timer & 0x00FFFFFF;
+
+               /*See if its time for us to do a scheduled event pass on all the plugins*/
+
+               if((LXVST_sched_timer_interval!=0) && (!(LXVST_sched_event_timer% LXVST_sched_timer_interval)))
+               {
+                       pthread_mutex_lock (&plugin_mutex);
+                   
+again:
+                       /*Parse through the linked list of plugins*/
+                       
+                       for (vstfx = vstfx_first; vstfx; vstfx = vstfx->next)
+                       {       
+                               pthread_mutex_lock (&vstfx->lock);
+
+                               /*Window scheduled for destruction*/
+                               
+                               if (vstfx->destroy) {
+                                       if (vstfx->linux_window) {
+                                               vstfx->plugin->dispatcher (vstfx->plugin, effEditClose, 0, 0, NULL, 0.0);
+                                                       
+                                               XDestroyWindow (LXVST_XDisplay, vstfx->linux_window);
+                                               /* FIXME - probably safe to assume we never have an XID of 0 but not explicitly true */
+                                               vstfx->linux_window = 0;
+                                               vstfx->destroy = FALSE;
+                                       }
+                                       
+                                       vstfx_event_loop_remove_plugin (vstfx);
+                                       vstfx->been_activated = FALSE;
+                                       pthread_cond_signal (&vstfx->window_status_change);
+                                       pthread_mutex_unlock (&vstfx->lock);
+                                       
+                                       goto again;
+                               } 
+                               
+                               /*Window does not yet exist - scheduled for creation*/
+
+                               /* FIXME - probably safe to assume 0 is not a valid XID but not explicitly true */
+                               if (vstfx->linux_window == 0) {
+                                       if (vstfx_create_editor (vstfx)) {
+                                               vstfx_error ("** ERROR ** VSTFX : Cannot create editor for plugin %s", vstfx->handle->name);
+                                               vstfx_event_loop_remove_plugin (vstfx);
+                                               pthread_cond_signal (&vstfx->window_status_change);
+                                               pthread_mutex_unlock (&vstfx->lock);
+                                               goto again;
+                                       } else {
+                                               /* condition/unlock: it was signalled & unlocked in fst_create_editor()   */
+                                       }
+                               }
+
+                               maybe_set_program (vstfx);
+                               vstfx->want_program = -1;
+                               vstfx->want_chunk = 0;
+                               
+                               /*scheduled call to dispatcher*/
+                               
+                               if (vstfx->dispatcher_wantcall) {
+                                       vstfx->dispatcher_retval = vstfx->plugin->dispatcher (
+                                               vstfx->plugin, 
+                                               vstfx->dispatcher_opcode,
+                                               vstfx->dispatcher_index,
+                                               vstfx->dispatcher_val,
+                                               vstfx->dispatcher_ptr,
+                                               vstfx->dispatcher_opt
+                                               );
+                                       
+                                       vstfx->dispatcher_wantcall = 0;
+                                       pthread_cond_signal (&vstfx->plugin_dispatcher_called);
+                               }
+                               
+                               /*Call the editor Idle function in the plugin*/
+                               
+                               vstfx->plugin->dispatcher (vstfx->plugin, effEditIdle, 0, 0, NULL, 0);
+
+                               if(vstfx->wantIdle)
+                                       vstfx->plugin->dispatcher (vstfx->plugin, 53, 0, 0, NULL, 0);
+                                       
+                               pthread_mutex_unlock (&vstfx->lock);
+                       }
+                       pthread_mutex_unlock (&plugin_mutex);
+               }
+       }
+
+       /*Drop out to here if we set gui_quit to 1 */
+
+       return NULL;
+}
+
+/*The VSTFX Init function - this needs to be called before the VSTFX engine
+can be accessed, it gets the UI thread running, opens a connection to X etc
+normally started in globals.cc*/
+
+int vstfx_init (void* ptr)
+{
+
+       int thread_create_result;
+       
+       pthread_attr_t thread_attributes;
+       
+       /*Init the attribs to defaults*/
+       
+       pthread_attr_init(&thread_attributes);
+       
+       /*Make sure the thread is joinable - this should be the default anyway - 
+       so we can join to it on vstfx_exit*/
+       
+       pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);
+       
+
+       /*This is where we need to open a connection to X, and start the GUI thread*/
+       
+       /*Open our connection to X - all linuxVST plugin UIs handled by the LXVST engine
+       will talk to X down this connection - X cannot handle multi-threaded access via
+       the same Display* */
+       
+       if(LXVST_XDisplay==NULL)
+               LXVST_XDisplay = XOpenDisplay(NULL);    //We might be able to make this open a specific screen etc
+
+       /*Drop out and report the error if we fail to connect to X */
+       
+       if(LXVST_XDisplay==NULL)
+       {
+               vstfx_error ("** ERROR ** VSTFX: Failed opening connection to X");
+               
+               return -1;
+       }
+       
+       /*We have a connection to X - so start the gui event loop*/
+       
+       /*Create the thread - use default attrs for now, don't think we need anything special*/
+       
+       thread_create_result = pthread_create(&LXVST_gui_event_thread, NULL, gui_event_loop, NULL);
+       
+       if(thread_create_result!=0)
+       {
+               /*There was a problem starting the GUI event thread*/
+               
+               vstfx_error ("** ERROR ** VSTFX: Failed starting GUI event thread");
+               
+               XCloseDisplay(LXVST_XDisplay);
+               
+               return -1;
+       }
+       
+       return 0;
+}
+
+/*The vstfx Quit function*/
+
+void vstfx_exit()
+{
+       gui_quit = 1;
+       
+       /*We need to pthread_join the gui_thread here so
+       we know when it has stopped*/
+       
+       pthread_join(LXVST_gui_event_thread, NULL);
+}
+
+/*Adds a new plugin (VSTFX) instance to the linked list*/
+
+int vstfx_run_editor (VSTState* vstfx)
+{
+       pthread_mutex_lock (&plugin_mutex);
+
+       /* Add the new VSTFX instance to the linked list */
+
+       if (vstfx_first == NULL) {
+               vstfx_first = vstfx;
+       } else {
+               VSTState* p = vstfx_first;
+               
+               while (p->next) {
+                       p = p->next;
+               }
+               p->next = vstfx;
+               
+               /* Mark the new end of the list */
+               
+               vstfx->next = NULL;
+       }
+
+       pthread_mutex_unlock (&plugin_mutex);
+
+       /* wait for the plugin editor window to be created (or not) */
+
+       pthread_mutex_lock (&vstfx->lock);
+       
+       if (!vstfx->linux_window) {
+               pthread_cond_wait (&vstfx->window_status_change, &vstfx->lock);
+       }
+       
+       pthread_mutex_unlock (&vstfx->lock);
+
+       if (!vstfx->linux_window) {
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/*Creates an editor for the plugin - normally called from within the gui event loop
+after run_editor has added the plugin (editor) to the linked list*/
+
+int vstfx_create_editor (VSTState* vstfx)
+{
+       Window parent_window;
+       
+       int x_size = 1;
+       int y_size = 1;
+
+       /* Note: vstfx->lock is held while this function is called */
+
+       if (!(vstfx->plugin->flags & effFlagsHasEditor))
+       {
+               vstfx_error ("** ERROR ** VSTFX: Plugin \"%s\" has no editor", vstfx->handle->name);
+               return -1;
+       }
+       
+       
+       /*Create an XWindow for the plugin to inhabit*/
+       
+       parent_window = XCreateSimpleWindow (
+               LXVST_XDisplay,
+               DefaultRootWindow(LXVST_XDisplay),
+               0,
+               0,
+               x_size,
+               y_size,
+               0,
+               0,
+               0
+               );
+                                                                               
+       /*Select the events we are interested in receiving - we need Substructure notify so that
+       if the plugin resizes its window - e.g. Loomer Manifold then we get a message*/
+       
+       XSelectInput(LXVST_XDisplay, 
+                               parent_window,
+                               SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask);
+                                                                               
+       vstfx->linux_window = parent_window;
+                                                                               
+       vstfx->xid = parent_window;  //vstfx->xid will be referenced to connect to GTK UI in ardour later
+       
+       /*Because the plugin may be operating on a different Display* to us, and therefore
+       the two event queues can be asynchronous, although we have created the window on
+       our display, we can't guarantee it exists in the server yet, which will
+       cause BadWindow crashes if the plugin tries to use it.
+       
+       It would be nice to use CreateNotify events here, but they don't get
+       through on all window managers, so instead we pass a client message
+       into out queue, after the XCreateWindow.  When this message pops out
+       in our event handler, it will trigger the second stage of plugin
+       Editor instantiation, and by then the Window should be valid...*/
+       
+       XClientMessageEvent event;
+       
+       /*Create an atom to identify our message (only if it doesn't already exist)*/
+       
+       Atom WindowActiveAtom = XInternAtom(LXVST_XDisplay, "LaunchEditor", false);
+       
+       event.type = ClientMessage;
+       event.send_event = true;
+       event.window = parent_window;
+       event.message_type = WindowActiveAtom;
+
+       event.format = 32;                                              //Data format
+       event.data.l[0] = 0x0FEEDBAC;                   //Something we can recognize later
+       
+       /*Push the event into the queue on our Display*/
+       
+       XSendEvent(LXVST_XDisplay, parent_window, FALSE, NoEventMask, (XEvent*)&event);
+
+       /*Unlock - and we are done for the first part of staring the Editor...*/
+       
+       pthread_mutex_unlock (&vstfx->lock);
+       
+       return 0;
+}
+
+int
+vstfx_launch_editor (VSTState* vstfx)
+{
+       /*This is the second stage of launching the editor (see vstfx_create editor)
+       we get called here in response to receiving the ClientMessage on our Window,
+       therefore it's about as safe (as can be) to assume that the Window we created
+       is now valid in the XServer and can be passed to the plugin in effEditOpen
+       without generating BadWindow errors when the plugin reparents itself into our
+       parent window*/
+       
+       if(vstfx->been_activated)
+               return 0;
+       
+       Window parent_window;
+       struct ERect* er;
+       
+       int x_size = 1;
+       int y_size = 1;
+       
+       parent_window = vstfx->linux_window;
+       
+       /*Open the editor - Bah! we have to pass the int windowID as a void pointer - yuck
+       it gets cast back to an int as the parent window XID in the plugin - and we have to pass the
+       Display* as a long */
+       
+       /**************************************************************/
+       /* 64Bit --- parent window is an int passed as a void* so     */
+       /* that should be ok for 64Bit machines                       */
+       /*                                                            */
+       /* Display is passed in as a long - ok on arch's where sizeof */
+       /* long = 8                                                   */
+       /*                                                            */
+       /* Most linux VST plugins open a connection to X on their own */
+       /* Display anyway so it may not matter                        */
+       /*                                                            */
+       /* linuxDSP VSTs don't use the host Display* at all           */
+       /**************************************************************/
+       
+       vstfx->plugin->dispatcher (vstfx->plugin, effEditOpen, 0, (long)LXVST_XDisplay, (void*)(parent_window), 0 );
+       
+       /*QUIRK - some plugins need a slight delay after opening the editor before you can
+       ask the window size or they might return zero - specifically discoDSP */
+       
+       usleep(100000);
+       
+       /*Now we can find out how big the parent window should be (and try) to resize it*/
+       
+       vstfx->plugin->dispatcher (vstfx->plugin, effEditGetRect, 0, 0, &er, 0 );
+
+       x_size = er->right - er->left;
+       y_size = er->bottom - er->top;
+       
+       vstfx->width =  x_size;
+       vstfx->height =  y_size;
+       
+       XResizeWindow(LXVST_XDisplay, parent_window, x_size, y_size);
+       
+       XFlush (LXVST_XDisplay);
+       
+       /*Not sure if we need to map the window or if the plugin will do it for us
+       it should be ok because XReparentWindow generates a Map event*/
+       
+       /*mark the editor as activated - mainly so that vstfx_get_XID
+       will know it is valid*/
+
+       vstfx->been_activated = TRUE;
+       
+       pthread_cond_signal (&vstfx->window_status_change);
+       return 0;
+}
+
+/** Destroy the editor window */
+void
+vstfx_destroy_editor (VSTState* vstfx)
+{
+       pthread_mutex_lock (&vstfx->lock);
+       if (vstfx->linux_window) {
+               vstfx->destroy = TRUE;
+               pthread_cond_wait (&vstfx->window_status_change, &vstfx->lock);
+       }
+       pthread_mutex_unlock (&vstfx->lock);
+}
+
+/** Remove a vstfx instance from the linked list parsed by the
+    event loop
+*/
+void
+vstfx_event_loop_remove_plugin (VSTState* vstfx)
+{
+       /* This only ever gets called from within our GUI thread
+          so we don't need to lock here - if we did there would be
+          a deadlock anyway
+       */
+       
+       VSTState* p;
+       VSTState* prev;
+       
+       for (p = vstfx_first, prev = NULL; p; prev = p, p = p->next) {
+               if (p == vstfx) {
+                       if (prev) {
+                               prev->next = p->next;
+                               break;
+                       }
+               }
+       }
+
+       if (vstfx_first == vstfx) {
+               vstfx_first = vstfx_first->next;
+       }
+}
+
index 31bb6c879b64663d7e40f2a86d85c89bf17177e1..5d86f428c2fc823b88b7ef4bd527e9e6ab12b97b 100644 (file)
@@ -18,7 +18,7 @@
 */
 
 #include "ardour/lxvst_plugin.h"
-#include "ardour/vstfx.h"
+#include "ardour/linux_vst_support.h"
 #include "lxvst_plugin_ui.h"
 #include "ardour_ui.h"
 #include <gdk/gdkx.h>
diff --git a/gtk2_ardour/vstfxwin.cc b/gtk2_ardour/vstfxwin.cc
deleted file mode 100755 (executable)
index 0687d06..0000000
+++ /dev/null
@@ -1,759 +0,0 @@
-/******************************************************************/
-/** VSTFX - An engine based on FST for handling linuxVST plugins **/
-/******************************************************************/
-
-/*This is derived from the original FST (C code) with some tweaks*/
-
-
-/** EDITOR tab stops at 4 **/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <jack/jack.h>
-#include <jack/thread.h>
-#include <libgen.h>
-
-#include <pthread.h>
-#include <signal.h>
-#include <glib.h>
-
-#include "ardour/vstfx.h"
-
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <dlfcn.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <pthread.h>
-
-struct ERect{
-    short top;
-    short left;
-    short bottom;
-    short right;
-};
-
-static pthread_mutex_t plugin_mutex;
-
-static VSTState * vstfx_first = NULL;
-
-const char magic[] = "VSTFX Plugin State v002";
-
-int  gui_thread_id = 0;
-static int gui_quit = 0;
-
-/*This will be our connection to X*/
-
-Display* LXVST_XDisplay = NULL;
-
-/*The thread handle for the GUI event loop*/
-
-pthread_t LXVST_gui_event_thread;
-
-/*Util functions to get the value of a property attached to an XWindow*/
-
-bool LXVST_xerror;
-
-int TempErrorHandler(Display *display, XErrorEvent *e)
-{
-       LXVST_xerror = true;
-       
-       return 0;
-}
-
-#ifdef LXVST_32BIT
-
-int getXWindowProperty(Window window, Atom atom)
-{
-       int result = 0;
-       int userSize;
-       unsigned long bytes;
-       unsigned long userCount;
-       unsigned char *data;
-       Atom userType;
-       LXVST_xerror = false;
-       
-       /*Use our own Xerror handler while we're in here - in an
-       attempt to stop the brain dead default Xerror behaviour of
-       qutting the entire application because of e.g. an invalid
-       window ID*/
-       
-       XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler);
-       
-       XGetWindowProperty(     LXVST_XDisplay,                 //The display
-                                               window,                                 //The Window
-                                               atom,                                   //The property
-                                               0,                                              //Offset into the data
-                                               1,                                              //Number of 32Bit chunks of data
-                                               false,                                  //false = don't delete the property
-                                               AnyPropertyType,                //Required property type mask
-                                               &userType,                              //Actual type returned
-                                               &userSize,                              //Actual format returned
-                                               &userCount,                             //Actual number of items stored in the returned data
-                                               &bytes,                                 //Number of bytes remaining if a partial read
-                                               &data);                                 //The actual data read
-                                               
-       if(LXVST_xerror == false && userCount == 1)
-               result = *(int*)data;
-               
-       XSetErrorHandler(olderrorhandler);
-       
-       /*Hopefully this will return zero if the property is not set*/
-       
-       return result;
-}
-
-#endif
-
-#ifdef LXVST_64BIT
-
-/********************************************************************/
-/* This is untested - have no 64Bit plugins which use this          */
-/* system of passing an eventProc address                           */
-/********************************************************************/
-
-long getXWindowProperty(Window window, Atom atom)
-{
-       long result = 0;
-       int userSize;
-       unsigned long bytes;
-       unsigned long userCount;
-       unsigned char *data;
-       Atom userType;
-       LXVST_xerror = false;
-       
-       /*Use our own Xerror handler while we're in here - in an
-       attempt to stop the brain dead default Xerror behaviour of
-       qutting the entire application because of e.g. an invalid
-       window ID*/
-       
-       XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler);
-       
-       XGetWindowProperty(     LXVST_XDisplay, 
-                                               window, 
-                                               atom,
-                                               0,
-                                               2,
-                                               false,
-                                               AnyPropertyType, 
-                                               &userType,
-                                               &userSize,
-                                               &userCount,
-                                               &bytes,
-                                               &data);
-                                               
-       if(LXVST_xerror == false && userCount == 1)
-               result = *(long*)data;
-               
-       XSetErrorHandler(olderrorhandler);
-       
-       /*Hopefully this will return zero if the property is not set*/
-       
-       return result;
-}
-
-#endif
-
-/*The event handler - called from within the main GUI thread to
-dispatch events to any VST UIs which have callbacks stuck to them*/
-
-static void
-dispatch_x_events (XEvent* event, VSTState* vstfx)
-{
-       /*Handle some of the Events we might be interested in*/
-       
-       switch(event->type)
-       {
-               /*Configure event - when the window is resized or first drawn*/
-                       
-               case ConfigureNotify:
-               {
-                       Window window = event->xconfigure.event;
-                       
-                       int width = event->xconfigure.width;
-                       int height = event->xconfigure.height;
-                       
-                       /*If we get a config notify on the parent window XID then we need to see
-                       if the size has been changed - some plugins re-size their UI window e.g.
-                       when opening a preset manager (you might think that should be spawned as a new window...) */
-                       
-                       /*if the size has changed, we flag this so that in lxvst_pluginui.cc we can make the
-                       change to the GTK parent window in ardour, from its UI thread*/ 
-                       
-                       if (window == (Window) (vstfx->linux_window)) {
-                               if (width != vstfx->width || height!=vstfx->height) {
-                                       vstfx->width = width;
-                                       vstfx->height = height;
-                                       vstfx->want_resize = 1;
-                                       
-                                       /*QUIRK : Loomer plugins not only resize the UI but throw it into some random
-                                       position at the same time. We need to re-position the window at the origin of
-                                       the parent window*/
-                                       
-                                       if (vstfx->linux_plugin_ui_window) {
-                                               XMoveWindow (LXVST_XDisplay, vstfx->linux_plugin_ui_window, 0, 0);
-                                       }
-                               }
-                       }
-                       
-                       break;
-                       
-               }
-               
-               /*Reparent Notify - when the plugin UI is reparented into
-               our Host Window we will get an event here... probably... */
-               
-               case ReparentNotify:
-               {
-                       Window ParentWindow = event->xreparent.parent;
-                       
-                       /*If the ParentWindow matches the window for the vstfx instance then
-                       the Child window must be the XID of the pluginUI window created by the
-                       plugin, so we need to see if it has a callback stuck to it, and if so
-                       set that up in the vstfx */
-                       
-                       /***********************************************************/
-                       /* 64Bit --- This mechanism is not 64Bit compatible at the */
-                       /* present time                                            */
-                       /***********************************************************/
-                       
-                       if (ParentWindow == (Window) (vstfx->linux_window)) {
-
-                               Window PluginUIWindowID = event->xreparent.window;
-                               
-                               vstfx->linux_plugin_ui_window = PluginUIWindowID;
-#ifdef LXVST_32BIT
-                               int result = getXWindowProperty(PluginUIWindowID, XInternAtom(LXVST_XDisplay, "_XEventProc", false));
-       
-                               if (result == 0) {
-                                       vstfx->eventProc = NULL;
-                               } else {
-                                       vstfx->eventProc = (void (*) (void* event))result;
-                               }
-#endif
-#ifdef LXVST_64BIT
-                               long result = getXWindowProperty(PluginUIWindowID, XInternAtom(LXVST_XDisplay, "_XEventProc", false));
-       
-                               if(result == 0)
-                                       vstfx->eventProc = NULL;
-                               else
-                                       vstfx->eventProc = (void (*) (void* event))result;
-#endif
-                       }
-                       break;
-               }
-               
-               case ClientMessage:
-               {
-                       Window window = event->xany.window;
-                       Atom message_type = event->xclient.message_type;
-                       
-                       /*The only client message we are interested in is to signal
-                       that the plugin parent window is now valid and can be passed
-                       to effEditOpen when the editor is launched*/
-                       
-                       if (window == (Window) (vstfx->linux_window)) {
-                               char* message = XGetAtomName(LXVST_XDisplay, message_type);
-                               
-                               if (strcmp(message,"LaunchEditor") == 0) {
-                                       if (event->xclient.data.l[0] == 0x0FEEDBAC) {
-                                               vstfx_launch_editor (vstfx);
-                                       }
-                               }
-                               
-                               XFree(message);
-                       }
-                       break;
-               }
-               
-               default:
-                       break;
-       }
-       
-       /* Some VSTs built with toolkits e.g. JUCE will manager their own UI
-       autonomously in the plugin, running the UI in its own thread, so once
-       we have created a parent window for the plugin, its UI takes care of
-       itself.*/
-       
-       /*Other types register a callback as an Xwindow property on the plugin
-       UI window after they create it.  If that is the case, we need to call it
-       here, passing the XEvent into it*/
-       
-       if (vstfx->eventProc == NULL) {
-               return;
-       }
-                               
-       vstfx->eventProc((void*)event);
-}
-
-static void
-maybe_set_program (VSTState* vstfx)
-{
-       if (vstfx->want_program != -1) {
-               if (vstfx->vst_version >= 2) {
-                       vstfx->plugin->dispatcher (vstfx->plugin, 67 /* effBeginSetProgram */, 0, 0, NULL, 0);
-               }
-
-               vstfx->plugin->dispatcher (vstfx->plugin, effSetProgram, 0, vstfx->want_program, NULL, 0);
-               
-               if (vstfx->vst_version >= 2) {
-                       vstfx->plugin->dispatcher (vstfx->plugin, 68 /* effEndSetProgram */, 0, 0, NULL, 0);
-               }
-               
-               vstfx->want_program = -1; 
-       }
-
-       if (vstfx->want_chunk == 1) {
-               vstfx->plugin->dispatcher (vstfx->plugin, 24 /* effSetChunk */, 1, vstfx->wanted_chunk_size, vstfx->wanted_chunk, 0);
-               vstfx->want_chunk = 0;
-       }
-}
-
-/** This is the main gui event loop for the plugin, we also need to pass
-any Xevents to all the UI callbacks plugins 'may' have registered on their
-windows, that is if they don't manage their own UIs **/
-
-void* gui_event_loop (void* ptr)
-{
-       VSTState* vstfx;
-       int LXVST_sched_event_timer = 0;
-       int LXVST_sched_timer_interval = 50; //ms
-       XEvent event;
-       
-       /*The 'Forever' loop - runs the plugin UIs etc - based on the FST gui event loop*/
-       
-       while (!gui_quit)
-       {
-               /* handle window creation requests, destroy requests, 
-                  and run idle callbacks */
-
-               /*Look at the XEvent queue - if there are any XEvents we need to handle them,
-               including passing them to all the plugin (eventProcs) we are currently managing*/
-               
-               if(LXVST_XDisplay)
-               {
-                       /*See if there are any events in the queue*/
-               
-                       int num_events = XPending(LXVST_XDisplay);
-                       
-                       /*process them if there are any*/
-               
-                       while(num_events)
-                       {
-                               XNextEvent(LXVST_XDisplay, &event);
-                               
-                               /*Call dispatch events, with the event, for each plugin in the linked list*/
-                               
-                               for (vstfx = vstfx_first; vstfx; vstfx = vstfx->next)
-                               {       
-                                       pthread_mutex_lock(&vstfx->lock);
-                                       
-                                       dispatch_x_events(&event, vstfx);
-                                       
-                                       pthread_mutex_unlock(&vstfx->lock);
-                               }
-                               
-                               num_events--;
-                       }
-               }
-
-               /*We don't want to use all the CPU.. */
-
-               usleep(1000);
-               
-               LXVST_sched_event_timer++;
-               
-               LXVST_sched_event_timer = LXVST_sched_event_timer & 0x00FFFFFF;
-
-               /*See if its time for us to do a scheduled event pass on all the plugins*/
-
-               if((LXVST_sched_timer_interval!=0) && (!(LXVST_sched_event_timer% LXVST_sched_timer_interval)))
-               {
-                       pthread_mutex_lock (&plugin_mutex);
-                   
-again:
-                       /*Parse through the linked list of plugins*/
-                       
-                       for (vstfx = vstfx_first; vstfx; vstfx = vstfx->next)
-                       {       
-                               pthread_mutex_lock (&vstfx->lock);
-
-                               /*Window scheduled for destruction*/
-                               
-                               if (vstfx->destroy) {
-                                       if (vstfx->linux_window) {
-                                               vstfx->plugin->dispatcher (vstfx->plugin, effEditClose, 0, 0, NULL, 0.0);
-                                                       
-                                               XDestroyWindow (LXVST_XDisplay, vstfx->linux_window);
-                                               /* FIXME - probably safe to assume we never have an XID of 0 but not explicitly true */
-                                               vstfx->linux_window = 0;
-                                               vstfx->destroy = FALSE;
-                                       }
-                                       
-                                       vstfx_event_loop_remove_plugin (vstfx);
-                                       vstfx->been_activated = FALSE;
-                                       pthread_cond_signal (&vstfx->window_status_change);
-                                       pthread_mutex_unlock (&vstfx->lock);
-                                       
-                                       goto again;
-                               } 
-                               
-                               /*Window does not yet exist - scheduled for creation*/
-
-                               /* FIXME - probably safe to assume 0 is not a valid XID but not explicitly true */
-                               if (vstfx->linux_window == 0) {
-                                       if (vstfx_create_editor (vstfx)) {
-                                               vstfx_error ("** ERROR ** VSTFX : Cannot create editor for plugin %s", vstfx->handle->name);
-                                               vstfx_event_loop_remove_plugin (vstfx);
-                                               pthread_cond_signal (&vstfx->window_status_change);
-                                               pthread_mutex_unlock (&vstfx->lock);
-                                               goto again;
-                                       } else {
-                                               /* condition/unlock: it was signalled & unlocked in fst_create_editor()   */
-                                       }
-                               }
-
-                               maybe_set_program (vstfx);
-                               vstfx->want_program = -1;
-                               vstfx->want_chunk = 0;
-                               
-                               /*scheduled call to dispatcher*/
-                               
-                               if (vstfx->dispatcher_wantcall) {
-                                       vstfx->dispatcher_retval = vstfx->plugin->dispatcher (
-                                               vstfx->plugin, 
-                                               vstfx->dispatcher_opcode,
-                                               vstfx->dispatcher_index,
-                                               vstfx->dispatcher_val,
-                                               vstfx->dispatcher_ptr,
-                                               vstfx->dispatcher_opt
-                                               );
-                                       
-                                       vstfx->dispatcher_wantcall = 0;
-                                       pthread_cond_signal (&vstfx->plugin_dispatcher_called);
-                               }
-                               
-                               /*Call the editor Idle function in the plugin*/
-                               
-                               vstfx->plugin->dispatcher (vstfx->plugin, effEditIdle, 0, 0, NULL, 0);
-
-                               if(vstfx->wantIdle)
-                                       vstfx->plugin->dispatcher (vstfx->plugin, 53, 0, 0, NULL, 0);
-                                       
-                               pthread_mutex_unlock (&vstfx->lock);
-                       }
-                       pthread_mutex_unlock (&plugin_mutex);
-               }
-       }
-
-       /*Drop out to here if we set gui_quit to 1 */
-
-       return NULL;
-}
-
-/*The VSTFX Init function - this needs to be called before the VSTFX engine
-can be accessed, it gets the UI thread running, opens a connection to X etc
-normally started in globals.cc*/
-
-int vstfx_init (void* ptr)
-{
-
-       int thread_create_result;
-       
-       pthread_attr_t thread_attributes;
-       
-       /*Init the attribs to defaults*/
-       
-       pthread_attr_init(&thread_attributes);
-       
-       /*Make sure the thread is joinable - this should be the default anyway - 
-       so we can join to it on vstfx_exit*/
-       
-       pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);
-       
-
-       /*This is where we need to open a connection to X, and start the GUI thread*/
-       
-       /*Open our connection to X - all linuxVST plugin UIs handled by the LXVST engine
-       will talk to X down this connection - X cannot handle multi-threaded access via
-       the same Display* */
-       
-       if(LXVST_XDisplay==NULL)
-               LXVST_XDisplay = XOpenDisplay(NULL);    //We might be able to make this open a specific screen etc
-
-       /*Drop out and report the error if we fail to connect to X */
-       
-       if(LXVST_XDisplay==NULL)
-       {
-               vstfx_error ("** ERROR ** VSTFX: Failed opening connection to X");
-               
-               return -1;
-       }
-       
-       /*We have a connection to X - so start the gui event loop*/
-       
-       /*Create the thread - use default attrs for now, don't think we need anything special*/
-       
-       thread_create_result = pthread_create(&LXVST_gui_event_thread, NULL, gui_event_loop, NULL);
-       
-       if(thread_create_result!=0)
-       {
-               /*There was a problem starting the GUI event thread*/
-               
-               vstfx_error ("** ERROR ** VSTFX: Failed starting GUI event thread");
-               
-               XCloseDisplay(LXVST_XDisplay);
-               
-               return -1;
-       }
-       
-       return 0;
-}
-
-/*The vstfx Quit function*/
-
-void vstfx_exit()
-{
-       gui_quit = 1;
-       
-       /*We need to pthread_join the gui_thread here so
-       we know when it has stopped*/
-       
-       pthread_join(LXVST_gui_event_thread, NULL);
-}
-
-/*Adds a new plugin (VSTFX) instance to the linked list*/
-
-int vstfx_run_editor (VSTState* vstfx)
-{
-       pthread_mutex_lock (&plugin_mutex);
-
-       /* Add the new VSTFX instance to the linked list */
-
-       if (vstfx_first == NULL) {
-               vstfx_first = vstfx;
-       } else {
-               VSTState* p = vstfx_first;
-               
-               while (p->next) {
-                       p = p->next;
-               }
-               p->next = vstfx;
-               
-               /* Mark the new end of the list */
-               
-               vstfx->next = NULL;
-       }
-
-       pthread_mutex_unlock (&plugin_mutex);
-
-       /* wait for the plugin editor window to be created (or not) */
-
-       pthread_mutex_lock (&vstfx->lock);
-       
-       if (!vstfx->linux_window) {
-               pthread_cond_wait (&vstfx->window_status_change, &vstfx->lock);
-       }
-       
-       pthread_mutex_unlock (&vstfx->lock);
-
-       if (!vstfx->linux_window) {
-               return -1;
-       }
-
-       return 0;
-}
-
-
-/*Creates an editor for the plugin - normally called from within the gui event loop
-after run_editor has added the plugin (editor) to the linked list*/
-
-int vstfx_create_editor (VSTState* vstfx)
-{
-       Window parent_window;
-       
-       int x_size = 1;
-       int y_size = 1;
-
-       /* Note: vstfx->lock is held while this function is called */
-
-       if (!(vstfx->plugin->flags & effFlagsHasEditor))
-       {
-               vstfx_error ("** ERROR ** VSTFX: Plugin \"%s\" has no editor", vstfx->handle->name);
-               return -1;
-       }
-       
-       
-       /*Create an XWindow for the plugin to inhabit*/
-       
-       parent_window = XCreateSimpleWindow (
-               LXVST_XDisplay,
-               DefaultRootWindow(LXVST_XDisplay),
-               0,
-               0,
-               x_size,
-               y_size,
-               0,
-               0,
-               0
-               );
-                                                                               
-       /*Select the events we are interested in receiving - we need Substructure notify so that
-       if the plugin resizes its window - e.g. Loomer Manifold then we get a message*/
-       
-       XSelectInput(LXVST_XDisplay, 
-                               parent_window,
-                               SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask);
-                                                                               
-       vstfx->linux_window = parent_window;
-                                                                               
-       vstfx->xid = parent_window;  //vstfx->xid will be referenced to connect to GTK UI in ardour later
-       
-       /*Because the plugin may be operating on a different Display* to us, and therefore
-       the two event queues can be asynchronous, although we have created the window on
-       our display, we can't guarantee it exists in the server yet, which will
-       cause BadWindow crashes if the plugin tries to use it.
-       
-       It would be nice to use CreateNotify events here, but they don't get
-       through on all window managers, so instead we pass a client message
-       into out queue, after the XCreateWindow.  When this message pops out
-       in our event handler, it will trigger the second stage of plugin
-       Editor instantiation, and by then the Window should be valid...*/
-       
-       XClientMessageEvent event;
-       
-       /*Create an atom to identify our message (only if it doesn't already exist)*/
-       
-       Atom WindowActiveAtom = XInternAtom(LXVST_XDisplay, "LaunchEditor", false);
-       
-       event.type = ClientMessage;
-       event.send_event = true;
-       event.window = parent_window;
-       event.message_type = WindowActiveAtom;
-
-       event.format = 32;                                              //Data format
-       event.data.l[0] = 0x0FEEDBAC;                   //Something we can recognize later
-       
-       /*Push the event into the queue on our Display*/
-       
-       XSendEvent(LXVST_XDisplay, parent_window, FALSE, NoEventMask, (XEvent*)&event);
-
-       /*Unlock - and we are done for the first part of staring the Editor...*/
-       
-       pthread_mutex_unlock (&vstfx->lock);
-       
-       return 0;
-}
-
-int
-vstfx_launch_editor (VSTState* vstfx)
-{
-       /*This is the second stage of launching the editor (see vstfx_create editor)
-       we get called here in response to receiving the ClientMessage on our Window,
-       therefore it's about as safe (as can be) to assume that the Window we created
-       is now valid in the XServer and can be passed to the plugin in effEditOpen
-       without generating BadWindow errors when the plugin reparents itself into our
-       parent window*/
-       
-       if(vstfx->been_activated)
-               return 0;
-       
-       Window parent_window;
-       struct ERect* er;
-       
-       int x_size = 1;
-       int y_size = 1;
-       
-       parent_window = vstfx->linux_window;
-       
-       /*Open the editor - Bah! we have to pass the int windowID as a void pointer - yuck
-       it gets cast back to an int as the parent window XID in the plugin - and we have to pass the
-       Display* as a long */
-       
-       /**************************************************************/
-       /* 64Bit --- parent window is an int passed as a void* so     */
-       /* that should be ok for 64Bit machines                       */
-       /*                                                            */
-       /* Display is passed in as a long - ok on arch's where sizeof */
-       /* long = 8                                                   */
-       /*                                                            */
-       /* Most linux VST plugins open a connection to X on their own */
-       /* Display anyway so it may not matter                        */
-       /*                                                            */
-       /* linuxDSP VSTs don't use the host Display* at all           */
-       /**************************************************************/
-       
-       vstfx->plugin->dispatcher (vstfx->plugin, effEditOpen, 0, (long)LXVST_XDisplay, (void*)(parent_window), 0 );
-       
-       /*QUIRK - some plugins need a slight delay after opening the editor before you can
-       ask the window size or they might return zero - specifically discoDSP */
-       
-       usleep(100000);
-       
-       /*Now we can find out how big the parent window should be (and try) to resize it*/
-       
-       vstfx->plugin->dispatcher (vstfx->plugin, effEditGetRect, 0, 0, &er, 0 );
-
-       x_size = er->right - er->left;
-       y_size = er->bottom - er->top;
-       
-       vstfx->width =  x_size;
-       vstfx->height =  y_size;
-       
-       XResizeWindow(LXVST_XDisplay, parent_window, x_size, y_size);
-       
-       XFlush (LXVST_XDisplay);
-       
-       /*Not sure if we need to map the window or if the plugin will do it for us
-       it should be ok because XReparentWindow generates a Map event*/
-       
-       /*mark the editor as activated - mainly so that vstfx_get_XID
-       will know it is valid*/
-
-       vstfx->been_activated = TRUE;
-       
-       pthread_cond_signal (&vstfx->window_status_change);
-       return 0;
-}
-
-/** Destroy the editor window */
-void
-vstfx_destroy_editor (VSTState* vstfx)
-{
-       pthread_mutex_lock (&vstfx->lock);
-       if (vstfx->linux_window) {
-               vstfx->destroy = TRUE;
-               pthread_cond_wait (&vstfx->window_status_change, &vstfx->lock);
-       }
-       pthread_mutex_unlock (&vstfx->lock);
-}
-
-/** Remove a vstfx instance from the linked list parsed by the
-    event loop
-*/
-void
-vstfx_event_loop_remove_plugin (VSTState* vstfx)
-{
-       /* This only ever gets called from within our GUI thread
-          so we don't need to lock here - if we did there would be
-          a deadlock anyway
-       */
-       
-       VSTState* p;
-       VSTState* prev;
-       
-       for (p = vstfx_first, prev = NULL; p; prev = p, p = p->next) {
-               if (p == vstfx) {
-                       if (prev) {
-                               prev->next = p->next;
-                               break;
-                       }
-               }
-       }
-
-       if (vstfx_first == vstfx) {
-               vstfx_first = vstfx_first->next;
-       }
-}
-
index 65e1da518649b19dee7799f973a146257487b7bb..3a5a301a13ae2b03dc1e85dee2e5a1f5d73c0589 100644 (file)
@@ -399,7 +399,7 @@ def build(bld):
         obj.uselib += ' X11 '
 
     if bld.is_defined('LXVST_SUPPORT'):
-        obj.source += [ 'vstfxwin.cc', 'lxvst_plugin_ui.cc' ]
+        obj.source += [ 'linux_vst_gui_support.cc', 'lxvst_plugin_ui.cc' ]
         obj.defines += [ 'LXVST_SUPPORT' ]
         obj.uselib += ' X11 '
 
diff --git a/libs/ardour/ardour/vstfx.h b/libs/ardour/ardour/vstfx.h
deleted file mode 100755 (executable)
index 31f8baf..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef __vstfx_h__
-#define __vstfx_h__
-
-#include <setjmp.h>
-#include <signal.h>
-#include <pthread.h>
-#include <stdio.h>
-
-#include "ardour/vst_types.h"
-
-/******************************************************************************************/
-/*VSTFX - an engine to manage native linux VST plugins - derived from FST for Windows VSTs*/
-/******************************************************************************************/
-extern void (*vstfx_error_callback)(const char *msg);
-
-void vstfx_set_error_function (void (*func)(const char *));
-
-void  vstfx_error (const char *fmt, ...);
-
-/*API to vstfx*/
-
-extern int         vstfx_launch_editor (VSTState *);
-extern int          vstfx_init (void *);
-extern void         vstfx_exit ();
-extern VSTHandle *  vstfx_load (const char*);
-extern int          vstfx_unload (VSTHandle *);
-extern VSTState *   vstfx_instantiate (VSTHandle *, audioMasterCallback, void *);
-extern void         vstfx_close (VSTState*);
-
-extern int          vstfx_create_editor (VSTState *);
-extern int          vstfx_run_editor (VSTState *);
-extern void         vstfx_destroy_editor (VSTState *);
-
-extern VSTInfo *    vstfx_get_info (char *);
-extern void         vstfx_free_info (VSTInfo *);
-extern void         vstfx_event_loop_remove_plugin (VSTState *);
-extern int          vstfx_call_dispatcher (VSTState *, int, int, int, void *, float);
-
-/** Load a plugin state from a file.**/
-
-extern int vstfx_load_state (VSTState* vstfx, char * filename);
-
-/** Save a plugin state to a file.**/
-
-extern bool vstfx_save_state (VSTState* vstfx, char * filename);
-
-
-#endif /* __vstfx_h__ */
index e07437ce9df954efe0d57ce1e965245333690add..5a2a2addd65b2318e6893594ba3a007a08beb7ee 100644 (file)
@@ -34,7 +34,7 @@
 #endif
 
 #ifdef LXVST_SUPPORT
-#include "ardour/vstfx.h"
+#include "ardour/linux_vst_support.h"
 #endif
 
 #ifdef AUDIOUNIT_SUPPORT
diff --git a/libs/ardour/linux_vst_info_file.cc b/libs/ardour/linux_vst_info_file.cc
new file mode 100644 (file)
index 0000000..58954c7
--- /dev/null
@@ -0,0 +1,423 @@
+/***********************************************************/
+/*vstfx infofile - module to manage info files             */
+/*containing cached information about a plugin. e.g. its   */
+/*name, creator etc etc                                    */
+/***********************************************************/
+
+#include <iostream>
+
+#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 "ardour/linux_vst_support.h"
+
+#define MAX_STRING_LEN 256
+
+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;
+    }
+}
+
+static VSTInfo *
+load_vstfx_info_file (FILE* fp)
+{
+       VSTInfo *info;
+       int i;
+       
+       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(1 != fscanf(fp, "%d\n", &info->UniqueID)) goto error;
+       if((info->Category = read_string(fp)) == 0) 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)) == 0) {
+               goto error;
+       }
+
+       for (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 (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)
+{
+    int i;
+
+    if (info == 0) {
+           vstfx_error("** ERROR ** VSTFXinfofile : info ptr is 0\n");
+           return -1;
+    }
+
+    if (fp == 0) {
+           vstfx_error("** ERROR ** VSTFXinfofile : file ptr is 0\n");
+           return -1;
+    }
+    
+    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]);
+    }
+       
+    return 0;
+}
+
+static char* vstfx_infofile_stat (char *dllpath, struct stat* statbuf, int personal)
+{
+       char* path;
+       char* dir_path;
+       char* basename;
+       char* base;
+       size_t blen;
+
+       if (strstr (dllpath, ".so" ) == 0) {
+               return 0;
+       }
+       
+       if (personal) {
+               dir_path = g_build_filename (g_get_home_dir(), ".fst", NULL);
+       } else {
+               dir_path = g_path_get_dirname (dllpath);
+       }
+       
+       base = g_path_get_basename (dllpath);
+       blen = strlen (base) + 2; // null char and '.'
+       basename = (char*) g_malloc (blen);
+       snprintf (basename, blen, ".%s.fsi", base);
+       g_free (base);
+       
+       path = g_build_filename (dir_path, basename, NULL);
+       
+       g_free (dir_path);
+       g_free (basename);
+
+
+       if (g_file_test (path, GFileTest (G_FILE_TEST_EXISTS|G_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, statbuf) == 0) {
+                               if (dllstat.st_mtime <= statbuf->st_mtime) {
+                                       /* plugin is older than info file */
+                                       return path;
+                               }
+                       }
+               } 
+       }
+
+       g_free (path);
+
+       return 0;
+}
+
+
+static FILE* vstfx_infofile_for_read (char* dllpath)
+{
+       struct stat own_statbuf;
+       struct stat sys_statbuf;
+       char *own_info;
+       char *sys_info;
+       
+       own_info = vstfx_infofile_stat (dllpath, &own_statbuf, 1);
+       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 */
+                               return fopen (sys_info, "r");
+                       }
+               } else {
+                       return fopen (own_info, "r");
+               }
+       }
+
+       return 0;
+}
+
+static FILE* vstfx_infofile_create (char* dllpath, int personal)
+{
+       char* path;
+       char* dir_path;
+       char* basename;
+       char* base;
+       size_t blen;
+
+       if (strstr (dllpath, ".so" ) == 0) {
+               return 0;
+       }
+       
+       if (personal) {
+               dir_path = g_build_filename (g_get_home_dir(), ".fst", NULL);
+
+               /* if the directory doesn't yet exist, try to create it */
+
+               if (!g_file_test (dir_path, G_FILE_TEST_IS_DIR)) {
+                       if (g_mkdir (dir_path, 0700)) {
+                               return 0;
+                       }
+               }
+
+       } else {
+               dir_path = g_path_get_dirname (dllpath);
+       }
+       
+       base = g_path_get_basename (dllpath);
+       blen = strlen (base) + 2; // null char and '.'
+       basename = (char*) g_malloc (blen);
+       snprintf (basename, blen, ".%s.fsi", base);
+       g_free (base);
+
+       path = g_build_filename (dir_path, basename, NULL);
+
+       g_free (dir_path);
+       g_free (basename);
+
+       FILE* f = fopen (path, "w");
+       g_free (path);
+
+       return f;
+}
+
+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 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)
+{
+       VSTInfo* info = (VSTInfo*) malloc (sizeof (VSTInfo));
+       
+       AEffect *plugin;
+       int i;
+       
+       /*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";
+       
+       if(!vstfx)
+       {
+               vstfx_error( "** ERROR ** VSTFXinfofile : vstfx ptr is 0\n" );
+               return 0;
+       }
+       
+       if(!info)
+               return 0;
+       
+       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");          // FIXME:  
+       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(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;
+       VSTInfo* info;
+
+       if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) {
+               VSTInfo *info;
+               info = load_vstfx_info_file (infofile);
+               fclose (infofile);
+               return info;
+       } 
+       
+       if(!(h = vstfx_load(dllpath)))
+               return 0;
+       
+       if(!(vstfx = vstfx_instantiate(h, simple_master_callback, 0))) {
+               vstfx_unload(h);
+               vstfx_error( "** ERROR ** VSTFXinfofile : Instantiate failed\n" );
+               return 0;
+       }
+       
+       infofile = vstfx_infofile_for_write (dllpath);
+       
+       if(!infofile) {
+               vstfx_close(vstfx);
+               vstfx_unload(h);
+               vstfx_error("cannot create new FST info file for plugin");
+               return 0;
+       }
+       
+       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);
+}
+
+
diff --git a/libs/ardour/linux_vst_support.cc b/libs/ardour/linux_vst_support.cc
new file mode 100644 (file)
index 0000000..e6f2735
--- /dev/null
@@ -0,0 +1,487 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <signal.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "ardour/linux_vst_support.h"
+#include "pbd/error.h"
+
+/***********************************************************/
+/* VSTFX - A set of modules for managing linux VST plugins */
+/* vstfx.cc, vstfxwin.cc and vstfxinfofile.cc              */
+/***********************************************************/
+
+/*Simple error handler stuff for VSTFX*/
+
+void vstfx_error (const char *fmt, ...)
+{
+       va_list ap;
+       char buffer[512];
+
+       va_start (ap, fmt);
+       vsnprintf (buffer, sizeof(buffer), fmt, ap);
+       vstfx_error_callback (buffer);
+       va_end (ap);
+}
+
+/*default error handler callback*/
+
+void default_vstfx_error_callback (const char *desc)
+{
+       PBD::error << desc << endmsg;
+}
+
+void (*vstfx_error_callback)(const char *desc) = &default_vstfx_error_callback;
+
+/* --- */
+
+/*Create and return a pointer to a new VSTFX handle*/
+
+VSTHandle *
+vstfx_handle_new ()
+{
+       VSTHandle* vstfx = (VSTHandle *) calloc (1, sizeof (VSTHandle));
+       return vstfx;
+}
+
+/*Create and return a pointer to a new vstfx instance*/
+
+VSTState *
+vstfx_new ()
+{
+       VSTState* vstfx = (VSTState *) calloc (1, sizeof (VSTState));
+       
+       /*Mutexes*/
+       
+       pthread_mutex_init (&vstfx->lock, NULL);
+       pthread_cond_init (&vstfx->window_status_change, NULL);
+       pthread_cond_init (&vstfx->plugin_dispatcher_called, NULL);
+       pthread_cond_init (&vstfx->window_created, NULL);
+
+       /*Safe values*/
+       
+       vstfx->want_program = -1;
+       vstfx->want_chunk = 0;
+       vstfx->n_pending_keys = 0;
+       vstfx->has_editor = 0;
+       vstfx->program_set_without_editor = 0;
+       vstfx->linux_window = 0;
+       vstfx->linux_plugin_ui_window = 0;
+       vstfx->eventProc = NULL;
+       vstfx->extra_data = NULL;
+       vstfx->want_resize = 0;
+       
+       return vstfx;
+}
+
+/*This loads the plugin shared library*/
+
+void* vstfx_load_vst_library(const char* path)
+{
+       void* dll;
+       char* full_path;
+       char* envdup;
+       char* lxvst_path;
+       size_t len1;
+       size_t len2;
+
+       /*Try and load the shared library pointed to by the path - 
+       NOTE: You have to give RTLD_LAZY or RTLD_NOW to dlopen or
+       you get some occasional failures to load - dlerror reports
+       invalid arguments*/
+
+       if ((dll = dlopen (path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
+               return dll;
+               
+       /*We didn't find the library so try and get the path specified in the
+       env variable LXVST_PATH*/
+
+       envdup = getenv ("LXVST_PATH");
+       
+       /*Path not specified - not much more we can do*/
+       
+       if (envdup == NULL)
+               return NULL;
+       
+       /*Copy the path into envdup*/
+               
+       envdup = strdup (envdup);
+       
+       if (envdup == NULL)
+               return NULL;
+               
+       len2 = strlen(path);
+
+       /*Try all the possibilities in the path - deliminated by : */
+
+       lxvst_path = strtok (envdup, ":");
+       
+       while (lxvst_path != NULL)
+       {
+               vstfx_error ("\"%s\"", lxvst_path);
+               len1 = strlen(lxvst_path);
+               
+               full_path = (char*)malloc(len1 + 1 + len2 + 1);
+               memcpy(full_path, lxvst_path, len1);
+               full_path[len1] = '/';
+               memcpy(full_path + len1 + 1, path, len2);
+               full_path[len1 + 1 + len2] = '\0';
+
+               /*Try and load the library*/
+
+               if ((dll = dlopen(full_path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
+               {
+                       /*Succeeded */
+                       break;
+               }
+       
+               /*Try again*/
+
+               lxvst_path = strtok (NULL, ":");
+       }
+
+       /*Free the path*/
+
+       free(envdup);
+
+       return dll;
+}
+
+/*This loads up a plugin, given the path to its .so file and
+ finds its main entry point etc*/
+
+VSTHandle *
+vstfx_load (const char *path)
+{
+       char* buf = NULL;
+       VSTHandle* fhandle;
+       int i;
+       
+       /*Create a new handle we can use to reference the plugin*/
+
+       fhandle = vstfx_handle_new();
+       
+       /*See if we have .so appended to the path - if not we need to make sure it is added*/
+       
+       if (strstr (path, ".so") == NULL)
+       {
+
+               /*Append the .so to the path - Make sure the path has enough space*/
+               
+               buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
+
+               sprintf (buf, "%s.so", path);
+               
+               fhandle->nameptr = strdup (path);
+
+       }
+       else
+       {
+               /*We already have .so appened to the filename*/
+               
+               buf = strdup(path);
+               
+               fhandle->nameptr = strdup (path);
+       }
+       
+       /*Use basename to shorten the path and then strip off the .so - the old VST problem,
+       we don't know anything about its name until we load and instantiate the plugin
+       which we don't want to do at this point*/
+       
+       for(i=0; i < (int)strlen(fhandle->nameptr); i++)
+       {
+               if(fhandle->nameptr[i] == '.')
+                       fhandle->nameptr[i] = 0;
+       }
+                       
+       
+       fhandle->name = basename (fhandle->nameptr);
+
+       /*call load_vstfx_library to actually load the .so into memory*/
+
+       if ((fhandle->dll = vstfx_load_vst_library (buf)) == NULL)
+       {
+               vstfx_unload (fhandle);
+               
+               free(buf);
+               
+               return NULL;
+       }
+
+       /*Find the main entry point into the plugin*/
+
+       if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == NULL)
+       {
+               /*If it can't be found, unload the plugin and return a NULL handle*/
+               
+               vstfx_unload (fhandle);
+               
+               free(buf);
+               
+               return NULL;
+       }
+
+       free(buf);
+
+       /*return the handle of the plugin*/
+
+       return fhandle;
+}
+
+/*This unloads a plugin*/
+
+int
+vstfx_unload (VSTHandle* fhandle)
+{
+       if (fhandle->plugincnt)
+       {
+               /*Still have plugin instances - can't unload the library
+               - actually dlclose keeps an instance count anyway*/
+               
+               return -1;
+       }
+
+       /*Valid plugin loaded?*/
+
+       if (fhandle->dll)
+       {
+               dlclose(fhandle->dll);
+               fhandle->dll = NULL;
+       }
+
+       if (fhandle->nameptr)
+       {
+               free (fhandle->nameptr);
+               fhandle->name = NULL;
+       }
+       
+       /*Don't need the plugin handle any more*/
+       
+       free (fhandle);
+       return 0;
+}
+
+/*This instantiates a plugin*/
+
+VSTState *
+vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
+{
+       VSTState* vstfx = vstfx_new ();
+
+       if(fhandle == NULL)
+       {
+           vstfx_error( "** ERROR ** VSTFX : The handle was NULL\n" );
+           return NULL;
+       }
+
+       if ((vstfx->plugin = fhandle->main_entry (amc)) == NULL) 
+       {
+               vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
+               free (vstfx);
+               return NULL;
+       }
+       
+       vstfx->handle = fhandle;
+       vstfx->plugin->user = userptr;
+               
+       if (vstfx->plugin->magic != kEffectMagic)
+       {
+               vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
+               free (vstfx);
+               return NULL;
+       }
+       
+       vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
+       
+       /*May or May not need to 'switch the plugin on' here - unlikely
+       since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
+       
+       //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, NULL, 0);
+       
+       vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
+       
+       vstfx->handle->plugincnt++;
+       vstfx->wantIdle = 0;
+       
+       return vstfx;
+}
+
+/*Close a vstfx instance*/
+
+void vstfx_close (VSTState* vstfx)
+{
+       vstfx_destroy_editor(vstfx);
+       
+       if(vstfx->plugin)
+       {
+               vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, NULL, 0);
+               
+               /*Calling dispatcher with effClose will cause the plugin's destructor to
+               be called, which will also remove the editor if it exists*/
+               
+               vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
+       }
+
+       if (vstfx->handle->plugincnt)
+                       vstfx->handle->plugincnt--;
+               
+       /*vstfx_unload will unload the dll if the instance count allows - 
+       we need to do this because some plugins keep their own instance count
+       and (JUCE) manages the plugin UI in its own thread.  When the plugins
+       internal instance count reaches zero, JUCE stops the UI thread and won't
+       restart it until the next time the library is loaded.  If we don't unload
+       the lib JUCE will never restart*/
+       
+       
+       if (vstfx->handle->plugincnt)
+       {
+               return;
+       }
+       
+       /*Valid plugin loaded - so we can unload it and NULL the pointer
+       to it.  We can't free the handle here because we don't know what else
+       might need it.  It should be / is freed when the plugin is deleted*/
+
+       if (vstfx->handle->dll)
+       {
+               dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
+               vstfx->handle->dll = NULL;
+       }
+}
+
+
+bool 
+vstfx_save_state (VSTState* vstfx, char * filename)
+{
+       FILE* f = fopen (filename, "wb");
+       if (f)
+       {
+               int bytelen;
+               int numParams = vstfx->plugin->numParams;
+               int i;
+               char productString[64];
+               char effectName[64];
+               char vendorString[64];
+               int success;
+
+               /* write header */
+               
+               fprintf(f, "<plugin_state>\n");
+
+               success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
+               
+               if(success == 1)
+               {
+                       fprintf (f, "  <check field=\"productString\" value=\"%s\"/>\n", productString);
+               }
+               else
+               {
+                       printf ("No product string\n");
+               }
+
+               success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
+               
+               if(success == 1)
+               {
+                       fprintf (f, "  <check field=\"effectName\" value=\"%s\"/>\n", effectName);
+                       printf ("Effect name: %s\n", effectName);
+               }
+               else
+               {
+                       printf ("No effect name\n");
+               }
+
+               success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
+               
+               if( success == 1 )
+               {
+                       fprintf (f, "  <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
+                       printf ("Vendor string: %s\n", vendorString);
+               }
+               else
+               {
+                       printf ("No vendor string\n");
+               }
+
+
+               if(vstfx->plugin->flags & 32 )
+               {
+                       numParams = 0;
+               }
+
+               for(i=0; i < numParams; i++)
+               {
+                       float val;
+                       
+                       pthread_mutex_lock( &vstfx->lock );
+                       val = vstfx->plugin->getParameter(vstfx->plugin, i );
+                       pthread_mutex_unlock( &vstfx->lock );
+                       fprintf( f, "  <param index=\"%d\" value=\"%f\"/>\n", i, val );
+               }
+
+               if(vstfx->plugin->flags & 32 )
+               {
+                       printf( "getting chunk...\n" );
+                       void * chunk;
+                       bytelen = vstfx_call_dispatcher(vstfx, 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, "  <chunk size=\"%d\">\n    %s\n  </chunk>\n", bytelen, encoded );
+                                       //g_free( encoded );
+                               }
+                       }
+               } 
+
+               fprintf( f, "</plugin_state>\n" );
+               fclose( f );
+       }
+       else
+       {
+               printf ("Could not open state file\n");
+               return false;
+       }
+       return true;
+}
+
+/*Set up a call to the plugins 'dispatcher' function*/
+
+int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt) 
+{
+       pthread_mutex_lock (&vstfx->lock);
+       
+       /*Set up the opcode and parameters*/
+       
+       vstfx->dispatcher_opcode = opcode;
+       vstfx->dispatcher_index = index;
+       vstfx->dispatcher_val = val;
+       vstfx->dispatcher_ptr = ptr;
+       vstfx->dispatcher_opt = opt;
+       
+       /*Signal that we want the call to happen*/
+       
+       vstfx->dispatcher_wantcall = 1;
+
+       /*Wait for the call to happen*/
+
+       pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
+       pthread_mutex_unlock (&vstfx->lock);
+
+       /*Return the result*/
+       
+       return vstfx->dispatcher_retval;
+}
index f14d052fd4ce684d9dceb1a24b40a24a5fe78b38..6e30e0c4436d8457ee0a939b089e762ebf0976a2 100755 (executable)
@@ -17,7 +17,7 @@
 
 */
 
-#include "ardour/vstfx.h"
+#include "ardour/linux_vst_support.h"
 #include "ardour/session.h"
 #include "ardour/lxvst_plugin.h"
 
index 0cfbdd17eb7cf8cfe74eb46695d40369630eaf11..54a130ec9cc5511e5c6b575b651a02fe528c85ec 100644 (file)
 #include <fstream>
 
 #ifdef WINDOWS_VST_SUPPORT
-#include <fst.h>
+#include "fst.h"
 #include "pbd/basename.h"
 #include <cstring>
 #endif // WINDOWS_VST_SUPPORT
 
 #ifdef LXVST_SUPPORT
-#include <ardour/vstfx.h>
-#include <pbd/basename.h>
+#include "ardour/linux_vst_support.h"
+#include "pbd/basename.h"
 #include <cstring>
 #endif //LXVST_SUPPORT
 
index 1c8b63e4662072bbb387a87ecd9e00f0b359ee60..9f93b48c745e664b076a58dc12e1e839ea68bdcb 100644 (file)
@@ -1,6 +1,6 @@
 /* Dummy LXVST methods so that libardour can be linked against the test code */
 
-#include "ardour/vstfx.h"
+#include "ardour/linux_vst_support.h"
 
 int
 vstfx_init (void* ptr)
diff --git a/libs/ardour/vstfx.cc b/libs/ardour/vstfx.cc
deleted file mode 100755 (executable)
index 5046afb..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <pthread.h>
-#include <signal.h>
-#include <dlfcn.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <pthread.h>
-
-#include "ardour/vstfx.h"
-#include "pbd/error.h"
-
-/***********************************************************/
-/* VSTFX - A set of modules for managing linux VST plugins */
-/* vstfx.cc, vstfxwin.cc and vstfxinfofile.cc              */
-/***********************************************************/
-
-/*Simple error handler stuff for VSTFX*/
-
-void vstfx_error (const char *fmt, ...)
-{
-       va_list ap;
-       char buffer[512];
-
-       va_start (ap, fmt);
-       vsnprintf (buffer, sizeof(buffer), fmt, ap);
-       vstfx_error_callback (buffer);
-       va_end (ap);
-}
-
-/*default error handler callback*/
-
-void default_vstfx_error_callback (const char *desc)
-{
-       PBD::error << desc << endmsg;
-}
-
-void (*vstfx_error_callback)(const char *desc) = &default_vstfx_error_callback;
-
-/* --- */
-
-/*Create and return a pointer to a new VSTFX handle*/
-
-VSTHandle *
-vstfx_handle_new ()
-{
-       VSTHandle* vstfx = (VSTHandle *) calloc (1, sizeof (VSTHandle));
-       return vstfx;
-}
-
-/*Create and return a pointer to a new vstfx instance*/
-
-VSTState *
-vstfx_new ()
-{
-       VSTState* vstfx = (VSTState *) calloc (1, sizeof (VSTState));
-       
-       /*Mutexes*/
-       
-       pthread_mutex_init (&vstfx->lock, NULL);
-       pthread_cond_init (&vstfx->window_status_change, NULL);
-       pthread_cond_init (&vstfx->plugin_dispatcher_called, NULL);
-       pthread_cond_init (&vstfx->window_created, NULL);
-
-       /*Safe values*/
-       
-       vstfx->want_program = -1;
-       vstfx->want_chunk = 0;
-       vstfx->n_pending_keys = 0;
-       vstfx->has_editor = 0;
-       vstfx->program_set_without_editor = 0;
-       vstfx->linux_window = 0;
-       vstfx->linux_plugin_ui_window = 0;
-       vstfx->eventProc = NULL;
-       vstfx->extra_data = NULL;
-       vstfx->want_resize = 0;
-       
-       return vstfx;
-}
-
-/*This loads the plugin shared library*/
-
-void* vstfx_load_vst_library(const char* path)
-{
-       void* dll;
-       char* full_path;
-       char* envdup;
-       char* lxvst_path;
-       size_t len1;
-       size_t len2;
-
-       /*Try and load the shared library pointed to by the path - 
-       NOTE: You have to give RTLD_LAZY or RTLD_NOW to dlopen or
-       you get some occasional failures to load - dlerror reports
-       invalid arguments*/
-
-       if ((dll = dlopen (path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
-               return dll;
-               
-       /*We didn't find the library so try and get the path specified in the
-       env variable LXVST_PATH*/
-
-       envdup = getenv ("LXVST_PATH");
-       
-       /*Path not specified - not much more we can do*/
-       
-       if (envdup == NULL)
-               return NULL;
-       
-       /*Copy the path into envdup*/
-               
-       envdup = strdup (envdup);
-       
-       if (envdup == NULL)
-               return NULL;
-               
-       len2 = strlen(path);
-
-       /*Try all the possibilities in the path - deliminated by : */
-
-       lxvst_path = strtok (envdup, ":");
-       
-       while (lxvst_path != NULL)
-       {
-               vstfx_error ("\"%s\"", lxvst_path);
-               len1 = strlen(lxvst_path);
-               
-               full_path = (char*)malloc(len1 + 1 + len2 + 1);
-               memcpy(full_path, lxvst_path, len1);
-               full_path[len1] = '/';
-               memcpy(full_path + len1 + 1, path, len2);
-               full_path[len1 + 1 + len2] = '\0';
-
-               /*Try and load the library*/
-
-               if ((dll = dlopen(full_path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
-               {
-                       /*Succeeded */
-                       break;
-               }
-       
-               /*Try again*/
-
-               lxvst_path = strtok (NULL, ":");
-       }
-
-       /*Free the path*/
-
-       free(envdup);
-
-       return dll;
-}
-
-/*This loads up a plugin, given the path to its .so file and
- finds its main entry point etc*/
-
-VSTHandle *
-vstfx_load (const char *path)
-{
-       char* buf = NULL;
-       VSTHandle* fhandle;
-       int i;
-       
-       /*Create a new handle we can use to reference the plugin*/
-
-       fhandle = vstfx_handle_new();
-       
-       /*See if we have .so appended to the path - if not we need to make sure it is added*/
-       
-       if (strstr (path, ".so") == NULL)
-       {
-
-               /*Append the .so to the path - Make sure the path has enough space*/
-               
-               buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
-
-               sprintf (buf, "%s.so", path);
-               
-               fhandle->nameptr = strdup (path);
-
-       }
-       else
-       {
-               /*We already have .so appened to the filename*/
-               
-               buf = strdup(path);
-               
-               fhandle->nameptr = strdup (path);
-       }
-       
-       /*Use basename to shorten the path and then strip off the .so - the old VST problem,
-       we don't know anything about its name until we load and instantiate the plugin
-       which we don't want to do at this point*/
-       
-       for(i=0; i < (int)strlen(fhandle->nameptr); i++)
-       {
-               if(fhandle->nameptr[i] == '.')
-                       fhandle->nameptr[i] = 0;
-       }
-                       
-       
-       fhandle->name = basename (fhandle->nameptr);
-
-       /*call load_vstfx_library to actually load the .so into memory*/
-
-       if ((fhandle->dll = vstfx_load_vst_library (buf)) == NULL)
-       {
-               vstfx_unload (fhandle);
-               
-               free(buf);
-               
-               return NULL;
-       }
-
-       /*Find the main entry point into the plugin*/
-
-       if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == NULL)
-       {
-               /*If it can't be found, unload the plugin and return a NULL handle*/
-               
-               vstfx_unload (fhandle);
-               
-               free(buf);
-               
-               return NULL;
-       }
-
-       free(buf);
-
-       /*return the handle of the plugin*/
-
-       return fhandle;
-}
-
-/*This unloads a plugin*/
-
-int
-vstfx_unload (VSTHandle* fhandle)
-{
-       if (fhandle->plugincnt)
-       {
-               /*Still have plugin instances - can't unload the library
-               - actually dlclose keeps an instance count anyway*/
-               
-               return -1;
-       }
-
-       /*Valid plugin loaded?*/
-
-       if (fhandle->dll)
-       {
-               dlclose(fhandle->dll);
-               fhandle->dll = NULL;
-       }
-
-       if (fhandle->nameptr)
-       {
-               free (fhandle->nameptr);
-               fhandle->name = NULL;
-       }
-       
-       /*Don't need the plugin handle any more*/
-       
-       free (fhandle);
-       return 0;
-}
-
-/*This instantiates a plugin*/
-
-VSTState *
-vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
-{
-       VSTState* vstfx = vstfx_new ();
-
-       if(fhandle == NULL)
-       {
-           vstfx_error( "** ERROR ** VSTFX : The handle was NULL\n" );
-           return NULL;
-       }
-
-       if ((vstfx->plugin = fhandle->main_entry (amc)) == NULL) 
-       {
-               vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
-               free (vstfx);
-               return NULL;
-       }
-       
-       vstfx->handle = fhandle;
-       vstfx->plugin->user = userptr;
-               
-       if (vstfx->plugin->magic != kEffectMagic)
-       {
-               vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
-               free (vstfx);
-               return NULL;
-       }
-       
-       vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
-       
-       /*May or May not need to 'switch the plugin on' here - unlikely
-       since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
-       
-       //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, NULL, 0);
-       
-       vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
-       
-       vstfx->handle->plugincnt++;
-       vstfx->wantIdle = 0;
-       
-       return vstfx;
-}
-
-/*Close a vstfx instance*/
-
-void vstfx_close (VSTState* vstfx)
-{
-       vstfx_destroy_editor(vstfx);
-       
-       if(vstfx->plugin)
-       {
-               vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, NULL, 0);
-               
-               /*Calling dispatcher with effClose will cause the plugin's destructor to
-               be called, which will also remove the editor if it exists*/
-               
-               vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
-       }
-
-       if (vstfx->handle->plugincnt)
-                       vstfx->handle->plugincnt--;
-               
-       /*vstfx_unload will unload the dll if the instance count allows - 
-       we need to do this because some plugins keep their own instance count
-       and (JUCE) manages the plugin UI in its own thread.  When the plugins
-       internal instance count reaches zero, JUCE stops the UI thread and won't
-       restart it until the next time the library is loaded.  If we don't unload
-       the lib JUCE will never restart*/
-       
-       
-       if (vstfx->handle->plugincnt)
-       {
-               return;
-       }
-       
-       /*Valid plugin loaded - so we can unload it and NULL the pointer
-       to it.  We can't free the handle here because we don't know what else
-       might need it.  It should be / is freed when the plugin is deleted*/
-
-       if (vstfx->handle->dll)
-       {
-               dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
-               vstfx->handle->dll = NULL;
-       }
-}
-
-
-bool 
-vstfx_save_state (VSTState* vstfx, char * filename)
-{
-       FILE* f = fopen (filename, "wb");
-       if (f)
-       {
-               int bytelen;
-               int numParams = vstfx->plugin->numParams;
-               int i;
-               char productString[64];
-               char effectName[64];
-               char vendorString[64];
-               int success;
-
-               /* write header */
-               
-               fprintf(f, "<plugin_state>\n");
-
-               success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
-               
-               if(success == 1)
-               {
-                       fprintf (f, "  <check field=\"productString\" value=\"%s\"/>\n", productString);
-               }
-               else
-               {
-                       printf ("No product string\n");
-               }
-
-               success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
-               
-               if(success == 1)
-               {
-                       fprintf (f, "  <check field=\"effectName\" value=\"%s\"/>\n", effectName);
-                       printf ("Effect name: %s\n", effectName);
-               }
-               else
-               {
-                       printf ("No effect name\n");
-               }
-
-               success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
-               
-               if( success == 1 )
-               {
-                       fprintf (f, "  <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
-                       printf ("Vendor string: %s\n", vendorString);
-               }
-               else
-               {
-                       printf ("No vendor string\n");
-               }
-
-
-               if(vstfx->plugin->flags & 32 )
-               {
-                       numParams = 0;
-               }
-
-               for(i=0; i < numParams; i++)
-               {
-                       float val;
-                       
-                       pthread_mutex_lock( &vstfx->lock );
-                       val = vstfx->plugin->getParameter(vstfx->plugin, i );
-                       pthread_mutex_unlock( &vstfx->lock );
-                       fprintf( f, "  <param index=\"%d\" value=\"%f\"/>\n", i, val );
-               }
-
-               if(vstfx->plugin->flags & 32 )
-               {
-                       printf( "getting chunk...\n" );
-                       void * chunk;
-                       bytelen = vstfx_call_dispatcher(vstfx, 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, "  <chunk size=\"%d\">\n    %s\n  </chunk>\n", bytelen, encoded );
-                                       //g_free( encoded );
-                               }
-                       }
-               } 
-
-               fprintf( f, "</plugin_state>\n" );
-               fclose( f );
-       }
-       else
-       {
-               printf ("Could not open state file\n");
-               return false;
-       }
-       return true;
-}
-
-/*Set up a call to the plugins 'dispatcher' function*/
-
-int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt) 
-{
-       pthread_mutex_lock (&vstfx->lock);
-       
-       /*Set up the opcode and parameters*/
-       
-       vstfx->dispatcher_opcode = opcode;
-       vstfx->dispatcher_index = index;
-       vstfx->dispatcher_val = val;
-       vstfx->dispatcher_ptr = ptr;
-       vstfx->dispatcher_opt = opt;
-       
-       /*Signal that we want the call to happen*/
-       
-       vstfx->dispatcher_wantcall = 1;
-
-       /*Wait for the call to happen*/
-
-       pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
-       pthread_mutex_unlock (&vstfx->lock);
-
-       /*Return the result*/
-       
-       return vstfx->dispatcher_retval;
-}
diff --git a/libs/ardour/vstfxinfofile.cc b/libs/ardour/vstfxinfofile.cc
deleted file mode 100755 (executable)
index 070c646..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/***********************************************************/
-/*vstfx infofile - module to manage info files             */
-/*containing cached information about a plugin. e.g. its   */
-/*name, creator etc etc                                    */
-/***********************************************************/
-
-#include <iostream>
-
-#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 "ardour/vstfx.h"
-
-#define MAX_STRING_LEN 256
-
-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;
-    }
-}
-
-static VSTInfo *
-load_vstfx_info_file (FILE* fp)
-{
-       VSTInfo *info;
-       int i;
-       
-       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(1 != fscanf(fp, "%d\n", &info->UniqueID)) goto error;
-       if((info->Category = read_string(fp)) == 0) 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)) == 0) {
-               goto error;
-       }
-
-       for (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 (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)
-{
-    int i;
-
-    if (info == 0) {
-           vstfx_error("** ERROR ** VSTFXinfofile : info ptr is 0\n");
-           return -1;
-    }
-
-    if (fp == 0) {
-           vstfx_error("** ERROR ** VSTFXinfofile : file ptr is 0\n");
-           return -1;
-    }
-    
-    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]);
-    }
-       
-    return 0;
-}
-
-static char* vstfx_infofile_stat (char *dllpath, struct stat* statbuf, int personal)
-{
-       char* path;
-       char* dir_path;
-       char* basename;
-       char* base;
-       size_t blen;
-
-       if (strstr (dllpath, ".so" ) == 0) {
-               return 0;
-       }
-       
-       if (personal) {
-               dir_path = g_build_filename (g_get_home_dir(), ".fst", NULL);
-       } else {
-               dir_path = g_path_get_dirname (dllpath);
-       }
-       
-       base = g_path_get_basename (dllpath);
-       blen = strlen (base) + 2; // null char and '.'
-       basename = (char*) g_malloc (blen);
-       snprintf (basename, blen, ".%s.fsi", base);
-       g_free (base);
-       
-       path = g_build_filename (dir_path, basename, NULL);
-       
-       g_free (dir_path);
-       g_free (basename);
-
-
-       if (g_file_test (path, GFileTest (G_FILE_TEST_EXISTS|G_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, statbuf) == 0) {
-                               if (dllstat.st_mtime <= statbuf->st_mtime) {
-                                       /* plugin is older than info file */
-                                       return path;
-                               }
-                       }
-               } 
-       }
-
-       g_free (path);
-
-       return 0;
-}
-
-
-static FILE* vstfx_infofile_for_read (char* dllpath)
-{
-       struct stat own_statbuf;
-       struct stat sys_statbuf;
-       char *own_info;
-       char *sys_info;
-       
-       own_info = vstfx_infofile_stat (dllpath, &own_statbuf, 1);
-       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 */
-                               return fopen (sys_info, "r");
-                       }
-               } else {
-                       return fopen (own_info, "r");
-               }
-       }
-
-       return 0;
-}
-
-static FILE* vstfx_infofile_create (char* dllpath, int personal)
-{
-       char* path;
-       char* dir_path;
-       char* basename;
-       char* base;
-       size_t blen;
-
-       if (strstr (dllpath, ".so" ) == 0) {
-               return 0;
-       }
-       
-       if (personal) {
-               dir_path = g_build_filename (g_get_home_dir(), ".fst", NULL);
-
-               /* if the directory doesn't yet exist, try to create it */
-
-               if (!g_file_test (dir_path, G_FILE_TEST_IS_DIR)) {
-                       if (g_mkdir (dir_path, 0700)) {
-                               return 0;
-                       }
-               }
-
-       } else {
-               dir_path = g_path_get_dirname (dllpath);
-       }
-       
-       base = g_path_get_basename (dllpath);
-       blen = strlen (base) + 2; // null char and '.'
-       basename = (char*) g_malloc (blen);
-       snprintf (basename, blen, ".%s.fsi", base);
-       g_free (base);
-
-       path = g_build_filename (dir_path, basename, NULL);
-
-       g_free (dir_path);
-       g_free (basename);
-
-       FILE* f = fopen (path, "w");
-       g_free (path);
-
-       return f;
-}
-
-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 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)
-{
-       VSTInfo* info = (VSTInfo*) malloc (sizeof (VSTInfo));
-       
-       AEffect *plugin;
-       int i;
-       
-       /*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";
-       
-       if(!vstfx)
-       {
-               vstfx_error( "** ERROR ** VSTFXinfofile : vstfx ptr is 0\n" );
-               return 0;
-       }
-       
-       if(!info)
-               return 0;
-       
-       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");          // FIXME:  
-       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(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;
-       VSTInfo* info;
-
-       if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) {
-               VSTInfo *info;
-               info = load_vstfx_info_file (infofile);
-               fclose (infofile);
-               return info;
-       } 
-       
-       if(!(h = vstfx_load(dllpath)))
-               return 0;
-       
-       if(!(vstfx = vstfx_instantiate(h, simple_master_callback, 0))) {
-               vstfx_unload(h);
-               vstfx_error( "** ERROR ** VSTFXinfofile : Instantiate failed\n" );
-               return 0;
-       }
-       
-       infofile = vstfx_infofile_for_write (dllpath);
-       
-       if(!infofile) {
-               vstfx_close(vstfx);
-               vstfx_unload(h);
-               vstfx_error("cannot create new FST info file for plugin");
-               return 0;
-       }
-       
-       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);
-}
-
-
index 6d79413a1f496fb6c04b47d691998506f8cdb3c7..d6b72dbf2de9df9370816c15756f24897870d005 100644 (file)
@@ -391,7 +391,7 @@ def build(bld):
         obj.defines += [ 'WINDOWS_VST_SUPPORT' ]
 
     if bld.is_defined('LXVST_SUPPORT'):
-        obj.source += [ 'lxvst_plugin.cc', 'vstfx.cc', 'vstfxinfofile.cc' ]
+        obj.source += [ 'lxvst_plugin.cc', 'linux_vst_support.cc', 'linux_vst_info_file.cc' ]
         obj.defines += [ 'LXVST_SUPPORT' ]
 
     if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT'):