From 0a919a7b36ee4b58e5ce3628a2d8b97bf751d2c4 Mon Sep 17 00:00:00 2001
From: "Tim E. Real" <termtech@rogers.com>
Date: Fri, 7 Dec 2012 07:41:24 +0000
Subject: Feature: Native VST instruments support. PLEASE SEE ChangeLog.

---
 muse2/CMakeLists.txt                      |   96 +-
 muse2/ChangeLog                           |    7 +
 muse2/config.h.in                         |    2 +
 muse2/muse/CMakeLists.txt                 |    1 +
 muse2/muse/arranger/tlist.cpp             |   14 +-
 muse2/muse/audiotrack.cpp                 |  122 +-
 muse2/muse/controlfifo.h                  |    4 +-
 muse2/muse/dssihost.cpp                   |   64 +-
 muse2/muse/dssihost.h                     |   19 +-
 muse2/muse/globals.cpp                    |    1 +
 muse2/muse/globals.h                      |    1 +
 muse2/muse/helper.cpp                     |    8 -
 muse2/muse/main.cpp                       |   11 +
 muse2/muse/osc.cpp                        |   11 +-
 muse2/muse/plugin.cpp                     |    2 +
 muse2/muse/plugin.h                       |    4 +
 muse2/muse/synth.cpp                      |   58 +-
 muse2/muse/synth.h                        |   47 +-
 muse2/muse/track.cpp                      |   18 +-
 muse2/muse/vst_native.cpp                 | 2628 +++++++++++++++++++++++++++++
 muse2/muse/vst_native.h                   |  281 +++
 muse2/muse/widgets/CMakeLists.txt         |    2 +
 muse2/muse/widgets/vst_native_editor.cpp  |  223 +++
 muse2/muse/widgets/vst_native_editor.h    |   91 +
 muse2/synti/deicsonze/deicsonzeplugin.cpp |    4 +
 25 files changed, 3545 insertions(+), 174 deletions(-)
 create mode 100644 muse2/muse/vst_native.cpp
 create mode 100644 muse2/muse/vst_native.h
 create mode 100644 muse2/muse/widgets/vst_native_editor.cpp
 create mode 100644 muse2/muse/widgets/vst_native_editor.h

diff --git a/muse2/CMakeLists.txt b/muse2/CMakeLists.txt
index b0a381e5..6f8d7817 100644
--- a/muse2/CMakeLists.txt
+++ b/muse2/CMakeLists.txt
@@ -22,6 +22,7 @@
 #=============================================================================
 
 include(FindPkgConfig)
+include(CheckIncludeFile)
 include(cmake/Summary.cmake)
 include(cmake/TargetDoc.cmake)
 
@@ -35,6 +36,12 @@ if (NOT DEFINED LIB_SUFFIX)
         SET(LIB_SUFFIX "" CACHE STRING "Suffix for installed library path. Ex. 64 for lib64")
 endif (NOT DEFINED LIB_SUFFIX)
 
+if (NOT DEFINED VST_HEADER_PATH)
+        SET(VST_HEADER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/vestige" CACHE PATH "Path to vst header files (aeffectx.h). Default is ./vestige. See ENABLE_VST_SDK.")
+endif (NOT DEFINED VST_HEADER_PATH)
+message(" vst header path: " ${VST_HEADER_PATH} )
+include_directories(${VST_HEADER_PATH})
+
 # set libdir if not use -DLIB_INSTALL_DIR
 if (NOT LIB_INSTALL_DIR)
         if(CMAKE_INSTALL_LIBDIR)
@@ -112,18 +119,16 @@ else (${SVNVER} STREQUAL "SVNVER-NOTFOUND")
             OUTPUT_VARIABLE MusE_SVNVER )
 endif (${SVNVER} STREQUAL "SVNVER-NOTFOUND")
 
-# Do we need this? - Orcan:
-# include ( ${PROJECT_SOURCE_DIR}/cmake/WrapMacros.cmake)
-
-option ( ENABLE_LASH        "enable LASH Audio Session Handler (or LADISH compatibility layer)"     ON)
-option ( ENABLE_OSC         "enable Lightweight Open Sound Control (liblo) (DSSI also recommended)"  ON)   
-option ( ENABLE_DSSI        "enable Disposable Soft Synth Interface (dssi) (OSC also recommended)" ON)
-option ( ENABLE_VST         "enable VST/win support (deprecated)"                                OFF)
-option ( ENABLE_FLUID       "enable fluidsynth softsynth plugins"                                ON)
-option ( ENABLE_EXPERIMENTAL "enable building experimental features"                             OFF)
-option ( ENABLE_PYTHON      "enable Python control support"                                      OFF)
-option ( UPDATE_TRANSLATIONS "Update source translation share/locale/*.ts files 
-         (WARNING: This will modify the .ts files in the source tree!!)"                         OFF)
+option ( ENABLE_LASH        "Enable LASH Audio Session Handler (or LADISH compatibility layer)"     ON)
+option ( ENABLE_OSC         "Enable Lightweight Open Sound Control (liblo) (DSSI also recommended)"  ON)
+option ( ENABLE_DSSI        "Enable Disposable Soft Synth Interface (dssi) (OSC also recommended)" ON)
+option ( ENABLE_VST         "Enable VST/win support (deprecated)"                                OFF)
+option ( ENABLE_VST_NATIVE  "Enable Native VST support (see ENABLE_VST_SDK and VST_HEADER_PATH)" ON)
+option ( ENABLE_VST_SDK     "Enable VST SDK support (requires SDK, recommended for best results!)" OFF)
+option ( ENABLE_FLUID       "Enable fluidsynth softsynth plugins."                                ON)
+option ( ENABLE_EXPERIMENTAL "Enable building experimental features."                             OFF)
+option ( ENABLE_PYTHON      "Enable Python control support."                                      OFF)
+option ( UPDATE_TRANSLATIONS "Update source translation share/locale/*.ts files (WARNING: This will modify the .ts files in the source tree!!)" OFF)
 option ( MODULES_BUILD_STATIC "Build type of internal modules"                                   OFF)
 
 if ( MODULES_BUILD_STATIC )
@@ -153,7 +158,6 @@ endif (APPLE)
 set(QT_MIN_VERSION "4.3.0")
 set(QT_USE_QTXML TRUE)
 set(QT_USE_QTDESIGNER TRUE)
-#set(QT_USE_QTNSPLUGIN TRUE)
 set(QT_USE_QTSVG TRUE)
 
 find_package(Qt4)
@@ -174,13 +178,21 @@ include(${QT_USE_FILE})
 ##   Begin MANDATORY packages...
 ##
 
-
 ##
 ## find doxygen program
 ##
 
 FIND_PROGRAM(DOXY doxygen)
 
+##
+## find ladspa.h
+##
+
+CHECK_INCLUDE_FILE(ladspa.h HAVE_LADSPA_H)
+if(NOT HAVE_LADSPA_H)
+      message(FATAL_ERROR "** ERROR: header file ladspa.h is required, but was not found.")
+endif(NOT HAVE_LADSPA_H)
+
 ##
 ## alsa >= 0.9.0
 ##
@@ -292,6 +304,10 @@ else (ENABLE_DSSI)
       message("DSSI disabled")
 endif (ENABLE_DSSI)
 
+##
+## Depricated FST-based VST support
+##
+
 if (ENABLE_VST)
       message("deprecated VST support enabled")
       set (VST_SUPPORT TRUE)
@@ -300,6 +316,36 @@ else (ENABLE_VST)
       set (VST_SUPPORT FALSE)
 endif (ENABLE_VST)
 
+##
+## Native VST support
+##
+
+SET (AEFFECT_H_FOUND FALSE)
+SET (VST_NATIVE_SUPPORT FALSE)
+
+if (ENABLE_VST_NATIVE)
+      find_file(VST_HEADER_CHECK aeffectx.h PATHS ${VST_HEADER_PATH} NO_DEFAULT_PATH)
+      if (VST_HEADER_CHECK STREQUAL "VST_HEADER_CHECK-NOTFOUND")
+        message("Native VST support disabled")
+      else (VST_HEADER_CHECK STREQUAL "VST_HEADER_CHECK-NOTFOUND")
+        SET (AEFFECT_H_FOUND TRUE)
+        message("Native VST support enabled")
+        set (VST_NATIVE_SUPPORT TRUE)
+      endif (VST_HEADER_CHECK STREQUAL "VST_HEADER_CHECK-NOTFOUND")
+    
+else (ENABLE_VST_NATIVE)
+      message("Native VST support disabled")
+endif (ENABLE_VST_NATIVE)
+
+# find_file creates a cached variable. We don't want VST_HEADER_CHECK cached.
+UNSET (VST_HEADER_CHECK CACHE)
+
+if (ENABLE_VST_SDK)
+  SET (VST_SDK_SUPPORT TRUE)
+else (ENABLE_VST_SDK) 
+  SET (VST_SDK_SUPPORT FALSE)
+endif (ENABLE_VST_SDK)
+
 ##
 ## TODO
 ##
@@ -313,19 +359,12 @@ SET (USE_SSE false)
 ##
 
 if ( ENABLE_FLUID )
-      # Be careful with naming here since we have two shared synth libraries
-      #  to be built later, named 'fluidsynth' and 'fluid' !
+      # Be careful with variable name here since we have a shared
+      #  synth library named 'fluid_synth' to be built later.
       PKG_CHECK_MODULES(FLUIDSYN fluidsynth>=0.9.0)
       if (FLUIDSYN_FOUND)
             include_directories(${FLUIDSYN_INCLUDE_DIRS})
             set(HAVE_FLUIDSYNTH ON)
-            ## This stuff is just F.Y.I. Please keep...
-            # message("FLUIDSYN_LIBRARIES " ${FLUIDSYN_LIBRARIES} )          # "fluidsynth"
-            # message("FLUIDSYN_LDFLAGS " ${FLUIDSYN_LDFLAGS} )              # "-lfluidsynth"
-            # message("FLUIDSYN_LDFLAGS_OTHER " ${FLUIDSYN_LDFLAGS_OTHER} )  # empty
-            # message("FLUIDSYN_INCLUDE_DIRS " ${FLUIDSYN_INCLUDE_DIRS} )    # empty
-            # message("FLUIDSYN_CFLAGS " ${FLUIDSYN_CFLAGS} )                # empty
-            # message("FLUIDSYN_CFLAGS_OTHER " ${FLUIDSYN_CFLAGS_OTHER} )    # empty
       endif (FLUIDSYN_FOUND)
 else ( ENABLE_FLUID )
       message("Fluidsynth disabled")
@@ -418,9 +457,6 @@ set(CMAKE_CXX_FLAGS         "-Wall -Wextra -Winvalid-pch -fno-exceptions -fPIC $
 set(CMAKE_CXX_FLAGS_RELEASE "-O2 -fomit-frame-pointer -ffast-math -fstrength-reduce -fPIC ${CMAKE_CXX_FLAGS_RELEASE}")
 set(CMAKE_CXX_FLAGS_DEBUG   "-g -DQT_DEBUG -fPIC ${CMAKE_CXX_FLAGS_DEBUG}")
 
-# subdirs(al awl grepmidi plugins midiplugins muse share synti)
-# subdirs(al lib grepmidi plugins xpm muse share demos doc synti utils)
-#subdirs(al lib grepmidi plugins muse share demos synti )
 # NOTE: share/ directory needs to be at the end so that the translations
 #       are scanned before coming to share/locale
 subdirs(al awl grepmidi man plugins muse synti packaging utils demos share)
@@ -480,7 +516,7 @@ endif (NOT UUID_FOUND)
 
 if (NOT JACK_FOUND)
       message("** ERROR: jack >= 0.103 is required, but development files were not found.")
-endif (NOT JACK_FOUND)           
+endif (NOT JACK_FOUND)
 
 if (ENABLE_LASH AND (NOT LASH_FOUND))
         message("** WARNING: lash (>= 0.2) was enabled, but development files were not found. ")
@@ -499,6 +535,11 @@ if (ENABLE_DSSI AND (NOT DSSI_FOUND))
         message("** WARNING: dssi (>= 0.9.0) was enabled, but development files were not found.")
 endif (ENABLE_DSSI AND (NOT DSSI_FOUND))
 
+if (ENABLE_VST_NATIVE AND (NOT AEFFECT_H_FOUND))
+        message("** WARNING: Native VST was enabled, but development files were not found.")
+        message("** HINT: Check the VST_HEADER_PATH variable. Points to ./vestige by default.")
+endif (ENABLE_VST_NATIVE AND (NOT AEFFECT_H_FOUND))
+
 if (ENABLE_FLUID AND (NOT FLUIDSYN_FOUND))
         message("** WARNING: fluidsynth (>= 0.9.0) was enabled, but development files were not found.")
 endif (ENABLE_FLUID AND (NOT FLUIDSYN_FOUND))
@@ -511,6 +552,7 @@ summary_add("OSC (Liblo) support" OSC_SUPPORT)
 summary_add("Python support" PYTHON_SUPPORT)
 summary_add("DSSI support" DSSI_SUPPORT)
 #summary_add("VST support" VST_SUPPORT)
+summary_add("Native VST support" VST_NATIVE_SUPPORT)
 summary_add("Fluidsynth support" HAVE_FLUIDSYNTH)
 summary_add("Experimental features" ENABLE_EXPERIMENTAL)
 summary_show()
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index c14b9d7f..2ecf15af 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,10 @@
+07.12.2012:
+         * Feature: Native VST instruments support. Best results are from compiling with the vst sdk. (Tim)
+           Featuring: True sample-accurate parameter automation, full native GUI support for TOUCH, WRITE modes.
+           New cmake options for enabling native vst, enabling true sdk support, and the vst header path.
+           Plugins environment variable is currently VST_NATIVE_PATH else "/usr/lib/vst:/usr/local/lib/vst".
+           TODOs: Parameter ranges: fixed at linear 0.0 - 1.0 for now. Program categories.
+                  Dynamic port changes. Plugins correct path and env var? No rack effect plugins yet. 
 25.11.2012:
          - Changed playback of midi in editors to default to on (rj)
 21.11.2012:
diff --git a/muse2/config.h.in b/muse2/config.h.in
index 35f01bca..029b4521 100644
--- a/muse2/config.h.in
+++ b/muse2/config.h.in
@@ -24,6 +24,8 @@
 #cmakedefine OSC_SUPPORT
 #cmakedefine DSSI_SUPPORT
 #cmakedefine VST_SUPPORT
+#cmakedefine VST_NATIVE_SUPPORT
+#cmakedefine VST_SDK_SUPPORT
 #cmakedefine USE_SSE
 
 #define VERSION          "${MusE_VERSION_FULL}"
diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt
index 36645db4..574a84cf 100644
--- a/muse2/muse/CMakeLists.txt
+++ b/muse2/muse/CMakeLists.txt
@@ -138,6 +138,7 @@ file (GLOB core_source_files
       undo.cpp
       value.cpp
       vst.cpp
+      vst_native.cpp
       wave.cpp
       waveevent.cpp 
       wavetrack.cpp 
diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp
index 3bc13934..31c2a7a3 100644
--- a/muse2/muse/arranger/tlist.cpp
+++ b/muse2/muse/arranger/tlist.cpp
@@ -1175,7 +1175,7 @@ void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y)
       {
       if(t->type() == MusECore::Track::AUDIO_SOFTSYNTH)
       {
-        MusECore::SynthI* synth = (MusECore::SynthI*)t;
+        MusECore::SynthI* synth = static_cast<MusECore::SynthI*>(t);
   
         QMenu* p = new QMenu;
         QAction* gact = p->addAction(tr("show gui"));
@@ -1191,7 +1191,7 @@ void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y)
         // If it has a gui but we don't have OSC, disable the action.
         #ifndef OSC_SUPPORT
         #ifdef DSSI_SUPPORT
-        if(dynamic_cast<MusECore::DssiSynthIF*>(synth->sif()))
+        if(synth->synth() && synth->synth()->synthType() == MusECore::Synth::DSSI_SYNTH)
         {
           nact->setChecked(false);
           nact->setEnabled(false);
@@ -1233,10 +1233,14 @@ void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y)
       #ifndef OSC_SUPPORT
       #ifdef DSSI_SUPPORT
       MusECore::MidiDevice* dev = port->device();
-      if(dev && dev->isSynti() && (dynamic_cast<MusECore::DssiSynthIF*>(((MusECore::SynthI*)dev)->sif())))
+      if(dev && dev->isSynti()) 
       {
-        nact->setChecked(false);
-        nact->setEnabled(false);
+        MusECore::SynthI* synth = static_cast<MusECore::SynthI*>(dev);
+        if(synth->synth() && synth->synth()->synthType() == MusECore::Synth::DSSI_SYNTH)
+        {
+          nact->setChecked(false);
+          nact->setEnabled(false);
+        }
       }  
       #endif
       #endif
diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp
index 08240f75..91b07063 100644
--- a/muse2/muse/audiotrack.cpp
+++ b/muse2/muse/audiotrack.cpp
@@ -38,6 +38,7 @@
 #include "audiodev.h"
 #include "synth.h"
 #include "dssihost.h"
+#include "vst_native.h"
 #include "app.h"
 #include "controlfifo.h"
 #include "fastlog.h"
@@ -845,7 +846,7 @@ double AudioTrack::pluginCtrlVal(int ctlID) const
       }
       else
       {
-        if(ctlID < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special dssi synth controller block.             
+        if(ctlID < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special synth controller block.
         {
           _efxPipe->controllersEnabled(ctlID, &en_1, &en_2); 
         }
@@ -853,20 +854,14 @@ double AudioTrack::pluginCtrlVal(int ctlID) const
         {
           if(type() == AUDIO_SOFTSYNTH)
           {
-#ifdef DSSI_SUPPORT            
             const SynthI* synth = static_cast<const SynthI*>(this);
-            if(synth->synth() && synth->synth()->synthType() == Synth::DSSI_SYNTH)
+            const SynthIF* sif = synth->sif();
+            if(sif)
             {
-              SynthIF* sif = synth->sif();
-              if(sif)
-              {
-                const DssiSynthIF* dssi_sif = static_cast<const DssiSynthIF*>(sif);
-                int in_ctrl_idx = ctlID & AC_PLUGIN_CTL_ID_MASK;
-                en_1 = dssi_sif->controllerEnabled(in_ctrl_idx);
-                en_2 = dssi_sif->controllerEnabled2(in_ctrl_idx);
-              }
+              int in_ctrl_idx = ctlID & AC_PLUGIN_CTL_ID_MASK;
+              en_1 = sif->controllerEnabled(in_ctrl_idx);
+              en_2 = sif->controllerEnabled2(in_ctrl_idx);
             }
-#endif
           }
         }
       }  
@@ -905,25 +900,19 @@ bool AudioTrack::addScheduledControlEvent(int track_ctrl_id, float val, unsigned
   }
   else
   {
-    if(track_ctrl_id < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special dssi synth controller block.             
+    if(track_ctrl_id < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special synth controller block.
       return _efxPipe->addScheduledControlEvent(track_ctrl_id, val, frame);
     else
     {
       if(type() == AUDIO_SOFTSYNTH)
       {
- #ifdef DSSI_SUPPORT
         const SynthI* synth = static_cast<const SynthI*>(this);
-        if(synth->synth() && synth->synth()->synthType() == Synth::DSSI_SYNTH)
+        SynthIF* sif = synth->sif();
+        if(sif)
         {
-          SynthIF* sif = synth->sif();
-          if(sif)
-          {
-            DssiSynthIF* dssi_sif = static_cast<DssiSynthIF*>(sif);
-            int in_ctrl_idx = track_ctrl_id & AC_PLUGIN_CTL_ID_MASK;
-            return dssi_sif->addScheduledControlEvent(in_ctrl_idx, val, frame);
-          }
+          int in_ctrl_idx = track_ctrl_id & AC_PLUGIN_CTL_ID_MASK;
+          return sif->addScheduledControlEvent(in_ctrl_idx, val, frame);
         }
- #endif
       }
     }
   }  
@@ -949,25 +938,19 @@ void AudioTrack::enableController(int track_ctrl_id, bool en)
   }
   else
   {
-    if(track_ctrl_id < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special dssi synth controller block.             
+    if(track_ctrl_id < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special synth controller block.
       _efxPipe->enableController(track_ctrl_id, en);
     else
     {
       if(type() == AUDIO_SOFTSYNTH)
       {
-#ifdef DSSI_SUPPORT        
-        SynthI* synth = static_cast<SynthI*>(this);
-        if(synth->synth() && synth->synth()->synthType() == Synth::DSSI_SYNTH)
+        const SynthI* synth = static_cast<const SynthI*>(this);
+        SynthIF* sif = synth->sif();
+        if(sif)
         {
-          SynthIF* sif = synth->sif();
-          if(sif)
-          {
-            DssiSynthIF* dssi_sif = static_cast<DssiSynthIF*>(sif);
-            int in_ctrl_idx = track_ctrl_id & AC_PLUGIN_CTL_ID_MASK;
-            dssi_sif->enableController(in_ctrl_idx, en);
-          }
+          int in_ctrl_idx = track_ctrl_id & AC_PLUGIN_CTL_ID_MASK;
+          sif->enableController(in_ctrl_idx, en);
         }
-#endif
       }
     }
   }  
@@ -996,7 +979,7 @@ void AudioTrack::controllersEnabled(int track_ctrl_id, bool* en1, bool* en2) con
       }
       else
       {
-        if(track_ctrl_id < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special dssi synth controller block.             
+        if(track_ctrl_id < (int)genACnum(MAX_PLUGINS, 0))  // The beginning of the special synth controller block.
         {
           _efxPipe->controllersEnabled(track_ctrl_id, &en_1, &en_2); 
         }
@@ -1004,20 +987,14 @@ void AudioTrack::controllersEnabled(int track_ctrl_id, bool* en1, bool* en2) con
         {
           if(type() == AUDIO_SOFTSYNTH)
           {
-#ifdef DSSI_SUPPORT
             const SynthI* synth = static_cast<const SynthI*>(this);
-            if(synth->synth() && synth->synth()->synthType() == Synth::DSSI_SYNTH)
+            const SynthIF* sif = synth->sif();
+            if(sif)
             {
-              SynthIF* sif = synth->sif();
-              if(sif)
-              {
-                const DssiSynthIF* dssi_sif = static_cast<const DssiSynthIF*>(sif);
-                int in_ctrl_idx = track_ctrl_id & AC_PLUGIN_CTL_ID_MASK;
-                en_1 = dssi_sif->controllerEnabled(in_ctrl_idx);
-                en_2 = dssi_sif->controllerEnabled2(in_ctrl_idx);
-              }
+              int in_ctrl_idx = track_ctrl_id & AC_PLUGIN_CTL_ID_MASK;
+              en_1 = sif->controllerEnabled(in_ctrl_idx);
+              en_2 = sif->controllerEnabled2(in_ctrl_idx);
             }
-#endif
           }
         }
       }  
@@ -1204,38 +1181,24 @@ bool AudioTrack::readProperties(Xml& xml, const QString& tag)
             //  controls would all be set to zero.
             // But we will allow for the (unintended, useless) possibility of a controller 
             //  with no matching plugin control.
-            PluginIBase* p = 0;     
+            const PluginIBase* p = 0;     
             bool ctlfound = false;
             unsigned m = l->id() & AC_PLUGIN_CTL_ID_MASK;       
             int n = (l->id() >> AC_PLUGIN_CTL_BASE_POW) - 1;
             if(n >= 0 && n < PipelineDepth)
-            {
               p = (*_efxPipe)[n];
-              if(p && m < p->parameters())
-                  ctlfound = true;
-            }
-            // Support a special block for dssi synth ladspa controllers. 
+            // Support a special block for synth controllers.
             else if(n == MAX_PLUGINS && type() == AUDIO_SOFTSYNTH)    
             {
-              SynthI* synti = dynamic_cast < SynthI* > (this);
-              if(synti)
-              {
-                SynthIF* sif = synti->sif();
-                if(sif)
-                {
-#ifdef DSSI_SUPPORT
-                  DssiSynthIF* dsif = dynamic_cast < DssiSynthIF* > (sif);
-                  if(dsif)
-                  {
-                    p = dsif;
-                    if(p && m < p->parameters())
-                        ctlfound = true;
-                  }
-#endif
-                }
-              }
+              const SynthI* synti = static_cast < SynthI* > (this);
+              const SynthIF* sif = synti->sif();
+              if(sif)
+                p = static_cast < const PluginIBase* > (sif);
             }
             
+            if(p && m < p->parameters())
+              ctlfound = true;
+            
             iCtrlList icl = _controller.find(l->id());
             if (icl == _controller.end())
                   _controller.add(l);
@@ -1382,22 +1345,13 @@ void AudioTrack::mapRackPluginsToControllers()
       const PluginIBase* p = 0;
       if(idx >= 0 && idx < PipelineDepth)
         p = (*_efxPipe)[idx];
-      // Support a special block for dssi synth ladspa controllers. 
+      // Support a special block for synth controllers.
       else if(idx == MAX_PLUGINS && type() == AUDIO_SOFTSYNTH)    
       {
-        const SynthI* synti = dynamic_cast < const SynthI* > (this);
-        if(synti)
-        {
-          SynthIF* sif = synti->sif();
-          if(sif)
-          {
-#ifdef DSSI_SUPPORT
-            const DssiSynthIF* dsif = dynamic_cast < const DssiSynthIF* > (sif);
-            if(dsif)
-              p = dsif;
-#endif
-          }
-        }
+        const SynthI* synti = static_cast < const SynthI* > (this);
+        SynthIF* sif = synti->sif();
+        if(sif)
+          p = static_cast < const PluginIBase* > (sif);
       }
       
       // If there's no plugin at that rack position, or the param is out of range of
diff --git a/muse2/muse/controlfifo.h b/muse2/muse/controlfifo.h
index 6a35c8a5..6ee2cedb 100644
--- a/muse2/muse/controlfifo.h
+++ b/muse2/muse/controlfifo.h
@@ -36,7 +36,9 @@ struct ControlEvent
   // Unique: Whether the item must not be skipped, even if it has the same 
   //  (possibly rounded) frame and index as the previous item. This is mainly for 
   //  dssi-vst guis, they require acknowledgment of every message.
-  bool unique; 
+  bool unique;
+  // Whether or not the event is from a synth or effect's own GUI.
+  bool fromGui;
   unsigned long idx;
   float value;
   unsigned long frame;    
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index 70db2a47..f62d1434 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -157,7 +157,7 @@ static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument
 //   scanVstDir
 //---------------------------------------------------------
 
-static void scanDSSIDir(QString& s) // ddskrjo removed const for argument
+static void scanDSSIDir(const QString& s)
 {
       if(MusEGlobal::debugMsg)
         printf("scanDSSIDir: scan DSSI plugin dir <%s>\n", s.toLatin1().constData());
@@ -202,8 +202,7 @@ void initDSSI()
                   char* buffer = new char[n + 1];
                   strncpy(buffer, p, n);
                   buffer[n] = '\0';
-                  QString tmpStr(buffer);
-                  scanDSSIDir(tmpStr);
+                  scanDSSIDir(QString(buffer));
                   delete[] buffer;
                   }
             p = pe;
@@ -270,7 +269,8 @@ DssiSynth::DssiSynth(QFileInfo& fi, const DSSI_Descriptor* d) : // ddskrjo remov
 DssiSynth::~DssiSynth() 
 { 
   if(dssi)
-    delete dssi;
+  //  delete dssi;
+    printf("DssiSynth::~DssiSynth Error: dssi descriptor is not NULL\n");
 }
 
 //---------------------------------------------------------
@@ -650,9 +650,8 @@ bool DssiSynthIF::init(DssiSynth* s)
           }
         }
       }
-          
-      if (ld->activate)
-            ld->activate(handle);
+
+      activate();
 
       // Set current configuration values.
       if(dssi->configure) 
@@ -1988,6 +1987,7 @@ int DssiSynthIF::oscControl(unsigned long port, float value)
   // p4.0.21
   ControlEvent ce;
   ce.unique = synth->_isDssiVst;    // Special for messages from vst gui to host - requires processing every message.
+  ce.fromGui = true;                // It came form the plugin's own GUI.
   ce.idx = cport;
   ce.value = value;
 
@@ -2305,21 +2305,27 @@ int DssiSynthIF::totalInChannels() const
   return synth->_inports; 
 }
 
+void DssiSynthIF::deactivate3()
+{
+  deactivate();
+}
+
+
 //--------------------------------
 // Methods for PluginIBase:
 //--------------------------------
 
-bool DssiSynthIF::on() const                                 { return true; }  // Synth is not part of a rack plugin chain. Always on.
-void DssiSynthIF::setOn(bool /*val*/)                        { }   
+//bool DssiSynthIF::on() const                                 { return true; }  // Synth is not part of a rack plugin chain. Always on.
+//void DssiSynthIF::setOn(bool /*val*/)                        { }   
 unsigned long DssiSynthIF::pluginID()                        { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->UniqueID : 0; }   
 int DssiSynthIF::id()                                        { return MAX_PLUGINS; } // Set for special block reserved for dssi synth. p4.0.20
 QString DssiSynthIF::pluginLabel() const                     { return (synth && synth->dssi) ? QString(synth->dssi->LADSPA_Plugin->Label) : QString(); } 
-QString DssiSynthIF::name() const                            { return synti->name(); }
+//QString DssiSynthIF::name() const                            { return synti->name(); }
 QString DssiSynthIF::lib() const                             { return synth ? synth->completeBaseName() : QString(); }
 QString DssiSynthIF::dirPath() const                         { return synth ? synth->absolutePath() : QString(); }
 QString DssiSynthIF::fileName() const                        { return synth ? synth->fileName() : QString(); }
-QString DssiSynthIF::titlePrefix() const                     { return QString(); }
-MusECore::AudioTrack* DssiSynthIF::track()                   { return (MusECore::AudioTrack*)synti; }
+//QString DssiSynthIF::titlePrefix() const                     { return QString(); }
+//MusECore::AudioTrack* DssiSynthIF::track()                   { return (MusECore::AudioTrack*)synti; }
 void DssiSynthIF::enableController(unsigned long i, bool v)  { controls[i].enCtrl = v; } 
 bool DssiSynthIF::controllerEnabled(unsigned long i) const   { return controls[i].enCtrl; }  
 void DssiSynthIF::enable2Controller(unsigned long i, bool v) { controls[i].en2Ctrl = v; }     
@@ -2338,10 +2344,38 @@ void DssiSynthIF::enable2AllControllers(bool v)
   for(unsigned long i = 0; i < synth->_controlInPorts; ++i)
     controls[i].en2Ctrl = v; 
 }
+void DssiSynthIF::updateControllers() { }
+void DssiSynthIF::activate()
+{
+  if(synth && synth->dssi && synth->dssi->LADSPA_Plugin && synth->dssi->LADSPA_Plugin->activate)
+    //for (int i = 0; i < instances; ++i)
+    //  _plugin->activate(handle[i]);
+    synth->dssi->LADSPA_Plugin->activate(handle);
+
+// REMOVE Tim. Or keep? From PluginI::activate().
+//   if (initControlValues) {
+//         for (unsigned long i = 0; i < controlPorts; ++i) {
+//               controls[i].val = controls[i].tmpVal;
+//               }
+//         }
+//   else {
+//         // get initial control values from plugin
+//         for (unsigned long i = 0; i < controlPorts; ++i) {
+//               controls[i].tmpVal = controls[i].val;
+//               }
+//         }
+}
+void DssiSynthIF::deactivate()
+{
+  if(!synth || !synth->dssi || !synth->dssi->LADSPA_Plugin ||!synth->dssi->LADSPA_Plugin->deactivate)
+    return;
+  //for (int i = 0; i < instances; ++i)
+  //  synth->dssi->LADSPA_Plugin->deactivate(handle[i]);
+  synth->dssi->LADSPA_Plugin->deactivate(handle);
+}
 
-void DssiSynthIF::updateControllers()                        { }
-void DssiSynthIF::writeConfiguration(int /*level*/, Xml& /*xml*/)        { }
-bool DssiSynthIF::readConfiguration(Xml& /*xml*/, bool /*readPreset*/) { return false; }
+//void DssiSynthIF::writeConfiguration(int /*level*/, Xml& /*xml*/)        { }
+//bool DssiSynthIF::readConfiguration(Xml& /*xml*/, bool /*readPreset*/) { return false; }
 
 unsigned long DssiSynthIF::parameters() const                { return synth ? synth->_controlInPorts : 0; }
 unsigned long DssiSynthIF::parametersOut() const             { return synth ? synth->_controlOutPorts : 0; }
diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h
index baa6adbe..99626c92 100644
--- a/muse2/muse/dssihost.h
+++ b/muse2/muse/dssihost.h
@@ -114,7 +114,7 @@ class DssiSynth : public Synth {
 //    VSTi synthesizer instance
 //---------------------------------------------------------
 
-class DssiSynthIF : public SynthIF, public PluginIBase
+class DssiSynthIF : public SynthIF
       {
       DssiSynth* synth;
       LADSPA_Handle handle;
@@ -143,6 +143,8 @@ class DssiSynthIF : public SynthIF, public PluginIBase
       
       virtual ~DssiSynthIF();
 
+      bool init(DssiSynth* s);
+
       virtual DssiSynth* dssiSynth() { return synth; }
       virtual SynthI* dssiSynthI()   { return synti; }
       
@@ -169,7 +171,7 @@ class DssiSynthIF : public SynthIF, public PluginIBase
       virtual int totalOutChannels() const;
       virtual int totalInChannels() const;
       
-      virtual void deactivate3() {}
+      virtual void deactivate3();
       
       virtual const char* getPatchName(int, int, bool);
       virtual void populatePatchPopup(MusEGui::PopupMenu*, int, bool);
@@ -179,11 +181,8 @@ class DssiSynthIF : public SynthIF, public PluginIBase
       virtual float getParameter(unsigned long /*idx*/) const;
       virtual float getParameterOut(unsigned long n) const;
       virtual void setParameter(unsigned long /*idx*/, float /*value*/);
-      
       virtual int getControllerInfo(int, const char**, int*, int*, int*, int*);
       
-      bool init(DssiSynth* s);
-
       #ifdef OSC_SUPPORT
       OscDssiIF& oscIF() { return _oscif; }
       int oscProgram(unsigned long prog, unsigned long bank);
@@ -196,17 +195,13 @@ class DssiSynthIF : public SynthIF, public PluginIBase
       //-------------------------
       // Methods for PluginIBase:
       //-------------------------
-      bool on() const;       
-      void setOn(bool val);   
+      
       unsigned long pluginID();        
       int id();
       QString pluginLabel() const;  
-      QString name() const;
       QString lib() const;            
       QString dirPath() const;
       QString fileName() const;
-      QString titlePrefix() const;
-      MusECore::AudioTrack* track();          
       void enableController(unsigned long i, bool v = true);      
       bool controllerEnabled(unsigned long i) const;          
       void enable2Controller(unsigned long i, bool v = true);      
@@ -214,8 +209,8 @@ class DssiSynthIF : public SynthIF, public PluginIBase
       void enableAllControllers(bool v = true);
       void enable2AllControllers(bool v = true);
       void updateControllers();
-      void writeConfiguration(int level, Xml& xml);
-      bool readConfiguration(Xml& xml, bool readPreset=false);
+      void activate();
+      void deactivate();
 
       unsigned long parameters() const;                            
       unsigned long parametersOut() const;
diff --git a/muse2/muse/globals.cpp b/muse2/muse/globals.cpp
index b61cda6d..831558f4 100644
--- a/muse2/muse/globals.cpp
+++ b/muse2/muse/globals.cpp
@@ -111,6 +111,7 @@ int realTimePriority = 40;  // 80
 int midiRTPrioOverride = -1;
 bool loadPlugins = true;
 bool loadVST = true;
+bool loadNativeVST = true;
 bool loadDSSI = true;
 bool usePythonBridge = false;
 bool useLASH = true;
diff --git a/muse2/muse/globals.h b/muse2/muse/globals.h
index da8221b9..3eb941a7 100644
--- a/muse2/muse/globals.h
+++ b/muse2/muse/globals.h
@@ -81,6 +81,7 @@ extern bool heavyDebugMsg;
 extern bool debugSync;
 extern bool loadPlugins;
 extern bool loadVST;
+extern bool loadNativeVST;
 extern bool loadDSSI;
 extern bool usePythonBridge;
 extern bool useLASH;
diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp
index 1c4db8c7..0d9b74bd 100644
--- a/muse2/muse/helper.cpp
+++ b/muse2/muse/helper.cpp
@@ -50,14 +50,6 @@
 #include <QFileDialog>
 #include <QString>
 
-#ifdef DSSI_SUPPORT
-#include "dssihost.h"
-#endif
-
-#ifdef VST_SUPPORT
-#include "vst.h"
-#endif
-
 using std::set;
 
 namespace MusEGlobal {
diff --git a/muse2/muse/main.cpp b/muse2/muse/main.cpp
index ceb245ba..e233a28e 100644
--- a/muse2/muse/main.cpp
+++ b/muse2/muse/main.cpp
@@ -71,6 +71,7 @@ extern void initMidiController();
 extern void initMetronome();
 extern void initOSC();
 extern void initVST();
+extern void initVST_Native();
 extern void initPlugins();
 extern void initDSSI();
 extern void readConfiguration();
@@ -238,6 +239,9 @@ static void usage(const char* prog, const char* txt)
 #ifdef VST_SUPPORT
       fprintf(stderr, "   -V       Don't load VST plugins\n");
 #endif
+#ifdef VST_NATIVE_SUPPORT
+      fprintf(stderr, "   -N       Don't load Native VST plugins\n");
+#endif
 #ifdef DSSI_SUPPORT
       fprintf(stderr, "   -I       Don't load DSSI plugins\n");
 #endif
@@ -352,6 +356,9 @@ int main(int argc, char* argv[])
 #ifdef VST_SUPPORT
       optstr += QString("V");
 #endif
+#ifdef VST_NATIVE_SUPPORT
+      optstr += QString("N");
+#endif
 #ifdef DSSI_SUPPORT
       optstr += QString("I");
 #endif
@@ -398,6 +405,7 @@ int main(int argc, char* argv[])
                   case 'Y': MusEGlobal::midiRTPrioOverride = atoi(optarg); break;
                   case 'p': MusEGlobal::loadPlugins = false; break;
                   case 'V': MusEGlobal::loadVST = false; break;
+                  case 'N': MusEGlobal::loadNativeVST = false; break;
                   case 'I': MusEGlobal::loadDSSI = false; break;
                   case 'L': MusEGlobal::useLASH = false; break;  
                   case 'y': MusEGlobal::usePythonBridge = true; break;
@@ -650,6 +658,9 @@ int main(int argc, char* argv[])
       if (MusEGlobal::loadVST)
             MusECore::initVST();
 
+      if (MusEGlobal::loadNativeVST)
+            MusECore::initVST_Native();
+
       if(MusEGlobal::loadDSSI)
             MusECore::initDSSI();
       
diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp
index 381e4acc..0f15083b 100644
--- a/muse2/muse/osc.cpp
+++ b/muse2/muse/osc.cpp
@@ -173,12 +173,11 @@ int oscMessageHandler(const char* path, const char* types, lo_arg** argv,
       const char* sub = strstr(p, ba.constData());
       if(sub == NULL) 
         continue;
-      
-      // TODO: Fix this dynamic cast - it may be a slowdown.
-      DssiSynthIF* instance = dynamic_cast<DssiSynthIF*>(synti->sif());
-      if(!instance)
-        break;
-        
+
+      if(!synti->sif() || !synti->synth() || synti->synth()->synthType() != MusECore::Synth::DSSI_SYNTH)
+        continue;
+      DssiSynthIF* instance = static_cast<DssiSynthIF*>(synti->sif());
+
       p = sub + ba.length();
       if (*p != '/' || *(p + 1) == 0)
       {
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index 9dc2005e..0ca7524c 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -1575,6 +1575,7 @@ bool PluginIBase::addScheduledControlEvent(unsigned long i, float val, unsigned
   }
   ControlEvent ce;
   ce.unique = false;
+  ce.fromGui = false;                 
   ce.idx = i;
   ce.value = val;
   // Time-stamp the event. This does a possibly slightly slow call to gettimeofday via timestamp().
@@ -2800,6 +2801,7 @@ int PluginI::oscControl(unsigned long port, float value)
   */
   ControlEvent ce;
   ce.unique = _plugin->_isDssiVst;   // Special for messages from vst gui to host - requires processing every message.
+  ce.fromGui = true;                 // It came form the plugin's own GUI.
   ce.idx = cport;
   ce.value = value;
   // Time-stamp the event. This does a possibly slightly slow call to gettimeofday via timestamp().
diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h
index 25d434ca..822bafbd 100644
--- a/muse2/muse/plugin.h
+++ b/muse2/muse/plugin.h
@@ -274,6 +274,9 @@ class PluginIBase
       virtual void enable2AllControllers(bool v = true) = 0;
       virtual void updateControllers() = 0;
       
+      virtual void activate() = 0;
+      virtual void deactivate() = 0;
+      
       virtual void writeConfiguration(int level, Xml& xml) = 0;
       virtual bool readConfiguration(Xml& xml, bool readPreset=false) = 0;
       
@@ -285,6 +288,7 @@ class PluginIBase
       virtual float paramOut(unsigned long i) const = 0;
       virtual const char* paramName(unsigned long i) = 0;
       virtual const char* paramOutName(unsigned long i) = 0;
+      // FIXME TODO: Either find a way to agnosticize these two ranges, or change them from ladspa ranges to a new MusE range class.
       virtual LADSPA_PortRangeHint range(unsigned long i) = 0;
       virtual LADSPA_PortRangeHint rangeOut(unsigned long i) = 0;
       
diff --git a/muse2/muse/synth.cpp b/muse2/muse/synth.cpp
index 840365ee..92c0a27d 100644
--- a/muse2/muse/synth.cpp
+++ b/muse2/muse/synth.cpp
@@ -61,7 +61,7 @@ namespace MusECore {
 extern void connectNodes(AudioTrack*, AudioTrack*);
 bool SynthI::_isVisible=false;
 
-const char* synthTypes[] = { "METRONOME", "MESS", "DSSI", "VST", "UNKNOWN" };
+const char* synthTypes[] = { "METRONOME", "MESS", "DSSI", "VST", "VST_NATIVE", "UNKNOWN" };
 QString synthType2String(Synth::Type type) { return QString(synthTypes[type]); } 
 
 Synth::Type string2SynthType(const QString& type) 
@@ -74,6 +74,62 @@ Synth::Type string2SynthType(const QString& type)
   return Synth::SYNTH_TYPE_END;
 } 
 
+//--------------------------------
+// Methods for PluginIBase:
+//--------------------------------
+
+bool SynthIF::on() const                                 { return true; }  // Synth is not part of a rack plugin chain. Always on.
+void SynthIF::setOn(bool /*val*/)                        { }
+unsigned long SynthIF::pluginID()                        { return 0; }
+int SynthIF::id()                                        { return MAX_PLUGINS; } // Set for special block reserved for synth. 
+QString SynthIF::pluginLabel() const                     { return QString(); } 
+QString SynthIF::name() const                            { return synti->name(); }
+QString SynthIF::lib() const                             { return QString(); }
+QString SynthIF::dirPath() const                         { return QString(); }
+QString SynthIF::fileName() const                        { return QString(); }
+QString SynthIF::titlePrefix() const                     { return QString(); }
+MusECore::AudioTrack* SynthIF::track()                   { return static_cast < MusECore::AudioTrack* > (synti); }
+void SynthIF::enableController(unsigned long, bool)  { }
+bool SynthIF::controllerEnabled(unsigned long) const   { return true;}
+void SynthIF::enable2Controller(unsigned long, bool) { }
+bool SynthIF::controllerEnabled2(unsigned long) const  { return true; }
+void SynthIF::enableAllControllers(bool)               { }
+void SynthIF::enable2AllControllers(bool)              { }
+void SynthIF::updateControllers()                        { }
+void SynthIF::activate()                                 { }
+void SynthIF::deactivate()                               { }
+void SynthIF::writeConfiguration(int /*level*/, Xml& /*xml*/)        { }
+bool SynthIF::readConfiguration(Xml& /*xml*/, bool /*readPreset*/) { return false; }
+unsigned long SynthIF::parameters() const                { return 0; }
+unsigned long SynthIF::parametersOut() const             { return 0; }
+void SynthIF::setParam(unsigned long, float)       { }
+float SynthIF::param(unsigned long) const              { return 0.0; }
+float SynthIF::paramOut(unsigned long) const           { return 0.0; }
+const char* SynthIF::paramName(unsigned long)          { return NULL; }
+const char* SynthIF::paramOutName(unsigned long)       { return NULL; }
+LADSPA_PortRangeHint SynthIF::range(unsigned long)
+{
+  LADSPA_PortRangeHint h;
+  h.HintDescriptor = 0;
+  h.LowerBound = 0.0;
+  h.UpperBound = 1.0;
+  return h;
+}
+LADSPA_PortRangeHint SynthIF::rangeOut(unsigned long)
+{
+  LADSPA_PortRangeHint h;
+  h.HintDescriptor = 0;
+  h.LowerBound = 0.0;
+  h.UpperBound = 1.0;
+  return h;
+}
+CtrlValueType SynthIF::ctrlValueType(unsigned long) const { return VAL_LINEAR; }
+CtrlList::Mode SynthIF::ctrlMode(unsigned long) const     { return CtrlList::INTERPOLATE; };
+
+//-------------------------------------------------------------------------
+
+
+
 bool MessSynthIF::nativeGuiVisible() const
       {
       return _mess ? _mess->nativeGuiVisible() : false;
diff --git a/muse2/muse/synth.h b/muse2/muse/synth.h
index f5ecc9ab..c41d5535 100644
--- a/muse2/muse/synth.h
+++ b/muse2/muse/synth.h
@@ -34,6 +34,7 @@
 #include "midiport.h"
 #include "track.h"
 #include "stringparam.h"
+#include "plugin.h"
 
 #include <QFileInfo>
 
@@ -67,7 +68,7 @@ class Synth {
       QString _version;
 
    public:
-      enum Type { METRO_SYNTH=0, MESS_SYNTH, DSSI_SYNTH, VST_SYNTH, SYNTH_TYPE_END };
+      enum Type { METRO_SYNTH=0, MESS_SYNTH, DSSI_SYNTH, VST_SYNTH, VST_NATIVE_SYNTH, SYNTH_TYPE_END };
 
       Synth(const QFileInfo& fi, QString label, QString descr, QString maker, QString ver);
       
@@ -119,7 +120,7 @@ class MessSynth : public Synth {
 //      0xNN                           The synth's unique ID byte
 //---------------------------------------------------------
 
-class SynthIF {
+class SynthIF : public PluginIBase {
       
    protected:
       SynthI* synti;
@@ -159,6 +160,47 @@ class SynthIF {
       virtual float getParameter(unsigned long idx) const = 0;        
       virtual void setParameter(unsigned long idx, float value) = 0;  
       virtual int getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval) = 0;
+
+      //-------------------------
+      // Methods for PluginIBase:
+      //-------------------------
+      
+      virtual bool on() const;
+      virtual void setOn(bool val);
+      virtual unsigned long pluginID();
+      virtual int id();
+      virtual QString pluginLabel() const;
+      virtual QString name() const;
+      virtual QString lib() const;
+      virtual QString dirPath() const;
+      virtual QString fileName() const;
+      virtual QString titlePrefix() const;
+      virtual MusECore::AudioTrack* track();
+      virtual void enableController(unsigned long i, bool v = true);
+      virtual bool controllerEnabled(unsigned long i) const;
+      virtual void enable2Controller(unsigned long i, bool v = true);
+      virtual bool controllerEnabled2(unsigned long i) const;
+      virtual void enableAllControllers(bool v = true);
+      virtual void enable2AllControllers(bool v = true);
+      virtual void updateControllers();
+      virtual void activate();
+      virtual void deactivate();
+
+      virtual void writeConfiguration(int level, Xml& xml);
+      virtual bool readConfiguration(Xml& xml, bool readPreset=false);
+
+      virtual unsigned long parameters() const;
+      virtual unsigned long parametersOut() const;
+      virtual void setParam(unsigned long i, float val);
+      virtual float param(unsigned long i) const;
+      virtual float paramOut(unsigned long i) const;
+      virtual const char* paramName(unsigned long i);
+      virtual const char* paramOutName(unsigned long i);
+      // FIXME TODO: Either find a way to agnosticize these two ranges, or change them from ladspa ranges to a new MusE range class.
+      virtual LADSPA_PortRangeHint range(unsigned long i);
+      virtual LADSPA_PortRangeHint rangeOut(unsigned long i);
+      virtual CtrlValueType ctrlValueType(unsigned long i) const;
+      virtual CtrlList::Mode ctrlMode(unsigned long i) const;
       };
 
 //---------------------------------------------------------
@@ -207,6 +249,7 @@ class SynthI : public AudioTrack, public MidiDevice,
       friend class MessSynthIF;
       friend class DssiSynthIF;
       friend class VstSynthIF;
+      friend class VstNativeSynthIF;
       
       SynthI();
       virtual ~SynthI();
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index b18a9410..b17515fe 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -291,7 +291,7 @@ void Track::internal_assign(const Track& t, int flags)
           {
             // Do not call setName here. Audio Input and Output override it and try to set 
             //  Jack ports, which have not been initialized yet here. Must wait until 
-            // .Audio Input and Output copy constructors or assign are called.
+            //  Audio Input and Output copy constructors or assign are called.
             _name = s;
             break;
           }
@@ -389,18 +389,10 @@ void Track::clearRecAutomation(bool clearList)
 
     if(type() == AUDIO_SOFTSYNTH)
     {
-#ifdef DSSI_SUPPORT
-      SynthI* synth = static_cast<SynthI*>(this);
-      if(synth->synth() && synth->synth()->synthType() == Synth::DSSI_SYNTH)
-      {
-        SynthIF* sif = synth->sif();
-        if(sif)
-        {
-          DssiSynthIF* dssi_sif = static_cast<DssiSynthIF*>(sif);
-          dssi_sif->enableAllControllers(true);
-        }
-      }
-#endif
+      const SynthI* synth = static_cast<const SynthI*>(this);
+      SynthIF* sif = synth->sif();
+      if(sif)
+        sif->enableAllControllers(true);
     }
     
     if(clearList)
diff --git a/muse2/muse/vst_native.cpp b/muse2/muse/vst_native.cpp
new file mode 100644
index 00000000..8febe142
--- /dev/null
+++ b/muse2/muse/vst_native.cpp
@@ -0,0 +1,2628 @@
+//===================================================================
+//  MusE
+//  Linux Music Editor
+//
+//  vst_native.cpp
+//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; version 2 of
+//  the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//===================================================================
+
+#include "config.h"
+
+#ifdef VST_NATIVE_SUPPORT
+
+#include <QDir>
+#include <QMenu>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <cmath>
+#include <set>
+#include <jack/jack.h>
+
+#include "globals.h"
+#include "gconfig.h"
+#include "audio.h"
+#include "synth.h"
+#include "jackaudio.h"
+#include "midi.h"
+#include "xml.h"
+#include "plugin.h"
+#include "popupmenu.h"
+
+#include "vst_native.h"
+
+#define OLD_PLUGIN_ENTRY_POINT "main"
+#define NEW_PLUGIN_ENTRY_POINT "VSTPluginMain"
+
+// Enable debugging messages
+//#define VST_NATIVE_DEBUG 
+//#define VST_NATIVE_DEBUG_PROCESS
+
+namespace MusECore {
+
+extern JackAudioDevice* jackAudio;
+
+//-----------------------------------------------------------------------------------------
+//   vstHostCallback
+//   This must be a function, it cannot be a class method so we dispatch to various objects from here.
+//-----------------------------------------------------------------------------------------
+
+VstIntPtr VSTCALLBACK vstNativeHostCallback(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
+{
+      VSTPlugin* plugin;
+      if(effect && effect->user)
+      {
+        plugin = (VSTPlugin*)(effect->user);
+        return ((VstNativeSynthIF*)plugin)->hostCallback(opcode, index, value, ptr, opt);
+      }
+      
+#ifdef VST_NATIVE_DEBUG      
+      fprintf(stderr, "vstNativeHostCallback eff:%p opcode:%ld\n", effect, opcode);
+#endif      
+      
+      switch (opcode) {
+            case audioMasterAutomate:
+                  // index, value, returns 0
+                  return 0;
+
+            case audioMasterVersion:
+                  // vst version, currently 2 (0 for older)
+                  return 2300;
+
+            case audioMasterCurrentId:
+                  // returns the unique id of a plug that's currently
+                  // loading
+                  return 0;
+
+            case audioMasterIdle:
+                  // call application idle routine (this will
+                  // call effEditIdle for all open editors too)
+                  return 0;
+
+            case audioMasterPinConnected:
+                  // inquire if an input or output is beeing connected;
+                  // index enumerates input or output counting from zero:
+                  // value is 0 for input and != 0 otherwise. note: the
+                  // return value is 0 for <true> such that older versions
+                  // will always return true.
+                  return 1;
+
+            case audioMasterWantMidi:
+                  // <value> is a filter which is currently ignored
+                  return 0;
+
+            case audioMasterGetTime:
+                  // returns const VstTimeInfo* (or 0 if not supported)
+                  // <value> should contain a mask indicating which fields are required
+                  // (see valid masks above), as some items may require extensive
+                  // conversions
+                  return 0;
+
+            case audioMasterProcessEvents:
+                  // VstEvents* in <ptr>
+                  return 0;
+
+            case audioMasterSetTime:
+                  // VstTimenfo* in <ptr>, filter in <value>, not supported
+                  return 0;
+
+            case audioMasterTempoAt:
+                  // returns tempo (in bpm * 10000) at sample frame location passed in <value>
+                  return 0;
+
+            case audioMasterGetNumAutomatableParameters:
+                  return 0;
+
+            case audioMasterGetParameterQuantization:
+                     // returns the integer value for +1.0 representation,
+                   // or 1 if full single float precision is maintained
+                     // in automation. parameter index in <value> (-1: all, any)
+                  return 0;
+
+            case audioMasterIOChanged:
+                   // numInputs and/or numOutputs has changed
+                  return 0;
+
+            case audioMasterNeedIdle:
+                   // plug needs idle calls (outside its editor window)
+                  return 0;
+
+            case audioMasterSizeWindow:
+                  // index: width, value: height
+                  return 0;
+
+            case audioMasterGetSampleRate:
+                  return MusEGlobal::sampleRate;
+
+            case audioMasterGetBlockSize:
+                  return MusEGlobal::segmentSize;
+
+            case audioMasterGetInputLatency:
+                  return 0;
+
+            case audioMasterGetOutputLatency:
+                  return 0;
+
+            case audioMasterGetPreviousPlug:
+                   // input pin in <value> (-1: first to come), returns cEffect*
+                  return 0;
+
+            case audioMasterGetNextPlug:
+                   // output pin in <value> (-1: first to come), returns cEffect*
+
+            case audioMasterWillReplaceOrAccumulate:
+                   // returns: 0: not supported, 1: replace, 2: accumulate
+                  return 0;
+
+            case audioMasterGetCurrentProcessLevel:
+                  // returns: 0: not supported,
+                  // 1: currently in user thread (gui)
+                  // 2: currently in audio thread (where process is called)
+                  // 3: currently in 'sequencer' thread (midi, timer etc)
+                  // 4: currently offline processing and thus in user thread
+                  // other: not defined, but probably pre-empting user thread.
+                  return 0;
+
+            case audioMasterGetAutomationState:
+                  // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
+                  // offline
+                  return 0;
+
+            case audioMasterOfflineStart:
+            case audioMasterOfflineRead:
+                   // ptr points to offline structure, see below. return 0: error, 1 ok
+                  return 0;
+
+            case audioMasterOfflineWrite:
+                  // same as read
+                  return 0;
+
+            case audioMasterOfflineGetCurrentPass:
+            case audioMasterOfflineGetCurrentMetaPass:
+                  return 0;
+
+            case audioMasterSetOutputSampleRate:
+                  // for variable i/o, sample rate in <opt>
+                  return 0;
+
+            case audioMasterGetSpeakerArrangement:
+                  // (long)input in <value>, output in <ptr>
+                  return 0;
+
+            case audioMasterGetVendorString:
+                  // fills <ptr> with a string identifying the vendor (max 64 char)
+                  strcpy ((char*) ptr, "MusE");
+                  return 1;
+
+            case audioMasterGetProductString:
+                  // fills <ptr> with a string with product name (max 64 char)
+                  strcpy ((char*) ptr, "NativeVST");
+                  return 1;
+
+            case audioMasterGetVendorVersion:
+                  // returns vendor-specific version
+                  return 2000;
+
+            case audioMasterVendorSpecific:
+                  // no definition, vendor specific handling
+                  return 0;
+
+            case audioMasterSetIcon:
+                  // void* in <ptr>, format not defined yet
+                  return 0;
+
+            case audioMasterCanDo:
+                  // string in ptr, see below
+                  return 0;
+
+            case audioMasterGetLanguage:
+                  // see enum
+                  return kVstLangEnglish;
+
+            case audioMasterOpenWindow:
+                  // returns platform specific ptr
+                  return 0;
+
+            case audioMasterCloseWindow:
+                  // close window, platform specific handle in <ptr>
+                  return 0;
+
+            case audioMasterGetDirectory:
+                  // get plug directory, FSSpec on MAC, else char*
+                  return 0;
+
+            case audioMasterUpdateDisplay:
+                  // something has changed, update 'multi-fx' display
+                  return 0;
+
+            case audioMasterBeginEdit:
+                  // begin of automation session (when mouse down), parameter index in <index>
+                  return 0;
+
+            case audioMasterEndEdit:
+                  // end of automation session (when mouse up),     parameter index in <index>
+                  return 0;
+
+            case audioMasterOpenFileSelector:
+                  // open a fileselector window with VstFileSelect* in <ptr>
+                  return 0;
+
+            case audioMasterCloseFileSelector:
+                  return 0;
+                  
+            default:
+                  break;
+            }
+
+      if(MusEGlobal::debugMsg)
+        fprintf(stderr, "  unknown opcode\n");
+
+      return 0;
+      }
+
+//---------------------------------------------------------
+//   loadPluginLib
+//---------------------------------------------------------
+
+static void scanVstNativeLib(QFileInfo& fi)
+{
+  void* handle = dlopen(fi.filePath().toAscii().constData(), RTLD_NOW);
+  if (handle == NULL)
+  {
+    fprintf(stderr, "scanVstNativeLib: dlopen(%s) failed: %s\n", fi.filePath().toAscii().constData(), dlerror());
+    return;
+  }
+
+  char buffer[128];
+  QString effectName;
+  QString vendorString;
+  QString productString;
+  std::vector<Synth*>::iterator is;
+  int vst_version = 0;
+  VstNativeSynth* new_synth = NULL;
+  
+  AEffect *(*getInstance)(audioMasterCallback);
+  getInstance = (AEffect*(*)(audioMasterCallback))dlsym(handle, NEW_PLUGIN_ENTRY_POINT);
+  if(!getInstance)
+  {
+    if(MusEGlobal::debugMsg)
+    {
+      fprintf(stderr, "VST 2.4 entrypoint \"" NEW_PLUGIN_ENTRY_POINT "\" not found in library %s, looking for \""
+                      OLD_PLUGIN_ENTRY_POINT "\"\n", fi.filePath().toAscii().constData());
+    }
+
+    getInstance = (AEffect*(*)(audioMasterCallback))dlsym(handle, OLD_PLUGIN_ENTRY_POINT);
+    if(!getInstance)
+    {
+      fprintf(stderr, "ERROR: VST entrypoints \"" NEW_PLUGIN_ENTRY_POINT "\" or \""
+                      OLD_PLUGIN_ENTRY_POINT "\" not found in library\n");
+      dlclose(handle);
+      return;
+    }
+    else if(MusEGlobal::debugMsg)
+    {
+      fprintf(stderr, "VST entrypoint \"" OLD_PLUGIN_ENTRY_POINT "\" found\n");
+    }
+  }
+  else if(MusEGlobal::debugMsg)
+  {
+    fprintf(stderr, "VST entrypoint \"" NEW_PLUGIN_ENTRY_POINT "\" found\n");
+  }
+
+  AEffect *plugin = getInstance(vstNativeHostCallback);
+  if(!plugin)
+  {
+    fprintf(stderr, "ERROR: Failed to instantiate plugin in VST library \"%s\"\n", fi.filePath().toAscii().constData());
+    dlclose(handle);
+    return;
+  }
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "plugin instantiated\n");
+
+  if(plugin->magic != kEffectMagic)
+  {
+    fprintf(stderr, "Not a VST plugin in library \"%s\"\n", fi.filePath().toAscii().constData());
+    dlclose(handle);
+    return;
+  }
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "plugin is a VST\n");
+
+  if(!(plugin->flags & effFlagsHasEditor))
+  {
+    if(MusEGlobal::debugMsg)
+      fprintf(stderr, "Plugin has no GUI\n");
+  }
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "Plugin has a GUI\n");
+
+  if(!(plugin->flags & effFlagsCanReplacing))
+    fprintf(stderr, "Plugin does not support processReplacing\n");
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "Plugin supports processReplacing\n");
+
+  plugin->dispatcher(plugin, effOpen, 0, 0, NULL, 0);
+  
+  buffer[0] = 0;
+  plugin->dispatcher(plugin, effGetEffectName, 0, 0, buffer, 0);
+  if(buffer[0])
+    effectName = QString(buffer);
+
+  buffer[0] = 0;
+  plugin->dispatcher(plugin, effGetVendorString, 0, 0, buffer, 0);
+  if (buffer[0])
+    vendorString = QString(buffer);
+
+  buffer[0] = 0;
+  plugin->dispatcher(plugin, effGetProductString, 0, 0, buffer, 0);
+  if (buffer[0])
+    productString = QString(buffer);
+  
+  // Make sure it doesn't already exist.
+  for(is = MusEGlobal::synthis.begin(); is != MusEGlobal::synthis.end(); ++is)
+    if((*is)->name() == effectName && (*is)->baseName() == fi.completeBaseName())
+      goto _ending;
+  
+  // "2 = VST2.x, older versions return 0". Observed 2400 on all the ones tested so far.
+  vst_version = plugin->dispatcher(plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
+  if(vst_version < 2 || !((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher(plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0)))
+  {
+    if(MusEGlobal::debugMsg)
+      fprintf(stderr, "Plugin is not a synth\n");
+    goto _ending;  
+  }
+
+  new_synth = new VstNativeSynth(fi, plugin, effectName, productString, vendorString, QString()); // TODO Version string?
+  
+  if(MusEGlobal::debugMsg)
+    fprintf(stderr, "scanVstNativeLib: adding vst synth plugin:%s name:%s effectName:%s vendorString:%s productString:%s vstver:%d\n",
+            fi.filePath().toLatin1().constData(),
+            fi.completeBaseName().toLatin1().constData(),
+            effectName.toLatin1().constData(),
+            vendorString.toLatin1().constData(),
+            productString.toLatin1().constData(),
+            vst_version
+            );
+
+  MusEGlobal::synthis.push_back(new_synth);
+
+_ending: ;
+  
+  //plugin->dispatcher(plugin, effMainsChanged, 0, 0, NULL, 0);
+  plugin->dispatcher(plugin, effClose, 0, 0, NULL, 0);
+  dlclose(handle);
+}
+
+//---------------------------------------------------------
+//   scanVstDir
+//---------------------------------------------------------
+
+static void scanVstNativeDir(const QString& s)
+{
+      if (MusEGlobal::debugMsg)
+            fprintf(stderr, "scan vst native plugin dir <%s>\n", s.toLatin1().constData());
+      QDir pluginDir(s, QString("*.so"), QDir::Unsorted, QDir::Files);
+      if(!pluginDir.exists())
+        return;
+      QStringList list = pluginDir.entryList();
+      int count = list.count();
+      for(int i = 0; i < count; ++i)
+      {
+        if(MusEGlobal::debugMsg)
+          fprintf(stderr, "scanVstNativeDir: found %s\n", (s + QString("/") + list[i]).toLatin1().constData());
+
+        QFileInfo fi(s + QString("/") + list[i]);
+        scanVstNativeLib(fi);
+      }
+}
+
+//---------------------------------------------------------
+//   initVST_Native
+//---------------------------------------------------------
+
+void initVST_Native()
+      {
+      const char* vstPath = getenv("VST_NATIVE_PATH");  // FIXME TODO: What's the right path and env var?
+      if (vstPath == 0)
+            vstPath = "/usr/lib/vst:/usr/local/lib/vst";
+
+      const char* p = vstPath;
+      while (*p != '\0') {
+            const char* pe = p;
+            while (*pe != ':' && *pe != '\0')
+                  pe++;
+
+            int n = pe - p;
+            if (n) {
+                  char* buffer = new char[n + 1];
+                  strncpy(buffer, p, n);
+                  buffer[n] = '\0';
+                  scanVstNativeDir(QString(buffer));
+                  delete[] buffer;
+                  }
+            p = pe;
+            if (*p == ':')
+                  p++;
+            }
+      }
+
+//---------------------------------------------------------
+//   VstNativeSynth
+//---------------------------------------------------------
+
+VstNativeSynth::VstNativeSynth(const QFileInfo& fi, AEffect* plugin, const QString& label, const QString& desc, const QString& maker, const QString& ver)
+  : Synth(fi, label, desc, maker, ver)
+{
+  _handle = NULL;
+  _hasGui = plugin->flags & effFlagsHasEditor;
+  _inports = plugin->numInputs;
+  _outports = plugin->numOutputs;
+  _controlInPorts = plugin->numParams;
+  _inPlaceCapable = false; //(plugin->flags & effFlagsCanReplacing) && (_inports == _outports) && MusEGlobal::config.vstInPlace;
+#ifdef VST_SDK_SUPPORT
+  _hasChunks = plugin->flags & effFlagsProgramChunks;
+#else
+  _hasChunks = false;
+#endif
+  
+  _flags = 0;
+  _vst_version = 0;
+  _vst_version = plugin->dispatcher(plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
+  // "2 = VST2.x, older versions return 0". Observed 2400 on all the ones tested so far.
+  if(_vst_version >= 2)
+  {
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"receiveVstEvents", 0.0f) > 0)
+      _flags |= canReceiveVstEvents;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"sendVstEvents", 0.0f) > 0)
+      _flags |= canSendVstEvents;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"sendVstMidiEvent", 0.0f) > 0)
+      _flags |= canSendVstMidiEvents;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"sendVstTimeInfo", 0.0f) > 0)
+      _flags |= canSendVstTimeInfo;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"receiveVstMidiEvent", 0.0f) > 0)
+      _flags |= canReceiveVstMidiEvents;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"receiveVstTimeInfo", 0.0f) > 0)
+      _flags |= canReceiveVstTimeInfo;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"offline", 0.0f) > 0)
+      _flags |=canProcessOffline;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"plugAsChannelInsert", 0.0f) > 0)
+      _flags |= canUseAsInsert;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"plugAsSend", 0.0f) > 0)
+      _flags |= canUseAsSend;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"mixDryWet", 0.0f) > 0)
+      _flags |= canMixDryWet;
+    if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"midiProgramNames", 0.0f) > 0)
+      _flags |= canMidiProgramNames;
+  }
+}
+
+//---------------------------------------------------------
+//   incInstances
+//---------------------------------------------------------
+
+void VstNativeSynth::incInstances(int val)
+{
+  _instances += val;
+  if(_instances == 0)
+  {
+    if(_handle)
+    {
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynth::incInstances no more instances, closing library\n");
+      #endif
+
+      dlclose(_handle);
+    }
+    _handle = NULL;
+    iIdx.clear();
+    oIdx.clear();
+    rpIdx.clear();
+    midiCtl2PortMap.clear();
+    port2MidiCtlMap.clear();
+  }
+}
+
+//---------------------------------------------------------
+//   instantiate
+//---------------------------------------------------------
+
+AEffect* VstNativeSynth::instantiate()
+{
+  int inst_num = _instances;
+  inst_num++;
+  QString n;
+  n.setNum(inst_num);
+  QString instanceName = baseName() + "-" + n;
+  QByteArray ba = info.filePath().toLatin1();
+  const char* path = ba.constData();
+  void* hnd = _handle;
+  int vst_version;
+
+  if(hnd == NULL)
+  {
+    hnd = dlopen(path, RTLD_NOW);
+    if(hnd == NULL)
+    {
+      fprintf(stderr, "dlopen(%s) failed: %s\n", path, dlerror());
+      return NULL;
+    }
+  }
+
+  AEffect *(*getInstance)(audioMasterCallback);
+  getInstance = (AEffect*(*)(audioMasterCallback))dlsym(hnd, NEW_PLUGIN_ENTRY_POINT);
+  if(!getInstance)
+  {
+    if(MusEGlobal::debugMsg)
+    {
+      fprintf(stderr, "VST 2.4 entrypoint \"" NEW_PLUGIN_ENTRY_POINT "\" not found in library %s, looking for \""
+                      OLD_PLUGIN_ENTRY_POINT "\"\n", path);
+    }
+
+    getInstance = (AEffect*(*)(audioMasterCallback))dlsym(hnd, OLD_PLUGIN_ENTRY_POINT);
+    if(!getInstance)
+    {
+      fprintf(stderr, "ERROR: VST entrypoints \"" NEW_PLUGIN_ENTRY_POINT "\" or \""
+                      OLD_PLUGIN_ENTRY_POINT "\" not found in library\n");
+      dlclose(hnd);
+      return NULL;
+    }
+    else if(MusEGlobal::debugMsg)
+    {
+      fprintf(stderr, "VST entrypoint \"" OLD_PLUGIN_ENTRY_POINT "\" found\n");
+    }
+  }
+  else if(MusEGlobal::debugMsg)
+  {
+    fprintf(stderr, "VST entrypoint \"" NEW_PLUGIN_ENTRY_POINT "\" found\n");
+  }
+
+  AEffect *plugin = getInstance(vstNativeHostCallback);
+  if(!plugin)
+  {
+    fprintf(stderr, "ERROR: Failed to instantiate plugin in VST library \"%s\"\n", path);
+    dlclose(hnd);
+    return NULL;
+  }
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "plugin instantiated\n");
+
+  if(plugin->magic != kEffectMagic)
+  {
+    fprintf(stderr, "Not a VST plugin in library \"%s\"\n", path);
+    dlclose(hnd);
+    return NULL;
+  }
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "plugin is a VST\n");
+
+  if(!(plugin->flags & effFlagsHasEditor))
+  {
+    if(MusEGlobal::debugMsg)
+      fprintf(stderr, "Plugin has no GUI\n");
+  }
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "Plugin has a GUI\n");
+
+  if(!(plugin->flags & effFlagsCanReplacing))
+    fprintf(stderr, "Plugin does not support processReplacing\n");
+  else if(MusEGlobal::debugMsg)
+    fprintf(stderr, "Plugin supports processReplacing\n");
+
+  plugin->dispatcher(plugin, effOpen, 0, 0, NULL, 0);
+
+  // "2 = VST2.x, older versions return 0". Observed 2400 on all the ones tested so far.
+  vst_version = plugin->dispatcher(plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
+  if(vst_version < 2 || !((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher(plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0)))
+  {
+    if(MusEGlobal::debugMsg)
+      fprintf(stderr, "Plugin is not a synth\n");
+    goto _error;
+  }
+
+  ++_instances;
+  _handle = hnd;
+  
+  plugin->dispatcher(plugin, effOpen, 0, 0, NULL, 0);
+  //plugin->dispatcher(plugin, effSetProgram, 0, 0, NULL, 0.0f); // REMOVE Tim. Or keep?
+  return plugin;
+
+_error:
+  //plugin->dispatcher(plugin, effMainsChanged, 0, 0, NULL, 0);
+  plugin->dispatcher(plugin, effClose, 0, 0, NULL, 0);
+  dlclose(hnd);
+  return NULL;
+}
+
+//---------------------------------------------------------
+//   createSIF
+//---------------------------------------------------------
+
+SynthIF* VstNativeSynth::createSIF(SynthI* s)
+      {
+      VstNativeSynthIF* sif = new VstNativeSynthIF(s);
+      sif->init(this);
+      return sif;
+      }
+  
+//---------------------------------------------------------
+//   VstNativeSynthIF
+//---------------------------------------------------------
+
+VstNativeSynthIF::VstNativeSynthIF(SynthI* s) : SynthIF(s)
+{
+      _guiVisible = false;
+      _synth = NULL;
+      _plugin = NULL;
+      _editor = NULL;
+      _inProcess = false;
+       _controls = NULL;
+//       controlsOut = 0;
+      _audioInBuffers = NULL;
+      _audioInSilenceBuf = NULL;
+      //_audioInSilenceBufs = NULL;
+      _audioOutBuffers = NULL;
+}
+
+VstNativeSynthIF::~VstNativeSynthIF()
+{
+  // Just in case it wasn't removed or deactivate3 wasn't called etc...
+  if(_plugin)
+    fprintf(stderr, "ERROR: ~VstNativeSynthIF: _plugin is not NULL!\n");
+  
+  if(_audioOutBuffers)
+  {
+    unsigned long op = _synth->outPorts();
+    for(unsigned long i = 0; i < op; ++i)
+    {
+      if(_audioOutBuffers[i])
+        free(_audioOutBuffers[i]);
+    }
+    delete[] _audioOutBuffers;
+  }
+
+  if(_audioInBuffers)
+  {
+    unsigned long ip = _synth->inPorts();
+    for(unsigned long i = 0; i < ip; ++i)
+    {
+      if(_audioInBuffers[i])
+        free(_audioInBuffers[i]);
+    }
+    delete[] _audioInBuffers;
+  }
+
+  if(_audioInSilenceBuf)
+    free(_audioInSilenceBuf);
+    
+//   if(_audioInSilenceBufs)
+//   {
+//     for(unsigned long i = 0; i < _synth->inPorts(); ++i)
+//     {
+//       if(_audioInSilenceBufs[i])
+//         free(_audioInSilenceBufs[i]);
+//     }
+//     delete[] _audioInSilenceBufs;
+//   }
+  
+  if(_controls)
+    delete[] _controls;
+}
+
+//---------------------------------------------------------
+//   init
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::init(Synth* s)
+      {
+      _synth = (VstNativeSynth*)s;
+      _plugin = _synth->instantiate();
+      if(!_plugin)
+        return false;
+      _plugin->user = this;
+
+      queryPrograms();
+      
+      unsigned long outports = _synth->outPorts();
+      if(outports != 0)
+      {
+        _audioOutBuffers = new float*[outports];
+        for(unsigned long k = 0; k < outports; ++k)
+        {
+          posix_memalign((void**)&_audioOutBuffers[k], 16, sizeof(float) * MusEGlobal::segmentSize);
+          memset(_audioOutBuffers[k], 0, sizeof(float) * MusEGlobal::segmentSize);
+        }
+      }
+
+      unsigned long inports = _synth->inPorts();
+      if(inports != 0)
+      {
+        _audioInBuffers = new float*[inports];
+        //_audioInSilenceBufs = new float*[inports];
+        for(unsigned long k = 0; k < inports; ++k)
+        {
+          posix_memalign((void**)&_audioInBuffers[k], 16, sizeof(float) * MusEGlobal::segmentSize);
+          memset(_audioInBuffers[k], 0, sizeof(float) * MusEGlobal::segmentSize);
+          //posix_memalign((void**)&_audioInSilenceBufs[k], 16, sizeof(float) * MusEGlobal::segmentSize);
+          //memset(_audioInSilenceBufs[k], 0, sizeof(float) * MusEGlobal::segmentSize);
+          _iUsedIdx.push_back(false); // Start out with all false.
+        }
+        
+        posix_memalign((void**)&_audioInSilenceBuf, 16, sizeof(float) * MusEGlobal::segmentSize);
+        memset(_audioInSilenceBuf, 0, sizeof(float) * MusEGlobal::segmentSize);
+      }
+
+      int controlPorts = _synth->inControls();
+      if(controlPorts != 0)
+        _controls = new Port[controlPorts];
+      else
+        _controls = NULL;
+
+      //_synth->midiCtl2PortMap.clear();
+      //_synth->port2MidiCtlMap.clear();
+
+      for(unsigned long i = 0; i < _synth->inControls(); ++i)
+      {
+        _controls[i].idx = i;
+        //float val;  // TODO
+        //ladspaDefaultValue(ld, k, &val);   // FIXME TODO
+        float val = _plugin->getParameter(_plugin, i);  // TODO
+        _controls[i].val    = val;
+        _controls[i].tmpVal = val;
+        _controls[i].enCtrl  = true;
+        _controls[i].en2Ctrl = true;
+
+        // Support a special block for synth ladspa controllers.
+        // Put the ID at a special block after plugins (far after).
+        int id = genACnum(MAX_PLUGINS, i);
+        const char* param_name = paramName(i);
+
+        // TODO FIXME!
+        ///float min, max;
+        ///ladspaControlRange(ld, k, &min, &max);
+        float min = 0.0, max = 1.0;
+
+        CtrlList* cl;
+        CtrlListList* cll = ((MusECore::AudioTrack*)synti)->controller();
+        iCtrlList icl = cll->find(id);
+        if (icl == cll->end())
+        {
+          cl = new CtrlList(id);
+          cll->add(cl);
+          //cl->setCurVal(controls[cip].val);
+          cl->setCurVal(_plugin->getParameter(_plugin, i));
+        }
+        else
+        {
+          cl = icl->second;
+          ///controls[cip].val = cl->curVal();
+          //setParam(i, cl->curVal());
+          if(dispatch(effCanBeAutomated, i, 0, NULL, 0.0f) == 1)
+            _plugin->setParameter(_plugin, i, cl->curVal());
+#ifdef VST_NATIVE_DEBUG
+          else  
+            fprintf(stderr, "VstNativeSynthIF::init %s parameter:%lu cannot be automated\n", name().toLatin1().constData(), i);
+#endif
+
+        }
+        cl->setRange(min, max);
+        cl->setName(QString(param_name));
+        //cl->setValueType(ladspaCtrlValueType(ld, k));
+        cl->setValueType(ctrlValueType(i));
+        //cl->setMode(ladspaCtrlMode(ld, k));
+        cl->setMode(ctrlMode(i));
+      }
+
+      activate();     
+      doSelectProgram(synti->_curBankH, synti->_curBankL, synti->_curProgram);
+      //doSelectProgram(synti->_curProgram);
+      
+      return true;
+      }
+
+//---------------------------------------------------------
+//   resizeEditor
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::resizeEditor(int w, int h)
+{
+  if(!_editor || w <= 0 || h <= 0)
+    return false;
+  _editor->resize(w, h);
+  return true;
+}
+
+//---------------------------------------------------------
+//   hostCallback
+//---------------------------------------------------------
+
+VstIntPtr VstNativeSynthIF::hostCallback(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
+      {
+      //static VstTimeInfo _timeInfo;
+      //jack_position_t jack_pos;
+      //jack_transport_state_t tstate;
+
+#ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::hostCallback %s opcode:%ld\n", name().toLatin1().constData(), opcode);
+#endif
+
+      switch (opcode) {
+            case audioMasterAutomate:
+                  // index, value, returns 0
+                  ///_plugin->setParameter (_plugin, index, opt);
+                  guiControlChanged(index, opt);
+                  return 0;
+
+            case audioMasterVersion:
+                  // vst version, currently 2 (0 for older)
+                  return 2300;
+
+            case audioMasterCurrentId:
+                  // returns the unique id of a plug that's currently
+                  // loading
+                  return 0;
+
+            case audioMasterIdle:
+                  // call application idle routine (this will
+                  // call effEditIdle for all open editors too)
+                  //_plugin->updateParamValues(false);
+                  //_plugin->dispatcher(_plugin, effEditIdle, 0, 0, NULL, 0.0f);
+                  idleEditor();
+                  return 0;
+
+            case audioMasterGetTime:
+                  // returns const VstTimeInfo* (or 0 if not supported)
+                  // <value> should contain a mask indicating which fields are required
+                  // (see valid masks above), as some items may require extensive
+                  // conversions
+
+// FIXME: TODO: Change this to MusE tempo and sig, and even if Jack is used,
+//               the jackAudio pointer may be 0. Jack may not be running and dummy used instead.
+#if 1
+                  return 0;
+#else
+                  memset(&_timeInfo, 0, sizeof(_timeInfo));
+
+                  if (_plugin) {
+                        tstate = jackAudio->transportQuery(&jack_pos);
+
+                        _timeInfo.samplePos  = jack_pos.frame;
+                        _timeInfo.sampleRate = jack_pos.frame_rate;
+                        _timeInfo.flags = 0;
+
+                        if ((value & (kVstBarsValid|kVstTempoValid)) && (jack_pos.valid & JackPositionBBT)) {
+                              _timeInfo.tempo = jack_pos.beats_per_minute;
+                              _timeInfo.timeSigNumerator = (long) floor (jack_pos.beats_per_bar);
+                              _timeInfo.timeSigDenominator = (long) floor (jack_pos.beat_type);
+                              _timeInfo.flags |= (kVstBarsValid|kVstTempoValid);
+                              }
+                        if (tstate == JackTransportRolling) {
+                              _timeInfo.flags |= kVstTransportPlaying;
+                              }
+                        }
+                  else {
+                        _timeInfo.samplePos  = 0;
+                        _timeInfo.sampleRate = MusEGlobal::sampleRate;
+                        }
+                  return (long)&_timeInfo;
+#endif
+
+            case audioMasterProcessEvents:
+                  // VstEvents* in <ptr>
+                  return 0;  // TODO:
+
+            case audioMasterIOChanged:
+                   // numInputs and/or numOutputs has changed
+                  return 0;
+
+            case audioMasterSizeWindow:
+                  // index: width, value: height
+                  if(resizeEditor(int(index), int(value)))
+                    return 1; // supported.
+                  return 0;
+
+            case audioMasterGetSampleRate:
+                  //return 0;
+                  return MusEGlobal::sampleRate;
+
+            case audioMasterGetBlockSize:
+                  //return 0;
+                  return MusEGlobal::segmentSize;
+
+            case audioMasterGetInputLatency:
+                  return 0;
+
+            case audioMasterGetOutputLatency:
+                  return 0;
+
+            case audioMasterGetCurrentProcessLevel:
+                  // returns: 0: not supported,
+                  // 1: currently in user thread (gui)
+                  // 2: currently in audio thread (where process is called)
+                  // 3: currently in 'sequencer' thread (midi, timer etc)
+                  // 4: currently offline processing and thus in user thread
+                  // other: not defined, but probably pre-empting user thread.
+                  if(_inProcess)
+                    return 2;
+                  else
+                    return 1;
+
+            case audioMasterGetAutomationState:
+                  // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
+                  // offline
+                  return 1;   // TODO:
+
+            case audioMasterOfflineStart:
+            case audioMasterOfflineRead:
+                   // ptr points to offline structure, see below. return 0: error, 1 ok
+                  return 0;
+
+            case audioMasterOfflineWrite:
+                  // same as read
+                  return 0;
+
+            case audioMasterOfflineGetCurrentPass:
+            case audioMasterOfflineGetCurrentMetaPass:
+                  return 0;
+
+            case audioMasterGetVendorString:
+                  // fills <ptr> with a string identifying the vendor (max 64 char)
+                  strcpy ((char*) ptr, "MusE");
+                  return 1;
+
+            case audioMasterGetProductString:
+                  // fills <ptr> with a string with product name (max 64 char)
+                  strcpy ((char*) ptr, "MusE Sequencer");
+                  return 1;
+
+            case audioMasterGetVendorVersion:
+                  // returns vendor-specific version
+                  return 2000;
+
+            case audioMasterVendorSpecific:
+                  // no definition, vendor specific handling
+                  return 0;
+
+            case audioMasterCanDo:
+                  // string in ptr, see below
+                  if(!strcmp((char*)ptr, "sendVstEvents") ||          
+                     !strcmp((char*)ptr, "receiveVstMidiEvent") ||    
+                     !strcmp((char*)ptr, "sendVstMidiEvent") ||
+                     !strcmp((char*)ptr, "sendVstTimeInfo") ||
+                     !strcmp((char*)ptr, "sizeWindow") ||
+                     !strcmp((char*)ptr, "supplyIdle"))               
+                    return 1;
+
+#if 0 //ifdef VST_SDK_SUPPORT
+                  else
+                  if(!strcmp((char*)ptr, "openFileSelector") ||       
+                     !strcmp((char*)ptr, "closeFileSelector"))        
+                    return 1;
+#endif
+                  return 0;
+
+            case audioMasterGetLanguage:
+                  // see enum
+                  //return 0;
+                  return kVstLangEnglish;
+
+            case audioMasterGetDirectory:
+                  // get plug directory, FSSpec on MAC, else char*
+                  return 0;
+
+            case audioMasterUpdateDisplay:
+                  // something has changed, update 'multi-fx' display
+
+                  //_plugin->updateParamValues(false);   
+                  //QApplication::processEvents();     // REMOVE Tim. Or keep. Commented in QTractor.
+
+                  _plugin->dispatcher(_plugin, effEditIdle, 0, 0, NULL, 0.0f);  // ?
+                  
+                  return 0;
+
+            case audioMasterBeginEdit:
+                  // begin of automation session (when mouse down), parameter index in <index>
+                  guiAutomationBegin(index);
+                  return 1;  
+
+            case audioMasterEndEdit:
+                  // end of automation session (when mouse up),     parameter index in <index>
+                  guiAutomationEnd(index);
+                  return 1;  
+
+#if 0 //ifdef VST_SDK_SUPPORT
+            case audioMasterOpenFileSelector:
+                  // open a fileselector window with VstFileSelect* in <ptr>
+                  return 0;
+                  
+            case audioMasterCloseFileSelector:
+                  return 0;
+#endif
+
+#ifdef VST_NATIVE_FORCE_DEPRECATED
+                  
+            case audioMasterGetSpeakerArrangement:
+                  // (long)input in <value>, output in <ptr>
+                  return 0;
+
+            case audioMasterPinConnected:
+                  // inquire if an input or output is beeing connected;
+                  // index enumerates input or output counting from zero:
+                  // value is 0 for input and != 0 otherwise. note: the
+                  // return value is 0 for <true> such that older versions
+                  // will always return true.
+                  //return 1;
+                  return 0;
+
+            // VST 2.0 opcodes...
+            case audioMasterWantMidi:
+                  // <value> is a filter which is currently ignored
+                  return 0;
+
+            case audioMasterSetTime:
+                  // VstTimenfo* in <ptr>, filter in <value>, not supported
+                  return 0;
+
+            case audioMasterTempoAt:
+                  // returns tempo (in bpm * 10000) at sample frame location passed in <value>
+                  return 0;  // TODO:
+
+            case audioMasterGetNumAutomatableParameters:
+                  return 0;
+
+            case audioMasterGetParameterQuantization:
+                     // returns the integer value for +1.0 representation,
+                   // or 1 if full single float precision is maintained
+                     // in automation. parameter index in <value> (-1: all, any)
+                  //return 0;
+                  return 1;
+
+            case audioMasterNeedIdle:
+                   // plug needs idle calls (outside its editor window)
+                  return 0;
+
+            case audioMasterGetPreviousPlug:
+                   // input pin in <value> (-1: first to come), returns cEffect*
+                  return 0;
+
+            case audioMasterGetNextPlug:
+                   // output pin in <value> (-1: first to come), returns cEffect*
+                  return 0;
+
+            case audioMasterWillReplaceOrAccumulate:
+                   // returns: 0: not supported, 1: replace, 2: accumulate
+                  //return 0;
+                  return 1;
+
+            case audioMasterSetOutputSampleRate:
+                  // for variable i/o, sample rate in <opt>
+                  return 0;
+
+            case audioMasterSetIcon:
+                  // void* in <ptr>, format not defined yet
+                  return 0;
+
+            case audioMasterOpenWindow:
+                  // returns platform specific ptr
+                  return 0;
+
+            case audioMasterCloseWindow:
+                  // close window, platform specific handle in <ptr>
+                  return 0;
+#endif
+
+                  
+            default:
+                  break;
+            }
+      return 0;
+      }
+      
+//---------------------------------------------------------
+//   idleEditor
+//---------------------------------------------------------
+
+void VstNativeSynthIF::idleEditor()
+{
+#ifdef VST_NATIVE_DEBUG
+  fprintf(stderr, "VstNativeSynthIF::idleEditor %p\n", this);
+#endif
+
+  _plugin->dispatcher(_plugin, effEditIdle, 0, 0, NULL, 0.0f);
+  if(_editor)
+    _editor->update();
+}
+
+//---------------------------------------------------------
+//   nativeGuiVisible
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::nativeGuiVisible() const
+      {
+      return _guiVisible;
+      }
+
+//---------------------------------------------------------
+//   guiVisible
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::guiVisible() const
+      {
+      return _gui && _gui->isVisible();
+      }
+
+//---------------------------------------------------------
+//   showGui
+//---------------------------------------------------------
+
+void VstNativeSynthIF::showGui(bool v)
+{
+    if (v) {
+            if (_gui == 0)
+                makeGui();
+            _gui->show();
+            }
+    else {
+            if (_gui)
+                _gui->hide();
+            }
+}
+
+//---------------------------------------------------------
+//   showGui
+//---------------------------------------------------------
+
+void VstNativeSynthIF::showNativeGui(bool v)
+      {
+      if(!(_plugin->flags & effFlagsHasEditor)) // || v == nativeGuiVisible())
+            return;
+      if(v)
+      {
+        if(_editor)
+        {
+          if(!_editor->isVisible())
+            _editor->show();
+          _editor->raise();
+          _editor->activateWindow();
+        }
+        else
+        {
+          Qt::WindowFlags wflags = Qt::Window
+                  | Qt::CustomizeWindowHint
+                  | Qt::WindowTitleHint
+                  | Qt::WindowSystemMenuHint
+                  | Qt::WindowMinMaxButtonsHint
+                  | Qt::WindowCloseButtonHint;
+          _editor = new MusEGui::VstNativeEditor(NULL, wflags);
+          _editor->open(this);
+
+          // TODO TEST Test if these might be helpful, especially opaque event.
+          //         _editor->setBackgroundRole(QPalette::NoRole);
+          //         _editor->setAttribute(Qt::WA_NoSystemBackground);
+          //         _editor->setAttribute(Qt::WA_StaticContents);
+          //         // This is absolutely required for speed! Otherwise painfully slow because of full background
+          //         //  filling, even when requesting small udpdates! Background is drawn by us.
+          //         _editor->setAttribute(Qt::WA_OpaquePaintEvent);
+          //         //_editor->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+        }
+      }
+      else
+      {
+        if(_editor)
+        {
+          delete _editor;
+          //_editor = NULL;  // No - done in editorDeleted.
+        }
+      }
+      _guiVisible = v;
+}
+
+//---------------------------------------------------------
+//   editorOpened
+//---------------------------------------------------------
+
+void VstNativeSynthIF::editorOpened()
+{
+  _guiVisible = true;
+}
+
+//---------------------------------------------------------
+//   editorClosed
+//---------------------------------------------------------
+
+void VstNativeSynthIF::editorClosed()
+{
+  _guiVisible = false;
+}
+
+//---------------------------------------------------------
+//   editorDeleted
+//---------------------------------------------------------
+
+void VstNativeSynthIF::editorDeleted()
+{
+  _editor = NULL;
+}
+
+//---------------------------------------------------------
+//   receiveEvent
+//---------------------------------------------------------
+
+MidiPlayEvent VstNativeSynthIF::receiveEvent()
+      {
+      return MidiPlayEvent();
+      }
+
+//---------------------------------------------------------
+//   hasGui
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::hasNativeGui() const
+      {
+      return _plugin->flags & effFlagsHasEditor;
+      }
+
+//---------------------------------------------------------
+//   channels
+//---------------------------------------------------------
+
+int VstNativeSynthIF::channels() const
+      {
+      //return _plugin->numOutputs;
+      return _plugin->numOutputs > MAX_CHANNELS ? MAX_CHANNELS : _plugin->numOutputs ;
+      }
+
+int VstNativeSynthIF::totalOutChannels() const
+      {
+      return _plugin->numOutputs;
+      }
+
+int VstNativeSynthIF::totalInChannels() const
+      {
+      return _plugin->numInputs;
+      }
+
+//---------------------------------------------------------
+//   deactivate3
+//---------------------------------------------------------
+
+void VstNativeSynthIF::deactivate3()
+      {
+      if(_editor)
+      {
+        delete _editor;
+        _editor = NULL;
+        _guiVisible = false;
+      }
+
+      deactivate();
+      if (_plugin) {
+            _plugin->dispatcher (_plugin, effClose, 0, 0, NULL, 0);
+            _plugin = NULL;
+            }
+      }
+
+//---------------------------------------------------------
+//   queryPrograms
+//---------------------------------------------------------
+
+void VstNativeSynthIF::queryPrograms()
+{
+      char buf[256];
+      programs.clear();
+      int num_progs = _plugin->numPrograms;
+      int iOldIndex = dispatch(effGetProgram, 0, 0, NULL, 0.0f);
+      bool need_restore = false;
+      for(int prog = 0; prog < num_progs; ++prog)
+      {
+        buf[0] = 0;
+
+//#ifdef VST_SDK_SUPPORT
+        // value = category. -1 = regular linear.
+        if(dispatch(effGetProgramNameIndexed, prog, -1, buf, 0.0f) == 0)  
+        {
+//#endif
+          dispatch(effSetProgram, 0, prog, NULL, 0.0f);
+          dispatch(effGetProgramName, 0, 0, buf, 0.0f);
+          need_restore = true;
+//#ifdef VST_SDK_SUPPORT
+        }
+//#endif
+
+        VST_Program p;
+        p.name    = QString(buf);
+        //p.program = prog & 0x7f;
+        //p.bank    = prog << 7;
+        p.program = prog;
+        programs.push_back(p);
+      }
+
+      // Restore current program.
+      if(need_restore) // && num_progs > 0)
+      { 
+        dispatch(effSetProgram, 0, iOldIndex, NULL, 0.0f);
+        fprintf(stderr, "FIXME: VstNativeSynthIF::queryPrograms(): effGetProgramNameIndexed returned 0. Used ugly effSetProgram/effGetProgramName instead\n");
+      }
+}
+
+//---------------------------------------------------------
+//   doSelectProgram
+//---------------------------------------------------------
+
+void VstNativeSynthIF::doSelectProgram(int bankH, int bankL, int prog)
+{
+  if(!_plugin)
+    return;
+
+#ifdef VST_NATIVE_DEBUG
+  fprintf(stderr, "VstNativeSynthIF::doSelectProgram bankH:%d bankL:%d prog:%d\n", bankH, bankL, prog);
+#endif
+
+  if(bankH == 0xff)
+    bankH = 0;
+  if(bankL == 0xff)
+    bankL = 0;
+  if(prog == 0xff)
+    prog = 0;
+  
+  int p = (bankH << 14) + (bankL << 7) + prog;
+
+  if(p >= _plugin->numPrograms)
+  {
+    fprintf(stderr, "VstNativeSynthIF::doSelectProgram program:%d out of range\n", p);
+    return;
+  }
+  
+  //for (unsigned short i = 0; i < instances(); ++i)
+  //{
+    // "host calls this before a new program (effSetProgram) is loaded"
+    //if(dispatch(effBeginSetProgram, 0, 0, NULL, 0.0f) == 1)  // TESTED: Usually it did not acknowledge. So IGNORE it.
+    dispatch(effBeginSetProgram, 0, 0, NULL, 0.0f);
+    //{
+      dispatch(effSetProgram, 0, p, NULL, 0.0f);
+      //dispatch(effSetProgram, 0, prog, NULL, 0.0f);
+      // "host calls this after the new program (effSetProgram) has been loaded"
+      dispatch(effEndSetProgram, 0, 0, NULL, 0.0f);
+    //}
+    //else
+    //  fprintf(stderr, "VstNativeSynthIF::doSelectProgram bankH:%d bankL:%d prog:%d Effect did not acknowledge effBeginSetProgram\n", bankH, bankL, prog);
+  //}
+    
+  // TODO: Is this true of VSTs? See the similar section in dssihost.cpp  // REMOVE Tim.
+  //   "A plugin is permitted to re-write the values of its input control ports when select_program is called.
+  //    The host should re-read the input control port values and update its own records appropriately.
+  //    (This is the only circumstance in which a DSSI plugin is allowed to modify its own input ports.)"   From dssi.h
+  // Need to update the automation value, otherwise it overwrites later with the last automation value.
+  if(id() != -1)
+  {
+    for(unsigned long k = 0; k < _synth->inControls(); ++k)
+    {
+      // We're in the audio thread context: no need to send a message, just modify directly.
+      synti->setPluginCtrlVal(genACnum(id(), k), _plugin->getParameter(_plugin, k));
+    }
+  }
+
+//   // Reset parameters default value...   // TODO ? 
+//   AEffect *pVstEffect = vst_effect(0);
+//   if (pVstEffect) {
+//           const qtractorPlugin::Params& params = qtractorPlugin::params();
+//           qtractorPlugin::Params::ConstIterator param = params.constBegin();
+//           for ( ; param != params.constEnd(); ++param) {
+//                   qtractorPluginParam *pParam = param.value();
+//                   float *pfValue = pParam->subject()->data();
+//                   *pfValue = pVstEffect->getParameter(pVstEffect, pParam->index());
+//                   pParam->setDefaultValue(*pfValue);
+//           }
+//   }
+  
+}
+
+//---------------------------------------------------------
+//   getPatchName
+//---------------------------------------------------------
+
+const char* VstNativeSynthIF::getPatchName(int /*chan*/, int prog, bool /*drum*/)
+{
+  unsigned long  program = prog & 0x7f;
+  unsigned long  lbank   = (prog >> 8) & 0xff;
+  unsigned long  hbank   = (prog >> 16) & 0xff;
+
+  if (lbank == 0xff)
+        lbank = 0;
+  if (hbank == 0xff)
+        hbank = 0;
+  prog = (hbank << 14) + (lbank << 7) + program;
+
+  if(prog < _plugin->numPrograms)
+  {
+    for(std::vector<VST_Program>::const_iterator i = programs.begin(); i != programs.end(); ++i)
+    {
+      if(i->program == program)
+        return i->name.toLatin1().constData();
+    }
+  }
+  return "?";
+}
+
+//---------------------------------------------------------
+//   populatePatchPopup
+//---------------------------------------------------------
+
+void VstNativeSynthIF::populatePatchPopup(MusEGui::PopupMenu* menu, int /*chan*/, bool /*drum*/)
+{
+  // The plugin can change the programs, patches etc.
+  // So make sure we're up to date by calling queryPrograms.
+  queryPrograms();
+  
+  menu->clear();
+
+  for (std::vector<VST_Program>::const_iterator i = programs.begin(); i != programs.end(); ++i)
+       {
+        //int bank = i->bank;
+        int prog = i->program;
+        //int id   = (bank << 7) + prog;
+
+        QAction *act = menu->addAction(i->name);
+        //act->setData(id);
+        act->setData(prog);
+        }
+
+}
+
+//---------------------------------------------------------
+//   getParameter
+//---------------------------------------------------------
+
+float VstNativeSynthIF::getParameter(unsigned long idx) const
+      {
+      if(idx >= _synth->inControls())
+      {
+        fprintf(stderr, "VstNativeSynthIF::getParameter param number %lu out of range of ports:%lu\n", idx, _synth->inControls());
+        return 0.0;
+      }
+
+      return _plugin->getParameter(_plugin, idx);
+      }
+
+//---------------------------------------------------------
+//   setParameter
+//---------------------------------------------------------
+
+void VstNativeSynthIF::setParameter(unsigned long idx, float value)
+      {
+      //_plugin->setParameter(_plugin, idx, value);
+      addScheduledControlEvent(idx, value, MusEGlobal::audio->curFrame());
+      }
+
+//---------------------------------------------------------
+//   guiAutomationBegin
+//---------------------------------------------------------
+
+void VstNativeSynthIF::guiAutomationBegin(unsigned long param_idx)
+{
+  AutomationType at = AUTO_OFF;
+  MusECore::AudioTrack* t = track();
+  if(t)
+    at = t->automationType();
+
+  // FIXME TODO: This stuff should probably be sent as control FIFO events.
+  //             And probably not safe - accessing from gui and audio threads...
+    
+  if (at == AUTO_READ || at == AUTO_TOUCH || at == AUTO_WRITE)
+    enableController(param_idx, false);
+
+  int plug_id = id();
+
+  if(plug_id == -1)
+    return;
+
+  plug_id = MusECore::genACnum(plug_id, param_idx);
+
+  //if(params[param].type == GuiParam::GUI_SLIDER)
+  //{
+    //double val = ((Slider*)params[param].actuator)->value();
+    float val = param(param_idx);
+    // FIXME TODO:
+    //if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint))
+    //      val = pow(10.0, val/20.0);
+    //else if (LADSPA_IS_HINT_INTEGER(params[param].hint))
+    //      val = rint(val);
+    //plugin->setParam(param, val);
+    //((DoubleLabel*)params[param].label)->setValue(val);
+
+    if(t)
+    {
+      t->setPluginCtrlVal(plug_id, val);
+      t->startAutoRecord(plug_id, val);
+    }
+  //}
+//   else if(params[param].type == GuiParam::GUI_SWITCH)
+//   {
+//     float val = (float)((CheckBox*)params[param].actuator)->isChecked();
+//     plugin->setParam(param, val);
+// 
+//     if(t)
+//     {
+//       t->setPluginCtrlVal(plug_id, val);
+//       t->startAutoRecord(plug_id, val);
+//     }
+//   }
+}
+
+//---------------------------------------------------------
+//   guiAutomationEnd
+//---------------------------------------------------------
+
+void VstNativeSynthIF::guiAutomationEnd(unsigned long param_idx)
+{
+  AutomationType at = AUTO_OFF;
+  MusECore::AudioTrack* t = track();
+  if(t)
+    at = t->automationType();
+
+  // FIXME TODO: This stuff should probably be sent as control FIFO events.
+  //             And probably not safe - accessing from gui and audio threads...
+    
+  // Special for switch - don't enable controller until transport stopped.
+  if ((at == AUTO_OFF) ||
+      (at == AUTO_READ) ||
+      (at == AUTO_TOUCH)) // && (params[param].type != GuiParam::GUI_SWITCH ||  // FIXME TODO
+                         //   !MusEGlobal::audio->isPlaying()) ) )
+    enableController(param_idx, true);
+
+  int plug_id = id();
+  if(!t || plug_id == -1)
+    return;
+  plug_id = MusECore::genACnum(plug_id, param_idx);
+
+  //if(params[param].type == GuiParam::GUI_SLIDER)
+  //{
+    //double val = ((Slider*)params[param].actuator)->value();
+    float val = param(param_idx);
+    // FIXME TODO:
+    //if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint))
+    //      val = pow(10.0, val/20.0);
+    //else if (LADSPA_IS_HINT_INTEGER(params[param].hint))
+    //      val = rint(val);
+    t->stopAutoRecord(plug_id, val);
+  //}
+}
+      
+//---------------------------------------------------------
+//   guiControlEventHandler
+//---------------------------------------------------------
+
+int VstNativeSynthIF::guiControlChanged(unsigned long param_idx, float value)
+{
+  #ifdef VST_NATIVE_DEBUG
+  fprintf(stderr, "VstNativeSynthIF::guiControlChanged received oscControl port:%lu val:%f\n", port, value);
+  #endif
+
+  if(param_idx >= _synth->inControls())
+  {
+    fprintf(stderr, "VstNativeSynthIF::guiControlChanged: port number:%lu is out of range of index list size:%lu\n", param_idx, _synth->inControls());
+    return 0;
+  }
+
+  ControlEvent ce;
+  ce.unique = false; // Not used for native vst.     
+  ce.fromGui = true; // It came form the plugin's own GUI.
+  ce.idx = param_idx;
+  ce.value = value;
+  // don't use timestamp(), because it's circular, which is making it impossible to deal
+  // with 'modulo' events which slip in 'under the wire' before processing the ring buffers.
+  ce.frame = MusEGlobal::audio->curFrame();
+
+  if(_controlFifo.put(ce))
+  {
+    fprintf(stderr, "VstNativeSynthIF::guiControlChanged: fifo overflow: in control number:%lu\n", param_idx);
+  }
+
+  // FIXME TODO: This stuff should probably be sent as control FIFO events.
+  //             And probably not safe - accessing from gui and audio threads...
+  
+  // Record automation:
+  // Take care of this immediately rather than in the fifo processing.
+  if(id() != -1)
+  {
+    unsigned long pid = genACnum(id(), param_idx);
+    AutomationType at = synti->automationType();
+
+    if ((at == AUTO_WRITE) ||
+        (at == AUTO_TOUCH && MusEGlobal::audio->isPlaying()))
+      enableController(param_idx, false);
+
+    synti->recordAutomation(pid, value);
+  }
+
+  return 0;
+}
+
+//---------------------------------------------------------
+//   write
+//---------------------------------------------------------
+
+void VstNativeSynthIF::write(int level, Xml& xml) const
+{
+#ifdef VST_SDK_SUPPORT
+  if(_synth->hasChunks())
+  {
+    //---------------------------------------------
+    // dump current state of synth
+    //---------------------------------------------
+    fprintf(stderr, "%s: commencing chunk data dump, plugin api version=%d\n", name().toLatin1().constData(), _synth->vstVersion());
+    unsigned long len = 0;
+    void* p = 0;
+    len = dispatch(effGetChunk, 0, 0, &p, 0.0); // index 0: is bank 1: is program
+    if (len)
+    {
+      xml.tag(level++, "midistate version=\"%d\"", SYNTH_MIDI_STATE_SAVE_VERSION);
+      xml.nput(level++, "<event type=\"%d\"", Sysex);
+      // 10 = 2 bytes header + "VSTSAVE" + 1 byte flags (compression etc)
+      xml.nput(" datalen=\"%d\">\n", len+10);
+      xml.nput(level, "");
+      xml.nput("%02x %02x ", (char)MUSE_SYNTH_SYSEX_MFG_ID, (char)VST_NATIVE_SYNTH_UNIQUE_ID); // Wrap in a proper header
+      xml.nput("56 53 54 53 41 56 45 "); // embed a save marker "string 'VSTSAVE'
+      xml.nput("%02x ", (char)0); // No flags yet, only uncompressed supported for now. TODO
+      for (unsigned long int i = 0; i < len; ++i)
+      {
+        if (i && (((i+10) % 16) == 0))
+        {
+          xml.nput("\n");
+          xml.nput(level, "");
+        }
+        xml.nput("%02x ", ((char*)(p))[i] & 0xff);
+      }
+      xml.nput("\n");
+      xml.tag(level--, "/event");
+      xml.etag(level--, "midistate");
+    }
+  }
+#else
+  fprintf(stderr, "support for vst chunks not compiled in!\n");
+#endif
+
+  //---------------------------------------------
+  // dump current state of synth
+  //---------------------------------------------
+
+  int params = _plugin->numParams;
+  for (int i = 0; i < params; ++i)
+  {
+    float f = _plugin->getParameter(_plugin, i);
+    xml.floatTag(level, "param", f);
+  }
+}
+
+//---------------------------------------------------------
+//   getData
+//---------------------------------------------------------
+
+void VstNativeSynthIF::setVstEvent(VstMidiEvent* event, int a, int b, int c, int d)
+{
+  event->type         = kVstMidiType;
+  event->byteSize     = 24;
+  event->deltaFrames  = 0;
+  event->flags        = 0;
+  event->detune       = 0;
+  event->noteLength   = 0;
+  event->noteOffset   = 0;
+  event->reserved1    = 0;
+  event->reserved2    = 0;
+  event->noteOffVelocity = 0;
+  event->midiData[0]  = a;
+  event->midiData[1]  = b;
+  event->midiData[2]  = c;
+  event->midiData[3]  = d;
+}
+
+//---------------------------------------------------------
+//   getData
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::processEvent(const MusECore::MidiPlayEvent& e, VstMidiEvent* event)
+{
+  int type = e.type();
+  int chn = e.channel();
+  int a   = e.dataA();
+  int b   = e.dataB();
+
+  int len = e.len();
+  char ca[len + 2];
+
+  ca[0] = 0xF0;
+  memcpy(ca + 1, (const char*)e.data(), len);
+  ca[len + 1] = 0xF7;
+
+  len += 2;
+
+  #ifdef VST_NATIVE_DEBUG
+  fprintf(stderr, "VstNativeSynthIF::processEvent midi event type:%d chn:%d a:%d b:%d\n", type, chn, a, b);
+  #endif
+
+  switch(type)
+  {
+    case MusECore::ME_NOTEON:
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_NOTEON\n");
+      #endif
+      setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
+    break;
+    case MusECore::ME_NOTEOFF:
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_NOTEOFF\n");
+      #endif
+      setVstEvent(event, (type | chn) & 0xff, a & 0x7f, 0);
+    break;
+    case MusECore::ME_PROGRAM:
+    {
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_PROGRAM\n");
+      #endif
+
+      int bankH = (a >> 16) & 0xff;
+      int bankL = (a >> 8) & 0xff;
+      int prog = a & 0xff;
+      synti->_curBankH = bankH;
+      synti->_curBankL = bankL;
+      synti->_curProgram = prog;
+      doSelectProgram(bankH, bankL, prog);
+      return false;  // Event pointer not filled. Return false.
+    }
+    break;
+    case MusECore::ME_CONTROLLER:
+    {
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_CONTROLLER\n");
+      #endif
+
+      if((a == 0) || (a == 32))
+        return false;
+
+      if(a == MusECore::CTRL_PROGRAM)
+      {
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_PROGRAM\n");
+        #endif
+
+        int bankH = (b >> 16) & 0xff;
+        int bankL = (b >> 8) & 0xff;
+        int prog = b & 0xff;
+
+        synti->_curBankH = bankH;
+        synti->_curBankL = bankL;
+        synti->_curProgram = prog;
+        doSelectProgram(bankH, bankL, prog);
+        return false; // Event pointer not filled. Return false.
+      }
+
+      if(a == MusECore::CTRL_PITCH)
+      {
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_PITCH\n");
+        #endif
+        int v = b + 8192;
+        setVstEvent(event, (type | chn) & 0xff, v & 0x7f, (v >> 7) & 0x7f);
+        return true;
+      }
+
+      if(a == MusECore::CTRL_AFTERTOUCH)
+      {
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_AFTERTOUCH\n");
+        #endif
+        setVstEvent(event, (type | chn) & 0xff, b & 0x7f);
+        return true;
+      }
+
+      if((a | 0xff)  == MusECore::CTRL_POLYAFTER)
+      {
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_POLYAFTER\n");
+        #endif
+        setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
+        return true;
+      }
+
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is:%d\n", a);
+      #endif
+      
+      // Regular controller. Pass it on.
+      setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
+      
+      return true; 
+
+// REMOVE Tim. Or keep. TODO For native vsts? Or not...
+//      
+//       const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin;
+// 
+//       MusECore::ciMidiCtl2LadspaPort ip = synth->midiCtl2PortMap.find(a);
+//       // Is it just a regular midi controller, not mapped to a LADSPA port (either by the plugin or by us)?
+//       // NOTE: There's no way to tell which of these controllers is supported by the plugin.
+//       // For example sustain footpedal or pitch bend may be supported, but not mapped to any LADSPA port.
+//       if(ip == synth->midiCtl2PortMap.end())
+//       {
+//         int ctlnum = a;
+//         if(MusECore::midiControllerType(a) != MusECore::MidiController::Controller7)
+//           return false;   // Event pointer not filled. Return false.
+//         else
+//         {
+//                 #ifdef VST_NATIVE_DEBUG
+//                 fprintf(stderr, "VstNativeSynthIF::processEvent non-ladspa midi event is Controller7. Current dataA:%d\n", a);
+//                 #endif
+//                 a &= 0x7f;
+//                 ctlnum = DSSI_CC_NUMBER(ctlnum);
+//         }
+// 
+//         // Fill the event.
+//         #ifdef VST_NATIVE_DEBUG
+//        fprintf(stderr, "VstNativeSynthIF::processEvent non-ladspa filling midi event chn:%d dataA:%d dataB:%d\n", chn, a, b);
+//         #endif
+//         snd_seq_ev_clear(event);
+//         event->queue = SND_SEQ_QUEUE_DIRECT;
+//         snd_seq_ev_set_controller(event, chn, a, b);
+//         return true;
+//       }
+// 
+//       unsigned long k = ip->second;
+//       unsigned long i = controls[k].idx;
+//       int ctlnum = DSSI_NONE;
+//       if(dssi->get_midi_controller_for_port)
+//         ctlnum = dssi->get_midi_controller_for_port(handle, i);
+// 
+//       // No midi controller for the ladspa port? Send to ladspa control.
+//       if(ctlnum == DSSI_NONE)
+//       {
+//         // Sanity check.
+//         if(k > synth->_controlInPorts)
+//           return false;
+// 
+//         // Simple but flawed solution: Start them at 0x60000 + 0x2000 = 0x62000. Max NRPN number is 0x3fff.
+//         ctlnum = k + (MusECore::CTRL_NRPN14_OFFSET + 0x2000);
+//       }
+//       else
+//       {
+//         #ifdef VST_NATIVE_DEBUG
+//         fprintf(stderr, "VstNativeSynthIF::processEvent plugin requests DSSI-style ctlnum:%x(h) %d(d) be mapped to control port:%lu...\n", ctlnum, ctlnum, i);
+//         #endif
+// 
+//         int c = ctlnum;
+//         // Can be both CC and NRPN! Prefer CC over NRPN.
+//         if(DSSI_IS_CC(ctlnum))
+//         {
+//           ctlnum = DSSI_CC_NUMBER(c);
+// 
+//           #ifdef VST_NATIVE_DEBUG
+//           fprintf(stderr, "VstNativeSynthIF::processEvent is CC ctlnum:%d\n", ctlnum);
+//           #endif
+// 
+//           #ifdef VST_NATIVE_DEBUG
+//           if(DSSI_IS_NRPN(ctlnum))
+//             fprintf(stderr, "VstNativeSynthIF::processEvent is also NRPN control. Using CC.\n");
+//           #endif
+//         }
+//         else
+//         if(DSSI_IS_NRPN(ctlnum))
+//         {
+//           ctlnum = DSSI_NRPN_NUMBER(c) + MusECore::CTRL_NRPN14_OFFSET;
+// 
+//           #ifdef VST_NATIVE_DEBUG
+//           fprintf(stderr, "VstNativeSynthIF::processEvent is NRPN ctlnum:%x(h) %d(d)\n", ctlnum, ctlnum);
+//           #endif
+//         }
+// 
+//       }
+// 
+//       float val = midi2LadspaValue(ld, i, ctlnum, b);
+// 
+//       #ifdef VST_NATIVE_DEBUG
+//       fprintf(stderr, "VstNativeSynthIF::processEvent control port:%lu port:%lu dataA:%d Converting val from:%d to ladspa:%f\n", i, k, a, b, val);
+//       #endif
+// 
+//       // Set the ladspa port value.
+//       controls[k].val = val;
+// 
+//       // Need to update the automation value, otherwise it overwrites later with the last automation value.
+//       if(id() != -1)
+//         // We're in the audio thread context: no need to send a message, just modify directly.
+//         synti->setPluginCtrlVal(genACnum(id(), k), val);
+// 
+//       // Since we absorbed the message as a ladspa control change, return false - the event is not filled.
+//       return false;
+    }
+    break;
+    case MusECore::ME_PITCHBEND:
+    {
+      int v = a + 8192;
+      setVstEvent(event, (type | chn) & 0xff, v & 0x7f, (v >> 7) & 0x7f);
+    }
+    break;
+    case MusECore::ME_AFTERTOUCH:
+      setVstEvent(event, (type | chn) & 0xff, a & 0x7f);
+    break;
+    case MusECore::ME_POLYAFTER:
+      setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
+    break;
+    case MusECore::ME_SYSEX:
+      {
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_SYSEX\n");
+        #endif
+
+        const unsigned char* data = e.data();
+        if(e.len() >= 2)
+        {
+          if(data[0] == MUSE_SYNTH_SYSEX_MFG_ID)
+          {
+            if(data[1] == VST_NATIVE_SYNTH_UNIQUE_ID)
+            {
+              //if(e.len() >= 9)
+              if(e.len() >= 10)
+              {
+                if (QString((const char*)(data + 2)).startsWith("VSTSAVE"))
+                {
+                  if(_synth->hasChunks())
+                  {
+#ifdef VST_SDK_SUPPORT
+                    int chunk_flags = data[9];
+                    if(chunk_flags & VST_NATIVE_CHUNK_FLAG_COMPRESSED)
+                      fprintf(stderr, "chunk flags:%x compressed chunks not supported yet.\n", chunk_flags);
+                    else
+                    {
+                      fprintf(stderr, "%s: loading chunk from sysex!\n", name().toLatin1().constData());
+                      // 10 = 2 bytes header + "VSTSAVE" + 1 byte flags (compression etc)
+                      len = dispatch(effSetChunk, 0, e.len()-10, (void*)(data+10), 0.0); // index 0: is bank 1: is program
+                    }
+#else
+                    fprintf(stderr, "support for vst chunks not compiled in!\n");
+#endif
+                  }
+                  // Event not filled.
+                  return false;
+                }
+              }
+            }
+          }
+        }
+
+        // DELETETHIS, 50 clean it up or fix it?
+        /*
+        // p3.3.39 Read the state of current bank and program and all input control values.
+        // TODO: Needs to be better. See write().
+        //else
+        if (QString((const char*)e.data()).startsWith("PARAMSAVE"))
+        {
+          #ifdef VST_NATIVE_DEBUG
+          fprintf(stderr, "VstNativeSynthIF::processEvent midi event is MusECore::ME_SYSEX PARAMSAVE\n");
+          #endif
+
+          unsigned long dlen = e.len() - 9; // Minus "PARAMSAVE"
+          if(dlen > 0)
+          {
+            //if(dlen < 2 * sizeof(unsigned long))
+            if(dlen < (2 + 2 * sizeof(unsigned long))) // Version major and minor bytes, bank and program.
+              fprintf(stderr, "VstNativeSynthIF::processEvent Error: PARAMSAVE data length does not include at least version major and minor, bank and program!\n");
+            else
+            {
+              // Not required, yet.
+              //char vmaj = *((char*)(e.data() + 9));  // After "PARAMSAVE"
+              //char vmin = *((char*)(e.data() + 10));
+
+              unsigned long* const ulp = (unsigned long*)(e.data() + 11);  // After "PARAMSAVE" + version major and minor.
+              // TODO: TODO: Set plugin bank and program.
+              _curBank = ulp[0];
+              _curProgram = ulp[1];
+
+              dlen -= (2 + 2 * sizeof(unsigned long)); // After the version major and minor, bank and program.
+
+              if(dlen > 0)
+              {
+                if((dlen % sizeof(float)) != 0)
+                  fprintf(stderr, "VstNativeSynthIF::processEvent Error: PARAMSAVE float data length not integral multiple of float size!\n");
+                else
+                {
+                  const unsigned long n = dlen / sizeof(float);
+                  if(n != synth->_controlInPorts)
+                    fprintf(stderr, "VstNativeSynthIF::processEvent Warning: PARAMSAVE number of floats:%lu != number of controls:%lu\n", n, synth->_controlInPorts);
+
+                  // Point to location after "PARAMSAVE", version major and minor, bank and progam.
+                  float* const fp = (float*)(e.data() + 9 + 2 + 2 * sizeof(unsigned long));
+
+                  for(unsigned long i = 0; i < synth->_controlInPorts && i < n; ++i)
+                  {
+                    const float v = fp[i];
+                    controls[i].val = v;
+                  }
+                }
+              }
+            }
+          }
+          // Event not filled.
+          return false;
+        }
+        */
+        //else
+        {
+          // FIXME TODO: Sysex support.
+          return false;
+
+          // NOTE: There is a limit on the size of a sysex. Got this:
+          // "VstNativeSynthIF::processEvent midi event is MusECore::ME_SYSEX"
+          // "WARNING: MIDI event of type ? decoded to 367 bytes, discarding"
+          // That might be ALSA doing that.
+//           snd_seq_ev_clear(event);
+//           event->queue = SND_SEQ_QUEUE_DIRECT;
+//           snd_seq_ev_set_sysex(event, len,
+//             (unsigned char*)ca);
+        }
+      }
+    break;
+    default:
+      if(MusEGlobal::debugMsg)
+        fprintf(stderr, "VstNativeSynthIF::processEvent midi event unknown type:%d\n", e.type());
+      // Event not filled.
+      return false;
+    break;
+  }
+
+  return true;
+}
+
+//---------------------------------------------------------
+//   getData
+//---------------------------------------------------------
+
+iMPEvent VstNativeSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent start_event, unsigned pos, int ports, unsigned nframes, float** buffer)
+{
+  // We may not be using nevents all at once - this will be just the maximum.
+  unsigned long nevents = el->size() + synti->eventFifo.getSize();
+  VstMidiEvent events[nevents];
+  char evbuf[sizeof(VstMidiEvent*) * nevents + sizeof(VstEvents)];
+  VstEvents *vst_events = (VstEvents*)evbuf;
+  vst_events->numEvents = 0;
+  vst_events->reserved  = 0;
+
+  int frameOffset = MusEGlobal::audio->getFrameOffset();
+  unsigned long syncFrame = MusEGlobal::audio->curSyncFrame();
+
+  #ifdef VST_NATIVE_DEBUG_PROCESS
+  fprintf(stderr, "VstNativeSynthIF::getData: pos:%u ports:%d nframes:%u syncFrame:%lu nevents:%lu\n", pos, ports, nframes, syncFrame, nevents);
+  #endif
+
+  unsigned long nop, k;
+  nop = ((unsigned long) ports) > _synth->outPorts() ? _synth->outPorts() : ((unsigned long) ports);
+  unsigned long sample = 0;
+
+  // I read that some plugins do not like changing sample run length (compressors etc). Some are OK with it.
+  // TODO: In order to support this effectively, must be user selectable, per-plugin. ENABLED for now.
+  const bool usefixedrate = false;  
+  unsigned long fixedsize = nframes; 
+
+  // For now, the fixed size is clamped to the MusEGlobal::audio buffer size.
+  // TODO: We could later add slower processing over several cycles -
+  //  so that users can select a small MusEGlobal::audio period but a larger control period.
+  if(fixedsize > nframes)
+    fixedsize = nframes;
+
+  unsigned long min_per = MusEGlobal::config.minControlProcessPeriod;  // Must be power of 2 !
+  if(min_per > nframes)
+    min_per = nframes;
+
+  // Inform the host callback we are in the audio thread.
+  _inProcess = true;
+
+  #ifdef VST_NATIVE_DEBUG_PROCESS
+  fprintf(stderr, "VstNativeSynthIF::getData: Handling inputs...\n");
+  #endif
+
+  // Handle inputs...
+  if(!((MusECore::AudioTrack*)synti)->noInRoute())
+  {
+    RouteList* irl = ((MusECore::AudioTrack*)synti)->inRoutes();
+    iRoute i = irl->begin();
+    if(!i->track->isMidiTrack())
+    {
+      int ch     = i->channel       == -1 ? 0 : i->channel;
+      int remch  = i->remoteChannel == -1 ? 0 : i->remoteChannel;
+      int chs    = i->channels      == -1 ? 0 : i->channels;
+
+      if((unsigned)ch < _synth->inPorts() && (unsigned)(ch + chs) <= _synth->inPorts())
+      {
+        int h = remch + chs;
+        for(int j = remch; j < h; ++j)
+          _iUsedIdx[j] = true;
+
+        ((MusECore::AudioTrack*)i->track)->copyData(pos, chs, ch, -1, nframes, &_audioInBuffers[remch]);
+      }
+    }
+
+    ++i;
+    for(; i != irl->end(); ++i)
+    {
+      if(i->track->isMidiTrack())
+        continue;
+
+      int ch     = i->channel       == -1 ? 0 : i->channel;
+      int remch  = i->remoteChannel == -1 ? 0 : i->remoteChannel;
+      int chs    = i->channels      == -1 ? 0 : i->channels;
+
+      if((unsigned)ch < _synth->inPorts() && (unsigned)(ch + chs) <= _synth->inPorts())
+      {
+        bool u1 = _iUsedIdx[remch];
+        if(chs >= 2)
+        {
+          bool u2 = _iUsedIdx[remch + 1];
+          if(u1 && u2)
+            ((MusECore::AudioTrack*)i->track)->addData(pos, chs, ch, -1, nframes, &_audioInBuffers[remch]);
+          else
+          if(!u1 && !u2)
+            ((MusECore::AudioTrack*)i->track)->copyData(pos, chs, ch, -1, nframes, &_audioInBuffers[remch]);
+          else
+          {
+            if(u1)
+              ((MusECore::AudioTrack*)i->track)->addData(pos, 1, ch, 1, nframes, &_audioInBuffers[remch]);
+            else
+              ((MusECore::AudioTrack*)i->track)->copyData(pos, 1, ch, 1, nframes, &_audioInBuffers[remch]);
+
+            if(u2)
+              ((MusECore::AudioTrack*)i->track)->addData(pos, 1, ch + 1, 1, nframes, &_audioInBuffers[remch + 1]);
+            else
+              ((MusECore::AudioTrack*)i->track)->copyData(pos, 1, ch + 1, 1, nframes, &_audioInBuffers[remch + 1]);
+          }
+        }
+        else
+        {
+            if(u1)
+              ((MusECore::AudioTrack*)i->track)->addData(pos, 1, ch, -1, nframes, &_audioInBuffers[remch]);
+            else
+              ((MusECore::AudioTrack*)i->track)->copyData(pos, 1, ch, -1, nframes, &_audioInBuffers[remch]);
+        }
+
+        int h = remch + chs;
+        for(int j = remch; j < h; ++j)
+          _iUsedIdx[j] = true;
+      }
+    }
+  }
+
+  #ifdef VST_NATIVE_DEBUG_PROCESS
+  fprintf(stderr, "VstNativeSynthIF::getData: Processing automation control values...\n");
+  #endif
+
+  while(sample < nframes)
+  {
+    unsigned long nsamp = usefixedrate ? fixedsize : nframes - sample;
+
+    //
+    // Process automation control values, while also determining the maximum acceptable
+    //  size of this run. Further processing, from FIFOs for example, can lower the size
+    //  from there, but this section determines where the next highest maximum frame
+    //  absolutely needs to be for smooth playback of the controller value stream...
+    //
+    if(id() != -1)
+    {
+      unsigned long frame = pos + sample;
+      AutomationType at = AUTO_OFF;
+      at = synti->automationType();
+      bool no_auto = !MusEGlobal::automation || at == AUTO_OFF;
+      AudioTrack* track = (static_cast<AudioTrack*>(synti));
+      int nextFrame;
+      const unsigned long in_ctrls = _synth->inControls();
+      for(unsigned long k = 0; k < in_ctrls; ++k)
+      {
+        //_controls[k].val = track->controller()->value(genACnum(id(), k), frame,
+        //                        no_auto || !_controls[k].enCtrl || !_controls[k].en2Ctrl,
+        //                        &nextFrame);
+        if(dispatch(effCanBeAutomated, k, 0, NULL, 0.0f) == 1)
+          _plugin->setParameter(_plugin, k, track->controller()->value(genACnum(id(), k), frame,
+                                 no_auto || !_controls[k].enCtrl || !_controls[k].en2Ctrl,
+                                 &nextFrame));
+#ifdef VST_NATIVE_DEBUG
+        else
+          fprintf(stderr, "VstNativeSynthIF::getData %s parameter:%lu cannot be automated\n", name().toLatin1().constData(), k);
+#endif
+            
+#ifdef VST_NATIVE_DEBUG_PROCESS
+        fprintf(stderr, "VstNativeSynthIF::getData k:%lu sample:%lu frame:%lu nextFrame:%d nsamp:%lu \n", k, sample, frame, nextFrame, nsamp);
+#endif
+        if(MusEGlobal::audio->isPlaying() && !usefixedrate && nextFrame != -1)
+        {
+          // Returned value of nextFrame can be zero meaning caller replaces with some (constant) value.
+          unsigned long samps = (unsigned long)nextFrame;
+          if(samps > frame + min_per)
+          {
+            unsigned long diff = samps - frame;
+            unsigned long mask = min_per-1;   // min_per must be power of 2
+            samps = diff & ~mask;
+            if((diff & mask) != 0)
+              samps += min_per;
+          }
+          else
+            samps = min_per;
+
+          if(samps < nsamp)
+            nsamp = samps;
+        }
+      }
+#ifdef VST_NATIVE_DEBUG_PROCESS
+      fprintf(stderr, "VstNativeSynthIF::getData sample:%lu nsamp:%lu\n", sample, nsamp);
+#endif
+    }
+
+    bool found = false;
+    unsigned long frame = 0;
+    unsigned long index = 0;
+    unsigned long evframe;
+    // Get all control ring buffer items valid for this time period...
+    while(!_controlFifo.isEmpty())
+    {
+      ControlEvent v = _controlFifo.peek();
+      // The events happened in the last period or even before that. Shift into this period with + n. This will sync with audio.
+      // If the events happened even before current frame - n, make sure they are counted immediately as zero-frame.
+      evframe = (syncFrame > v.frame + nframes) ? 0 : v.frame - syncFrame + nframes;
+
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::getData found:%d evframe:%lu frame:%lu  event frame:%lu idx:%lu val:%f unique:%d\n",
+          found, evframe, frame, v.frame, v.idx, v.value, v.unique);
+      #endif
+
+      // Protection. Observed this condition. Why? Supposed to be linear timestamps.
+      if(found && evframe < frame)
+      {
+        fprintf(stderr, "VstNativeSynthIF::getData *** Error: evframe:%lu < frame:%lu event: frame:%lu idx:%lu val:%f unique:%d\n",
+          evframe, frame, v.frame, v.idx, v.value, v.unique);
+
+        // No choice but to ignore it.
+        _controlFifo.remove();               // Done with the ring buffer's item. Remove it.
+        continue;
+      }
+
+      if(evframe >= nframes                                                        // Next events are for a later period.
+         || (!usefixedrate && !found && !v.unique && (evframe - sample >= nsamp))  // Next events are for a later run in this period. (Autom took prio.)
+         || (found && !v.unique && (evframe - sample >= min_per))                  // Eat up events within minimum slice - they're too close.
+         || (usefixedrate && found && v.unique && v.idx == index))                 // Special for dssi-vst: Fixed rate and must reply to all.
+        break;
+      _controlFifo.remove();               // Done with the ring buffer's item. Remove it.
+
+      if(v.idx >= _synth->inControls()) // Sanity check.
+        break;
+      found = true;
+      frame = evframe;
+      index = v.idx;
+      // Set the ladspa control port value.
+      //controls[v.idx].val = v.value;
+      if(dispatch(effCanBeAutomated, v.idx, 0, NULL, 0.0f) == 1)
+        _plugin->setParameter(_plugin, v.idx, v.value);
+#ifdef VST_NATIVE_DEBUG
+      else
+        fprintf(stderr, "VstNativeSynthIF::getData %s parameter:%lu cannot be automated\n", name().toLatin1().constData(), v.idx);
+#endif
+
+      // Need to update the automation value, otherwise it overwrites later with the last automation value.
+      if(id() != -1)
+        synti->setPluginCtrlVal(genACnum(id(), v.idx), v.value);
+    }
+
+    if(found && !usefixedrate)  // If a control FIFO item was found, takes priority over automation controller stream.
+      nsamp = frame - sample;
+
+    if(sample + nsamp >= nframes)         // Safety check.
+      nsamp = nframes - sample;
+
+    // TODO: Don't allow zero-length runs. This could/should be checked in the control loop instead.
+    // Note this means it is still possible to get stuck in the top loop (at least for a while).
+    if(nsamp == 0)
+      continue;
+
+    nevents = 0;
+    // Process event list events...
+    for(; start_event != el->end(); ++start_event)
+    {
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::getData eventlist event time:%d pos:%u sample:%lu nsamp:%lu frameOffset:%d\n", start_event->time(), pos, sample, nsamp, frameOffset);
+      #endif
+
+      if(start_event->time() >= (pos + sample + nsamp + frameOffset))  // frameOffset? Test again...
+      {
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, " event is for future:%lu, breaking loop now\n", start_event->time() - frameOffset - pos - sample);
+        #endif
+        break;
+      }
+
+      // Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values.
+      // Same code as in MidiPort::sendEvent()
+      if(synti->midiPort() != -1)
+      {
+        MusECore::MidiPort* mp = &MusEGlobal::midiPorts[synti->midiPort()];
+        if(start_event->type() == MusECore::ME_CONTROLLER)
+        {
+          int da = start_event->dataA();
+          int db = start_event->dataB();
+          db = mp->limitValToInstrCtlRange(da, db);
+          if(!mp->setHwCtrlState(start_event->channel(), da, db))
+            continue;
+        }
+        else if(start_event->type() == MusECore::ME_PITCHBEND)
+        {
+          int da = mp->limitValToInstrCtlRange(MusECore::CTRL_PITCH, start_event->dataA());
+          if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PITCH, da))
+            continue;
+        }
+        else if(start_event->type() == MusECore::ME_AFTERTOUCH)
+        {
+          int da = mp->limitValToInstrCtlRange(MusECore::CTRL_AFTERTOUCH, start_event->dataA());
+          if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_AFTERTOUCH, da))
+            continue;
+        }
+        else if(start_event->type() == MusECore::ME_POLYAFTER)
+        {
+          int ctl = (MusECore::CTRL_POLYAFTER & ~0xff) | (start_event->dataA() & 0x7f);
+          int db = mp->limitValToInstrCtlRange(ctl, start_event->dataB());
+          if(!mp->setHwCtrlState(start_event->channel(), ctl , db))
+            continue;
+        }
+        else if(start_event->type() == MusECore::ME_PROGRAM)
+        {
+          if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PROGRAM, start_event->dataA()))
+            continue;
+        }
+      }
+
+      // Returns false if the event was not filled. It was handled, but some other way.
+      if(processEvent(*start_event, &events[nevents]))
+      {
+        // Time-stamp the event.
+        int ft = start_event->time() - frameOffset - pos - sample;
+        if(ft < 0)
+          ft = 0;
+
+        if (ft >= int(nsamp))
+        {
+            fprintf(stderr, "VstNativeSynthIF::getData: eventlist event time:%d out of range. pos:%d offset:%d ft:%d sample:%lu nsamp:%lu\n", start_event->time(), pos, frameOffset, ft, sample, nsamp);
+            ft = nsamp - 1;
+        }
+
+        #ifdef VST_NATIVE_DEBUG
+        fprintf(stderr, "VstNativeSynthIF::getData eventlist: ft:%d current nevents:%lu\n", ft, nevents);
+        #endif
+
+        vst_events->events[nevents] = (VstEvent*)&events[nevents];
+        events[nevents].deltaFrames = ft;
+        ++nevents;
+      }
+    }
+
+    // Now process putEvent events...
+    while(!synti->eventFifo.isEmpty())
+    {
+      MusECore::MidiPlayEvent e = synti->eventFifo.peek();
+
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::getData eventFifo event time:%d\n", e.time());
+      #endif
+
+      if(e.time() >= (pos + sample + nsamp + frameOffset))
+        break;
+
+      synti->eventFifo.remove();    // Done with ring buffer's event. Remove it.
+      // Returns false if the event was not filled. It was handled, but some other way.
+      if(processEvent(e, &events[nevents]))
+      {
+        // Time-stamp the event.
+        int ft = e.time() - frameOffset - pos  - sample;
+        if(ft < 0)
+          ft = 0;
+        if (ft >= int(nsamp))
+        {
+            fprintf(stderr, "VstNativeSynthIF::getData: eventFifo event time:%d out of range. pos:%d offset:%d ft:%d sample:%lu nsamp:%lu\n", e.time(), pos, frameOffset, ft, sample, nsamp);
+            ft = nsamp - 1;
+        }
+        vst_events->events[nevents] = (VstEvent*)&events[nevents];
+        events[nevents].deltaFrames = ft;
+
+        ++nevents;
+      }
+    }
+
+    #ifdef VST_NATIVE_DEBUG_PROCESS
+    fprintf(stderr, "VstNativeSynthIF::getData: Connecting and running. sample:%lu nsamp:%lu nevents:%lu\n", sample, nsamp, nevents);
+    #endif
+
+    // Set the events pointer.
+    if(nevents > 0)
+    {
+      vst_events->numEvents = nevents;
+      dispatch(effProcessEvents, 0, 0, vst_events, 0.0f);
+    }
+
+    float* in_bufs[_synth->inPorts()];
+    float* out_bufs[_synth->outPorts()];
+    
+    k = 0;
+    // Connect the given buffers directly to the ports, up to a max of synth ports.
+    for(; k < nop; ++k)
+      out_bufs[k] = buffer[k] + sample;
+    // Connect the remaining ports to some local buffers (not used yet).
+    const unsigned long op =_synth->outPorts();  
+    for(; k < op; ++k)
+      out_bufs[k] = _audioOutBuffers[k] + sample;
+    // Connect all inputs either to some local buffers, or a silence buffer.
+    const unsigned long ip =_synth->inPorts();
+    for(k = 0; k < ip; ++k)
+    {
+      if(_iUsedIdx[k])
+      {
+        _iUsedIdx[k] = false; // Reset
+        in_bufs[k] = _audioInBuffers[k] + sample;
+      }
+      else
+        in_bufs[k] = _audioInSilenceBuf + sample;
+    }
+
+    // Run the synth for a period of time. This processes events and gets/fills our local buffers...
+    if((_plugin->flags & effFlagsCanReplacing) && _plugin->processReplacing)
+    {
+      _plugin->processReplacing(_plugin, in_bufs, out_bufs, nsamp);
+    }
+#if 0 //ifdef VST_NATIVE_FORCE_DEPRECATED
+    else
+    {
+      // TODO: This is not right, we don't accumulate data here. Depricated now, and frowned upon anyway...
+      if(_plugin->process)
+        _plugin->process(_plugin, in_bufs, out_bufs, nsamp);
+    }
+#endif
+    
+    sample += nsamp;
+  }
+
+  // Inform the host callback we will be no longer in the audio thread.
+  _inProcess = true;
+  
+  return start_event;
+}
+
+//---------------------------------------------------------
+//   putEvent
+//---------------------------------------------------------
+
+bool VstNativeSynthIF::putEvent(const MidiPlayEvent& ev)
+      {
+      #ifdef VST_NATIVE_DEBUG
+      fprintf(stderr, "VstNativeSynthIF::putEvent midi event time:%d chn:%d a:%d b:%d\n", ev.time(), ev.channel(), ev.dataA(), ev.dataB());
+      #endif
+      
+      if (MusEGlobal::midiOutputTrace)
+            ev.dump();
+      return synti->eventFifo.put(ev);
+      }
+
+
+//--------------------------------
+// Methods for PluginIBase:
+//--------------------------------
+
+unsigned long VstNativeSynthIF::pluginID()                        { return (_plugin) ? _plugin->uniqueID : 0; }
+int VstNativeSynthIF::id()                                        { return MAX_PLUGINS; } // Set for special block reserved for synth. 
+QString VstNativeSynthIF::pluginLabel() const                     { return _synth ? QString(_synth->name()) : QString(); } // FIXME Maybe wrong
+QString VstNativeSynthIF::lib() const                             { return _synth ? _synth->completeBaseName() : QString(); }
+QString VstNativeSynthIF::dirPath() const                         { return _synth ? _synth->absolutePath() : QString(); }
+QString VstNativeSynthIF::fileName() const                        { return _synth ? _synth->fileName() : QString(); }
+void VstNativeSynthIF::enableController(unsigned long i, bool v)  { _controls[i].enCtrl = v; }
+bool VstNativeSynthIF::controllerEnabled(unsigned long i) const   { return _controls[i].enCtrl;}
+void VstNativeSynthIF::enable2Controller(unsigned long i, bool v) { _controls[i].en2Ctrl = v; }
+bool VstNativeSynthIF::controllerEnabled2(unsigned long i) const  { return _controls[i].en2Ctrl; }
+void VstNativeSynthIF::enableAllControllers(bool v)
+{
+  if(!_synth)
+    return;
+  for(unsigned long i = 0; i < _synth->inControls(); ++i)
+    _controls[i].enCtrl = v;
+}
+void VstNativeSynthIF::enable2AllControllers(bool v)
+{
+  if(!_synth)
+    return;
+  for(unsigned long i = 0; i < _synth->inControls(); ++i)
+    _controls[i].en2Ctrl = v;
+}
+void VstNativeSynthIF::updateControllers() { }
+void VstNativeSynthIF::activate()
+{
+  //for (unsigned short i = 0; i < instances(); ++i) {
+  //        dispatch(i, effMainsChanged, 0, 1, NULL, 0.0f);
+  dispatch(effMainsChanged, 0, 1, NULL, 0.0f);
+//#ifdef VST_SDK_SUPPORT
+  //dispatch(i, effStartProcess, 0, 0, NULL, 0.0f);
+  dispatch(effStartProcess, 0, 0, NULL, 0.0f);
+//#endif
+  //}
+
+// REMOVE Tim. Or keep? From PluginI::activate().
+//   if (initControlValues) {
+//         for (unsigned long i = 0; i < controlPorts; ++i) {
+//               controls[i].val = controls[i].tmpVal;
+//               }
+//         }
+//   else {
+//         // get initial control values from plugin
+//         for (unsigned long i = 0; i < controlPorts; ++i) {
+//               controls[i].tmpVal = controls[i].val;
+//               }
+//         }
+}
+void VstNativeSynthIF::deactivate()
+{
+  //for (unsigned short i = 0; i < instances(); ++i) {
+//#ifdef VST_SDK_SUPPORT
+  //dispatch(i, effStopProcess, 0, 0, NULL, 0.0f);
+  dispatch(effStopProcess, 0, 0, NULL, 0.0f);
+//#endif
+  //dispatch(i, effMainsChanged, 0, 0, NULL, 0.0f);
+  dispatch(effMainsChanged, 0, 0, NULL, 0.0f);
+  //}
+}
+
+unsigned long VstNativeSynthIF::parameters() const                { return _synth ? _synth->inControls() : 0; }
+unsigned long VstNativeSynthIF::parametersOut() const             { return 0; }
+void VstNativeSynthIF::setParam(unsigned long i, float val)       { setParameter(i, val); }
+float VstNativeSynthIF::param(unsigned long i) const              { return getParameter(i); }
+float VstNativeSynthIF::paramOut(unsigned long) const           { return 0.0; }
+const char* VstNativeSynthIF::paramName(unsigned long i)          
+{
+  if(!_plugin)
+    return 0;
+  static char buf[256];
+  buf[0] = 0;
+  dispatch(effGetParamName, i, 0, buf, 0);
+  return buf;
+}
+
+const char* VstNativeSynthIF::paramOutName(unsigned long)       { return 0; }
+LADSPA_PortRangeHint VstNativeSynthIF::range(unsigned long /*i*/)     
+{
+  LADSPA_PortRangeHint h;
+  // FIXME TODO:
+  h.HintDescriptor = 0;
+  h.LowerBound = 0.0;
+  h.UpperBound = 1.0;
+  return h;
+}
+LADSPA_PortRangeHint VstNativeSynthIF::rangeOut(unsigned long)  
+{
+  // There are no output controls.
+  LADSPA_PortRangeHint h;
+  h.HintDescriptor = 0;
+  h.LowerBound = 0.0;
+  h.UpperBound = 1.0;
+  return h;
+}
+// FIXME TODO:
+CtrlValueType VstNativeSynthIF::ctrlValueType(unsigned long /*i*/) const { return VAL_LINEAR; }
+CtrlList::Mode VstNativeSynthIF::ctrlMode(unsigned long /*i*/) const     { return CtrlList::INTERPOLATE; };
+
+} // namespace MusECore
+
+#else  // VST_NATIVE_SUPPORT
+namespace MusECore {
+void initVST_Native() {}
+} // namespace MusECore
+#endif
+
diff --git a/muse2/muse/vst_native.h b/muse2/muse/vst_native.h
new file mode 100644
index 00000000..3b877cd8
--- /dev/null
+++ b/muse2/muse/vst_native.h
@@ -0,0 +1,281 @@
+//=========================================================
+//  MusE
+//  Linux Music Editor
+//
+//  vst_native.h
+//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; version 2 of
+//  the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//=========================================================
+
+#ifndef __VST_NATIVE_H__
+#define __VST_NATIVE_H__
+
+#include "config.h"
+
+// Make sure this number is unique among all the MESS synths and DSSI and VST host synths.
+#define VST_NATIVE_SYNTH_UNIQUE_ID 9
+// Midistate sysex initialization command.
+#define VST_NATIVE_INIT_DATA_CMD 1
+
+#define VST_NATIVE_PARAMSAVE_VERSION_MAJOR  0
+#define VST_NATIVE_PARAMSAVE_VERSION_MINOR  1
+
+#define VST_NATIVE_CHUNK_FLAG_COMPRESSED 1
+
+#ifdef VST_NATIVE_SUPPORT
+
+class VstNativeSynthIF;
+
+typedef class VstNativeSynthIF VSTPlugin;
+
+#include "aeffectx.h"
+
+//#define VST_2_3_EXTENSIONS          // TODO Detect this  ?
+#define VST_2_4_EXTENSIONS          // TODO Detect this  ?
+#define VST_NATIVE_FORCE_DEPRECATED   // TODO On or off?
+
+#ifndef VST_SDK_SUPPORT
+#ifndef effCanBeAutomated
+#define effCanBeAutomated 26
+#endif
+#ifndef effGetProgramNameIndexed
+#define effGetProgramNameIndexed 29
+#endif
+#ifndef effBeginSetProgram
+#define effBeginSetProgram 67  
+#endif
+#ifndef effEndSetProgram
+#define effEndSetProgram 68
+#endif
+#ifndef effStartProcess
+#define effStartProcess 71
+#endif
+#ifndef effStopProcess
+#define effStopProcess 72
+#endif
+#endif
+
+#if defined(VST_2_4_EXTENSIONS)
+#ifdef VST_SDK_SUPPORT
+typedef long     VstInt32;
+typedef long     VstIntPtr;
+#else
+typedef int32_t  VstInt32;
+typedef intptr_t VstIntPtr;
+#endif
+#define VSTCALLBACK
+#endif
+
+#include "vst_native_editor.h"
+#include "synth.h"
+#include "plugin.h"
+#include "midictrl.h"
+
+#endif // VST_NATIVE_SUPPORT
+
+namespace MusEGui {
+class PopupMenu;
+}
+
+namespace MusECore {
+
+#ifdef VST_NATIVE_SUPPORT
+
+struct VstRect{
+    short top;
+    short left;
+    short bottom;
+    short right;
+};
+
+struct VST_Program {
+    //unsigned long bank;
+    unsigned long program;
+    QString name;
+};
+
+
+//---------------------------------------------------------
+//   VstNativeSynth
+//---------------------------------------------------------
+
+class VstNativeSynth : public Synth {
+      enum VstPluginFlags
+      {
+        canSendVstEvents          = 1 << 0,
+        canSendVstMidiEvents      = 1 << 1,
+        canSendVstTimeInfo        = 1 << 2,
+        canReceiveVstEvents       = 1 << 3,
+        canReceiveVstMidiEvents   = 1 << 4,
+        canReceiveVstTimeInfo     = 1 << 5,
+        canProcessOffline         = 1 << 6,
+        canUseAsInsert            = 1 << 7,
+        canUseAsSend              = 1 << 8,
+        canMixDryWet              = 1 << 9,
+        canMidiProgramNames       = 1 << 10
+      };
+
+      void* _handle;
+      int _vst_version;
+      unsigned int _flags;
+      
+      unsigned long /*_portCount,*/ _inports, _outports, _controlInPorts; //, _controlOutPorts;
+      std::vector<unsigned long> iIdx;  // Audio input index to port number.
+      std::vector<unsigned long> oIdx;  // Audio output index to port number.
+      std::vector<unsigned long> rpIdx; // Port number to control input index. Item is -1 if it's not a control input.
+      MusECore::MidiCtl2LadspaPortMap midiCtl2PortMap;   // Maps midi controller numbers to vst port numbers.
+      MusECore::MidiCtl2LadspaPortMap port2MidiCtlMap;   // Maps vst port numbers to midi controller numbers.
+      bool _hasGui;
+      bool _inPlaceCapable;
+      bool _hasChunks;
+      
+   public:
+      VstNativeSynth(const QFileInfo& fi, AEffect* plugin, const QString& label, const QString& desc, const QString& maker, const QString& ver);
+
+      virtual ~VstNativeSynth() {}
+      virtual Type synthType() const { return VST_NATIVE_SYNTH; }
+      virtual void incInstances(int val);
+      virtual AEffect* instantiate();
+      virtual SynthIF* createSIF(SynthI*);
+      unsigned long inPorts()     const { return _inports; }
+      unsigned long outPorts()    const { return _outports; }
+      unsigned long inControls()  const { return _controlInPorts; }
+      //unsigned long outControls() const { return _controlOutPorts; }
+
+      int vstVersion()  const { return _vst_version; }
+      bool hasChunks()  const { return _hasChunks; }
+      const std::vector<unsigned long>* getRpIdx() { return &rpIdx; }
+      };
+
+//---------------------------------------------------------
+//   VstNativeSynthIF
+//    VSTi synthesizer instance
+//---------------------------------------------------------
+
+class VstNativeSynthIF : public SynthIF
+      {
+      friend class VstNativeSynth;
+      friend class MusEGui::VstNativeEditor;
+      
+      VstNativeSynth* _synth;
+      AEffect* _plugin;
+      MusEGui::VstNativeEditor* _editor;
+      bool _guiVisible;
+      bool _inProcess; // To inform the callback of the 'process level' - are we in the audio thread?
+
+      Port* _controls;
+      float** _audioOutBuffers;
+      float** _audioInBuffers;
+      std::vector<unsigned long> _iUsedIdx;  // During process, tells whether an audio input port was used by any input routes.
+      float*  _audioInSilenceBuf;            // Just all zeros all the time, so we don't have to clear for silence.
+      //float**  _audioInSilenceBufs;          // Just all zeros all the time, so we don't have to clear for silence.
+
+      std::vector<VST_Program> programs;
+      void queryPrograms();
+      void doSelectProgram(int bankH, int bankL, int prog);
+      bool processEvent(const MusECore::MidiPlayEvent&, VstMidiEvent*);
+      void setVstEvent(VstMidiEvent* event, int a = 0, int b = 0, int c = 0, int d = 0);
+      
+      void editorDeleted();
+      void editorOpened();
+      void editorClosed();
+      
+   public:
+      VstNativeSynthIF(SynthI* s);
+      virtual ~VstNativeSynthIF();
+
+      virtual bool init(Synth*);
+      
+      AEffect* plugin() const { return _plugin; }
+      VstIntPtr hostCallback(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
+      VstIntPtr dispatch(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) const {
+                  if(_plugin) return _plugin->dispatcher(_plugin, opcode, index, value, ptr, opt); return 0;  }
+      void idleEditor();
+      bool resizeEditor(int w, int h);
+      
+      virtual bool initGui()       { return true; };
+      virtual void guiHeartBeat()  {  }
+      virtual bool guiVisible() const;
+      virtual void showGui(bool);
+      virtual bool hasGui() const { return true; }
+      virtual bool nativeGuiVisible() const;
+      virtual void showNativeGui(bool v);
+      virtual bool hasNativeGui() const;
+      virtual void getGeometry(int*x, int*y, int*w, int*h) const { *x=0;*y=0;*w=0;*h=0; }
+      virtual void setGeometry(int, int, int, int) {}
+      virtual void getNativeGeometry(int*x, int*y, int*w, int*h) const { *x=0;*y=0;*w=0;*h=0; }
+      virtual void setNativeGeometry(int, int, int, int) {}
+      virtual void preProcessAlways() { };
+      virtual iMPEvent getData(MidiPort*, MPEventList*, iMPEvent, unsigned pos, int ports, unsigned nframes, float** buffer) ;
+      virtual bool putEvent(const MidiPlayEvent& ev);
+      virtual MidiPlayEvent receiveEvent();
+      virtual int eventsPending() const { return 0; }
+      virtual int channels() const;
+      virtual int totalOutChannels() const;
+      virtual int totalInChannels() const;
+      virtual void deactivate3();
+      virtual const char* getPatchName(int chan, int prog, bool drum);
+      virtual void populatePatchPopup(MusEGui::PopupMenu* menu, int chan, bool drum);
+      virtual void write(int level, Xml& xml) const;
+      virtual float getParameter(unsigned long idx) const;
+      virtual void setParameter(unsigned long idx, float value);
+      virtual int getControllerInfo(int, const char**, int*, int*, int*, int*) { return 0; }
+
+      virtual void guiAutomationBegin(unsigned long param_idx);
+      virtual void guiAutomationEnd(unsigned long param_idx);
+      virtual int guiControlChanged(unsigned long param_idx, float value);
+
+      //-------------------------
+      // Methods for PluginIBase:
+      //-------------------------
+      unsigned long pluginID();
+      int id();
+      QString pluginLabel() const;
+      QString lib() const;
+      QString dirPath() const;
+      QString fileName() const;
+      void enableController(unsigned long i, bool v = true);
+      bool controllerEnabled(unsigned long i) const;
+      void enable2Controller(unsigned long i, bool v = true);
+      bool controllerEnabled2(unsigned long i) const;
+      void enableAllControllers(bool v = true);
+      void enable2AllControllers(bool v = true);
+      void updateControllers();
+      void activate();
+      void deactivate();
+
+      unsigned long parameters() const;
+      unsigned long parametersOut() const;
+      void setParam(unsigned long i, float val);
+      float param(unsigned long i) const;
+      float paramOut(unsigned long i) const;
+      const char* paramName(unsigned long i);
+      const char* paramOutName(unsigned long i);
+      LADSPA_PortRangeHint range(unsigned long i);
+      LADSPA_PortRangeHint rangeOut(unsigned long i);
+      CtrlValueType ctrlValueType(unsigned long i) const;
+      CtrlList::Mode ctrlMode(unsigned long i) const;
+      };
+
+#endif // VST_NATIVE_SUPPORT
+
+extern void initVST_Native();
+
+} // namespace MusECore
+
+#endif
+
diff --git a/muse2/muse/widgets/CMakeLists.txt b/muse2/muse/widgets/CMakeLists.txt
index ed72e1a9..8c407525 100644
--- a/muse2/muse/widgets/CMakeLists.txt
+++ b/muse2/muse/widgets/CMakeLists.txt
@@ -105,6 +105,7 @@ QT4_WRAP_CPP (widget_mocs
       view.h
       vscale.h
       visibletracks.h
+      vst_native_editor.h
       warn_bad_timing.h
       )
 
@@ -231,6 +232,7 @@ file (GLOB widgets_source_files
       view.cpp
       vscale.cpp
       visibletracks.cpp
+      vst_native_editor.cpp
       warn_bad_timing.cpp
       )
 
diff --git a/muse2/muse/widgets/vst_native_editor.cpp b/muse2/muse/widgets/vst_native_editor.cpp
new file mode 100644
index 00000000..8f739041
--- /dev/null
+++ b/muse2/muse/widgets/vst_native_editor.cpp
@@ -0,0 +1,223 @@
+//=========================================================
+//  MusE
+//  Linux Music Editor
+//  vst_native_editor.cpp
+//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)
+//  Some of the editor window coding was adapted from QTractor (by rncbc aka Rui Nuno Capela)
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; version 2 of
+//  the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//=========================================================
+
+#include "vst_native_editor.h"
+#include "vst_native.h"
+
+#include <QtGlobal>
+#if defined(Q_WS_X11)
+#include <QX11Info>
+#endif
+
+namespace MusEGui {
+
+//---------------------------------------------------------------------
+// Helpers for editor widget.
+//---------------------------------------------------------------------
+
+#if defined(Q_WS_X11)
+
+static bool g_bXError = false;
+
+static int tempXErrorHandler ( Display *, XErrorEvent * )
+{
+        g_bXError = true;
+        return 0;
+}
+
+static XEventProc getXEventProc ( Display *pDisplay, Window w )
+{
+        int iSize;
+        unsigned long iBytes, iCount;
+        unsigned char *pData;
+        XEventProc eventProc = NULL;
+        Atom aType, aName = XInternAtom(pDisplay, "_XEventProc", false);
+
+        g_bXError = false;
+        XErrorHandler oldErrorHandler = XSetErrorHandler(tempXErrorHandler);
+        XGetWindowProperty(pDisplay, w, aName, 0, 1, false,
+                AnyPropertyType, &aType,  &iSize, &iCount, &iBytes, &pData);
+        if (g_bXError == false && iCount == 1)
+                eventProc = (XEventProc) (pData);
+        XSetErrorHandler(oldErrorHandler);
+
+        return eventProc;
+}
+
+static Window getXChildWindow ( Display *pDisplay, Window w )
+{
+        Window wRoot, wParent, *pwChildren;
+        unsigned int iChildren = 0;
+
+        XQueryTree(pDisplay, w, &wRoot, &wParent, &pwChildren, &iChildren);
+
+        return (iChildren > 0 ? pwChildren[0] : 0);
+}
+
+#endif // Q_WS_X11
+
+VstNativeEditor::VstNativeEditor(QWidget *parent, Qt::WindowFlags wflags)
+  : QWidget(parent, wflags),
+        #if defined(Q_WS_X11)
+          _display(QX11Info::display()),
+          _vstEditor(0),
+          _vstEventProc(0),
+          _buttonPress(false),
+        #endif
+          _sif(0)
+{
+  setAttribute(Qt::WA_DeleteOnClose);
+}
+
+VstNativeEditor::~VstNativeEditor()
+{
+  if(_sif)
+  {
+    _sif->dispatch(effEditClose, 0, 0, NULL, 0.0f);
+    _sif->editorDeleted();
+    _sif = NULL;
+  }
+}
+
+//---------------------------------------------------------------------
+// open
+//---------------------------------------------------------------------
+
+void VstNativeEditor::open(MusECore::VstNativeSynthIF* sif)
+{
+  _sif = sif;
+
+  // Start the proper (child) editor...
+  long  value = 0;
+  void *ptr = (void *) winId();
+#if defined(Q_WS_X11)
+  value = (long) _display;
+#endif
+
+  MusECore::VstRect* pRect;
+  if(_sif->dispatch(effEditGetRect, 0, 0, &pRect, 0.0f))   
+  {
+          int w = pRect->right - pRect->left;
+          int h = pRect->bottom - pRect->top;
+          if (w > 0 && h > 0)
+                  QWidget::setFixedSize(w, h);
+  }
+
+  _sif->dispatch(effEditOpen, 0, value, ptr, 0.0f);  
+
+#if defined(Q_WS_X11)
+  _vstEditor = getXChildWindow(_display, (Window) winId());
+  if(_vstEditor)
+    _vstEventProc = getXEventProc(_display, _vstEditor);
+#endif
+    
+  if(_sif->track())
+  {
+    QString title = _sif->track()->name() + ":" + _sif->pluginLabel();
+    setWindowTitle(title);
+  }
+
+  //_sif->editorOpened();
+  if(!isVisible())
+    show();
+  raise();
+  activateWindow();
+  _sif->idleEditor();
+}
+
+#if defined(Q_WS_X11)
+
+//---------------------------------------------------------------------
+// x11EventFilter
+//---------------------------------------------------------------------
+
+bool VstNativeEditor::x11EventFilter(XEvent *pEvent)
+{
+  if(_vstEventProc && pEvent->xany.window == _vstEditor)
+  {
+    // Avoid mouse tracking events...
+    switch (pEvent->xany.type) {
+    case ButtonPress:
+      _buttonPress = true;
+      break;
+    case ButtonRelease:
+      _buttonPress = false;
+      break;
+    case MotionNotify:
+      if(!_buttonPress)
+        return false;
+      // Fall thru...
+    default:
+      break;
+    }
+    // Process as intended...
+    (*_vstEventProc)(pEvent);
+    return true;
+  }
+  else
+    return false;
+}
+
+#endif
+
+//---------------------------------------------------------------------
+// showEvent
+//---------------------------------------------------------------------
+
+void VstNativeEditor::showEvent(QShowEvent *pShowEvent)
+{
+  QWidget::showEvent(pShowEvent);
+
+  if(_sif)
+    _sif->editorOpened();
+}
+
+//---------------------------------------------------------------------
+// closeEvent
+//---------------------------------------------------------------------
+
+void VstNativeEditor::closeEvent(QCloseEvent *pCloseEvent)
+{
+  if(_sif)
+    _sif->editorClosed();
+    
+  QWidget::closeEvent(pCloseEvent);
+}
+
+//---------------------------------------------------------------------
+// moveEvent
+//---------------------------------------------------------------------
+
+void VstNativeEditor::moveEvent(QMoveEvent *pMoveEvent)
+{
+  QWidget::moveEvent(pMoveEvent);
+#if defined(Q_WS_X11)
+  if(_vstEditor)
+  {
+    XMoveWindow(_display, _vstEditor, 0, 0);
+    //QWidget::update();  // REMOVE Tim. Or keep? Commented in Qtractor.
+  }
+#endif
+}
+
+} // namespace MusEGui
diff --git a/muse2/muse/widgets/vst_native_editor.h b/muse2/muse/widgets/vst_native_editor.h
new file mode 100644
index 00000000..1f591275
--- /dev/null
+++ b/muse2/muse/widgets/vst_native_editor.h
@@ -0,0 +1,91 @@
+//=========================================================
+//  MusE
+//  Linux Music Editor
+//  vst_native_editor.h
+//  (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net)
+//  Some of the editor window coding was adapted from QTractor (by rncbc aka Rui Nuno Capela)
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; version 2 of
+//  the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+//=========================================================
+
+#ifndef __VST_NATIVE_EDITOR_H__
+#define __VST_NATIVE_EDITOR_H__
+
+//#include "vst_native.h"
+//#include <QtGlobal>
+#include <QWidget>
+
+#if defined(Q_WS_X11)
+#include <QX11Info>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#undef Bool
+#undef Status
+#undef None
+#undef KeyPress
+#undef KeyRelease
+#undef FocusIn
+#undef FocusOut
+#undef Type
+#undef FontChange
+#undef CursorShape
+#undef Unsorted
+typedef void (*XEventProc)(XEvent *);
+#endif
+
+namespace MusECore {
+class VstNativeSynthIF;
+}
+
+namespace MusEGui {
+
+class VstNativeEditor : public QWidget
+{
+    Q_OBJECT
+
+#if defined(Q_WS_X11)
+    Display*   _display;
+    Window     _vstEditor;
+    XEventProc _vstEventProc;
+    bool       _buttonPress;
+#endif
+
+    MusECore::VstNativeSynthIF* _sif;
+        
+protected:
+
+    virtual void showEvent(QShowEvent *pShowEvent);
+    virtual void closeEvent(QCloseEvent *pCloseEvent);
+    virtual void moveEvent(QMoveEvent *pMoveEvent);
+
+public:
+    VstNativeEditor(QWidget *parent, Qt::WindowFlags wflags = 0);
+    ~VstNativeEditor();
+
+    void open(MusECore::VstNativeSynthIF* sif);
+    //void close();
+
+#if defined(Q_WS_X11)
+    // Local X11 event filter.
+    bool x11EventFilter(XEvent *pEvent);
+#endif
+
+    //MusECore::VstNativeSynthIF* sif() const { return _sif; }
+};
+
+} // namespace MusEGui
+
+#endif
diff --git a/muse2/synti/deicsonze/deicsonzeplugin.cpp b/muse2/synti/deicsonze/deicsonzeplugin.cpp
index 43ae5d73..a9eec657 100644
--- a/muse2/synti/deicsonze/deicsonzeplugin.cpp
+++ b/muse2/synti/deicsonze/deicsonzeplugin.cpp
@@ -311,6 +311,8 @@ void DeicsOnzeGui::addPluginSlider(int index, QString text, bool isLog,
 }
 
 void DeicsOnzeGui::buildGuiReverb() {
+  if(!_deicsOnze->_pluginIReverb)
+    return;
   MusECore::PluginI* plugI = _deicsOnze->_pluginIReverb;
   QString name = plugI->name();
   name.resize(name.size()-2);
@@ -355,6 +357,8 @@ void DeicsOnzeGui::buildGuiReverb() {
 }
 
 void DeicsOnzeGui::buildGuiChorus() {
+  if(!_deicsOnze->_pluginIChorus)
+    return;
   MusECore::PluginI* plugI = _deicsOnze->_pluginIChorus;
   QString name = plugI->name();
   name.resize(name.size()-2);
-- 
cgit v1.2.3