From bf32fe9882d7dd1dd6fbb88f39a42371063b6cd6 Mon Sep 17 00:00:00 2001
From: "Tim E. Real" <termtech@rogers.com>
Date: Mon, 1 Nov 2010 08:36:22 +0000
Subject: All MESS plugins: compile with -fvisibility=hidden, fixes LADSPA
 plugins not appearing in list. Added simpledrums2 (from muse_qt4_evolution).

---
 muse2/synti/CMakeLists.txt                      |    3 +-
 muse2/synti/deicsonze/CMakeLists.txt            |    2 +-
 muse2/synti/deicsonze/deicsonze.cpp             |    5 +
 muse2/synti/deicsonze2/CMakeLists.txt           |    2 +-
 muse2/synti/deicsonze2/deicsonze.cpp            |    5 +
 muse2/synti/fluid/CMakeLists.txt                |    2 +-
 muse2/synti/fluid/fluid.cpp                     |    6 +
 muse2/synti/fluidsynth/CMakeLists.txt           |    2 +-
 muse2/synti/fluidsynth/fluidsynti.cpp           |    6 +
 muse2/synti/organ/CMakeLists.txt                |    2 +-
 muse2/synti/organ/organ.cpp                     |    7 +-
 muse2/synti/s1/CMakeLists.txt                   |    5 +-
 muse2/synti/s1/s1.cpp                           |    7 +-
 muse2/synti/simpledrums/CMakeLists.txt          |    2 +-
 muse2/synti/simpledrums/simpledrums.cpp         |    6 +
 muse2/synti/simpledrums2/CMakeLists.txt         |   52 +
 muse2/synti/simpledrums2/COPYING                |    3 +
 muse2/synti/simpledrums2/README                 |   43 +
 muse2/synti/simpledrums2/ReleaseNotes.txt       |   18 +
 muse2/synti/simpledrums2/common.h               |  110 ++
 muse2/synti/simpledrums2/simpledrums.cpp        | 1726 +++++++++++++++++++++++
 muse2/synti/simpledrums2/simpledrums.h          |  173 +++
 muse2/synti/simpledrums2/simpledrumsgui.cpp     |  890 ++++++++++++
 muse2/synti/simpledrums2/simpledrumsgui.h       |  214 +++
 muse2/synti/simpledrums2/simpledrumsguibase.ui  |   23 +
 muse2/synti/simpledrums2/ssplugin.cpp           |  460 ++++++
 muse2/synti/simpledrums2/ssplugin.h             |  173 +++
 muse2/synti/simpledrums2/sspluginchooserbase.ui |  106 ++
 muse2/synti/simpledrums2/ssplugingui.cpp        |  530 +++++++
 muse2/synti/simpledrums2/ssplugingui.h          |  204 +++
 muse2/synti/vam/CMakeLists.txt                  |    2 +-
 muse2/synti/vam/vam.cpp                         |    7 +-
 32 files changed, 4784 insertions(+), 12 deletions(-)
 create mode 100644 muse2/synti/simpledrums2/CMakeLists.txt
 create mode 100644 muse2/synti/simpledrums2/COPYING
 create mode 100644 muse2/synti/simpledrums2/README
 create mode 100644 muse2/synti/simpledrums2/ReleaseNotes.txt
 create mode 100644 muse2/synti/simpledrums2/common.h
 create mode 100644 muse2/synti/simpledrums2/simpledrums.cpp
 create mode 100644 muse2/synti/simpledrums2/simpledrums.h
 create mode 100644 muse2/synti/simpledrums2/simpledrumsgui.cpp
 create mode 100644 muse2/synti/simpledrums2/simpledrumsgui.h
 create mode 100644 muse2/synti/simpledrums2/simpledrumsguibase.ui
 create mode 100644 muse2/synti/simpledrums2/ssplugin.cpp
 create mode 100644 muse2/synti/simpledrums2/ssplugin.h
 create mode 100644 muse2/synti/simpledrums2/sspluginchooserbase.ui
 create mode 100644 muse2/synti/simpledrums2/ssplugingui.cpp
 create mode 100644 muse2/synti/simpledrums2/ssplugingui.h

(limited to 'muse2/synti')

diff --git a/muse2/synti/CMakeLists.txt b/muse2/synti/CMakeLists.txt
index b2bc87ea..1a7fd322 100644
--- a/muse2/synti/CMakeLists.txt
+++ b/muse2/synti/CMakeLists.txt
@@ -28,7 +28,8 @@ include_directories(
    )
 
 # set (SubDirs libsynti s1 organ deicsonze deicsonze2 simpledrums vam)
-set (SubDirs libsynti s1 organ deicsonze simpledrums vam)
+# set (SubDirs libsynti s1 organ deicsonze simpledrums vam)
+set (SubDirs libsynti s1 organ deicsonze simpledrums2 vam)
 
 if (HAVE_FLUIDSYNTH)
       set (SubDirs ${SubDirs} fluid fluidsynth )
diff --git a/muse2/synti/deicsonze/CMakeLists.txt b/muse2/synti/deicsonze/CMakeLists.txt
index a39b0e14..c9da5854 100644
--- a/muse2/synti/deicsonze/CMakeLists.txt
+++ b/muse2/synti/deicsonze/CMakeLists.txt
@@ -47,7 +47,7 @@ add_library ( deicsonze SHARED
 set_target_properties ( deicsonze
    PROPERTIES PREFIX ""
    #COMPILE_FLAGS "-O2 -include ${PROJECT_BINARY_DIR}/all-pic.h"
-   COMPILE_FLAGS "-DINSTPREFIX='\"${CMAKE_INSTALL_PREFIX}\"' -include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-fvisibility=hidden -DINSTPREFIX='\"${CMAKE_INSTALL_PREFIX}\"' -include ${PROJECT_BINARY_DIR}/all-pic.h"
    )
 
 target_link_libraries(deicsonze
diff --git a/muse2/synti/deicsonze/deicsonze.cpp b/muse2/synti/deicsonze/deicsonze.cpp
index 3dc5fafd..4eea4102 100644
--- a/muse2/synti/deicsonze/deicsonze.cpp
+++ b/muse2/synti/deicsonze/deicsonze.cpp
@@ -1660,7 +1660,12 @@ extern "C" {
 	MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
 	instantiate
     };
+    // We must compile with -fvisibility=hidden to avoid namespace
+    // conflicts with global variables.
+    // Only visible symbol is "mess_descriptor".
+    // (TODO: all plugins should be compiled this way)
 
+    __attribute__ ((visibility("default")))
     const MESS* mess_descriptor() { return &descriptor; }
 }
 
diff --git a/muse2/synti/deicsonze2/CMakeLists.txt b/muse2/synti/deicsonze2/CMakeLists.txt
index 430953ca..12f88212 100644
--- a/muse2/synti/deicsonze2/CMakeLists.txt
+++ b/muse2/synti/deicsonze2/CMakeLists.txt
@@ -46,7 +46,7 @@ target_link_libraries( deicsonze synti )
 set_target_properties ( deicsonze
    PROPERTIES PREFIX ""
    #COMPILE_FLAGS "-O2 -include ${PROJECT_BINARY_DIR}/all-pic.h"
-   COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h"
    )
 
 target_link_libraries(deicsonze
diff --git a/muse2/synti/deicsonze2/deicsonze.cpp b/muse2/synti/deicsonze2/deicsonze.cpp
index 28b9183e..74c1f56e 100644
--- a/muse2/synti/deicsonze2/deicsonze.cpp
+++ b/muse2/synti/deicsonze2/deicsonze.cpp
@@ -4350,7 +4350,12 @@ extern "C" {
 	MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
 	instantiate
     };
+    // We must compile with -fvisibility=hidden to avoid namespace
+    // conflicts with global variables.
+    // Only visible symbol is "mess_descriptor".
+    // (TODO: all plugins should be compiled this way)
 
+    __attribute__ ((visibility("default")))
     const MESS* mess_descriptor() { return &descriptor; }
 }
 
diff --git a/muse2/synti/fluid/CMakeLists.txt b/muse2/synti/fluid/CMakeLists.txt
index 38184550..0007537f 100644
--- a/muse2/synti/fluid/CMakeLists.txt
+++ b/muse2/synti/fluid/CMakeLists.txt
@@ -38,7 +38,7 @@ add_library ( fluid SHARED
 #
 set_target_properties ( fluid
    PROPERTIES PREFIX ""
-   COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h"
    LINK_FLAGS "${FLUIDSYN_LDFLAGS}"   # "-lfluidsynth"
    )
 target_link_libraries(fluid
diff --git a/muse2/synti/fluid/fluid.cpp b/muse2/synti/fluid/fluid.cpp
index a03be4de..13cfbef3 100644
--- a/muse2/synti/fluid/fluid.cpp
+++ b/muse2/synti/fluid/fluid.cpp
@@ -61,6 +61,12 @@ extern "C" {
             MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
             instantiate,
             };
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+  
+      __attribute__ ((visibility("default")))
       const MESS* mess_descriptor() { return &descriptor; }
       }
 
diff --git a/muse2/synti/fluidsynth/CMakeLists.txt b/muse2/synti/fluidsynth/CMakeLists.txt
index cdb298e2..0c3e1b97 100644
--- a/muse2/synti/fluidsynth/CMakeLists.txt
+++ b/muse2/synti/fluidsynth/CMakeLists.txt
@@ -38,7 +38,7 @@ add_library ( fluidsynth SHARED
 #
 set_target_properties ( fluidsynth 
    PROPERTIES PREFIX ""
-   COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h"
    LINK_FLAGS "${FLUIDSYN_LDFLAGS}"   # "-lfluidsynth"
    )
 
diff --git a/muse2/synti/fluidsynth/fluidsynti.cpp b/muse2/synti/fluidsynth/fluidsynti.cpp
index bf27a61c..bf12b7f8 100644
--- a/muse2/synti/fluidsynth/fluidsynti.cpp
+++ b/muse2/synti/fluidsynth/fluidsynti.cpp
@@ -1310,6 +1310,12 @@ extern "C"
             MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
             instantiate,
             };
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+  
+      __attribute__ ((visibility("default")))
       const MESS* mess_descriptor() { return &descriptor; }
       }
 
diff --git a/muse2/synti/organ/CMakeLists.txt b/muse2/synti/organ/CMakeLists.txt
index 8dd67aa8..40db20c1 100644
--- a/muse2/synti/organ/CMakeLists.txt
+++ b/muse2/synti/organ/CMakeLists.txt
@@ -40,7 +40,7 @@ add_library ( organ SHARED
 #
 set_target_properties ( organ
    PROPERTIES PREFIX ""
-   COMPILE_FLAGS "-O2 -include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-fvisibility=hidden -O2 -include ${PROJECT_BINARY_DIR}/all-pic.h"
    )
 
 target_link_libraries(organ
diff --git a/muse2/synti/organ/organ.cpp b/muse2/synti/organ/organ.cpp
index a1788a6c..2dede8de 100644
--- a/muse2/synti/organ/organ.cpp
+++ b/muse2/synti/organ/organ.cpp
@@ -704,7 +704,12 @@ extern "C" {
             MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
             instantiate,
             };
-
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+  
+      __attribute__ ((visibility("default")))
       const MESS* mess_descriptor() { return &descriptor; }
       }
 
diff --git a/muse2/synti/s1/CMakeLists.txt b/muse2/synti/s1/CMakeLists.txt
index 890c6b12..7dffe905 100644
--- a/muse2/synti/s1/CMakeLists.txt
+++ b/muse2/synti/s1/CMakeLists.txt
@@ -25,7 +25,10 @@ add_library ( s1 SHARED s1.cpp )
 # tell cmake to name target s1.so instead of 
 # libs1.so
 #
-set_target_properties ( s1 PROPERTIES PREFIX "" )
+set_target_properties ( s1 
+  PROPERTIES PREFIX "" 
+  COMPILE_FLAGS "-fvisibility=hidden"
+  )
 
 target_link_libraries(s1
       synti
diff --git a/muse2/synti/s1/s1.cpp b/muse2/synti/s1/s1.cpp
index c73615bd..8520a742 100644
--- a/muse2/synti/s1/s1.cpp
+++ b/muse2/synti/s1/s1.cpp
@@ -221,7 +221,12 @@ extern "C" {
             MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
             instantiate
             };
-
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+  
+      __attribute__ ((visibility("default")))
       const MESS* mess_descriptor() { return &descriptor; }
       }
 
diff --git a/muse2/synti/simpledrums/CMakeLists.txt b/muse2/synti/simpledrums/CMakeLists.txt
index 696389c6..6b015f2b 100644
--- a/muse2/synti/simpledrums/CMakeLists.txt
+++ b/muse2/synti/simpledrums/CMakeLists.txt
@@ -40,7 +40,7 @@ add_library ( simpledrums SHARED
 #
 set_target_properties ( simpledrums
    PROPERTIES PREFIX ""
-   COMPILE_FLAGS "-O6 -include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-O6 -fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h"
    )
 
 target_link_libraries(simpledrums
diff --git a/muse2/synti/simpledrums/simpledrums.cpp b/muse2/synti/simpledrums/simpledrums.cpp
index 5a0431a0..8bca91a4 100644
--- a/muse2/synti/simpledrums/simpledrums.cpp
+++ b/muse2/synti/simpledrums/simpledrums.cpp
@@ -1531,6 +1531,12 @@ extern "C"
             MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
             instantiate,
             };
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+
+      __attribute__ ((visibility("default")))
       const MESS* mess_descriptor() { return &descriptor; }
       }
 
diff --git a/muse2/synti/simpledrums2/CMakeLists.txt b/muse2/synti/simpledrums2/CMakeLists.txt
new file mode 100644
index 00000000..3c7ba3c7
--- /dev/null
+++ b/muse2/synti/simpledrums2/CMakeLists.txt
@@ -0,0 +1,52 @@
+#=============================================================================
+#  MusE
+#  Linux Music Editor
+#  $Id:$
+#
+#  Copyright (C) 2002-2006 by Werner Schweer and others
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License version 2.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#=============================================================================
+
+QT4_WRAP_CPP ( simpledrums_mocs simpledrumsgui.h ssplugingui.h )
+QT4_WRAP_UI (  simpledrums_uis simpledrumsguibase.ui sspluginchooserbase.ui )
+
+add_library ( simpledrums SHARED
+      simpledrums.cpp
+      simpledrumsgui.cpp
+      simpledrums.h
+      ssplugin.cpp
+      ssplugingui.cpp
+      ssplugin.h
+      common.h
+      ${simpledrums_mocs}
+      ${simpledrums_uis}
+      )
+
+# - tell cmake to name target simpledrums.so instead of
+#   libsimpledrums.so
+# - use precompiled header files
+#
+set_target_properties ( simpledrums
+   PROPERTIES PREFIX ""
+   COMPILE_FLAGS "-O6 -fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h"
+   )
+
+target_link_libraries(simpledrums
+      synti
+#      awl
+      ${QT_LIBRARIES}
+      )
+
+install_targets ( /${CMAKE_INSTALL_LIBDIR}/${MusE_INSTALL_NAME}/synthi/ simpledrums )
+
diff --git a/muse2/synti/simpledrums2/COPYING b/muse2/synti/simpledrums2/COPYING
new file mode 100644
index 00000000..5c3cefc2
--- /dev/null
+++ b/muse2/synti/simpledrums2/COPYING
@@ -0,0 +1,3 @@
+COPYING
+---------------------------------------
+This software is licensed under GNU GPL.
diff --git a/muse2/synti/simpledrums2/README b/muse2/synti/simpledrums2/README
new file mode 100644
index 00000000..468640b1
--- /dev/null
+++ b/muse2/synti/simpledrums2/README
@@ -0,0 +1,43 @@
+--------------------------------------
+Simpledrums v 0.2, by Mathias Lundgren
+--------------------------------------
+
+Simpledrums is a simple MESS-synth sampler (MusE Experimental Soft
+Synth) aiming at becoming a simple, tightly integrated sampler for
+MusE, specifically aimed at drumsamples.
+
+Features:
+- 16 channels/samples (1 sample/channel)
+- Simple controls for each individual channel: volume, balance, noteoff-ignore, channel on/off
+- Main volume
+- 4 LADSPA send-effects can be used, 4 effect taps for each individual channel
+- All channel parameters are controllable via the GUI, or by MusE:s controller handling (controller pane in pianoroll/drumeditor)
+- All effect parameters can be controlled via the GUI, or by Sysex messages (f.ex. turn effect on/off, modify effect parameters)
+- Complete synth state (fx-parameters, samples etc) is saved together with MusE project, and restored later when loaded
+- Samples automatically resampled when loaded (if needed)
+
+That's all folks!
+
+-------------
+Known issues:
+-------------
+- Not the prettiest gui in the world
+- All samples are read directly into memory (no caching)
+- Some obscure LADSPA-effects make SimpleSynth segfault
+- More...
+
+-------------
+Future plans:
+-------------
+- Fix all the known issues! ;-)
+- Sample loops
+- Sample offset variation w respect to note velocity
+- Treble/eq-controller for each individual channel
+- Treble level variation w respect to note velocity
+- More...
+
+Mathias Lundgren, (lunar_shuttle@users.sourceforge.net), 2004
+Plugin management code based on Werner Schweers plugin management handling for MusE
+
+(C) Copyright Mathias Lundgren, Werner Schweer 2000-2004
+Licensed under the GNU General Public License
diff --git a/muse2/synti/simpledrums2/ReleaseNotes.txt b/muse2/synti/simpledrums2/ReleaseNotes.txt
new file mode 100644
index 00000000..e0d633d8
--- /dev/null
+++ b/muse2/synti/simpledrums2/ReleaseNotes.txt
@@ -0,0 +1,18 @@
+RELEASE NOTES:
+--------------
+????-??-?? ver 0.2
+- Support for 4 LADSPA sendeffects added
+- Resampling of samples when loading (libsamplerate)
+- Synth state is saved to/restored from project file
+- Channel settings: balance, volume, effect tap for each sendeffect
+- Effect settings: all LADSPA parameters controllable and saved to MusE project, effect master volume, effect on/off
+- Support for mono + stereo samples
+- Support for stereo + mono LADSPA effects
+- Bugfixes, GUI-improvements etc...
+
+2004-11-09 ver 0.1
+- Simpledrums initial release
+- 16 channels (1 sample for each channel) with parameters: volume, balance, noteoff-ignore
+
+(C) Copyright Mathias Lundgren, Werner Schweer 2000-2004
+Licensed under the GNU General Public License
diff --git a/muse2/synti/simpledrums2/common.h b/muse2/synti/simpledrums2/common.h
new file mode 100644
index 00000000..e4763540
--- /dev/null
+++ b/muse2/synti/simpledrums2/common.h
@@ -0,0 +1,110 @@
+//
+// C++ Interface: common
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef __MUSE_TESTO_COMMON_H__
+#define __MUSE_TESTO_COMMON_H__
+
+#include "muse/midictrl.h"
+
+#define SS_VERSIONSTRING "1.0"
+
+#define SS_DEBUG        0
+#define SS_DEBUG_INIT   0
+#define SS_TRACE_FUNC   0
+#define SS_DEBUG_MIDI   0
+#define SS_DEBUG_LADSPA 0
+#define SS_DEBUG_STATE  0
+
+#define SS_DBG(string) if (SS_DEBUG) fprintf(stderr, "%s:%d:%s: %s\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string);
+#define SS_DBG2(string1, string2) if (SS_DEBUG) fprintf(stderr, "%s:%d:%s: %s: %s\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string1, string2);
+#define SS_DBG_I(string1, int) if (SS_DEBUG) fprintf(stderr, "%s:%d:%s: %s: %d\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string1, int);
+
+#define SS_TRACE_IN if (SS_TRACE_FUNC) fprintf (stderr, "->%s:%d\n", __PRETTY_FUNCTION__, __LINE__);
+#define SS_TRACE_OUT if (SS_TRACE_FUNC) fprintf (stderr, "<-%s:%d\n", __PRETTY_FUNCTION__, __LINE__);
+#define SS_ERROR(string) fprintf(stderr, "SimpleDrums error: %s\n", string)
+#define SS_DBG_LADSPA(string1) if (SS_DEBUG_LADSPA) fprintf(stderr, "%s:%d:%s: %s\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string1);
+#define SS_DBG_LADSPA2(string1, string2) if (SS_DEBUG_LADSPA) fprintf(stderr, "%s:%d:%s: %s: %s\n", __FILE__ , __LINE__ , __PRETTY_FUNCTION__, string1, string2);
+
+#define SS_SYSEX_INIT_DATA_VERSION           1
+
+#define SS_NR_OF_CHANNELS                   16
+#define SS_AUDIO_CHANNELS                    2
+#define SS_NR_OF_SENDEFFECTS                 4
+
+// Controller-related:
+#define SS_CHANNEL_CTRL_VOLUME 0
+#define SS_CHANNEL_CTRL_PAN    1
+#define SS_CHANNEL_CTRL_NOFF   2
+#define SS_CHANNEL_CTRL_ONOFF  3
+#define SS_CHANNEL_SENDFX1     4
+#define SS_CHANNEL_SENDFX2     5
+#define SS_CHANNEL_SENDFX3     6
+#define SS_CHANNEL_SENDFX4     7
+
+#define SS_PLUGIN_RETURN       0
+#define SS_PLUGIN_ONOFF        1
+
+#define SS_NR_OF_MASTER_CONTROLLERS          1
+#define SS_NR_OF_CHANNEL_CONTROLLERS         8
+#define SS_NR_OF_PLUGIN_CONTROLLERS          2
+
+#define SS_NR_OF_CONTROLLERS                 (SS_NR_OF_MASTER_CONTROLLERS + (SS_NR_OF_CHANNELS * SS_NR_OF_CHANNEL_CONTROLLERS) + (SS_NR_OF_PLUGIN_CONTROLLERS*SS_NR_OF_SENDEFFECTS))
+#define SS_FIRST_MASTER_CONTROLLER           CTRL_NRPN14_OFFSET
+#define SS_FIRST_CHANNEL_CONTROLLER          (SS_FIRST_MASTER_CONTROLLER + SS_NR_OF_MASTER_CONTROLLERS)
+#define SS_LAST_MASTER_CONTROLLER            (SS_FIRST_CHANNEL_CONTROLLER - 1)
+#define SS_LAST_CHANNEL_CONTROLLER           (SS_FIRST_CHANNEL_CONTROLLER -1 + (SS_NR_OF_CHANNEL_CONTROLLERS * SS_NR_OF_CHANNELS))
+
+#define SS_FIRST_PLUGIN_CONTROLLER           (SS_LAST_CHANNEL_CONTROLLER + 1)
+#define SS_LAST_PLUGIN_CONTROLLER            (SS_FIRST_PLUGIN_CONTROLLER -1 + SS_NR_OF_SENDEFFECTS*SS_NR_OF_PLUGIN_CONTROLLERS)
+
+#define SS_MASTER_CTRL_VOLUME                SS_FIRST_MASTER_CONTROLLER
+
+#define SS_CHANNEL_VOLUME_CONTROLLER(int)    (SS_FIRST_CHANNEL_CONTROLLER + (SS_NR_OF_CHANNEL_CONTROLLERS * int) + SS_CHANNEL_CTRL_VOLUME)
+#define SS_CHANNEL_PAN_CONTROLLER(int)       (SS_FIRST_CHANNEL_CONTROLLER + (SS_NR_OF_CHANNEL_CONTROLLERS * int) + SS_CHANNEL_CTRL_PAN)
+#define SS_CHANNEL_NOFF_CONTROLLER(int)      (SS_FIRST_CHANNEL_CONTROLLER + (SS_NR_OF_CHANNEL_CONTROLLERS * int) + SS_CHANNEL_CTRL_NOFF)
+#define SS_CHANNEL_ONOFF_CONTROLLER(int)     (SS_FIRST_CHANNEL_CONTROLLER + (SS_NR_OF_CHANNEL_CONTROLLERS * int) + SS_CHANNEL_CTRL_ONOFF)
+#define SS_CHANNEL_SENDFX_CONTROLLER(int1,int2) (SS_FIRST_CHANNEL_CONTROLLER + (SS_NR_OF_CHANNEL_CONTROLLERS * int1) + SS_CHANNEL_SENDFX1 + int2)
+
+#define SS_PLUGIN_RETURNLEVEL_CONTROLLER(int) (SS_FIRST_PLUGIN_CONTROLLER + (int * SS_NR_OF_PLUGIN_CONTROLLERS))
+#define SS_PLUGIN_ONOFF_CONTROLLER(int) (SS_FIRST_PLUGIN_CONTROLLER + (int * SS_NR_OF_PLUGIN_CONTROLLERS) + 1)
+
+#define SS_LOWEST_NOTE                       36
+#define SS_HIGHEST_NOTE                      (SS_LOWEST_NOTE + SS_NR_OF_CHANNELS)
+
+#define SS_PLUGIN_PARAM_MIN                  0
+#define SS_PLUGIN_PARAM_MAX                127
+
+typedef unsigned char byte;
+
+enum {
+      SS_SYSEX_LOAD_SAMPLE = 0,   // gui -> synth: tell synth to load sample
+      SS_SYSEX_INIT_DATA,         // synth reinitialization, the position of this (1) in the enum must not be changed since this value is written into proj file
+      SS_SYSEX_LOAD_SAMPLE_OK,    // synth -> gui: tell gui sample loaded OK
+      SS_SYSEX_LOAD_SAMPLE_ERROR, // synth -> gui: tell gui sample ! loaded OK
+      SS_SYSEX_CLEAR_SAMPLE,       // gui -> synth: tell synth to clear sample
+      SS_SYSEX_CLEAR_SAMPLE_OK,    // synth->gui: confirm sample cleared OK
+      SS_SYSEX_LOAD_SENDEFFECT,   // gui -> synth: tell synth to load laspa-effect
+      SS_SYSEX_LOAD_SENDEFFECT_OK,// synth->gui: plugin loaded ok
+      SS_SYSEX_LOAD_SENDEFFECT_ERROR, // synth->gui: plugin _not_ loaded ok
+      SS_SYSEX_CLEAR_SENDEFFECT,  // gui->synth: clear plugin
+      SS_SYSEX_CLEAR_SENDEFFECT_OK,// synth->gui: plugin cleared
+      SS_SYSEX_SET_PLUGIN_PARAMETER, //gui->synth: set plugin parameter
+      SS_SYSEX_SET_PLUGIN_PARAMETER_OK, // synth->gui: set plugin parameter (update gui)
+      SS_SYSEX_ERRORMSG,           // synth -> gui: general error message from synth
+      SS_SYSEX_GET_INIT_DATA,      // gui->synth: request init data
+      SS_SYSEX_SEND_INIT_DATA      // synth->gui: give gui init data
+      };
+
+extern int SS_samplerate;
+extern float SS_map_pluginparam2logdomain(int pluginparam_val);
+extern int SS_map_logdomain2pluginparam(float pluginparam_log);
+#endif
+
diff --git a/muse2/synti/simpledrums2/simpledrums.cpp b/muse2/synti/simpledrums2/simpledrums.cpp
new file mode 100644
index 00000000..242fd8dd
--- /dev/null
+++ b/muse2/synti/simpledrums2/simpledrums.cpp
@@ -0,0 +1,1726 @@
+//
+// C++ Implementation: simplesynth
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "muse/midictrl.h"
+#include "muse/midi.h"
+#include "libsynti/mpevent.h"
+#include "simpledrums.h"
+// #include <qstring.h>
+#include <samplerate.h>
+
+const char* SimpleSynth::synth_state_descr[] =
+      {
+      "SS_INITIALIZING",
+      "SS_LOADING_SAMPLE",
+      "SS_CLEARING_SAMPLE",
+      "SS_RUNNING"
+      };
+
+const char* SimpleSynth::channel_state_descr[] =
+      {
+      "SS_CHANNEL_INACTIVE",
+      "SS_SAMPLE_PLAYING"
+      };
+
+#define SWITCH_SYNTH_STATE(state)\
+synth_state = state; \
+if (SS_DEBUG_STATE) \
+      fprintf (stderr, "SS STATE: %s\n", SimpleSynth::synth_state_descr[state]);
+
+#define SWITCH_CHAN_STATE(ch, s)\
+channels[ch].state = s; \
+if (SS_DEBUG_STATE) \
+      fprintf (stderr, "SS CHAN %d STATE: %s\n", ch, SimpleSynth::channel_state_descr[s]);
+
+#define SS_CHANNEL_VOLUME_QUOT 100.0
+#define SS_MASTER_VOLUME_QUOT  100.0
+int SS_samplerate;
+
+#define SS_LOG_MAX   0
+#define SS_LOG_MIN -10
+#define SS_LOG_OFFSET SS_LOG_MIN
+
+
+//
+// Map plugin parameter on domain [SS_PLUGIN_PARAM_MIN, SS_PLUGIN_PARAM_MAX] to domain [SS_LOG_MIN, SS_LOG_MAX] (log domain)
+//
+float SS_map_pluginparam2logdomain(int pluginparam_val)
+      {
+      float scale = (float) (SS_LOG_MAX - SS_LOG_MIN)/ (float) SS_PLUGIN_PARAM_MAX;
+      float scaled = (float) pluginparam_val * scale;
+      float mapped = scaled + SS_LOG_OFFSET;
+      return mapped;
+      }
+//
+// Map plugin parameter on domain to domain [SS_LOG_MIN, SS_LOG_MAX] to [SS_PLUGIN_PARAM_MIN, SS_PLUGIN_PARAM_MAX]  (from log-> [0,127])
+// (inverse func to the above)
+int SS_map_logdomain2pluginparam(float pluginparam_log)
+      {
+      float mapped = pluginparam_log - SS_LOG_OFFSET;
+      float scale = (float) SS_PLUGIN_PARAM_MAX / (float) (SS_LOG_MAX - SS_LOG_MIN);
+      int scaled  = (int) round(mapped * scale);
+      return scaled;
+      }
+
+//---------------------------------------------------------
+//   SimpleSynth
+//---------------------------------------------------------
+SimpleSynth::SimpleSynth(int sr)
+      : Mess(SS_AUDIO_CHANNELS)
+      {
+      SS_TRACE_IN
+      SS_samplerate = sr;
+      SS_initPlugins();
+
+      simplesynth_ptr = this;
+      master_vol = 100.0 / SS_MASTER_VOLUME_QUOT;
+      master_vol_ctrlval = 100;
+
+      //initialize
+      for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
+            channels[i].sample = 0;
+            channels[i].playoffset = 0;
+            channels[i].noteoff_ignore = false;
+            channels[i].volume = (double) (100.0/SS_CHANNEL_VOLUME_QUOT );
+            channels[i].volume_ctrlval = 100;
+            channels[i].pan = 64;
+            channels[i].balanceFactorL = 1.0;
+            channels[i].balanceFactorR = 1.0;
+            SWITCH_CHAN_STATE(i, SS_CHANNEL_INACTIVE);
+            channels[i].channel_on = false;
+            for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
+                  channels[i].sendfxlevel[j] = 0.0;
+                  }
+            }
+
+      //Process buffer:
+      processBuffer[0] = new double[SS_PROCESS_BUFFER_SIZE]; //left
+      processBuffer[1] = new double[SS_PROCESS_BUFFER_SIZE]; //right
+
+      //Send effects
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            sendFxLineOut[i][0] = new float[SS_SENDFX_BUFFER_SIZE]; //left out
+            sendFxLineOut[i][1] = new float[SS_SENDFX_BUFFER_SIZE]; //right out
+            sendFxReturn[i][0]  = new float[SS_SENDFX_BUFFER_SIZE]; //left in
+            sendFxReturn[i][1]  = new float[SS_SENDFX_BUFFER_SIZE]; //right in
+            }
+
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            sendEffects[i].state       = SS_SENDFX_OFF;
+            sendEffects[i].plugin      = 0;
+            sendEffects[i].retgain     = 1.0;
+            sendEffects[i].retgain_ctrlval = 100;
+            sendEffects[i].nrofparameters = 0;
+            }
+
+      //Build controller list:
+      controllers[0].name = "Master volume";
+      controllers[0].num  = CTRL_NRPN14_OFFSET;
+      controllers[0].min  = 0;
+      controllers[0].max  = 127;
+
+      int i=1;
+      for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) {
+            QString c1 = "Channel " + QString::number(ch + 1) + " volume";
+            QString c2 = "Channel " + QString::number(ch + 1) + " pan";
+            QString c3 = "Channel " + QString::number(ch + 1) + " noteoff ignore";
+            QString c4 = "Channel " + QString::number(ch + 1) + " on/off";
+            QString c5 = "Channel " + QString::number(ch + 1) + " fx send 1";
+            QString c6 = "Channel " + QString::number(ch + 1) + " fx send 2";
+            QString c7 = "Channel " + QString::number(ch + 1) + " fx send 3";
+            QString c8 = "Channel " + QString::number(ch + 1) + " fx send 4";
+            controllers[i].name = c1.toLatin1().data();
+            controllers[i].num  = CTRL_NRPN14_OFFSET+i;
+            controllers[i].min  = 0;
+            controllers[i].max  = 127;
+
+            controllers[i+1].name = c2.toLatin1().data();
+            controllers[i+1].num  = CTRL_NRPN14_OFFSET+i+1;
+            controllers[i+1].min  = 0;
+            controllers[i+1].max  = 127;
+
+            controllers[i+2].name = c3.toLatin1().data();
+            controllers[i+2].num  = CTRL_NRPN14_OFFSET+i+2;
+            controllers[i+2].min  = 0;
+            controllers[i+2].max  = 1;
+
+            controllers[i+3].name = c4.toLatin1().data();
+            controllers[i+3].num  = CTRL_NRPN14_OFFSET+i+3;
+            controllers[i+3].min  = 0;
+            controllers[i+3].max  = 1;
+
+            controllers[i+4].name = c5.toLatin1().data();
+            controllers[i+4].num  = CTRL_NRPN14_OFFSET+i+4;
+
+            controllers[i+5].name = c6.toLatin1().data();
+            controllers[i+5].num  = CTRL_NRPN14_OFFSET+i+5;
+
+            controllers[i+6].name = c7.toLatin1().data();
+            controllers[i+6].num  = CTRL_NRPN14_OFFSET+i+6;
+
+            controllers[i+7].name = c8.toLatin1().data();
+            controllers[i+7].num  = CTRL_NRPN14_OFFSET+i+7;
+
+            controllers[i+4].min = controllers[i+5].min = controllers[i+6].min = controllers[i+7].min = 0;
+            controllers[i+4].max = controllers[i+5].max = controllers[i+6].max = controllers[i+7].max = 127;
+
+            i+=8;
+            }
+
+      for (int sfx=0; sfx<SS_NR_OF_SENDEFFECTS; sfx++) {
+            QString c1 = "Sendfx " + QString::number(sfx) + " ret gain";
+            QString c2 = "Sendfx " + QString::number(sfx) + " on/off";
+            controllers[i].name = c1.toLatin1().data();
+            controllers[i].num  = CTRL_NRPN14_OFFSET+i;
+            controllers[i].min  = 0;
+            controllers[i].max  = 127;
+
+            controllers[i+1].name = c2.toLatin1().data();
+            controllers[i+1].num  = CTRL_NRPN14_OFFSET+i+1;
+            controllers[i+1].min  = 0;
+            controllers[i+1].max  = 1;
+            i+=2;
+            }
+
+      pthread_mutex_init(&SS_LoaderMutex, NULL);
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   ~SimpleSynth
+//---------------------------------------------------------
+SimpleSynth::~SimpleSynth()
+      {
+      SS_TRACE_IN
+
+      // Cleanup channels and samples:
+      SS_DBG("Cleaning up sample data");
+      for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
+            if (channels[i].sample) {
+                  delete[] channels[i].sample->data;
+                  delete channels[i].sample;
+                  }
+            }
+      simplesynth_ptr = NULL;
+
+      SS_DBG("Deleting pluginlist");
+      //Cleanup plugins:
+      for (iPlugin i = plugins.begin(); i != plugins.end(); ++i) {
+            delete (*i);
+            }
+      plugins.clear();
+
+      SS_DBG("Deleting sendfx buffers");
+      //Delete sendfx buffers:
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            delete[] sendFxLineOut[i][0];
+            delete[] sendFxLineOut[i][1];
+            delete[] sendFxReturn[i][0];
+            delete[] sendFxReturn[i][1];
+            }
+
+      //processBuffer:
+      SS_DBG("Deleting process buffer");
+      delete[] processBuffer[0];
+      delete[] processBuffer[1];
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   guiVisible
+/*!
+    \fn SimpleSynth::guiVisible
+    \brief Tells if the gui is hidden or shown
+    \return true/false if gui is shown/hidden
+ */
+//---------------------------------------------------------
+bool SimpleSynth::guiVisible() const
+      {
+      SS_TRACE_IN
+      bool v = gui->isVisible();
+      SS_TRACE_OUT
+      return v;
+      }
+
+//---------------------------------------------------------
+//   hasGui
+/*!
+    \fn SimpleSynth::hasGui
+    \brief Tells if the synth has a gui or not
+    \return true if synth has gui, false it synth has no gui
+ */
+//---------------------------------------------------------
+bool SimpleSynth::hasGui() const
+      {
+      SS_TRACE_IN
+      SS_TRACE_OUT
+      return true;
+      }
+
+//---------------------------------------------------------
+//   playNote
+/*!
+    \fn SimpleSynth::playNote
+    \brief Triggers a note on (noteoffs are noteons with velo=0)
+    \param channel midi channel
+    \param pitch note pitch
+    \param velo note velocity
+    \return false for ok, true for not ok (not sure these are handled differently, but...)
+ */
+//---------------------------------------------------------
+bool SimpleSynth::playNote(int /*channel*/, int pitch, int velo)
+      {
+      SS_TRACE_IN
+      //Don't bother about channel, we're processing every playnote!
+      if ((pitch >= SS_LOWEST_NOTE) && (pitch <= SS_HIGHEST_NOTE)) {
+            bool noteOff = (velo == 0 ? 1 : 0);
+            int ch = pitch - SS_LOWEST_NOTE;
+            if(!noteOff) {
+                  if (channels[ch].sample) {
+                        //Turn on the white stuff:
+                        channels[ch].playoffset = 0;
+                        SWITCH_CHAN_STATE(ch , SS_SAMPLE_PLAYING);
+                        channels[ch].cur_velo = (double) velo / 127.0;
+                        channels[ch].gain_factor = channels[ch].cur_velo * channels[ch].volume;
+                        if (SS_DEBUG_MIDI) {
+                              printf("Playing note %d on channel %d\n", pitch, ch);
+                              }
+                        }
+                  }
+            else {
+                  //Note off:
+                  if (channels[ch].noteoff_ignore) {
+                        if (SS_DEBUG_MIDI) {
+                              printf("Note off on channel %d\n", ch);
+                              }
+                        SWITCH_CHAN_STATE(ch , SS_CHANNEL_INACTIVE);
+                        channels[ch].playoffset = 0;
+                        channels[ch].cur_velo = 0;
+                        }
+                  }
+            }
+      SS_TRACE_OUT
+      return false;
+      }
+
+//---------------------------------------------------------
+//   processEvent
+/*!
+    \fn SimpleSynth::processEvent
+    \brief All events from sequencer first shows up here and are forwarded to their correct functions
+    \param event The event sent from sequencer
+    \return false for ok, true for not ok
+ */
+//---------------------------------------------------------
+bool SimpleSynth::processEvent(const MidiPlayEvent& ev)
+      {
+      SS_TRACE_IN
+      switch(ev.type()) {
+            case ME_CONTROLLER:
+                  if (SS_DEBUG_MIDI) {
+                        printf("SimpleSynth::processEvent - Controller. Chan: %x dataA: %x dataB: %x\n", ev.channel(), ev.dataA(), ev.dataB());
+                        for (int i=0; i< ev.len(); i++)
+                              printf("%x ", ev.data()[i]);
+                        }
+                  setController(ev.channel(), ev.dataA(), ev.dataB(), false);
+                  return true;
+            case ME_NOTEON:
+                  return playNote(ev.channel(), ev.dataA(), ev.dataB());
+            case ME_NOTEOFF:
+                  return playNote(ev.channel(), ev.dataA(), 0);
+            case ME_SYSEX:
+                  //Debug print
+                  if (SS_DEBUG_MIDI) {
+                        printf("SimpleSynth::processEvent - Sysex received\n");
+                        for (int i=0; i< ev.len(); i++)
+                              printf("%x ", ev.data()[i]);
+                        printf("\n");
+                        }
+                  return sysex(ev.len(), ev.data());
+            }
+      return false;
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   setController
+/*!
+    \fn SimpleSynth::setController
+    \brief Called from sequencer indirectly via SimpleSynth::processEvent
+    \brief when the synth is supposed to set a controller value
+    \param channel channel nr
+    \param id controller id
+    \param val value of controller
+    \return false for ok, true for not ok
+ */
+//---------------------------------------------------------
+bool SimpleSynth::setController(int channel, int id, int val)
+      {
+      SS_TRACE_IN
+      if (SS_DEBUG_MIDI) {
+            printf("SimpleSynth::setController - received controller on channel %d, id %d value %d\n", channel, id, val);
+            }
+
+      // Channel controllers:
+      if (id >= SS_FIRST_CHANNEL_CONTROLLER && id <= SS_LAST_CHANNEL_CONTROLLER ) {
+            // Find out which channel we're dealing with:
+            id-= SS_FIRST_CHANNEL_CONTROLLER;
+            int ch = (id / SS_NR_OF_CHANNEL_CONTROLLERS);
+            id = (id % SS_NR_OF_CHANNEL_CONTROLLERS);
+
+            switch (id) {
+                  case SS_CHANNEL_CTRL_VOLUME:
+                        if (SS_DEBUG_MIDI)
+                              printf("Received channel ctrl volume %d for channel %d\n", val, ch);
+                        channels[ch].volume_ctrlval = val;
+                        updateVolume(ch, val);
+                        break;
+                  case SS_CHANNEL_CTRL_NOFF:
+                        if (SS_DEBUG_MIDI)
+                              printf("Received ctrl noff %d for channel %d\n", val, ch);
+                        channels[ch].noteoff_ignore = val;
+                        break;
+                  case SS_CHANNEL_CTRL_PAN:
+                        {
+                        if (SS_DEBUG_MIDI)
+                              printf("Received ctrl pan %d for channel %d\n", val, ch);
+                        channels[ch].pan = val;
+                        updateBalance(ch, val);
+                        break;
+                        }
+                  case SS_CHANNEL_CTRL_ONOFF:
+                        {
+                        if (SS_DEBUG_MIDI)
+                              printf("Received ctrl onoff %d for channel %d\n", val, ch);
+
+                        if (val == false && channels[ch].channel_on == true) {
+                              SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
+                              channels[ch].channel_on = val;
+                              }
+                        else if (val == true && channels[ch].channel_on == false) { // if it actually _was_ off:
+                              SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
+                              channels[ch].playoffset = 0;
+                              channels[ch].channel_on = val;
+                              }
+                        break;
+                        }
+                  case SS_CHANNEL_SENDFX1:
+                  case SS_CHANNEL_SENDFX2:
+                  case SS_CHANNEL_SENDFX3:
+                  case SS_CHANNEL_SENDFX4:
+                        {
+                        int fxid = id - SS_CHANNEL_SENDFX1;
+                        channels[ch].sendfxlevel[fxid] = (double)val/127.0;
+                        break;
+                        }
+
+                  default:
+                        if (SS_DEBUG_MIDI)
+                              printf("Unknown controller received for channel %d. id=%d\n", ch, id);
+                        break;
+                  }
+            }
+      // Master controllers:
+      else if (id >= SS_FIRST_MASTER_CONTROLLER && id <= SS_LAST_MASTER_CONTROLLER) {
+            if (SS_DEBUG_MIDI)
+                  printf("Mastervol controller received: %d\n", id);
+            master_vol_ctrlval = val;
+            master_vol = (double) master_vol_ctrlval / SS_MASTER_VOLUME_QUOT;
+            }
+      // Emmm, this one should've been there in the beginning
+      else if (id == CTRL_VOLUME) {
+            if (SS_DEBUG_MIDI) {
+                  printf("Ctrl volume received: vol: %d\n", val);
+                  }
+            master_vol_ctrlval = val;
+            master_vol = (double) master_vol_ctrlval / SS_MASTER_VOLUME_QUOT;
+            //This one can't be from the gui, update gui:
+            guiUpdateMasterVol(val);
+            }
+      // Plugin controllers:
+      else if (id >= SS_FIRST_PLUGIN_CONTROLLER && id <= SS_LAST_PLUGIN_CONTROLLER) {
+
+            int fxid = (id - SS_FIRST_PLUGIN_CONTROLLER) / SS_NR_OF_PLUGIN_CONTROLLERS;
+            int cmd = (id - SS_FIRST_PLUGIN_CONTROLLER) % SS_NR_OF_PLUGIN_CONTROLLERS;
+
+            // Plugin return-gain:
+            if (cmd == SS_PLUGIN_RETURN) {
+                  if (SS_DEBUG_MIDI)
+                        printf("Ctrl fx retgain received: fxid: %d val: %d\n", fxid, val);
+                  sendEffects[fxid].retgain_ctrlval = val;
+                  sendEffects[fxid].retgain = (double) val / 75.0;
+                  }
+            // Plugin on/off:
+            else if (cmd == SS_PLUGIN_ONOFF) {
+                  if (SS_DEBUG_MIDI)
+                        printf("Ctrl fx onoff received: fxid: %d val: %d\n", fxid, val);
+                  sendEffects[fxid].state = (SS_SendFXState) val;
+                  }
+            }
+      else {
+            if (SS_DEBUG_MIDI)
+                  printf("Unknown controller received: %d\n", id);
+            }
+      SS_TRACE_OUT
+      return false;
+      }
+
+//---------------------------------------------------------
+/*!
+    \fn SimpleSynth::setController
+ */
+//---------------------------------------------------------
+bool SimpleSynth::setController(int channel, int id, int val, bool /*fromGui*/)
+      {
+      SS_TRACE_IN
+      bool ret = setController(channel, id, val); //Perhaps TODO... Separate events from the gui
+      SS_TRACE_OUT
+      return ret;
+      }
+//---------------------------------------------------------
+//   sysex
+/*!
+    \fn SimpleSynth::sysex
+    \brief Called from sequencer indirectly via SimpleSynth::processEvent
+    \param len length of the sysex data
+    \param data the sysex data
+    \return false for ok, true for not ok
+*/
+//---------------------------------------------------------
+bool SimpleSynth::sysex(int /*len*/, const unsigned char* data)
+      {
+      SS_TRACE_IN
+      int cmd = data[0];
+      switch (cmd) {
+            case SS_SYSEX_LOAD_SAMPLE:
+                  {
+                  int channel = data[1];
+                  //int l = data[2];
+                  const char* filename = (const char*)(data+3);
+                  if (SS_DEBUG_MIDI) {
+                        printf("Sysex cmd: load sample, filename %s, on channel: %d\n", filename, channel);
+                        }
+                  loadSample(channel, filename);
+                  break;
+                  }
+            case SS_SYSEX_CLEAR_SAMPLE:
+                  {
+                  int ch = data[1];
+                  clearSample(ch);
+                  break;
+                  }
+
+            case SS_SYSEX_INIT_DATA:
+                  {
+                  parseInitData(data);
+                  break;
+                  }
+
+            case SS_SYSEX_LOAD_SENDEFFECT:
+                  {
+                  int fxid = data[1];
+                  QString lib = (const char*) (data + 2);
+                  QString label = (const char*) (data + lib.length() + 3);
+                  if (SS_DEBUG_MIDI) {
+                        printf("Sysex cmd load effect: %d %s %s\n", fxid, lib.toLatin1().data(), label.toLatin1().data());
+                        }
+                  initSendEffect(fxid, lib, label);
+                  break;
+                  }
+
+            case SS_SYSEX_CLEAR_SENDEFFECT:
+                  {
+                  int fxid = data[1];
+                  if (SS_DEBUG_MIDI) {
+                        printf("Sysex cmd clear effect: %d\n", fxid);
+                        }
+                  sendEffects[fxid].state = SS_SENDFX_OFF;
+                  cleanupPlugin(fxid);
+                  sendEffects[fxid].plugin = 0;
+                  break;
+                  }
+
+            case SS_SYSEX_SET_PLUGIN_PARAMETER:
+                  {
+                  int fxid = data[1];
+                  int parameter = data[2];
+                  int val = data[3];
+                  // Write it to the plugin:
+                  float floatval = sendEffects[fxid].plugin->convertGuiControlValue(parameter, val);
+                  setFxParameter(fxid, parameter, floatval);
+                  break;
+                  }
+
+            case SS_SYSEX_GET_INIT_DATA:
+                  {
+                  int initdata_len = 0;
+                  const byte* tmp_initdata = NULL;
+                  byte* event_data = NULL;
+
+                  getInitData(&initdata_len, &tmp_initdata);
+                  int totlen = initdata_len + 1;
+
+                  event_data = new byte[initdata_len + 1];
+                  event_data[0] = SS_SYSEX_SEND_INIT_DATA;
+                  memcpy(event_data + 1, tmp_initdata, initdata_len);
+                  delete[] tmp_initdata;
+                  tmp_initdata = NULL;
+
+                  MidiPlayEvent ev(0, 0, ME_SYSEX, event_data, totlen);
+                  gui->writeEvent(ev);
+                  delete[] event_data;
+
+                  break;
+                  }
+
+            default:
+                  if (SS_DEBUG_MIDI)
+                        printf("Unknown sysex cmd received: %d\n", cmd);
+                  break;
+            }
+      SS_TRACE_OUT
+      return false;
+      }
+
+//---------------------------------------------------------
+//   getPatchName
+/*!
+    \fn SimpleSynth::getPatchName
+    \brief Called from host to get names of patches
+    \param index - which patchnr we're about to deliver
+    \return const char* with patchname
+ */
+//---------------------------------------------------------
+const char* SimpleSynth::getPatchName(int /*index*/, int, int) const
+      {
+      SS_TRACE_IN
+      SS_TRACE_OUT
+      return 0;
+      }
+
+//---------------------------------------------------------
+//   getPatchInfo
+/*!
+    \fn SimpleSynth::getPatchInfo
+    \brief Called from host to get info about patches
+    \param index - which patchnr we're about to deliver
+    \param patch - if this one is 0, this is the first call, otherwise keep deliver the host patches... or something
+    \return MidiPatch with patch info for host
+ */
+//---------------------------------------------------------
+const MidiPatch* SimpleSynth::getPatchInfo(int index, const MidiPatch* patch) const
+      {
+      SS_TRACE_IN
+      index = 0; patch = 0;
+      SS_TRACE_OUT
+      return 0;
+      }
+
+//---------------------------------------------------------
+//   getControllerInfo
+/*!
+    \fn SimpleSynth::getControllerInfo
+    \brief Called from host to collect info about which controllers the synth supports
+    \param index current controller number
+    \param name pointer where name is stored
+    \param controller int pointer where muse controller number is stored
+    \param min int pointer where controller min value is stored
+    \param max int pointer where controller max value is stored
+    \return 0 when done, otherwise return next desired controller index
+ */
+//---------------------------------------------------------
+int SimpleSynth::getControllerInfo(int index, const char** name, int* controller, int* min, int* max)
+      {
+      SS_TRACE_IN
+      if (index >= SS_NR_OF_CONTROLLERS) {
+            SS_TRACE_OUT
+            return 0;
+            }
+
+      *name = controllers[index].name.c_str();
+      *controller = controllers[index].num;
+      *min = controllers[index].min;
+      *max = controllers[index].max;
+
+      if (SS_DEBUG_MIDI) {
+            printf("setting controller info: index %d name %s controller %d min %d max %d\n", index, *name, *controller, *min, *max);
+            }
+      SS_TRACE_OUT
+      return (index +1);
+      }
+
+//---------------------------------------------------------
+//   process
+/*!
+    \fn SimpleSynth::process
+    \brief Realtime function where the processing actually occurs
+    \param channels - audio data
+    \param offset - sample offset
+    \param len - nr of samples to process
+ */
+//---------------------------------------------------------
+void SimpleSynth::process(float** out, int offset, int len)
+      {
+      //Process messages from the gui
+      while (gui->fifoSize()) {
+            MidiPlayEvent ev = gui->readEvent();
+            if (ev.type() == ME_SYSEX) {
+                  sysex(ev.len(), ev.data());
+                  sendEvent(ev);
+                  }
+            else if (ev.type() == ME_CONTROLLER) {
+                  setController(ev.channel(), ev.dataA(), ev.dataB(), true);
+                  sendEvent(ev);
+                  }
+            else {
+                  if (SS_DEBUG)
+                        printf("SimpleSynth::process(): unknown event, type: %d\n", ev.type());
+                  }
+            }
+
+      if (synth_state == SS_RUNNING) {
+
+      //Temporary mix-doubles
+      double out1, out2;
+      //double ltemp, rtemp;
+      float* data;
+      // Velocity factor:
+      double gain_factor;
+
+
+      // Clear send-channels. Skips if fx not turned on
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            if (sendEffects[i].state == SS_SENDFX_ON) {
+                  memset(sendFxLineOut[i][0], 0, SS_SENDFX_BUFFER_SIZE * sizeof(float));
+                  memset(sendFxLineOut[i][1], 0, SS_SENDFX_BUFFER_SIZE * sizeof(float));
+                  }
+            }
+
+
+      memset(out[0] + offset, 0, len * sizeof(float));
+      memset(out[1] + offset, 0, len * sizeof(float));
+
+      //Process 1 channel at a time
+      for (int ch=0; ch < SS_NR_OF_CHANNELS; ch++) {
+            // If channels is turned off, skip:
+            if (channels[ch].channel_on == false)
+                  continue;
+
+            //If sample isn't playing, skip:
+            if (channels[ch].state == SS_SAMPLE_PLAYING) {
+                  memset(processBuffer[0], 0, SS_PROCESS_BUFFER_SIZE * sizeof(double));
+                  memset(processBuffer[1], 0, SS_PROCESS_BUFFER_SIZE * sizeof(double));
+
+                  for (int i=0; i<len; i++) {
+                        // Current channel sample data:
+                        data = channels[ch].sample->data;
+                        gain_factor = channels[ch].gain_factor;
+                        // Current velocity factor:
+
+                        if (channels[ch].sample->channels == 2) {
+                              //
+                              // Stereo sample:
+                              //
+                              // Add from sample:
+                              out1 = (double) (data[channels[ch].playoffset] * gain_factor * channels[ch].balanceFactorL);
+                              out2 = (double) (data[channels[ch].playoffset + 1] * gain_factor * channels[ch].balanceFactorR);
+                              channels[ch].playoffset += 2;
+                              }
+                        else {
+                              //
+                              // Mono sample:
+                              //
+                              out1 = (double) (data[channels[ch].playoffset] * gain_factor * channels[ch].balanceFactorL);
+                              out2 = (double) (data[channels[ch].playoffset] * gain_factor * channels[ch].balanceFactorR);
+                              channels[ch].playoffset++;
+                              }
+
+                        processBuffer[0][i] = out1;
+                        processBuffer[1][i] = out2;
+
+                        // If send-effects tap is on, tap signal to respective lineout channel
+                        for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
+                              if (channels[ch].sendfxlevel[j] != 0.0) {
+                                    //If the effect has 2 inputs (stereo in):
+                                    if (sendEffects[j].inputs == 2) {
+                                          sendFxLineOut[j][0][i]+= (out1 * channels[ch].sendfxlevel[j]);
+                                          sendFxLineOut[j][1][i]+= (out2 * channels[ch].sendfxlevel[j]);
+                                          }
+                                    //If the effect is mono (1 input), only use first fxLineOut
+                                    else if (sendEffects[j].inputs == 1) {
+                                          sendFxLineOut[j][0][i]+= ((out1 + out2) * channels[ch].sendfxlevel[j] / 2.0);
+                                          }
+                                    //Effects with 0 or >2 inputs are ignored
+                                    }
+                              }
+
+                        //
+                        // If we've reached the last sample, set state to inactive
+                        //
+                        if (channels[ch].playoffset >= channels[ch].sample->samples) {
+                              SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
+                              channels[ch].playoffset = 0;
+                              break;
+                              }
+                        }
+                        // Add contribution for this channel, for this frame, to final result:
+                        for (int i=0; i<len; i++) {
+                              out[0][i+offset]+=processBuffer[0][i];
+                              out[1][i+offset]+=processBuffer[1][i];
+                              }
+                  }
+            }
+            // Do something funny with the sendies:
+            for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
+                  if (sendEffects[j].state == SS_SENDFX_ON) {
+                        sendEffects[j].plugin->process(len);
+                        for (int i=0; i<len; i++) {
+                              //Effect has mono output:
+                              if (sendEffects[j].outputs == 1) {
+                                    //Add the result to both channels:
+                                    out[0][i+offset]+=((sendEffects[j].retgain * sendFxReturn[j][0][i]) / 2.0);
+                                    out[1][i+offset]+=((sendEffects[j].retgain * sendFxReturn[j][0][i]) / 2.0);
+                                    }
+                              else if (sendEffects[j].outputs == 2) {
+                                    // Effect has stereo output
+                                    out[0][i+offset]+=(sendEffects[j].retgain * sendFxReturn[j][0][i]);
+                                    out[1][i+offset]+=(sendEffects[j].retgain * sendFxReturn[j][1][i]);
+                                    }
+                              }
+                        }
+                  }
+            // Finally master gain:
+            for (int i=0; i<len; i++) {
+                  out[0][i+offset] = (out[0][i+offset] * master_vol);
+                  out[1][i+offset] = (out[1][i+offset] * master_vol);
+                  }
+            }
+      }
+
+//---------------------------------------------------------
+//   showGui
+/*!
+    \fn SimpleSynth::showGui
+    \brief Displays or hides the gui window
+    \param val true or false = gui shown or hidden
+ */
+//---------------------------------------------------------
+void SimpleSynth::showGui(bool val)
+      {
+      SS_TRACE_IN
+      gui->setShown(val);
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+/*!
+    \fn SimpleSynth::init
+    \brief Initializes the SimpleSynth
+    \param name string set to caption in the gui dialog
+    \return true if successful, false if unsuccessful
+ */
+//---------------------------------------------------------
+bool SimpleSynth::init(const char* name)
+      {
+      SS_TRACE_IN
+      SWITCH_SYNTH_STATE(SS_INITIALIZING);
+      gui = new SimpleSynthGui();
+      gui->show();
+      gui->setWindowTitle(name);
+      SWITCH_SYNTH_STATE(SS_RUNNING);
+      SS_TRACE_OUT
+      return true;
+      }
+
+//---------------------------------------------------------
+/*!
+    \fn SimpleSynth::getInitData
+    \brief Data for reinitialization of SimpleSynth when loading project
+    \param n - number of chars used in the data
+    \param data - data that is sent as a sysex to the synth on reload of project
+ */
+//---------------------------------------------------------
+void SimpleSynth::getInitData(int* n, const unsigned char** data)
+      {
+      SS_TRACE_IN
+      // Calculate length of data
+      // For each channel, we need to store volume, pan, noff, onoff
+      int len = SS_NR_OF_CHANNEL_CONTROLLERS * SS_NR_OF_CHANNELS;
+      // Sampledata: filenames len
+      for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
+            if (channels[i].sample) {
+                  int filenamelen = strlen(channels[i].sample->filename.c_str()) + 2;
+                  len+=filenamelen;
+                  }
+            else
+                  len++; //Add place for SS_NO_SAMPLE
+            }
+      len+=3; // 1 place for SS_SYSEX_INIT_DATA, 1 byte for master vol, 1 byte for version data
+
+      // Effect data length
+      len++; //Add place for SS_SYSEX_INIT_DATA_VERSION, as control
+
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            Plugin* plugin = sendEffects[i].plugin;
+            if (plugin) {
+                  int namelen = plugin->lib().size() + 2;
+                  int labelnamelen = plugin->label().size() + 2;
+                  len+=(namelen + labelnamelen);
+
+                  len+=3; //1 byte for nr of parameters, 1 byte for return gain, 1 byte for effect on/off
+                  len+=sendEffects[i].nrofparameters; // 1 byte for each parameter value
+                  }
+            else {
+                  len++; //place for SS_NO_PLUGIN
+                  }
+            }
+
+      // First, SS_SYSEX_INIT_DATA
+      byte* buffer = new byte[len];
+      memset(buffer, 0, len);
+      buffer[0] = SS_SYSEX_INIT_DATA;
+      buffer[1] = SS_SYSEX_INIT_DATA_VERSION;
+      if (SS_DEBUG_INIT) {
+            printf("Length of init data: %d\n", len);
+            printf("buffer[0] - SS_SYSEX_INIT_DATA: %d\n", SS_SYSEX_INIT_DATA);
+            printf("buffer[1] - SS_SYSEX_INIT_DATA_VERSION: %d\n", SS_SYSEX_INIT_DATA_VERSION);
+            }
+      int i = 2;
+      // All channels:
+      // 0       - volume ctrlval (0-127)
+      // 1       - pan (0-127)
+      // 2       - noff ignore (0-1)
+      // 3       - channel on/off (0-1)
+      // 4 - 7   - sendfx 1-4 (0-127)
+      // 8       - len of filename, n
+      // 9 - 9+n - filename
+      for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) {
+            buffer[i]   = (byte) channels[ch].volume_ctrlval;
+            buffer[i+1] = (byte) channels[ch].pan;
+            buffer[i+2] = (byte) channels[ch].noteoff_ignore;
+            buffer[i+3] = (byte) channels[ch].channel_on;
+            buffer[i+4] = (byte) round(channels[ch].sendfxlevel[0] * 127.0);
+            buffer[i+5] = (byte) round(channels[ch].sendfxlevel[1] * 127.0);
+            buffer[i+6] = (byte) round(channels[ch].sendfxlevel[2] * 127.0);
+            buffer[i+7] = (byte) round(channels[ch].sendfxlevel[3] * 127.0);
+
+            if (SS_DEBUG_INIT) {
+                  printf("Channel %d:\n", ch);
+                  printf("buffer[%d] - channels[ch].volume_ctrlval = \t%d\n", i, channels[ch].volume_ctrlval);
+                  printf("buffer[%d] - channels[ch].pan = \t\t%d\n", i+1, channels[ch].pan);
+                  printf("buffer[%d] - channels[ch].noteoff_ignore = \t%d\n", i+2, channels[ch].noteoff_ignore );
+                  printf("buffer[%d] - channels[ch].channel_on = \t%d\n", i+3, channels[ch].channel_on);
+                  for (int j= i+4; j < i+8; j++) {
+                        printf("buffer[%d] - channels[ch].sendfxlevel[%d]= \t%d\n", j, j-i-4, (int)round(channels[ch].sendfxlevel[j-i-4] * 127.0));
+                        }
+                  }
+            if (channels[ch].sample) {
+                  int filenamelen = strlen(channels[ch].sample->filename.c_str()) + 1;
+                  buffer[i+8] = (byte) filenamelen;
+                  memcpy((buffer+(i+9)), channels[ch].sample->filename.c_str(), filenamelen);
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d] - filenamelen: %d\n", i+8, filenamelen);
+                        printf("buffer[%d] - buffer[%d] - filename: ", (i+9), (i+9) + filenamelen - 1);
+                        for (int j = i+9; j< i+9+filenamelen; j++) {
+                              printf("%c",buffer[j]);
+                              }
+                        printf("\n");
+                        }
+                  i+= (SS_NR_OF_CHANNEL_CONTROLLERS + 1 + filenamelen);
+                  }
+            else {
+                  buffer[i+8] = SS_NO_SAMPLE;
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d]: SS_NO_SAMPLE: - %d\n", i+8, SS_NO_SAMPLE);
+                        }
+                  i+= (SS_NR_OF_CHANNEL_CONTROLLERS + 1);
+                  }
+            }
+      if (SS_DEBUG_INIT) {
+            printf("buffer[%d]: Master vol: - %d\n", i, master_vol_ctrlval);
+            }
+      buffer[i] = master_vol_ctrlval;
+      *(data) = buffer; *n = len;
+      i++;
+
+      //Send effects:
+      buffer[i] = SS_SYSEX_INIT_DATA_VERSION; //Just for check
+      if (SS_DEBUG_INIT) {
+            printf("buffer[%d]: Control value, SS_SYSEX_INIT_DATA_VERSION\n", i);
+            }
+
+      i++;
+      for (int j=0; j<SS_NR_OF_SENDEFFECTS; j++) {
+            if (sendEffects[j].plugin) {
+                  int labelnamelen = sendEffects[j].plugin->label().size() + 1;
+                  buffer[i] = labelnamelen;
+                  memcpy((buffer+i+1), sendEffects[j].plugin->label().toLatin1().data(), labelnamelen);
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d] - labelnamelen: %d\n", i, labelnamelen);
+                        printf("buffer[%d] - buffer[%d] - filename: ", (i+1), (i+1) + labelnamelen - 1);
+                        for (int k = i+1; k < i+1+labelnamelen; k++) {
+                              printf("%c",buffer[k]);
+                              }
+                        printf("\n");
+                        }
+
+                  i+=(labelnamelen + 1);
+
+                  int namelen = sendEffects[j].plugin->lib().size() + 1;
+                  buffer[i] = namelen;
+                  memcpy((buffer+i+1), sendEffects[j].plugin->lib().toLatin1().data(), namelen);
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d] - libnamelen : %d\n", i, namelen);
+                        printf("buffer[%d] - buffer[%d] - filename: ", (i+1), (i+1) + namelen - 1);
+                        for (int k = i+1; k < i+1+namelen; k++) {
+                              printf("%c",buffer[k]);
+                              }
+                        printf("\n");
+                        }
+
+                  i+=(namelen + 1);
+
+                  buffer[i]=sendEffects[j].nrofparameters;
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d]: sendEffects[%d].nrofparameters=%d\n", i, j, buffer[i]);
+                        }
+                  i++;
+
+                  buffer[i]=sendEffects[j].retgain_ctrlval;
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d]: sendEffects[%d].retgain_ctrlval=%d\n", i, j, buffer[i]);
+                        }
+                  i++;
+
+                  for (int k=0; k<sendEffects[j].nrofparameters; k++) {
+                        //TODO: Convert to 127-scale
+                        buffer[i] = sendEffects[j].plugin->getGuiControlValue(k);
+                        if (SS_DEBUG_INIT) {
+                              printf("buffer[%d]: sendEffects[%d].parameterval[%d]=%d\n", i, j, k, buffer[i]);
+                              }
+                        i++;
+                        }
+                  }
+            // No plugin loaded:
+            else {
+                  buffer[i] = SS_NO_PLUGIN;
+                  if (SS_DEBUG_INIT) {
+                        printf("buffer[%d]: SS_NO_PLUGIN\n", i);
+                        }
+                  i++;
+                  }
+            }
+
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::parseInitData()
+ */
+void SimpleSynth::parseInitData(const unsigned char* data)
+      {
+      SS_TRACE_IN
+      //int len = strlen((const char*)data);
+      if (SS_DEBUG_INIT) {
+            printf("buffer[1], SS_SYSEX_INIT_DATA_VERSION=%d\n", *(data+1));
+            }
+      const byte* ptr = data+2;
+      for (int ch=0; ch<SS_NR_OF_CHANNELS; ch++) {
+               channels[ch].volume_ctrlval = (byte) *(ptr);
+
+               if (SS_DEBUG_INIT) {
+                     printf("Channel %d:\n", ch);
+                     printf("buffer[%ld] - channels[ch].volume_ctrlval = \t%d\n", ptr-data, *ptr);
+                     printf("buffer[%ld] - channels[ch].pan = \t\t%d\n", ptr-data+1, *(ptr+1));
+                     printf("buffer[%ld] - channels[ch].noteoff_ignore = \t%d\n", ptr-data+2, *(ptr+2));
+                     printf("buffer[%ld] - channels[ch].channel_on = \t%d\n", ptr-data+3, *(ptr+3));
+                     }
+               updateVolume(ch, *(ptr));
+               guiUpdateVolume(ch, *(ptr));
+
+               channels[ch].pan = *(ptr+1);
+               updateBalance(ch, *(ptr+1));
+               guiUpdateBalance(ch, *(ptr+1));
+
+               channels[ch].noteoff_ignore = *(ptr+2);
+               guiUpdateNoff(ch, *(ptr+2));
+
+               channels[ch].channel_on = *(ptr+3);
+               guiUpdateChoff(ch, *(ptr+3));
+
+               ptr+=4;
+
+               for (int i=0; i<4; i++) {
+                     channels[ch].sendfxlevel[i] = (float) (*(ptr)/127.0);
+                     guiUpdateSendFxLevel(ch, i, *(ptr));
+                     ptr++;
+                     }
+
+               bool hasSample = *(ptr);
+               ptr++;
+
+               channels[ch].sample = 0;
+               channels[ch].playoffset = 0;
+               SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
+               if (SS_DEBUG_INIT) {
+                     printf("parseInitData: channel %d, volume: %f pan: %d bfL %f bfR %f chON %d s1: %f s2: %f s3: %f s4: %f\n",
+                              ch,
+                              channels[ch].volume,
+                              channels[ch].pan,
+                              channels[ch].balanceFactorL,
+                              channels[ch].balanceFactorR,
+                              channels[ch].channel_on,
+                              channels[ch].sendfxlevel[0],
+                              channels[ch].sendfxlevel[1],
+                              channels[ch].sendfxlevel[2],
+                              channels[ch].sendfxlevel[3]
+                              );
+                     }
+               if (hasSample) {
+                     std::string filenametmp = (const char*) ptr;
+                     ptr+= strlen(filenametmp.c_str()) + 1;
+                     //printf("We should load %s\n", filenametmp.c_str());
+                     loadSample(ch, filenametmp.c_str());
+                     }
+               else {
+                     //Clear sample
+                     clearSample(ch);
+                     guiNotifySampleCleared(ch);
+                     }
+               }
+      //Master vol:
+      master_vol_ctrlval = *(ptr);
+      master_vol = (double) master_vol_ctrlval / SS_MASTER_VOLUME_QUOT;
+      guiUpdateMasterVol(master_vol_ctrlval);
+      if (SS_DEBUG_INIT) {
+                  printf("Master vol: %d\n", master_vol_ctrlval);
+                  }
+      ptr++;
+
+      // Effects:
+      if (*(ptr) != SS_SYSEX_INIT_DATA_VERSION) {
+            fprintf(stderr, "Error loading init data - control byte not found. Skipping...\n");
+            SS_TRACE_OUT
+            return;
+            }
+      ptr++;
+
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            if (SS_DEBUG_INIT)
+                  printf("buffer[%ld] - sendeffect[%d], labelnamelen=%d\n", ptr-data, i, *ptr);
+            int labelnamelen = *(ptr);
+
+            if (labelnamelen != SS_NO_PLUGIN) {
+                  ptr++;
+                  std::string labelnametmp = (const char*) ptr;
+                  ptr+= labelnamelen;
+
+                  //int libnamelen = *(ptr);
+                  ptr++;
+                  std::string libnametmp = (const char*) ptr;
+                  ptr+= strlen(libnametmp.c_str()) + 1;
+
+
+                  initSendEffect(i, libnametmp.c_str(), labelnametmp.c_str());
+                  //initSendEffect(0, "cmt", "freeverb3");
+
+                  byte params = *(ptr);
+                  byte retgain = *(ptr+1);
+                  ptr+=2;
+
+                  sendEffects[i].nrofparameters = params;
+
+                  sendEffects[i].retgain_ctrlval = retgain;
+                  sendEffects[i].retgain = retgain;
+                  sendEffects[i].retgain = (double) retgain/ 75.0;
+                  MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_PLUGIN_RETURNLEVEL_CONTROLLER(i), retgain);
+                  gui->writeEvent(ev);
+
+                  for (int j=0; j<params; j++) {
+                        if (SS_DEBUG_INIT)
+                              printf("buffer[%ld] - sendeffect[%d], parameter[%d]=%d\n", ptr-data, i, j, *ptr);
+                        setFxParameter(i, j, sendEffects[i].plugin->convertGuiControlValue(j, *(ptr)));
+                        ptr++;
+                        }
+                  }
+            else {
+                  if (sendEffects[i].plugin)
+                        cleanupPlugin(i);
+                  ptr++;
+                  }
+            }
+
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SimpleSynth::loadSample(int chno, const char* filename)
+ */
+bool SimpleSynth::loadSample(int chno, const char* filename)
+      {
+      SS_TRACE_IN
+      SS_Channel* ch = &channels[chno];
+
+      // Thread stuff:
+      SS_SampleLoader* loader = new SS_SampleLoader;
+      loader->channel = ch;
+      loader->filename = std::string(filename);
+      loader->ch_no   = chno;
+      if (SS_DEBUG) {
+            printf("Loader filename is: %s\n", filename);
+            }
+      pthread_t sampleThread;
+      pthread_attr_t* attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
+      pthread_attr_init(attributes);
+      pthread_attr_setdetachstate(attributes, PTHREAD_CREATE_DETACHED);
+      if (pthread_create(&sampleThread, attributes, ::loadSampleThread, (void*) loader)) {
+            perror("creating thread failed:");
+            pthread_attr_destroy(attributes);
+            delete loader;
+            return false;
+            }
+
+      pthread_attr_destroy(attributes);
+      SS_TRACE_OUT
+      return true;
+      }
+
+/*!
+    \fn loadSampleThread(void* p)
+    \brief Since process needs to respond withing a certain time, loading of samples need to be done in a separate thread
+ */
+static void* loadSampleThread(void* p)
+      {
+      SS_TRACE_IN
+      pthread_mutex_lock(&SS_LoaderMutex);
+
+      // Crit section:
+      SS_State prevState = synth_state;
+      SWITCH_SYNTH_STATE(SS_LOADING_SAMPLE);
+      SS_SampleLoader* loader = (SS_SampleLoader*) p;
+      SS_Channel* ch = loader->channel;
+      int ch_no      = loader->ch_no;
+
+      if (ch->sample) {
+            delete[] ch->sample->data;
+            delete ch->sample;
+            }
+      ch->sample = new SS_Sample;
+      SS_Sample* smp = ch->sample;
+
+      SNDFILE* sf;
+      const char* filename = loader->filename.c_str();
+      SF_INFO sfi;
+
+      if (SS_DEBUG)
+            printf("loadSampleThread: filename = %s\n", filename);
+
+      sf = sf_open(filename, SFM_READ, &sfi);
+      if (sf == 0) {
+            fprintf(stderr,"Error opening file: %s\n", filename);
+            SWITCH_SYNTH_STATE(prevState);
+            simplesynth_ptr->guiSendSampleLoaded(false, loader->ch_no, filename);
+            delete ch->sample; ch->sample = 0;
+            delete loader;
+            pthread_mutex_unlock(&SS_LoaderMutex);
+            SS_TRACE_OUT
+            pthread_exit(0);
+            }
+
+      //Print some info:
+      if (SS_DEBUG) {
+            printf("Sample info:\n");
+            printf("Frames: \t%ld\n", (long) sfi.frames);
+            printf("Channels: \t%d\n", sfi.channels);
+            printf("Samplerate: \t%d\n", sfi.samplerate);
+            }
+
+      //
+      // Allocate and read the thingie
+      //
+
+      // If current samplerate is the same as MusE's:
+      if (SS_samplerate == sfi.samplerate) {
+            smp->data = new float[sfi.channels * sfi.frames];
+            sf_count_t n = sf_readf_float(sf, smp->data, sfi.frames);
+            smp->frames = sfi.frames;
+            smp->samples = (n * sfi.channels);
+            smp->channels = sfi.channels;
+            if (SS_DEBUG) {
+                  printf("%ld frames read\n", (long) n);
+                  }
+            }
+      else  // otherwise, resample:
+      {
+            smp->channels = sfi.channels;
+            // Get new nr of frames:
+            double srcratio = (double) SS_samplerate/ (double) sfi.samplerate;
+            smp->frames = (long) floor(((double) sfi.frames * srcratio));
+            smp->frames = (sfi.channels == 1 ? smp->frames * 2 : smp->frames ); // Double nr of new frames if mono->stereo
+            smp->samples = smp->frames * smp->channels;
+
+            if (SS_DEBUG) {
+                  printf("Resampling from %ld frames to %ld frames - srcration: %lf\n", sfi.frames, smp->frames, srcratio);
+                  printf("Nr of new samples: %ld\n", smp->samples);
+                  }
+
+            // Read to temporary:
+            float temp[sfi.frames * sfi.channels];
+            int frames_read = sf_readf_float(sf, temp, sfi.frames);
+            if (frames_read != sfi.frames) {
+                  fprintf(stderr,"Error reading sample %s\n", filename);
+                  simplesynth_ptr->guiSendSampleLoaded(false, loader->ch_no, filename);
+                  sf_close(sf);
+                  SWITCH_SYNTH_STATE(prevState);
+                  delete ch->sample; ch->sample = 0;
+                  delete loader;
+                  pthread_mutex_unlock(&SS_LoaderMutex);
+                  pthread_exit(0);
+                  SS_TRACE_OUT
+                  }
+
+            // Allocate mem for the new one
+            smp->data = new float[smp->frames * smp->channels];
+            memset(smp->data, 0, sizeof(float)* smp->frames * smp->channels);
+
+            // libsamplerate & co (secret rabbits in the code!)
+            SRC_DATA srcdata;
+            srcdata.data_in  = temp;
+            srcdata.data_out = smp->data;
+            srcdata.input_frames  = sfi.frames;
+            srcdata.output_frames = smp->frames;
+            srcdata.src_ratio = (double) SS_samplerate / (double) sfi.samplerate;
+
+            if (SS_DEBUG) {
+                  printf("Converting sample....\n");
+                  }
+
+            if (src_simple(&srcdata, SRC_SINC_BEST_QUALITY, sfi.channels)) {
+                  SS_ERROR("Error when resampling, ignoring current sample");
+                  //TODO: deallocate and stuff
+                  }
+            else if (SS_DEBUG) {
+                  printf("Sample converted. %ld input frames used, %ld output frames generated\n",
+                           srcdata.input_frames_used,
+                           srcdata.output_frames_gen);
+                  }
+         }
+      //Just close the dam thing
+      sf_close(sf);
+      SWITCH_SYNTH_STATE(prevState);
+      ch->sample->filename = loader->filename;
+      simplesynth_ptr->guiSendSampleLoaded(true, ch_no, filename);
+      delete loader;
+      pthread_mutex_unlock(&SS_LoaderMutex);
+      SS_TRACE_OUT
+      pthread_exit(0);
+      }
+
+
+//static Mess* instantiate(int sr, const char* name)
+static Mess* instantiate(int sr, QWidget*, QString* projectPathPtr, const char* name)
+      {
+      printf("SimpleSynth sampleRate %d\n", sr);
+      SimpleSynth* synth = new SimpleSynth(sr);
+      if (!synth->init(name)) {
+            delete synth;
+            synth = 0;
+            }
+      return synth;
+      }
+
+
+/*!
+    \fn SimpleSynth::updateBalance(int pan)
+ */
+void SimpleSynth::updateBalance(int ch, int val)
+      {
+      SS_TRACE_IN
+      channels[ch].pan = val;
+
+      // Balance:
+      channels[ch].balanceFactorL = 1.0;
+      channels[ch].balanceFactorR = 1.0;
+      double offset = 0;
+      int dev = val - 64;
+      offset = (double) dev / 64.0;
+      if (offset < 0) {
+            channels[ch].balanceFactorR = 1.0 + offset;
+            }
+      else {
+            channels[ch].balanceFactorL = 1.0 - offset;
+            }
+
+      if (SS_DEBUG_MIDI)
+            printf("balanceFactorL %f balanceFactorR %f\n", channels[ch].balanceFactorL, channels[ch].balanceFactorR);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::updateVolume(int invol_ctrlval)
+ */
+void SimpleSynth::updateVolume(int ch, int invol_ctrlval)
+      {
+      SS_TRACE_IN
+      channels[ch].volume = (double)invol_ctrlval/ (double) SS_CHANNEL_VOLUME_QUOT;
+      channels[ch].volume_ctrlval = invol_ctrlval;
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiUpdateBalance(int ch, int bal)
+ */
+void SimpleSynth::guiUpdateBalance(int ch, int bal)
+      {
+      SS_TRACE_IN
+      MidiPlayEvent ev(0, 0, ch, ME_CONTROLLER, SS_CHANNEL_PAN_CONTROLLER(ch), bal);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiUpdateVolume(int ch, int val)
+ */
+void SimpleSynth::guiUpdateVolume(int ch, int val)
+      {
+      SS_TRACE_IN
+      MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_VOLUME_CONTROLLER(ch), val);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiUpdateNoff(bool b)
+ */
+void SimpleSynth::guiUpdateNoff(int ch, bool b)
+      {
+      SS_TRACE_IN
+      MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_NOFF_CONTROLLER(ch), b);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiUpdateChoff(int ch, bool b)
+ */
+void SimpleSynth::guiUpdateChoff(int ch, bool b)
+      {
+      SS_TRACE_IN
+      MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_ONOFF_CONTROLLER(ch), b);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiUpdateMasterVol(int val)
+ */
+void SimpleSynth::guiUpdateMasterVol(int val)
+      {
+      SS_TRACE_IN
+      MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_MASTER_CTRL_VOLUME, val);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SimpleSynth::guiUpdateSendFxLevel(int fxid, int level)
+ */
+void SimpleSynth::guiUpdateSendFxLevel(int channel, int fxid, int level)
+      {
+      SS_TRACE_IN
+      MidiPlayEvent ev(0, 0, 0, ME_CONTROLLER, SS_CHANNEL_SENDFX_CONTROLLER(channel, fxid), level);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiSendSampleLoaded(int ch, const char* filename)
+ */
+void SimpleSynth::guiSendSampleLoaded(bool success, int ch, const char* filename)
+      {
+      SS_TRACE_IN
+      int len = strlen(filename) + 3; //2 + filenamelen + 1;
+      byte out[len];
+
+      if (success) {
+            out[0] = SS_SYSEX_LOAD_SAMPLE_OK;
+            }
+      else {
+            out[0] = SS_SYSEX_LOAD_SAMPLE_ERROR;
+            }
+      out[1] = ch;
+      memcpy(out+2, filename, strlen(filename)+1);
+      MidiPlayEvent ev(0, 0, ME_SYSEX, out, len);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiSendError(const char* errorstring)
+ */
+void SimpleSynth::guiSendError(const char* errorstring)
+      {
+      SS_TRACE_IN
+      byte out[strlen(errorstring)+2];
+      out[0] = SS_SYSEX_ERRORMSG;
+      memcpy(out+1, errorstring, strlen(errorstring) +1);
+      SS_TRACE_OUT
+      }
+
+extern "C"
+      {
+      static MESS descriptor = {
+            "SimpleSynth",
+            "Mathias Lundgren (lunar_shuttle@users.sf.net)",
+            "0.1",      //Version string
+            MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
+            instantiate,
+            };
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+
+      __attribute__ ((visibility("default")))
+      const MESS* mess_descriptor() { return &descriptor; }
+      }
+
+
+/*!
+    \fn SimpleSynth::initSendEffect(int sendeffectid, QString lib, QString name)
+ */
+bool SimpleSynth::initSendEffect(int id, QString lib, QString name)
+      {
+      SS_TRACE_IN
+      bool success = false;
+      if (sendEffects[id].plugin) {
+            //Cleanup if one was already there:
+            cleanupPlugin(id);
+            }
+      sendEffects[id].plugin  = (LadspaPlugin*) plugins.find(lib, name);
+      LadspaPlugin* plugin = sendEffects[id].plugin;
+      if (plugin) { //We found one
+
+            sendEffects[id].inputs  = plugin->inports();
+            sendEffects[id].outputs = plugin->outports();
+
+            if (plugin->instantiate()) {
+                  SS_DBG2("Plugin instantiated", name.toLatin1().data());
+                  SS_DBG_I("Parameters", plugin->parameter());
+                  SS_DBG_I("No of inputs", plugin->inports());
+                  SS_DBG_I("No of outputs",plugin->outports());
+                  SS_DBG_I("Inplace-capable", plugin->inPlaceCapable());
+
+                  // Connect inputs/outputs:
+                  // If single output/input, only use first channel in sendFxLineOut/sendFxReturn
+                  SS_DBG("Connecting ports...");
+                  plugin->connectInport(0, sendFxLineOut[id][0]);
+                  if (plugin->inports() == 2)
+                        plugin->connectInport(1, sendFxLineOut[id][1]);
+                  else if (plugin->inports() > 2) {
+                        fprintf(stderr, "Plugin has more than 2 inputs, not supported\n");
+                        }
+
+                  plugin->connectOutport(0, sendFxReturn[id][0]);
+                  if (plugin->outports() == 2)
+                        plugin->connectOutport(1, sendFxReturn[id][1]);
+                  else if (plugin->outports() > 2) {
+                        fprintf(stderr, "Plugin has more than 2 outputs, not supported\n");
+                        }
+                  SS_DBG("Ports connected");
+                  if (plugin->start()) {
+                        sendEffects[id].state = SS_SENDFX_ON;
+                        success = true;
+
+                        int n = plugin->parameter();
+                        sendEffects[id].nrofparameters = n;
+
+                        // This is not nice, but freeverb doesn't want to play until some values are set:
+                        if (name == "freeverb3") {
+                              setFxParameter(id, 2, 0.5);
+                              setFxParameter(id, 3, 0.5);
+                              setFxParameter(id, 4, 0.5);
+                              guiUpdateFxParameter(id, 2, 0.5);
+                              guiUpdateFxParameter(id, 3, 0.5);
+                              guiUpdateFxParameter(id, 4, 0.5);
+                              }
+                        }
+                  //TODO: cleanup if failed
+                  }
+            }
+      //Notify gui
+      int len = 3;
+      byte out[len];
+      out[0] = SS_SYSEX_LOAD_SENDEFFECT_OK;
+      out[1] = id;
+      int j=0;
+      for (iPlugin i = plugins.begin(); i!=plugins.end(); i++, j++) {
+            if ((*i)->lib() == plugin->lib() && (*i)->label() == plugin->label()) {
+                  out[2] = j;
+                  MidiPlayEvent ev(0, 0, ME_SYSEX, out, len);
+                  gui->writeEvent(ev);
+                  }
+            }
+
+      if (!success) {
+            QString errorString = "Error loading plugin \"" + plugin->label() + "\"";
+            guiSendError(errorString.toLatin1().data());
+            }
+      return success;
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::setSendFxLevel(int channel, int effectid, double val)
+ */
+void SimpleSynth::setSendFxLevel(int channel, int effectid, double val)
+      {
+      SS_TRACE_IN
+      channels[channel].sendfxlevel[effectid] = val;
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::cleanupPlugin(int id)
+ */
+void SimpleSynth::cleanupPlugin(int id)
+      {
+      SS_TRACE_IN
+      LadspaPlugin* plugin = sendEffects[id].plugin;
+      plugin->stop();
+      SS_DBG2("Stopped fx", plugin->label().toLatin1().data());
+      sendEffects[id].nrofparameters = 0;
+      sendEffects[id].state = SS_SENDFX_OFF;
+      sendEffects[id].plugin = 0;
+
+      byte d[2];
+      d[0] = SS_SYSEX_CLEAR_SENDEFFECT_OK;
+      d[1] = id;
+      MidiPlayEvent ev(0, 0, ME_SYSEX, d, 2);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::setFxParameter(int fxid, int param, float val)
+    \brief Set fx-parameter on plugin and notify gui
+ */
+void SimpleSynth::setFxParameter(int fxid, int param, float val)
+      {
+      SS_TRACE_IN
+      LadspaPlugin* plugin = sendEffects[fxid].plugin;
+      if (SS_DEBUG_LADSPA) {
+            printf("Setting fx parameter: %f\n", val);
+            }
+      plugin->setParam(param, val);
+      //sendEffects[fxid].parameter[param] = val;
+      //guiUpdateFxParameter(fxid, param, val);
+      SS_TRACE_OUT
+      }
+
+
+
+/*!
+    \fn SimpleSynth::guiUpdateFxParameter(int fxid, int param, float val)
+    \brief Notify gui of changed fx-parameter
+ */
+void SimpleSynth::guiUpdateFxParameter(int fxid, int param, float val)
+      {
+      SS_TRACE_IN
+      LadspaPlugin* plugin = sendEffects[fxid].plugin;
+      float min, max;
+      plugin->range(param, &min, &max);
+      //offset:
+      val-= min;
+
+      int intval = plugin->getGuiControlValue(param);
+      /*if (plugin->isLog(param)) {
+            intval = SS_map_logdomain2pluginparam(logf(val/(max - min) + min));
+            }
+      else if (plugin->isBool(param)) {
+            intval = (int) val;
+            }
+      else {
+            float scale = SS_PLUGIN_PARAM_MAX / (max - min);
+            intval = (int) ((val - min) * scale);
+            }*/
+      if (SS_DEBUG_MIDI) {
+            printf("Updating gui, fx parameter. fxid=%d, param=%d val=%d\n", fxid, param, intval);
+            }
+
+      byte d[4];
+      d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER_OK;
+      d[1] = fxid;
+      d[2] = param;
+      d[3] = intval;
+      MidiPlayEvent ev(0, 0, ME_SYSEX, d, 4);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::clearSample(int ch)
+    \brief Clears a sample (actually clears a channel)
+ */
+void SimpleSynth::clearSample(int ch)
+      {
+      SS_TRACE_IN
+      if (channels[ch].sample) {
+            if (SS_DEBUG)
+                  printf("Clearing sample on channel %d\n", ch);
+            SS_State prevstate = synth_state;
+            SWITCH_CHAN_STATE(ch, SS_CHANNEL_INACTIVE);
+            SWITCH_SYNTH_STATE(SS_CLEARING_SAMPLE);
+            if (channels[ch].sample->data) {
+                  delete[] channels[ch].sample->data;
+                  channels[ch].sample->data = 0;
+                  }
+            if (channels[ch].sample) {
+                  delete channels[ch].sample;
+                  channels[ch].sample = 0;
+                  }
+            SWITCH_SYNTH_STATE(prevstate);
+            guiNotifySampleCleared(ch);
+            if (SS_DEBUG) {
+                  printf("Clear sample - sample cleared on channel %d\n", ch);
+                  }
+            }
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynth::guiNotifySampleCleared(int ch)
+ */
+void SimpleSynth::guiNotifySampleCleared(int ch)
+      {
+      SS_TRACE_IN
+      byte d[2];
+      d[0] = SS_SYSEX_CLEAR_SAMPLE_OK;
+      d[1] = (byte) ch;
+      MidiPlayEvent ev(0, 0, ME_SYSEX, d, 2);
+      gui->writeEvent(ev);
+      SS_TRACE_OUT
+      }
diff --git a/muse2/synti/simpledrums2/simpledrums.h b/muse2/synti/simpledrums2/simpledrums.h
new file mode 100644
index 00000000..f9463800
--- /dev/null
+++ b/muse2/synti/simpledrums2/simpledrums.h
@@ -0,0 +1,173 @@
+//
+// C++ Interface: simplesynth
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef SIMPLESYNTH_H
+#define SIMPLESYNTH_H
+
+#include <sndfile.h>
+#include "libsynti/mess.h"
+#include "common.h"
+#include "libsynti/mpevent.h"
+#include "simpledrumsgui.h"
+#include "ssplugin.h"
+
+#define SS_NO_SAMPLE       0
+#define SS_NO_PLUGIN       0
+
+#define SS_PROCESS_BUFFER_SIZE 4096 //TODO: Add initialization method for nr of frames in each process from MusE - if nr of frames > than this, this will fail
+#define SS_SENDFX_BUFFER_SIZE  SS_PROCESS_BUFFER_SIZE
+
+enum SS_ChannelState
+   {
+      SS_CHANNEL_INACTIVE=0,
+      SS_SAMPLE_PLAYING,
+   };
+
+enum SS_State
+   {
+      SS_INITIALIZING=0,
+      SS_LOADING_SAMPLE,
+      SS_CLEARING_SAMPLE,
+      SS_RUNNING,
+   };
+
+enum SS_SendFXState
+   {
+      SS_SENDFX_OFF=0,
+      SS_SENDFX_ON
+   };
+
+struct SS_SendFx
+   {
+      SS_SendFXState state;
+      LadspaPlugin*  plugin;
+      int            inputs;
+      int            outputs;
+      int            retgain_ctrlval;
+      double         retgain;
+      int            nrofparameters;
+   };
+
+struct SS_Sample
+   {
+      float*      data;
+      int         samplerate;
+      int         bits;
+      std::string filename;
+      long        samples;
+      long        frames;
+      int         channels;
+      SF_INFO     sfinfo;
+   };
+
+struct SS_Channel
+   {
+      SS_ChannelState state;
+      const char*     name;
+      SS_Sample*      sample;
+      int             playoffset;
+      bool            noteoff_ignore;
+
+      double          volume;
+      int             volume_ctrlval;
+
+      double          cur_velo;
+      double          gain_factor;
+
+      int             pan;
+      double          balanceFactorL;
+      double          balanceFactorR;
+
+      bool            channel_on;
+
+      //Send fx:
+      double          sendfxlevel[SS_NR_OF_SENDEFFECTS];
+   };
+
+struct SS_Controller
+   {
+      std::string name;
+      int num;
+      int min, max;
+   };
+
+struct SS_SampleLoader
+   {
+      SS_Channel*  channel;
+      std::string  filename;
+      int          ch_no;
+   };
+
+class SimpleSynth : public Mess
+   {
+   public:
+      SimpleSynth(int);
+
+      virtual ~SimpleSynth();
+
+      virtual bool guiVisible() const;
+      virtual bool hasGui() const;
+      virtual bool playNote(int arg1, int arg2, int arg3);
+      virtual bool processEvent(const MidiPlayEvent& arg1);
+      virtual bool setController(int arg1, int arg2, int arg3);
+      virtual bool sysex(int arg1, const unsigned char* arg2);
+      virtual const char* getPatchName(int arg1, int arg2, int arg3) const;
+      virtual const MidiPatch* getPatchInfo(int arg1, const MidiPatch* arg2) const;
+      virtual int getControllerInfo(int arg1, const char** arg2, int* arg3, int* arg4, int* arg5);
+      virtual void process(float** data, int offset, int len);
+      virtual void showGui(bool arg1);
+      virtual void getInitData(int*, const unsigned char**);
+      bool init(const char* name);
+      void guiSendSampleLoaded(bool success, int ch, const char* filename);
+      void guiSendError(const char* errorstring);
+
+      static const char* synth_state_descr[];
+      static const char* channel_state_descr[];
+
+private:
+      SimpleSynthGui* gui;
+
+      SS_Channel channels[SS_NR_OF_CHANNELS];
+      SS_Controller controllers[SS_NR_OF_CONTROLLERS];
+      bool setController(int channel, int id, int val, bool fromGui);
+      bool loadSample(int ch_no, const char* filename);
+      void parseInitData(const unsigned char* data);
+      void updateVolume(int ch, int in_volume_ctrlval);
+      void updateBalance(int ch, int pan);
+      void guiNotifySampleCleared(int ch);
+      void guiUpdateBalance(int ch, int bal);
+      void guiUpdateVolume(int ch, int val);
+      void guiUpdateNoff(int ch, bool b);
+      void guiUpdateChoff(int ch, bool b);
+      void guiUpdateMasterVol(int val);
+      void guiUpdateFxParameter(int fxid, int param, float val);
+      void guiUpdateSendFxLevel(int channel, int fxid, int level);
+      bool initSendEffect(int sendeffectid, QString lib, QString name);
+      void setSendFxLevel(int channel, int effectid, double val);
+      void cleanupPlugin(int id);
+      void setFxParameter(int fxid, int param, float val);
+      void clearSample(int ch);
+      double master_vol;
+      int master_vol_ctrlval;
+
+      //Send effects:
+      SS_SendFx sendEffects[SS_NR_OF_SENDEFFECTS];
+      float* sendFxLineOut[SS_NR_OF_SENDEFFECTS][2]; //stereo output (fed into LADSPA inputs),sent from the individual channels -> LADSPA fx
+      float* sendFxReturn[SS_NR_OF_SENDEFFECTS][2];  //stereo inputs, from LADSPA plugins, sent from LADSPA -> SS and added to the mix
+      double* processBuffer[2];
+   };
+
+static void* loadSampleThread(void*);
+static pthread_mutex_t SS_LoaderMutex;
+static SS_State synth_state;
+static SimpleSynth* simplesynth_ptr;
+
+#endif
diff --git a/muse2/synti/simpledrums2/simpledrumsgui.cpp b/muse2/synti/simpledrums2/simpledrumsgui.cpp
new file mode 100644
index 00000000..ab511cec
--- /dev/null
+++ b/muse2/synti/simpledrums2/simpledrumsgui.cpp
@@ -0,0 +1,890 @@
+//
+// C++ Implementation: testogui
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <QButtonGroup>
+#include <QLabel>
+#include <QFileDialog>
+#include <QSocketNotifier>
+#include <QLayout>
+#include <QToolTip>
+#include <QLineEdit>
+#include <QMessageBox>
+
+#include "simpledrumsgui.h"
+#include "libsynti/mpevent.h"
+#include "muse/midi.h"
+#include "ssplugingui.h"
+
+#define SS_VOLUME_MIN_VALUE                     0
+#define SS_VOLUME_MAX_VALUE                   127
+#define SS_VOLUME_DEFAULT_VALUE               100
+#define SS_MASTERVOL_MAX_VALUE                127
+#define SS_MASTERVOL_DEFAULT_VALUE    100.0/127.0
+#define SS_SENDFX_MIN_VALUE                     0
+#define SS_SENDFX_MAX_VALUE                   127
+
+//Gui constants:
+#define SS_BTNGRP_WIDTH                        50
+#define SS_BTNGRP_HEIGHT                       80
+#define SS_ONOFF_WIDTH                         16
+#define SS_ONOFF_HEIGHT                        21
+#define SS_VOLSLDR_WIDTH                       (SS_BTNGRP_WIDTH - 8)
+#define SS_VOLSLDR_LENGTH                     120
+#define SS_PANSLDR_WIDTH                       (SS_BTNGRP_WIDTH - 8)
+#define SS_PANSLDR_LENGTH                      20
+#define SS_PANSLDR_DEFAULT_VALUE               63
+#define SS_NONOFF_LABEL_WIDTH                  30
+#define SS_NONOFF_LABEL_HEIGHT                 16
+#define SS_NONOFF_WIDTH                        SS_ONOFF_WIDTH
+#define SS_NONOFF_HEIGHT                       SS_ONOFF_HEIGHT
+#define SS_SENDFX_WIDTH                        ((SS_BTNGRP_WIDTH/2) - 4)
+//#define SS_SENDFX_WIDTH                        28
+#define SS_SENDFX_HEIGHT                       SS_SENDFX_WIDTH
+#define SS_MASTERSLDR_WIDTH                    (SS_BTNGRP_WIDTH - 8)
+#define SS_MASTERSLDR_HEIGHT                   (SS_BTNGRP_HEIGHT - 4)
+
+
+// Sample groupbox
+
+#define SS_SAMPLENAME_LABEL_WIDTH              30
+#define SS_SAMPLENAME_LABEL_HEIGHT             21
+#define SS_SAMPLENAME_LABEL_XOFF                4
+
+#define SS_SAMPLE_LOAD_WIDTH                   15
+#define SS_SAMPLE_LOAD_HEIGHT                  19
+
+#define SS_SAMPLE_CLEAR_WIDTH                   SS_SAMPLE_LOAD_WIDTH
+#define SS_SAMPLE_CLEAR_HEIGHT                  SS_SAMPLE_LOAD_HEIGHT
+
+#define SS_SAMPLENAME_LINEEDIT_WIDTH           90
+#define SS_SAMPLENAME_LINEEDIT_HEIGHT          21
+
+#define SS_SAMPLE_INFO_LINE_HEIGHT             22
+#define SS_SAMPLE_INFO_LINE_WIDTH               (SS_SAMPLENAME_LINEEDIT_XOFF + SS_SAMPLENAME_LINEEDIT_WIDTH)
+
+#define SS_GUI_WINDOW_WIDTH                     ((SS_NR_OF_CHANNELS +1) * SS_BTNGRP_XOFF)
+#define SS_MAIN_GROUPBOX_HEIGHT                 200
+#define SS_GUI_WINDOW_HEIGHT                    (SS_BTNGRP_HEIGHT + SS_MAIN_GROUPBOX_HEIGHT)
+#define SS_MAIN_GROUPBOX_WIDTH                  SS_GUI_WINDOW_WIDTH
+
+SimpleSynthGui* simplesynthgui_ptr;
+
+
+/*!
+    \fn QChannelSlider::QChannelSlider(Qt::Orientation orientation, int ch, QWidget* parent, const char* name)
+ */
+QChannelSlider::QChannelSlider(Qt::Orientation orientation, int ch, QWidget* parent)
+      : QSlider(orientation, parent)
+      {
+      channel = ch;
+      }
+
+
+/*!
+    \fn QChannelSlider::getChannel()
+ */
+int QChannelSlider::getChannel()
+      {
+      return channel;
+      }
+
+
+/*!
+    \fn QChannelSlider::setChannel(int ch)
+ */
+void QChannelSlider::setChannel(int ch)
+      {
+      channel = ch;
+      }
+
+/*!
+    \fn QChannelSlider::setValue(int val)
+ */
+void QChannelSlider::setValue(int val)
+      {
+      val = (val > 127 ? 127 : val);
+      val = (val < 0 ? 0 : val);
+      QSlider::setValue(val);
+      emit valueChanged(channel, val);
+      }
+
+/*!
+    \fn QInvertedChannelSlider::setValue(int val)
+ */
+void QInvertedChannelSlider::setValue(int val)
+      {
+      int inverted = this->maximum() - val;
+      inverted = (inverted > 127 ? 127 : inverted);
+      inverted = (inverted < 0 ? 0 : inverted);
+      QSlider::setValue(val);
+      emit valueChanged(channel, inverted);
+      }
+
+/*!
+    \fn QInvertedSlider::setValue(int val)
+ */
+void QInvertedSlider::setValue(int val)
+      {
+      int inverted = this->maximum() - val;
+      inverted = (inverted > 127 ? 127 : inverted);
+      inverted = (inverted < 0 ? 0 : inverted);
+      emit invertedValueChanged(inverted);
+      QSlider::setValue(val);
+      }
+
+
+/*!
+    \fn QChannelCheckbox::QChannelCheckbox(QWidget* parent, int ch)
+ */
+QChannelCheckbox::QChannelCheckbox(QWidget* parent, int ch)
+   : QCheckBox(parent)
+      {
+      channel = ch;
+      connect(this, SIGNAL(clicked()), SLOT(isClicked()));
+      }
+
+
+/*!
+    \fn QChannelCheckbox::isClicked()
+ */
+void QChannelCheckbox::isClicked()
+      {
+      emit channelState(channel, this->isChecked());
+      }
+
+/*!
+    \fn QChannelButton::QChannelButton(QWidget* parent, const char* text, int ch, const char* name)
+ */
+QChannelButton::QChannelButton(QWidget* parent, const char* text, int ch)
+      : QPushButton(parent), channel (ch)
+      {
+      connect(this, SIGNAL(clicked()), SLOT(isClicked()));
+      setText(text);
+      }
+
+/*!
+    \fn QChannelButton::isClicked()
+ */
+void QChannelButton::isClicked()
+      {
+      emit channelState(channel, this->isChecked());
+      }
+
+/*!
+    \fn QChannelDial()
+ */
+QChannelDial::QChannelDial(QWidget* parent, int ch, int fxid)
+   : QDial(parent)
+      {
+      setTracking(true);
+      channel = ch;
+      sendfxid = fxid;
+      }
+
+/*!
+    \fn QChannelSlider::setValue(int val)
+ */
+void QChannelDial::setValue(int val)
+      {
+      QDial::setValue(val);
+      emit valueChanged(channel, sendfxid, val);
+      }
+
+/*!
+    \fn SimpleSynthGui::SimpleSynthGui()
+ */
+SimpleSynthGui::SimpleSynthGui()
+      {
+      SS_TRACE_IN
+      setupUi(this);
+      simplesynthgui_ptr = this;
+      pluginGui = new SS_PluginGui(this);
+      pluginGui->hide();
+
+      QVBoxLayout* mainLayout = new QVBoxLayout(this); //, 3);
+      QHBoxLayout* channelLayout = new QHBoxLayout;
+      mainLayout->addLayout(channelLayout);
+
+      //this->setFixedWidth(SS_GUI_WINDOW_WIDTH);
+      //this->setFixedHeight(SS_GUI_WINDOW_HEIGHT);
+      for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
+            channelButtonGroups[i] = new QGroupBox(this);
+//            channelButtonGroups[i]->setMinimumSize(SS_BTNGRP_WIDTH, SS_BTNGRP_HEIGHT);
+            channelButtonGroups[i]->setTitle(QString::number(i + 1));
+
+            QString name = QString("volumeSlider");
+            name.append(i + 1);
+
+            channelLayout->addWidget(channelButtonGroups[i]);
+
+            QVBoxLayout* inchnlLayout = new QVBoxLayout(channelButtonGroups[i]); //, 2, 0, "channelinternallayout");
+            inchnlLayout->setAlignment(Qt::AlignHCenter);
+
+            onOff[i] = new QChannelCheckbox(channelButtonGroups[i], i);
+//            onOff[i]->setMinimumSize(SS_ONOFF_WIDTH, SS_ONOFF_HEIGHT);
+            onOff[i]->setToolTip("Channel " + QString::number(i + 1) + " on/off");
+            inchnlLayout->addWidget(onOff[i]);
+            connect(onOff[i], SIGNAL(channelState(int, bool)), SLOT(channelOnOff(int, bool)));
+
+            volumeSliders[i] = new QInvertedChannelSlider(Qt::Vertical, i, channelButtonGroups[i]);
+            volumeSliders[i]->setMinimum(SS_VOLUME_MIN_VALUE);
+            volumeSliders[i]->setMaximum(SS_VOLUME_MAX_VALUE);
+            volumeSliders[i]->setValue(SS_VOLUME_MAX_VALUE - SS_VOLUME_DEFAULT_VALUE);
+//            volumeSliders[i]->setMinimumSize(SS_VOLSLDR_WIDTH, SS_VOLSLDR_LENGTH);
+            volumeSliders[i]->setToolTip("Volume, channel " + QString::number(i + 1));
+//            setMinimumSize(SS_VOLSLDR_WIDTH, SS_VOLSLDR_LENGTH);
+            inchnlLayout->addWidget(volumeSliders[i]);
+            connect(volumeSliders[i], SIGNAL(valueChanged(int, int)), SLOT(volumeChanged(int, int)));
+
+            nOffLabel[i] = new QLabel(channelButtonGroups[i]);
+//            nOffLabel[i]->setMinimumSize(SS_NONOFF_LABEL_WIDTH, SS_NONOFF_LABEL_HEIGHT);
+            nOffLabel[i]->setText("nOff");
+            inchnlLayout->addWidget(nOffLabel[i]);
+
+            nOffIgnore[i] = new QChannelCheckbox(channelButtonGroups[i], i);
+//            nOffIgnore[i]->setMinimumSize(SS_NONOFF_WIDTH, SS_NONOFF_HEIGHT);
+            nOffIgnore[i]->setToolTip("Note off ignore, channel " + QString::number(i + 1));
+            inchnlLayout->addWidget(nOffIgnore[i]);
+            connect(nOffIgnore[i], SIGNAL(channelState(int, bool)),SLOT(channelNoteOffIgnore(int, bool)));
+
+            panSliders[i] = new QChannelSlider(Qt::Horizontal, i, channelButtonGroups[i]);
+            panSliders[i]->setRange(0, 127);
+            panSliders[i]->setValue(SS_PANSLDR_DEFAULT_VALUE);
+//            panSliders[i]->setMinimumSize(SS_PANSLDR_WIDTH, SS_PANSLDR_LENGTH);
+            panSliders[i]->setToolTip("Pan, channel " + QString::number(i + 1));
+            inchnlLayout->addWidget(panSliders[i]);
+            connect(panSliders[i], SIGNAL(valueChanged(int, int)), SLOT(panChanged(int, int)));
+
+            QGridLayout* dialGrid = new QGridLayout;
+            inchnlLayout->addLayout(dialGrid);
+            sendFxDial[i][0] = new QChannelDial(channelButtonGroups[i], i, 0);
+            sendFxDial[i][0]->setRange(0, 127);
+            sendFxDial[i][0]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
+            sendFxDial[i][0]->setToolTip("Fx 1 send amount");
+            //inchnlLayout->addWidget(sendFxDial[i][0]);
+            dialGrid->addWidget(sendFxDial[i][0], 0, 0, Qt::AlignCenter | Qt::AlignTop);
+
+            connect(sendFxDial[i][0], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
+
+            sendFxDial[i][1] = new QChannelDial(channelButtonGroups[i], i, 1);
+            sendFxDial[i][1]->setRange(0, 127);
+            //inchnlLayout->add(sendFxDial[i][1]);
+            dialGrid->addWidget(sendFxDial[i][1], 0, 1, Qt::AlignCenter | Qt::AlignTop);
+            sendFxDial[i][1]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
+            sendFxDial[i][1]->setToolTip("Fx 2 send amount");
+
+            connect(sendFxDial[i][1], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
+
+            sendFxDial[i][2] = new QChannelDial(channelButtonGroups[i], i, 2);
+            sendFxDial[i][2]->setRange(0, 127);
+            sendFxDial[i][2]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
+            //inchnlLayout->add(sendFxDial[i][2]);
+            dialGrid->addWidget(sendFxDial[i][2], 1, 0, Qt::AlignCenter | Qt::AlignTop);
+            sendFxDial[i][2]->setToolTip("Fx 3 send amount");
+            connect(sendFxDial[i][2], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
+
+            sendFxDial[i][3] = new QChannelDial(channelButtonGroups[i], i, 3);
+            sendFxDial[i][3]->setRange(0, 127);
+            sendFxDial[i][3]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
+            sendFxDial[i][3]->setToolTip("Fx 4 send amount");
+
+            dialGrid->addWidget(sendFxDial[i][3], 1, 1, Qt::AlignCenter | Qt::AlignTop);
+            connect(sendFxDial[i][3], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
+            inchnlLayout->activate();
+            //channelLayout->activate();
+            }
+
+      //Master buttongroup:
+      masterButtonGroup = new QGroupBox(this);
+      channelLayout->addWidget(masterButtonGroup);
+      QVBoxLayout* mbgLayout = new QVBoxLayout(masterButtonGroup);
+      mbgLayout->setAlignment(Qt::AlignCenter);
+//      masterButtonGroup->setMinimumSize(SS_BTNGRP_WIDTH, SS_BTNGRP_HEIGHT);
+      masterSlider = new QInvertedSlider(Qt::Vertical, masterButtonGroup);
+      masterSlider->setToolTip("Master volume");
+      mbgLayout->addWidget(masterSlider);
+      masterSlider->setRange(0, 127);
+      masterSlider->setValue(SS_VOLUME_MAX_VALUE - (int)(SS_MASTERVOL_DEFAULT_VALUE*SS_VOLUME_MAX_VALUE));
+//      masterSlider->setMinimumSize(SS_MASTERSLDR_WIDTH, SS_MASTERSLDR_HEIGHT);
+      connect(masterSlider, SIGNAL(invertedValueChanged(int)), SLOT(masterVolChanged(int)));
+
+      //Main groupbox
+      mainGroupBox = new QGroupBox(this);
+      mainLayout->addWidget(mainGroupBox);
+
+      QGridLayout* mgbLayout = new QGridLayout(mainGroupBox); // , 8, 3, 1);
+
+      int i=0;
+
+      for (int c=0; c<2; c++) {
+            for (int r=0; r<SS_NR_OF_CHANNELS/2; r++) {
+                  QHBoxLayout* strip = new QHBoxLayout;//(mgbLayout, 5);
+                  mgbLayout->addLayout(strip, r, c);
+
+                  QLabel* channelLabel = new QLabel(QString("Ch ") + QString::number(i + 1), mainGroupBox);
+                  strip->addWidget(channelLabel);
+
+                  sampleNameLineEdit[i] = new QLineEdit(mainGroupBox);
+                  sampleNameLineEdit[i]->setReadOnly(true);
+                  strip->addWidget(sampleNameLineEdit[i]);
+
+                  loadSampleButton[i] = new QChannelButton(mainGroupBox, "L", i);
+//                  loadSampleButton[i]->setMinimumSize(SS_SAMPLE_LOAD_WIDTH, SS_SAMPLE_LOAD_HEIGHT);
+                  loadSampleButton[i]->setToolTip("Load sample on channel " + QString::number(i + 1));
+                  strip->addWidget(loadSampleButton[i]);
+                  connect(loadSampleButton[i], SIGNAL(channelState(int, bool)), SLOT(loadSampleDialogue(int)));
+
+                  clearSampleButton[i] = new QChannelButton(mainGroupBox, "C", i);
+//                  clearSampleButton[i]->setMinimumSize(SS_SAMPLE_CLEAR_WIDTH, SS_SAMPLE_CLEAR_HEIGHT);
+                  clearSampleButton[i]->setToolTip("Clear sample on channel " + QString::number(i + 1));
+                  strip->addWidget(clearSampleButton[i]);
+                  connect(clearSampleButton[i], SIGNAL(channelState(int, bool)), SLOT(clearSample(int)));
+
+                  i++;
+                  }
+            }
+
+      // Right bottom panel:
+      QGroupBox* rbPanel= new QGroupBox(mainGroupBox);
+      mgbLayout->addWidget(rbPanel, 1, 3, 7, 1, Qt::AlignCenter);
+      QGridLayout* rbLayout = new QGridLayout(rbPanel); // 6, 1, 8, 5);
+
+      openPluginsButton = new QPushButton("&Send Effects");
+      openPluginsButton->setToolTip("Configure LADSPA send effects");
+      connect(openPluginsButton, SIGNAL(clicked()), SLOT(openPluginButtonClicked()));
+      rbLayout->addWidget(openPluginsButton, 2, 1, Qt::AlignCenter | Qt::AlignVCenter);
+      aboutButton = new QPushButton("About SimpleDrums");
+      connect(aboutButton, SIGNAL(clicked()), SLOT(aboutButtonClicked()));
+//TD      rbLayout->addRowSpacing(3, 20);
+      rbLayout->addWidget(aboutButton, 4, 1, Qt::AlignLeft | Qt::AlignVCenter);
+
+
+      loadButton = new QPushButton(tr("&Load setup"), rbPanel);
+      connect(loadButton, SIGNAL(clicked()), SLOT(loadSetup()));
+      saveButton = new QPushButton(tr("&Save setup"), rbPanel);
+      connect(saveButton, SIGNAL(clicked()), SLOT(saveSetup()));
+      //rbLayout->addWidget(openPluginsButton, 1, 1, Qt::AlignCenter | Qt::AlignVCenter);
+//      rbLayout->addRowSpacing(2, 20);
+      rbLayout->addWidget(loadButton,  3, 1, Qt::AlignCenter | Qt::AlignVCenter);
+      rbLayout->addWidget(saveButton,  4, 1, Qt::AlignCenter | Qt::AlignVCenter);
+//      rbLayout->addRowSpacing(5, 20);
+      rbLayout->addWidget(aboutButton, 6, 1, Qt::AlignCenter | Qt::AlignVCenter);
+
+      lastDir = "";
+      //Connect socketnotifier to fifo
+      QSocketNotifier* s = new QSocketNotifier(readFd, QSocketNotifier::Read);
+      connect(s, SIGNAL(activated(int)), SLOT(readMessage(int)));
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SimpleSynthGui::~SimpleSynthGui()
+ */
+SimpleSynthGui::~SimpleSynthGui()
+      {
+      SS_TRACE_IN
+      simplesynthgui_ptr = 0;
+      delete pluginGui;
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SimpleSynthGui::readMessage(int)
+ */
+void SimpleSynthGui::readMessage(int)
+      {
+      MessGui::readMessage();
+      }
+
+/*!
+    \fn SimpleSynthGui::processEvent(const MidiPlayEvent& ev)
+ */
+void SimpleSynthGui::processEvent(const MidiPlayEvent& ev)
+      {
+      SS_TRACE_IN
+      if (SS_DEBUG_MIDI) {
+            printf("GUI received midi event\n");
+            }
+      if (ev.type() == ME_CONTROLLER) {
+            int id  = ev.dataA();
+            int val = ev.dataB();
+
+            // Channel controllers:
+            if (id >= SS_FIRST_CHANNEL_CONTROLLER && id <= SS_LAST_CHANNEL_CONTROLLER ) {
+                  // Find out which channel we're dealing with:
+                  id-= SS_FIRST_CHANNEL_CONTROLLER;
+                  int ch = (id / SS_NR_OF_CHANNEL_CONTROLLERS);
+                  id = (id % SS_NR_OF_CHANNEL_CONTROLLERS);
+
+                  int fxid = -1;
+
+                  if (SS_DEBUG_MIDI) {
+                        printf("GUI received midi controller - id: %d val %d channel %d\n", id, val, ch);
+                        }
+
+                  switch(id) {
+                        case SS_CHANNEL_CTRL_VOLUME:
+                              volumeSliders[ch]->blockSignals(true);
+                              volumeSliders[ch]->setValue(SS_VOLUME_MAX_VALUE - val);
+                              volumeSliders[ch]->blockSignals(false);
+                              break;
+
+                        case SS_CHANNEL_CTRL_PAN:
+                              panSliders[ch]->blockSignals(true);
+                              panSliders[ch]->setValue(val);
+                              panSliders[ch]->blockSignals(false);
+                              break;
+
+                        case SS_CHANNEL_CTRL_NOFF:
+                              nOffIgnore[ch]->blockSignals(true);
+                              nOffIgnore[ch]->setChecked(val);
+                              nOffIgnore[ch]->blockSignals(false);
+                              break;
+
+                        case SS_CHANNEL_CTRL_ONOFF:
+                              onOff[ch]->blockSignals(true);
+                              onOff[ch]->setChecked(val);
+                              onOff[ch]->blockSignals(false);
+                              break;
+
+                        case SS_CHANNEL_SENDFX1:
+                        case SS_CHANNEL_SENDFX2:
+                        case SS_CHANNEL_SENDFX3:
+                        case SS_CHANNEL_SENDFX4:
+                              fxid = id - SS_CHANNEL_SENDFX1;
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui::processEvent - Channel sendfx, fxid: %d, val: %d\n", fxid, val);
+                                    }
+                              sendFxDial[ch][fxid]->blockSignals(true);
+                              sendFxDial[ch][fxid]->setValue(val);
+                              sendFxDial[ch][fxid]->blockSignals(false);
+                              break;
+
+                        default:
+                              if (SS_DEBUG_MIDI)
+                                    printf("SimpleSynthGui::processEvent - unknown controller received: %d\n", id);
+                        }
+                  }
+            // Master controllers:
+            else if (id >= SS_FIRST_MASTER_CONTROLLER && id <= SS_LAST_MASTER_CONTROLLER) {
+                  if (id == SS_MASTER_CTRL_VOLUME) {
+                        masterSlider->blockSignals(true);
+                        masterSlider->setValue(SS_MASTERVOL_MAX_VALUE - val);
+                        masterSlider->blockSignals(false);
+                        }
+                  }
+            else if (id>= SS_FIRST_PLUGIN_CONTROLLER && id <= SS_LAST_PLUGIN_CONTROLLER) {
+                  int fxid = (id - SS_FIRST_PLUGIN_CONTROLLER) / SS_NR_OF_PLUGIN_CONTROLLERS;
+                  int cmd = (id - SS_FIRST_PLUGIN_CONTROLLER) % SS_NR_OF_PLUGIN_CONTROLLERS;
+
+                  // Plugin return-gain:
+                  if (cmd == SS_PLUGIN_RETURN) {
+                        if (SS_DEBUG_MIDI)
+                              printf("SimpleSynthGui::processEvent - fx retgain received: fxid: %d val: %d\n", fxid, val);
+
+                        SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid);
+                        pf->setRetGain(val);
+                        }
+                  }
+            }
+            //
+            // Sysexes:
+            //
+            else if (ev.type() == ME_SYSEX) {
+                  byte* data = ev.data();
+                  int cmd = *data;
+                  switch (cmd) {
+                        case SS_SYSEX_LOAD_SAMPLE_OK: {
+                              int ch = *(data+1);
+                              QString filename = (const char*) (data+2);
+                              sampleNameLineEdit[ch]->setText(filename.section('/',-1,-1));
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui - sample %s loaded OK on channel: %d\n", filename.toLatin1().data(), ch);
+                                    }
+                              if (!onOff[ch]->isChecked()) {
+                                    onOff[ch]->blockSignals(true);
+                                    onOff[ch]->setChecked(true);
+                                    onOff[ch]->blockSignals(false);
+                                    channelOnOff(ch, true);
+                                    }
+                              break;
+                              }
+
+                        case SS_SYSEX_LOAD_SAMPLE_ERROR: {
+                              //int ch = *(data+1);
+                              const char* filename = (const char*) (data+2);
+                              /*QMessageBox* yn = new QMessageBox("Sample not found", "Failed to load sample: " + QString(filename) + "\n" +
+                                                      "Do you want to open file browser and try to locate it elsewhere?",
+                                                      QMessageBox::Warning,
+                                                      QMessageBox::Yes,
+                                                      QMessageBox::No,
+                                                      QMessageBox::NoButton,
+                                                      this);*/
+                              /*int res = QMessageBox::warning(this,
+                                                      "SimpleDrums","Failed to load sample: " + QString(filename) + "\n" +
+                                                      "Do you want to open file browser and try to locate it elsewhere?",
+                                                      "&Yes", "&No");
+                                                      */
+                              //int res = yn->exec();
+                              printf("Error: Sample %s not found! TODO: Fix this\n", filename);
+                              //if (res == 0) {
+                              //      loadSampleDialogue(ch);
+                              //      }
+                              break;
+                              }
+
+                        case SS_SYSEX_LOAD_SENDEFFECT_OK: {
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui - sysex load sendeffect OK on fxid: %d\n", *(data+1));
+                                    }
+                              int fxid = *(data+1);
+                              SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid);
+                              pf->updatePluginValue(*(data+2));
+                              break;
+                              }
+
+                        case SS_SYSEX_CLEAR_SENDEFFECT_OK: {
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui - sysex clear sendeffect OK on fxid: %d\n", *(data+1));
+                                    }
+                              SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)*(data+1));
+                              pf->clearPluginDisplay();
+                              break;
+                              }
+
+                        case SS_SYSEX_CLEAR_SAMPLE_OK: {
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui - sysex clear samle OK on channel: %d\n", *(data+1));
+                                    }
+                              byte ch = *(data+1);
+                              sampleNameLineEdit[ch]->setText("");
+                              break;
+                              }
+
+                        case SS_SYSEX_SET_PLUGIN_PARAMETER_OK: {
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui - plugin parameter OK on fxid: %d\n", *(data+1));
+                                    }
+                              SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)*(data+1));
+                              int param = *(data+2);
+                              int val   = *(data+3);
+                              pf->blockSignals(true);
+                              pf->setParameterValue(param, val);
+                              pf->blockSignals(false);
+                              break;
+                              }
+
+                        case SS_SYSEX_SEND_INIT_DATA: {
+// FN: TODO
+#if 1
+                              const unsigned initdata_len = ev.len() - 1;
+                              byte* init_data = (data + 1);
+                              QFileInfo fileInfo = QFileInfo(lastSavedProject);
+
+                              lastProjectDir = fileInfo.path();
+                              if (fileInfo.suffix() != "sds" && fileInfo.suffix() != "SDS") {
+                                    lastSavedProject += ".sds";
+                                    fileInfo = QFileInfo(lastSavedProject);
+                                    }
+                              QFile theFile(fileInfo.filePath());
+
+                              // Write data
+                              if (theFile.open(QIODevice::WriteOnly)) {
+                                    theFile.write((const char*)&initdata_len, sizeof(initdata_len)); // First write length
+                                    if (theFile.write((const char*)init_data, initdata_len) == -1) {
+                                          // Fatal error writing
+                                          QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, "SimpleDrums error Dialog", "Fatal error when writing to file. Setup not saved.",
+                                                QMessageBox::Ok, this);
+                                          msgBox->exec();
+                                          delete msgBox;
+                                          }
+                                    theFile.close();
+                                    }
+                              else {
+                                    // An error occured when opening
+                                    QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, "SimpleDrums error Dialog", "Error opening file. Setup was not saved.",
+                                          QMessageBox::Ok, this);
+                                    msgBox->exec();
+                                    delete msgBox;
+                                    }
+#endif
+
+                              break;
+                              }
+
+
+                        default:
+                              if (SS_DEBUG_MIDI) {
+                                    printf("SimpleSynthGui::processEvent - unknown sysex cmd received: %d\n", cmd);
+                                    }
+                              break;
+                        }
+                  }
+      SS_TRACE_OUT
+      }
+
+
+/*!
+    \fn SimpleSynthGui::volumeChanged(int val)
+ */
+void SimpleSynthGui::volumeChanged(int channel, int val)
+      {
+      setChannelVolume(channel, val);
+      }
+
+/*!
+    \fn SimpleSynthGui::panChanged(int channel, int value)
+ */
+void SimpleSynthGui::panChanged(int channel, int value)
+      {
+      sendController(0, SS_CHANNEL_PAN_CONTROLLER(channel), value);
+      }
+
+/*!
+    \fn SimpleSynthGui::channelOnOff(int channel, bool state)
+ */
+void SimpleSynthGui::channelOnOff(int channel, bool state)
+      {
+      sendController(0, SS_CHANNEL_ONOFF_CONTROLLER(channel), state);
+      }
+
+/*!
+    \fn SimpleSynthGui::channelNoteOffIgnore(bool state)
+ */
+void SimpleSynthGui::channelNoteOffIgnore(int channel, bool state)
+      {
+      sendController(0, SS_CHANNEL_NOFF_CONTROLLER(channel), (int) state);
+      }
+
+/*!
+    \fn SimpleSynthGui::sendFxChanged(int ch, int fxid, int val)
+ */
+void SimpleSynthGui::sendFxChanged(int ch, int fxid, int val)
+      {
+      sendController(0, SS_CHANNEL_SENDFX_CONTROLLER(ch, fxid), (int) val);
+      }
+
+/*!
+    \fn SimpleSynthGui::masterVolChanged(int val)
+ */
+void SimpleSynthGui::masterVolChanged(int val)
+      {
+      sendController(0, SS_MASTER_CTRL_VOLUME, val);
+      }
+
+/*!
+    \fn SimpleSynthGui::setChannelVolume(int channel, byte volume)
+ */
+void SimpleSynthGui::setChannelVolume(int channel, int volume)
+      {
+      //volumeSliders[channel]->setValue(SS_VOLUME_MAX_VALUE - volume);
+      sendController(0, SS_CHANNEL_VOLUME_CONTROLLER(channel), (int)volume);
+      }
+
+
+/*!
+    \fn SimpleSynthGui::loadSampleDialogue(int channel)
+ */
+void SimpleSynthGui::loadSampleDialogue(int channel)
+      {
+      QString filename =
+            QFileDialog::getOpenFileName(
+      					   this,
+                                       tr("Load sample dialog"),
+      					   lastDir,
+                                       QString("*.wav *.WAV"));
+
+      if (filename != QString::null) {
+            QFileInfo fi(filename);
+            lastDir = fi.path();
+
+            if (SS_DEBUG)
+                  printf("lastDir = %s\n", lastDir.toLatin1().data());
+
+            int l = filename.length() + 4;
+            byte d[l];
+
+            d[0] = SS_SYSEX_LOAD_SAMPLE;
+            d[1] = (byte) channel;
+            d[2] = (byte) filename.length();
+            memcpy(d+3, filename.toLatin1().data(), filename.length()+1);
+            sendSysex(d, l);
+            }
+      }
+
+
+
+/*!
+    \fn SimpleSynthGui::clearSample(int ch)
+ */
+void SimpleSynthGui::clearSample(int ch)
+      {
+      if (sampleNameLineEdit[ch]->text().length() > 0) { //OK, we've got a live one here
+            byte d[2];
+            d[0] = SS_SYSEX_CLEAR_SAMPLE;
+            d[1] = (byte) ch;
+            sendSysex(d, 2);
+            sampleNameLineEdit[ch]->setText("");
+            }
+      }
+
+/*!
+    \fn SimpleSynthGui::displayPluginGui()
+ */
+void SimpleSynthGui::displayPluginGui()
+      {
+      pluginGui->show();
+      }
+
+/*!
+    \fn SimpleSynthGui::loadEffectInvoked(int fxid, QString lib, QString label)
+ */
+void SimpleSynthGui::loadEffectInvoked(int fxid, QString lib, QString label)
+      {
+      int l = 4 + lib.length() + label.length();
+      byte d[l];
+      d[0] = SS_SYSEX_LOAD_SENDEFFECT;
+      d[1] = (byte) fxid;
+      memcpy (d+2, lib.toLatin1().data(), lib.length()+1);
+      memcpy (d+3+lib.length(), label.toLatin1().data(), label.length()+1);
+      sendSysex(d, l);
+      }
+
+
+/*!
+    \fn SimpleSynthGui::returnLevelChanged(int fxid, int val)
+ */
+void SimpleSynthGui::returnLevelChanged(int fxid, int val)
+      {
+      sendController(0, SS_PLUGIN_RETURNLEVEL_CONTROLLER(fxid), val);
+      }
+
+
+/*!
+    \fn SimpleSynthGui::toggleEffectOnOff(int fxid, int state)
+ */
+void SimpleSynthGui::toggleEffectOnOff(int fxid, int state)
+      {
+      sendController(0, SS_PLUGIN_ONOFF_CONTROLLER(fxid), state);
+      }
+
+
+/*!
+    \fn SimpleSynthGui::clearPlugin(int fxid)
+ */
+void SimpleSynthGui::clearPlugin(int fxid)
+      {
+      byte d[2];
+      d[0] = SS_SYSEX_CLEAR_SENDEFFECT;
+      d[1] = fxid;
+      sendSysex(d, 2);
+      }
+
+
+/*!
+    \fn SimpleSynthGui::effectParameterChanged(int fxid, int parameter, int val)
+ */
+void SimpleSynthGui::effectParameterChanged(int fxid, int parameter, int val)
+      {
+      //printf("Gui: effectParameterChanged: %d %d %d\n", fxid, parameter, val);
+      int len = 4;
+      byte d[len];
+      d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER;
+      d[1] = (byte) fxid;
+      d[2] = (byte) parameter;
+      d[3] = (byte) val;
+      sendSysex(d, len);
+      }
+
+
+/*!
+    \fn SimpleSynthGui::openPluginButtonClicked()
+ */
+void SimpleSynthGui::openPluginButtonClicked()
+      {
+      if (pluginGui->isVisible())
+            pluginGui->raise();
+      else
+            displayPluginGui();
+      }
+
+
+/*!
+    \fn SimpleSynthGui::aboutButtonClicked()
+ */
+void SimpleSynthGui::aboutButtonClicked()
+      {
+      QString caption = "SimpleDrums ver";
+      caption+= SS_VERSIONSTRING;
+      QString text = caption + "\n\n(C) Copyright 2000-2004 Mathias Lundgren (lunar_shuttle@users.sf.net), Werner Schweer\nPublished under the GNU Public License";
+      QMessageBox* msgBox = new QMessageBox(caption, text, QMessageBox::NoIcon,
+            QMessageBox::Ok, Qt::NoButton, Qt::NoButton, this);
+      msgBox->exec();
+      }
+
+
+/*!
+    \fn SimpleSynthGui::loadSetup()
+    \brief Load setup from file
+ */
+void SimpleSynthGui::loadSetup()
+      {
+      bool success = true;
+      QString filename =
+            QFileDialog::getOpenFileName(this, "Load setup dialog", lastProjectDir,
+                                       QString("*.sds *.SDS"));
+
+      if (filename != QString::null) {
+            QFile theFile(filename);
+            if (theFile.open(QIODevice::ReadOnly)) {
+                  unsigned initdata_len = 0;
+                  if (theFile.read((char*)&initdata_len, sizeof(initdata_len)) == -1)
+                     success = false;
+
+                  byte* init_data = new byte[initdata_len];
+                  if (theFile.read((char*)(init_data), initdata_len) == -1)
+                     success = false;
+
+                  if (!success) {
+                        QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, "SimpleDrums Error Dialog", "Error opening/reading from file. Setup not loaded.",
+                              QMessageBox::Ok, this);
+                        msgBox->exec();
+                        delete msgBox;
+                        }
+                  else {
+                        sendSysex(init_data, initdata_len);
+                        }
+
+                  delete[] init_data;
+                  }
+            }
+      }
+
+
+/*!
+    \fn SimpleSynthGui::saveSetup()
+    \brief Save setup to file
+ */
+void SimpleSynthGui::saveSetup()
+      {
+      QString filename =
+            QFileDialog::getSaveFileName(this, "Save setup dialog", lastProjectDir,
+                                       QString("*.sds *.SDS"));
+
+      if (filename != QString::null) {
+            lastSavedProject = filename;
+            byte d[1];
+            d[0] = SS_SYSEX_GET_INIT_DATA;
+            sendSysex(d, 1); // Makes synth send gui initdata, where rest of the saving takes place
+            }
+      }
+
diff --git a/muse2/synti/simpledrums2/simpledrumsgui.h b/muse2/synti/simpledrums2/simpledrumsgui.h
new file mode 100644
index 00000000..16a5caf5
--- /dev/null
+++ b/muse2/synti/simpledrums2/simpledrumsgui.h
@@ -0,0 +1,214 @@
+//
+// C++ Interface: testogui
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef __MUSE_TESTOGUI_H__
+#define __MUSE_TESTOGUI_H__
+
+#include <QSlider>
+#include <QCheckBox>
+#include <QPushButton>
+#include <QDial>
+#include <QLabel>
+//#include <QFileInfo>
+#include <QGroupBox>
+
+#include "libsynti/gui.h"
+#include "ui_simpledrumsguibase.h"
+#include "common.h"
+
+class QButtonGroup;
+class QLabel;
+class SS_PluginGui;
+
+//--------------------------------------
+// QChannelSlider
+//--------------------------------------
+class QChannelSlider: public QSlider
+   {
+   Q_OBJECT
+
+   public:
+      QChannelSlider(Qt::Orientation, int ch, QWidget* paren = 0);
+      int getChannel();
+      void setChannel(int ch);
+
+   public slots:
+      virtual void setValue(int val);
+
+   signals:
+      void valueChanged(int channel, int value);
+
+   protected:
+      int channel;
+   };
+
+//--------------------------------------
+// QInvertedSlider
+//--------------------------------------
+class QInvertedSlider : public QSlider
+   {
+   Q_OBJECT
+   public:
+      QInvertedSlider(Qt::Orientation o, QWidget* parent = 0)
+         : QSlider(o, parent) {}
+
+   public slots:
+      virtual void setValue(int val);
+
+   signals:
+      void invertedValueChanged(int value);
+   };
+
+//--------------------------------------
+// QInvertedChannelSlider
+//--------------------------------------
+class QInvertedChannelSlider : public QChannelSlider
+   {
+   Q_OBJECT
+   public:
+      QInvertedChannelSlider(Qt::Orientation o, int channel, QWidget* parent = 0)
+         : QChannelSlider(o, channel, parent) {};
+
+   public slots:
+      virtual void setValue(int val);
+   };
+
+
+//--------------------------------------
+// QChannelOnOff
+//--------------------------------------
+
+class QChannelCheckbox : public QCheckBox
+   {
+   Q_OBJECT
+   public:
+      QChannelCheckbox(QWidget* parent, int channel);
+
+   private:
+      int channel;
+
+    private slots:
+      void isClicked();
+
+   signals:
+      void channelState(int channel, bool state);
+   };
+
+//--------------------------------------
+// QChannelButton
+//--------------------------------------
+class QChannelButton : public QPushButton
+   {
+   Q_OBJECT
+
+   private:
+      int channel;
+
+   public:
+      QChannelButton(QWidget* parent, const char* text, int ch);
+
+   private slots:
+      void isClicked();
+
+   signals:
+      void channelState(int channel, bool state);
+
+   };
+
+//--------------------------------------
+// QChannelDial
+//--------------------------------------
+
+class QChannelDial : public QDial
+   {
+   Q_OBJECT
+
+   public:
+      QChannelDial(QWidget* parent, int ch, int fxid);
+
+   signals:
+      void valueChanged(int channel, int fxid, int val);
+
+   public slots:
+      virtual void setValue(int val);
+
+   protected:
+      int channel;
+      int sendfxid;
+   };
+
+//--------------------------------------
+// SimpleSynthGui - the Gui
+//--------------------------------------
+class SimpleSynthGui : public QDialog, public Ui::SimpleDrumsGuiBase, public MessGui
+   {
+   Q_OBJECT
+   private:
+      // MESS interface:
+      virtual void processEvent(const MidiPlayEvent& ev);
+      void setChannelVolume(int channel, int volume);
+      void displayPluginGui();
+      QGroupBox* channelButtonGroups[SS_NR_OF_CHANNELS];
+      QGroupBox*           masterButtonGroup;
+      QGroupBox*              mainGroupBox;
+      QInvertedChannelSlider* volumeSliders[SS_NR_OF_CHANNELS];
+      QChannelSlider*         panSliders[SS_NR_OF_CHANNELS];
+      QChannelCheckbox*       onOff[SS_NR_OF_CHANNELS];
+      QChannelCheckbox*       nOffIgnore[SS_NR_OF_CHANNELS];
+      QChannelButton*         loadSampleButton[SS_NR_OF_CHANNELS];
+      QChannelButton*         clearSampleButton[SS_NR_OF_CHANNELS];
+      QLabel*                 nOffLabel[SS_NR_OF_CHANNELS];
+      QLineEdit*              sampleNameLineEdit[SS_NR_OF_CHANNELS];
+      QInvertedSlider*        masterSlider;
+      QChannelDial*           sendFxDial[SS_NR_OF_CHANNELS][SS_NR_OF_SENDEFFECTS];
+
+      QPushButton*            openPluginsButton;
+      QPushButton*            aboutButton;
+      QPushButton*            loadButton;
+      QPushButton*            saveButton;
+
+
+      QString lastDir;
+      QString lastSavedProject;
+      QString lastProjectDir;
+      SS_PluginGui* pluginGui;
+
+   public:
+      SimpleSynthGui();
+      virtual ~SimpleSynthGui();
+
+   public slots:
+      void loadEffectInvoked(int fxid, QString lib, QString label);
+      void returnLevelChanged(int fxid, int val);
+      void toggleEffectOnOff(int fxid, int state);
+      void clearPlugin(int fxid);
+      void effectParameterChanged(int fxid, int parameter, int val);
+
+   private slots:
+      void volumeChanged(int channel, int val);
+      void panChanged(int channel, int value);
+      void channelOnOff(int channel, bool state);
+      void channelNoteOffIgnore(int channel, bool state);
+      void masterVolChanged(int val);
+      void loadSampleDialogue(int channel);
+      void readMessage(int);
+      void clearSample(int ch);
+      void sendFxChanged(int ch, int fxid, int val);
+      void openPluginButtonClicked();
+      void aboutButtonClicked();
+      void loadSetup();
+      void saveSetup();
+
+   };
+
+extern SimpleSynthGui* simplesynthgui_ptr;
+
+#endif
diff --git a/muse2/synti/simpledrums2/simpledrumsguibase.ui b/muse2/synti/simpledrums2/simpledrumsguibase.ui
new file mode 100644
index 00000000..412bfdf6
--- /dev/null
+++ b/muse2/synti/simpledrums2/simpledrumsguibase.ui
@@ -0,0 +1,23 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>SimpleDrumsGuiBase</class>
+ <widget class="QDialog" name="SimpleDrumsGuiBase" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>602</width>
+    <height>509</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>DrumSynth 0.1</string>
+  </property>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/muse2/synti/simpledrums2/ssplugin.cpp b/muse2/synti/simpledrums2/ssplugin.cpp
new file mode 100644
index 00000000..7e8986e7
--- /dev/null
+++ b/muse2/synti/simpledrums2/ssplugin.cpp
@@ -0,0 +1,460 @@
+//
+// C++ Implementation: plugin
+//
+// Description:
+//
+//
+//  (C) Copyright 2000 Werner Schweer (ws@seh.de)
+// Additions/modifications: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <QtCore>
+#include <QtGui>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include "ssplugin.h"
+#include "common.h"
+
+PluginList plugins;
+
+
+Plugin::Plugin(const QFileInfo* f)
+   : fi(*f)
+      {
+      }
+
+//---------------------------------------------------------
+//   loadPluginLib
+//---------------------------------------------------------
+
+static void loadPluginLib(QFileInfo* fi)
+      {
+      SS_TRACE_IN
+      if (SS_DEBUG_LADSPA) {
+            printf("loadPluginLib: %s\n", fi->fileName().toLatin1().data());
+            }
+      void* handle = dlopen(fi->filePath().toAscii().data(), RTLD_NOW);
+      if (handle == 0) {
+            fprintf(stderr, "dlopen(%s) failed: %s\n",
+              fi->filePath().toAscii().data(), dlerror());
+            return;
+            }
+      LADSPA_Descriptor_Function ladspa = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
+
+      if (!ladspa) {
+            const char *txt = dlerror();
+            if (txt) {
+                  fprintf(stderr,
+                        "Unable to find ladspa_descriptor() function in plugin "
+                        "library file \"%s\": %s.\n"
+                        "Are you sure this is a LADSPA plugin file?\n",
+                        fi->filePath().toAscii().data(),
+                        txt);
+                  return;//exit(1);
+                  }
+            }
+      const LADSPA_Descriptor* descr;
+      for (int i = 0;; ++i) {
+            descr = ladspa(i);
+            if (descr == NULL)
+                  break;
+            plugins.push_back(new LadspaPlugin(fi, ladspa, descr));
+            }
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   loadPluginDir
+//---------------------------------------------------------
+
+static void loadPluginDir(const QString& s)
+      {
+      SS_TRACE_IN
+      QDir pluginDir(s, QString("*.so"), 0, QDir::Files);
+      if (pluginDir.exists()) {
+            QFileInfoList list = pluginDir.entryInfoList();
+            int n = list.size();
+            for (int i = 0; i < n; ++i) {
+                  QFileInfo fi = list.at(i);
+                  loadPluginLib(&fi);
+                  }
+            }
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   initPlugins
+//    search for LADSPA plugins
+//---------------------------------------------------------
+
+void SS_initPlugins()
+      {
+      SS_TRACE_IN
+      //loadPluginDir(museGlobalLib + QString("/plugins"));
+
+      char* ladspaPath = getenv("LADSPA_PATH");
+      if (ladspaPath == 0)
+            ladspaPath = "/usr/lib/ladspa:/usr/local/lib/ladspa";
+
+      char* p = ladspaPath;
+      while (*p != '\0') {
+            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';
+                  loadPluginDir(QString(buffer));
+                  delete[] buffer;
+                  }
+            p = pe;
+            if (*p == ':')
+                  p++;
+            }
+      SS_TRACE_OUT
+      }
+
+
+//---------------------------------------------------------
+//   LadspaPlugin
+//---------------------------------------------------------
+
+LadspaPlugin::LadspaPlugin(const QFileInfo* f,
+   const LADSPA_Descriptor_Function ldf,
+   const LADSPA_Descriptor* d)
+   : Plugin(f), ladspa(ldf), plugin(d)
+      {
+      SS_TRACE_IN
+      _inports        = 0;
+      _outports       = 0;
+      _parameter      = 0;
+      handle          = 0;
+      active          = false;
+      controls        = 0;
+      inputs          = 0;
+      outputs         = 0;
+
+      for (unsigned k = 0; k < plugin->PortCount; ++k) {
+            LADSPA_PortDescriptor pd = d->PortDescriptors[k];
+            static const int CI = LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT;
+            if ((pd &  CI) == CI) {
+                  ++_parameter;
+                  pIdx.push_back(k);
+                  }
+            else if (pd &  LADSPA_PORT_INPUT) {
+                  ++_inports;
+                  iIdx.push_back(k);
+                  }
+            else if (pd &  LADSPA_PORT_OUTPUT) {
+                  ++_outports;
+                  oIdx.push_back(k);
+                  }
+            }
+
+      /*if (SS_DEBUG_LADSPA) {
+            printf("Label: %s\tLib: %s\tPortCount: %d\n", this->label().toLatin1().data(), this->lib().toLatin1().data(), plugin->PortCount);
+            printf("LADSPA_PORT_CONTROL|LADSPA_PORT_INPUT: %d\t", pIdx.size());
+            printf("Input ports: %d\t", iIdx.size());
+            printf("Output ports: %d\n\n", oIdx.size());
+            }*/
+
+      LADSPA_Properties properties = plugin->Properties;
+      _inPlaceCapable = !LADSPA_IS_INPLACE_BROKEN(properties);
+      if (_inports != _outports)
+            _inPlaceCapable = false;
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   ~LadspaPlugin
+//---------------------------------------------------------
+LadspaPlugin::~LadspaPlugin()
+      {
+      SS_TRACE_IN
+      if (active) {
+            stop();
+            }
+      if (handle) {
+         SS_DBG_LADSPA2("Cleaning up ", this->label().toLatin1().data());
+         plugin->cleanup(handle);
+         }
+
+      //Free ports:
+      if (controls)
+            delete controls;
+      if (inputs)
+            delete inputs;
+      if (outputs)
+            delete outputs;
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   instantiate
+//---------------------------------------------------------
+
+bool LadspaPlugin::instantiate()
+      {
+      bool success = false;
+      handle = plugin->instantiate(plugin, SS_samplerate);
+      success = (handle != NULL);
+      if (success)
+            SS_DBG_LADSPA2("Plugin instantiated", label().toLatin1().data());
+      return success;
+      }
+
+//---------------------------------------------------------
+//   start
+// activate and connect control ports
+//---------------------------------------------------------
+
+bool LadspaPlugin::start()
+      {
+      SS_TRACE_IN
+      if (handle) {
+            if (plugin->activate) {
+                  plugin->activate(handle);
+                  SS_DBG_LADSPA("Plugin activated");
+                  }
+            active = true;
+            }
+      else {
+            SS_DBG_LADSPA("Error trying to activate plugin - plugin not instantiated!");
+            SS_TRACE_OUT
+            return false;
+            }
+
+      //Connect ports:
+      controls = new Port[_parameter];
+
+      for (int k = 0; k < _parameter; ++k) {
+            double val = defaultValue(k);
+            controls[k].val    = val;
+            plugin->connect_port(handle, pIdx[k], &controls[k].val);
+            }
+
+      outputs  = new Port[_outports];
+      inputs   = new Port[_inports];
+
+      SS_TRACE_OUT
+      return true;
+      }
+
+//---------------------------------------------------------
+//   stop
+// deactivate
+//---------------------------------------------------------
+void LadspaPlugin::stop()
+      {
+      SS_TRACE_IN
+      if (handle) {
+            SS_DBG_LADSPA2("Trying to stop plugin", label().toLatin1().data());
+            if (plugin->deactivate) {
+                  SS_DBG_LADSPA2("Deactivating ", label().toLatin1().data());
+                  plugin->deactivate(handle);
+                  active = false;
+                  }
+            }
+      else
+            SS_DBG_LADSPA("Warning - tried to stop plugin, but plugin was never started...\n");
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   range
+//---------------------------------------------------------
+
+void LadspaPlugin::range(int i, float* min, float* max) const
+      {
+      SS_TRACE_IN
+      i = pIdx[i];
+      LADSPA_PortRangeHint range = plugin->PortRangeHints[i];
+      LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor;
+      if (desc & LADSPA_HINT_TOGGLED) {
+            *min = 0.0;
+            *max = 1.0;
+            return;
+            }
+      float m = 1.0;
+      if (desc & LADSPA_HINT_SAMPLE_RATE)
+            m = (float) SS_samplerate;
+
+      if (desc & LADSPA_HINT_BOUNDED_BELOW)
+            *min =  range.LowerBound * m;
+      else
+            *min = 0.0;
+      if (desc & LADSPA_HINT_BOUNDED_ABOVE)
+            *max =  range.UpperBound * m;
+      else
+            *max = 1.0;
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   defaultValue
+//---------------------------------------------------------
+
+float LadspaPlugin::defaultValue(int k) const
+      {
+      SS_TRACE_IN
+      k = pIdx[k];
+      LADSPA_PortRangeHint range = plugin->PortRangeHints[k];
+      LADSPA_PortRangeHintDescriptor rh = range.HintDescriptor;
+      double val = 1.0;
+      if (LADSPA_IS_HINT_DEFAULT_MINIMUM(rh))
+            val = range.LowerBound;
+      else if (LADSPA_IS_HINT_DEFAULT_LOW(rh))
+            if (LADSPA_IS_HINT_LOGARITHMIC(range.HintDescriptor))
+                  val = exp(fast_log10(range.LowerBound) * .75 +
+                     log(range.UpperBound) * .25);
+            else
+                  val = range.LowerBound*.75 + range.UpperBound*.25;
+      else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(rh))
+            if (LADSPA_IS_HINT_LOGARITHMIC(range.HintDescriptor))
+                  val = exp(log(range.LowerBound) * .5 +
+                     log(range.UpperBound) * .5);
+            else
+                  val = range.LowerBound*.5 + range.UpperBound*.5;
+      else if (LADSPA_IS_HINT_DEFAULT_HIGH(rh))
+            if (LADSPA_IS_HINT_LOGARITHMIC(range.HintDescriptor))
+                  val = exp(log(range.LowerBound) * .25 +
+                     log(range.UpperBound) * .75);
+            else
+                  val = range.LowerBound*.25 + range.UpperBound*.75;
+      else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(rh))
+            val = range.UpperBound;
+      else if (LADSPA_IS_HINT_DEFAULT_0(rh))
+            val = 0.0;
+      else if (LADSPA_IS_HINT_DEFAULT_1(rh))
+            val = 1.0;
+      else if (LADSPA_IS_HINT_DEFAULT_100(rh))
+            val = 100.0;
+      else if (LADSPA_IS_HINT_DEFAULT_440(rh))
+            val = 440.0;
+      SS_TRACE_OUT
+      return val;
+      }
+
+//---------------------------------------------------------
+//   find
+//---------------------------------------------------------
+
+Plugin* PluginList::find(const QString& file, const QString& name)
+      {
+      SS_TRACE_IN
+      for (iPlugin i = begin(); i != end(); ++i) {
+            if ((file == (*i)->lib()) && (name == (*i)->label())) {
+                  SS_TRACE_OUT
+                  return *i;
+                  }
+            }
+      printf("Plugin <%s> not found\n", name.toLatin1().data());
+      SS_TRACE_OUT
+      return 0;
+      }
+
+//---------------------------------------------------------
+//   connectInport
+//---------------------------------------------------------
+void LadspaPlugin::connectInport(int k, LADSPA_Data* datalocation)
+      {
+      SS_TRACE_IN
+      plugin->connect_port(handle, iIdx[k], datalocation);
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   connectOutport
+//---------------------------------------------------------
+void LadspaPlugin::connectOutport(int k, LADSPA_Data* datalocation)
+      {
+      SS_TRACE_IN
+      plugin->connect_port(handle, oIdx[k], datalocation);
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   process
+//---------------------------------------------------------
+void LadspaPlugin::process(unsigned long frames)
+      {
+      plugin->run(handle, frames);
+      }
+
+//---------------------------------------------------------
+//   setParam
+//---------------------------------------------------------
+
+void LadspaPlugin::setParam(int k, float val)
+      {
+      SS_TRACE_IN
+      controls[k].val = val;
+      SS_TRACE_OUT
+      }
+
+//---------------------------------------------------------
+//   getGuiControlValue
+//  scale control value to gui-slider/checkbox representation
+//---------------------------------------------------------
+
+int LadspaPlugin::getGuiControlValue(int param) const
+      {
+      SS_TRACE_IN
+      float val = getControlValue(param);
+      float min, max;
+      range(param, &min, &max);
+      int intval;
+      if (isLog(param)) {
+            intval = SS_map_logdomain2pluginparam(logf(val/(max - min) + min));
+            }
+      else if (isBool(param)) {
+            intval = (int) val;
+            }
+      else {
+            float scale = SS_PLUGIN_PARAM_MAX / (max - min);
+            intval = (int) ((val - min) * scale);
+            }
+      SS_TRACE_OUT
+      return intval;
+      }
+
+//---------------------------------------------------------
+//   convertGuiControlValue
+//  scale control value to gui-slider/checkbox representation
+//---------------------------------------------------------
+
+float LadspaPlugin::convertGuiControlValue(int parameter, int val) const
+      {
+      SS_TRACE_IN
+      float floatval = 0;
+      float min, max;
+      range(parameter, &min, &max);
+
+      if (isLog(parameter)) {
+            if (val > 0) {
+                  float logged = SS_map_pluginparam2logdomain(val);
+                  float e = expf(logged) * (max - min);
+                  e+=min;
+                  floatval = e;
+                  }
+            }
+      else if (isBool(parameter)) {
+            floatval = (float) val;
+            }
+      else if (isInt(parameter)) {
+            float scale = (max - min) / SS_PLUGIN_PARAM_MAX;
+            floatval = (float) round((((float) val) * scale) + min);
+            }
+      else {
+            float scale = (max - min) / SS_PLUGIN_PARAM_MAX;
+            floatval = (((float) val) * scale) + min;
+            }
+      SS_TRACE_OUT
+      return floatval;
+      }
diff --git a/muse2/synti/simpledrums2/ssplugin.h b/muse2/synti/simpledrums2/ssplugin.h
new file mode 100644
index 00000000..64e80921
--- /dev/null
+++ b/muse2/synti/simpledrums2/ssplugin.h
@@ -0,0 +1,173 @@
+//
+// C++ Interface: plugin
+//
+// Description:
+//
+//
+//  (C) Copyright 2000 Werner Schweer (ws@seh.de)
+// Additions/modifications: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef __PLUGIN_H__
+#define __PLUGIN_H__
+
+#include <QFileInfo>
+
+#include <ladspa.h>
+#include <math.h>
+
+//---------------------------------------------------------
+//   Port
+//---------------------------------------------------------
+
+struct Port {
+      float val;
+      };
+
+//---------------------------------------------------------
+//   Plugin
+//---------------------------------------------------------
+
+class Plugin
+   {
+   protected:
+      QFileInfo fi;
+
+   public:
+      Plugin(const QFileInfo* f);
+      virtual ~Plugin() {}
+      virtual QString label() const     { return QString(); }
+      virtual QString name() const      { return QString(); }
+      virtual unsigned long id() const  { return 0;         }
+      virtual QString maker() const     { return QString(); }
+      virtual QString copyright() const { return QString(); }
+      virtual int parameter() const       { return 0;     }
+      virtual int inports() const         { return 0;     }
+      virtual int outports() const        { return 0;     }
+      virtual bool inPlaceCapable() const { return false; }
+
+      virtual bool isLog(int) const       { return false; }
+      virtual bool isBool(int) const      { return false; }
+      virtual bool isInt(int) const       { return false; }
+      virtual float defaultValue(int) const { return 0.0f;  }
+      virtual void range(int, float* min, float* max) const {
+            *min = 0.0f;
+            *max = 1.0f;
+            }
+      virtual const char* getParameterName(int /*param*/) const           { return ""; }
+      QString lib() const               { return fi.baseName();    }
+      QString path() const              { return fi.absolutePath();     }
+   };
+
+//---------------------------------------------------------
+//   LadspaPlugin
+//---------------------------------------------------------
+
+class LadspaPlugin : public Plugin
+   {
+      LADSPA_Descriptor_Function ladspa;
+      const LADSPA_Descriptor* plugin;
+      LADSPA_Handle handle;
+      bool active;
+
+      Port* controls;
+      Port* inputs;
+      Port* outputs;
+
+   protected:
+      int _parameter;
+      std::vector<int> pIdx; //control port numbers
+
+      int _inports;
+      std::vector<int> iIdx; //input port numbers
+
+      int _outports;
+      std::vector<int> oIdx; //output port numbers
+
+      bool _inPlaceCapable;
+
+   public:
+      LadspaPlugin(const QFileInfo* f, const LADSPA_Descriptor_Function, const LADSPA_Descriptor* d);
+      virtual ~LadspaPlugin();
+      virtual QString label() const     { return QString(plugin->Label); }
+      virtual QString name() const      { return QString(plugin->Name); }
+      virtual unsigned long id() const  { return plugin->UniqueID; }
+      virtual QString maker() const     { return QString(plugin->Maker); }
+      virtual QString copyright() const { return QString(plugin->Copyright); }
+      virtual int parameter() const { return _parameter;     }
+      virtual int inports() const   { return _inports; }
+      virtual int outports() const  { return _outports; }
+      virtual bool inPlaceCapable() const { return _inPlaceCapable; }
+      const LADSPA_Descriptor* ladspaDescriptor() const { return plugin; }
+      virtual bool isLog(int k) const {
+            LADSPA_PortRangeHint r = plugin->PortRangeHints[pIdx[k]];
+            return LADSPA_IS_HINT_LOGARITHMIC(r.HintDescriptor);
+            }
+      virtual bool isBool(int k) const {
+            return LADSPA_IS_HINT_TOGGLED(plugin->PortRangeHints[pIdx[k]].HintDescriptor);
+            }
+      virtual bool isInt(int k) const {
+            LADSPA_PortRangeHint r = plugin->PortRangeHints[pIdx[k]];
+            return LADSPA_IS_HINT_INTEGER(r.HintDescriptor);
+            }
+      virtual void range(int i, float*, float*) const;
+      virtual const char* getParameterName(int i) const {
+            return plugin->PortNames[pIdx[i]];
+            }
+      virtual float defaultValue(int) const;
+      virtual float getControlValue(int k) const {
+            return controls[k].val;
+            }
+
+      int   getGuiControlValue(int parameter) const;
+      float convertGuiControlValue(int parameter, int val) const;
+
+      bool instantiate();
+      bool start();
+      void stop();
+      void connectInport(int k, LADSPA_Data* datalocation);
+      void connectOutport(int k, LADSPA_Data* datalocation);
+      void process(unsigned long);
+      void setParam(int i, float val);
+
+   };
+
+
+static inline float fast_log2 (float val)
+      {
+      /* don't use reinterpret_cast<> because that prevents this
+         from being used by pure C code (for example, GnomeCanvasItems)
+      */
+      int* const exp_ptr = (int *)(&val);
+      int x              = *exp_ptr;
+      const int log_2    = ((x >> 23) & 255) - 128;
+      x &= ~(255 << 23);
+      x += 127 << 23;
+      *exp_ptr = x;
+      val = ((-1.0f/3) * val + 2) * val - 2.0f/3;   // (1)
+      return (val + log_2);
+      }
+
+static inline float fast_log10 (const float val)
+      {
+      return fast_log2(val) / 3.312500f;
+      }
+
+//---------------------------------------------------------
+//   PluginList
+//---------------------------------------------------------
+
+typedef std::list<Plugin*>::iterator iPlugin;
+
+class PluginList : public std::list<Plugin*> {
+   public:
+      Plugin* find(const QString& file, const QString& name);
+      PluginList() {}
+      };
+
+extern void SS_initPlugins();
+extern PluginList plugins;
+
+#endif
diff --git a/muse2/synti/simpledrums2/sspluginchooserbase.ui b/muse2/synti/simpledrums2/sspluginchooserbase.ui
new file mode 100644
index 00000000..63d254df
--- /dev/null
+++ b/muse2/synti/simpledrums2/sspluginchooserbase.ui
@@ -0,0 +1,106 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>SS_PluginChooserBase</class>
+ <widget class="QDialog" name="SS_PluginChooserBase" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>777</width>
+    <height>681</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>SimpleDrums - Ladspa Plugin Chooser</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <property name="margin" >
+    <number>10</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QTreeWidget" name="effectsListView" >
+     <column>
+      <property name="text" >
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text" >
+       <string>Label</string>
+      </property>
+     </column>
+     <column>
+      <property name="text" >
+       <string>Inports</string>
+      </property>
+     </column>
+     <column>
+      <property name="text" >
+       <string>Outports</string>
+      </property>
+     </column>
+     <column>
+      <property name="text" >
+       <string>Creator</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType" >
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>301</width>
+         <height>31</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelButton" >
+       <property name="text" >
+        <string>&amp;Cancel</string>
+       </property>
+       <property name="shortcut" >
+        <string>Alt+C</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="okButton" >
+       <property name="text" >
+        <string>&amp;OK</string>
+       </property>
+       <property name="shortcut" >
+        <string>Alt+O</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/muse2/synti/simpledrums2/ssplugingui.cpp b/muse2/synti/simpledrums2/ssplugingui.cpp
new file mode 100644
index 00000000..0428988b
--- /dev/null
+++ b/muse2/synti/simpledrums2/ssplugingui.cpp
@@ -0,0 +1,530 @@
+//
+// C++ Implementation: ssplugingui
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "ssplugingui.h"
+#include "ssplugin.h"
+#include "simpledrumsgui.h"
+
+#define SS_PLUGINGUI_XOFF       300
+#define SS_PLUGINGUI_YOFF       300
+#define SS_PLUGINGUI_WIDTH      450
+#define SS_PLUGINGUI_MAX_WIDTH  700
+
+#define SS_PLUGINFRONT_MINWIDTH SS_PLUGINGUI_WIDTH
+#define SS_PLUGINFRONT_MINHEIGHT 70
+#define SS_PLUGINFRONT_MARGIN    9
+#define SS_PLUGINFRONT_INC_PARAM    30
+#define SS_PLUGINFRONT_INC_PARAM_MIN 60
+#define SS_PLUGINGUI_HEIGHT (SS_NR_OF_SENDEFFECTS * SS_PLUGINFRONT_MINHEIGHT)
+
+#define SS_PLUGINCHOOSER_NAMECOL     0
+#define SS_PLUGINCHOOSER_LABELCOL    1
+#define SS_PLUGINCHOOSER_INPORTSCOL  2
+#define SS_PLUGINCHOOSER_OUTPORTSCOL 3
+#define SS_PLUGINCHOOSER_CREATORCOL  4
+
+
+/*!
+    \fn SS_PluginChooser::SS_PluginChooser(QWidget* parent, const char* name = 0)
+ */
+SS_PluginChooser::SS_PluginChooser(QWidget* parent)
+      :QDialog(parent)
+      {
+      SS_TRACE_IN
+      setupUi(this);
+      selectedPlugin = 0;
+
+      for (iPlugin i=plugins.begin(); i !=plugins.end(); i++) {
+            //Support for only 2 or 1 inport/outports
+            if ( ((*i)->outports() == 2 || (*i)->outports() == 1) && ((*i)->inports() == 2 || (*i)->inports() == 1) ) {
+                  QTreeWidgetItem* tmpItem = new QTreeWidgetItem(effectsListView);
+                  tmpItem->setText(SS_PLUGINCHOOSER_NAMECOL, (*i)->name());
+                  tmpItem->setText(SS_PLUGINCHOOSER_LABELCOL, (*i)->label());
+                  tmpItem->setText(SS_PLUGINCHOOSER_INPORTSCOL, QString::number((*i)->inports()));
+                  tmpItem->setText(SS_PLUGINCHOOSER_OUTPORTSCOL, QString::number((*i)->outports()));
+                  tmpItem->setText(SS_PLUGINCHOOSER_CREATORCOL, (*i)->maker());
+                  effectsListView->addTopLevelItem(tmpItem);
+                  }
+            }
+      connect(okButton, SIGNAL(pressed()), SLOT(okPressed()));
+      connect(cancelButton, SIGNAL(pressed()), SLOT(cancelPressed()));
+      connect(effectsListView, SIGNAL(selectionChanged(QTreeWidgetItem*)), SLOT(selectionChanged(QTreeWidgetItem*)));
+      connect(effectsListView, SIGNAL(doubleClicked(QTreeWidgetItem*)), SLOT(doubleClicked(QTreeWidgetItem*)));
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginChooser::selectionChanged(QListViewItem* item)
+ */
+void SS_PluginChooser::selectionChanged(QTreeWidgetItem* item)
+      {
+      SS_TRACE_IN
+      selectedItem  = item;
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginChooser::okPressed()
+ */
+void SS_PluginChooser::okPressed()
+      {
+      SS_TRACE_IN
+      selectedPlugin = findSelectedPlugin();
+      done(QDialog::Accepted);
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginChooser::cancelPressed()
+ */
+void SS_PluginChooser::cancelPressed()
+      {
+      SS_TRACE_IN
+      SS_TRACE_OUT
+      done(QDialog::Rejected);
+      }
+
+/*!
+    \fn SS_PluginChooser::doubleClicked(QListViewItem* item)
+ */
+void SS_PluginChooser::doubleClicked(QTreeWidgetItem* /*item*/)
+      {
+      SS_TRACE_IN
+      selectedPlugin = findSelectedPlugin();
+      SS_TRACE_OUT
+      done(QDialog::Accepted);
+      }
+
+/*!
+    \fn SS_PluginChooser::getSelectedPlugin()
+ */
+LadspaPlugin* SS_PluginChooser::findSelectedPlugin()
+      {
+      SS_TRACE_IN
+      LadspaPlugin* selected = 0;
+      for (iPlugin i=plugins.begin(); i != plugins.end(); i++) {
+            if ((*i)->name() == selectedItem->text(SS_PLUGINCHOOSER_NAMECOL))
+                  selected = (LadspaPlugin*) (*i);
+            }
+      SS_TRACE_OUT
+      return selected;
+      }
+
+/*!
+    \fn SS_PluginFront::SS_PluginFront(QWidget* parent, const char* name = 0)
+ */
+SS_PluginFront::SS_PluginFront(QWidget* parent, int in_fxid)
+      : QGroupBox(parent), fxid (in_fxid)
+      {
+      SS_TRACE_IN
+      expanded = false;
+      pluginChooser = 0;
+      plugin = 0;
+      expGroup = 0;
+
+//TD      setLineWidth(3);
+      setFlat(false);
+//TD      setFrameStyle( Q3Frame::Box | Q3Frame::Raised );
+//TD      setFrameShape(QFrame::StyledPanel);
+//      setFrameShadow(Qt::Sunken);
+      setFocusPolicy(Qt::NoFocus);
+      setMinimumSize(SS_PLUGINFRONT_MINWIDTH, SS_PLUGINFRONT_MINHEIGHT);
+      setMaximumSize(SS_PLUGINGUI_MAX_WIDTH, SS_PLUGINFRONT_MINHEIGHT);
+
+      QVBoxLayout* bigLayout = new QVBoxLayout(this);
+      bigLayout->setMargin(SS_PLUGINFRONT_MARGIN);
+      bigLayout->setAlignment(Qt::AlignTop);
+//TODO      bigLayout->setResizeMode(QLayout::SetNoConstraint);
+
+      layout = new QHBoxLayout;
+      bigLayout->addLayout(layout);
+      layout->setAlignment(Qt::AlignVCenter);
+//TODO      layout->setResizeMode(QLayout::SetNoConstraint);
+
+
+      QVBoxLayout* onOffLayout = new QVBoxLayout;
+      layout->addLayout(onOffLayout);
+      onOffLayout->setMargin(SS_PLUGINFRONT_MARGIN);
+      onOff = new QCheckBox(this);
+      onOffLayout->addWidget(new QLabel("On/Off", this));
+      onOffLayout->addWidget(onOff);
+      connect(onOff, SIGNAL(toggled(bool)), SLOT(onOffToggled(bool)));
+
+      pluginName = new QLineEdit(this);
+      pluginName->setReadOnly(true);
+      layout->addWidget(pluginName);
+
+      loadFxButton = new QPushButton("L", this);
+      QRect r = loadFxButton->geometry();
+      loadFxButton->setGeometry(r.x(), r.y(), 20, pluginName->geometry().height());
+      loadFxButton->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+      loadFxButton->setMinimumSize(20,pluginName->geometry().height());
+      loadFxButton->setMaximumSize(30,pluginName->geometry().height());
+      connect(loadFxButton, SIGNAL(clicked()), SLOT(loadButton()));
+      layout->addWidget(loadFxButton);
+
+      clearFxButton = new QPushButton("C", this);
+      r = clearFxButton->geometry();
+      clearFxButton->setGeometry(r.x(), r.y(), 20, pluginName->geometry().height());
+      clearFxButton->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+      clearFxButton->setMinimumSize(20,pluginName->geometry().height());
+      clearFxButton->setMaximumSize(30,pluginName->geometry().height());
+      connect(clearFxButton, SIGNAL(clicked()), SLOT(clearButtonPressed()));
+      layout->addWidget(clearFxButton);
+
+      layout->addSpacing(5);
+
+      expandButton = new QPushButton("->", this);
+      r = loadFxButton->geometry();
+      expandButton->setGeometry(r.x(), r.y(), 20, pluginName->geometry().height());
+      expandButton->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+      expandButton->setMinimumSize(20,pluginName->geometry().height());
+      expandButton->setMaximumSize(30,pluginName->geometry().height());
+      connect(expandButton, SIGNAL(clicked()), SLOT(expandButtonPressed()));
+      layout->addWidget(expandButton);
+
+      layout->addSpacing(5);
+
+      QVBoxLayout* gainSliderLayout = new QVBoxLayout;
+      layout->addLayout(gainSliderLayout);
+      gainSliderLayout->addWidget(new QLabel("Return level", this));
+      gainSliderLayout->setMargin(SS_PLUGINFRONT_MARGIN);
+      outGainSlider = new QSlider(Qt::Horizontal, this);
+      outGainSlider->setMinimumSize(100, pluginName->geometry().height());
+      outGainSlider->setMaximumSize(500, pluginName->geometry().height());
+      loadFxButton->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+      outGainSlider->setRange(0, 127);
+      outGainSlider->setValue(75);
+      connect(outGainSlider, SIGNAL(valueChanged(int)), SLOT(returnSliderMoved(int)));
+      gainSliderLayout->addWidget(outGainSlider);
+      clearPluginDisplay();
+
+      expLayout = new QVBoxLayout; // (bigLayout, 2);
+      bigLayout->addLayout(expLayout);
+
+      clearFxButton->setToolTip(tr("Clear and unload effect"));
+      loadFxButton->setToolTip(tr("Load effect"));
+      expandButton->setToolTip(tr("Toggle display of effect parameters"));
+      onOff->setToolTip(tr("Turn effect on/off"));
+      SS_TRACE_OUT
+      }
+
+SS_PluginFront::~SS_PluginFront()
+      {
+      if (pluginChooser)
+            delete pluginChooser;
+      }
+
+/*!
+    \fn SS_PluginFront::clearPluginDisplay()
+ */
+void SS_PluginFront::clearPluginDisplay()
+      {
+      SS_TRACE_IN
+      if (expanded)
+            expandButtonPressed();
+
+      pluginName->setText("No plugin loaded");
+      pluginName->setEnabled(false);
+      onOff->setEnabled(false);
+      onOff->blockSignals(true);
+      onOff->setChecked(false);
+      onOff->blockSignals(false);
+
+      clearFxButton->setEnabled(false);
+      expandButton->setEnabled(false);
+      outGainSlider->setEnabled(false);
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginFront::setPluginName(QString name)
+ */
+void SS_PluginFront::setPluginName(QString name)
+      {
+      pluginName->setText(name);
+      }
+
+
+/*!
+    \fn SS_PluginFront::loadButton()
+ */
+void SS_PluginFront::loadButton()
+      {
+      SS_TRACE_IN
+      if (!pluginChooser)
+            pluginChooser = new SS_PluginChooser(this);
+
+      pluginChooser->exec();
+      if ((pluginChooser->result() == QDialog::Accepted) && pluginChooser->getSelectedPlugin()) {
+            Plugin* p = pluginChooser->getSelectedPlugin();
+            //printf("Selected plugin: %s\n", pluginChooser->getSelectedPlugin()->name().toLatin1().data());
+            emit loadPlugin(fxid, p->lib(), p->label());
+            }
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginFront::returnSliderMoved(int val)
+ */
+void SS_PluginFront::returnSliderMoved(int val)
+      {
+      emit returnLevelChanged(fxid, val);
+      }
+
+
+/*!
+    \fn SS_PluginFront::updatePluginValue(unsigned i)
+ */
+void SS_PluginFront::updatePluginValue(unsigned k)
+      {
+      SS_TRACE_IN
+      // If parameters are shown - close them
+      if (expanded) {
+            expandButtonPressed();
+            }
+
+      unsigned j=0;
+      if (k > plugins.size()) {
+            fprintf(stderr, "Internal error, tried to update plugin w range outside of list\n");
+            return;
+            }
+
+      iPlugin i;
+      for (i = plugins.begin(); j != k; i++, j++);
+      plugin = (LadspaPlugin*) *(i);
+      setPluginName(plugin->label());
+      outGainSlider->setEnabled(true);
+      clearFxButton->setEnabled(true);
+      expandButton->setEnabled(true);
+      pluginName->setEnabled(true);
+      onOff->setEnabled(true);
+      onOff->setChecked(true);
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginFront::onOffToggled(bool state)
+ */
+void SS_PluginFront::onOffToggled(bool state)
+      {
+      emit fxToggled(fxid, state);
+      }
+
+/*!
+    \fn SS_PluginFront::sizeHint() const
+ */
+QSize SS_PluginFront::sizeHint() const
+      {
+      return QSize(SS_PLUGINFRONT_MINWIDTH, 50);
+      }
+
+/*!
+    \fn SS_PluginFront::sizePolicy() const
+ */
+QSizePolicy SS_PluginFront::sizePolicy() const
+      {
+      return QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+      }
+
+
+/*!
+    \fn SS_PluginFront::clearButtonPressed()
+ */
+void SS_PluginFront::clearButtonPressed()
+      {
+      // If parameters are shown - close them
+      if (expanded) {
+            expandButtonPressed();
+            }
+      emit clearPlugin(fxid);
+      }
+
+/*!
+    \fn SS_PluginFront::setRetGain(int val)
+ */
+void SS_PluginFront::setRetGain(int val)
+      {
+      outGainSlider->blockSignals(true);
+      outGainSlider->setValue(val);
+      outGainSlider->blockSignals(false);
+      }
+
+/*!
+    \fn SS_PluginFront::expandButtonPressed()
+ */
+void SS_PluginFront::expandButtonPressed()
+      {
+      SS_TRACE_IN
+      int sizeIncrease = 0;
+      QRect pf = geometry();
+
+      if (!expanded) {
+            plugin->parameter() == 1 ? sizeIncrease = SS_PLUGINFRONT_INC_PARAM_MIN : sizeIncrease = plugin->parameter() * SS_PLUGINFRONT_INC_PARAM;
+            pf.setHeight(pf.height() + sizeIncrease);
+            setMinimumSize(QSize(pf.width(), pf.height()));
+            setMaximumSize(QSize(SS_PLUGINGUI_MAX_WIDTH, pf.height()));
+            setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+            setGeometry(pf);
+            emit sizeChanged(fxid, sizeIncrease);
+
+            expanded = true;
+            expandButton->setText("<-");
+            createPluginParameters();
+            }
+      else {
+//TODO            expLayout->remove(expGroup);
+            expGroup->hide();
+            expGroup->deleteLater();
+            paramWidgets.clear();
+            expGroup = 0;
+            plugin->parameter() == 1 ? sizeIncrease = (0-SS_PLUGINFRONT_INC_PARAM_MIN) : sizeIncrease = 0 - (plugin->parameter() * SS_PLUGINFRONT_INC_PARAM);
+            expandButton->setText("->");
+            expanded = false;
+            pf.setHeight(pf.height() + sizeIncrease);
+            pf.setTop(pf.top() + sizeIncrease);
+            pf.setBottom(pf.bottom() + sizeIncrease);
+            setGeometry(pf);
+            adjustSize();
+            layout->activate();
+            setMinimumSize(QSize(pf.width(), pf.height()));
+            setMaximumSize(QSize(SS_PLUGINGUI_MAX_WIDTH, pf.height()));
+            setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+            emit sizeChanged(fxid, sizeIncrease);
+            }
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginFront::createPluginParameters()
+ */
+void SS_PluginFront::createPluginParameters()
+      {
+      SS_TRACE_IN
+      expGroup = new QGroupBox(this);
+
+      expGroup->setMinimumSize(QSize(50, 50));
+      expGroup->setMaximumSize(QSize(SS_PLUGINGUI_MAX_WIDTH, (plugin->parameter() * SS_PLUGINFRONT_INC_PARAM  - SS_PLUGINFRONT_MARGIN)));
+      expGroup->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
+      expLayout->addWidget(expGroup);
+      expGroup->show();
+      QVBoxLayout* expGroupLayout = new QVBoxLayout(expGroup); // , 1);
+      expGroupLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
+//TD      expGroupLayout->setResizeMode(QLayout::FreeResize);
+      expGroupLayout->setMargin(SS_PLUGINFRONT_MARGIN);
+
+      for (int i=0; i < plugin->parameter(); i++) {
+            QHBoxLayout* paramStrip = new QHBoxLayout; // (expGroupLayout, 3);
+            expGroupLayout->addLayout(paramStrip);
+            paramStrip->setAlignment(Qt::AlignLeft);
+            QLabel* paramName = new QLabel(plugin->getParameterName(i), expGroup);
+            paramName->show();
+            paramName->setMinimumSize(QSize(150, 10));
+            paramName->setMaximumSize(QSize(300, SS_PLUGINFRONT_INC_PARAM));
+            paramName->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
+
+            paramStrip->addWidget(paramName);
+
+            if (plugin->isBool(i)) {
+                  SS_ParameterCheckBox* paramCheckBox = new SS_ParameterCheckBox(expGroup, plugin, fxid, i);
+                  paramCheckBox->setEnabled(true);
+                  paramCheckBox->setParamValue((int) plugin->getControlValue(i));
+                  paramCheckBox->show();
+                  paramStrip->addWidget(paramCheckBox);
+                  connect(paramCheckBox, SIGNAL(valueChanged(int, int, int)), SLOT(parameterValueChanged(int, int, int)));
+                  }
+            else  {
+                  SS_ParameterSlider* paramSlider = new SS_ParameterSlider(expGroup, plugin, fxid, i);
+                  paramSlider->setEnabled(true);
+                  paramSlider->show();
+                  paramSlider->setRange(SS_PLUGIN_PARAM_MIN, SS_PLUGIN_PARAM_MAX);
+
+                  float max, min;
+                  plugin->range(i, &min, &max);
+                  //int intval = 0;
+                  paramSlider->setParamValue(plugin->getGuiControlValue(i));
+                  connect(paramSlider, SIGNAL(valueChanged(int, int, int)), SLOT(parameterValueChanged(int, int, int)));
+                  paramStrip->addWidget(paramSlider);
+                  }
+            }
+      expLayout->activate();
+      SS_TRACE_OUT
+      }
+
+/*!
+    \fn SS_PluginFront::parameterValueChanged(int fxid, int parameter, int val)
+ */
+void SS_PluginFront::parameterValueChanged(int fxid, int parameter, int val)
+      {
+      emit effectParameterChanged(fxid, parameter, val);
+      }
+
+/*!
+    \fn SS_PluginFront::setParameterValue(int param, float val)
+ */
+void SS_PluginFront::setParameterValue(int param, int val)
+      {
+      SS_TRACE_IN
+      int j=0;
+      for (SS_iParameterWidgetList i=paramWidgets.begin(); i != paramWidgets.end(); i++, j++) {
+            if (j == param) {
+                  (*i)->setParamValue(val);
+                  }
+            }
+      SS_TRACE_OUT
+      }
+
+SS_PluginGui::SS_PluginGui(QWidget* parent)
+      : QDialog(parent, false)
+      {
+      setWindowTitle("SimpleDrums LADSPA sendeffects");
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            pluginFronts[i] = 0;
+            }
+      layout = new QVBoxLayout(this);
+
+      for (int i=0; i<SS_NR_OF_SENDEFFECTS; i++) {
+            pluginFronts[i] = new SS_PluginFront(this, i);
+            pluginFronts[i]->update();
+            layout->addWidget(pluginFronts[i]);
+            connect(pluginFronts[i], SIGNAL(loadPlugin(int, QString, QString)), simplesynthgui_ptr, SLOT(loadEffectInvoked(int, QString, QString)));
+            connect(pluginFronts[i], SIGNAL(returnLevelChanged(int, int)), simplesynthgui_ptr, SLOT(returnLevelChanged(int, int)));
+            connect(pluginFronts[i], SIGNAL(fxToggled(int, int)), simplesynthgui_ptr, SLOT(toggleEffectOnOff(int, int)));
+            connect(pluginFronts[i], SIGNAL(clearPlugin(int)), simplesynthgui_ptr, SLOT(clearPlugin(int)));
+            connect(pluginFronts[i], SIGNAL(sizeChanged(int, int)), SLOT(pluginFrontSizeChanged(int, int)));
+            connect(pluginFronts[i], SIGNAL(effectParameterChanged(int, int, int)), simplesynthgui_ptr, SLOT(effectParameterChanged(int, int, int)));
+            }
+      setMinimumSize(QSize(SS_PLUGINGUI_WIDTH, geometry().height()));
+      setMaximumSize(QSize(SS_PLUGINGUI_MAX_WIDTH, geometry().height()));
+      }
+
+
+/*!
+    \fn SS_PluginGui::pluginFrontSizeChanged(int fxid, int val)
+ */
+void SS_PluginGui::pluginFrontSizeChanged(int /*fxid*/, int val)
+      {
+      QRect r = geometry();
+      r.setHeight(r.height() + val);
+      setMinimumSize(QSize(SS_PLUGINGUI_WIDTH, r.height()));
+      setMaximumSize(QSize(SS_PLUGINGUI_MAX_WIDTH, r.height()));
+      setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+      setGeometry(r);
+      adjustSize();
+      }
+
+SS_PluginFront* SS_PluginGui::getPluginFront(unsigned i)
+      {
+      SS_TRACE_IN
+      if (i<SS_NR_OF_SENDEFFECTS)
+      SS_TRACE_OUT
+      return pluginFronts[i];
+      }
diff --git a/muse2/synti/simpledrums2/ssplugingui.h b/muse2/synti/simpledrums2/ssplugingui.h
new file mode 100644
index 00000000..3d77ecf0
--- /dev/null
+++ b/muse2/synti/simpledrums2/ssplugingui.h
@@ -0,0 +1,204 @@
+//
+// C++ Interface: ssplugingui
+//
+// Description:
+//
+//
+// Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef __SS_PLUGINGUI_H__
+#define __SS_PLUGINGUI_H__
+#include <QDialog>
+#include <QSlider>
+#include <QButtonGroup>
+#include <QtGui>
+//#include <QHBoxLayout>
+//#include <QVBoxLayout>
+
+#include "ui_sspluginchooserbase.h"
+#include "common.h"
+#include "ssplugin.h"
+
+class SS_ParameterWidget
+      {
+   protected:
+      int fxid;
+      int parameter;
+
+      LadspaPlugin* plugin;
+
+   public:
+      SS_ParameterWidget() { }
+      virtual ~SS_ParameterWidget() { }
+      int getFxId() { SS_TRACE_IN SS_TRACE_OUT return fxid; }
+      bool isBool() { SS_TRACE_IN SS_TRACE_OUT return plugin->isBool(parameter); }
+      bool isLog()  { SS_TRACE_IN SS_TRACE_OUT return plugin->isLog(parameter); }
+      bool isInt()  { SS_TRACE_IN SS_TRACE_OUT return plugin->isInt(parameter); }
+      virtual void setParamValue(int) { printf("Virtual function - should not be called!"); };
+      };
+
+class SS_ParameterCheckBox : public QCheckBox, public SS_ParameterWidget
+   {
+   Q_OBJECT
+
+   public:
+      SS_ParameterCheckBox(QWidget* parent, LadspaPlugin* in_plugin, int in_id, int in_parameter)
+         : QCheckBox(parent) , SS_ParameterWidget()
+         {
+         SS_TRACE_IN
+         plugin = in_plugin;
+         fxid = in_id;
+         parameter = in_parameter;
+         connect(this, SIGNAL(clicked()), SLOT(isClicked()));
+         SS_TRACE_OUT
+         }
+
+      virtual void setParamValue(int val) { SS_TRACE_IN setChecked(val); SS_TRACE_OUT}
+
+   private slots:
+      void isClicked() { SS_TRACE_IN emit valueChanged(fxid, parameter, (int)this->isChecked()); SS_TRACE_OUT}
+
+   signals:
+      void valueChanged(int id, int param, int val);
+   };
+
+class SS_ParameterSlider : public QSlider, public SS_ParameterWidget
+   {
+   Q_OBJECT
+
+   public:
+      SS_ParameterSlider(QWidget* parent, LadspaPlugin* in_plugin, int in_id, int in_parameter)
+         : QSlider(Qt::Horizontal, parent), SS_ParameterWidget()
+         {
+         SS_TRACE_IN
+         plugin = in_plugin;
+         fxid = in_id;
+         parameter = in_parameter;
+         SS_TRACE_OUT
+         }
+
+      virtual void setParamValue(int val) { SS_TRACE_IN setValue(val); SS_TRACE_OUT}
+
+   public slots:
+      virtual void setValue(int val) { SS_TRACE_IN QSlider::setValue(val); emit valueChanged(fxid, parameter, val); SS_TRACE_OUT }
+
+   signals:
+      void valueChanged(int id, int param, int val);
+   };
+
+typedef std::list<SS_ParameterWidget*>           SS_ParameterWidgetList;
+typedef std::list<SS_ParameterWidget*>::iterator SS_iParameterWidgetList ;
+
+//-------------------------------
+// SS_PluginChooser
+//-------------------------------
+class SS_PluginChooser : public QDialog, Ui::SS_PluginChooserBase
+{
+   Q_OBJECT
+   private:
+         LadspaPlugin* selectedPlugin;
+   protected:
+
+   public:
+         SS_PluginChooser(QWidget* parent);
+         LadspaPlugin* getSelectedPlugin() { SS_TRACE_IN SS_TRACE_OUT return selectedPlugin; }
+
+   private slots:
+      void okPressed();
+      void cancelPressed();
+      void selectionChanged(QTreeWidgetItem* item);
+      void doubleClicked(QTreeWidgetItem* item);
+
+   private:
+      QTreeWidgetItem* selectedItem;
+      LadspaPlugin* findSelectedPlugin();
+
+};
+
+//-------------------------------
+// SS_PluginGuiFront
+//-------------------------------
+class SS_PluginFront : public QGroupBox
+   {
+   Q_OBJECT
+   private:
+      QHBoxLayout*      layout;
+      QVBoxLayout*      expLayout;
+      QLineEdit*        pluginName;
+      QCheckBox*        onOff;
+      QPushButton*      loadFxButton;
+      QPushButton*      clearFxButton;
+      QPushButton*      expandButton;
+      QSlider*          outGainSlider;
+      SS_PluginChooser* pluginChooser;
+      LadspaPlugin*     plugin;
+      QGroupBox*     expGroup;
+
+      int               fxid;
+      bool              expanded;
+
+      //For effect parameters:
+      SS_ParameterWidgetList  paramWidgets;
+
+   protected:
+
+   public:
+      SS_PluginFront(QWidget* parent, int id);
+      void setPluginName(QString name);
+      ~SS_PluginFront();
+      void updatePluginValue(unsigned i);
+      void clearPluginDisplay();
+      void setParameterValue(int param, int val);
+      void setRetGain(int val);
+
+   protected:
+      virtual QSize sizeHint() const;
+      virtual QSizePolicy sizePolicy() const;
+
+   private slots:
+      void loadButton();
+      void returnSliderMoved(int val);
+      void onOffToggled(bool state);
+      void clearButtonPressed();
+      void expandButtonPressed();
+      void parameterValueChanged(int fxid, int parameter, int val);
+
+   signals:
+      void loadPlugin(int fxid, QString lib, QString name);
+      void returnLevelChanged(int fxid, int val);
+      void fxToggled(int fxid, int state);
+      void clearPlugin(int fxid);
+      void sizeChanged(int fxid, int val);
+      void effectParameterChanged(int fxid, int param, int val);
+
+   private:
+      void createPluginParameters();
+   };
+
+
+//-------------------------------
+// SS_PluginGui
+// Main plugin class, dialog
+//-------------------------------
+class SS_PluginGui : public QDialog
+   {
+   Q_OBJECT
+   private:
+      QVBoxLayout* layout;
+      SS_PluginFront* pluginFronts[4];
+
+   public:
+      SS_PluginGui(QWidget* parent);
+      SS_PluginFront* getPluginFront(unsigned i);
+      ~SS_PluginGui() {}
+private slots:
+    void pluginFrontSizeChanged(int fxid, int val);
+   };
+
+
+#endif
+
diff --git a/muse2/synti/vam/CMakeLists.txt b/muse2/synti/vam/CMakeLists.txt
index b93a5c9d..d146b2f9 100644
--- a/muse2/synti/vam/CMakeLists.txt
+++ b/muse2/synti/vam/CMakeLists.txt
@@ -38,7 +38,7 @@ add_library ( vam SHARED
 #
 set_target_properties ( vam 
    PROPERTIES PREFIX ""
-   COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all-pic.h"
+   COMPILE_FLAGS "-fvisibility=hidden -include ${PROJECT_BINARY_DIR}/all-pic.h"
    )
 
 target_link_libraries(vam
diff --git a/muse2/synti/vam/vam.cpp b/muse2/synti/vam/vam.cpp
index 95b80c13..9d0d6e30 100644
--- a/muse2/synti/vam/vam.cpp
+++ b/muse2/synti/vam/vam.cpp
@@ -1044,7 +1044,12 @@ extern "C" {
             MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
             instantiate,
             };
-
+      // We must compile with -fvisibility=hidden to avoid namespace
+      // conflicts with global variables.
+      // Only visible symbol is "mess_descriptor".
+      // (TODO: all plugins should be compiled this way)
+  
+      __attribute__ ((visibility("default")))
       const MESS* mess_descriptor() { return &descriptor; }
       }
 
-- 
cgit v1.2.3