Index: /branches/tabbedInterface/no_gui/no_gui.pro
===================================================================
--- /branches/tabbedInterface/no_gui/no_gui.pro	(revision 1444)
+++ /branches/tabbedInterface/no_gui/no_gui.pro	(revision 1444)
@@ -0,0 +1,25 @@
+######################################################################
+# Automatically generated by qmake (2.01a) to 26. helmi 14:51:41 2009
+######################################################################
+include(../features.pri)
+
+TARGET = Hydrogen
+INCLUDEPATH += ../ ../libs/hydrogen/include
+INCLUDEPATH += .
+DESTDIR = ..
+
+QT += network xml
+
+CONFIG += qt warn_on precompile_header release
+LIBS += ../libs/liblibhydrogen.a
+PRE_TARGETDEPS = ../libs/liblibhydrogen.a
+
+OBJECTS_DIR = objs
+UI_DIR = objs
+UI_HEADERS_DIR = objs
+UI_SOURCES_DIR = objs
+MOC_DIR = objs
+
+INCLUDEPATH += .
+
+SOURCES += main.cpp
Index: /branches/tabbedInterface/no_gui/main.cpp
===================================================================
--- /branches/tabbedInterface/no_gui/main.cpp	(revision 1455)
+++ /branches/tabbedInterface/no_gui/main.cpp	(revision 1455)
@@ -0,0 +1,346 @@
+/*
+ * A headless attempt for hydrogen
+ * Copyright(c) 2009 by Sebastian Moors
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QLibraryInfo>
+#include "config.h"
+#include "version.h"
+#include <getopt.h>
+
+
+
+#ifdef LASH_SUPPORT
+#include <hydrogen/LashClient.h>
+#endif
+
+#include <hydrogen/Song.h>
+#include <hydrogen/midiMap.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/globals.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/data_path.h>
+#include <hydrogen/h2_exception.h>
+#include <hydrogen/SoundLibrary.h>
+#include <hydrogen/LocalFileMng.h>
+
+#include <iostream>
+using namespace std;
+
+void showInfo();
+void showUsage();
+
+
+#define HAS_ARG 1
+static struct option long_opts[] = {
+        {"driver", required_argument, NULL, 'd'},
+        {"song", required_argument, NULL, 's'},
+        {"version", 0, NULL, 'v'},
+        {"nosplash", 0, NULL, 'n'},
+        {"verbose", optional_argument, NULL, 'V'},
+        {"help", 0, NULL, 'h'},
+	{"install", required_argument, NULL, 'i'},
+	{"drumkit", required_argument, NULL, 'k'},
+        {0, 0, 0, 0},
+};
+
+#define NELEM(a) ( sizeof(a)/sizeof((a)[0]) )
+
+
+
+
+int main(int argc, char *argv[])
+{
+        try {
+                // Options...
+                char *cp;
+                struct option *op;
+                char opts[NELEM(long_opts) * 3 + 1];
+
+                // Build up the short option QString
+                cp = opts;
+                for (op = long_opts; op < &long_opts[NELEM(long_opts)]; op++) {
+                        *cp++ = op->val;
+                        if (op->has_arg)
+                                *cp++ = ':';
+                        if (op->has_arg == optional_argument )
+                                *cp++ = ':';  // gets another one
+                }
+
+
+                // Deal with the options
+                QString songFilename;
+                bool bNoSplash = false;
+                QString sSelectedDriver;
+                bool showVersionOpt = false;
+                const char* logLevelOpt = "Error";
+                bool showHelpOpt = false;
+		QString drumkitName;
+		QString drumkitToLoad;
+
+                int c;
+                for (;;) {
+                        c = getopt_long(argc, argv, opts, long_opts, NULL);
+                        if (c == -1)
+                                break;
+
+                        switch(c) {
+                                case 'd':
+                                        sSelectedDriver = QString::fromLocal8Bit(optarg);
+                                        break;
+
+                                case 's':
+                                        songFilename = QString::fromLocal8Bit(optarg);
+                                        break;
+
+				case 'i':
+					//install h2drumkit
+					drumkitName = QString::fromLocal8Bit(optarg);
+					break;
+
+				case 'k':
+					//load Drumkit
+					drumkitToLoad = QString::fromLocal8Bit(optarg);
+					break;
+
+                                case 'v':
+                                        showVersionOpt = true;
+                                        break;
+
+                                case 'V':
+                                        if( optarg ) {
+                                                logLevelOpt = optarg;
+                                        } else {
+                                                logLevelOpt = "Warning";
+                                        }
+                                        break;
+                                case 'n':
+                                        bNoSplash = true;
+                                        break;
+
+                                case 'h':
+                                case '?':
+                                        showHelpOpt = true;
+                                        break;
+                        }
+                }
+
+                if( showVersionOpt ) {
+                        std::cout << get_version() << std::endl;
+                        exit(0);
+                }
+                showInfo();
+                if( showHelpOpt ) {
+                        showUsage();
+                        exit(0);
+                }
+
+                // Man your battle stations... this is not a drill.
+                Logger::create_instance();
+                MidiMap::create_instance();
+                H2Core::Preferences::create_instance();
+                Object::set_logging_level( logLevelOpt );
+                // See below for H2Core::Hydrogen.
+
+
+                _INFOLOG( QString("Using QT version ") + QString( qVersion() ) );
+                _INFOLOG( "Using data path: " + H2Core::DataPath::get_data_path() );
+
+                H2Core::Preferences *pPref = H2Core::Preferences::get_instance();
+
+#ifdef LASH_SUPPORT
+
+                LashClient::create_instance("hydrogen", "Hydrogen", &argc, &argv);
+                LashClient* lashClient = LashClient::get_instance();
+
+#endif
+		if( ! drumkitName.isEmpty() ){
+		    H2Core::Drumkit::install( drumkitName );
+		    exit(0);
+		}
+
+                if (sSelectedDriver == "auto") {
+                        pPref->m_sAudioDriver = "Auto";
+                }
+                else if (sSelectedDriver == "jack") {
+                        pPref->m_sAudioDriver = "Jack";
+                }
+                else if ( sSelectedDriver == "oss" ) {
+                        pPref->m_sAudioDriver = "Oss";
+                }
+                else if ( sSelectedDriver == "alsa" ) {
+                        pPref->m_sAudioDriver = "Alsa";
+                }
+		if (sSelectedDriver == "CoreAudio") {
+			pPref->m_sAudioDriver = "CoreAudio";
+		}
+
+
+
+
+#ifdef LASH_SUPPORT
+        if ( H2Core::Preferences::get_instance()->useLash() ){
+                if (lashClient->isConnected())
+                {
+                        lash_event_t* lash_event = lashClient->getNextEvent();
+                        if (lash_event && lash_event_get_type(lash_event) == LASH_Restore_File)
+                        {
+                                // notify client that this project was not a new one
+                                lashClient->setNewProject(false);
+
+                                songFilename = "";
+                                songFilename.append( QString::fromLocal8Bit(lash_event_get_string(lash_event)) );
+                                songFilename.append("/hydrogen.h2song");
+
+//				Logger::get_instance()->log("[LASH] Restore file: " + songFilename);
+
+                                lash_event_destroy(lash_event);
+                        }
+                        else if (lash_event)
+                        {
+//				Logger::get_instance()->log("[LASH] ERROR: Instead of restore file got event: " + lash_event_get_type(lash_event));
+                                lash_event_destroy(lash_event);
+                        }
+                }
+        }
+#endif
+                H2Core::Hydrogen::create_instance();
+
+
+
+                // Load default song
+                H2Core::Song *song = NULL;
+                if ( !songFilename.isEmpty() ) {
+                        song = H2Core::Song::load( songFilename );
+                        if (song == NULL) {
+                                song = H2Core::Song::get_empty_song();
+                                song->set_filename( "" );
+                        }
+                }
+                else {
+                        H2Core::Preferences *pref = H2Core::Preferences::get_instance();
+                        bool restoreLastSong = pref->isRestoreLastSongEnabled();
+                        QString filename = pref->getLastSongFilename();
+                        if ( restoreLastSong && ( !filename.isEmpty() )) {
+                                song = H2Core::Song::load( filename );
+                                if (song == NULL) {
+                                        _INFOLOG("Starting with empty song");
+                                        song = H2Core::Song::get_empty_song();
+                                        song->set_filename( "" );
+                                }
+                        }
+                        else {
+                                song = H2Core::Song::get_empty_song();
+                                song->set_filename( "" );
+                        }
+                }
+
+
+                H2Core::Hydrogen::get_instance()->setSong( song );
+                H2Core::Preferences::get_instance()->setLastSongFilename(  songFilename);
+
+
+
+		if( ! drumkitToLoad.isEmpty() ){
+                    H2Core::LocalFileMng* mng;
+                    H2Core::Drumkit* drumkitInfo = mng->loadDrumkit( drumkitToLoad );
+                    H2Core::Hydrogen::get_instance()->loadDrumkit( drumkitInfo );
+		}
+
+                while( true ){
+
+                }
+
+
+                delete pPref;
+                delete H2Core::EventQueue::get_instance();
+                delete H2Core::AudioEngine::get_instance();
+
+                delete MidiMap::get_instance();
+                delete ActionManager::get_instance();
+
+                _INFOLOG( "Quitting..." );
+                cout << "\nBye..." << endl;
+                delete Logger::get_instance();
+
+                int nObj = Object::get_objects_number();
+                if (nObj != 0) {
+                        std::cerr << "\n\n\n " << nObj << " alive objects\n\n" << std::endl << std::endl;
+                        Object::print_object_map();
+                }
+
+
+        }
+        catch ( const H2Core::H2Exception& ex ) {
+                std::cerr << "[main] Exception: " << ex.what() << std::endl;
+        }
+        catch (...) {
+                std::cerr << "[main] Unknown exception X-(" << std::endl;
+        }
+
+        return 0;
+}
+
+
+
+/**
+ * Show some information
+ */
+void showInfo()
+{
+        cout << "\nHydrogen " + get_version() + " [" + __DATE__ + "]  [http://www.hydrogen-music.org]" << endl;
+        cout << "Copyright 2002-2008 Alessandro Cominu" << endl;
+//	_INFOLOG( "Compiled modules: " + QString(COMPILED_FEATURES) << endl;
+
+        if ( Object::is_using_verbose_log() ) {
+                cout << "\nVerbose log mode = active" << endl;
+        }
+
+        cout << "\nHydrogen comes with ABSOLUTELY NO WARRANTY" << endl;
+        cout << "This is free software, and you are welcome to redistribute it" << endl;
+        cout << "under certain conditions. See the file COPYING for details\n" << endl;
+}
+
+
+
+/**
+ * Show the correct usage
+ */
+void showUsage()
+{
+        std::cout << "Usage: hydrogen [-v] [-h] -s file" << std::endl;
+        std::cout << "   -d, --driver AUDIODRIVER - Use the selected audio driver (jack, alsa, oss)" << std::endl;
+        std::cout << "   -s, --song FILE - Load a song (*.h2song) at startup" << std::endl;
+	std::cout << "   -k, --kit drumkit_name - Load a drumkit at startup" << std::endl;
+	std::cout << "   -i, --install FILE - install a drumkit (*.h2drumkit)" << std::endl;
+#ifdef LASH_SUPPORT
+        std::cout << "   --lash-no-start-server - If LASH server not running, don't start" << endl
+                  << "                            it (LASH 0.5.3 and later)." << std::endl;
+        std::cout << "   --lash-no-autoresume - Tell LASH server not to assume I'm returning" << std::endl
+                  << "                          from a crash." << std::endl;
+#endif
+        std::cout << "   -n, --nosplash - Hide splash screen" << std::endl;
+        std::cout << "   -V[Level], --verbose[=Level] - Print a lot of debugging info" << std::endl;
+        std::cout << "                 Level, if present, may be None, Error, Warning, Info, Debug or 0xHHHH" << std::endl;
+        std::cout << "   -v, --version - Show version info" << std::endl;
+        std::cout << "   -h, --help - Show this help message" << std::endl;
+}
Index: /branches/tabbedInterface/plugins/plugins.pro
===================================================================
--- /branches/tabbedInterface/plugins/plugins.pro	(revision 3)
+++ /branches/tabbedInterface/plugins/plugins.pro	(revision 3)
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = wasp
Index: /branches/tabbedInterface/plugins/wasp/wasp_noisifier/wasp_noisifier.pro
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp_noisifier/wasp_noisifier.pro	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp_noisifier/wasp_noisifier.pro	(revision 3)
@@ -0,0 +1,18 @@
+TEMPLATE = lib
+QT -= qt
+QT -= gui
+QT -= core
+DESTDIR = ../../
+INCLUDEPATH += ../include
+SOURCES += noisifier.c
+
+linux-g++* {
+	CONFIG = plugin
+	
+	# there's something weird in linux qmake...this is a simple and ugly workaround
+	QMAKE_LINK_SHLIB_CMD = ld -shared -o libwasp_noisifier.so noisifier.o
+}
+
+win32 {
+	CONFIG = dll
+}
Index: /branches/tabbedInterface/plugins/wasp/wasp_noisifier/noisifier.c
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp_noisifier/noisifier.c	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp_noisifier/noisifier.c	(revision 3)
@@ -0,0 +1,617 @@
+/*
+
+noisifier.c
+
+Noisifier (mono/stereo)
+
+(c)2005 Artemiy Pavlov
+
+*/
+
+/* Includes: */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "ladspa.h"
+
+/* The port numbers for the plugin: */
+
+#define NOISIFIER_TYPE 0
+#define NOISIFIER_DENSITY 1
+#define NOISIFIER_BALANCE 2
+#define NOISIFIER_INPUT1  3
+#define NOISIFIER_OUTPUT1 4
+#define NOISIFIER_INPUT2 5
+#define NOISIFIER_OUTPUT2 6
+
+/* The structure used to hold port connection information and state  */
+
+typedef struct {
+
+	LADSPA_Data * m_pfType;
+	LADSPA_Data * m_pfDensity;
+	LADSPA_Data * m_pfBalance;
+	LADSPA_Data * m_pfInputBuffer1;
+	LADSPA_Data * m_pfOutputBuffer1;
+	LADSPA_Data * m_pfInputBuffer2;
+	LADSPA_Data * m_pfOutputBuffer2;
+  
+	int m_fStep;
+	LADSPA_Data m_fNoise1;
+	LADSPA_Data m_fNoise2;
+
+} Noisifier;
+
+/* Construct a new plugin instance. */
+
+LADSPA_Handle instantiateNoisifier(const LADSPA_Descriptor * Descriptor, unsigned long SampleRate) {
+
+	return malloc(sizeof(Noisifier));
+	
+}
+
+/* Connect a port to a data location. */
+
+void connectPortToNoisifier(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) {
+
+	Noisifier * psNoisifier;
+
+	psNoisifier = (Noisifier *)Instance;
+	
+	switch (Port) {
+		case NOISIFIER_TYPE:
+			psNoisifier->m_pfType = DataLocation;
+    		break;
+		case NOISIFIER_DENSITY:
+			psNoisifier->m_pfDensity = DataLocation;
+    		break;
+		case NOISIFIER_BALANCE:
+			psNoisifier->m_pfBalance = DataLocation;
+    		break;
+  		case NOISIFIER_INPUT1:
+    		psNoisifier->m_pfInputBuffer1 = DataLocation;
+    		break;
+  		case NOISIFIER_OUTPUT1:
+    		psNoisifier->m_pfOutputBuffer1 = DataLocation;
+    		break;
+  		case NOISIFIER_INPUT2:
+    		psNoisifier->m_pfInputBuffer2 = DataLocation;
+    		break;
+  		case NOISIFIER_OUTPUT2:
+		    psNoisifier->m_pfOutputBuffer2 = DataLocation;
+    		break;
+  }
+  
+}
+
+/* Noisifier mono */
+
+void runMonoNoisifier(LADSPA_Handle Instance, unsigned long SampleCount) {
+  
+	LADSPA_Data * pfInput;
+	LADSPA_Data * pfOutput;
+	LADSPA_Data fType;
+	LADSPA_Data fDensity;
+	LADSPA_Data fBalance;
+	
+	LADSPA_Data fNoise = 0;
+	int fStep = 0;
+	
+	LADSPA_Data inputData;
+	LADSPA_Data outputData;
+	
+	Noisifier * psNoisifier;
+	unsigned long lSampleIndex;
+
+	psNoisifier = (Noisifier *)Instance;
+	
+	fType = *(psNoisifier->m_pfType);
+	fDensity = *(psNoisifier->m_pfDensity);
+	fBalance = *(psNoisifier->m_pfBalance);
+	
+	if(fType >= 1.0f && fType < 2.0f){
+	
+		fType = 1;
+		
+		fDensity= 100.0f * (1 - fDensity);
+		
+	}
+	
+	if(fType >= 2.0f && fType < 3.0f){
+	
+		fType = 2;
+		
+		fDensity = 1.0f * pow ((1 - fDensity), 0.1f);
+		
+	}
+	
+	if(fType == 0){
+	
+		fStep = psNoisifier->m_fStep;
+		fNoise = psNoisifier->m_fNoise1;
+		
+		if(fNoise == 0){
+			fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+		}
+		
+	}
+	
+	pfInput = psNoisifier->m_pfInputBuffer1;
+	pfOutput = psNoisifier->m_pfOutputBuffer1;
+		
+	for(lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){	
+	
+		inputData = *(pfInput++);
+		
+		if(fType == 1){
+	
+			fStep = fStep + 1;
+			
+			if(fStep >= fDensity){
+				fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+				fStep = 0;
+			}
+			
+		}
+		
+		if(fType == 2){
+	
+			fNoise = 1.0f * rand()/RAND_MAX;
+			
+			if(fNoise >= fDensity){
+				fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+			} else {
+				fNoise = 0.0f;
+			}
+			
+		}
+		
+		outputData = inputData * fNoise * fBalance + inputData * ( 1 - fBalance );
+		
+		*(pfOutput++) = outputData;
+	}
+	
+	if(fType == 1){
+		psNoisifier->m_fStep = fStep;
+		psNoisifier->m_fNoise1 = fNoise;
+	}
+	
+}
+
+/* Noisifier stereo */
+
+void runStereoNoisifier(LADSPA_Handle Instance, unsigned long SampleCount) {
+  
+	LADSPA_Data * pfInput;
+	LADSPA_Data * pfOutput;
+	LADSPA_Data fType;
+	LADSPA_Data fDensity;
+	LADSPA_Data fBalance;
+	
+	LADSPA_Data fNoise = 0;
+	int fStep = 0;
+	
+	LADSPA_Data inputData;
+	LADSPA_Data outputData;
+	
+	Noisifier * psNoisifier;
+	unsigned long lSampleIndex;
+
+	psNoisifier = (Noisifier *)Instance;
+
+	fType = *(psNoisifier->m_pfType);
+	fDensity = *(psNoisifier->m_pfDensity);
+	fBalance = *(psNoisifier->m_pfBalance);
+	
+	if(fType >= 1.0f && fType < 2.0f){
+	
+		fType = 1;
+		
+		fDensity= 100.0f * (1 - fDensity);
+		
+	}
+	
+	if(fType >= 2.0f && fType < 3.0f){
+	
+		fType = 2;
+		
+		fDensity = 1.0f * pow ((1 - fDensity), 0.1f);
+		
+	}
+	
+	if(fType == 0){
+	
+		fStep = psNoisifier->m_fStep;
+		fNoise = psNoisifier->m_fNoise1;
+		
+		if(fNoise == 0){
+			fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+		}
+		
+	}
+		
+	pfInput = psNoisifier->m_pfInputBuffer1;
+	pfOutput = psNoisifier->m_pfOutputBuffer1;
+  
+	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){
+		
+		inputData = *(pfInput++);
+		
+		if(fType == 1){
+	
+			fStep = fStep + 1;
+			
+			if(fStep >= fDensity){
+				fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+				fStep = 0;
+			}
+			
+		}
+		
+		if(fType == 2){
+	
+			fNoise = 1.0f * rand()/RAND_MAX;
+			
+			if(fNoise >= fDensity){
+				fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+			} else {
+				fNoise = 0.0f;
+			}
+			
+		}
+		
+		outputData = inputData * fNoise * fBalance + inputData * ( 1 - fBalance );
+		
+		*(pfOutput++) = outputData;
+		
+	}
+
+	if(fType == 1){
+		psNoisifier->m_fNoise2 = fNoise;
+	}
+	
+	if(fNoise==0){
+		fNoise = 1.0f * rand()/RAND_MAX;
+	}
+	
+	pfInput = psNoisifier->m_pfInputBuffer2;
+	pfOutput = psNoisifier->m_pfOutputBuffer2;
+  
+	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){
+	
+		inputData = *(pfInput++);
+		
+		if(fType == 1){
+	
+			fStep = fStep + 1;
+			
+			if(fStep >= fDensity){
+				fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+				fStep = 0;
+			}
+			
+		}
+		
+		if(fType == 2){
+	
+			fNoise = 1.0f * rand()/RAND_MAX;
+			
+			if(fNoise >= fDensity){
+				fNoise = 2.0f * rand()/RAND_MAX - 1.0f;
+			} else {
+				fNoise = 0.0f;
+			}
+			
+		}
+		
+		outputData = inputData * fNoise * fBalance + inputData * ( 1 - fBalance );
+		
+		*(pfOutput++) = outputData;
+		
+	}
+	
+	if(fType == 1){
+		psNoisifier->m_fStep = fStep;
+		psNoisifier->m_fNoise2 = fNoise;
+	}
+}
+
+/* Noisifier cleanup */
+
+void cleanupNoisifier(LADSPA_Handle Instance) {
+
+	Noisifier * psNoisifier;
+	psNoisifier = (Noisifier *)Instance;
+
+	free(psNoisifier);
+}
+
+LADSPA_Descriptor * g_psMonoDescriptor = NULL;
+LADSPA_Descriptor * g_psStereoDescriptor = NULL;
+
+/* Noisifier _init() function */
+
+void _init() {
+
+  char ** pcPortNames;
+  LADSPA_PortDescriptor * piPortDescriptors;
+  LADSPA_PortRangeHint * psPortRangeHints;
+
+  g_psMonoDescriptor
+    = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
+  g_psStereoDescriptor 
+    = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
+
+  if (g_psMonoDescriptor) {
+  
+    g_psMonoDescriptor->UniqueID
+      = 2543;
+    g_psMonoDescriptor->Label
+      = strdup("NoisifierM");
+    g_psMonoDescriptor->Properties
+      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
+    g_psMonoDescriptor->Name 
+      = strdup("Noisifier (mono)");
+    g_psMonoDescriptor->Maker
+      = strdup("Artemiy Pavlov");
+    g_psMonoDescriptor->Copyright
+      = strdup("(c)2005 GPL");
+    g_psMonoDescriptor->PortCount
+      = 5;
+    piPortDescriptors
+      = (LADSPA_PortDescriptor *)calloc(5, sizeof(LADSPA_PortDescriptor));
+    g_psMonoDescriptor->PortDescriptors
+      = (const LADSPA_PortDescriptor *)piPortDescriptors;
+	  
+	piPortDescriptors[NOISIFIER_TYPE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[NOISIFIER_DENSITY]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[NOISIFIER_BALANCE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[NOISIFIER_INPUT1]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[NOISIFIER_OUTPUT1]
+	= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	  
+	pcPortNames
+	= (char **)calloc(5, sizeof(char *));
+	g_psMonoDescriptor->PortNames 
+	= (const char **)pcPortNames;
+	  
+	pcPortNames[NOISIFIER_TYPE]
+	= strdup("Noise Type");
+	pcPortNames[NOISIFIER_DENSITY]
+	= strdup("Noise Density");
+	pcPortNames[NOISIFIER_BALANCE]
+	= strdup("Balance");
+	pcPortNames[NOISIFIER_INPUT1]
+	= strdup("Input");
+	pcPortNames[NOISIFIER_OUTPUT1]
+	= strdup("Output");
+	  
+    psPortRangeHints = ((LADSPA_PortRangeHint *)
+		calloc(5, sizeof(LADSPA_PortRangeHint)));
+    g_psMonoDescriptor->PortRangeHints
+	= (const LADSPA_PortRangeHint *)psPortRangeHints;
+	  
+	psPortRangeHints[NOISIFIER_TYPE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[NOISIFIER_TYPE].LowerBound
+	= 1;
+	psPortRangeHints[NOISIFIER_TYPE].UpperBound
+	= 2;
+	  
+	psPortRangeHints[NOISIFIER_DENSITY].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[NOISIFIER_DENSITY].LowerBound
+	= 0;
+	psPortRangeHints[NOISIFIER_DENSITY].UpperBound
+	= 1;
+	 
+	psPortRangeHints[NOISIFIER_BALANCE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[NOISIFIER_BALANCE].LowerBound
+	= 0;
+	psPortRangeHints[NOISIFIER_BALANCE].UpperBound
+	= 1;
+	 
+	psPortRangeHints[NOISIFIER_INPUT1].HintDescriptor
+	= 0;
+	psPortRangeHints[NOISIFIER_OUTPUT1].HintDescriptor
+	= 0;
+	  
+	g_psMonoDescriptor->instantiate 
+	= instantiateNoisifier;
+	g_psMonoDescriptor->connect_port 
+	= connectPortToNoisifier;
+	g_psMonoDescriptor->activate
+	= NULL;
+	g_psMonoDescriptor->run
+	= runMonoNoisifier;
+	g_psMonoDescriptor->run_adding
+	= NULL;
+	g_psMonoDescriptor->set_run_adding_gain
+	= NULL;
+	g_psMonoDescriptor->deactivate
+	= NULL;
+	g_psMonoDescriptor->cleanup
+	= cleanupNoisifier;
+  }
+  
+  if (g_psStereoDescriptor) {
+
+	g_psStereoDescriptor->UniqueID
+	= 2544;
+	g_psStereoDescriptor->Label
+	= strdup("NoisifierS");
+	g_psStereoDescriptor->Properties
+	= LADSPA_PROPERTY_HARD_RT_CAPABLE;
+	g_psStereoDescriptor->Name 
+	= strdup("Noisifier (stereo)");
+	g_psStereoDescriptor->Maker
+	= strdup("Artemiy Pavlov");
+	g_psStereoDescriptor->Copyright
+	= strdup("(c)2005 SineShine");
+	g_psStereoDescriptor->PortCount
+	= 7;
+	piPortDescriptors
+	= (LADSPA_PortDescriptor *)calloc(7, sizeof(LADSPA_PortDescriptor));
+	g_psStereoDescriptor->PortDescriptors
+	= (const LADSPA_PortDescriptor *)piPortDescriptors;
+	  
+	piPortDescriptors[NOISIFIER_TYPE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[NOISIFIER_DENSITY]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[NOISIFIER_BALANCE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[NOISIFIER_INPUT1]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[NOISIFIER_OUTPUT1]
+	= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[NOISIFIER_INPUT2]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[NOISIFIER_OUTPUT2]
+	= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	  
+    pcPortNames
+      = (char **)calloc(7, sizeof(char *));
+    g_psStereoDescriptor->PortNames 
+      = (const char **)pcPortNames;
+	  
+    pcPortNames[NOISIFIER_TYPE]
+      = strdup("Noise Type");
+	pcPortNames[NOISIFIER_DENSITY]
+      = strdup("Noise Density");
+	pcPortNames[NOISIFIER_BALANCE]
+      = strdup("Balance");
+    pcPortNames[NOISIFIER_INPUT1]
+      = strdup("Input L");
+    pcPortNames[NOISIFIER_OUTPUT1]
+      = strdup("Output L");
+    pcPortNames[NOISIFIER_INPUT2]
+      = strdup("Input R");
+    pcPortNames[NOISIFIER_OUTPUT2]
+      = strdup("Output R");
+	  
+    psPortRangeHints = ((LADSPA_PortRangeHint *) 
+		calloc(7, sizeof(LADSPA_PortRangeHint)));
+    g_psStereoDescriptor->PortRangeHints
+	= (const LADSPA_PortRangeHint *)psPortRangeHints;
+	  
+	psPortRangeHints[NOISIFIER_TYPE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[NOISIFIER_TYPE].LowerBound
+	= 1;
+	psPortRangeHints[NOISIFIER_TYPE].UpperBound
+	= 2;
+	  
+	psPortRangeHints[NOISIFIER_DENSITY].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[NOISIFIER_DENSITY].LowerBound
+	= 0;
+	psPortRangeHints[NOISIFIER_DENSITY].UpperBound
+	= 1;
+	  
+	psPortRangeHints[NOISIFIER_BALANCE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[NOISIFIER_BALANCE].LowerBound
+	= 0;
+	psPortRangeHints[NOISIFIER_BALANCE].UpperBound
+	= 1;
+	  
+	psPortRangeHints[NOISIFIER_INPUT1].HintDescriptor
+	 = 0;
+	psPortRangeHints[NOISIFIER_OUTPUT1].HintDescriptor
+	= 0;
+	psPortRangeHints[NOISIFIER_INPUT2].HintDescriptor
+	= 0;
+	psPortRangeHints[NOISIFIER_OUTPUT2].HintDescriptor
+	= 0;
+	  
+	g_psStereoDescriptor->instantiate 
+	= instantiateNoisifier;
+	g_psStereoDescriptor->connect_port 
+	= connectPortToNoisifier;
+	g_psStereoDescriptor->activate
+	= NULL;
+	g_psStereoDescriptor->run
+	= runStereoNoisifier;
+	g_psStereoDescriptor->run_adding
+	= NULL;
+	g_psStereoDescriptor->set_run_adding_gain
+	= NULL;
+	g_psStereoDescriptor->deactivate
+	= NULL;
+	g_psStereoDescriptor->cleanup
+	= cleanupNoisifier;
+	
+  }
+}
+
+void deleteDescriptor(LADSPA_Descriptor * psDescriptor) {
+  unsigned long lIndex;
+  if (psDescriptor) {
+    free((char *)psDescriptor->Label);
+    free((char *)psDescriptor->Name);
+    free((char *)psDescriptor->Maker);
+    free((char *)psDescriptor->Copyright);
+    free((LADSPA_PortDescriptor *)psDescriptor->PortDescriptors);
+    for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++)
+      free((char *)(psDescriptor->PortNames[lIndex]));
+    free((char **)psDescriptor->PortNames);
+    free((LADSPA_PortRangeHint *)psDescriptor->PortRangeHints);
+    free(psDescriptor);
+  }
+}
+
+void _fini() {
+  deleteDescriptor(g_psMonoDescriptor);
+  deleteDescriptor(g_psStereoDescriptor);
+}
+
+
+#ifdef WIN32
+	#define _DLL_EXPORT_ __declspec(dllexport)
+	int bIsFirstTime = 1; 
+	void _init(); // forward declaration
+#else
+	#define _DLL_EXPORT_ 
+#endif
+
+
+
+_DLL_EXPORT_ const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) {
+#ifdef WIN32
+	if (bIsFirstTime) {
+		_init();
+		bIsFirstTime = 0;
+	}
+#endif
+  switch (Index) {
+  case 0:
+    return g_psMonoDescriptor;
+  case 1:
+    return g_psStereoDescriptor;
+  default:
+    return NULL;
+  }
+}
Index: /branches/tabbedInterface/plugins/wasp/LICENSE
===================================================================
--- /branches/tabbedInterface/plugins/wasp/LICENSE	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/LICENSE	(revision 3)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /branches/tabbedInterface/plugins/wasp/include/Gd.h
===================================================================
--- /branches/tabbedInterface/plugins/wasp/include/Gd.h	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/include/Gd.h	(revision 3)
@@ -0,0 +1,23 @@
+#include "stdlib.h"
+#include "math.h"
+
+/*
+
+DSPE: digital signal processing essentials
+
+Gd.h
+Random number generator with Gaussian distribution
+
+(c)2005 Artemiy Pavlov
+http://artemiolabs.com
+
+This program is free software, it may be distributed under the terms
+and conditions of the GNU General Public License version 2 or later.
+
+*/
+
+float Gdrand(float deviation){
+
+	return powf (10, - deviation * powf( (float)(rand()/RAND_MAX) - 1, 2));
+
+}
Index: /branches/tabbedInterface/plugins/wasp/include/LFO.h
===================================================================
--- /branches/tabbedInterface/plugins/wasp/include/LFO.h	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/include/LFO.h	(revision 3)
@@ -0,0 +1,88 @@
+#include "math.h"
+
+/*
+
+DSPE: digital signal processing essentials
+
+LFO.h
+A library of functions to produce various LFO forms
+
+(c)2005 Artemiy Pavlov
+http://artemiolabs.com
+
+This program is free software, it may be distributed under the terms
+and conditions of the GNU General Public License version 2 or later.
+
+*/
+
+/*
+
+Simple triangle LFO
+
+*/
+
+float LFOtri(float step, float period){
+
+	if(step < period/2.0f) {
+		return 1.0f - 2.0f * (step/period);
+	} else {
+		return 2.0f * (step/period) - 1.0f;
+	}
+
+}
+
+/*
+
+Simple sine LFO
+
+*/
+
+float LFOsin(float step, float period){
+
+	return sinf (2.0f * M_PI * (step/period));
+
+}
+
+/*
+
+Saw LFO with variable knee
+
+*/
+
+float LFOsaw(float step, float period, float knee){
+	
+	if(step <= knee*period) {
+		return 1.0f/knee * (1.0f - knee) * step/period;
+	} else {
+		return 1.0f - step/period + knee;
+	}
+
+}
+
+/*
+
+Trapezoid LFO with variable knee
+
+[knee value]	[form]
+
+0.0				square
+0.25			trapezoid
+0.5				triangle
+
+*/
+
+float LFOtrp(float step, float period, float knee){
+
+	if(step < (knee*period)/2.0f) {
+		return (step/period) * 2.0f/knee;
+	} else if(step >= (knee*period)/2.0f && step < period*(1.0f-knee)/2.0f) {
+		return 1.0f;
+	} else if(step >= period*(1.0f-knee)/2.0f && step < period*(1.0f+knee)/2.0f) {
+		return (1.0f - step/(period/2.0f)) * 1.0f/knee;
+	} else if(step >= period*(1.0f+knee)/2.0f && step < period-(knee*period)/2.0f) {
+		return -1.0f;
+	} else {
+		return (step/period - 1.0f) * 2.0f/knee;
+	}
+	
+}
Index: /branches/tabbedInterface/plugins/wasp/include/ladspa.h
===================================================================
--- /branches/tabbedInterface/plugins/wasp/include/ladspa.h	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/include/ladspa.h	(revision 3)
@@ -0,0 +1,603 @@
+/* ladspa.h
+
+   Linux Audio Developer's Simple Plugin API Version 1.1[LGPL].
+   Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
+   Stefan Westerfeld.
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+   
+   This library 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
+   Lesser General Public License for more details.
+   
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+   USA. */
+
+#ifndef LADSPA_INCLUDED
+#define LADSPA_INCLUDED
+
+#define LADSPA_VERSION "1.1"
+#define LADSPA_VERSION_MAJOR 1
+#define LADSPA_VERSION_MINOR 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+
+/* Overview: 
+
+   There is a large number of synthesis packages in use or development
+   on the Linux platform at this time. This API (`The Linux Audio
+   Developer's Simple Plugin API') attempts to give programmers the
+   ability to write simple `plugin' audio processors in C/C++ and link
+   them dynamically (`plug') into a range of these packages (`hosts').
+   It should be possible for any host and any plugin to communicate
+   completely through this interface.
+
+   This API is deliberately short and simple. To achieve compatibility
+   with a range of promising Linux sound synthesis packages it
+   attempts to find the `greatest common divisor' in their logical
+   behaviour. Having said this, certain limiting decisions are
+   implicit, notably the use of a fixed type (LADSPA_Data) for all
+   data transfer and absence of a parameterised `initialisation'
+   phase. See below for the LADSPA_Data typedef.
+
+   Plugins are expected to distinguish between control and audio
+   data. Plugins have `ports' that are inputs or outputs for audio or
+   control data and each plugin is `run' for a `block' corresponding
+   to a short time interval measured in samples. Audio data is
+   communicated using arrays of LADSPA_Data, allowing a block of audio
+   to be processed by the plugin in a single pass. Control data is
+   communicated using single LADSPA_Data values. Control data has a
+   single value at the start of a call to the `run()' or `run_adding()'
+   function, and may be considered to remain this value for its
+   duration. The plugin may assume that all its input and output ports
+   have been connected to the relevant data location (see the
+   `connect_port()' function below) before it is asked to run.
+
+   Plugins will reside in shared object files suitable for dynamic
+   linking by dlopen() and family. The file will provide a number of
+   `plugin types' that can be used to instantiate actual plugins
+   (sometimes known as `plugin instances') that can be connected
+   together to perform tasks.
+
+   This API contains very limited error-handling. */
+
+/*****************************************************************************/
+
+/* Fundamental data type passed in and out of plugin. This data type
+   is used to communicate audio samples and control values. It is
+   assumed that the plugin will work sensibly given any numeric input
+   value although it may have a preferred range (see hints below). 
+
+   For audio it is generally assumed that 1.0f is the `0dB' reference
+   amplitude and is a `normal' signal level. */
+
+typedef float LADSPA_Data;
+
+/*****************************************************************************/
+
+/* Special Plugin Properties: 
+ 
+   Optional features of the plugin type are encapsulated in the
+   LADSPA_Properties type. This is assembled by ORing individual
+   properties together. */
+
+typedef int LADSPA_Properties;
+
+/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
+   real-time dependency (e.g. listens to a MIDI device) and so its
+   output must not be cached or subject to significant latency. */
+#define LADSPA_PROPERTY_REALTIME        0x1
+
+/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
+   may cease to work correctly if the host elects to use the same data
+   location for both input and output (see connect_port()). This
+   should be avoided as enabling this flag makes it impossible for
+   hosts to use the plugin to process audio `in-place.' */
+#define LADSPA_PROPERTY_INPLACE_BROKEN  0x2
+
+/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
+   is capable of running not only in a conventional host but also in a
+   `hard real-time' environment. To qualify for this the plugin must
+   satisfy all of the following:
+
+   (1) The plugin must not use malloc(), free() or other heap memory
+   management within its run() or run_adding() functions. All new
+   memory used in run() must be managed via the stack. These
+   restrictions only apply to the run() function.
+
+   (2) The plugin will not attempt to make use of any library
+   functions with the exceptions of functions in the ANSI standard C
+   and C maths libraries, which the host is expected to provide.
+
+   (3) The plugin will not access files, devices, pipes, sockets, IPC
+   or any other mechanism that might result in process or thread
+   blocking.
+      
+   (4) The plugin will take an amount of time to execute a run() or
+   run_adding() call approximately of form (A+B*SampleCount) where A
+   and B depend on the machine and host in use. This amount of time
+   may not depend on input signals or plugin state. The host is left
+   the responsibility to perform timings to estimate upper bounds for
+   A and B. */
+#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4
+
+#define LADSPA_IS_REALTIME(x)        ((x) & LADSPA_PROPERTY_REALTIME)
+#define LADSPA_IS_INPLACE_BROKEN(x)  ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
+#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)
+
+/*****************************************************************************/
+
+/* Plugin Ports: 
+
+   Plugins have `ports' that are inputs or outputs for audio or
+   data. Ports can communicate arrays of LADSPA_Data (for audio
+   inputs/outputs) or single LADSPA_Data values (for control
+   input/outputs). This information is encapsulated in the
+   LADSPA_PortDescriptor type which is assembled by ORing individual
+   properties together.
+
+   Note that a port must be an input or an output port but not both
+   and that a port must be a control or audio port but not both. */
+
+typedef int LADSPA_PortDescriptor;
+
+/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
+#define LADSPA_PORT_INPUT   0x1
+
+/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
+#define LADSPA_PORT_OUTPUT  0x2
+
+/* Property LADSPA_PORT_CONTROL indicates that the port is a control
+   port. */
+#define LADSPA_PORT_CONTROL 0x4
+
+/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
+   port. */
+#define LADSPA_PORT_AUDIO   0x8
+
+#define LADSPA_IS_PORT_INPUT(x)   ((x) & LADSPA_PORT_INPUT)
+#define LADSPA_IS_PORT_OUTPUT(x)  ((x) & LADSPA_PORT_OUTPUT)
+#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
+#define LADSPA_IS_PORT_AUDIO(x)   ((x) & LADSPA_PORT_AUDIO)
+
+/*****************************************************************************/
+
+/* Plugin Port Range Hints: 
+
+   The host may wish to provide a representation of data entering or
+   leaving a plugin (e.g. to generate a GUI automatically). To make
+   this more meaningful, the plugin should provide `hints' to the host
+   describing the usual values taken by the data.
+   
+   Note that these are only hints. The host may ignore them and the
+   plugin must not assume that data supplied to it is meaningful. If
+   the plugin receives invalid input data it is expected to continue
+   to run without failure and, where possible, produce a sensible
+   output (e.g. a high-pass filter given a negative cutoff frequency
+   might switch to an all-pass mode).
+    
+   Hints are meaningful for all input and output ports but hints for
+   input control ports are expected to be particularly useful.
+   
+   More hint information is encapsulated in the
+   LADSPA_PortRangeHintDescriptor type which is assembled by ORing
+   individual hint types together. Hints may require further
+   LowerBound and UpperBound information.
+
+   All the hint information for a particular port is aggregated in the
+   LADSPA_PortRangeHint structure. */
+
+typedef int LADSPA_PortRangeHintDescriptor;
+
+/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
+   of the LADSPA_PortRangeHint should be considered meaningful. The
+   value in this field should be considered the (inclusive) lower
+   bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
+   specified then the value of LowerBound should be multiplied by the
+   sample rate. */
+#define LADSPA_HINT_BOUNDED_BELOW   0x1
+
+/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
+   of the LADSPA_PortRangeHint should be considered meaningful. The
+   value in this field should be considered the (inclusive) upper
+   bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
+   specified then the value of UpperBound should be multiplied by the
+   sample rate. */
+#define LADSPA_HINT_BOUNDED_ABOVE   0x2
+
+/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
+   considered a Boolean toggle. Data less than or equal to zero should
+   be considered `off' or `false,' and data above zero should be
+   considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
+   conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or
+   LADSPA_HINT_DEFAULT_1. */
+#define LADSPA_HINT_TOGGLED         0x4
+
+/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
+   should be interpreted as multiples of the sample rate. For
+   instance, a frequency range from 0Hz to the Nyquist frequency (half
+   the sample rate) could be requested by this hint in conjunction
+   with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
+   at all must support this hint to retain meaning. */
+#define LADSPA_HINT_SAMPLE_RATE     0x8
+
+/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
+   user will find it more intuitive to view values using a logarithmic
+   scale. This is particularly useful for frequencies and gains. */
+#define LADSPA_HINT_LOGARITHMIC     0x10
+
+/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
+   probably wish to provide a stepped control taking only integer
+   values. Any bounds set should be slightly wider than the actual
+   integer range required to avoid floating point rounding errors. For
+   instance, the integer set {0,1,2,3} might be described as [-0.1,
+   3.1]. */
+#define LADSPA_HINT_INTEGER         0x20
+
+/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal'
+   value for the port that is sensible as a default. For instance,
+   this value is suitable for use as an initial value in a user
+   interface or as a value the host might assign to a control port
+   when the user has not provided one. Defaults are encoded using a
+   mask so only one default may be specified for a port. Some of the
+   hints make use of lower and upper bounds, in which case the
+   relevant bound or bounds must be available and
+   LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting
+   default must be rounded if LADSPA_HINT_INTEGER is present. Default
+   values were introduced in LADSPA v1.1. */
+#define LADSPA_HINT_DEFAULT_MASK    0x3C0
+
+/* This default values indicates that no default is provided. */
+#define LADSPA_HINT_DEFAULT_NONE    0x0
+
+/* This default hint indicates that the suggested lower bound for the
+   port should be used. */
+#define LADSPA_HINT_DEFAULT_MINIMUM 0x40
+
+/* This default hint indicates that a low value between the suggested
+   lower and upper bounds should be chosen. For ports with
+   LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 +
+   log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper
+   * 0.25). */
+#define LADSPA_HINT_DEFAULT_LOW     0x80
+
+/* This default hint indicates that a middle value between the
+   suggested lower and upper bounds should be chosen. For ports with
+   LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 +
+   log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper *
+   0.5). */
+#define LADSPA_HINT_DEFAULT_MIDDLE  0xC0
+
+/* This default hint indicates that a high value between the suggested
+   lower and upper bounds should be chosen. For ports with
+   LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 +
+   log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper
+   * 0.75). */
+#define LADSPA_HINT_DEFAULT_HIGH    0x100
+
+/* This default hint indicates that the suggested upper bound for the
+   port should be used. */
+#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140
+
+/* This default hint indicates that the number 0 should be used. Note
+   that this default may be used in conjunction with
+   LADSPA_HINT_TOGGLED. */
+#define LADSPA_HINT_DEFAULT_0       0x200
+
+/* This default hint indicates that the number 1 should be used. Note
+   that this default may be used in conjunction with
+   LADSPA_HINT_TOGGLED. */
+#define LADSPA_HINT_DEFAULT_1       0x240
+
+/* This default hint indicates that the number 100 should be used. */
+#define LADSPA_HINT_DEFAULT_100     0x280
+
+/* This default hint indicates that the Hz frequency of `concert A'
+   should be used. This will be 440 unless the host uses an unusual
+   tuning convention, in which case it may be within a few Hz. */
+#define LADSPA_HINT_DEFAULT_440     0x2C0
+
+#define LADSPA_IS_HINT_BOUNDED_BELOW(x)   ((x) & LADSPA_HINT_BOUNDED_BELOW)
+#define LADSPA_IS_HINT_BOUNDED_ABOVE(x)   ((x) & LADSPA_HINT_BOUNDED_ABOVE)
+#define LADSPA_IS_HINT_TOGGLED(x)         ((x) & LADSPA_HINT_TOGGLED)
+#define LADSPA_IS_HINT_SAMPLE_RATE(x)     ((x) & LADSPA_HINT_SAMPLE_RATE)
+#define LADSPA_IS_HINT_LOGARITHMIC(x)     ((x) & LADSPA_HINT_LOGARITHMIC)
+#define LADSPA_IS_HINT_INTEGER(x)         ((x) & LADSPA_HINT_INTEGER)
+
+#define LADSPA_IS_HINT_HAS_DEFAULT(x)     ((x) & LADSPA_HINT_DEFAULT_MASK)
+#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_MINIMUM)
+#define LADSPA_IS_HINT_DEFAULT_LOW(x)     (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_LOW)
+#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x)  (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_MIDDLE)
+#define LADSPA_IS_HINT_DEFAULT_HIGH(x)    (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_HIGH)
+#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_MAXIMUM)
+#define LADSPA_IS_HINT_DEFAULT_0(x)       (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_0)
+#define LADSPA_IS_HINT_DEFAULT_1(x)       (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_1)
+#define LADSPA_IS_HINT_DEFAULT_100(x)     (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                           == LADSPA_HINT_DEFAULT_100)
+#define LADSPA_IS_HINT_DEFAULT_440(x)     (((x) & LADSPA_HINT_DEFAULT_MASK)   \
+                                            == LADSPA_HINT_DEFAULT_440)
+
+typedef struct _LADSPA_PortRangeHint {
+
+  /* Hints about the port. */
+  LADSPA_PortRangeHintDescriptor HintDescriptor;
+
+  /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
+     LADSPA_HINT_SAMPLE_RATE is also active then this value should be
+     multiplied by the relevant sample rate. */
+  LADSPA_Data LowerBound;
+
+  /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
+     LADSPA_HINT_SAMPLE_RATE is also active then this value should be
+     multiplied by the relevant sample rate. */
+  LADSPA_Data UpperBound;
+
+} LADSPA_PortRangeHint;
+
+/*****************************************************************************/
+
+/* Plugin Handles: 
+
+   This plugin handle indicates a particular instance of the plugin
+   concerned. It is valid to compare this to NULL (0 for C++) but
+   otherwise the host should not attempt to interpret it. The plugin
+   may use it to reference internal instance data. */
+
+typedef void * LADSPA_Handle;
+
+/*****************************************************************************/
+
+/* Descriptor for a Type of Plugin: 
+
+   This structure is used to describe a plugin type. It provides a
+   number of functions to examine the type, instantiate it, link it to
+   buffers and workspaces and to run it. */
+
+typedef struct _LADSPA_Descriptor { 
+
+  /* This numeric identifier indicates the plugin type
+     uniquely. Plugin programmers may reserve ranges of IDs from a
+     central body to avoid clashes. Hosts may assume that IDs are
+     below 0x1000000. */
+  unsigned long UniqueID;
+
+  /* This identifier can be used as a unique, case-sensitive
+     identifier for the plugin type within the plugin file. Plugin
+     types should be identified by file and label rather than by index
+     or plugin name, which may be changed in new plugin
+     versions. Labels must not contain white-space characters. */
+  const char * Label;
+
+  /* This indicates a number of properties of the plugin. */
+  LADSPA_Properties Properties;
+
+  /* This member points to the null-terminated name of the plugin
+     (e.g. "Sine Oscillator"). */
+  const char * Name;
+
+  /* This member points to the null-terminated string indicating the
+     maker of the plugin. This can be an empty string but not NULL. */
+  const char * Maker;
+
+  /* This member points to the null-terminated string indicating any
+     copyright applying to the plugin. If no Copyright applies the
+     string "None" should be used. */
+  const char * Copyright;
+
+  /* This indicates the number of ports (input AND output) present on
+     the plugin. */
+  unsigned long PortCount;
+
+  /* This member indicates an array of port descriptors. Valid indices
+     vary from 0 to PortCount-1. */
+  const LADSPA_PortDescriptor * PortDescriptors;
+
+  /* This member indicates an array of null-terminated strings
+     describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
+     0 to PortCount-1. */
+  const char * const * PortNames;
+
+  /* This member indicates an array of range hints for each port (see
+     above). Valid indices vary from 0 to PortCount-1. */
+  const LADSPA_PortRangeHint * PortRangeHints;
+
+  /* This may be used by the plugin developer to pass any custom
+     implementation data into an instantiate call. It must not be used
+     or interpreted by the host. It is expected that most plugin
+     writers will not use this facility as LADSPA_Handle should be
+     used to hold instance data. */
+  void * ImplementationData;
+
+  /* This member is a function pointer that instantiates a plugin. A
+     handle is returned indicating the new plugin instance. The
+     instantiation function accepts a sample rate as a parameter. The
+     plugin descriptor from which this instantiate function was found
+     must also be passed. This function must return NULL if
+     instantiation fails. 
+
+     Note that instance initialisation should generally occur in
+     activate() rather than here. */
+  LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
+                               unsigned long                     SampleRate);
+
+  /* This member is a function pointer that connects a port on an
+     instantiated plugin to a memory location at which a block of data
+     for the port will be read/written. The data location is expected
+     to be an array of LADSPA_Data for audio ports or a single
+     LADSPA_Data value for control ports. Memory issues will be
+     managed by the host. The plugin must read/write the data at these
+     locations every time run() or run_adding() is called and the data
+     present at the time of this connection call should not be
+     considered meaningful.
+
+     connect_port() may be called more than once for a plugin instance
+     to allow the host to change the buffers that the plugin is
+     reading or writing. These calls may be made before or after
+     activate() or deactivate() calls.
+
+     connect_port() must be called at least once for each port before
+     run() or run_adding() is called. When working with blocks of
+     LADSPA_Data the plugin should pay careful attention to the block
+     size passed to the run function as the block allocated may only
+     just be large enough to contain the block of samples.
+
+     Plugin writers should be aware that the host may elect to use the
+     same buffer for more than one port and even use the same buffer
+     for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
+     However, overlapped buffers or use of a single buffer for both
+     audio and control data may result in unexpected behaviour. */
+   void (*connect_port)(LADSPA_Handle Instance,
+                        unsigned long Port,
+                        LADSPA_Data * DataLocation);
+
+  /* This member is a function pointer that initialises a plugin
+     instance and activates it for use. This is separated from
+     instantiate() to aid real-time support and so that hosts can
+     reinitialise a plugin instance by calling deactivate() and then
+     activate(). In this case the plugin instance must reset all state
+     information dependent on the history of the plugin instance
+     except for any data locations provided by connect_port() and any
+     gain set by set_run_adding_gain(). If there is nothing for
+     activate() to do then the plugin writer may provide a NULL rather
+     than an empty function.
+
+     When present, hosts must call this function once before run() (or
+     run_adding()) is called for the first time. This call should be
+     made as close to the run() call as possible and indicates to
+     real-time plugins that they are now live. Plugins should not rely
+     on a prompt call to run() after activate(). activate() may not be
+     called again unless deactivate() is called first. Note that
+     connect_port() may be called before or after a call to
+     activate(). */
+  void (*activate)(LADSPA_Handle Instance);
+
+  /* This method is a function pointer that runs an instance of a
+     plugin for a block. Two parameters are required: the first is a
+     handle to the particular instance to be run and the second
+     indicates the block size (in samples) for which the plugin
+     instance may run.
+
+     Note that if an activate() function exists then it must be called
+     before run() or run_adding(). If deactivate() is called for a
+     plugin instance then the plugin instance may not be reused until
+     activate() has been called again.
+
+     If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
+     then there are various things that the plugin should not do
+     within the run() or run_adding() functions (see above). */
+  void (*run)(LADSPA_Handle Instance,
+              unsigned long SampleCount);
+
+  /* This method is a function pointer that runs an instance of a
+     plugin for a block. This has identical behaviour to run() except
+     in the way data is output from the plugin. When run() is used,
+     values are written directly to the memory areas associated with
+     the output ports. However when run_adding() is called, values
+     must be added to the values already present in the memory
+     areas. Furthermore, output values written must be scaled by the
+     current gain set by set_run_adding_gain() (see below) before
+     addition.
+
+     run_adding() is optional. When it is not provided by a plugin,
+     this function pointer must be set to NULL. When it is provided,
+     the function set_run_adding_gain() must be provided also. */
+  void (*run_adding)(LADSPA_Handle Instance,
+                     unsigned long SampleCount);
+
+  /* This method is a function pointer that sets the output gain for
+     use when run_adding() is called (see above). If this function is
+     never called the gain is assumed to default to 1. Gain
+     information should be retained when activate() or deactivate()
+     are called.
+
+     This function should be provided by the plugin if and only if the
+     run_adding() function is provided. When it is absent this
+     function pointer must be set to NULL. */
+  void (*set_run_adding_gain)(LADSPA_Handle Instance,
+                              LADSPA_Data   Gain);
+
+  /* This is the counterpart to activate() (see above). If there is
+     nothing for deactivate() to do then the plugin writer may provide
+     a NULL rather than an empty function.
+
+     Hosts must deactivate all activated units after they have been
+     run() (or run_adding()) for the last time. This call should be
+     made as close to the last run() call as possible and indicates to
+     real-time plugins that they are no longer live. Plugins should
+     not rely on prompt deactivation. Note that connect_port() may be
+     called before or after a call to deactivate().
+
+     Deactivation is not similar to pausing as the plugin instance
+     will be reinitialised when activate() is called to reuse it. */
+  void (*deactivate)(LADSPA_Handle Instance);
+
+  /* Once an instance of a plugin has been finished with it can be
+     deleted using the following function. The instance handle passed
+     ceases to be valid after this call.
+  
+     If activate() was called for a plugin instance then a
+     corresponding call to deactivate() must be made before cleanup()
+     is called. */
+  void (*cleanup)(LADSPA_Handle Instance);
+
+} LADSPA_Descriptor;
+
+/**********************************************************************/
+
+/* Accessing a Plugin: */
+
+/* The exact mechanism by which plugins are loaded is host-dependent,
+   however all most hosts will need to know is the name of shared
+   object file containing the plugin types. To allow multiple hosts to
+   share plugin types, hosts may wish to check for environment
+   variable LADSPA_PATH. If present, this should contain a
+   colon-separated path indicating directories that should be searched
+   (in order) when loading plugin types.
+
+   A plugin programmer must include a function called
+   "ladspa_descriptor" with the following function prototype within
+   the shared object file. This function will have C-style linkage (if
+   you are using C++ this is taken care of by the `extern "C"' clause
+   at the top of the file).
+
+   A host will find the plugin shared object file by one means or
+   another, find the ladspa_descriptor() function, call it, and
+   proceed from there.
+
+   Plugin types are accessed by index (not ID) using values from 0
+   upwards. Out of range indexes must result in this function
+   returning NULL, so the plugin count can be determined by checking
+   for the least index that results in NULL being returned. */
+
+const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);
+
+/* Datatype corresponding to the ladspa_descriptor() function. */
+typedef const LADSPA_Descriptor * 
+(*LADSPA_Descriptor_Function)(unsigned long Index);
+
+/**********************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LADSPA_INCLUDED */
+
+/* EOF */
Index: /branches/tabbedInterface/plugins/wasp/include/waveshaper.h
===================================================================
--- /branches/tabbedInterface/plugins/wasp/include/waveshaper.h	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/include/waveshaper.h	(revision 3)
@@ -0,0 +1,95 @@
+#include "math.h"
+
+/*
+
+Wave shaper curve functions
+
+(c)2005 Artemiy Pavlov
+Sineshine sonic innovations - http://sineshine.com
+
+This program is free software, it may be distributed under the terms
+and conditions of the GNU General Public License version 2 or later.
+
+*/
+
+float waveshaper_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_double_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) * sin ( 4 * M_PI * curve * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_triple_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) * sin ( 4 * M_PI * curve * signal) * sin ( 8 * M_PI * curve * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_quadruple_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) * sin ( 4 * M_PI * curve * signal) * sin ( 6 * M_PI * curve * signal) * sin ( 8 * M_PI * curve * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_morph_double_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) * sin ( 4 * M_PI * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_morph_triple_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) * sin ( 4 * M_PI * curve * signal) * sin ( 6 * M_PI * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_morph_quadruple_sine( float signal , float curve ){
+
+	signal = (0.5f * sin ( 2 * M_PI * curve * signal) * sin ( 4 * M_PI * signal) * sin ( 6 * M_PI * curve * signal) * sin ( 8 * M_PI * signal) + 0.5f) * signal;
+	
+	return signal;
+
+}
+
+float waveshaper_rect_sine( float signal , float curve ){
+
+	float value = sin ( 2 * M_PI * curve * signal);
+	
+	if( value < 0.0f )
+		value = -value;
+
+	signal = (0.5f * value + 0.5f) * signal;
+
+	return signal;
+
+}
+
+float waveshaper_nonlin_rect_sine( float signal , float curve ){
+
+	float value = sin ( 2 * M_PI * curve * pow (signal, 1/(curve+1)));
+	
+	if( value < 0.0f )
+		value = -value;
+
+	signal = (0.5f * value + 0.5f) * signal;
+	
+	return signal;
+
+}
Index: /branches/tabbedInterface/plugins/wasp/wasp_xshaper/wasp_xshaper.pro
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp_xshaper/wasp_xshaper.pro	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp_xshaper/wasp_xshaper.pro	(revision 3)
@@ -0,0 +1,17 @@
+TEMPLATE = lib
+QT -= qt
+QT -= gui
+QT -= core
+DESTDIR = ../../
+INCLUDEPATH += ../include
+SOURCES += xshaper.c
+
+linux-g++* {
+	CONFIG = plugin
+	# there's something weird in linux qmake...this is a simple and ugly workaround
+	QMAKE_LINK_SHLIB_CMD = ld -shared -o libwasp_xshaper.so xshaper.o
+}
+
+win32 {
+	CONFIG = dll
+}
Index: /branches/tabbedInterface/plugins/wasp/wasp_xshaper/xshaper.c
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp_xshaper/xshaper.c	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp_xshaper/xshaper.c	(revision 3)
@@ -0,0 +1,1350 @@
+/*
+
+x-shaper.c
+
+Multi-mode wave shaper (mono/stereo)
+
+(c)2005 Artemiy Pavlov
+
+*/
+
+/* Includes: */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "ladspa.h"
+#include "waveshaper.h"
+#include "LFO.h"
+
+/* The port numbers for the plugin: */
+
+#define XSHAPER_GAIN 0
+#define XSHAPER_TYPE 1
+#define XSHAPER_CURVE 2
+#define XSHAPER_AMOUNT 3
+#define XSHAPER_LFO1FORM 4
+#define XSHAPER_LFO1RATE 5
+#define XSHAPER_LFO1DEPTH 6
+#define XSHAPER_LFO2FORM 7
+#define XSHAPER_LFO2RATE 8
+#define XSHAPER_LFO2DEPTH 9
+#define XSHAPER_INPUT1  10
+#define XSHAPER_OUTPUT1 11
+#define XSHAPER_INPUT2 12
+#define XSHAPER_OUTPUT2 13
+
+#define XSHAPER_TYPES 9
+#define XSHAPER_LFOTYPES 5
+
+/* The structure used to hold port connection information and state  */
+
+typedef struct {
+	
+	unsigned long SampleRate;
+
+	LADSPA_Data * m_pfGain;
+	LADSPA_Data * m_pfCurve;
+	LADSPA_Data * m_pfType;
+	LADSPA_Data * m_pfAmount;
+	LADSPA_Data * m_pfLFO1Form;
+	LADSPA_Data * m_pfLFO1Rate;
+	LADSPA_Data * m_pfLFO1Depth;
+	LADSPA_Data * m_pfLFO2Form;
+	LADSPA_Data * m_pfLFO2Rate;
+	LADSPA_Data * m_pfLFO2Depth;
+	LADSPA_Data * m_pfInputBuffer1;
+	LADSPA_Data * m_pfOutputBuffer1;
+	LADSPA_Data * m_pfInputBuffer2;
+	LADSPA_Data * m_pfOutputBuffer2;
+
+	LADSPA_Data m_fGainLast;
+	LADSPA_Data m_fCurveLast;
+	LADSPA_Data m_fAmountLast;
+	LADSPA_Data m_fLFO1RateLast;
+	LADSPA_Data m_fLFO2RateLast;
+	LADSPA_Data m_fLFO1DepthLast;
+	LADSPA_Data m_fLFO2DepthLast;
+	
+	float m_fLFO1Step;
+	float m_fLFO2Step;
+
+} XShaper;
+
+/* Construct a new plugin instance. */
+
+LADSPA_Handle instantiateXShaper(const LADSPA_Descriptor * Descriptor, unsigned long SampleRate) {
+
+	XShaper *mp = calloc(sizeof(XShaper),1);
+
+	mp->SampleRate = SampleRate;
+	
+	return mp;
+	
+}
+
+/* Connect a port to a data location. */
+
+void connectPortToXShaper(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) {
+
+	XShaper * psXShaper;
+
+	psXShaper = (XShaper *)Instance;
+	
+	switch (Port) {
+		case XSHAPER_GAIN:
+			psXShaper->m_pfGain = DataLocation;
+    		break;
+		case XSHAPER_TYPE:
+			psXShaper->m_pfType = DataLocation;
+    		break;
+		case XSHAPER_CURVE:
+			psXShaper->m_pfCurve = DataLocation;
+    		break;
+		case XSHAPER_AMOUNT:
+			psXShaper->m_pfAmount = DataLocation;
+    		break;
+		case XSHAPER_LFO1FORM:
+			psXShaper->m_pfLFO1Form = DataLocation;
+    		break;
+		case XSHAPER_LFO1RATE:
+			psXShaper->m_pfLFO1Rate = DataLocation;
+    		break;
+		case XSHAPER_LFO1DEPTH:
+			psXShaper->m_pfLFO1Depth = DataLocation;
+    		break;
+		case XSHAPER_LFO2FORM:
+			psXShaper->m_pfLFO2Form = DataLocation;
+    		break;
+		case XSHAPER_LFO2RATE:
+			psXShaper->m_pfLFO2Rate = DataLocation;
+    		break;
+		case XSHAPER_LFO2DEPTH:
+			psXShaper->m_pfLFO2Depth = DataLocation;
+    		break;
+  		case XSHAPER_INPUT1:
+    		psXShaper->m_pfInputBuffer1 = DataLocation;
+    		break;
+  		case XSHAPER_OUTPUT1:
+    		psXShaper->m_pfOutputBuffer1 = DataLocation;
+    		break;
+  		case XSHAPER_INPUT2:
+    		psXShaper->m_pfInputBuffer2 = DataLocation;
+    		break;
+  		case XSHAPER_OUTPUT2:
+		    psXShaper->m_pfOutputBuffer2 = DataLocation;
+    		break;
+  }
+  
+}
+
+/* XShaper mono */
+
+void runMonoXShaper(LADSPA_Handle Instance, unsigned long SampleCount) {
+  
+	/* audio i/o */
+	
+	unsigned long fSampleRate;
+	
+	LADSPA_Data * pfInput;
+	LADSPA_Data * pfOutput;
+	LADSPA_Data inputData;
+	LADSPA_Data outputData;
+	
+	/* input params */
+	
+	LADSPA_Data fGain;
+	LADSPA_Data fType;
+	LADSPA_Data fCurve;
+	LADSPA_Data fAmount;
+	
+	LADSPA_Data fLFO1Form;
+	LADSPA_Data fLFO1Rate;
+	LADSPA_Data fLFO1Depth;
+	float fLFO1Step;
+	LADSPA_Data fLFO1Period;
+	LADSPA_Data fLFO1Value = 0.0f;
+	
+	LADSPA_Data fLFO2Form;
+	LADSPA_Data fLFO2Rate;
+	LADSPA_Data fLFO2Depth;
+	float fLFO2Step;
+	LADSPA_Data fLFO2Period;
+	LADSPA_Data fLFO2Value = 0.0f;
+	
+	/* interpolation */
+	
+	LADSPA_Data rCurve;
+	LADSPA_Data fGainLast;
+	LADSPA_Data fCurveLast;
+	LADSPA_Data fAmountLast;
+	LADSPA_Data fLFO1RateLast;
+	LADSPA_Data fLFO2RateLast;
+	LADSPA_Data fLFO1DepthLast;
+	LADSPA_Data fLFO2DepthLast;
+	LADSPA_Data dGain;
+	LADSPA_Data dCurve;
+	LADSPA_Data dAmount;
+	LADSPA_Data dLFO1Rate;
+	LADSPA_Data dLFO2Rate;
+	LADSPA_Data dLFO1Depth;
+	LADSPA_Data dLFO2Depth;
+
+	XShaper * psXShaper;
+	unsigned long lSampleIndex;
+
+	psXShaper = (XShaper *)Instance;
+	
+	fSampleRate = psXShaper->SampleRate;
+	
+	fGain = *(psXShaper->m_pfGain);
+	fType = *(psXShaper->m_pfType);
+	fCurve = *(psXShaper->m_pfCurve);
+	fAmount = *(psXShaper->m_pfAmount);
+	fLFO1Form = *(psXShaper->m_pfLFO1Form);
+	fLFO1Rate = *(psXShaper->m_pfLFO1Rate);
+	fLFO1Depth = *(psXShaper->m_pfLFO1Depth);
+	fLFO2Form = *(psXShaper->m_pfLFO2Form);
+	fLFO2Rate = *(psXShaper->m_pfLFO2Rate);
+	fLFO2Depth = *(psXShaper->m_pfLFO2Depth);
+	
+	if(fLFO1Rate < 0.001f)
+		fLFO1Rate = 0.001f;
+	
+	if(fLFO2Rate < 0.001f)
+		fLFO2Rate = 0.001f;
+	
+	if(fType >= 0.0f && fType <= 1.0f){
+		fType = 1;
+	} else if(fType > 1.0f && fType <= 2.0f){
+		fType = 2;
+	} else if(fType > 2.0f && fType <= 3.0f){
+		fType = 3;
+	} else if(fType > 3.0f && fType <= 4.0f){
+		fType = 4;
+	} else if(fType > 4.0f && fType <= 5.0f){
+		fType = 5;
+	} else if(fType > 5.0f && fType <= 6.0f){
+		fType = 6;
+	} else if(fType > 6.0f && fType <= 7.0f){
+		fType = 7;
+	} else if(fType > 7.0f && fType <= 8.0f){
+		fType = 8;
+	} else if(fType > 8.0f && fType <= 9.0f){
+		fType = 9;
+	}
+	
+	if(fLFO1Form >= 0.0f && fLFO1Form <= 1.0f){
+		fLFO1Form = 1;
+	} else if(fLFO1Form > 1.0f && fLFO1Form <= 2.0f){
+		fLFO1Form = 2;
+	} else if(fLFO1Form > 2.0f && fLFO1Form <= 3.0f){
+		fLFO1Form = 3;
+	} else if(fLFO1Form > 3.0f && fLFO1Form <= 4.0f){
+		fLFO1Form = 4;
+	} else if(fLFO1Form > 4.0f && fLFO1Form <= 5.0f){
+		fLFO1Form = 5;
+	} else {
+		fLFO1Form = 1;
+	}
+	
+	if(fLFO2Form >= 0.0f && fLFO2Form <= 1.0f){
+		fLFO2Form = 1;
+	} else if(fLFO2Form > 1.0f && fLFO2Form <= 2.0f){
+		fLFO2Form = 2;
+	} else if(fLFO2Form > 2.0f && fLFO2Form <= 3.0f){
+		fLFO2Form = 3;
+	} else if(fLFO2Form > 3.0f && fLFO2Form <= 4.0f){
+		fLFO2Form = 4;
+	} else if(fLFO2Form > 4.0f && fLFO2Form <= 5.0f){
+		fLFO2Form = 5;
+	} else {
+		fLFO2Form = 1;
+	}
+	
+	fLFO1Step = psXShaper->m_fLFO1Step;
+	fLFO2Step = psXShaper->m_fLFO2Step;
+	
+	if(!fLFO1Step)
+		fLFO1Step = 0;
+	if(!fLFO2Step)
+		fLFO2Step = 0;
+	
+	fGainLast = psXShaper->m_fGainLast;
+	fCurveLast = psXShaper->m_fCurveLast;
+	fAmountLast = psXShaper->m_fAmountLast;
+	fLFO1RateLast = psXShaper->m_fLFO1RateLast;
+	fLFO2RateLast = psXShaper->m_fLFO2RateLast;
+	fLFO1DepthLast = psXShaper->m_fLFO1DepthLast;
+	fLFO2DepthLast = psXShaper->m_fLFO2DepthLast;
+	
+	if(!fGainLast)
+		fGainLast = fGain;
+		
+	if(!fCurveLast)
+		fCurveLast = fCurve;
+	
+	if(!fAmountLast)
+		fAmountLast = fAmount;
+	
+	if(!fLFO1RateLast)
+		fLFO1RateLast = fLFO1Rate;
+	
+	if(!fLFO2RateLast)
+		fLFO2RateLast = fLFO2Rate;
+	
+	if(!fLFO1DepthLast)
+		fLFO1DepthLast = fLFO1Depth;
+	
+	if(!fLFO2DepthLast)
+		fLFO2DepthLast = fLFO2Depth;
+	
+	dGain = (fGain - fGainLast) / SampleCount;
+	dCurve = (fCurve - fCurveLast) / SampleCount;
+	dAmount = (fAmount - fAmountLast) / SampleCount;
+	dLFO1Rate = (fLFO1Rate - fLFO1RateLast) / SampleCount;
+	dLFO2Rate = (fLFO2Rate - fLFO2RateLast) / SampleCount;
+	dLFO1Depth = (fLFO1Depth - fLFO1DepthLast) / SampleCount;
+	dLFO2Depth = (fLFO2Depth - fLFO2DepthLast) / SampleCount;
+	
+	fGain = fGainLast;
+	fCurve = fCurveLast;
+	fAmount = fAmountLast;
+	fLFO1Rate = fLFO1RateLast;
+	fLFO2Rate = fLFO2RateLast;
+	fLFO1Depth = fLFO1DepthLast;
+	fLFO2Depth = fLFO2DepthLast;
+	
+	pfInput = psXShaper->m_pfInputBuffer1;
+	pfOutput = psXShaper->m_pfOutputBuffer1;
+	
+	for(lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){	
+	
+		fGain = fGain + dGain;
+		fCurve = fCurve + dCurve;
+		fAmount = fAmount + dAmount;
+		fLFO1Rate = fLFO1Rate + dLFO1Rate;
+		fLFO2Rate = fLFO2Rate + dLFO2Rate;
+		fLFO1Depth = fLFO1Depth + dLFO1Depth;
+		fLFO2Depth = fLFO2Depth + dLFO2Depth;
+		
+		fLFO1Period = fSampleRate/fLFO1Rate;
+		fLFO2Period = fSampleRate/fLFO2Rate;
+		
+		fLFO1Step++;
+		fLFO2Step++;
+		
+		if(fLFO1Step >= fLFO1Period){
+			fLFO1Step = 0;
+		}
+		
+		if(fLFO2Step >= fLFO2Period){
+			fLFO2Step = 0;
+		}
+		
+		switch ((int)fLFO1Form){
+			case 1:
+				fLFO1Value = LFOtri(fLFO1Step,fLFO1Period);
+				break;
+			case 2:
+				fLFO1Value = LFOsin(fLFO1Step,fLFO1Period);
+				break;
+			case 3:
+				fLFO1Value = LFOsaw(fLFO1Step,fLFO1Period,0.05f);
+				break;
+			case 4:
+				fLFO1Value = LFOtrp(fLFO1Step,fLFO1Period,0.02f);
+				break;
+			case 5:
+				fLFO1Value = LFOtrp(fLFO1Step,fLFO1Period,0.25f);
+				break;
+		}
+		
+		switch ((int)fLFO2Form){
+			case 1:
+				fLFO2Value = LFOtri(fLFO2Step,fLFO2Period);
+				break;
+			case 2:
+				fLFO2Value = LFOsin(fLFO2Step,fLFO2Period);
+				break;
+			case 3:
+				fLFO2Value = LFOsaw(fLFO2Step,fLFO2Period,0.02f);
+				break;
+			case 4:
+				fLFO2Value = LFOtrp(fLFO2Step,fLFO2Period,0.02f);
+				break;
+			case 5:
+				fLFO2Value = LFOtrp(fLFO2Step,fLFO2Period,0.25f);
+				break;
+		}
+		
+		rCurve = 3.0f * (fCurve + 0.5f * (fLFO2Value * fLFO2Depth));
+	
+		fLFO1Value = (fLFO1Value + 1.0f)/2.0f;
+		
+		inputData = *(pfInput++) * (fGain * (1-fLFO1Depth) +  fLFO1Value * fLFO1Depth);
+		
+		if( inputData < 0.0f ){
+			outputData = -inputData;
+		} else {
+			outputData = inputData;
+		}
+		
+		if(fType == 1){
+			outputData = waveshaper_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 2){
+			outputData = waveshaper_double_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 3){
+			outputData = waveshaper_quadruple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 4){
+			outputData = waveshaper_triple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 5){
+			outputData = waveshaper_morph_double_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 6){
+			outputData = waveshaper_morph_triple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 7){
+			outputData = waveshaper_morph_quadruple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 8){
+			outputData = waveshaper_rect_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 9){
+			outputData = waveshaper_nonlin_rect_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		}
+		
+		if(outputData < 0.0f){
+			outputData = -outputData;
+		}
+		
+		if(inputData >= 0.0f){
+			*(pfOutput++) = outputData ;
+		} else {
+			*(pfOutput++) = -outputData ;
+		}
+		
+	}
+		
+	psXShaper->m_fGainLast = fGain;
+	psXShaper->m_fCurveLast = fCurve;
+	psXShaper->m_fAmountLast = fAmount;
+	psXShaper->m_fLFO1RateLast = fLFO1Rate;
+	psXShaper->m_fLFO2RateLast = fLFO2Rate;
+	psXShaper->m_fLFO1DepthLast = fLFO1Depth;
+	psXShaper->m_fLFO2DepthLast = fLFO2Depth;
+	
+	psXShaper->m_fLFO1Step = fLFO1Step;
+	psXShaper->m_fLFO2Step = fLFO2Step;
+	rCurve = fCurve + 0.5f * (fLFO2Value * fLFO2Depth);
+		
+		if(fType == 1){
+			rCurve = - rCurve + 1.01f;
+		} else {
+			rCurve = rCurve + 1.01f;
+		}
+		
+		rCurve = rCurve * 1.5f;
+}
+
+/* XShaper stereo */
+
+void runStereoXShaper(LADSPA_Handle Instance, unsigned long SampleCount) {
+  
+	/* audio i/o */
+	
+	unsigned long fSampleRate;
+	
+	LADSPA_Data * pfInput;
+	LADSPA_Data * pfOutput;
+	LADSPA_Data inputData;
+	LADSPA_Data outputData;
+	
+	/* input params */
+	
+	LADSPA_Data fGain;
+	LADSPA_Data fType;
+	LADSPA_Data fCurve;
+	LADSPA_Data fAmount;
+	
+	LADSPA_Data fLFO1Form;
+	LADSPA_Data fLFO1Rate;
+	LADSPA_Data fLFO1Depth;
+	float fLFO1Step;
+	LADSPA_Data fLFO1Period;
+	LADSPA_Data fLFO1Value = 0.0f;
+	
+	LADSPA_Data fLFO2Form;
+	LADSPA_Data fLFO2Rate;
+	LADSPA_Data fLFO2Depth;
+	float fLFO2Step;
+	LADSPA_Data fLFO2Period;
+	LADSPA_Data fLFO2Value = 0.0f;
+	
+	/* interpolation */
+	
+	LADSPA_Data rCurve;
+	LADSPA_Data fGainLast;
+	LADSPA_Data fCurveLast;
+	LADSPA_Data fAmountLast;
+	LADSPA_Data fLFO1RateLast;
+	LADSPA_Data fLFO2RateLast;
+	LADSPA_Data fLFO1DepthLast;
+	LADSPA_Data fLFO2DepthLast;
+	LADSPA_Data dGain;
+	LADSPA_Data dCurve;
+	LADSPA_Data dAmount;
+	LADSPA_Data dLFO1Rate;
+	LADSPA_Data dLFO2Rate;
+	LADSPA_Data dLFO1Depth;
+	LADSPA_Data dLFO2Depth;
+	
+	XShaper * psXShaper;
+	unsigned long lSampleIndex;
+
+	psXShaper = (XShaper *)Instance;
+	
+	fSampleRate = psXShaper->SampleRate;
+	
+	fGain = *(psXShaper->m_pfGain);
+	fType = *(psXShaper->m_pfType);
+	fCurve = *(psXShaper->m_pfCurve);
+	fAmount = *(psXShaper->m_pfAmount);
+	fLFO1Form = *(psXShaper->m_pfLFO1Form);
+	fLFO1Rate = *(psXShaper->m_pfLFO1Rate);
+	fLFO1Depth = *(psXShaper->m_pfLFO1Depth);
+	fLFO2Form = *(psXShaper->m_pfLFO2Form);
+	fLFO2Rate = *(psXShaper->m_pfLFO2Rate);
+	fLFO2Depth = *(psXShaper->m_pfLFO2Depth);
+	
+	if(fLFO1Rate < 0.001f)
+		fLFO1Rate = 0.001f;
+	
+	if(fLFO2Rate < 0.001f)
+		fLFO2Rate = 0.001f;
+	
+	if(fType >= 0.0f && fType <= 1.0f){
+		fType = 1;
+	} else if(fType > 1.0f && fType <= 2.0f){
+		fType = 2;
+	} else if(fType > 2.0f && fType <= 3.0f){
+		fType = 3;
+	} else if(fType > 3.0f && fType <= 4.0f){
+		fType = 4;
+	} else if(fType > 4.0f && fType <= 5.0f){
+		fType = 5;
+	} else if(fType > 5.0f && fType <= 6.0f){
+		fType = 6;
+	} else if(fType > 6.0f && fType <= 7.0f){
+		fType = 7;
+	} else if(fType > 7.0f && fType <= 8.0f){
+		fType = 8;
+	} else if(fType > 8.0f && fType <= 9.0f){
+		fType = 9;
+	}
+
+	if(fLFO1Form >= 0.0f && fLFO1Form <= 1.0f){
+		fLFO1Form = 1;
+	} else if(fLFO1Form > 1.0f && fLFO1Form <= 2.0f){
+		fLFO1Form = 2;
+	} else if(fLFO1Form > 2.0f && fLFO1Form <= 3.0f){
+		fLFO1Form = 3;
+	} else if(fLFO1Form > 3.0f && fLFO1Form <= 4.0f){
+		fLFO1Form = 4;
+	} else if(fLFO1Form > 4.0f && fLFO1Form <= 5.0f){
+		fLFO1Form = 5;
+	} else {
+		fLFO1Form = 1;
+	}
+	
+	if(fLFO2Form >= 0.0f && fLFO2Form <= 1.0f){
+		fLFO2Form = 1;
+	} else if(fLFO2Form > 1.0f && fLFO2Form <= 2.0f){
+		fLFO2Form = 2;
+	} else if(fLFO2Form > 2.0f && fLFO2Form <= 3.0f){
+		fLFO2Form = 3;
+	} else if(fLFO2Form > 3.0f && fLFO2Form <= 4.0f){
+		fLFO2Form = 4;
+	} else if(fLFO2Form > 4.0f && fLFO2Form <= 5.0f){
+		fLFO2Form = 5;
+	} else {
+		fLFO2Form = 1;
+	}
+	
+	fLFO1Step = psXShaper->m_fLFO1Step;
+	fLFO2Step = psXShaper->m_fLFO2Step;
+	
+	if(!fLFO1Step)
+		fLFO1Step = 0;
+	if(!fLFO2Step)
+		fLFO2Step = 0;
+	
+	fGainLast = psXShaper->m_fGainLast;
+	fCurveLast = psXShaper->m_fCurveLast;
+	fAmountLast = psXShaper->m_fAmountLast;
+	fLFO1RateLast = psXShaper->m_fLFO1RateLast;
+	fLFO2RateLast = psXShaper->m_fLFO2RateLast;
+	fLFO1DepthLast = psXShaper->m_fLFO1DepthLast;
+	fLFO2DepthLast = psXShaper->m_fLFO2DepthLast;
+	
+	if(!fGainLast)
+		fGainLast = fGain;
+		
+	if(!fCurveLast)
+		fCurveLast = fCurve;
+	
+	if(!fAmountLast)
+		fAmountLast = fAmount;
+	
+	if(!fLFO1RateLast)
+		fLFO1RateLast = fLFO1Rate;
+	
+	if(!fLFO2RateLast)
+		fLFO2RateLast = fLFO2Rate;
+	
+	if(!fLFO1DepthLast)
+		fLFO1DepthLast = fLFO1Depth;
+	
+	if(!fLFO2DepthLast)
+		fLFO2DepthLast = fLFO2Depth;
+	
+	dGain = (fGain - fGainLast) / SampleCount;
+	dCurve = (fCurve - fCurveLast) / SampleCount;
+	dAmount = (fAmount - fAmountLast) / SampleCount;
+	dLFO1Rate = (fLFO1Rate - fLFO1RateLast) / SampleCount;
+	dLFO2Rate = (fLFO2Rate - fLFO2RateLast) / SampleCount;
+	dLFO1Depth = (fLFO1Depth - fLFO1DepthLast) / SampleCount;
+	dLFO2Depth = (fLFO2Depth - fLFO2DepthLast) / SampleCount;
+	
+	fGain = fGainLast;
+	fCurve = fCurveLast;
+	fAmount = fAmountLast;
+	fLFO1Rate = fLFO1RateLast;
+	fLFO2Rate = fLFO2RateLast;
+	fLFO1Depth = fLFO1DepthLast;
+	fLFO2Depth = fLFO2DepthLast;
+	
+	pfInput = psXShaper->m_pfInputBuffer1;
+	pfOutput = psXShaper->m_pfOutputBuffer1;
+  
+	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){
+		
+		fGain = fGain + dGain;
+		fCurve = fCurve + dCurve;
+		fAmount = fAmount + dAmount;
+		fLFO1Rate = fLFO1Rate + dLFO1Rate;
+		fLFO2Rate = fLFO2Rate + dLFO2Rate;
+		fLFO1Depth = fLFO1Depth + dLFO1Depth;
+		fLFO2Depth = fLFO2Depth + dLFO2Depth;
+		
+		fLFO1Period = fSampleRate/fLFO1Rate;
+		fLFO2Period = fSampleRate/fLFO2Rate;
+		
+		fLFO1Step++;
+		fLFO2Step++;
+		
+		if(fLFO1Step >= fLFO1Period){
+			fLFO1Step = 0;
+		}
+		
+		if(fLFO2Step >= fLFO2Period){
+			fLFO2Step = 0;
+		}
+		
+		switch ((int)fLFO1Form){
+			case 1:
+				fLFO1Value = LFOtri(fLFO1Step,fLFO1Period);
+				break;
+			case 2:
+				fLFO1Value = LFOsin(fLFO1Step,fLFO1Period);
+				break;
+			case 3:
+				fLFO1Value = LFOsaw(fLFO1Step,fLFO1Period,0.05f);
+				break;
+			case 4:
+				fLFO1Value = LFOtrp(fLFO1Step,fLFO1Period,0.02f);
+				break;
+			case 5:
+				fLFO1Value = LFOtrp(fLFO1Step,fLFO1Period,0.25f);
+				break;
+		}
+		
+		switch ((int)fLFO2Form){
+			case 1:
+				fLFO2Value = LFOtri(fLFO2Step,fLFO2Period);
+				break;
+			case 2:
+				fLFO2Value = LFOsin(fLFO2Step,fLFO2Period);
+				break;
+			case 3:
+				fLFO2Value = LFOsaw(fLFO2Step,fLFO2Period,0.02f);
+				break;
+			case 4:
+				fLFO2Value = LFOtrp(fLFO2Step,fLFO2Period,0.02f);
+				break;
+			case 5:
+				fLFO2Value = LFOtrp(fLFO2Step,fLFO2Period,0.25f);
+				break;
+		}
+		
+		rCurve = 3.0f * (fCurve + 0.5f * (fLFO2Value * fLFO2Depth));
+		
+		fLFO1Value = (fLFO1Value + 1.0f)/2.0f;
+		
+		inputData = *(pfInput++) * (fGain * (1-fLFO1Depth) +  fLFO1Value * fLFO1Depth);
+		
+		if( inputData < 0.0f ){
+			outputData = -inputData;
+		} else {
+			outputData = inputData;
+		}
+		
+		if(fType == 1){
+			outputData = waveshaper_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 2){
+			outputData = waveshaper_double_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 3){
+			outputData = waveshaper_quadruple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 4){
+			outputData = waveshaper_triple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 5){
+			outputData = waveshaper_morph_double_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 6){
+			outputData = waveshaper_morph_triple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 7){
+			outputData = waveshaper_morph_quadruple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 8){
+			outputData = waveshaper_rect_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 9){
+			outputData = waveshaper_nonlin_rect_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		}
+		
+		if(fType >= 3 && fType <= 8){
+			if(outputData < 0.0f)
+				outputData = -outputData;
+		}
+		
+		if( inputData >= 0.0f ){
+			*(pfOutput++) = outputData ;
+		} else {
+			*(pfOutput++) = -outputData ;
+		}
+		
+	}
+	
+	fLFO1Step = psXShaper->m_fLFO1Step;
+	fLFO2Step = psXShaper->m_fLFO2Step;
+	
+	if(!fLFO1Step)
+		fLFO1Step = 0;
+	if(!fLFO2Step)
+		fLFO2Step = 0;
+
+	fGain = fGainLast;
+	fCurve = fCurveLast;
+	fAmount = fAmountLast;
+	fLFO1Rate = fLFO1RateLast;
+	fLFO2Rate = fLFO2RateLast;
+	fLFO1Depth = fLFO1DepthLast;
+	fLFO2Depth = fLFO2DepthLast;
+
+	pfInput = psXShaper->m_pfInputBuffer2;
+	pfOutput = psXShaper->m_pfOutputBuffer2;
+	
+	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){
+		
+		fGain = fGain + dGain;
+		fCurve = fCurve + dCurve;
+		fAmount = fAmount + dAmount;
+		fLFO1Rate = fLFO1Rate + dLFO1Rate;
+		fLFO2Rate = fLFO2Rate + dLFO2Rate;
+		fLFO1Depth = fLFO1Depth + dLFO1Depth;
+		fLFO2Depth = fLFO2Depth + dLFO2Depth;
+		
+		fLFO1Period = fSampleRate/fLFO1Rate;
+		fLFO2Period = fSampleRate/fLFO2Rate;
+		
+		fLFO1Step++;
+		fLFO2Step++;
+		
+		if(fLFO1Step >= fLFO1Period){
+			fLFO1Step = 0;
+		}
+		
+		if(fLFO2Step >= fLFO2Period){
+			fLFO2Step = 0;
+		}
+		
+		switch ((int)fLFO1Form){
+			case 1:
+				fLFO1Value = LFOtri(fLFO1Step,fLFO1Period);
+				break;
+			case 2:
+				fLFO1Value = LFOsin(fLFO1Step,fLFO1Period);
+				break;
+			case 3:
+				fLFO1Value = LFOsaw(fLFO1Step,fLFO1Period,0.05f);
+				break;
+			case 4:
+				fLFO1Value = LFOtrp(fLFO1Step,fLFO1Period,0.02f);
+				break;
+			case 5:
+				fLFO1Value = LFOtrp(fLFO1Step,fLFO1Period,0.25f);
+				break;
+		}
+		
+		switch ((int)fLFO2Form){
+			case 1:
+				fLFO2Value = LFOtri(fLFO2Step,fLFO2Period);
+				break;
+			case 2:
+				fLFO2Value = LFOsin(fLFO2Step,fLFO2Period);
+				break;
+			case 3:
+				fLFO2Value = LFOsaw(fLFO2Step,fLFO2Period,0.02f);
+				break;
+			case 4:
+				fLFO2Value = LFOtrp(fLFO2Step,fLFO2Period,0.02f);
+				break;
+			case 5:
+				fLFO2Value = LFOtrp(fLFO2Step,fLFO2Period,0.25f);
+				break;
+		}
+		
+		rCurve = 3.0f * (fCurve + 0.5f * (fLFO2Value * fLFO2Depth));
+	
+		fLFO1Value = (fLFO1Value + 1.0f)/2.0f;
+		
+		inputData = *(pfInput++) * (fGain * (1-fLFO1Depth) +  fLFO1Value * fLFO1Depth);
+		
+		if( inputData < 0.0f ){
+			outputData = -inputData;
+		} else {
+			outputData = inputData;
+		}
+		
+		if(fType == 1){
+			outputData = waveshaper_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 2){
+			outputData = waveshaper_double_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 3){
+			outputData = waveshaper_quadruple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 4){
+			outputData = waveshaper_triple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 5){
+			outputData = waveshaper_morph_double_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 6){
+			outputData = waveshaper_morph_triple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 7){
+			outputData = waveshaper_morph_quadruple_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 8){
+			outputData = waveshaper_rect_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		} else if(fType == 9){
+			outputData = waveshaper_nonlin_rect_sine(outputData,rCurve) * fAmount + outputData * (1 - fAmount);
+		}
+		
+		if(fType >= 3 && fType <= 8){
+			if(outputData < 0.0f)
+				outputData = -outputData;
+		}
+		
+		if( inputData >= 0.0f ){
+			*(pfOutput++) = outputData ;
+		} else {
+			*(pfOutput++) = -outputData ;
+		}
+		
+	}
+	
+	psXShaper->m_fGainLast = fGain;
+	psXShaper->m_fCurveLast = fCurve;
+	psXShaper->m_fAmountLast = fAmount;
+	psXShaper->m_fLFO1RateLast = fLFO1Rate;
+	psXShaper->m_fLFO2RateLast = fLFO2Rate;
+	psXShaper->m_fLFO1DepthLast = fLFO1Depth;
+	psXShaper->m_fLFO2DepthLast = fLFO2Depth;
+	
+	psXShaper->m_fLFO1Step = fLFO1Step;
+	psXShaper->m_fLFO2Step = fLFO2Step;
+}
+
+/* XShaper cleanup */
+
+void cleanupXShaper(LADSPA_Handle Instance) {
+
+	XShaper * psXShaper;
+	psXShaper = (XShaper *)Instance;
+
+	free(psXShaper);
+}
+
+LADSPA_Descriptor * g_psMonoDescriptor = NULL;
+LADSPA_Descriptor * g_psStereoDescriptor = NULL;
+
+/* XShaper _init() function */
+
+void _init() {
+
+  char ** pcPortNames;
+  LADSPA_PortDescriptor * piPortDescriptors;
+  LADSPA_PortRangeHint * psPortRangeHints;
+
+  g_psMonoDescriptor
+    = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
+  g_psStereoDescriptor 
+    = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
+
+  if (g_psMonoDescriptor) {
+  
+    g_psMonoDescriptor->UniqueID
+      = 2547;
+    g_psMonoDescriptor->Label
+      = strdup("XShaperM");
+    g_psMonoDescriptor->Properties
+      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
+    g_psMonoDescriptor->Name 
+      = strdup("X-Shaper (mono)");
+    g_psMonoDescriptor->Maker
+      = strdup("Artemiy Pavlov");
+    g_psMonoDescriptor->Copyright
+      = strdup("(c)2005 GPL");
+    g_psMonoDescriptor->PortCount
+      = 12;
+    piPortDescriptors
+      = (LADSPA_PortDescriptor *)calloc(12, sizeof(LADSPA_PortDescriptor));
+    g_psMonoDescriptor->PortDescriptors
+      = (const LADSPA_PortDescriptor *)piPortDescriptors;
+	  
+	piPortDescriptors[XSHAPER_GAIN]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_TYPE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_CURVE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_AMOUNT]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO1FORM]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO1RATE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO1DEPTH]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO2FORM]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO2RATE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO2DEPTH]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_INPUT1]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[XSHAPER_OUTPUT1]
+	= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	  
+	pcPortNames
+	= (char **)calloc(12, sizeof(char *));
+	g_psMonoDescriptor->PortNames 
+	= (const char **)pcPortNames;
+	  
+	pcPortNames[XSHAPER_GAIN]
+	= strdup("Gain");
+	pcPortNames[XSHAPER_TYPE]
+	= strdup("Type");
+	pcPortNames[XSHAPER_CURVE]
+	= strdup("Curve");
+	pcPortNames[XSHAPER_AMOUNT]
+	= strdup("Amount");
+	pcPortNames[XSHAPER_LFO1FORM]
+	= strdup("LFO1 Form");
+	pcPortNames[XSHAPER_LFO1RATE]
+	= strdup("LFO1 Rate");
+	pcPortNames[XSHAPER_LFO1DEPTH]
+	= strdup("LFO1 Gain Depth");
+	pcPortNames[XSHAPER_LFO2FORM]
+	= strdup("LFO2 Form");
+	pcPortNames[XSHAPER_LFO2RATE]
+	= strdup("LFO2 Rate");
+	pcPortNames[XSHAPER_LFO2DEPTH]
+	= strdup("LFO2 Curve Depth");
+	pcPortNames[XSHAPER_INPUT1]
+	= strdup("Input");
+	pcPortNames[XSHAPER_OUTPUT1]
+	= strdup("Output");
+	  
+    psPortRangeHints = ((LADSPA_PortRangeHint *)
+		calloc(12, sizeof(LADSPA_PortRangeHint)));
+    g_psMonoDescriptor->PortRangeHints
+      = (const LADSPA_PortRangeHint *)psPortRangeHints;
+	
+	psPortRangeHints[XSHAPER_GAIN].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_GAIN].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_GAIN].UpperBound
+	= 1;
+	    
+	psPortRangeHints[XSHAPER_TYPE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_TYPE].LowerBound
+	= 1;
+	psPortRangeHints[XSHAPER_TYPE].UpperBound
+	= XSHAPER_TYPES;
+	 
+	psPortRangeHints[XSHAPER_CURVE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[XSHAPER_CURVE].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_CURVE].UpperBound
+	= 1;
+	 
+	psPortRangeHints[XSHAPER_AMOUNT].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_AMOUNT].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_AMOUNT].UpperBound
+	= 1;
+	
+	psPortRangeHints[XSHAPER_LFO1FORM].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO1FORM].LowerBound
+	= 1;
+	psPortRangeHints[XSHAPER_LFO1FORM].UpperBound
+	= XSHAPER_LFOTYPES;
+	
+	psPortRangeHints[XSHAPER_LFO1RATE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO1RATE].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_LFO1RATE].UpperBound
+	= 10;
+	
+	psPortRangeHints[XSHAPER_LFO1DEPTH].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[XSHAPER_LFO1DEPTH].LowerBound
+	= -1;
+	psPortRangeHints[XSHAPER_LFO1DEPTH].UpperBound
+	= 1;
+	
+	psPortRangeHints[XSHAPER_LFO2FORM].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO2FORM].LowerBound
+	= 1;
+	psPortRangeHints[XSHAPER_LFO2FORM].UpperBound
+	= XSHAPER_LFOTYPES;
+	
+	psPortRangeHints[XSHAPER_LFO2RATE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO2RATE].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_LFO2RATE].UpperBound
+	= 10;
+	
+	psPortRangeHints[XSHAPER_LFO2DEPTH].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[XSHAPER_LFO2DEPTH].LowerBound
+	= -1;
+	psPortRangeHints[XSHAPER_LFO2DEPTH].UpperBound
+	= 1;
+	 
+	psPortRangeHints[XSHAPER_INPUT1].HintDescriptor
+	 = 0;
+    psPortRangeHints[XSHAPER_OUTPUT1].HintDescriptor
+	 = 0;
+	  
+    g_psMonoDescriptor->instantiate 
+      = instantiateXShaper;
+    g_psMonoDescriptor->connect_port 
+      = connectPortToXShaper;
+    g_psMonoDescriptor->activate
+      = NULL;
+    g_psMonoDescriptor->run
+      = runMonoXShaper;
+    g_psMonoDescriptor->run_adding
+      = NULL;
+    g_psMonoDescriptor->set_run_adding_gain
+      = NULL;
+    g_psMonoDescriptor->deactivate
+      = NULL;
+    g_psMonoDescriptor->cleanup
+      = cleanupXShaper;
+  }
+  
+  if (g_psStereoDescriptor) {
+    
+    g_psStereoDescriptor->UniqueID
+      = 2548;
+    g_psStereoDescriptor->Label
+      = strdup("XShaperS");
+    g_psStereoDescriptor->Properties
+      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
+    g_psStereoDescriptor->Name 
+      = strdup("X-Shaper (stereo)");
+    g_psStereoDescriptor->Maker
+      = strdup("Artemiy Pavlov");
+    g_psStereoDescriptor->Copyright
+      = strdup("(c)2005 GPL");
+    g_psStereoDescriptor->PortCount
+      = 14;
+    piPortDescriptors
+      = (LADSPA_PortDescriptor *)calloc(14, sizeof(LADSPA_PortDescriptor));
+    g_psStereoDescriptor->PortDescriptors
+      = (const LADSPA_PortDescriptor *)piPortDescriptors;
+	 
+	piPortDescriptors[XSHAPER_GAIN]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_TYPE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_CURVE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_AMOUNT]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO1FORM]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO1RATE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO1DEPTH]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO2FORM]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO2RATE]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_LFO2DEPTH]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[XSHAPER_INPUT1]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[XSHAPER_OUTPUT1]
+	= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[XSHAPER_INPUT2]
+	= LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+	piPortDescriptors[XSHAPER_OUTPUT2]
+	= LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	  
+	pcPortNames
+	= (char **)calloc(14, sizeof(char *));
+	g_psStereoDescriptor->PortNames 
+	= (const char **)pcPortNames;
+	
+	pcPortNames[XSHAPER_GAIN]
+	= strdup("Gain");
+	pcPortNames[XSHAPER_TYPE]
+	= strdup("Type");
+	pcPortNames[XSHAPER_CURVE]
+	= strdup("Curve");
+	pcPortNames[XSHAPER_AMOUNT]
+	= strdup("Amount");
+	pcPortNames[XSHAPER_LFO1FORM]
+	= strdup("LFO1 Form");
+	pcPortNames[XSHAPER_LFO1RATE]
+	= strdup("LFO1 Rate");
+	pcPortNames[XSHAPER_LFO1DEPTH]
+	= strdup("LFO1 Gain Depth");
+	pcPortNames[XSHAPER_LFO2FORM]
+	= strdup("LFO2 Form");
+	pcPortNames[XSHAPER_LFO2RATE]
+	= strdup("LFO2 Rate");
+	pcPortNames[XSHAPER_LFO2DEPTH]
+	= strdup("LFO2 Curve Depth");
+	pcPortNames[XSHAPER_INPUT1]
+	= strdup("Input L");
+	pcPortNames[XSHAPER_OUTPUT1]
+	= strdup("Output L");
+	pcPortNames[XSHAPER_INPUT2]
+	= strdup("Input R");
+	pcPortNames[XSHAPER_OUTPUT2]
+	= strdup("Output R");
+	  
+    psPortRangeHints = ((LADSPA_PortRangeHint *)
+			calloc(14, sizeof(LADSPA_PortRangeHint)));
+    g_psStereoDescriptor->PortRangeHints
+      = (const LADSPA_PortRangeHint *)psPortRangeHints;
+	
+	psPortRangeHints[XSHAPER_GAIN].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_GAIN].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_GAIN].UpperBound
+	= 1;
+	  
+   psPortRangeHints[XSHAPER_TYPE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_TYPE].LowerBound
+	= 1;
+	psPortRangeHints[XSHAPER_TYPE].UpperBound
+	= XSHAPER_TYPES;
+	 
+	psPortRangeHints[XSHAPER_CURVE].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_DEFAULT_0);    
+	psPortRangeHints[XSHAPER_CURVE].LowerBound
+	 = 0;
+	psPortRangeHints[XSHAPER_CURVE].UpperBound
+	 = 1;
+	 
+	psPortRangeHints[XSHAPER_AMOUNT].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_AMOUNT].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_AMOUNT].UpperBound
+	= 1;
+	
+	psPortRangeHints[XSHAPER_LFO1FORM].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO1FORM].LowerBound
+	= 1;
+	psPortRangeHints[XSHAPER_LFO1FORM].UpperBound
+	= XSHAPER_LFOTYPES;
+	
+	psPortRangeHints[XSHAPER_LFO1RATE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO1RATE].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_LFO1RATE].UpperBound
+	= 10;
+	
+	psPortRangeHints[XSHAPER_LFO1DEPTH].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[XSHAPER_LFO1DEPTH].LowerBound
+	= -1;
+	psPortRangeHints[XSHAPER_LFO1DEPTH].UpperBound
+	= 1;
+	
+	psPortRangeHints[XSHAPER_LFO2FORM].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_INTEGER
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO2FORM].LowerBound
+	= 1;
+	psPortRangeHints[XSHAPER_LFO2FORM].UpperBound
+	= XSHAPER_LFOTYPES;
+	
+	psPortRangeHints[XSHAPER_LFO2RATE].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_1);
+	psPortRangeHints[XSHAPER_LFO2RATE].LowerBound
+	= 0;
+	psPortRangeHints[XSHAPER_LFO2RATE].UpperBound
+	= 10;
+	
+	psPortRangeHints[XSHAPER_LFO2DEPTH].HintDescriptor
+	= (LADSPA_HINT_BOUNDED_BELOW 
+	| LADSPA_HINT_BOUNDED_ABOVE
+	| LADSPA_HINT_DEFAULT_0);
+	psPortRangeHints[XSHAPER_LFO2DEPTH].LowerBound
+	= -1;
+	psPortRangeHints[XSHAPER_LFO2DEPTH].UpperBound
+	= 1;
+	  
+	psPortRangeHints[XSHAPER_INPUT1].HintDescriptor
+	 = 0;
+    psPortRangeHints[XSHAPER_OUTPUT1].HintDescriptor
+	 = 0;
+    psPortRangeHints[XSHAPER_INPUT2].HintDescriptor
+	 = 0;
+    psPortRangeHints[XSHAPER_OUTPUT2].HintDescriptor
+	 = 0;
+	  
+    g_psStereoDescriptor->instantiate 
+      = instantiateXShaper;
+    g_psStereoDescriptor->connect_port 
+      = connectPortToXShaper;
+    g_psStereoDescriptor->activate
+      = NULL;
+    g_psStereoDescriptor->run
+      = runStereoXShaper;
+    g_psStereoDescriptor->run_adding
+      = NULL;
+    g_psStereoDescriptor->set_run_adding_gain
+      = NULL;
+    g_psStereoDescriptor->deactivate
+      = NULL;
+    g_psStereoDescriptor->cleanup
+      = cleanupXShaper;
+  }
+}
+
+void deleteDescriptor(LADSPA_Descriptor * psDescriptor) {
+  unsigned long lIndex;
+  if (psDescriptor) {
+    free((char *)psDescriptor->Label);
+    free((char *)psDescriptor->Name);
+    free((char *)psDescriptor->Maker);
+    free((char *)psDescriptor->Copyright);
+    free((LADSPA_PortDescriptor *)psDescriptor->PortDescriptors);
+    for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++)
+      free((char *)(psDescriptor->PortNames[lIndex]));
+    free((char **)psDescriptor->PortNames);
+    free((LADSPA_PortRangeHint *)psDescriptor->PortRangeHints);
+    free(psDescriptor);
+  }
+}
+
+void _fini() {
+  deleteDescriptor(g_psMonoDescriptor);
+  deleteDescriptor(g_psStereoDescriptor);
+}
+
+
+#ifdef WIN32
+	#define _DLL_EXPORT_ __declspec(dllexport)
+	int bIsFirstTime = 1; 
+	void _init(); // forward declaration
+#else
+	#define _DLL_EXPORT_ 
+#endif
+
+
+
+_DLL_EXPORT_ const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) {
+#ifdef WIN32
+	if (bIsFirstTime) {
+		_init();
+		bIsFirstTime = 0;
+	}
+#endif
+  switch (Index) {
+  case 0:
+    return g_psMonoDescriptor;
+  case 1:
+    return g_psStereoDescriptor;
+  default:
+    return NULL;
+  }
+}
+
Index: /branches/tabbedInterface/plugins/wasp/AUTHORS
===================================================================
--- /branches/tabbedInterface/plugins/wasp/AUTHORS	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/AUTHORS	(revision 3)
@@ -0,0 +1,9 @@
+Artemiy Pavlov
+ - project author, maintainer, coder
+ 
+Thanks to:
+- Richard Furse for his great plugin examples
+- Lars Luthman, Fons Adriansen and Steve Harris for their invaluable help at 
+  the linux-audio-dev list
+- Alessandro Cominu for helping with debugging my very first (and buggy) plugin
+- Tim Goetze for kindly providing a range of vacant plugin IDs
Index: /branches/tabbedInterface/plugins/wasp/ChangeLog
===================================================================
--- /branches/tabbedInterface/plugins/wasp/ChangeLog	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/ChangeLog	(revision 3)
@@ -0,0 +1,27 @@
+2005-xx-xx Artemiy Pavlov
+
+	* Release 0.2.0
+	* X-Shaper: removed round and parabolic curves, added new sine-based curves
+	* X-Shaper: put wave shaper curve functions in "waveshaper.h"
+	* X-Shaper: fixed clipping in rectified sine curves
+
+2005-08-07 Artemiy Pavlov
+
+	* Release 0.1.3
+	* X-Shaper: added two LFOs and per-sample interpolation for most parameters
+
+2005-07-09 Artemiy Pavlov
+
+	* Release 0.1.2
+	* Performance improvements and new "Amount" parameter in X-Shaper
+
+2005-07-08 Artemiy Pavlov
+
+	* Release 0.1.1
+	* Added "Gain" parameter and two new curve types to X-Shaper
+
+2005-07-06 Artemiy Pavlov 
+
+	* Release 0.1.0
+	* 4 plugins: X-Shaper, Clipping Booster, Noisifier, Variable Noise
+
Index: /branches/tabbedInterface/plugins/wasp/wasp_booster/wasp_booster.pro
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp_booster/wasp_booster.pro	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp_booster/wasp_booster.pro	(revision 3)
@@ -0,0 +1,18 @@
+TEMPLATE = lib
+QT -= qt
+QT -= gui
+QT -= core
+DESTDIR = ../../
+INCLUDEPATH += ../include
+SOURCES += booster.c
+
+linux-g++* {
+	CONFIG = plugin
+
+	# there's something weird in linux qmake...this is a simple and ugly workaround
+	QMAKE_LINK_SHLIB_CMD = ld -shared -o libwasp_booster.so booster.o
+}
+
+win32 {
+	CONFIG = dll
+}
Index: /branches/tabbedInterface/plugins/wasp/wasp_booster/booster.c
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp_booster/booster.c	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp_booster/booster.c	(revision 3)
@@ -0,0 +1,540 @@
+/*
+
+booster.c
+
+Clipping booster (mono/stereo)
+
+(c)2005 Artemiy Pavlov
+
+*/
+
+/* Includes: */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "ladspa.h"
+
+/* The port numbers for the plugin: */
+
+#define BOOSTER_CURVE 0
+#define BOOSTER_GAIN 1
+#define BOOSTER_CLIP 2
+#define BOOSTER_INPUT1  3
+#define BOOSTER_OUTPUT1 4
+#define BOOSTER_INPUT2 5
+#define BOOSTER_OUTPUT2 6
+
+#define MAX_GAIN 36
+
+/* The structure used to hold port connection information and state  */
+
+typedef struct {
+
+	LADSPA_Data * m_pfCurve;
+	LADSPA_Data * m_pfGain;
+	LADSPA_Data * m_pfClip;
+	LADSPA_Data * m_pfInputBuffer1;
+	LADSPA_Data * m_pfOutputBuffer1;
+	LADSPA_Data * m_pfInputBuffer2;
+	LADSPA_Data * m_pfOutputBuffer2;
+
+} Booster;
+
+/* Construct a new plugin instance. */
+
+LADSPA_Handle instantiateBooster(const LADSPA_Descriptor * Descriptor, unsigned long SampleRate) {
+
+	return malloc(sizeof(Booster));
+	
+}
+
+/* Connect a port to a data location. */
+
+void connectPortToBooster(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) {
+
+	Booster * psBooster;
+
+	psBooster = (Booster *)Instance;
+	
+	switch (Port) {
+		case BOOSTER_GAIN:
+			psBooster->m_pfGain = DataLocation;
+    		break;
+		case BOOSTER_CLIP:
+			psBooster->m_pfClip = DataLocation;
+    		break;
+		case BOOSTER_CURVE:
+    		psBooster->m_pfCurve = DataLocation;
+    		break;
+  		case BOOSTER_INPUT1:
+    		psBooster->m_pfInputBuffer1 = DataLocation;
+    		break;
+  		case BOOSTER_OUTPUT1:
+    		psBooster->m_pfOutputBuffer1 = DataLocation;
+    		break;
+  		case BOOSTER_INPUT2:
+    		psBooster->m_pfInputBuffer2 = DataLocation;
+    		break;
+  		case BOOSTER_OUTPUT2:
+		    psBooster->m_pfOutputBuffer2 = DataLocation;
+    		break;
+  }
+  
+}
+
+/* Booster mono */
+
+void runMonoBooster(LADSPA_Handle Instance, unsigned long SampleCount) {
+  
+	LADSPA_Data * pfInput;
+	LADSPA_Data * pfOutput;
+	LADSPA_Data fGain;
+	LADSPA_Data fClip;
+	LADSPA_Data fCurve;
+	LADSPA_Data inputData;
+	LADSPA_Data outputData;
+	LADSPA_Data boosterGain;
+	LADSPA_Data asymmetryPositive;
+	LADSPA_Data asymmetryNegative;
+	
+	Booster * psBooster;
+	unsigned long lSampleIndex;
+
+	psBooster = (Booster *)Instance;
+	
+	fGain = *(psBooster->m_pfGain);
+	fClip = *(psBooster->m_pfClip);
+	fCurve = *(psBooster->m_pfCurve);
+	
+	boosterGain = powf( 10, fGain/20 );
+	fCurve = fCurve * 1.5f + 1;
+		
+	if( boosterGain < 0)
+		boosterGain = 0;
+		
+	asymmetryPositive = 1.0f;
+	asymmetryNegative = -1.0f;
+
+	asymmetryPositive = asymmetryPositive * fClip;
+	asymmetryNegative = asymmetryNegative * fClip;
+	
+	pfInput = psBooster->m_pfInputBuffer1;
+	pfOutput = psBooster->m_pfOutputBuffer1;
+	
+	for(lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){	
+	
+		inputData = *(pfInput++);
+		
+		if( inputData < 0 ){
+			outputData = -inputData;
+		} else {
+			outputData = inputData;
+		}
+		
+		outputData =  powf ( 1 - powf(1 - outputData , fCurve), 1/fCurve ) * boosterGain;
+		
+		if (outputData > asymmetryPositive) {
+ 			outputData = asymmetryPositive;
+ 		}
+		  
+		if( inputData >= 0 ){
+			*(pfOutput++) = outputData ;
+		} else {
+			*(pfOutput++) = -outputData ;
+		}
+		
+	}
+	
+}
+
+/* Booster stereo */
+
+void runStereoBooster(LADSPA_Handle Instance, unsigned long SampleCount) {
+  
+	LADSPA_Data * pfInput;
+	LADSPA_Data * pfOutput;
+	LADSPA_Data fGain;
+	LADSPA_Data fClip;
+	LADSPA_Data fCurve;
+	LADSPA_Data inputData;
+	LADSPA_Data outputData;
+	LADSPA_Data boosterGain;
+	LADSPA_Data asymmetryPositive;
+	LADSPA_Data asymmetryNegative;
+	
+	Booster * psBooster;
+	unsigned long lSampleIndex;
+
+	psBooster = (Booster *)Instance;
+
+	fGain = *(psBooster->m_pfGain);
+	fClip = *(psBooster->m_pfClip);
+	fCurve = *(psBooster->m_pfCurve);
+	
+	boosterGain = powf( 10, fGain/20 );
+	fCurve = fCurve * 1.5f + 1;
+	
+	if( boosterGain < 0)
+		boosterGain = 0;
+		
+	asymmetryPositive = 1.0f;
+	asymmetryNegative = -1.0f;
+		
+	asymmetryPositive = asymmetryPositive * fClip;
+	asymmetryNegative = asymmetryNegative * fClip;
+	
+	pfInput = psBooster->m_pfInputBuffer1;
+	pfOutput = psBooster->m_pfOutputBuffer1;
+  
+	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){
+		
+		inputData = *(pfInput++);
+		
+		if( inputData < 0 ){
+			outputData = -inputData;
+		} else {
+			outputData = inputData;
+		}
+		
+		outputData =  powf ( 1 - powf(1 - outputData , fCurve), 1/fCurve ) * boosterGain;
+		
+		if (outputData > asymmetryPositive) {
+ 			outputData = asymmetryPositive;
+ 		}
+		  
+		if( inputData >= 0 ){
+			*(pfOutput++) = outputData ;
+		} else {
+			*(pfOutput++) = -outputData ;
+		}
+		
+	}
+
+	pfInput = psBooster->m_pfInputBuffer2;
+	pfOutput = psBooster->m_pfOutputBuffer2;
+  
+	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++){
+	
+    	inputData = *(pfInput++);
+		
+		if( inputData < 0 ){
+			outputData = -inputData;
+		} else {
+			outputData = inputData;
+		}
+		
+		outputData =  powf ( 1 - powf(1 - outputData , fCurve), 1/fCurve ) * boosterGain;
+		
+		if (outputData > asymmetryPositive) {
+ 			outputData = asymmetryPositive;
+ 		}
+		  
+		if( inputData >= 0 ){
+			*(pfOutput++) = outputData ;
+		} else {
+			*(pfOutput++) = -outputData ;
+		}
+		
+	}
+}
+
+/* Booster cleanup */
+
+void cleanupBooster(LADSPA_Handle Instance) {
+
+	Booster * psBooster;
+	psBooster = (Booster *)Instance;
+
+	free(psBooster);
+}
+
+LADSPA_Descriptor * g_psMonoDescriptor = NULL;
+LADSPA_Descriptor * g_psStereoDescriptor = NULL;
+
+/* Booster _init() function */
+
+void _init() {
+
+  char ** pcPortNames;
+  LADSPA_PortDescriptor * piPortDescriptors;
+  LADSPA_PortRangeHint * psPortRangeHints;
+
+  g_psMonoDescriptor
+    = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
+  g_psStereoDescriptor 
+    = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
+
+  if (g_psMonoDescriptor) {
+  
+    g_psMonoDescriptor->UniqueID
+      = 2545;
+    g_psMonoDescriptor->Label
+      = strdup("BoosterM");
+    g_psMonoDescriptor->Properties
+      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
+    g_psMonoDescriptor->Name 
+      = strdup("Clipping Booster (mono)");
+    g_psMonoDescriptor->Maker
+      = strdup("Artemiy Pavlov");
+    g_psMonoDescriptor->Copyright
+      = strdup("(c)2005 GPL");
+    g_psMonoDescriptor->PortCount
+      = 5;
+    piPortDescriptors
+      = (LADSPA_PortDescriptor *)calloc(5, sizeof(LADSPA_PortDescriptor));
+    g_psMonoDescriptor->PortDescriptors
+      = (const LADSPA_PortDescriptor *)piPortDescriptors;
+	  
+    piPortDescriptors[BOOSTER_CURVE]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+    piPortDescriptors[BOOSTER_GAIN]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[BOOSTER_CLIP]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+    piPortDescriptors[BOOSTER_INPUT1]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+    piPortDescriptors[BOOSTER_OUTPUT1]
+      = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	  
+    pcPortNames
+      = (char **)calloc(5, sizeof(char *));
+	g_psMonoDescriptor->PortNames 
+      = (const char **)pcPortNames;
+	  
+    pcPortNames[BOOSTER_CURVE]
+      = strdup("Curve");
+	pcPortNames[BOOSTER_GAIN]
+      = strdup("Gain (dB)");
+	 pcPortNames[BOOSTER_CLIP]
+      = strdup("Clip");
+	pcPortNames[BOOSTER_INPUT1]
+      = strdup("Input");
+    pcPortNames[BOOSTER_OUTPUT1]
+      = strdup("Output");
+	  
+    psPortRangeHints = ((LADSPA_PortRangeHint *)
+			calloc(5, sizeof(LADSPA_PortRangeHint)));
+    g_psMonoDescriptor->PortRangeHints
+      = (const LADSPA_PortRangeHint *)psPortRangeHints;
+	
+	psPortRangeHints[BOOSTER_CURVE].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_DEFAULT_0);
+	 
+    psPortRangeHints[BOOSTER_CURVE].LowerBound
+	 = 0;
+	psPortRangeHints[BOOSTER_CURVE].UpperBound
+	 = 1; 
+	  
+    psPortRangeHints[BOOSTER_GAIN].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_INTEGER
+	 | LADSPA_HINT_DEFAULT_0);
+    psPortRangeHints[BOOSTER_GAIN].LowerBound
+	 = 0;
+	psPortRangeHints[BOOSTER_GAIN].UpperBound
+	 = MAX_GAIN;
+	 
+	 psPortRangeHints[BOOSTER_CLIP].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_DEFAULT_1);
+    psPortRangeHints[BOOSTER_CLIP].LowerBound
+	 = 0;
+	psPortRangeHints[BOOSTER_CLIP].UpperBound
+	 = 1;
+	  
+	psPortRangeHints[BOOSTER_INPUT1].HintDescriptor
+	 = 0;
+    psPortRangeHints[BOOSTER_OUTPUT1].HintDescriptor
+	 = 0;
+	  
+    g_psMonoDescriptor->instantiate 
+      = instantiateBooster;
+    g_psMonoDescriptor->connect_port 
+      = connectPortToBooster;
+    g_psMonoDescriptor->activate
+      = NULL;
+    g_psMonoDescriptor->run
+      = runMonoBooster;
+    g_psMonoDescriptor->run_adding
+      = NULL;
+    g_psMonoDescriptor->set_run_adding_gain
+      = NULL;
+    g_psMonoDescriptor->deactivate
+      = NULL;
+    g_psMonoDescriptor->cleanup
+      = cleanupBooster;
+  }
+  
+  if (g_psStereoDescriptor) {
+    
+    g_psStereoDescriptor->UniqueID
+      = 2546;
+    g_psStereoDescriptor->Label
+      = strdup("BoosterS");
+    g_psStereoDescriptor->Properties
+      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
+    g_psStereoDescriptor->Name 
+      = strdup("Clipping Booster (stereo)");
+    g_psStereoDescriptor->Maker
+      = strdup("Artemiy Pavlov");
+    g_psStereoDescriptor->Copyright
+      = strdup("(c)2005 GPL");
+    g_psStereoDescriptor->PortCount
+      = 7;
+    piPortDescriptors
+      = (LADSPA_PortDescriptor *)calloc(7, sizeof(LADSPA_PortDescriptor));
+    g_psStereoDescriptor->PortDescriptors
+      = (const LADSPA_PortDescriptor *)piPortDescriptors;
+    piPortDescriptors[BOOSTER_CURVE]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[BOOSTER_GAIN]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+	piPortDescriptors[BOOSTER_CLIP]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
+    piPortDescriptors[BOOSTER_INPUT1]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+    piPortDescriptors[BOOSTER_OUTPUT1]
+      = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+    piPortDescriptors[BOOSTER_INPUT2]
+      = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
+    piPortDescriptors[BOOSTER_OUTPUT2]
+      = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+	  
+    pcPortNames
+      = (char **)calloc(7, sizeof(char *));
+    g_psStereoDescriptor->PortNames 
+      = (const char **)pcPortNames;
+	  
+    pcPortNames[BOOSTER_CURVE]
+      = strdup("Curve");
+	pcPortNames[BOOSTER_GAIN]
+      = strdup("Gain (dB)");
+	pcPortNames[BOOSTER_CLIP]
+      = strdup("Clip");
+    pcPortNames[BOOSTER_INPUT1]
+      = strdup("Input L");
+    pcPortNames[BOOSTER_OUTPUT1]
+      = strdup("Output L");
+    pcPortNames[BOOSTER_INPUT2]
+      = strdup("Input R");
+    pcPortNames[BOOSTER_OUTPUT2]
+      = strdup("Output R");
+	  
+    psPortRangeHints = ((LADSPA_PortRangeHint *)
+			calloc(7, sizeof(LADSPA_PortRangeHint)));
+    g_psStereoDescriptor->PortRangeHints
+      = (const LADSPA_PortRangeHint *)psPortRangeHints;
+	  
+    
+	psPortRangeHints[BOOSTER_CURVE].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_DEFAULT_0);
+	 
+    psPortRangeHints[BOOSTER_CURVE].LowerBound
+	 = 0;
+	psPortRangeHints[BOOSTER_CURVE].UpperBound
+	 = 1; 
+	
+	psPortRangeHints[BOOSTER_GAIN].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_INTEGER
+	 | LADSPA_HINT_DEFAULT_0);
+    
+	psPortRangeHints[BOOSTER_GAIN].LowerBound
+	 = 0;
+	psPortRangeHints[BOOSTER_GAIN].UpperBound
+	 = MAX_GAIN;
+	  
+	psPortRangeHints[BOOSTER_CLIP].HintDescriptor
+      = (LADSPA_HINT_BOUNDED_BELOW 
+	 | LADSPA_HINT_BOUNDED_ABOVE
+	 | LADSPA_HINT_DEFAULT_1);
+    psPortRangeHints[BOOSTER_CLIP].LowerBound
+	 = 0;
+	psPortRangeHints[BOOSTER_CLIP].UpperBound
+	 = 1;
+	 
+	psPortRangeHints[BOOSTER_INPUT1].HintDescriptor
+	 = 0;
+    psPortRangeHints[BOOSTER_OUTPUT1].HintDescriptor
+	 = 0;
+    psPortRangeHints[BOOSTER_INPUT2].HintDescriptor
+	 = 0;
+    psPortRangeHints[BOOSTER_OUTPUT2].HintDescriptor
+	 = 0;
+	  
+    g_psStereoDescriptor->instantiate 
+      = instantiateBooster;
+    g_psStereoDescriptor->connect_port 
+      = connectPortToBooster;
+    g_psStereoDescriptor->activate
+      = NULL;
+    g_psStereoDescriptor->run
+      = runStereoBooster;
+    g_psStereoDescriptor->run_adding
+      = NULL;
+    g_psStereoDescriptor->set_run_adding_gain
+      = NULL;
+    g_psStereoDescriptor->deactivate
+      = NULL;
+    g_psStereoDescriptor->cleanup
+      = cleanupBooster;
+  }
+}
+
+void deleteDescriptor(LADSPA_Descriptor * psDescriptor) {
+  unsigned long lIndex;
+  if (psDescriptor) {
+    free((char *)psDescriptor->Label);
+    free((char *)psDescriptor->Name);
+    free((char *)psDescriptor->Maker);
+    free((char *)psDescriptor->Copyright);
+    free((LADSPA_PortDescriptor *)psDescriptor->PortDescriptors);
+    for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++)
+      free((char *)(psDescriptor->PortNames[lIndex]));
+    free((char **)psDescriptor->PortNames);
+    free((LADSPA_PortRangeHint *)psDescriptor->PortRangeHints);
+    free(psDescriptor);
+  }
+}
+
+void _fini() {
+  deleteDescriptor(g_psMonoDescriptor);
+  deleteDescriptor(g_psStereoDescriptor);
+}
+
+
+#ifdef WIN32
+	#define _DLL_EXPORT_ __declspec(dllexport)
+	int bIsFirstTime = 1; 
+	void _init(); // forward declaration
+#else
+	#define _DLL_EXPORT_ 
+#endif
+
+
+
+_DLL_EXPORT_ const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) {
+#ifdef WIN32
+	if (bIsFirstTime) {
+		_init();
+		bIsFirstTime = 0;
+	}
+#endif
+
+  switch (Index) {
+  case 0:
+    return g_psMonoDescriptor;
+  case 1:
+    return g_psStereoDescriptor;
+  default:
+    return NULL;
+  }
+}
Index: /branches/tabbedInterface/plugins/wasp/wasp.pro
===================================================================
--- /branches/tabbedInterface/plugins/wasp/wasp.pro	(revision 3)
+++ /branches/tabbedInterface/plugins/wasp/wasp.pro	(revision 3)
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = wasp_booster wasp_noisifier wasp_xshaper
Index: /branches/tabbedInterface/extra/extra.pro
===================================================================
--- /branches/tabbedInterface/extra/extra.pro	(revision 3)
+++ /branches/tabbedInterface/extra/extra.pro	(revision 3)
@@ -0,0 +1,5 @@
+include(../features.pri)
+
+TEMPLATE = subdirs
+SUBDIRS = hydrogenPlayer hydrogenSynth
+
Index: /branches/tabbedInterface/extra/hydrogenSynth/hydrogenSynth.pro
===================================================================
--- /branches/tabbedInterface/extra/hydrogenSynth/hydrogenSynth.pro	(revision 177)
+++ /branches/tabbedInterface/extra/hydrogenSynth/hydrogenSynth.pro	(revision 177)
@@ -0,0 +1,87 @@
+include(../../features.pri)
+
+TARGET = hydrogenSynth
+INCLUDEPATH += ../../libs/hydrogen/include
+QT += xml
+CONFIG += qt warn_on precompile_header release
+#PRECOMPILED_HEADER  = src/Precompiled.h
+LIBS += ../../libs/libhydrogen.a
+
+
+linux-g++ {
+	message( LINUX BUILD )
+	LIBS += -lsndfile
+	LIBS += -ltar
+}
+linux-g++-64 {
+	message( LINUX 64bit BUILD )
+	LIBS += -lsndfile
+	LIBS += -ltar
+}
+
+win32 {
+	message( WIN32 BUILD )
+	INCLUDEPATH += ../../win32build/includes
+	INCLUDEPATH += ../../win32build/libs/libpthread
+	INCLUDEPATH += ../../win32build/libs/libsndfile
+	INCLUDEPATH += ../../win32build/libs/flac
+
+	LIBS += ../../win32build/libs/libsndfile/libsndfile.a
+	LIBS += ../../win32build/libs/libpthread/libpthreadGC1.a
+	LIBS += ../../win32build/libs/portaudio/libportaudio.a
+	LIBS += ../../win32build/libs/portmidi/libporttime.a
+	LIBS += ../../win32build/libs/portmidi/libportmidi.a
+	LIBS += -lwinmm
+}
+
+macx {
+	message( MAC BUILD )
+	LIBS += -L/opt/local/lib
+	LIBS += -lsndfile
+	LIBS += -ltar
+	INCLUDEPATH += /System/Library/Frameworks/Carbon.framework/Headers
+	QMAKE_LFLAGS_SONAME  = -Wl,-install_name,@executable_path/../Frameworks/
+}
+
+
+DEFINES += $$H2DEFINES
+contains(H2DEFINES, LRDF_SUPPORT ){
+	LIBS += -llrdf
+}
+
+contains(H2DEFINES, ALSA_SUPPORT ){
+	LIBS += -lasound
+}
+
+contains(H2DEFINES, JACK_SUPPORT ) {
+	LIBS += -ljack
+}
+
+contains(H2DEFINES, LASH_SUPPORT ) {
+	LIBS += -llash
+}
+
+contains(H2DEFINES, FLAC_SUPPORT ) {
+	linux-g++ {
+		LIBS += -lFLAC -lFLAC++
+	}
+	linux-g++-64 {
+		LIBS += -lFLAC -lFLAC++
+	}
+	win32 {
+		LIBS += ../../win32build/libs/flac/libFLAC++.a
+		LIBS += ../../win32build/libs/flac/libFLAC.a
+	}
+	macx {
+		LIBS += -lFLAC -lFLAC++
+	}
+}
+
+# the executable will be built in debug mode
+QMAKE_CXXFLAGS += -g -Wall
+
+
+
+SOURCES += \
+	HydrogenSynth.cpp
+
Index: /branches/tabbedInterface/extra/hydrogenSynth/HydrogenSynth.cpp
===================================================================
--- /branches/tabbedInterface/extra/hydrogenSynth/HydrogenSynth.cpp	(revision 1244)
+++ /branches/tabbedInterface/extra/hydrogenSynth/HydrogenSynth.cpp	(revision 1244)
@@ -0,0 +1,76 @@
+#include <iostream>
+using namespace std;
+
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/fx/Effects.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/note.h>
+
+#include <QtGui>
+
+int main( int argc, char* argv[] )
+{
+	cout << "--=( Hydrogen Synth test )=--" << endl;
+
+	QApplication a(argc, argv);
+
+	Object::use_verbose_log( true );
+
+	H2Core::Hydrogen *pHydrogen = H2Core::Hydrogen::get_instance();
+
+	H2Core::AudioEngine *pEngine = H2Core::AudioEngine::get_instance();
+
+	H2Core::Synth *pSynth = pEngine->get_synth();
+
+
+
+	char pippo;
+
+	while (true) {
+		pippo = getchar();
+		switch( pippo ) {
+			case 'a':
+				{
+				cout << "note on" << endl;
+				H2Core::NoteKey key;
+				key.m_key = H2Core::NoteKey::C;
+				H2Core::Note *pNote = new H2Core::Note( 0, 0, 0.8, 1.0, 1.0, -1, 0.0, key );
+
+				pSynth->noteOn( pNote );
+
+				}
+				break;
+
+			case 's':
+				{
+				cout << "note off" << endl;
+				H2Core::NoteKey key;
+				key.m_key = H2Core::NoteKey::C;
+				H2Core::Note *pNote = new H2Core::Note( 0, 0, 0.8, 1.0, 1.0, -1, 0.0, key );
+				pSynth->noteOff( pNote );
+				}
+				break;
+
+			case 'q':
+				cout << endl << "shutdown..." << endl;
+				pHydrogen->sequencer_stop();
+
+				delete H2Core::AudioEngine::get_instance();
+				delete H2Core::EventQueue::get_instance();
+				delete H2Core::Preferences::get_instance();
+				delete Logger::get_instance();
+
+				std::cout << std::endl << std::endl << Object::get_objects_number() << " alive objects" << std::endl << std::endl;
+				Object::print_object_map();
+
+				return 0;
+				break;
+		}
+	}
+
+	cout << "bye..." << endl;
+	return 0;
+}
+
Index: /branches/tabbedInterface/extra/serverTools/hydrogen.php
===================================================================
--- /branches/tabbedInterface/extra/serverTools/hydrogen.php	(revision 122)
+++ /branches/tabbedInterface/extra/serverTools/hydrogen.php	(revision 122)
@@ -0,0 +1,157 @@
+<?php
+	/*
+	* Hydrogen Web Toolkit
+	* Copyright(c) 2008 by Sebastian Moors [mauser@smoors.de]
+	*
+	* http://www.hydrogen-music.org
+	*
+	* This program is free software; you can redistribute it and/or modify
+	* it under the terms of the GNU General Public License as published by
+	* the Free Software Foundation; either version 2 of the License, or
+	* (at your option) any later version.
+	*
+	* This program is distributed in the hope that it will be useful,
+	* but WITHOUT ANY WARRANTY, without even the implied warranty of
+	* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	* GNU General Public License for more details.
+	*
+	* You should have received a copy of the GNU General Public License
+	* along with this program; if not, write to the Free Software
+	* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+	*
+	*/
+
+
+	/*
+		Use this script if you want to share your hydrogen songs,patterns and
+		drumkits with other people. It generates a xml-file which can be used
+		with the hydrogen soundlibrary.
+
+		Just place this script in one directory with all your drumkits, songs 
+		and patterns and make it available via a webserver.
+
+		Songs and patterns could be parsed in place. Since drumkits are archives,
+		we cannot parse the files at runtime. Therefore, just the name and the url of the drumkit will be used. 
+		If you want additional informations ( such as author / info ) take a look
+		at the metaInfo.inc file (the file has to be in the same directory as this script).
+		
+	*/
+
+
+	/*
+		metaInfo.inc holds meta informations about the drumkits, namely:
+		
+		- url
+		- author 
+		- info
+		- name
+
+		If metaInfo.inc is not available, the script takes the filename as namely	and guesses the url
+	*/
+
+	if ( is_file("metaInfo.inc") ) {
+		include("metaInfo.inc");
+	}
+
+
+	function getTag( $xml , $tag ){
+		preg_match( "/". $tag . "(.*)</" , $xml , $found );
+		if( ISSET( $found[1] ) ) {
+			return $found[1];
+		} 
+	}
+
+
+	//$url should be defined in metaInfo.inc
+	if( ! ISSET( $url ) ){
+		$url = $_SERVER [ 'SERVER_NAME' ] ;
+		$dir = dirname ( $_SERVER['PHP_SELF'] ) ;
+		$url = "http://$url$dir";
+	}
+
+	$author = "";
+	$info = "";
+
+	/* Start of xml-document */
+
+	print "<?xml version='1.0' encoding='UTF-8'?>\n";
+	print "<drumkit_list>\n";
+
+
+	/* Start of song listing */
+	
+
+	$dir = "./";
+	if ($dh = opendir( $dir )) {
+        	while (( $file = readdir($dh) ) !== false) {
+			$extension = array_pop( explode(".", $file) );
+			if( $extension == "h2song" ) {
+				print "\t<song>\n";
+				$content = file( $dir.$file );
+				$xml = join( " ",$content );
+				print "\t\t<name>" . getTag( $xml , "<name>" ) . "</name>\n";
+				print "\t\t<url>" . $url.$file ."</url>\n";
+				print "\t\t<author>" . getTag( $xml , "<author>" ) . "</author>\n";
+				print "\t\t<info>" . getTag( $xml , "<info>" ) . "</info>\n";
+				print "\t</song>\n";
+			}
+        	}
+	    	closedir( $dh );
+    	}
+	/* End of song listing */
+
+
+
+	/* Start of pattern listing */
+	$dir = "./";
+	if ($dh = opendir( $dir )) {
+        	while ( ( $file = readdir( $dh ) ) !== false ) {
+			$extension = array_pop(explode( ".", $file ));
+			if( $extension == "h2pattern" ) {
+				$content = file( $dir.$file );
+				$xml = join( " " , $content );
+				print "\t<pattern>\n";
+				print "\t\t<name>" . getTag( $xml , "<name>" ) . "</name>\n";
+				print "\t\t<url>" . $url.$file ."</url>\n";
+				print "\t</pattern>\n";
+			}
+        	}
+	    	closedir( $dh );
+    	}	
+	/* End of pattern listing */
+
+
+	/* Start of drumkit listing */
+	$dir = "./";
+	if ($dh = opendir( $dir ) ) {
+        	while ( ( $file = readdir( $dh ) ) !== false) {
+			$extension = array_pop( explode( ".", $file ) );
+			if( $extension == "h2drumkit" ) {
+				$content = file( $dir.$file );
+				$xml = join( " " , $content );
+				print "\t<drumkit>\n";
+			
+				//name: filename without extension
+				$name = basename( $file,".h2drumkit" );
+
+				If( ISSET( $drumkit_list[ $name ]) ){
+					$author = $drumkit_list[ $name ][ "author" ];
+					$info = $drumkit_list[ $name ][ "info" ];
+				}
+
+				print "\t\t<name> $name </name>\n";
+				print "\t\t<url>" . $url.$file ."</url>\n";
+				print "\t\t<author>$author</author>\n";
+				print "\t\t<info>$info</info>\n";
+				print "\t</drumkit>\n";
+			}
+        	}
+	    	closedir( $dh );
+    	}	
+	/* End of pattern listing */
+
+
+	print "</drumkit_list>\n";
+		
+
+?>
Index: /branches/tabbedInterface/extra/serverTools/metaInfo.inc
===================================================================
--- /branches/tabbedInterface/extra/serverTools/metaInfo.inc	(revision 122)
+++ /branches/tabbedInterface/extra/serverTools/metaInfo.inc	(revision 122)
@@ -0,0 +1,10 @@
+<?php
+
+	/*
+	$url = "http://example.com/";
+
+	$drumkit_list[ "K-27_Trash_Kit" ][ "author" ] = "wolke";
+	$drumkit_list[ "K-27_Trash_Kit" ][ "info" ] = "A real trash kit!";
+	*/
+
+?>
Index: /branches/tabbedInterface/extra/hydrogenPlayer/hydrogenPlayer.pro
===================================================================
--- /branches/tabbedInterface/extra/hydrogenPlayer/hydrogenPlayer.pro	(revision 177)
+++ /branches/tabbedInterface/extra/hydrogenPlayer/hydrogenPlayer.pro	(revision 177)
@@ -0,0 +1,88 @@
+include(../../features.pri)
+
+TARGET = hydrogenPlayer
+INCLUDEPATH += ../../libs/hydrogen/include
+QT += xml console
+CONFIG += qt warn_on precompile_header release
+#PRECOMPILED_HEADER  = src/Precompiled.h
+LIBS += ../../libs/libhydrogen.a
+
+PRE_TARGETDEPS = ../../libs/libhydrogen.a
+
+linux-g++ {
+	message( LINUX BUILD )
+	LIBS += -lsndfile
+	LIBS += -ltar
+}
+linux-g++-64 {
+	message( LINUX 64bit BUILD )
+	LIBS += -lsndfile
+	LIBS += -ltar
+}
+
+win32 {
+	message( WIN32 BUILD )
+	INCLUDEPATH += ../../win32build/includes
+	INCLUDEPATH += ../../win32build/libs/libpthread
+	INCLUDEPATH += ../../win32build/libs/libsndfile
+	INCLUDEPATH += ../../win32build/libs/flac
+
+	LIBS += ../../win32build/libs/libsndfile/libsndfile.a
+	LIBS += ../../win32build/libs/libpthread/libpthreadGC1.a
+	LIBS += ../../win32build/libs/portaudio/libportaudio.a
+	LIBS += ../../win32build/libs/portmidi/libporttime.a
+	LIBS += ../../win32build/libs/portmidi/libportmidi.a
+	LIBS += -lwinmm
+}
+
+macx {
+	message( MAC BUILD )
+	LIBS += -L/opt/local/lib
+	LIBS += -lsndfile
+	LIBS += -ltar
+	INCLUDEPATH += /System/Library/Frameworks/Carbon.framework/Headers
+	QMAKE_LFLAGS_SONAME  = -Wl,-install_name,@executable_path/../Frameworks/
+}
+
+
+DEFINES += $$H2DEFINES
+contains(H2DEFINES, LRDF_SUPPORT ){
+	LIBS += -llrdf
+}
+
+contains(H2DEFINES, ALSA_SUPPORT ){
+	LIBS += -lasound
+}
+
+contains(H2DEFINES, JACK_SUPPORT ) {
+	LIBS += -ljack
+}
+
+contains(H2DEFINES, LASH_SUPPORT ) {
+	LIBS += -llash
+}
+
+contains(H2DEFINES, FLAC_SUPPORT ) {
+	linux-g++ {
+		LIBS += -lFLAC -lFLAC++
+	}
+	linux-g++-64 {
+		LIBS += -lFLAC -lFLAC++
+	}
+	win32 {
+		LIBS += ../../win32build/libs/flac/libFLAC++.a
+		LIBS += ../../win32build/libs/flac/libFLAC.a
+	}
+	macx {
+		LIBS += -lFLAC -lFLAC++
+	}
+}
+
+# the executable will be built in debug mode
+QMAKE_CXXFLAGS += -g -Wall
+
+
+
+SOURCES += \
+	HydrogenPlayer.cpp
+
Index: /branches/tabbedInterface/extra/hydrogenPlayer/HydrogenPlayer.cpp
===================================================================
--- /branches/tabbedInterface/extra/hydrogenPlayer/HydrogenPlayer.cpp	(revision 1244)
+++ /branches/tabbedInterface/extra/hydrogenPlayer/HydrogenPlayer.cpp	(revision 1244)
@@ -0,0 +1,137 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <iostream>
+#include <cstdio>
+#include <cstdlib>
+
+#include <hydrogen/Object.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/LocalFileMng.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/fx/Effects.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/audio_engine.h>
+
+using std::cout;
+using std::endl;
+
+#include <QApplication>
+
+void usage()
+{
+	cout << "Usage: hydrogenPlayer song.h2song" << endl;
+	exit(0);
+}
+
+void quit()
+{
+	_INFOLOG( "Quitting..." );
+	sleep(1);
+	cout << "\nBye..." << endl;
+	delete Logger::get_instance();
+	exit(0);
+}
+
+int main(int argc, char** argv)
+{
+	Object::use_verbose_log( true );
+	_INFOLOG( "test" );
+
+
+	if (argc != 2) {
+		usage();
+	}
+	cout << "Hydrogen player starting..." << endl << endl;
+
+	QApplication a(argc, argv);
+
+	QString filename = argv[1];
+
+	H2Core::Preferences *preferences = H2Core::Preferences::get_instance();
+	H2Core::AudioEngine::get_instance();
+
+	H2Core::Song *pSong = H2Core::Song::load( filename );
+	if (pSong == NULL) {
+		cout << "Error loading song!" << endl;
+	}
+
+	H2Core::Hydrogen *hydrogen = H2Core::Hydrogen::get_instance();
+	hydrogen->setSong(pSong);
+
+
+	cout << "Press b for rewind from beginning" << endl;
+	cout << "Press p for play" << endl;
+	cout << "Press s for stop" << endl;
+	cout << "Press q for quit" << endl;
+	cout << "f = show frames" << endl;
+
+	char pippo;
+
+	while (true) {
+		pippo = getchar();
+		switch( pippo ) {
+			case 'q':
+				cout << endl << "HydrogenPlayer shutdown..." << endl;
+				hydrogen->sequencer_stop();
+
+				delete hydrogen;
+				delete pSong;
+				delete H2Core::EventQueue::get_instance();
+				delete H2Core::AudioEngine::get_instance();
+				delete preferences;
+				delete Logger::get_instance();
+
+				std::cout << std::endl << std::endl << Object::get_objects_number() << " alive objects" << std::endl << std::endl;
+				Object::print_object_map();
+
+				exit(0);
+				break;
+
+			case 'p':
+				hydrogen->sequencer_play();
+				break;
+
+			case 's':
+				hydrogen->sequencer_stop();
+				break;
+
+			case 'b':
+				hydrogen->setPatternPos( 0 );
+				break;
+
+			case 'f':
+				cout << "Frames = " << hydrogen->getTotalFrames() << endl;
+				break;
+
+			case 'd':
+				cout << "DEBUG" << endl;
+				Object::print_object_map();
+				int nObj = Object::get_objects_number();
+				std::cout << std::endl << std::endl << nObj << " alive objects" << std::endl << std::endl;
+				break;
+		}
+	}
+}
+
+
+
Index: /branches/tabbedInterface/INSTALL.txt
===================================================================
--- /branches/tabbedInterface/INSTALL.txt	(revision 1299)
+++ /branches/tabbedInterface/INSTALL.txt	(revision 1299)
@@ -0,0 +1,192 @@
+------------------------------------------------------------------------------
+                       H Y D R O G E N          Drum machine
+------------------------------------------------------------------------------
+
+BUILDING AND INSTALLING HYDROGEN
+================================
+
+Contents:
+
+1. System Requirements
+2. Download
+3. Binary Packages
+4. Prerequisites to Build from Source
+5. Build and Install from Source
+6. INSTALL.txt Changelog
+
+1. System Requirements
+----------------------
+
+Hydrogen is supported on the following operating systems:
+
+  * Linux/Unix/BSD
+  * Mac OS X
+
+Hydrogen is *not* supported on Windows because there are currently no
+Windows developers on the project... and so the Windows components
+have fallen into disrepair.
+
+Hydrogen is known to work well on fairly old systems like this (as of
+2009):
+
+  Pentium III 500 MHz
+  198 MB RAM
+  Consumer-Grade (cheap) audio card
+  Keyboard and Mouse
+  1x1 USB MIDI Interface (optional)
+
+2. Download
+-----------
+
+Hydrogen can be downloaded as a binary package, source distribution,
+or you can check out the current development version with Subversion.
+These can be accessed on the Hydrogen home page:
+
+	http://www.hydrogen-music.org/
+
+The source code for the current development version can be checked out
+via Subversion:
+
+	$ svn co http://svn.assembla.com/svn/hydrogen/trunk hydrogen
+
+3. Binary Packages
+------------------
+
+Debian (GNU/Linux) and Ubuntu (GNU/Linux):
+
+	Hydrogen can usually be installed with apt:
+
+	# apt-get install hydrogen
+
+	However, if you wish to have a more current version of
+	Hydrogen, the Hydrogen dev's typically maintain a .deb package
+	for Debian stable, testing, and some Ubuntu distributions.
+	Note that apt takes care of any library dependencies that you
+	have.
+
+Other GNU/Linux:
+
+	Check your package management system for the package
+	'hydrogen.'
+
+Mac OS X:
+
+	They Hydrogen home page has a binary package available for OS
+	X.  Extract the ZIP archive and it will create a hydrogen.app
+	folder.
+
+4. Prerequisites to Build from Source
+-------------------------------------
+
+In order to build from source, you will need the following libraries
+installed on your system, and the development header files:
+
+	REQUIRED
+	* Qt 4 Library (>=4.4.0, 4.3.x might work, 4.2.x won't)
+	* Qt 4 SDK (moc, uic, etc.)
+	* GNU g++ compiler (>=4.0, 3.x might work)
+	* scons (>=0.98, 1.0 preferred, <0.98 might work)
+	* libsndfile >=1.0.17
+	* zlib and libtar -OR- libarchive
+	  OS X: You will probably need to build libarchive from source.
+	* At least 1 audio and 1 midi driver
+	* OS X: Xcode
+
+	DRIVERS AVAILABLE
+	* JACK Audio Connection Kit (>=0.103.0)
+	* ALSA (Advanced Linux Sound Architecture)
+	* OSS
+	* PortAudio (v18, not v19)
+	* PortMIDI
+	* CoreAudio (OS X)
+	* CoreMidi (OS X)
+
+	OPTIONAL SUPPORT
+	* LASH (Linux Audio Session Handler)
+	* libFLAC for handling FLAC sound files.
+	* liblrdf for LADSPA plugins
+
+On a single, 500MHz processor Hydrogen takes about 1.5 hours to build.
+
+5. Build and Install from Source
+--------------------------------
+
+If you wish to build a package for your operating system, skip down to
+the end of this section.
+
+This instructions are thought for building hydrogen on linux.
+We're providing a set of qmake project files for windows and
+mac osx builds. 
+Please read the relevant wiki pages for more informations:
+
+http://trac.assembla.com/hydrogen/wiki/development%3AcompileOSX
+http://trac.assembla.com/hydrogen/wiki/coding%3Apackagingwin
+
+After you have all the prerequisites, building and installing will
+look like this:
+
+	$ tar xjf hydrogen-0.9.4.tar.bz2
+	$ cd hydrogen-0.9.4
+	$ scons
+	$ sudo scons install
+
+If you wish to configure features like LADSPA plugins, FLAC support,
+or debugging symbols, get more information like this:
+
+	$ scons --help
+
+To change the directory where scons is installed, it is done like
+this:
+
+	$ scons prefix=/path/to/install/dir
+	$ sudo scons install
+
+Uninstalling Hydrogen is done like this:
+
+	$ sudo scons -c install
+
+Note that scons is a build system and not a package manager.  While we
+make every effort to ensure that Hydrogen uninstalls cleanly, it is
+not a guarantee.
+
+Hydrogen uses a scons tool that detects the correct Qt settings, but
+sometimes it needs a little help.  If Hydrogen fails to build
+(typically when a .ui file fails), set the Qt 4 install directory like
+this:
+
+	$ QTDIR=/opt/lib/qt4 scons
+
+It's also best to ensure that your PATH is pointing to the Qt 4
+versions of moc and uic, and not the Qt 3 versions.
+
+___CREATING A BINARY PACKAGE___
+
+If you are a package maintainer and wish for your packaging scripts to
+be included in the Hydrogen source tree, we would be happy to work
+with you.  Please contact the developer mailing list (see the Hydrogen
+home page).  The instructions below are for the package systems that
+have been contributed so far.
+
+___CREATING A .DEB PACKAGE___
+
+In order to create a .deb package for Debian or Debian-based systems
+(like Ubuntu), you first need the debhelper package:
+
+	# apt-get install debhelper
+
+To build the Hydrogen package:
+
+	$ tar xjf hydrogen-0.9.4.tar
+	$ cd hydrogen-0.9.4
+	$ cd linux
+	$ fakeroot dpkg-buildpackage
+
+This will place the .deb package and description files in the parent
+directory.  If you wish to change the version number for the archive,
+edit linux/debian/changelog to set the version.
+
+6. INSTALL.txt Changelog
+------------------------
+
+2009-04-08 Gabriel M. Beddingfield <gabriel@teuton.org>
+	* Create INSTALL.txt
Index: /branches/tabbedInterface/gui/gui.pro
===================================================================
--- /branches/tabbedInterface/gui/gui.pro	(revision 1377)
+++ /branches/tabbedInterface/gui/gui.pro	(revision 1377)
@@ -0,0 +1,218 @@
+######################################################################
+# Automatically generated by qmake (2.01a) to 26. helmi 14:51:41 2009
+######################################################################
+include(../features.pri)
+
+TARGET = Hydrogen
+INCLUDEPATH += ../ ../libs/hydrogen/include
+INCLUDEPATH += ./src/
+DESTDIR = ..
+
+QT += network xml
+
+CONFIG += qt warn_on precompile_header release
+PRECOMPILED_HEADER = src/Precompiled.h
+LIBS += ../libs/liblibhydrogen.a
+PRE_TARGETDEPS = ../libs/liblibhydrogen.a
+#QMAKE_CXXFLAGS += /D__PRETTY_FUNCTION__="__FUNCTION__" /wd4305 /DPTW32_STATIC_LIB
+
+OBJECTS_DIR = objs
+UI_DIR = objs
+UI_HEADERS_DIR = objs
+UI_SOURCES_DIR = objs
+MOC_DIR = objs
+win32 {
+    INCLUDEPATH += ../3rdparty/install/include
+    #INCLUDEPATH += ../3rdparty/install/libs/libpthread
+    #INCLUDEPATH += ../3rdparty/install/libs/libsndfile
+    #INCLUDEPATH += ../3rdparty/install/libs/flac
+    #INCLUDEPATH += ../3rdparty/install/libs/portaudio
+    #INCLUDEPATH += ../3rdparty/install/libs/portmidi
+    INCLUDEPATH += ../../../source/pthreads-w32-2-8-0-release
+
+    LIBS += "C:\Program Files\GnuWin32\lib\libarchive.lib"
+    LIBS += "C:\Qt\2009.03\mingw\lib\libpthread.a"
+    LIBS += "C:\Documents and Settings\sebastian\Desktop\hydrogen\3rdparty\libsndfile-1_0_17\libsndfile-1.dll"
+}
+
+#old windows libs..
+#LIBS += ../libflac++.lib ../libflac++_dynamic.lib ../libflac++_static.lib ../libflac.lib winmm.lib
+#LIBS += ../libflac++_static.lib ../libflac_static.lib winmm.lib
+#LIBS += ../optarg.lib
+#LIBS += ../ogg_static.lib
+#LIBS += ../pm_dll.lib
+#LIBS += ../portmidi.lib
+#LIBS += ../portaudio_x86.lib
+#LIBS += ../porttime.lib
+#LIBS += ../pthreadvc2.lib
+#LIBS += dsound.lib ../cmtar.lib ../sndfile.lib wsock32.lib
+
+
+DEPENDPATH += . \
+              src \
+              src\AudioFileBrowser \
+              src\InstrumentEditor \
+              src\Mixer \
+              src\PatternEditor \
+              src\PlaylistEditor \
+              src\SongEditor \
+              src\SoundLibrary \
+              src\SampleEditor \
+              src\UI \
+              src\widgets
+INCLUDEPATH += .
+
+TRANSLATIONS = \
+	../data/i18n/hydrogen.de.ts \
+	../data/i18n/hydrogen.fr.ts \
+	../data/i18n/hydrogen.it.ts \
+	../data/i18n/hydrogen.nl.ts \
+	../data/i18n/hydrogen.pt_BR.ts \
+	../data/i18n/hydrogen.sv.ts \
+	../data/i18n/hydrogen.es.ts \
+	../data/i18n/hydrogen.hu_HU.ts \
+	../data/i18n/hydrogen.ja.ts \
+	../data/i18n/hydrogen.pl.ts \
+	../data/i18n/hydrogen.ru.ts
+# Input
+HEADERS += src/AboutDialog.h \
+           src/AudioEngineInfoForm.h \
+           src/EventListener.h \
+           src/ExportSongDialog.h \
+           src/HelpBrowser.h \
+           src/HydrogenApp.h \
+           src/InstrumentRack.h \
+           src/LadspaFXProperties.h \
+           src/LadspaFXSelector.h \
+           src/MainForm.h \
+           src/PatternFillDialog.h \
+           src/PatternPropertiesDialog.h \
+           src/PlayerControl.h \
+           src/precompiled.h \
+           src/PreferencesDialog.h \
+           src/Skin.h \
+           src/SongPropertiesDialog.h \
+           src/SplashScreen.h \
+           src/AudioFileBrowser/AudioFileBrowser.h \
+           src/AudioFileBrowser/SampleWaveDisplay.h \
+           src/InstrumentEditor/InstrumentEditor.h \
+           src/InstrumentEditor/InstrumentEditorPanel.h \
+           src/InstrumentEditor/LayerPreview.h \
+           src/InstrumentEditor/WaveDisplay.h \
+           src/Mixer/Mixer.h \
+           src/Mixer/MixerLine.h \
+           src/PatternEditor/DrumPatternEditor.h \
+           src/PatternEditor/NotePropertiesRuler.h \
+           src/PatternEditor/PatternEditorInstrumentList.h \
+           src/PatternEditor/PatternEditorPanel.h \
+           src/PatternEditor/PatternEditorRuler.h \
+           src/PatternEditor/PianoRollEditor.h \
+           src/PlaylistEditor/PlaylistDialog.h \
+	   src/SampleEditor/DetailWaveDisplay.h \
+	   src/SampleEditor/MainSampleWaveDisplay.h \
+	   src/SampleEditor/TargetWaveDisplay.h \
+	   src/SampleEditor/SampleEditor.h \
+           src/SongEditor/SongEditor.h \
+           src/SongEditor/SongEditorPanel.h \
+           src/SongEditor/SongEditorPanelBpmWidget.h \
+           src/SoundLibrary/FileBrowser.h \
+           src/SoundLibrary/SoundLibraryExportDialog.h \
+           src/SoundLibrary/SoundLibraryImportDialog.h \
+           src/SoundLibrary/SoundLibraryPanel.h \
+           src/SoundLibrary/SoundLibraryPropertiesDialog.h \
+           src/SoundLibrary/SoundLibraryRepositoryDialog.h \
+           src/SoundLibrary/SoundLibrarySaveDialog.h \
+           src/SoundLibrary/SoundLibraryTree.h \
+           src/widgets/Button.h \
+           src/widgets/ClickableLabel.h \
+           src/widgets/CpuLoadWidget.h \
+           src/widgets/DownloadWidget.h \
+           src/widgets/Fader.h \
+           src/widgets/LCD.h \
+           src/widgets/LCDCombo.h \
+           src/widgets/MidiActivityWidget.h \
+           src/widgets/MidiSenseWidget.h \
+           src/widgets/midiTable.h \
+           src/widgets/PixmapWidget.h \
+           src/widgets/Rotary.h \
+ src/MetroBlinker.h
+FORMS += src/AudioFileBrowser/AudioFileBrowser_UI.ui \
+         src/PlaylistEditor/PlaylistDialog_UI.ui \
+	 src/SampleEditor/SampleEditor_Ui.ui \
+         src/SoundLibrary/SoundLibraryExportDialog_UI.ui \
+         src/SoundLibrary/SoundLibraryImportDialog_UI.ui \
+         src/SoundLibrary/SoundLibraryPropertiesDialog_UI.ui \
+         src/SoundLibrary/SoundLibraryRepositoryDialog_UI.ui \
+         src/SoundLibrary/SoundLibrarySaveDialog_UI.ui \
+         src/SongEditor/SongEditorPanelBpmWidget_UI.ui \
+         src/UI/about_dialog.ui \
+         src/UI/AudioEngineInfoForm_UI.ui \
+         src/UI/DrumkitManager_UI.ui \
+         src/UI/ExportSongDialog_UI.ui \
+         src/UI/LadspaFXSelector_UI.ui \
+         src/UI/PatternFillDialog_UI.ui \
+         src/UI/PatternPropertiesDialog_UI.ui \
+         src/UI/PreferencesDialog_UI.ui \
+         src/UI/SongPropertiesDialog_UI.ui \
+ src/MetroBlinker_UI.ui
+SOURCES += src/AboutDialog.cpp \
+	  ../version.cpp \
+           src/AudioEngineInfoForm.cpp \
+           src/ExportSongDialog.cpp \
+           src/HelpBrowser.cpp \
+           src/HydrogenApp.cpp \
+           src/InstrumentRack.cpp \
+           src/LadspaFXProperties.cpp \
+           src/LadspaFXSelector.cpp \
+           src/main.cpp \
+           src/MainForm.cpp \
+           src/PatternFillDialog.cpp \
+           src/PatternPropertiesDialog.cpp \
+           src/PlayerControl.cpp \
+           src/PreferencesDialog.cpp \
+           src/SongPropertiesDialog.cpp \
+           src/SplashScreen.cpp \
+           src/AudioFileBrowser/AudioFileBrowser.cpp \
+           src/AudioFileBrowser/SampleWaveDisplay.cpp \
+           src/InstrumentEditor/InstrumentEditor.cpp \
+           src/InstrumentEditor/InstrumentEditorPanel.cpp \
+           src/InstrumentEditor/LayerPreview.cpp \
+           src/InstrumentEditor/WaveDisplay.cpp \
+           src/Mixer/Mixer.cpp \
+           src/Mixer/MixerLine.cpp \
+           src/PatternEditor/DrumPatternEditor.cpp \
+           src/PatternEditor/NotePropertiesRuler.cpp \
+           src/PatternEditor/PatternEditorInstrumentList.cpp \
+           src/PatternEditor/PatternEditorPanel.cpp \
+           src/PatternEditor/PatternEditorRuler.cpp \
+           src/PatternEditor/PianoRollEditor.cpp \
+           src/PlaylistEditor/PlaylistDialog.cpp \
+	   src/SampleEditor/DetailWaveDisplay.cpp \
+	   src/SampleEditor/MainSampleWaveDisplay.cpp \
+	   src/SampleEditor/TargetWaveDisplay.cpp \
+	   src/SampleEditor/SampleEditor.cpp \
+           src/SongEditor/SongEditor.cpp \
+           src/SongEditor/SongEditorPanel.cpp \
+           src/SongEditor/SongEditorPanelBpmWidget.cpp \
+           src/SoundLibrary/FileBrowser.cpp \
+           src/SoundLibrary/SoundLibraryExportDialog.cpp \
+           src/SoundLibrary/SoundLibraryImportDialog.cpp \
+           src/SoundLibrary/SoundLibraryPanel.cpp \
+           src/SoundLibrary/SoundLibraryPropertiesDialog.cpp \
+           src/SoundLibrary/SoundLibraryRepositoryDialog.cpp \
+           src/SoundLibrary/SoundLibrarySaveDialog.cpp \
+           src/SoundLibrary/SoundLibraryTree.cpp \
+           src/widgets/Button.cpp \
+           src/widgets/ClickableLabel.cpp \
+           src/widgets/CpuLoadWidget.cpp \
+           src/widgets/DownloadWidget.cpp \
+           src/widgets/Fader.cpp \
+           src/widgets/LCD.cpp \
+           src/widgets/LCDCombo.cpp \
+           src/widgets/MidiActivityWidget.cpp \
+           src/widgets/MidiSenseWidget.cpp \
+           src/widgets/midiTable.cpp \
+           src/widgets/PixmapWidget.cpp \
+           src/widgets/Rotary.cpp \
+ \
+ src/MetroBlinker.cpp
Index: /branches/tabbedInterface/gui/src/AboutDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/AboutDialog.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/AboutDialog.h	(revision 377)
@@ -0,0 +1,53 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ABOUT__DIALOG_H
+#define ABOUT__DIALOG_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include "ui_about_dialog.h"
+
+class AboutDialog : public QDialog, public Ui_AboutDialog_UI
+{
+Q_OBJECT
+public:
+	AboutDialog(QWidget* parent);
+	~AboutDialog();
+
+private slots:
+	void on_okBtn_clicked();
+
+private:
+	class Author {
+		public:
+			QString m_sName;
+			QString m_sEmail;
+			QString m_sInfo;
+
+			Author( QString sName, QString sEmail, QString sInfo ) : m_sName( sName ), m_sEmail( sEmail ), m_sInfo( sInfo ) {}
+	};
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/PlayerControl.h
===================================================================
--- /branches/tabbedInterface/gui/src/PlayerControl.h	(revision 1488)
+++ /branches/tabbedInterface/gui/src/PlayerControl.h	(revision 1488)
@@ -0,0 +1,200 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PLAYER_CONTROL_H
+#define PLAYER_CONTROL_H
+
+#include <QtGui>
+
+#include "EventListener.h"
+#include <hydrogen/Object.h>
+
+namespace H2Core
+{
+	class Hydrogen;
+}
+
+class LCDSpinBox;
+class LCDDisplay;
+class Button;
+class ToggleButton;
+class CpuLoadWidget;
+class MidiActivityWidget;
+class PixmapWidget;
+
+///
+///
+///
+class MetronomeWidget : public QWidget,public EventListener, public Object
+{
+	Q_OBJECT
+	public:
+		MetronomeWidget(QWidget *pParent);
+		~MetronomeWidget();
+
+		virtual void metronomeEvent( int nValue );
+		virtual void paintEvent( QPaintEvent*);
+
+
+	public slots:
+		void updateWidget();
+
+
+	private:
+		enum m_state {
+			METRO_FIRST,
+			METRO_ON,
+			METRO_OFF
+		};
+
+		int m_nValue;
+		int m_state;
+
+		QPixmap m_metro_off;
+		QPixmap m_metro_on_firstbeat;
+		QPixmap m_metro_on;
+
+};
+
+
+///
+/// Player control panel
+///
+class PlayerControl : public QLabel, public Object
+{
+	Q_OBJECT
+	public:
+		PlayerControl(QWidget *parent);
+		~PlayerControl();
+
+		void showMessage( const QString& msg, int msec );
+		void showScrollMessage( const QString& msg, int msec, bool test );
+
+	private slots:
+		void recBtnClicked(Button* ref);
+		void recBtnRightClicked(Button* ref);
+		void playBtnClicked(Button* ref);
+		void stopBtnClicked(Button* ref);
+		void updatePlayerControl();
+		void songModeBtnClicked(Button* ref);
+		void liveModeBtnClicked(Button* ref);
+		void switchModeBtnClicked(Button* ref);
+		void jackTransportBtnClicked(Button* ref);
+		//jack time master
+		void jackMasterBtnClicked(Button* ref);
+		//~ jack time master
+		void bpmChanged();
+		void bpmButtonClicked( Button *pRef );
+		void bpmButtonPressed( Button* pBtn);
+		void bpmClicked();
+		void FFWDBtnClicked(Button *pRef);
+		void RewindBtnClicked(Button *pRef);
+		void songLoopBtnClicked(Button* ref);
+		void metronomeButtonClicked(Button* ref);
+		void onBpmTimerEvent();
+		void onStatusTimerEvent();
+		void onScrollTimerEvent();
+		void showButtonClicked( Button* pRef );
+
+		//beatcounter
+		void bconoffBtnClicked( Button* ref);
+		void bcSetPlayBtnClicked(Button* ref);
+		void bcbButtonClicked(Button* bBtn);
+		void bctButtonClicked(Button* tBtn);
+		//~ beatcounter
+		
+		//rubberband
+		void rubberbandButtonToggle(Button* ref);
+
+	private:
+		H2Core::Hydrogen *m_pEngine;
+		QPixmap m_background;
+
+		Button *m_pRwdBtn;
+		ToggleButton *m_pRecBtn;
+		ToggleButton *m_pRecDelBtn;
+		ToggleButton *m_pPlayBtn;
+		Button *m_pStopBtn;
+		Button *m_pFfwdBtn;
+
+		ToggleButton *m_pSongLoopBtn;
+
+		ToggleButton *m_pSongModeBtn;
+		ToggleButton *m_pLiveModeBtn;
+		Button *m_pSwitchModeBtn;
+
+		//beatcounter
+		ToggleButton *m_pBConoffBtn;
+		ToggleButton *m_pBCSpaceBtn;
+		ToggleButton *m_pBCSetPlayBtn;
+		Button *m_pBCTUpBtn;
+		Button *m_pBCTDownBtn;
+		Button *m_pBCBUpBtn;
+		Button *m_pBCBDownBtn;
+		//~ beatcounter
+
+		//rubberbandBPMChange
+		ToggleButton *m_pRubberBPMChange;
+
+		ToggleButton *m_pJackTransportBtn;
+		//jack time master
+		ToggleButton *m_pJackMasterBtn;
+		//~ jack time master
+		Button *m_pBPMUpBtn;
+		Button *m_pBPMDownBtn;
+
+		CpuLoadWidget *m_pCpuLoadWidget;
+		MidiActivityWidget *m_pMidiActivityWidget;
+
+		LCDSpinBox *m_pLCDBPMSpinbox;
+
+		LCDDisplay *m_pTimeDisplayH;
+		LCDDisplay *m_pTimeDisplayM;
+		LCDDisplay *m_pTimeDisplayS;
+		LCDDisplay *m_pTimeDisplayMS;
+
+		//beatcounter
+		PixmapWidget *m_pControlsBCPanel;
+
+		LCDDisplay *m_pBCDisplayZ;
+		LCDDisplay *m_pBCDisplayB;
+		LCDDisplay *m_pBCDisplayT;
+		//~ beatcounter
+
+		MetronomeWidget *m_pMetronomeWidget;
+		ToggleButton *m_pMetronomeBtn;
+
+		QTimer *m_pBPMTimer;
+
+		int m_nBPMIncrement;
+
+		ToggleButton *m_pShowMixerBtn;
+		ToggleButton *m_pShowInstrumentRackBtn;
+
+		LCDDisplay *m_pStatusLabel;
+		QTimer *m_pStatusTimer;
+		QTimer *m_pScrollTimer;
+		QString m_pScrollMessage; 
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/MetroBlinker.h
===================================================================
--- /branches/tabbedInterface/gui/src/MetroBlinker.h	(revision 1385)
+++ /branches/tabbedInterface/gui/src/MetroBlinker.h	(revision 1385)
@@ -0,0 +1,74 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef METRO_BLINKER_H
+#define METRO_BLINKER_H
+
+#include "config.h"
+
+#include <QDialog>
+#include "ui_MetroBlinker_UI.h"
+#include <hydrogen/Object.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include "EventListener.h"
+
+
+class MetroBlinker : public QDialog, public Ui_MetroBlinker_UI, public Object, public EventListener
+
+{
+	Q_OBJECT
+	public:
+		
+		MetroBlinker( QWidget* pParent );
+		~MetroBlinker();
+
+		virtual void metronomeEvent( int nValue );	
+		virtual void paintEvent( QPaintEvent*);
+
+	private slots:
+
+		void updateMetronomBackground();
+		//void updateBackground();
+
+
+	private:
+		QTimer *timer;
+		QTimer *timer2; //for moving metronom
+		QColor p_color;
+//		QPixmap *m_pBackground;
+		QPalette blinkerPalette;
+		int p_counter;
+		int p_fadealpha;
+		float p_bpm;
+		int p_bar;
+		int p_wechselblink;
+		QString TAG;
+		QString TAG2;
+		int tagbeat;
+
+
+};
+
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorInstrumentList.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorInstrumentList.h	(revision 1494)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorInstrumentList.h	(revision 1494)
@@ -0,0 +1,124 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef PATTERN_EDITOR_INSTRUMENT_LIST_H
+#define PATTERN_EDITOR_INSTRUMENT_LIST_H
+
+#include "config.h"
+
+#include <hydrogen/globals.h>
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+#include "../widgets/PixmapWidget.h"
+
+namespace H2Core
+{
+	class Pattern;
+}
+
+class PatternEditorPanel;
+class ToggleButton;
+
+class InstrumentLine : public PixmapWidget
+{
+	Q_OBJECT
+
+	public:
+		InstrumentLine(QWidget* pParent);
+
+		void setName(const QString& sName);
+		void setSelected(bool isSelected);
+		void setNumber(int nIndex);
+		void setMuted(bool isMuted);
+		void setSoloed( bool soloed );
+
+	private slots:
+		void functionClearNotes();
+
+		void functionFillAllNotes();
+		void functionFillEveryTwoNotes();
+		void functionFillEveryThreeNotes();
+		void functionFillEveryFourNotes();
+		void functionFillEverySixNotes();
+		void functionFillEveryEightNotes();
+		void functionFillNotes( int every );
+
+		void functionRandomizeVelocity();
+		void functionDeleteInstrument();
+		void muteClicked();
+		void soloClicked();
+
+
+	private:
+		QMenu *m_pFunctionPopup;
+		QMenu *m_pFunctionPopupSub;
+		QLabel *m_pNameLbl;
+		bool m_bIsSelected;
+		int m_nInstrumentNumber;	///< The related instrument number
+		ToggleButton *m_pMuteBtn;
+		ToggleButton *m_pSoloBtn;
+
+		virtual void mousePressEvent(QMouseEvent *ev);
+		H2Core::Pattern* getCurrentPattern();
+};
+
+
+class PatternEditorInstrumentList : public QWidget, public Object {
+	Q_OBJECT
+
+	public:
+		PatternEditorInstrumentList( QWidget *parent, PatternEditorPanel *pPatternEditorPanel );
+		~PatternEditorInstrumentList();
+
+		virtual void mousePressEvent(QMouseEvent *event);
+		virtual void mouseMoveEvent(QMouseEvent *event);
+
+
+		virtual void dragEnterEvent(QDragEnterEvent *event);
+		virtual void dropEvent(QDropEvent *event);
+
+
+	public slots:
+		void updateInstrumentLines();
+
+
+	protected:
+		PatternEditorPanel *m_pPatternEditorPanel;
+		H2Core::Pattern *m_pPattern;
+		uint m_nGridHeight;
+		uint m_nEditorWidth;
+		uint m_nEditorHeight;
+		InstrumentLine* m_pInstrumentLine[MAX_INSTRUMENTS];
+		QTimer *m_pUpdateTimer;
+
+		QPoint __drag_start_position;
+
+		InstrumentLine* createInstrumentLine();
+		void moveInstrumentLine(int,int);
+
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorRuler.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorRuler.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorRuler.cpp	(revision 1244)
@@ -0,0 +1,258 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QTimer>
+#include <QPainter>
+
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Pattern.h>
+using namespace H2Core;
+
+#include "PatternEditorRuler.h"
+#include "PatternEditorPanel.h"
+#include "../HydrogenApp.h"
+#include "../Skin.h"
+
+
+PatternEditorRuler::PatternEditorRuler( QWidget* parent )
+ : QWidget( parent )
+ , Object( "PatternEditorRuler" )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	//infoLog( "INIT" );
+
+	Preferences *pPref = Preferences::get_instance();
+
+	//QColor backgroundColor(230, 230, 230);
+	UIStyle *pStyle = pPref->getDefaultUIStyle();
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+
+
+	m_pPattern = NULL;
+	m_nGridWidth = Preferences::get_instance()->getPatternEditorGridWidth();
+
+	m_nRulerWidth = 20 + m_nGridWidth * ( MAX_NOTES * 4 );
+	m_nRulerHeight = 25;
+
+	resize( m_nRulerWidth, m_nRulerHeight );
+//	setFixedSize( size() );
+
+	bool ok = m_tickPosition.load( Skin::getImagePath() + "/patternEditor/tickPosition.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap " );
+	}
+
+	m_pBackground = new QPixmap( m_nRulerWidth, m_nRulerHeight );
+	m_pBackground->fill( backgroundColor );
+
+	m_pTimer = new QTimer(this);
+	connect(m_pTimer, SIGNAL(timeout()), this, SLOT(updateEditor()));
+
+	HydrogenApp::get_instance()->addEventListener( this );
+}
+
+
+
+PatternEditorRuler::~PatternEditorRuler() {
+	//infoLog( "DESTROY");
+}
+
+
+
+void PatternEditorRuler::updateStart(bool start) {
+	if (start) {
+		m_pTimer->start(50);	// update ruler at 20 fps
+	}
+	else {
+		m_pTimer->stop();
+	}
+}
+
+
+
+void PatternEditorRuler::showEvent ( QShowEvent *ev )
+{
+	UNUSED( ev );
+	updateEditor();
+	updateStart(true);
+}
+
+
+
+void PatternEditorRuler::hideEvent ( QHideEvent *ev )
+{
+	UNUSED( ev );
+	updateStart(false);
+}
+
+
+
+void PatternEditorRuler::updateEditor( bool bRedrawAll )
+{
+	static int oldNTicks = 0;
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() )  ) {
+		m_pPattern = pPatternList->get( nSelectedPatternNumber );
+	}
+	else {
+		m_pPattern = NULL;
+	}
+
+
+	bool bActive = false;	// is the pattern playing now?
+	PatternList *pList = pEngine->getCurrentPatternList();
+	for (uint i = 0; i < pList->get_size(); i++) {
+		if ( m_pPattern == pList->get(i) ) {
+			bActive = true;
+			break;
+		}
+	}
+
+	int state = pEngine->getState();
+	if ( ( state == STATE_PLAYING ) && (bActive) ) {
+		m_nTicks = pEngine->getTickPosition();
+	}
+	else {
+		m_nTicks = -1;	// hide the tickPosition
+	}
+
+
+	if (oldNTicks != m_nTicks) {
+		// redraw all
+		bRedrawAll = true;
+		//update( 0, 0, width(), height() );
+	}
+	oldNTicks = m_nTicks;
+
+	if (bRedrawAll) {
+		update( 0, 0, width(), height() );
+	}
+}
+
+
+
+void PatternEditorRuler::paintEvent( QPaintEvent *ev)
+{
+	if (!isVisible()) {
+		return;
+	}
+
+	QPainter painter(this);
+
+
+	painter.drawPixmap( ev->rect(), *m_pBackground, ev->rect() );
+
+	// gray background for unusable section of pattern
+	if (m_pPattern) {
+		int nXStart = 20 + m_pPattern->get_length() * m_nGridWidth;
+		if ( (m_nRulerWidth - nXStart) != 0 ) {
+			painter.fillRect( nXStart, 0, m_nRulerWidth - nXStart, m_nRulerHeight, QColor(170,170,170) );
+		}
+	}
+
+	// numbers
+	QColor textColor( 100, 100, 100 );
+	QColor lineColor( 170, 170, 170 );
+
+	Preferences *pref = Preferences::get_instance();
+	QString family = pref->getApplicationFontFamily();
+	int size = pref->getApplicationFontPointSize();
+	QFont font( family, size );
+	painter.setFont(font);
+	painter.drawLine( 0, 0, m_nRulerWidth, 0 );
+	painter.drawLine( 0, m_nRulerHeight - 1, m_nRulerWidth - 1, m_nRulerHeight - 1);
+
+	uint nQuarter = 48;
+
+	for ( int i = 0; i < 64 ; i++ ) {
+		int nText_x = 20 + nQuarter / 4 * i * m_nGridWidth;
+		if ( ( i % 4 ) == 0 ) {
+			painter.setPen( textColor );
+			painter.drawText( nText_x - 30, 0, 60, m_nRulerHeight, Qt::AlignCenter, QString("%1").arg(i / 4 + 1) );
+			//ERRORLOG(QString("nText_x: %1, true, : %2").arg(nText_x).arg(m_nRulerWidth));
+		}
+		else {
+			painter.setPen( QPen( QColor( lineColor ), 1, Qt::SolidLine ) );
+			painter.drawLine( nText_x, ( m_nRulerHeight - 5 ) / 2, nText_x, m_nRulerHeight - ( (m_nRulerHeight - 5 ) / 2 ));
+			//ERRORLOG("PAINT LINE");
+		}
+	}
+
+	// draw tickPosition
+	if (m_nTicks != -1) {
+		uint x = (uint)( 20 + m_nTicks * m_nGridWidth - 5 - 11 / 2.0 );
+		painter.drawPixmap( QRect( x, height() / 2, 11, 8 ), m_tickPosition, QRect( 0, 0, 11, 8 ) );
+
+	}
+}
+
+
+
+void PatternEditorRuler::zoomIn()
+{
+	if (m_nGridWidth >= 3){
+		m_nGridWidth *= 2;
+	}else
+	{
+		m_nGridWidth *= 1.5;
+	}
+	m_nRulerWidth = 20 + m_nGridWidth * ( MAX_NOTES * 4 );
+	resize(  QSize(m_nRulerWidth, m_nRulerHeight ));
+	delete m_pBackground;
+	m_pBackground = new QPixmap( m_nRulerWidth, m_nRulerHeight );
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	m_pBackground->fill( backgroundColor );
+	update();
+}
+
+
+void PatternEditorRuler::zoomOut()
+{
+	if ( m_nGridWidth > 1.5 ) {
+		if (m_nGridWidth > 3){
+			m_nGridWidth /= 2;
+		}else
+		{
+			m_nGridWidth /= 1.5;
+		}
+	m_nRulerWidth = 20 + m_nGridWidth * ( MAX_NOTES * 4 );
+	resize( QSize(m_nRulerWidth, m_nRulerHeight) );
+	delete m_pBackground;
+	m_pBackground = new QPixmap( m_nRulerWidth, m_nRulerHeight );
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	m_pBackground->fill( backgroundColor );
+	update();
+	}
+}
+
+
+void PatternEditorRuler::selectedPatternChangedEvent()
+{
+	updateEditor( true );
+}
Index: /branches/tabbedInterface/gui/src/PatternEditor/DrumPatternEditor.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/DrumPatternEditor.h	(revision 1555)
+++ /branches/tabbedInterface/gui/src/PatternEditor/DrumPatternEditor.h	(revision 1555)
@@ -0,0 +1,110 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef DRUM_PATTERN_EDITOR_H
+#define DRUM_PATTERN_EDITOR_H
+
+#include "config.h"
+#include "../EventListener.h"
+
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+
+namespace H2Core
+{
+	class Note;
+	class Pattern;
+}
+
+class PatternEditorInstrumentList;
+class PatternEditorPanel;
+
+///
+/// Drum pattern editor
+///
+class DrumPatternEditor : public QWidget, public EventListener, public Object
+{
+	Q_OBJECT
+
+	public:
+		DrumPatternEditor(QWidget* parent, PatternEditorPanel *panel);
+		~DrumPatternEditor();
+
+		void setResolution(uint res, bool bUseTriplets);
+		uint getResolution() {	return m_nResolution;	}
+		bool isUsingTriplets() {	return m_bUseTriplets;	}
+
+		void zoom_in();
+		void zoom_out();
+
+		// Implements EventListener interface
+		virtual void patternModifiedEvent();
+		virtual void patternChangedEvent();
+		virtual void selectedPatternChangedEvent();
+		virtual void selectedInstrumentChangedEvent();
+		//~ Implements EventListener interface
+
+		static QColor computeNoteColor( float );
+
+
+	public slots:
+		void updateEditor();
+
+	private:
+		float m_nGridWidth;
+		uint m_nGridHeight;
+		int m_nEditorHeight;
+		uint m_nResolution;
+		bool m_bUseTriplets;
+
+		//QPixmap *m_pBackground;
+		//QPixmap *m_pTemp;
+
+		// usati per la lunghezza della nota
+		bool m_bRightBtnPressed;
+		H2Core::Note *m_pDraggedNote;
+		//~
+
+		H2Core::Pattern *m_pPattern;
+
+		PatternEditorPanel *m_pPatternEditorPanel;
+
+		void __draw_note( H2Core::Note* note, QPainter& painter );
+		void __draw_pattern( QPainter& painter );
+		void __draw_grid( QPainter& painter );
+		void __create_background( QPainter& pointer );
+
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void keyPressEvent (QKeyEvent *ev);
+		virtual void showEvent ( QShowEvent *ev );
+		virtual void hideEvent ( QHideEvent *ev );
+		virtual void paintEvent(QPaintEvent *ev);
+
+		int getColumn(QMouseEvent *ev);
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/PatternEditor/NotePropertiesRuler.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/NotePropertiesRuler.h	(revision 593)
+++ /branches/tabbedInterface/gui/src/PatternEditor/NotePropertiesRuler.h	(revision 593)
@@ -0,0 +1,91 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef NOTE_PROPERTIES_RULER_H
+#define NOTE_PROPERTIES_RULER_H
+
+#include "../EventListener.h"
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+namespace H2Core
+{
+	class Pattern;
+	class NoteKey;
+}
+
+class PatternEditorPanel;
+
+class NotePropertiesRuler : public QWidget, public Object, public EventListener
+{
+	Q_OBJECT
+	public:
+		enum NotePropertiesMode {
+			VELOCITY,
+			PAN,
+			LEADLAG,
+			NOTEKEY
+		};
+
+		NotePropertiesRuler( QWidget *parent, PatternEditorPanel *pPatternEditorPanel, NotePropertiesMode mode );
+		~NotePropertiesRuler();
+
+		void zoomIn();
+		void zoomOut();
+
+		//public slots:
+		void updateEditor();
+
+	private:
+		static const int m_nKeys = 24;
+		static const int m_nBasePitch = 12;
+
+		NotePropertiesMode m_mode;
+
+		PatternEditorPanel *m_pPatternEditorPanel;
+		H2Core::Pattern *m_pPattern;
+		float m_nGridWidth;
+		uint m_nEditorWidth;
+		uint m_nEditorHeight;
+
+		QPixmap *m_pBackground;
+
+		void createVelocityBackground(QPixmap *pixmap);
+		void createPanBackground(QPixmap *pixmap);
+		void createLeadLagBackground(QPixmap *pixmap);
+		void createNoteKeyBackground(QPixmap *pixmap);
+		void paintEvent(QPaintEvent *ev);
+		void mousePressEvent(QMouseEvent *ev);
+		void mouseMoveEvent(QMouseEvent *ev);
+		void wheelEvent(QWheelEvent *ev);
+
+		// Implements EventListener interface
+		virtual void selectedPatternChangedEvent();
+		virtual void selectedInstrumentChangedEvent();
+		//~ Implements EventListener interface
+
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorRuler.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorRuler.h	(revision 723)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorRuler.h	(revision 723)
@@ -0,0 +1,80 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PATTERN_EDITOR_RULER_H
+#define PATTERN_EDITOR_RULER_H
+
+#include "../EventListener.h"
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+
+class PatternEditorPanel;
+
+namespace H2Core
+{
+	class Pattern;
+}
+
+class PatternEditorRuler : public QWidget, public Object, public EventListener
+{
+	Q_OBJECT
+
+	public:
+		PatternEditorRuler( QWidget* parent );
+		~PatternEditorRuler();
+
+		void paintEvent(QPaintEvent *ev);
+		void updateStart(bool start);
+
+		void showEvent( QShowEvent *ev );
+		void hideEvent( QHideEvent *ev );
+
+		void zoomIn();
+		void zoomOut();
+		float getGridWidth() const {
+		return m_nGridWidth;
+		};
+
+	public slots:
+		void updateEditor( bool bRedrawAll = false );
+
+	private:
+		uint m_nRulerWidth;
+		uint m_nRulerHeight;
+		float m_nGridWidth;
+
+		QPixmap *m_pBackground;
+		QPixmap m_tickPosition;
+
+		QTimer *m_pTimer;
+		int m_nTicks;
+		PatternEditorPanel *m_pPatternEditorPanel;
+		H2Core::Pattern *m_pPattern;
+
+		// Implements EventListener interface
+		virtual void selectedPatternChangedEvent();
+		//~ Implements EventListener interface
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorPanel.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorPanel.cpp	(revision 1439)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorPanel.cpp	(revision 1439)
@@ -0,0 +1,1121 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/event_queue.h>
+using namespace H2Core;
+
+
+#include "HydrogenApp.h"
+#include "PatternEditorPanel.h"
+#include "PatternEditorInstrumentList.h"
+#include "PatternEditorRuler.h"
+#include "NotePropertiesRuler.h"
+#include "DrumPatternEditor.h"
+#include "PianoRollEditor.h"
+
+#include "../MainForm.h"
+#include "../widgets/Button.h"
+#include "../widgets/Fader.h"
+#include "../widgets/PixmapWidget.h"
+#include "../widgets/LCDCombo.h"
+
+#include "../Skin.h"
+#include "../SongEditor/SongEditorPanel.h"
+
+#include <cmath>
+
+#include <QtGui>
+
+
+void PatternEditorPanel::updateSLnameLabel( )
+{
+	QFont font;
+	font.setBold( true );
+	pSLlabel->setFont( font );
+	pSLlabel->setText( Hydrogen::get_instance()->m_currentDrumkit  );
+} 
+
+
+
+PatternEditorPanel::PatternEditorPanel( QWidget *pParent )
+ : QWidget( pParent )
+ , Object( "PatternEditorPanel" )
+ , m_pPattern( NULL )
+ , m_bEnablePatternResize( true )
+{
+	setAcceptDrops(true);
+
+	Preferences *pPref = Preferences::get_instance();
+	
+
+// Editor TOP
+	PixmapWidget *editor_top = new PixmapWidget(0);
+	editor_top->setPixmap("/patternEditor/editor_top.png", true);
+	editor_top->setFixedHeight(24);
+
+	PixmapWidget *editor_top_2 = new PixmapWidget(0);
+	editor_top_2->setPixmap("/patternEditor/editor_top.png", true);
+	editor_top_2->setFixedHeight(24);
+
+	QHBoxLayout *editor_top_hbox = new QHBoxLayout(editor_top);
+	editor_top_hbox->setSpacing(0);
+	editor_top_hbox->setMargin(0);
+	editor_top_hbox->setAlignment(Qt::AlignLeft);
+
+	QHBoxLayout *editor_top_hbox_2 = new QHBoxLayout(editor_top_2);
+	editor_top_hbox_2->setSpacing(0);
+	editor_top_hbox_2->setMargin(0);
+	editor_top_hbox_2->setAlignment(Qt::AlignLeft);
+
+
+	//soundlibrary name
+	pSLlabel = new QLabel( NULL );
+	pSLlabel->setText( Hydrogen::get_instance()->m_currentDrumkit );
+	pSLlabel->setFixedSize( 170, 20 );
+	pSLlabel->move( 10, 3 );
+	pSLlabel->setToolTip( trUtf8("Loaded Soundlibrary") );
+	editor_top_hbox->addWidget( pSLlabel ); 
+
+//wolke some background images back_size_res
+	PixmapWidget *pSizeResol = new PixmapWidget( NULL );
+	pSizeResol->setFixedSize( 200, 20 );
+	pSizeResol->setPixmap( "/patternEditor/background_res-new.png" );
+	pSizeResol->move( 0, 3 );
+	editor_top_hbox_2->addWidget( pSizeResol );
+
+	// PATTERN size
+	__pattern_size_combo = new LCDCombo(pSizeResol, 4);
+	__pattern_size_combo->move( 34, 2 );
+	__pattern_size_combo->setToolTip( trUtf8("Select pattern size") );
+	for ( int i = 1; i <= 32; i++) {
+		__pattern_size_combo->addItem( QString( "%1" ).arg( i ) );
+	}
+	__pattern_size_combo->update();
+	connect(__pattern_size_combo, SIGNAL( valueChanged( QString ) ), this, SLOT( patternSizeChanged(QString) ) );
+	//editor_top_hbox->addWidget(__pattern_size_combo);
+
+
+	// GRID resolution
+	__resolution_combo = new LCDCombo( pSizeResol , 7);
+	__resolution_combo->setToolTip(trUtf8("Select grid resolution"));
+	__resolution_combo->addItem( "4" );
+	__resolution_combo->addItem( "8" );
+	__resolution_combo->addItem( "16" );
+	__resolution_combo->addItem( "32" );
+	__resolution_combo->addItem( "64" );
+	__resolution_combo->addSeparator();
+	__resolution_combo->addItem( "4T" );
+	__resolution_combo->addItem( "8T" );
+	__resolution_combo->addItem( "16T" );
+	__resolution_combo->addItem( "32T" );
+	__resolution_combo->addSeparator();
+	__resolution_combo->addItem( "off" );
+	__resolution_combo->update();
+	__resolution_combo->move( 121, 2 );
+	connect(__resolution_combo, SIGNAL(valueChanged(QString)), this, SLOT(gridResolutionChanged(QString)));
+	//editor_top_hbox->addWidget(__resolution_combo);
+
+
+	PixmapWidget *pRec = new PixmapWidget( NULL );
+	pRec->setFixedSize( 110, 20 );
+	pRec->setPixmap( "/patternEditor/background_rec-new.png" );
+	pRec->move( 0, 3 );
+	editor_top_hbox_2->addWidget( pRec );
+
+
+	// Hear notes btn
+	ToggleButton *hearNotesBtn = new ToggleButton(
+			pRec,
+			"/patternEditor/btn_hear_on.png",
+			"/patternEditor/btn_hear_off.png",
+			"/patternEditor/btn_hear_off.png",
+			QSize(15, 13)
+	);
+	hearNotesBtn->move( 34, 3 );
+	hearNotesBtn->setToolTip( trUtf8( "Hear new notes" ) );
+	connect( hearNotesBtn, SIGNAL(clicked(Button*)), this, SLOT( hearNotesBtnClick(Button*)));
+	hearNotesBtn->setPressed( pPref->getHearNewNotes() );
+
+
+	// quantize
+	ToggleButton* quantizeEventsBtn = new ToggleButton(
+			pRec,
+			"/patternEditor/btn_quant_on.png",
+			"/patternEditor/btn_quant_off.png",
+			"/patternEditor/btn_quant_off.png",
+			QSize(15, 13)
+	);
+	quantizeEventsBtn->move( 90, 3 );
+	quantizeEventsBtn->setPressed( pPref->getQuantizeEvents());
+	quantizeEventsBtn->setToolTip( trUtf8( "Quantize keyboard/midi events to grid" ) );
+	connect( quantizeEventsBtn, SIGNAL(clicked(Button*)), this, SLOT( quantizeEventsBtnClick(Button*)));
+
+	__recpredelete = new QComboBox( NULL );
+	__recpredelete->setFixedSize( 130, 20 );
+	__recpredelete->move( 2, 1 );
+	__recpredelete->addItem ( QString( "On play" ));
+	__recpredelete->addItem ( QString( "On rec: once fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/1 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/2 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/4 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/8 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/16 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/32 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/64 fp" ));
+	__recpredelete->addItem ( QString( "On rec: 1/64" ));
+	__recpredelete->addItem ( QString( "On rec: 1/32" ));
+	__recpredelete->addItem ( QString( "On rec: 1/16" ));
+	__recpredelete->addItem ( QString( "On rec: 1/8" ));
+	__recpredelete->addItem ( QString( "On rec: 1/4" ));
+	__recpredelete->addItem ( QString( "On rec: 1/2" ));
+	__recpredelete->addItem ( QString( "On rec: 1/1" ));
+	__recpredelete->addItem ( QString( "On rec: once" ));
+	__recpredelete->update();
+	__recpredelete->setToolTip( trUtf8( "destructive mode pre delete settings" ) );
+	editor_top_hbox_2->addWidget( __recpredelete );
+	connect( __recpredelete, SIGNAL( currentIndexChanged( int ) ), this, SLOT( recPreDeleteSelect( int) ) );
+
+	__recpostdelete = new QComboBox( NULL );
+	__recpostdelete->setFixedSize( 60, 20 );
+	__recpostdelete->move( 2, 1 );
+	__recpostdelete->addItem ( QString( "off" ));
+	__recpostdelete->addItem ( QString( "1/64" ));
+	__recpostdelete->addItem ( QString( "1/32" ));
+	__recpostdelete->addItem ( QString( "1/16" ));
+	__recpostdelete->addItem ( QString( "1/8" ));
+	__recpostdelete->addItem ( QString( "1/4" ));
+	__recpostdelete->addItem ( QString( "1/2" ));
+	__recpostdelete->addItem ( QString( "1/1" ));
+	__recpostdelete->update();
+	__recpostdelete->setToolTip( trUtf8( "destructive mode post delete settings" ) );
+	editor_top_hbox_2->addWidget( __recpostdelete );
+	connect( __recpostdelete, SIGNAL( currentIndexChanged( int ) ), this, SLOT( recPostDeleteSelect( int) ) );
+
+	QComboBox *selInstrument = new QComboBox( NULL );
+	selInstrument->setFixedSize( 100, 20 );
+	selInstrument->move( 2, 1 );
+	selInstrument->addItem ( QString( "drumset" ));
+	selInstrument->addItem ( QString( "instrument" ));
+	selInstrument->update();
+	selInstrument->setToolTip( trUtf8( "Midi keyboard or computer keys play whole drumset or single instruments" ) );
+	editor_top_hbox_2->addWidget( selInstrument );
+	connect( selInstrument, SIGNAL( currentIndexChanged( QString ) ), this, SLOT( playselectedinstrument(QString) ) );
+
+	__rightclickSelection = new QComboBox( NULL );
+	__rightclickSelection->setFixedSize( 100, 20 );
+	__rightclickSelection->move( 2, 1 );
+	__rightclickSelection->addItem ( QString( "note length" ));
+	__rightclickSelection->addItem ( QString( "note off" ));
+	__rightclickSelection->update();
+	__rightclickSelection->setToolTip( trUtf8( "Right click into pattern editor add note-off-note or edit note-length, velocity or pan" ) );
+	editor_top_hbox_2->addWidget( __rightclickSelection );
+	connect( __rightclickSelection, SIGNAL( currentIndexChanged( QString ) ), this, SLOT( rightclickSelect(QString) ) );
+
+//---------------------------experimental pianoroll--------------------------------------
+// show drum editor btn
+	__show_drum_btn = new ToggleButton(
+			NULL,
+			"/skin_btn_on.png",
+			"/skin_btn_off.png",
+			"/skin_btn_over.png",
+			QSize(50, 17),
+			true
+	);
+	__show_drum_btn->setText( trUtf8("Piano") );
+	__show_drum_btn->setPressed( false );
+	__show_drum_btn->setToolTip( trUtf8( "Show piano roll editor" ) );
+	connect(__show_drum_btn, SIGNAL(clicked(Button*)), this, SLOT( showDrumEditorBtnClick(Button*)));
+	editor_top_hbox_2->addWidget(__show_drum_btn);
+
+// hide the butten during develop on piano roll editor
+//__show_drum_btn->hide();
+
+//---------------------------------------------------------------------------------------
+
+	// zoom-in btn
+	Button *zoom_in_btn = new Button(
+			NULL,
+			"/songEditor/btn_new_on.png",
+			"/songEditor/btn_new_off.png",
+			"/songEditor/btn_new_over.png",
+			QSize(19, 13)
+	);
+// 	zoom_in_btn->move( 51, 3 );
+// 	zoom_in_btn->setText("+");
+	zoom_in_btn->setToolTip( trUtf8( "Zoom in" ) );
+	connect(zoom_in_btn, SIGNAL(clicked(Button*)), this, SLOT( zoomInBtnClicked(Button*) ) );
+	//editor_top_hbox_2->addWidget(zoom_in_btn);
+
+
+	// zoom-out btn
+	Button *zoom_out_btn = new Button(
+			NULL,
+			"/songEditor/btn_minus_on.png",
+			"/songEditor/btn_minus_off.png",
+			"/songEditor/btn_minus_over.png",
+			QSize(19, 13)
+	);
+// 	zoom_out_btn->move( 2, 3 );
+	//zoom_out_btn->setText("-");
+	zoom_out_btn->setToolTip( trUtf8( "Zoom out" ) );
+	connect( zoom_out_btn, SIGNAL(clicked(Button*)), this, SLOT( zoomOutBtnClicked(Button*) ) );
+	//editor_top_hbox_2->addWidget(zoom_out_btn);
+
+
+// End Editor TOP
+
+
+// RULER____________________________________
+
+	// Ruler ScrollView
+	m_pRulerScrollView = new QScrollArea( NULL );
+	m_pRulerScrollView->setFrameShape( QFrame::NoFrame );
+	m_pRulerScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pRulerScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pRulerScrollView->setFixedHeight( 25 );
+	// Ruler
+	m_pPatternEditorRuler = new PatternEditorRuler( m_pRulerScrollView->viewport() );
+
+	m_pRulerScrollView->setWidget( m_pPatternEditorRuler );
+
+//~ RULER
+
+
+// EDITOR _____________________________________
+	// Editor scrollview
+	m_pEditorScrollView = new QScrollArea( NULL );
+	m_pEditorScrollView->setFrameShape( QFrame::NoFrame );
+	m_pEditorScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pEditorScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+
+
+	// Editor
+	m_pDrumPatternEditor = new DrumPatternEditor( m_pEditorScrollView->viewport(), this );
+
+	m_pEditorScrollView->setWidget( m_pDrumPatternEditor );
+
+	connect( m_pEditorScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorScroll(int) ) );
+
+
+//PianoRollEditor
+	m_pPianoRollScrollView = new QScrollArea( NULL );
+	m_pPianoRollScrollView->setFrameShape( QFrame::NoFrame );
+	m_pPianoRollScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
+	m_pPianoRollScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pPianoRollEditor = new PianoRollEditor( m_pPianoRollScrollView->viewport(), this );
+	m_pPianoRollScrollView->setWidget( m_pPianoRollEditor );
+
+//	connect( m_pPianoRollScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorScroll(int) ) );
+
+
+	m_pPianoRollScrollView->hide();
+
+//~ EDITOR
+
+
+
+
+
+
+// INSTRUMENT LIST
+	// Instrument list scrollview
+	m_pInstrListScrollView = new QScrollArea( NULL );
+	m_pInstrListScrollView->setFrameShape( QFrame::NoFrame );
+	m_pInstrListScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pInstrListScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+
+	// Instrument list
+	m_pInstrumentList = new PatternEditorInstrumentList( m_pInstrListScrollView->viewport(), this );
+	m_pInstrListScrollView->setWidget( m_pInstrumentList );
+	m_pInstrListScrollView->setFixedWidth( m_pInstrumentList->width() );
+
+	connect( m_pInstrListScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorScroll(int) ) );
+//~ INSTRUMENT LIST
+
+
+
+
+// NOTE_VELOCITY EDITOR
+	m_pNoteVelocityScrollView = new QScrollArea( NULL );
+	m_pNoteVelocityScrollView->setFrameShape( QFrame::NoFrame );
+	m_pNoteVelocityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNoteVelocityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNoteVelocityEditor = new NotePropertiesRuler( m_pNoteVelocityScrollView->viewport(), this, NotePropertiesRuler::VELOCITY );
+	m_pNoteVelocityScrollView->setWidget( m_pNoteVelocityEditor );
+	m_pNoteVelocityScrollView->setFixedHeight( 100 );
+//~ NOTE_VELOCITY EDITOR
+
+
+// NOTE_PAN EDITOR
+	m_pNotePanScrollView = new QScrollArea( NULL );
+	m_pNotePanScrollView->setFrameShape( QFrame::NoFrame );
+	m_pNotePanScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNotePanScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNotePanEditor = new NotePropertiesRuler( m_pNotePanScrollView->viewport(), this, NotePropertiesRuler::PAN );
+	m_pNotePanScrollView->setWidget( m_pNotePanEditor );
+	m_pNotePanScrollView->setFixedHeight( 100 );
+//~ NOTE_PAN EDITOR
+
+
+// NOTE_LEADLAG EDITOR
+	m_pNoteLeadLagScrollView = new QScrollArea( NULL );
+	m_pNoteLeadLagScrollView->setFrameShape( QFrame::NoFrame );
+	m_pNoteLeadLagScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNoteLeadLagScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNoteLeadLagEditor = new NotePropertiesRuler( m_pNoteLeadLagScrollView->viewport(), this, NotePropertiesRuler::LEADLAG );
+	m_pNoteLeadLagScrollView->setWidget( m_pNoteLeadLagEditor );
+	m_pNoteLeadLagScrollView->setFixedHeight( 100 );
+//~ NOTE_LEADLAG EDITOR
+
+
+// NOTE_NOTEKEY EDITOR
+
+
+	m_pNoteNoteKeyScrollView = new QScrollArea( NULL );
+	m_pNoteNoteKeyScrollView->setFrameShape( QFrame::NoFrame );
+	m_pNoteNoteKeyScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNoteNoteKeyScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pNoteNoteKeyEditor = new NotePropertiesRuler( m_pNoteNoteKeyScrollView->viewport(), this, NotePropertiesRuler::NOTEKEY );
+	m_pNoteNoteKeyScrollView->setWidget( m_pNoteNoteKeyEditor );
+	m_pNoteNoteKeyScrollView->setFixedHeight( 210 );
+
+
+//~ NOTE_NOTEKEY EDITOR
+
+
+	// external horizontal scrollbar
+	m_pPatternEditorHScrollBar = new QScrollBar( Qt::Horizontal , NULL  );
+	connect( m_pPatternEditorHScrollBar, SIGNAL(valueChanged(int)), this, SLOT( syncToExternalHorizontalScrollbar(int) ) );
+
+	// external vertical scrollbar
+	m_pPatternEditorVScrollBar = new QScrollBar( Qt::Vertical, NULL );
+	connect( m_pPatternEditorVScrollBar, SIGNAL(valueChanged(int)), this, SLOT( syncToExternalHorizontalScrollbar(int) ) );
+
+	QHBoxLayout *pPatternEditorHScrollBarLayout = new QHBoxLayout();
+	pPatternEditorHScrollBarLayout->setSpacing( 0 );
+	pPatternEditorHScrollBarLayout->setMargin( 0 );
+	pPatternEditorHScrollBarLayout->addWidget( m_pPatternEditorHScrollBar );
+	pPatternEditorHScrollBarLayout->addWidget( zoom_in_btn );
+	pPatternEditorHScrollBarLayout->addWidget( zoom_out_btn );
+
+	QWidget *pPatternEditorHScrollBarContainer = new QWidget();
+	pPatternEditorHScrollBarContainer->setLayout( pPatternEditorHScrollBarLayout );
+
+
+	QPalette label_palette;
+	label_palette.setColor( QPalette::Foreground, QColor( 230, 230, 230 ) );
+
+	QFont boldFont;
+	boldFont.setBold( true );
+	m_pPatternNameLbl = new QLabel( NULL );
+	m_pPatternNameLbl->setFont( boldFont );
+	m_pPatternNameLbl->setText( "pattern name label" );
+	//m_pPatternNameLbl->setFixedWidth(200);
+	m_pPatternNameLbl->setPalette(label_palette);
+
+
+
+
+
+
+// NOTE_PROPERTIES BUTTONS
+	PixmapWidget *pPropertiesPanel = new PixmapWidget( NULL );
+	pPropertiesPanel->setColor( QColor( 58, 62, 72 ) );
+
+	pPropertiesPanel->setFixedSize( 181, 100 );
+
+	QVBoxLayout *pPropertiesVBox = new QVBoxLayout( pPropertiesPanel );
+	pPropertiesVBox->setSpacing( 0 );
+	pPropertiesVBox->setMargin( 0 );
+
+
+	__pPropertiesCombo = new LCDCombo( NULL, 20);
+	__pPropertiesCombo->setToolTip(trUtf8("Select note properties"));
+	__pPropertiesCombo->addItem( trUtf8("Velocity") );
+	__pPropertiesCombo->addItem( trUtf8("Pan") );
+	__pPropertiesCombo->addItem( trUtf8("Lead and Lag") );
+	__pPropertiesCombo->addItem( trUtf8("NoteKey") );
+	__pPropertiesCombo->update();
+	connect( __pPropertiesCombo, SIGNAL(valueChanged(QString)), this, SLOT(propertiesComboChanged(QString)));
+
+	pPropertiesVBox->addWidget( __pPropertiesCombo );
+
+//~ NOTE_PROPERTIES BUTTONS
+
+
+// LAYOUT
+	QWidget *pMainPanel = new QWidget();
+
+	QGridLayout *pGrid = new QGridLayout();
+	pGrid->setSpacing( 0 );
+	pGrid->setMargin( 0 );
+
+	pGrid->addWidget( editor_top, 0, 0);
+	pGrid->addWidget( editor_top_2, 0, 1, 1, 3);
+	pGrid->addWidget( m_pPatternNameLbl, 1, 0 );
+	pGrid->addWidget( m_pRulerScrollView, 1, 1 );
+
+	pGrid->addWidget( m_pInstrListScrollView, 2, 0 );
+
+	pGrid->addWidget( m_pEditorScrollView, 2, 1 );
+	pGrid->addWidget( m_pPianoRollScrollView, 2, 1 );
+
+	pGrid->addWidget( m_pPatternEditorVScrollBar, 2, 2 );
+	pGrid->addWidget( pPatternEditorHScrollBarContainer, 10, 1 );
+	pGrid->addWidget( m_pNoteVelocityScrollView, 4, 1 );
+	pGrid->addWidget( m_pNotePanScrollView, 4, 1 );
+	pGrid->addWidget( m_pNoteLeadLagScrollView, 4, 1 );
+	pGrid->addWidget( m_pNoteNoteKeyScrollView, 4, 1 );
+
+	pGrid->addWidget( pPropertiesPanel, 4, 0 );
+	pGrid->setRowStretch( 2, 100 );
+	pMainPanel->setLayout( pGrid );
+
+
+
+
+
+	// restore grid resolution
+	int nIndex;
+	if ( pPref->isPatternEditorUsingTriplets() == false ) {
+		switch ( pPref->getPatternEditorGridResolution() ) {
+			case 4:
+				__resolution_combo->set_text( "4" );
+				nIndex = 0;
+				break;
+
+			case 8:
+				__resolution_combo->set_text( "8" );
+				nIndex = 1;
+				break;
+
+			case 16:
+				__resolution_combo->set_text( "16" );
+				nIndex = 2;
+				break;
+
+			case 32:
+				__resolution_combo->set_text( "32" );
+				nIndex = 3;
+				break;
+
+			case 64:
+				__resolution_combo->set_text( "64" );
+				nIndex = 4;
+				break;
+
+			default:
+				ERRORLOG( QString("Wrong grid resolution: %1").arg( pPref->getPatternEditorGridResolution() ) );
+				__resolution_combo->set_text( "4" );
+				nIndex = 0;
+		}
+	}
+	else {
+		switch ( pPref->getPatternEditorGridResolution() ) {
+			case 8:
+				__resolution_combo->set_text( "4T" );
+				nIndex = 5;
+				break;
+
+			case 16:
+				__resolution_combo->set_text( "8T" );
+				nIndex = 6;
+				break;
+
+			case 32:
+				__resolution_combo->set_text( "16T" );
+				nIndex = 7;
+				break;
+
+			case 64:
+				__resolution_combo->set_text( "32T" );
+				nIndex = 8;
+				break;
+
+			default:
+				ERRORLOG( QString("Wrong grid resolution: %1").arg( pPref->getPatternEditorGridResolution() ) );
+				__resolution_combo->set_text( "4T" );
+				nIndex = 5;
+		}
+	}
+	gridResolutionChanged(__resolution_combo->getText());
+
+	//set pre delete
+	__recpredelete->setCurrentIndex(pPref->m_nRecPreDelete);
+	__recpostdelete->setCurrentIndex(pPref->m_nRecPostDelete);
+	displayorHidePrePostCB();
+
+	// LAYOUT
+	QVBoxLayout *pVBox = new QVBoxLayout();
+	pVBox->setSpacing( 0 );
+	pVBox->setMargin( 0 );
+	this->setLayout( pVBox );
+
+	pVBox->addWidget( pMainPanel );
+
+	HydrogenApp::get_instance()->addEventListener( this );
+
+	selectedPatternChangedEvent(); // force an update
+
+	__pPropertiesCombo->set_text( trUtf8("Velocity"));
+}
+
+
+
+
+PatternEditorPanel::~PatternEditorPanel()
+{
+}
+
+
+
+void PatternEditorPanel::syncToExternalHorizontalScrollbar(int)
+{
+	//INFOLOG( "[syncToExternalHorizontalScrollbar]" );
+
+	// drum Editor
+	m_pEditorScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+	m_pEditorScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
+
+	// piano roll Editor
+	m_pPianoRollScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+//	m_pPianoRollScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
+
+
+	// Ruler
+	m_pRulerScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+
+	// Instrument list
+	m_pInstrListScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
+
+	// Velocity ruler
+	m_pNoteVelocityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+
+	// pan ruler
+	m_pNotePanScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+
+	// leadlag ruler
+	m_pNoteLeadLagScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+
+	// notekey ruler
+	m_pNoteNoteKeyScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
+}
+
+
+void PatternEditorPanel::on_patternEditorScroll(int nValue)
+{
+	//INFOLOG( "[on_patternEditorScroll] " + QString::number(nValue)  );
+	m_pPatternEditorVScrollBar->setValue( nValue );	
+	resizeEvent(NULL);
+}
+
+
+
+
+void PatternEditorPanel::gridResolutionChanged( QString str )
+{
+	int nResolution;
+	bool bUseTriplets = false;
+
+	if ( str.contains( "off" ) ) {
+		nResolution=MAX_NOTES;
+	}
+	else if ( str.contains( "T" ) ) {
+		bUseTriplets = true;
+		QString temp = str;
+		temp.chop( 1 );
+		nResolution = temp.toInt() * 2;
+	}
+	else {
+		nResolution = str.toInt();
+	}
+
+	//INFOLOG( to_string( nResolution ) );
+	m_pDrumPatternEditor->setResolution( nResolution, bUseTriplets );
+	m_pPianoRollEditor->setResolution( nResolution, bUseTriplets );
+
+	Preferences::get_instance()->setPatternEditorGridResolution( nResolution );
+	Preferences::get_instance()->setPatternEditorUsingTriplets( bUseTriplets );
+}
+
+
+
+void PatternEditorPanel::selectedPatternChangedEvent()
+{
+	PatternList *pPatternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
+	int nSelectedPatternNumber = Hydrogen::get_instance()->getSelectedPatternNumber();
+
+	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() ) ) {
+		// update pattern name text
+		m_pPattern = pPatternList->get( nSelectedPatternNumber );
+		QString sCurrentPatternName = m_pPattern->get_name();
+		this->setWindowTitle( ( trUtf8( "Pattern editor - %1").arg( sCurrentPatternName ) ) );
+		//m_pNameLCD->setText( sCurrentPatternName );
+		m_pPatternNameLbl->setText( sCurrentPatternName );
+
+		// update pattern size combobox
+		int nPatternSize = m_pPattern->get_length();
+		int nEighth = MAX_NOTES / 8;
+		for ( int i = 1; i <= 32; i++ ) {
+			if ( nPatternSize == nEighth * i ) {
+				__pattern_size_combo->set_text( QString( "%1" ).arg( i ) );
+				break;
+			}
+		}
+	}
+	else {
+		m_pPattern = NULL;
+
+		this->setWindowTitle( ( trUtf8( "Pattern editor - %1").arg(QString("No pattern selected.")) ) );
+		//m_pNameLCD->setText( trUtf8( "No pattern selected" ) );
+		m_pPatternNameLbl->setText( trUtf8( "No pattern selected" ) );
+	}
+
+	resizeEvent( NULL ); // force an update of the scrollbars
+}
+
+
+
+void PatternEditorPanel::hearNotesBtnClick(Button *ref)
+{
+	Preferences *pref = ( Preferences::get_instance() );
+	pref->setHearNewNotes( ref->isPressed() );
+
+	if (ref->isPressed() ) {
+		( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Hear new notes = On" ), 2000 );
+	}
+	else {
+		( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Hear new notes = Off" ), 2000 );
+	}
+
+}
+
+
+
+
+void PatternEditorPanel::quantizeEventsBtnClick(Button *ref)
+{
+	Preferences *pref = ( Preferences::get_instance() );
+	pref->setQuantizeEvents( ref->isPressed() );
+
+	if (ref->isPressed() ) {
+		( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Quantize incoming keyboard/midi events = On" ), 2000 );
+	}
+	else {
+		( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Quantize incoming keyboard/midi events = Off" ), 2000 );
+	}
+}
+
+
+
+
+void PatternEditorPanel::stateChangedEvent(int state)
+{
+	if ( state == STATE_READY) {
+		m_bEnablePatternResize = true;
+	}
+	else {
+		m_bEnablePatternResize = false;
+	}
+}
+
+
+
+void PatternEditorPanel::resizeEvent( QResizeEvent *ev )
+{
+	UNUSED( ev );
+	QScrollArea *pScrollArea = m_pEditorScrollView;
+
+
+//	if ( m_pPianoRollScrollView->isVisible() ) {
+//		pScrollArea = m_pPianoRollScrollView;
+//	}
+//	else {
+		pScrollArea = m_pEditorScrollView;
+//	}
+
+	m_pPatternEditorHScrollBar->setMinimum( pScrollArea->horizontalScrollBar()->minimum() );
+	m_pPatternEditorHScrollBar->setMaximum( pScrollArea->horizontalScrollBar()->maximum() );
+	m_pPatternEditorHScrollBar->setSingleStep( pScrollArea->horizontalScrollBar()->singleStep() );
+	m_pPatternEditorHScrollBar->setPageStep( pScrollArea->horizontalScrollBar()->pageStep() );
+
+	m_pPatternEditorVScrollBar->setMinimum( pScrollArea->verticalScrollBar()->minimum() );
+	m_pPatternEditorVScrollBar->setMaximum( pScrollArea->verticalScrollBar()->maximum() );
+	m_pPatternEditorVScrollBar->setSingleStep( pScrollArea->verticalScrollBar()->singleStep() );
+	m_pPatternEditorVScrollBar->setPageStep( pScrollArea->verticalScrollBar()->pageStep() );
+}
+
+
+
+
+void PatternEditorPanel::showEvent ( QShowEvent *ev )
+{
+	UNUSED( ev );
+//	m_pPatternEditorVScrollBar->setValue( m_pPatternEditorVScrollBar->maximum() );
+}
+
+
+/// richiamato dall'uso dello scroll del mouse
+void PatternEditorPanel::contentsMoving(int dummy)
+{
+	UNUSED( dummy );
+	//INFOLOG( "contentsMoving" );
+	syncToExternalHorizontalScrollbar(0);
+}
+
+
+
+void PatternEditorPanel::selectedInstrumentChangedEvent()
+{
+  //m_pNoteVelocityEditor->updateEditor();
+  //m_pNotePanEditor->updateEditor();
+  //m_pNoteLeadLagEditor->updateEditor();
+
+	resizeEvent(NULL);	// force a scrollbar update
+}
+
+
+void PatternEditorPanel::showDrumEditorBtnClick(Button *ref)
+{
+	UNUSED( ref );
+	if ( !__show_drum_btn->isPressed() ){
+		__show_drum_btn->setText( trUtf8("Piano") );
+		__show_drum_btn->setToolTip( trUtf8( "Show piano roll editor" ) );
+		m_pPianoRollScrollView->hide();
+		m_pEditorScrollView->show();
+		m_pInstrListScrollView->show();
+	
+		m_pDrumPatternEditor->selectedInstrumentChangedEvent(); // force an update
+	
+		// force a re-sync of extern scrollbars
+		resizeEvent( NULL );
+		//
+		__rightclickSelection->clear();
+		__rightclickSelection->addItem ( QString( "note length" ));
+		__rightclickSelection->addItem ( QString( "note off" ));
+	}
+	else
+	{
+		__show_drum_btn->setText( trUtf8("Drum") );	
+		__show_drum_btn->setToolTip( trUtf8( "Show drum editor" ) );
+		m_pPianoRollScrollView->show();
+		m_pPianoRollScrollView->verticalScrollBar()->setValue( 250 );
+		m_pEditorScrollView->show();
+		m_pInstrListScrollView->show();
+	
+		m_pPianoRollEditor->updateEditor(); // force an update	
+		// force a re-sync of extern scrollbars
+		resizeEvent( NULL );
+
+		__rightclickSelection->clear();
+		__rightclickSelection->addItem ( QString( "note length" ));
+		__rightclickSelection->addItem ( QString( "note off" ));
+		__rightclickSelection->addItem ( QString( "edit velocity" ));
+		__rightclickSelection->addItem ( QString( "edit pan" ));
+		__rightclickSelection->addItem ( QString( "edit lead lag" ));
+	}
+}
+
+
+void PatternEditorPanel::zoomInBtnClicked(Button *ref)
+{
+	if(m_pPatternEditorRuler->getGridWidth() >=24){
+		return;
+	}
+	UNUSED( ref );
+	m_pPatternEditorRuler->zoomIn();
+	m_pDrumPatternEditor->zoom_in();
+	m_pNoteVelocityEditor->zoomIn();
+	m_pNoteLeadLagEditor->zoomIn();
+	m_pNoteNoteKeyEditor->zoomIn();
+	m_pNotePanEditor->zoomIn();
+	m_pPianoRollEditor->zoom_in();		
+
+	resizeEvent( NULL );
+}
+
+
+
+void PatternEditorPanel::zoomOutBtnClicked(Button *ref)
+{
+	UNUSED( ref );
+	m_pPatternEditorRuler->zoomOut();
+	m_pDrumPatternEditor->zoom_out();
+	m_pNoteVelocityEditor->zoomOut();
+	m_pNoteLeadLagEditor->zoomOut();
+	m_pNoteNoteKeyEditor->zoomOut();
+	m_pNotePanEditor->zoomOut();
+	m_pPianoRollEditor->zoom_out();	
+
+	resizeEvent( NULL );
+}
+
+
+
+void PatternEditorPanel::patternSizeChanged( QString str )
+{
+	INFOLOG( "pattern size changed" );
+
+	uint nEighth = MAX_NOTES / 8;
+	int nSelected = str.toInt();
+
+	if ( !m_pPattern ) {
+		return;
+	}
+
+	if ( m_pPattern->get_length() == nEighth * nSelected ) {
+		// non e' necessario aggiornare
+		return;
+	}
+
+
+	if ( !m_bEnablePatternResize ) {
+		__pattern_size_combo->set_text(QString::number(m_pPattern->get_length() / nEighth ),false);
+		QMessageBox::information( this, "Hydrogen", trUtf8( "Is not possible to change the pattern size when playing." ) );
+		return;
+	}
+
+
+	if ( nSelected > 0 && nSelected <= 32 ) {
+		m_pPattern->set_length( nEighth * nSelected );
+		//m_pPatternSizeLCD->setText( QString( "%1" ).arg( nSelected ) );
+	}
+	else {
+		ERRORLOG( QString("[patternSizeChanged] Unhandled case %1").arg( nSelected ) );
+	}
+
+	m_pPatternEditorRuler->updateEditor( true );	// redraw all
+	m_pNoteVelocityEditor->updateEditor();
+	m_pNotePanEditor->updateEditor();
+	m_pNoteLeadLagEditor->updateEditor();
+	m_pNoteNoteKeyEditor->updateEditor();
+	m_pPianoRollEditor->updateEditor();
+
+	resizeEvent( NULL );
+
+	EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
+}
+
+
+
+void PatternEditorPanel::moveUpBtnClicked(Button *)
+{
+	Hydrogen *engine = Hydrogen::get_instance();
+	int nSelectedInstrument = engine->getSelectedInstrumentNumber();
+
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+	Song *pSong = engine->getSong();
+	InstrumentList *pInstrumentList = pSong->get_instrument_list();
+
+	if ( ( nSelectedInstrument - 1 ) >= 0 ) {
+		Instrument *pTemp = pInstrumentList->get( nSelectedInstrument - 1 );
+		pInstrumentList->replace( pInstrumentList->get( nSelectedInstrument ), nSelectedInstrument - 1 );
+		pInstrumentList->replace( pTemp, nSelectedInstrument );
+
+		AudioEngine::get_instance()->unlock();
+		engine->setSelectedInstrumentNumber( nSelectedInstrument - 1 );
+
+		pSong->__is_modified = true;
+	}
+	else {
+		AudioEngine::get_instance()->unlock();
+	}
+}
+
+
+
+void PatternEditorPanel::moveDownBtnClicked(Button *)
+{
+	Hydrogen *engine = Hydrogen::get_instance();
+	int nSelectedInstrument = engine->getSelectedInstrumentNumber();
+
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+	Song *pSong = engine->getSong();
+	InstrumentList *pInstrumentList = pSong->get_instrument_list();
+
+	if ( ( nSelectedInstrument + 1 ) < (int)pInstrumentList->get_size() ) {
+		Instrument *pTemp = pInstrumentList->get( nSelectedInstrument + 1 );
+		pInstrumentList->replace( pInstrumentList->get( nSelectedInstrument ), nSelectedInstrument + 1 );
+		pInstrumentList->replace( pTemp, nSelectedInstrument );
+
+		AudioEngine::get_instance()->unlock();
+		engine->setSelectedInstrumentNumber( nSelectedInstrument + 1 );
+
+		pSong->__is_modified = true;
+	}
+	else {
+		AudioEngine::get_instance()->unlock();
+	}
+
+}
+
+
+
+
+void PatternEditorPanel::dragEnterEvent(QDragEnterEvent *event)
+{
+	m_pInstrumentList->dragEnterEvent( event );
+}
+
+
+
+void PatternEditorPanel::dropEvent(QDropEvent *event)
+{
+	m_pInstrumentList->dropEvent( event );
+}
+
+
+
+void PatternEditorPanel::propertiesComboChanged( QString text )
+{
+	if ( text == trUtf8( "Velocity" ) ) {
+		m_pNotePanScrollView->hide();
+		m_pNoteLeadLagScrollView->hide();
+		m_pNoteNoteKeyScrollView->hide();
+		m_pNoteVelocityScrollView->show();
+
+		m_pNoteVelocityEditor->updateEditor();
+	}
+	else if ( text == trUtf8( "Pan" ) ) {
+		m_pNoteVelocityScrollView->hide();
+		m_pNoteLeadLagScrollView->hide();
+		m_pNoteNoteKeyScrollView->hide();
+		m_pNotePanScrollView->show();
+
+		m_pNotePanEditor->updateEditor();
+	}
+	else if ( text == trUtf8( "Lead and Lag" ) ) {
+		m_pNoteVelocityScrollView->hide();
+		m_pNotePanScrollView->hide();
+		m_pNoteNoteKeyScrollView->hide();
+		m_pNoteLeadLagScrollView->show();
+ 
+		m_pNoteLeadLagEditor->updateEditor();
+	}
+	else if ( text == trUtf8( "NoteKey" ) ) {
+		m_pNoteVelocityScrollView->hide();
+		m_pNotePanScrollView->hide();
+		m_pNoteLeadLagScrollView->hide();
+		m_pNoteNoteKeyScrollView->show();
+ 
+		m_pNoteNoteKeyEditor->updateEditor();
+	}
+	else if ( text == trUtf8( "Cutoff" ) ) {
+	}
+	else if ( text == trUtf8( "Resonance" ) ) {
+	}
+	else {
+		ERRORLOG( "Unknown text: " + text );
+	}
+}
+
+
+
+void PatternEditorPanel::playselectedinstrument( QString text )
+{
+	if ( text == "drumset" ){
+		Preferences::get_instance()->__playselectedinstrument = false;
+	}else
+	{
+		Preferences::get_instance()->__playselectedinstrument = true;
+	}
+}
+
+
+void PatternEditorPanel::rightclickSelect( QString text )
+{
+//	__rightclickedpattereditor
+//	0 = note length
+//	1 = note off"
+//	2 = edit velocity
+//	3 = edit pan
+//	4 = edit lead lag
+
+	if ( text == "note length" ){
+		Preferences::get_instance()->__rightclickedpattereditor = 0;
+	}
+	else if ( text == "note off" ) {
+		Preferences::get_instance()->__rightclickedpattereditor = 1;
+	}
+	else if ( text == "edit velocity" ) {
+		Preferences::get_instance()->__rightclickedpattereditor = 2;
+//		propertiesComboChanged( "Velocity" );
+		__pPropertiesCombo->set_text("Velocity");
+	}
+	else if ( text == "edit pan" ) {
+		Preferences::get_instance()->__rightclickedpattereditor = 3;
+//		propertiesComboChanged( "Pan" );
+		__pPropertiesCombo->set_text("Pan");
+	}
+	else if ( text == "edit lead lag" ) {
+		Preferences::get_instance()->__rightclickedpattereditor = 4;
+//		propertiesComboChanged( "Lead and Lag" );
+		__pPropertiesCombo->set_text( "Lead and Lag" );
+	}
+
+}
+
+void PatternEditorPanel::recPreDeleteSelect( int index )
+{
+	Preferences::get_instance()->m_nRecPreDelete = index;
+	if( index>=9 && index <=15 ){
+		__recpostdelete->show();
+	}else{
+		__recpostdelete->hide();
+	}
+}
+
+
+void PatternEditorPanel::recPostDeleteSelect( int index )
+{
+	Preferences::get_instance()->m_nRecPostDelete = index;
+}
+
+
+void PatternEditorPanel::displayorHidePrePostCB()
+{
+	int index = __recpredelete->currentIndex();
+	if( Preferences::get_instance()->getDestructiveRecord() ){
+		__recpostdelete->show();
+		if( index>=8 && index <=14 ){
+			__recpostdelete->show();
+		}else{
+			__recpostdelete->hide();
+		}
+		__recpredelete->show();
+	}else{
+		__recpostdelete->hide();
+		__recpredelete->hide();
+	}
+}
+
+void PatternEditorPanel::updatePianorollEditor()
+{
+	m_pDrumPatternEditor->updateEditor(); // force an update
+}
Index: /branches/tabbedInterface/gui/src/PatternEditor/PianoRollEditor.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PianoRollEditor.cpp	(revision 1497)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PianoRollEditor.cpp	(revision 1497)
@@ -0,0 +1,915 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "PianoRollEditor.h"
+#include "PatternEditorPanel.h"
+#include "NotePropertiesRuler.h"
+#include <cassert>
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/note.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/audio_engine.h>
+using namespace H2Core;
+
+#include "../HydrogenApp.h"
+
+PianoRollEditor::PianoRollEditor( QWidget *pParent, PatternEditorPanel *panel )
+ : QWidget( pParent )
+ , Object( "PianoRollEditor" )
+ , m_nResolution( 8 )
+ , m_bRightBtnPressed( false )
+ , m_bUseTriplets( false )
+ , m_pPattern( NULL )
+ , m_pPatternEditorPanel( panel )
+ , m_pDraggedNote( NULL )
+{
+	INFOLOG( "INIT" );
+
+	m_nRowHeight = 10;
+	m_nOctaves = 7;
+
+	setAttribute(Qt::WA_NoBackground);
+	setFocusPolicy(Qt::ClickFocus);
+	m_nGridWidth = Preferences::get_instance()->getPatternEditorGridWidth();
+
+	m_nEditorWidth = 20 + m_nGridWidth *  (MAX_NOTES * 4);
+	m_nEditorHeight = m_nOctaves * 12 * m_nRowHeight;
+
+	m_pBackground = new QPixmap( m_nEditorWidth, m_nEditorHeight );
+	m_pTemp = new QPixmap( m_nEditorWidth, m_nEditorHeight );
+
+	resize( m_nEditorWidth, m_nEditorHeight );
+	
+	createBackground();
+
+	HydrogenApp::get_instance()->addEventListener( this );
+}
+
+
+
+PianoRollEditor::~PianoRollEditor()
+{
+	INFOLOG( "DESTROY" );
+}
+
+
+void PianoRollEditor::setResolution(uint res, bool bUseTriplets)
+{
+	this->m_nResolution = res;
+	this->m_bUseTriplets = bUseTriplets;
+	updateEditor();
+}
+
+
+void PianoRollEditor::updateEditor()
+{
+//	uint nEditorWidth;
+	if ( m_pPattern ) {
+		m_nEditorWidth = 20 + m_nGridWidth * m_pPattern->get_length();
+	}
+	else {
+		m_nEditorWidth = 20 + m_nGridWidth * MAX_NOTES;
+	}
+	resize( m_nEditorWidth, height() );
+
+	// redraw all
+	update( 0, 0, width(), height() );
+
+	createBackground();
+	drawPattern();
+//	ERRORLOG(QString("update editor %1").arg(m_nEditorWidth));
+}
+
+
+
+//eventlistener
+void PianoRollEditor::patternModifiedEvent() 
+{
+	updateEditor();
+}
+
+
+
+void PianoRollEditor::selectedInstrumentChangedEvent()
+{
+	updateEditor();
+}
+
+
+void PianoRollEditor::selectedPatternChangedEvent()
+{
+	//INFOLOG( "updating m_pPattern pointer" );
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() ) ) {
+		m_pPattern = pPatternList->get( nSelectedPatternNumber );
+	}
+	else {
+		m_pPattern = NULL;
+	}
+	updateEditor();
+}
+
+
+
+void PianoRollEditor::paintEvent(QPaintEvent *ev)
+{
+	QPainter painter( this );
+	painter.drawPixmap( ev->rect(), *m_pTemp, ev->rect() );
+}
+
+
+
+void PianoRollEditor::createBackground()
+{
+	//INFOLOG( "(re)creating the background" );
+
+	QColor backgroundColor( 250, 250, 250 );
+	m_pBackground->fill( backgroundColor );
+
+
+	QColor octaveColor( 230, 230, 230 );
+	QColor octaveAlternateColor( 200, 200, 200 );
+	QColor baseOctaveColor( 245, 245, 245 );
+	QColor baseNoteColor( 255, 255, 255 );
+
+	QColor fbk( 160, 160, 160 );
+
+	unsigned start_x = 0;
+	unsigned end_x = width();
+
+	QPainter p( m_pBackground );
+
+	for ( uint octave = 0; octave < m_nOctaves; ++octave ) {
+		unsigned start_y = octave * 12 * m_nRowHeight;
+
+		if ( octave % 2 ) {
+
+		
+			if ( octave == 3 ){
+		
+//				p.fillRect( start_x, start_y, end_x - start_x, 12 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y, end_x - start_x, start_y + 1 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y + 1 * m_nRowHeight, end_x - start_x, start_y + 2 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 2 * m_nRowHeight, end_x - start_x, start_y + 3 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y + 3 * m_nRowHeight, end_x - start_x, start_y + 4 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 4 * m_nRowHeight, end_x - start_x, start_y + 5 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y + 5 * m_nRowHeight, end_x - start_x, start_y + 6 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 6 * m_nRowHeight, end_x - start_x, start_y + 7 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y + 7 * m_nRowHeight, end_x - start_x, start_y + 8 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y + 8 * m_nRowHeight, end_x - start_x, start_y + 9 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 9 * m_nRowHeight, end_x - start_x, start_y + 10 * m_nRowHeight, baseOctaveColor );
+				p.fillRect( start_x, start_y + 10 * m_nRowHeight, end_x - start_x, start_y + 11 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 11 * m_nRowHeight, end_x - start_x, start_y + 12 * m_nRowHeight, baseNoteColor );
+			}
+			else
+			{
+			//	p.fillRect( start_x, start_y, end_x - start_x, 12 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y, end_x - start_x, start_y + 1 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y + 1 * m_nRowHeight, end_x - start_x, start_y + 2 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 2 * m_nRowHeight, end_x - start_x, start_y + 3 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y + 3 * m_nRowHeight, end_x - start_x, start_y + 4 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 4 * m_nRowHeight, end_x - start_x, start_y + 5 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y + 5 * m_nRowHeight, end_x - start_x, start_y + 6 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 6 * m_nRowHeight, end_x - start_x, start_y + 7 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y + 7 * m_nRowHeight, end_x - start_x, start_y + 8 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y + 8 * m_nRowHeight, end_x - start_x, start_y + 9 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 9 * m_nRowHeight, end_x - start_x, start_y + 10 * m_nRowHeight, octaveColor );
+				p.fillRect( start_x, start_y + 10 * m_nRowHeight, end_x - start_x, start_y + 11 * m_nRowHeight, fbk );
+				p.fillRect( start_x, start_y + 11 * m_nRowHeight, end_x - start_x, start_y + 12 * m_nRowHeight, octaveColor );
+
+			}
+		}
+		else {
+//			p.fillRect( start_x, start_y, end_x - start_x, 12 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y, end_x - start_x, start_y + 1 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y + 1 * m_nRowHeight, end_x - start_x, start_y + 2 * m_nRowHeight, fbk );
+			p.fillRect( start_x, start_y + 2 * m_nRowHeight, end_x - start_x, start_y + 3 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y + 3 * m_nRowHeight, end_x - start_x, start_y + 4 * m_nRowHeight, fbk );
+			p.fillRect( start_x, start_y + 4 * m_nRowHeight, end_x - start_x, start_y + 5 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y + 5 * m_nRowHeight, end_x - start_x, start_y + 6 * m_nRowHeight, fbk );
+			p.fillRect( start_x, start_y + 6 * m_nRowHeight, end_x - start_x, start_y + 7 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y + 7 * m_nRowHeight, end_x - start_x, start_y + 8 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y + 8 * m_nRowHeight, end_x - start_x, start_y + 9 * m_nRowHeight, fbk );
+			p.fillRect( start_x, start_y + 9 * m_nRowHeight, end_x - start_x, start_y + 10 * m_nRowHeight, octaveAlternateColor );
+			p.fillRect( start_x, start_y + 10 * m_nRowHeight, end_x - start_x, start_y + 11 * m_nRowHeight, fbk );
+			p.fillRect( start_x, start_y + 11 * m_nRowHeight, end_x - start_x, start_y + 12 * m_nRowHeight, octaveAlternateColor );
+			
+		}		
+	}
+
+
+	// horiz lines
+	for ( uint row = 0; row < ( 12 * m_nOctaves ); ++row ) {
+		unsigned y = row * m_nRowHeight;
+		p.drawLine( start_x, y,end_x , y );
+	}
+
+	//draw text
+	QFont font;
+	font.setPointSize ( 9 );
+//	font.setWeight( 63 );
+	p.setFont( font );
+	p.setPen( QColor(10, 10, 10 ) );
+
+	int offset = 0;
+	int insertx = 3;
+	for ( int oct = 0; oct < (int)m_nOctaves; oct++ ){
+		if( oct > 3 ){
+			p.drawText( insertx, m_nRowHeight  + offset, "B" );
+			p.drawText( insertx, 10 + m_nRowHeight  + offset, "A#" );
+			p.drawText( insertx, 20 + m_nRowHeight  + offset, "A" );
+			p.drawText( insertx, 30 + m_nRowHeight  + offset, "G#" );
+			p.drawText( insertx, 40 + m_nRowHeight  + offset, "G" );
+			p.drawText( insertx, 50 + m_nRowHeight  + offset, "F#" );
+			p.drawText( insertx, 60 + m_nRowHeight  + offset, "F" );
+			p.drawText( insertx, 70 + m_nRowHeight  + offset, "E" );
+			p.drawText( insertx, 80 + m_nRowHeight  + offset, "D#" );
+			p.drawText( insertx, 90 + m_nRowHeight  + offset, "D" );
+			p.drawText( insertx, 100 + m_nRowHeight  + offset, "C#" );
+			p.drawText( insertx, 110 + m_nRowHeight  + offset, "C" );
+			offset += 12 * m_nRowHeight;	
+		}else
+		{
+			p.drawText( insertx, m_nRowHeight  + offset, "b" );
+			p.drawText( insertx, 10 + m_nRowHeight  + offset, "a#" );
+			p.drawText( insertx, 20 + m_nRowHeight  + offset, "a" );
+			p.drawText( insertx, 30 + m_nRowHeight  + offset, "g#" );
+			p.drawText( insertx, 40 + m_nRowHeight  + offset, "g" );
+			p.drawText( insertx, 50 + m_nRowHeight  + offset, "f#" );
+			p.drawText( insertx, 60 + m_nRowHeight  + offset, "f" );
+			p.drawText( insertx, 70 + m_nRowHeight  + offset, "e" );
+			p.drawText( insertx, 80 + m_nRowHeight  + offset, "d#" );
+			p.drawText( insertx, 90 + m_nRowHeight  + offset, "d" );
+			p.drawText( insertx, 100 + m_nRowHeight  + offset, "c#" );
+			p.drawText( insertx, 110 + m_nRowHeight  + offset, "c" );
+			offset += 12 * m_nRowHeight;
+		}
+	}		
+		
+	draw_grid( p );
+}
+
+
+
+
+void PianoRollEditor::draw_grid( QPainter& p )
+{
+	static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	static const QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
+	static const QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
+	static const QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
+	static const QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
+	static const QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
+
+	// vertical lines
+
+	int nBase;
+	if (m_bUseTriplets) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+
+	int n4th = 4 * MAX_NOTES / (nBase * 4);
+	int n8th = 4 * MAX_NOTES / (nBase * 8);
+	int n16th = 4 * MAX_NOTES / (nBase * 16);
+	int n32th = 4 * MAX_NOTES / (nBase * 32);
+	int n64th = 4 * MAX_NOTES / (nBase * 64);
+
+	int nNotes = MAX_NOTES;
+	if ( m_pPattern ) {
+		nNotes = m_pPattern->get_length();
+	}
+	if (!m_bUseTriplets) {
+		for ( int i = 0; i < nNotes + 1; i++ ) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % n4th) == 0 ) {
+				if (m_nResolution >= 4) {
+					p.setPen( QPen( res_1, 1, Qt::DashLine) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n8th) == 0 ) {
+				if (m_nResolution >= 8) {
+					p.setPen( QPen( res_2, 0, Qt::DashLine ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n16th) == 0 ) {
+				if (m_nResolution >= 16) {
+					p.setPen( QPen( res_3, 0, Qt::DashLine ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n32th) == 0 ) {
+				if (m_nResolution >= 32) {
+					p.setPen( QPen( res_4, 0, Qt::DashLine ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n64th) == 0 ) {
+				if (m_nResolution >= 64) {
+					p.setPen( QPen( res_5, 0, Qt::DashLine  ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+		}
+	}
+	else {	// Triplets
+		uint nCounter = 0;
+		int nSize = 4 * MAX_NOTES / (nBase * m_nResolution);
+
+		for ( int i = 0; i < nNotes + 1; i++ ) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % nSize) == 0) {
+				if ((nCounter % 3) == 0) {
+					p.setPen( QPen( res_1, 0, Qt::DashLine ) );
+				}
+				else {
+					p.setPen( QPen( res_3, 0, Qt::DashLine ) );
+				}
+				p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				nCounter++;
+			}
+		}
+	}
+}
+
+
+void PianoRollEditor::drawPattern()
+{
+	if ( isVisible() == false ) {
+		return;
+	}
+
+
+	//INFOLOG( "draw pattern" );
+
+	QPainter p( m_pTemp );
+	// copy the background image
+	p.drawPixmap( rect(), *m_pBackground, rect() );
+
+
+	// for each note...
+	std::multimap <int, Note*>::iterator pos;
+	for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); pos++ ) {
+		//cout << "note" << endl;
+		//cout << "note n: " << pos->first << endl;
+		Note *note = pos->second;
+		assert( note );
+		drawNote( note, &p );
+	}
+
+}
+
+
+void PianoRollEditor::drawNote( Note *pNote, QPainter *pPainter )
+{
+	static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	static const QColor noteColor( pStyle->m_patternEditor_noteColor.getRed(), pStyle->m_patternEditor_noteColor.getGreen(), pStyle->m_patternEditor_noteColor.getBlue() );
+	static const QColor noteoffColor( pStyle->m_patternEditor_noteoffColor.getRed(), pStyle->m_patternEditor_noteoffColor.getGreen(), pStyle->m_patternEditor_noteoffColor.getBlue() );
+
+	int nInstrument = -1;
+	InstrumentList * pInstrList = Hydrogen::get_instance()->getSong()->get_instrument_list();
+	for ( uint nInstr = 0; nInstr < pInstrList->get_size(); ++nInstr ) {
+		Instrument *pInstr = pInstrList->get( nInstr );
+		if ( pInstr == pNote->get_instrument() ) {
+ 			nInstrument = nInstr;
+			break;
+		}
+	}
+	if ( nInstrument == -1 ) {
+		//ERRORLOG( "Instrument not found..skipping note" );
+		return;
+	}
+
+	if ( nInstrument != Hydrogen::get_instance()->getSelectedInstrumentNumber() ) {
+		return;
+	}
+
+	uint start_x = 20 + pNote->get_position() * m_nGridWidth;
+	uint start_y = height() - m_nRowHeight - ( m_nRowHeight * pNote->m_noteKey.m_key + ( 12 * (pNote->m_noteKey.m_nOctave +3) ) * m_nRowHeight ) + 1;
+	uint w = 8;
+	uint h = m_nRowHeight - 2;
+
+	int red = (int) (pNote->get_velocity() * 255);
+	int green;
+	int blue;
+	blue = (255 - (int) red)* .33;
+	green =  (255 - (int) red);
+
+	if ( pNote->get_length() == -1 && pNote->get_noteoff() == false ) {
+		pPainter->setBrush(QColor( red,green,blue ));
+		pPainter->drawEllipse( start_x -4 , start_y, w, h );
+	}
+	else if ( pNote->get_length() == 1 && pNote->get_noteoff() == true ){
+		pPainter->setBrush(QColor( noteoffColor ));
+		pPainter->drawEllipse( start_x -4 , start_y, w, h );
+	}
+	else {
+		float fNotePitch = pNote->m_noteKey.m_nOctave * 12 + pNote->m_noteKey.m_key;
+		float fStep = pow( 1.0594630943593, ( double )fNotePitch );
+
+		int nend = m_nGridWidth * pNote->get_length() / fStep;
+		nend = nend - 1;	// lascio un piccolo spazio tra una nota ed un altra
+
+		pPainter->setBrush(QColor( red,green,blue ));
+		pPainter->fillRect( start_x, start_y, nend, h, QColor( red,green,blue ) );
+		pPainter->drawRect( start_x, start_y, nend, h );
+	}
+}
+
+
+int PianoRollEditor::getColumn(QMouseEvent *ev)
+{
+	int nBase;
+	if (m_bUseTriplets) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+	int nWidth = (m_nGridWidth * 4 * MAX_NOTES) / (nBase * m_nResolution);
+
+	int x = ev->x();
+	int nColumn;
+	nColumn = x - 20 + (nWidth / 2);
+	nColumn = nColumn / nWidth;
+	nColumn = (nColumn * 4 * MAX_NOTES) / (nBase * m_nResolution);
+	return nColumn;
+}
+
+
+void PianoRollEditor::mousePressEvent(QMouseEvent *ev)
+{
+	//ERRORLOG("Mouse press event");
+	if ( m_pPattern == NULL ) {
+		return;
+	}
+
+	Song *pSong = Hydrogen::get_instance()->getSong();
+
+	int row = ((int) ev->y()) / ((int) m_nEditorHeight);
+	if (row >= (int) m_nOctaves * 12 ) {
+		return;
+	}
+
+	int nColumn = getColumn( ev );
+
+	if ( nColumn >= (int)m_pPattern->get_length() ) {
+		update( 0, 0, width(), height() );
+		return;
+	}
+	
+	int pressedline = ((int) ev->y()) / ((int) m_nRowHeight);
+
+	Instrument *pSelectedInstrument = NULL;
+	int nSelectedInstrumentnumber = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+	pSelectedInstrument = pSong->get_instrument_list()->get( nSelectedInstrumentnumber );
+	assert(pSelectedInstrument);
+
+	//ERRORLOG(QString("pressedline: %1, column %2, event ev: %3, editorhight %4").arg(pressedline).arg(nColumn).arg(ev->y()).arg(m_nEditorHeight));
+
+	int pressedoctave = 3 - (pressedline / 12 );
+	int pressednotekey = 0;
+	if ( pressedline < 12 ){
+		pressednotekey = 11 - pressedline;
+	}
+	else
+	{
+		pressednotekey = 11 - pressedline % 12;
+	}
+
+	
+	//ERRORLOG(QString("pressedline: %1, octave %2, notekey: %3").arg(pressedline).arg(pressedoctave).arg(pressednotekey));
+
+	if (ev->button() == Qt::LeftButton ) {
+		m_bRightBtnPressed = false;
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+		bool bNoteAlreadyExist = false;
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.lower_bound( nColumn ); pos != m_pPattern->note_map.upper_bound( nColumn ); ++pos ) {
+			Note *pNote = pos->second;
+			assert( pNote );
+			if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
+				// the note exists...remove it!
+				bNoteAlreadyExist = true;
+				delete pNote;
+				m_pPattern->note_map.erase( pos );
+				break;
+			}
+		}
+
+		if ( bNoteAlreadyExist == false ) {
+			// create the new note
+			const unsigned nPosition = nColumn;
+			const float fVelocity = 0.8f;
+			const float fPan_L = 0.5f;
+			const float fPan_R = 0.5f;
+			const int nLength = -1;
+			const float fPitch = 0.0f;
+			Note *pNote = new Note( pSelectedInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch );
+			pNote->set_noteoff( false );
+
+			if ( pressednotekey == 0 )//note c
+				pNote->m_noteKey.m_key = H2Core::NoteKey::C;
+			if ( pressednotekey == 1 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::Cs;
+			if ( pressednotekey == 2 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::D;
+			if ( pressednotekey == 3 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::Ef;
+			if ( pressednotekey == 4 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::E;
+			if ( pressednotekey == 5 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::F;
+			if ( pressednotekey == 6 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::Fs;
+			if ( pressednotekey == 7 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::G;
+			if ( pressednotekey == 8 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::Af;
+			if ( pressednotekey == 9 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::A;
+			if ( pressednotekey == 10 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::Bf;
+			if ( pressednotekey == 11 )
+				pNote->m_noteKey.m_key = H2Core::NoteKey::B;
+			
+			pNote->m_noteKey.m_nOctave = pressedoctave;
+			m_pPattern->note_map.insert( std::make_pair( nPosition, pNote ) );
+
+			// hear note
+			Preferences *pref = Preferences::get_instance();
+			if ( pref->getHearNewNotes() ) {
+				Note *pNote2 = new Note( pSelectedInstrument, 0, fVelocity, fPan_L, fPan_R, nLength, fPitch);
+				if ( pressednotekey == 0 )//note c
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::C;
+				if ( pressednotekey == 1 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::Cs;
+				if ( pressednotekey == 2 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::D;
+				if ( pressednotekey == 3 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::Ef;
+				if ( pressednotekey == 4 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::E;
+				if ( pressednotekey == 5 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::F;
+				if ( pressednotekey == 6 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::Fs;
+				if ( pressednotekey == 7 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::G;
+				if ( pressednotekey == 8 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::Af;
+				if ( pressednotekey == 9 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::A;
+				if ( pressednotekey == 10 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::Bf;
+				if ( pressednotekey == 11 )
+					pNote2->m_noteKey.m_key = H2Core::NoteKey::B;
+				
+				pNote2->m_noteKey.m_nOctave = pressedoctave;
+				AudioEngine::get_instance()->get_sampler()->note_on(pNote2);
+			}
+		}
+		pSong->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+	}
+
+	else if (ev->button() == Qt::RightButton ) {
+		m_bRightBtnPressed = true;
+		m_pDraggedNote = NULL;
+		m_pOldPoint = ev->y();
+
+		unsigned nRealColumn = 0;
+		if( ev->x() > 20 ) {
+			nRealColumn = (ev->x() - 20) / static_cast<float>(m_nGridWidth);
+		}
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.lower_bound( nColumn ); pos != m_pPattern->note_map.upper_bound( nColumn ); ++pos ) {
+			Note *pNote = pos->second;
+			assert( pNote );
+
+			if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
+				m_pDraggedNote = pNote;
+				break;
+			}
+		}
+		if ( !m_pDraggedNote ) {
+			for ( pos = m_pPattern->note_map.lower_bound( nRealColumn ); pos != m_pPattern->note_map.upper_bound( nRealColumn ); ++pos ) {
+				Note *pNote = pos->second;
+				assert( pNote );
+
+				if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
+					m_pDraggedNote = pNote;
+					break;
+				}
+			}	
+///
+		//	__rightclickedpattereditor
+		//	0 = note length
+		//	1 = note off"
+		//	2 = edit velocity
+		//	3 = edit pan
+		//	4 = edit lead lag
+
+			if ( Preferences::get_instance()->__rightclickedpattereditor == 1){
+				// create the new note
+				const unsigned nPosition = nColumn;
+				const float fVelocity = 0.0f;
+				const float fPan_L = 0.5f;
+				const float fPan_R = 0.5f;
+				const int nLength = 1;
+				const float fPitch = 0.0f;
+				Note *poffNote = new Note( pSelectedInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch);
+				poffNote->set_noteoff( true );
+				if ( pressednotekey == 0 )//note c
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::C;
+				if ( pressednotekey == 1 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::Cs;
+				if ( pressednotekey == 2 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::D;
+				if ( pressednotekey == 3 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::Ef;
+				if ( pressednotekey == 4 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::E;
+				if ( pressednotekey == 5 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::F;
+				if ( pressednotekey == 6 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::Fs;
+				if ( pressednotekey == 7 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::G;
+				if ( pressednotekey == 8 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::Af;
+				if ( pressednotekey == 9 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::A;
+				if ( pressednotekey == 10 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::Bf;
+				if ( pressednotekey == 11 )
+					poffNote->m_noteKey.m_key = H2Core::NoteKey::B;
+				
+				poffNote->m_noteKey.m_nOctave = pressedoctave;
+				
+				m_pPattern->note_map.insert( std::make_pair( nPosition, poffNote ) );
+	
+				pSong->__is_modified = true;
+			}
+
+		}
+
+		for ( int nCol = 0; unsigned(nCol) < nRealColumn; ++nCol ) {
+			if ( m_pDraggedNote ) break;
+			for ( pos = m_pPattern->note_map.lower_bound( nCol ); pos != m_pPattern->note_map.upper_bound( nCol ); ++pos ) {
+				Note *pNote = pos->second;
+				assert( pNote );
+
+				if ( ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument )
+				    && ( (nRealColumn <= pNote->get_position() + pNote->get_length() )
+				    && nRealColumn >= pNote->get_position() ) ){
+					m_pDraggedNote = pNote;
+					break;
+				}
+			}
+		}
+		AudioEngine::get_instance()->unlock();
+	}
+
+//	update( 0, 0, width(), height() );
+	updateEditor();
+	m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+	m_pPatternEditorPanel->getPanEditor()->updateEditor();
+	m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+	m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+	
+}
+
+
+void PianoRollEditor::mouseMoveEvent(QMouseEvent *ev)
+{
+	if (m_pPattern == NULL) {
+		return;
+	}
+
+	int row = ((int) ev->y()) / ((int) m_nEditorHeight);
+	if (row >= (int) m_nOctaves * 12 ) {
+		return;
+	}
+
+	//	__rightclickedpattereditor
+	//	0 = note length
+	//	1 = note off"
+	//	2 = edit velocity
+	//	3 = edit pan
+	//	4 = edit lead lag
+
+	if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 0 ) ) {
+		if ( m_pDraggedNote->get_noteoff() ) return;
+		int nTickColumn = getColumn( ev );
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+		int nLen = nTickColumn - (int)m_pDraggedNote->get_position();
+
+		if (nLen <= 0) {
+			nLen = -1;
+		}
+
+		float fNotePitch = m_pDraggedNote->m_noteKey.m_nOctave * 12 + m_pDraggedNote->m_noteKey.m_key;
+		float fStep = 0;
+		if(nLen > -1){
+			fStep = pow( 1.0594630943593, ( double )fNotePitch );
+		}else
+		{
+			fStep = 1.0; 
+		}
+		m_pDraggedNote->set_length( nLen * fStep);
+
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+
+		//__draw_pattern();
+		updateEditor();
+		m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+		m_pPatternEditorPanel->getPanEditor()->updateEditor();
+		m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+		m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+	}
+
+	//edit velocity
+	if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 2 ) ) {
+		if ( m_pDraggedNote->get_noteoff() ) return;
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+		float val = m_pDraggedNote->get_velocity();
+
+		
+		float ymove = m_pOldPoint - ev->y();
+		val = val  +  (ymove / 100);
+		if (val > 1) {
+			val = 1;
+		}
+		else if (val < 0.0) {
+			val = 0.0;
+		}
+
+		m_pDraggedNote->set_velocity( val );
+
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+
+		//__draw_pattern();
+		updateEditor();
+		m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+		m_pPatternEditorPanel->getPanEditor()->updateEditor();
+		m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+		m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+		m_pOldPoint = ev->y();
+	}
+
+	//edit pan
+	if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 3 ) ) {
+		if ( m_pDraggedNote->get_noteoff() ) return;
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+		float pan_L, pan_R;
+		
+		float val = (m_pDraggedNote->get_pan_r() - m_pDraggedNote->get_pan_l() + 0.5);
+	
+		float ymove = m_pOldPoint - ev->y();
+		val = val  +  (ymove / 100);
+
+
+		if ( val > 0.5 ) {
+			pan_L = 1.0 - val;
+			pan_R = 0.5;
+		}
+		else {
+			pan_L = 0.5;
+			pan_R = val;
+		}
+
+		m_pDraggedNote->set_pan_l( pan_L );
+		m_pDraggedNote->set_pan_r( pan_R );
+
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+
+		//__draw_pattern();
+		updateEditor();
+		m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+		m_pPatternEditorPanel->getPanEditor()->updateEditor();
+		m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+		m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+		m_pOldPoint = ev->y();
+	}
+
+	//edit lead lag
+	if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 4 ) ) {
+		if ( m_pDraggedNote->get_noteoff() ) return;
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+		
+		float val = ( m_pDraggedNote->get_leadlag() - 1.0 ) / -2.0 ;
+	
+		float ymove = m_pOldPoint - ev->y();
+		val = val  +  (ymove / 100);
+
+		if (val > 1.0) {
+			val = 1.0;
+		}
+		else if (val < 0.0) {
+			val = 0.0;
+		}
+
+		m_pDraggedNote->set_leadlag((val * -2.0) + 1.0);
+		char valueChar[100];
+		if ( m_pDraggedNote->get_leadlag() < 0.0 ) {
+			sprintf( valueChar, "%.2f",  ( m_pDraggedNote->get_leadlag() * -5 ) ); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
+			HydrogenApp::get_instance()->setStatusBarMessage( QString("Leading beat by: %1 ticks").arg( valueChar ), 2000 );
+		} else if ( m_pDraggedNote->get_leadlag() > 0.0 ) {
+			sprintf( valueChar, "%.2f",  ( m_pDraggedNote->get_leadlag() * 5 ) ); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
+			HydrogenApp::get_instance()->setStatusBarMessage( QString("Lagging beat by: %1 ticks").arg( valueChar ), 2000 );
+		} else {
+			HydrogenApp::get_instance()->setStatusBarMessage( QString("Note on beat"), 2000 );
+		}
+
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+
+		//__draw_pattern();
+		updateEditor();
+		m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+		m_pPatternEditorPanel->getPanEditor()->updateEditor();
+		m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+		m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+		m_pOldPoint = ev->y();
+	}
+
+}
+
+
+void PianoRollEditor::mouseReleaseEvent(QMouseEvent *ev)
+{
+	//INFOLOG("Mouse release event" );
+}
+
+
+void PianoRollEditor::zoom_in()
+{
+	if (m_nGridWidth >= 3){
+		m_nGridWidth *= 2;
+	}else
+	{
+		m_nGridWidth *= 1.5;
+	}
+	updateEditor();
+}
+
+
+
+void PianoRollEditor::zoom_out()
+{
+	if ( m_nGridWidth > 1.5 ) {
+		if (m_nGridWidth > 3){
+			m_nGridWidth /= 2;
+		}else
+		{
+			m_nGridWidth /= 1.5;
+		}
+		updateEditor();
+	}
+}
Index: /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorInstrumentList.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorInstrumentList.cpp	(revision 1511)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorInstrumentList.cpp	(revision 1511)
@@ -0,0 +1,688 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "PatternEditorInstrumentList.h"
+
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/note.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/Song.h>
+using namespace H2Core;
+
+#include "PatternEditorPanel.h"
+#include "DrumPatternEditor.h"
+#include "../HydrogenApp.h"
+#include "../Mixer/Mixer.h"
+#include "../widgets/Button.h"
+
+#include <QtGui>
+#include <cassert>
+
+using namespace std;
+
+
+
+
+
+InstrumentLine::InstrumentLine(QWidget* pParent)
+  : PixmapWidget(pParent, "InstrumentLine")
+  , m_bIsSelected(false)
+{
+	int h = Preferences::get_instance()->getPatternEditorGridHeight();
+	setFixedSize(181, h);
+
+	m_pNameLbl = new QLabel(this);
+	m_pNameLbl->resize( 145, h );
+	m_pNameLbl->move( 10, 1 );
+	QFont nameFont;
+	nameFont.setPointSize( 10 );
+	nameFont.setBold( true );
+	m_pNameLbl->setFont(nameFont);
+
+	m_pMuteBtn = new ToggleButton(
+			this,
+			"/patternEditor/btn_mute_on.png",
+			"/patternEditor/btn_mute_off.png",
+			"/patternEditor/btn_mute_off.png",
+			QSize( 9, 9 )
+	);
+	//m_pMuteBtn->setText( "M" );
+	m_pMuteBtn->move( 155, 5 );
+	m_pMuteBtn->setPressed(false);
+	connect(m_pMuteBtn, SIGNAL(clicked(Button*)), this, SLOT(muteClicked()));
+
+	m_pSoloBtn = new ToggleButton(
+			this,
+			"/patternEditor/btn_solo_on.png",
+			"/patternEditor/btn_solo_off.png",
+			"/patternEditor/btn_solo_off.png",
+			QSize( 9, 9 )
+	);
+	//m_pSoloBtn->setText( "S" );
+	m_pSoloBtn->move( 165, 5 );
+	m_pSoloBtn->setPressed(false);
+	connect(m_pSoloBtn, SIGNAL(clicked(Button*)), this, SLOT(soloClicked()));
+
+
+
+	// Popup menu
+	m_pFunctionPopup = new QMenu( this );
+	m_pFunctionPopup->addAction( trUtf8( "Clear notes" ), this, SLOT( functionClearNotes() ) );
+	m_pFunctionPopupSub = new QMenu( trUtf8( "Fill notes ..." ), m_pFunctionPopup );
+	m_pFunctionPopupSub->addAction( trUtf8( "Fill all notes" ), this, SLOT( functionFillAllNotes() ) );
+	m_pFunctionPopupSub->addAction( trUtf8( "Fill 1/2 notes" ), this, SLOT( functionFillEveryTwoNotes() ) );
+	m_pFunctionPopupSub->addAction( trUtf8( "Fill 1/3 notes" ), this, SLOT( functionFillEveryThreeNotes() ) );
+	m_pFunctionPopupSub->addAction( trUtf8( "Fill 1/4 notes" ), this, SLOT( functionFillEveryFourNotes() ) );
+	m_pFunctionPopupSub->addAction( trUtf8( "Fill 1/6 notes" ), this, SLOT( functionFillEverySixNotes() ) );
+	m_pFunctionPopupSub->addAction( trUtf8( "Fill 1/8 notes" ), this, SLOT( functionFillEveryEightNotes() ) );
+	m_pFunctionPopup->addMenu( m_pFunctionPopupSub );
+	m_pFunctionPopup->addAction( trUtf8( "Randomize velocity" ), this, SLOT( functionRandomizeVelocity() ) );
+	m_pFunctionPopup->addSeparator();
+	m_pFunctionPopup->addAction( trUtf8( "Delete instrument" ), this, SLOT( functionDeleteInstrument() ) );
+
+	m_bIsSelected = true;
+	setSelected(false);
+}
+
+
+
+void InstrumentLine::setName(const QString& sName)
+{
+	m_pNameLbl->setText(sName);
+}
+
+
+
+void InstrumentLine::setSelected(bool bSelected)
+{
+	if (bSelected == m_bIsSelected) {
+		return;
+	}
+	m_bIsSelected = bSelected;
+	if (m_bIsSelected) {
+		setPixmap( "/patternEditor/instrument_line_selected.png");
+	}
+	else {
+		setPixmap( "/patternEditor/instrument_line.png");
+	}
+}
+
+
+
+void InstrumentLine::setNumber(int nIndex)
+{
+	m_nInstrumentNumber = nIndex;
+}
+
+
+
+void InstrumentLine::setMuted(bool isMuted)
+{
+	m_pMuteBtn->setPressed(isMuted);
+}
+
+
+void InstrumentLine::setSoloed( bool soloed )
+{
+	m_pSoloBtn->setPressed( soloed );
+}
+
+
+
+void InstrumentLine::muteClicked()
+{
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+
+	Instrument *pInstr = instrList->get(m_nInstrumentNumber);
+	pInstr->set_muted( !pInstr->is_muted());
+}
+
+
+
+void InstrumentLine::soloClicked()
+{
+	HydrogenApp::get_instance()->getMixer()->soloClicked( m_nInstrumentNumber );
+}
+
+
+
+void InstrumentLine::mousePressEvent(QMouseEvent *ev)
+{
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( m_nInstrumentNumber );
+	HydrogenApp::get_instance()->getPatternEditorPanel()->updatePianorollEditor();
+
+	if ( ev->button() == Qt::LeftButton ) {
+		const float velocity = 0.8f;
+		const float pan_L = 0.5f;
+		const float pan_R = 0.5f;
+		const int nLength = -1;
+		const float fPitch = 0.0f;
+		Song *pSong = Hydrogen::get_instance()->getSong();
+		
+		Instrument *pInstr = pSong->get_instrument_list()->get( m_nInstrumentNumber );
+		
+		Note *pNote = new Note( pInstr, 0, velocity, pan_L, pan_R, nLength, fPitch);
+		AudioEngine::get_instance()->get_sampler()->note_on(pNote);
+	}
+	else if (ev->button() == Qt::RightButton ) {
+		m_pFunctionPopup->popup( QPoint( ev->globalX(), ev->globalY() ) );
+	}
+
+	// propago l'evento al parent: serve per il drag&drop
+	PixmapWidget::mousePressEvent(ev);
+}
+
+
+
+H2Core::Pattern* InstrumentLine::getCurrentPattern()
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	assert( pPatternList != NULL );
+
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if ( nSelectedPatternNumber != -1 ) {
+		Pattern* pCurrentPattern = pPatternList->get( nSelectedPatternNumber );
+		return pCurrentPattern;
+	}
+	return NULL;
+}
+
+
+
+
+void InstrumentLine::functionClearNotes()
+{
+// 	AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+	Hydrogen * H = Hydrogen::get_instance();
+	Pattern *pCurrentPattern = getCurrentPattern();
+
+	int nSelectedInstrument = m_nInstrumentNumber;
+	Instrument *pSelectedInstrument = H->getSong()->get_instrument_list()->get( nSelectedInstrument );
+	
+	pCurrentPattern->purge_instrument( pSelectedInstrument );
+// 	std::multimap <int, Note*>::iterator pos;
+// 	for ( pos = pCurrentPattern->note_map.begin(); pos != pCurrentPattern->note_map.end(); ++pos ) {
+// 		Note *pNote = pos->second;
+// 		assert( pNote );
+// 		if ( pNote->get_instrument() != pSelectedInstrument ) {
+// 			continue;
+// 		}
+// 
+// 		delete pNote;
+// 		pCurrentPattern->note_map.erase( pos );
+// 	}
+// 	AudioEngine::get_instance()->unlock();	// unlock the audio engine
+
+	// this will force an update...
+	EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
+}
+
+
+
+void InstrumentLine::functionFillAllNotes(){ functionFillNotes(1); }
+void InstrumentLine::functionFillEveryTwoNotes(){ functionFillNotes(2); }
+void InstrumentLine::functionFillEveryThreeNotes(){ functionFillNotes(3); }
+void InstrumentLine::functionFillEveryFourNotes(){ functionFillNotes(4); }
+void InstrumentLine::functionFillEverySixNotes(){ functionFillNotes(6); }
+void InstrumentLine::functionFillEveryEightNotes(){ functionFillNotes(8); }
+
+void InstrumentLine::functionFillNotes( int every )
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+
+	const float velocity = 0.8f;
+	const float pan_L = 0.5f;
+	const float pan_R = 0.5f;
+	const float fPitch = 0.0f;
+	const int nLength = -1;
+
+	PatternEditorPanel *pPatternEditorPanel = HydrogenApp::get_instance()->getPatternEditorPanel();
+	DrumPatternEditor *pPatternEditor = pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if ( pPatternEditor->isUsingTriplets() ) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+	int nResolution = 4 * MAX_NOTES * every / ( nBase * pPatternEditor->getResolution() );
+
+
+	AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+
+	Song *pSong = pEngine->getSong();
+
+	Pattern* pCurrentPattern = getCurrentPattern();
+	if (pCurrentPattern != NULL) {
+		int nPatternSize = pCurrentPattern->get_length();
+		int nSelectedInstrument = pEngine->getSelectedInstrumentNumber();
+
+		if (nSelectedInstrument != -1) {
+			Instrument *instrRef = (pSong->get_instrument_list())->get( nSelectedInstrument );
+
+			for (int i = 0; i < nPatternSize; i += nResolution) {
+				bool noteAlreadyPresent = false;
+
+				std::multimap <int, Note*>::iterator pos;
+				for ( pos = pCurrentPattern->note_map.lower_bound( i ); pos != pCurrentPattern->note_map.upper_bound( i ); ++pos ) {
+					Note *pNote = pos->second;
+					if ( pNote->get_instrument() == instrRef ) {
+						// note already exists
+						noteAlreadyPresent = true;
+						break;
+					}
+				}
+
+				if ( noteAlreadyPresent == false ) {
+					// create the new note
+					Note *pNote = new Note( instrRef, i, velocity, pan_L, pan_R, nLength, fPitch );
+					//pNote->setInstrument(instrRef);
+					pCurrentPattern->note_map.insert( std::make_pair( i, pNote ) );
+				}
+			}
+		}
+	}
+	AudioEngine::get_instance()->unlock();	// unlock the audio engine
+
+	// this will force an update...
+	EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
+}
+
+
+
+
+
+void InstrumentLine::functionRandomizeVelocity()
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+
+	PatternEditorPanel *pPatternEditorPanel = HydrogenApp::get_instance()->getPatternEditorPanel();
+	DrumPatternEditor *pPatternEditor = pPatternEditorPanel->getDrumPatternEditor();
+
+	AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+	int nBase;
+	if ( pPatternEditor->isUsingTriplets() ) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+	int nResolution = 4 * MAX_NOTES / ( nBase * pPatternEditor->getResolution() );
+
+	Song *pSong = pEngine->getSong();
+
+	Pattern* pCurrentPattern = getCurrentPattern();
+	if (pCurrentPattern != NULL) {
+		int nPatternSize = pCurrentPattern->get_length();
+		int nSelectedInstrument = pEngine->getSelectedInstrumentNumber();
+
+		if (nSelectedInstrument != -1) {
+			Instrument *instrRef = (pSong->get_instrument_list())->get( nSelectedInstrument );
+
+			for (int i = 0; i < nPatternSize; i += nResolution) {
+				std::multimap <int, Note*>::iterator pos;
+				for ( pos = pCurrentPattern->note_map.lower_bound(i); pos != pCurrentPattern->note_map.upper_bound( i ); ++pos ) {
+					Note *pNote = pos->second;
+					if ( pNote->get_instrument() == instrRef ) {
+						float fVal = ( rand() % 100 ) / 100.0;
+						fVal = pNote->get_velocity() + ( ( fVal - 0.50 ) / 2 );
+						if ( fVal < 0  ) {
+							fVal = 0;
+						}
+						if ( fVal > 1 ) {
+							fVal = 1;
+						}
+						pNote->set_velocity(fVal);
+					}
+				}
+			}
+		}
+	}
+	AudioEngine::get_instance()->unlock();	// unlock the audio engine
+
+	// this will force an update...
+	EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
+
+}
+
+
+
+
+
+void InstrumentLine::functionDeleteInstrument()
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	pEngine->removeInstrument( m_nInstrumentNumber, false );
+	
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+#ifdef JACK_SUPPORT
+	pEngine->renameJackPorts();
+#endif
+	AudioEngine::get_instance()->unlock();
+}
+
+
+
+//////
+
+
+
+PatternEditorInstrumentList::PatternEditorInstrumentList( QWidget *parent, PatternEditorPanel *pPatternEditorPanel )
+ : QWidget( parent )
+ , Object( "PatternEditorInstrumentList" )
+{
+	//setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG("INIT");
+	m_pPattern = NULL;
+ 	m_pPatternEditorPanel = pPatternEditorPanel;
+
+	m_nGridHeight = Preferences::get_instance()->getPatternEditorGridHeight();
+
+	m_nEditorWidth = 181;
+	m_nEditorHeight = m_nGridHeight * MAX_INSTRUMENTS;
+
+	resize( m_nEditorWidth, m_nEditorHeight );
+
+
+	setAcceptDrops(true);
+
+	for ( int i = 0; i < MAX_INSTRUMENTS; ++i) {
+		m_pInstrumentLine[i] = NULL;
+	}
+
+
+	updateInstrumentLines();
+
+	m_pUpdateTimer = new QTimer( this );
+	connect( m_pUpdateTimer, SIGNAL( timeout() ), this, SLOT( updateInstrumentLines() ) );
+	m_pUpdateTimer->start(50);
+
+}
+
+
+
+PatternEditorInstrumentList::~PatternEditorInstrumentList()
+{
+	//INFOLOG( "DESTROY" );
+	m_pUpdateTimer->stop();
+}
+
+
+
+
+///
+/// Create a new InstrumentLine
+///
+InstrumentLine* PatternEditorInstrumentList::createInstrumentLine()
+{
+	InstrumentLine *pLine = new InstrumentLine(this);
+	return pLine;
+}
+
+
+void PatternEditorInstrumentList::moveInstrumentLine( int nSourceInstrument , int nTargetInstrument )
+{
+		Hydrogen *engine = Hydrogen::get_instance();
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+		Song *pSong = engine->getSong();
+		InstrumentList *pInstrumentList = pSong->get_instrument_list();
+
+		if ( ( nTargetInstrument > (int)pInstrumentList->get_size() ) || ( nTargetInstrument < 0) ) {
+			AudioEngine::get_instance()->unlock();
+			return;
+		}
+
+
+		// move instruments...
+
+		Instrument *pSourceInstr = pInstrumentList->get(nSourceInstrument);
+		if ( nSourceInstrument < nTargetInstrument) {
+			for (int nInstr = nSourceInstrument; nInstr < nTargetInstrument; nInstr++) {
+				Instrument * pInstr = pInstrumentList->get(nInstr + 1);
+				pInstrumentList->replace( pInstr, nInstr );
+			}
+			pInstrumentList->replace( pSourceInstr, nTargetInstrument );
+		}
+		else {
+			for (int nInstr = nSourceInstrument; nInstr >= nTargetInstrument; nInstr--) {
+				Instrument * pInstr = pInstrumentList->get(nInstr - 1);
+				pInstrumentList->replace( pInstr, nInstr );
+			}
+			pInstrumentList->replace( pSourceInstr, nTargetInstrument );
+		}
+
+		#ifdef JACK_SUPPORT
+		engine->renameJackPorts();
+		#endif
+
+		AudioEngine::get_instance()->unlock();
+		engine->setSelectedInstrumentNumber( nTargetInstrument );
+
+		pSong->__is_modified = true;
+}
+
+///
+/// Update every InstrumentLine, create or destroy lines if necessary.
+///
+void PatternEditorInstrumentList::updateInstrumentLines()
+{
+	//INFOLOG( "Update lines" );
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *pSong = pEngine->getSong();
+	InstrumentList *pInstrList = pSong->get_instrument_list();
+	Mixer * mixer = HydrogenApp::get_instance()->getMixer();
+
+	unsigned nSelectedInstr = pEngine->getSelectedInstrumentNumber();
+
+	unsigned nInstruments = pInstrList->get_size();
+	for ( unsigned nInstr = 0; nInstr < MAX_INSTRUMENTS; ++nInstr ) {
+		if ( nInstr >= nInstruments ) {	// unused instrument! let's hide and destroy the mixerline!
+			if ( m_pInstrumentLine[ nInstr ] ) {
+				delete m_pInstrumentLine[ nInstr ];
+				m_pInstrumentLine[ nInstr ] = NULL;
+
+				int newHeight = m_nGridHeight * nInstruments;
+				resize( width(), newHeight );
+
+			}
+			continue;
+		}
+		else {
+			if ( m_pInstrumentLine[ nInstr ] == NULL ) {
+				// the instrument line doesn't exists..I'll create a new one!
+				m_pInstrumentLine[ nInstr ] = createInstrumentLine();
+				m_pInstrumentLine[nInstr]->move( 0, m_nGridHeight * nInstr );
+				m_pInstrumentLine[nInstr]->show();
+
+				int newHeight = m_nGridHeight * nInstruments;
+				resize( width(), newHeight );
+			}
+			InstrumentLine *pLine = m_pInstrumentLine[ nInstr ];
+			Instrument* pInstr = pInstrList->get(nInstr);
+			assert(pInstr);
+
+			pLine->setNumber(nInstr);
+			pLine->setName( pInstr->get_name() );
+			pLine->setSelected( nInstr == nSelectedInstr );
+			pLine->setMuted( pInstr->is_muted() );
+			if ( mixer ) {
+				pLine->setSoloed( mixer->isSoloClicked( nInstr ) );
+			}
+
+		}
+	}
+
+}
+
+
+
+
+void PatternEditorInstrumentList::dragEnterEvent(QDragEnterEvent *event)
+{
+	INFOLOG( "[dragEnterEvent]" );
+	if ( event->mimeData()->hasFormat("text/plain") ) {
+		Song *song = (Hydrogen::get_instance())->getSong();
+		int nInstruments = song->get_instrument_list()->get_size();
+		if ( nInstruments < MAX_INSTRUMENTS ) {
+			event->acceptProposedAction();
+		}
+	}
+}
+
+
+void PatternEditorInstrumentList::dropEvent(QDropEvent *event)
+{
+	//WARNINGLOG("Drop!");
+	QString sText = event->mimeData()->text();
+	//ERRORLOG(sText);
+	
+
+	if(sText.startsWith("Songs:") || sText.startsWith("Patterns:") || sText.startsWith("move pattern:") || sText.startsWith("drag pattern:")) return;
+
+	if (sText.startsWith("move instrument:")) {
+
+		Hydrogen *engine = Hydrogen::get_instance();
+		int nSourceInstrument = engine->getSelectedInstrumentNumber();
+
+		int nTargetInstrument = event->pos().y() / m_nGridHeight;
+
+		if ( nSourceInstrument == nTargetInstrument ) {
+			event->acceptProposedAction();
+			return;
+		}
+
+		moveInstrumentLine( nSourceInstrument , nTargetInstrument );
+
+		event->acceptProposedAction();
+	}
+	if( sText.startsWith("importInstrument:") ) {
+		//an instrument was dragged from the soundlibrary browser to the patterneditor
+
+		sText = sText.remove(0,QString("importInstrument:").length());
+
+		QStringList tokens = sText.split( "::" );
+		QString sDrumkitName = tokens.at( 0 );
+		QString sInstrumentName = tokens.at( 1 );
+		
+		Instrument *pNewInstrument = Instrument::load_instrument( sDrumkitName, sInstrumentName );
+		if( pNewInstrument == NULL ) return;		
+
+		Hydrogen *pEngine = Hydrogen::get_instance();
+
+		// create a new valid ID for this instrument
+		int nID = -1;
+		for ( uint i = 0; i < pEngine->getSong()->get_instrument_list()->get_size(); ++i ) {
+			Instrument* pInstr = pEngine->getSong()->get_instrument_list()->get( i );
+			if ( pInstr->get_id().toInt() > nID ) {
+				nID = pInstr->get_id().toInt();
+			}
+		}
+		++nID;
+
+		pNewInstrument->set_id( QString("%1").arg( nID ) );
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		pEngine->getSong()->get_instrument_list()->add( pNewInstrument );
+
+		#ifdef JACK_SUPPORT
+		pEngine->renameJackPorts();
+		#endif
+
+		AudioEngine::get_instance()->unlock();
+
+	
+		int nTargetInstrument = event->pos().y() / m_nGridHeight;
+
+		/*
+		    "X > 181": border between the instrument names on the left and the grid
+		    Because the right part of the grid starts above the name column, we have to subtract the difference 
+		*/
+
+		if (  event->pos().x() > 181 ) nTargetInstrument = ( event->pos().y() - 90 )  / m_nGridHeight ;
+
+		//move instrument to the position where it was dropped
+		moveInstrumentLine(pEngine->getSong()->get_instrument_list()->get_size() - 1 , nTargetInstrument );
+
+
+
+		// select the new instrument
+		pEngine->setSelectedInstrumentNumber(nTargetInstrument);
+
+		event->acceptProposedAction();
+	}
+}
+
+
+
+void PatternEditorInstrumentList::mousePressEvent(QMouseEvent *event)
+{
+	if (event->button() == Qt::LeftButton) {
+		__drag_start_position = event->pos();
+	}
+
+}
+
+
+
+void PatternEditorInstrumentList::mouseMoveEvent(QMouseEvent *event)
+{
+	if (!(event->buttons() & Qt::LeftButton)) {
+		return;
+	}
+	if ( abs(event->pos().y() - __drag_start_position.y()) < (int)m_nGridHeight) {
+		return;
+	}
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	int nSelectedInstr = pEngine->getSelectedInstrumentNumber();
+	Instrument *pInstr = pEngine->getSong()->get_instrument_list()->get(nSelectedInstr);
+
+	QString sText = QString("move instrument:%1").arg( pInstr->get_name() );
+
+	QDrag *pDrag = new QDrag(this);
+	QMimeData *pMimeData = new QMimeData;
+
+	pMimeData->setText( sText );
+	pDrag->setMimeData( pMimeData);
+	//drag->setPixmap(iconPixmap);
+
+	pDrag->start( Qt::CopyAction | Qt::MoveAction );
+
+	// propago l'evento
+	QWidget::mouseMoveEvent(event);
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorPanel.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorPanel.h	(revision 1439)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PatternEditorPanel.h	(revision 1439)
@@ -0,0 +1,189 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef PATTERN_EDITOR_PANEL_H
+#define PATTERN_EDITOR_PANEL_H
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+#include "PianoRollEditor.h"
+#include "../EventListener.h"
+
+class Button;
+class ToggleButton;
+class Fader;
+class PatternEditorRuler;
+class PatternEditorInstrumentList;
+class NotePropertiesRuler;
+class LCDCombo;
+class DrumPatternEditor;
+class PianoRollEditor;
+
+
+namespace H2Core
+{
+	class Pattern;
+}
+
+///
+/// Pattern Editor Panel
+///
+class PatternEditorPanel : public QWidget, public EventListener, public Object
+{
+	Q_OBJECT
+
+	public:
+		PatternEditorPanel(QWidget *parent);
+		~PatternEditorPanel();
+
+		DrumPatternEditor* getDrumPatternEditor() {	return m_pDrumPatternEditor;	}
+		NotePropertiesRuler* getVelocityEditor() {	return m_pNoteVelocityEditor;	}
+		NotePropertiesRuler* getPanEditor() {	return m_pNotePanEditor;	}
+		NotePropertiesRuler* getLeadLagEditor() {	return m_pNoteLeadLagEditor;	}
+		NotePropertiesRuler* getNoteKeyEditor() {	return m_pNoteNoteKeyEditor;	}
+		PatternEditorInstrumentList* getInstrumentList() {	return m_pInstrumentList;	}
+		PianoRollEditor* getPianoRollEditor() {		return m_pPianoRollEditor;	}
+
+		void updateSLnameLabel();
+		void displayorHidePrePostCB();
+		void updatePianorollEditor();
+
+		// Implements EventListener interface
+		virtual void selectedPatternChangedEvent();
+		virtual void selectedInstrumentChangedEvent();
+		virtual void stateChangedEvent(int nState);
+		//~ Implements EventListener interface
+
+	private slots:
+		void gridResolutionChanged( QString text );
+		void propertiesComboChanged( QString text );
+		void patternSizeChanged( QString text );
+
+		void hearNotesBtnClick(Button *ref);
+		void quantizeEventsBtnClick(Button *ref);
+
+		void showDrumEditorBtnClick(Button *ref);
+
+		void syncToExternalHorizontalScrollbar(int);
+		void contentsMoving(int dummy);
+		void on_patternEditorScroll(int);
+
+
+		void zoomInBtnClicked(Button *ref);
+		void zoomOutBtnClicked(Button *ref);
+
+		void moveDownBtnClicked(Button *);
+		void moveUpBtnClicked(Button *);
+
+		void playselectedinstrument( QString text );
+		void rightclickSelect( QString text );
+		void recPreDeleteSelect( int index );
+		void recPostDeleteSelect( int index );
+
+	private:
+		H2Core::Pattern *m_pPattern;
+		QPixmap m_backgroundPixmap;
+		QLabel *pSLlabel;
+
+		// Editor top
+		LCDCombo *__pattern_size_combo;
+		LCDCombo *__resolution_combo;
+		ToggleButton *__show_drum_btn;
+		ToggleButton *__show_piano_btn;
+		QComboBox *__recpredelete;
+		QComboBox *__recpostdelete;
+
+
+		// ~Editor top
+
+		//
+		LCDCombo * __pPropertiesCombo;
+
+		// drum editor
+		QScrollArea* m_pEditorScrollView;
+		DrumPatternEditor *m_pDrumPatternEditor;
+
+		// piano roll editor
+		QScrollArea* m_pPianoRollInternScrollView;
+		QScrollArea* m_pPianoRollScrollView;
+		PianoRollEditor *m_pPianoRollEditor;
+
+		// ruler
+		QScrollArea* m_pRulerScrollView;
+		PatternEditorRuler *m_pPatternEditorRuler;
+
+		// instr list
+		QScrollArea* m_pInstrListScrollView;
+		PatternEditorInstrumentList  *m_pInstrumentList;
+
+		// note velocity editor
+		QScrollArea* m_pNoteVelocityScrollView;
+		NotePropertiesRuler *m_pNoteVelocityEditor;
+
+		// note pan editor
+		QScrollArea* m_pNotePanScrollView;
+		NotePropertiesRuler *m_pNotePanEditor;
+
+		// note leadlag editor
+		QScrollArea* m_pNoteLeadLagScrollView;
+		NotePropertiesRuler *m_pNoteLeadLagEditor;
+
+		// note notekey editor
+		QScrollArea* m_pNoteNoteKeyScrollView;
+		NotePropertiesRuler *m_pNoteNoteKeyEditor;
+		
+
+
+		QScrollBar *m_pPatternEditorHScrollBar;
+		QScrollBar *m_pPatternEditorVScrollBar;
+
+		// TOOLBAR
+		QLabel *m_pPatternNameLbl;
+
+
+
+		Button *m_pRandomVelocityBtn;
+		//~ TOOLBAR
+
+
+		Button *sizeDropdownBtn;
+		Button *resDropdownBtn;
+
+
+		QComboBox* __rightclickSelection;
+ 
+		bool m_bEnablePatternResize;
+
+
+		virtual void dragEnterEvent(QDragEnterEvent *event);
+		virtual void dropEvent(QDropEvent *event);
+
+		virtual void resizeEvent(QResizeEvent *ev);
+		virtual void showEvent(QShowEvent *ev);
+};
+
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/PatternEditor/PianoRollEditor.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/PianoRollEditor.h	(revision 1439)
+++ /branches/tabbedInterface/gui/src/PatternEditor/PianoRollEditor.h	(revision 1439)
@@ -0,0 +1,94 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PIANO_ROLL_EDITOR_H
+#define PIANO_ROLL_EDITOR_H
+
+#include <hydrogen/Object.h>
+#include "../EventListener.h"
+
+#include <QtGui>
+
+namespace H2Core
+{
+	class Pattern;
+	class Note;
+}
+
+class PatternEditorPanel;
+
+class PianoRollEditor: public QWidget, public EventListener, public Object
+{
+	public:
+		PianoRollEditor( QWidget *pParent, PatternEditorPanel *panel );
+		~PianoRollEditor();
+
+
+		// Implements EventListener interface
+		virtual void selectedPatternChangedEvent();
+		virtual void selectedInstrumentChangedEvent();
+		virtual void patternModifiedEvent();
+		//~ Implements EventListener interface
+		void setResolution(uint res, bool bUseTriplets);
+
+		void zoom_in();
+		void zoom_out();
+
+	public slots:
+		void updateEditor();
+
+	private:
+
+		unsigned m_nRowHeight;
+		unsigned m_nOctaves;
+
+		uint m_nResolution;
+		bool m_bRightBtnPressed;
+		bool m_bUseTriplets;
+
+		H2Core::Pattern *m_pPattern;
+
+		float m_nGridWidth;
+		uint m_nEditorWidth;
+		uint m_nEditorHeight;
+		QPixmap *m_pBackground;
+		QPixmap *m_pTemp;
+		int m_pOldPoint;
+
+		PatternEditorPanel *m_pPatternEditorPanel;
+		H2Core::Note *m_pDraggedNote;
+
+		void createBackground();
+		void drawPattern();
+		void draw_grid(QPainter& p );
+		void drawNote( H2Core::Note *pNote, QPainter *pPainter );
+
+		virtual void paintEvent(QPaintEvent *ev);
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+//		virtual void keyPressEvent ( QKeyEvent * ev );
+		int getColumn(QMouseEvent *ev);
+};
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/PatternEditor/DrumPatternEditor.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/DrumPatternEditor.cpp	(revision 1555)
+++ /branches/tabbedInterface/gui/src/PatternEditor/DrumPatternEditor.cpp	(revision 1555)
@@ -0,0 +1,782 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "DrumPatternEditor.h"
+#include "PatternEditorPanel.h"
+#include "NotePropertiesRuler.h"
+
+#include <hydrogen/globals.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/note.h>
+#include <hydrogen/audio_engine.h>
+
+#include "../HydrogenApp.h"
+#include "../Mixer/Mixer.h"
+#include "../Skin.h"
+
+#include <math.h>
+#include <cassert>
+#include <algorithm>
+
+#include <QtGui>
+
+using namespace std;
+using namespace H2Core;
+
+DrumPatternEditor::DrumPatternEditor(QWidget* parent, PatternEditorPanel *panel)
+ : QWidget( parent )
+ , Object( "DrumPatternEditor" )
+ , m_nResolution( 8 )
+ , m_bUseTriplets( false )
+ , m_bRightBtnPressed( false )
+ , m_pDraggedNote( NULL )
+ , m_pPattern( NULL )
+ , m_pPatternEditorPanel( panel )
+{
+	//setAttribute(Qt::WA_NoBackground);
+	setFocusPolicy(Qt::ClickFocus);
+
+	m_nGridWidth = Preferences::get_instance()->getPatternEditorGridWidth();
+	m_nGridHeight = Preferences::get_instance()->getPatternEditorGridHeight();
+
+	unsigned nEditorWidth = 20 + m_nGridWidth * ( MAX_NOTES * 4 );
+	m_nEditorHeight = m_nGridHeight * MAX_INSTRUMENTS;
+
+	resize( nEditorWidth, m_nEditorHeight );
+
+	HydrogenApp::get_instance()->addEventListener( this );
+	
+}
+
+
+
+DrumPatternEditor::~DrumPatternEditor()
+{
+}
+
+
+
+void DrumPatternEditor::updateEditor()
+{
+	Hydrogen* engine = Hydrogen::get_instance();
+
+	// check engine state
+	int state = engine->getState();
+	if ( (state != STATE_READY) && (state != STATE_PLAYING) ) {
+		ERRORLOG( "FIXME: skipping pattern editor update (state shoud be READY or PLAYING)" );
+		return;
+	}
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() ) ) {
+		m_pPattern = pPatternList->get( nSelectedPatternNumber );
+	}
+	else {
+		m_pPattern = NULL;
+	}
+
+
+	uint nEditorWidth;
+	if ( m_pPattern ) {
+		nEditorWidth = 20 + m_nGridWidth * m_pPattern->get_length();
+	}
+	else {
+		nEditorWidth = 20 + m_nGridWidth * MAX_NOTES;
+	}
+	resize( nEditorWidth, height() );
+
+	// redraw all
+	update( 0, 0, width(), height() );
+}
+
+
+
+int DrumPatternEditor::getColumn(QMouseEvent *ev)
+{
+	int nBase;
+	if (m_bUseTriplets) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+	int nWidth = (m_nGridWidth * 4 * MAX_NOTES) / (nBase * m_nResolution);
+
+	int x = ev->x();
+	int nColumn;
+	nColumn = x - 20 + (nWidth / 2);
+	nColumn = nColumn / nWidth;
+	nColumn = (nColumn * 4 * MAX_NOTES) / (nBase * m_nResolution);
+	return nColumn;
+}
+
+
+
+void DrumPatternEditor::mousePressEvent(QMouseEvent *ev)
+{
+	if ( m_pPattern == NULL ) {
+		return;
+	}
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	int nInstruments = pSong->get_instrument_list()->get_size();
+
+	int row = (int)( ev->y()  / (float)m_nGridHeight);
+	if (row >= nInstruments) {
+		return;
+	}
+
+	int nColumn = getColumn( ev );
+
+	if ( nColumn >= (int)m_pPattern->get_length() ) {
+		update( 0, 0, width(), height() );
+		return;
+	}
+	Instrument *pSelectedInstrument = pSong->get_instrument_list()->get( row );
+
+	if (ev->button() == Qt::LeftButton ) {
+		m_bRightBtnPressed = false;
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+
+		bool bNoteAlreadyExist = false;
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.lower_bound( nColumn ); pos != m_pPattern->note_map.upper_bound( nColumn ); ++pos ) {
+			Note *pNote = pos->second;
+			assert( pNote );
+			if ( pNote->get_instrument() == pSelectedInstrument ) {
+				// the note exists...remove it!
+				bNoteAlreadyExist = true;
+				delete pNote;
+				m_pPattern->note_map.erase( pos );
+				break;
+			}
+		}
+
+		if ( bNoteAlreadyExist == false ) {
+			// create the new note
+			const unsigned nPosition = nColumn;
+			const float fVelocity = 0.8f;
+			const float fPan_L = 0.5f;
+			const float fPan_R = 0.5f;
+			const int nLength = -1;
+			const float fPitch = 0.0f;
+			Note *pNote = new Note( pSelectedInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch );
+			pNote->set_noteoff( false );
+			m_pPattern->note_map.insert( std::make_pair( nPosition, pNote ) );
+
+			// hear note
+			Preferences *pref = Preferences::get_instance();
+			if ( pref->getHearNewNotes() ) {
+				Note *pNote2 = new Note( pSelectedInstrument, 0, fVelocity, fPan_L, fPan_R, nLength, fPitch);
+				AudioEngine::get_instance()->get_sampler()->note_on(pNote2);
+			}
+		}
+		pSong->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+	}
+	else if (ev->button() == Qt::RightButton ) {
+		m_bRightBtnPressed = true;
+		m_pDraggedNote = NULL;
+
+		unsigned nRealColumn = 0;
+		if( ev->x() > 20 ) {
+			nRealColumn = (ev->x() - 20) / static_cast<float>(m_nGridWidth);
+		}
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.lower_bound( nColumn ); pos != m_pPattern->note_map.upper_bound( nColumn ); ++pos ) {
+			Note *pNote = pos->second;
+			assert( pNote );
+
+			if ( pNote->get_instrument() == pSelectedInstrument ) {
+				m_pDraggedNote = pNote;
+				break;
+			}
+		}
+		if ( !m_pDraggedNote ) {
+			for ( pos = m_pPattern->note_map.lower_bound( nRealColumn ); pos != m_pPattern->note_map.upper_bound( nRealColumn ); ++pos ) {
+				Note *pNote = pos->second;
+				assert( pNote );
+
+				if ( pNote->get_instrument() == pSelectedInstrument ) {
+					m_pDraggedNote = pNote;
+					break;
+				}
+			}
+
+///
+		//	__rightclickedpattereditor
+		//	0 = note length
+		//	1 = note off"
+		//	2 = edit velocity
+		//	3 = edit pan
+		//	4 = edit lead lag
+
+			if ( Preferences::get_instance()->__rightclickedpattereditor == 1){
+				// create the new note
+				const unsigned nPosition = nColumn;
+				const float fVelocity = 0.0f;
+				const float fPan_L = 0.5f;
+				const float fPan_R = 0.5f;
+				const int nLength = 1;
+				const float fPitch = 0.0f;
+				Note *poffNote = new Note( pSelectedInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch);
+				poffNote->set_noteoff( true );
+	
+				
+				m_pPattern->note_map.insert( std::make_pair( nPosition, poffNote ) );
+	
+				pSong->__is_modified = true;
+			}
+///
+		}
+		// potrei essere sulla coda di una nota precedente..
+		for ( int nCol = 0; unsigned(nCol) < nRealColumn; ++nCol ) {
+			if ( m_pDraggedNote ) break;
+			for ( pos = m_pPattern->note_map.lower_bound( nCol ); pos != m_pPattern->note_map.upper_bound( nCol ); ++pos ) {
+				Note *pNote = pos->second;
+				assert( pNote );
+
+				if ( pNote->get_instrument() == pSelectedInstrument
+				    && ( (nRealColumn <= pNote->get_position() + pNote->get_length() )
+				    && nRealColumn >= pNote->get_position() ) ){
+					m_pDraggedNote = pNote;
+					break;
+				}
+			}
+		}
+		AudioEngine::get_instance()->unlock();
+	}
+
+	// update the selected line
+	int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+	if (nSelectedInstrument != row) {
+		Hydrogen::get_instance()->setSelectedInstrumentNumber( row );
+	}
+	else {
+		update( 0, 0, width(), height() );
+		m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+		m_pPatternEditorPanel->getPanEditor()->updateEditor();
+		m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+		m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+	}
+}
+
+
+
+void DrumPatternEditor::mouseReleaseEvent(QMouseEvent *ev)
+{
+	UNUSED( ev );
+	setCursor( QCursor( Qt::ArrowCursor ) );
+
+	if (m_pPattern == NULL) {
+		return;
+	}
+}
+
+
+
+void DrumPatternEditor::mouseMoveEvent(QMouseEvent *ev)
+{
+	if (m_pPattern == NULL) {
+		return;
+	}
+
+	int row = MAX_INSTRUMENTS - 1 - (ev->y()  / (int)m_nGridHeight);
+	if (row >= MAX_INSTRUMENTS) {
+		return;
+	}
+
+	//	__rightclickedpattereditor
+	//	0 = note length
+	//	1 = note off"
+	//	2 = edit velocity
+	//	3 = edit pan
+	//	4 = edit lead lag
+
+	if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 0 ) ) {
+		if ( m_pDraggedNote->get_noteoff() ) return;
+		int nTickColumn = getColumn( ev );
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );	// lock the audio engine
+		int nLen = nTickColumn - (int)m_pDraggedNote->get_position();
+
+		if (nLen <= 0) {
+			nLen = -1;
+		}
+
+		float fNotePitch = m_pDraggedNote->m_noteKey.m_nOctave * 12 + m_pDraggedNote->m_noteKey.m_key;
+		float fStep = 0;
+		if(nLen > -1){
+			fStep = pow( 1.0594630943593, ( double )fNotePitch );
+		}else
+		{
+			fStep = 1.0; 
+		}
+		m_pDraggedNote->set_length( nLen * fStep);
+
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+		AudioEngine::get_instance()->unlock(); // unlock the audio engine
+
+		//__draw_pattern();
+		update( 0, 0, width(), height() );
+		m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+		m_pPatternEditorPanel->getPanEditor()->updateEditor();
+		m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+		m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+	}
+
+}
+
+
+
+void DrumPatternEditor::keyPressEvent (QKeyEvent *ev)
+{
+	ev->ignore();
+}
+
+
+
+///
+/// Draws a pattern
+///
+void DrumPatternEditor::__draw_pattern(QPainter& painter)
+{
+	const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	const QColor selectedRowColor( pStyle->m_patternEditor_selectedRowColor.getRed(), pStyle->m_patternEditor_selectedRowColor.getGreen(), pStyle->m_patternEditor_selectedRowColor.getBlue() );
+
+	__create_background( painter );
+
+	if (m_pPattern == NULL) {
+		return;
+	}
+
+	int nNotes = m_pPattern->get_length();
+	int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+	Song *pSong = Hydrogen::get_instance()->getSong();
+
+	InstrumentList * pInstrList = pSong->get_instrument_list();
+
+	
+	if ( m_nEditorHeight != (int)( m_nGridHeight * pInstrList->get_size() ) ) {
+		// the number of instruments is changed...recreate all
+		m_nEditorHeight = m_nGridHeight * pInstrList->get_size();
+		resize( width(), m_nEditorHeight );
+	}
+
+	for ( uint nInstr = 0; nInstr < pInstrList->get_size(); ++nInstr ) {
+		uint y = m_nGridHeight * nInstr;
+		if ( nInstr == (uint)nSelectedInstrument ) {	// selected instrument
+			painter.fillRect( 0, y + 1, ( 20 + nNotes * m_nGridWidth ), m_nGridHeight - 1, selectedRowColor );
+		}
+	}
+
+
+	// draw the grid
+	__draw_grid( painter );
+	
+
+	/*
+		BUGFIX
+		
+		if m_pPattern is not renewed every time we draw a note, 
+		hydrogen will crash after you save a song and create a new one. 
+		-smoors
+	*/
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() ) ) {
+		m_pPattern = pPatternList->get( nSelectedPatternNumber );
+	}
+	else {
+		m_pPattern = NULL;
+	}
+	// ~ FIX
+
+
+
+	if( m_pPattern->note_map.size() == 0) return;
+
+	std::multimap <int, Note*>::iterator pos;
+	for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); pos++ ) {
+		Note *note = pos->second;
+		assert( note );
+		__draw_note( note, painter );
+	}
+}
+
+
+
+QColor DrumPatternEditor::computeNoteColor( float velocity ){
+    int red;
+    int green;
+    int blue;
+
+
+    /*
+	The note gets painted black if it has the default velocity (0.8).
+	The color changes if you alter the velocity..
+    */
+
+    //qDebug() << "x: " << x;
+    //qDebug() << "x2: " << x*x;
+
+
+    if( velocity < 0.8){
+	red = fabs(-( velocity - 0.8))*255;
+	green =  fabs(-( velocity - 0.8))*255;
+	blue =  green * 1.25;
+    } else {
+	green = blue = 0;
+	red = (velocity-0.8)*5*255;
+    }
+
+    //qDebug() << "R " << red << "G " << green << "blue " << blue;
+    return QColor( red, green, blue );
+}
+
+
+
+///
+/// Draws a note
+///
+void DrumPatternEditor::__draw_note( Note *note, QPainter& p )
+{
+	static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	static const QColor noteColor( pStyle->m_patternEditor_noteColor.getRed(), pStyle->m_patternEditor_noteColor.getGreen(), pStyle->m_patternEditor_noteColor.getBlue() );
+	static const QColor noteoffColor( pStyle->m_patternEditor_noteoffColor.getRed(), pStyle->m_patternEditor_noteoffColor.getGreen(), pStyle->m_patternEditor_noteoffColor.getBlue() );
+
+	p.setRenderHint( QPainter::Antialiasing );
+
+	int nInstrument = -1;
+	InstrumentList * pInstrList = Hydrogen::get_instance()->getSong()->get_instrument_list();
+	for ( uint nInstr = 0; nInstr < pInstrList->get_size(); ++nInstr ) {
+		Instrument *pInstr = pInstrList->get( nInstr );
+		if ( pInstr == note->get_instrument() ) {
+ 			nInstrument = nInstr;
+			break;
+		}
+	}
+	if ( nInstrument == -1 ) {
+		ERRORLOG( "Instrument not found..skipping note" );
+		return;
+	}
+
+	uint pos = note->get_position();
+
+	p.setPen( noteColor );
+
+
+	QColor color = computeNoteColor( note->get_velocity() );
+
+	uint w = 8;
+	uint h =  m_nGridHeight / 3;
+
+	if ( note->get_length() == -1 && note->get_noteoff() == false ) {	// trigger note
+		uint x_pos = 20 + (pos * m_nGridWidth);// - m_nGridWidth / 2.0;
+		uint y_pos = ( nInstrument * m_nGridHeight) + (m_nGridHeight / 2) - 3;
+		p.setBrush( color );
+		p.drawEllipse( x_pos -4 , y_pos, w, h );
+
+
+	}
+	else if ( note->get_length() == 1 && note->get_noteoff() == true ){
+		p.setPen( noteoffColor );
+		uint x_pos = 20 + ( pos * m_nGridWidth );// - m_nGridWidth / 2.0;
+
+		uint y_pos = ( nInstrument * m_nGridHeight ) + (m_nGridHeight / 2) - 3;
+		p.setBrush(QColor( noteoffColor));
+		p.drawEllipse( x_pos -4 , y_pos, w, h );
+
+
+
+	}		
+	else {
+		float fNotePitch = note->m_noteKey.m_nOctave * 12 + note->m_noteKey.m_key;
+		float fStep = pow( 1.0594630943593, ( double )fNotePitch );
+
+		uint x = 20 + (pos * m_nGridWidth);
+		int w = m_nGridWidth * note->get_length() / fStep;
+		w = w - 1;	// lascio un piccolo spazio tra una nota ed un altra
+
+		int y = (int) ( ( nInstrument ) * m_nGridHeight  + (m_nGridHeight / 100.0 * 30.0) );
+		int h = (int) (m_nGridHeight - ((m_nGridHeight / 100.0 * 30.0) * 2.0) );
+		p.setBrush( color );
+		p.fillRect( x, y + 1, w, h + 1, color );	/// \todo: definire questo colore nelle preferenze
+		p.drawRect( x, y + 1, w, h + 1 );
+	}
+}
+
+
+
+
+void DrumPatternEditor::__draw_grid( QPainter& p )
+{
+	static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	static const QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
+	static const QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
+	static const QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
+	static const QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
+	static const QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
+
+	// vertical lines
+	p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+
+	int nBase;
+	if (m_bUseTriplets) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+
+	int n4th = 4 * MAX_NOTES / (nBase * 4);
+	int n8th = 4 * MAX_NOTES / (nBase * 8);
+	int n16th = 4 * MAX_NOTES / (nBase * 16);
+	int n32th = 4 * MAX_NOTES / (nBase * 32);
+	int n64th = 4 * MAX_NOTES / (nBase * 64);
+
+	int nNotes = MAX_NOTES;
+	if ( m_pPattern ) {
+		nNotes = m_pPattern->get_length();
+	}
+	if (!m_bUseTriplets) {
+		for ( int i = 0; i < nNotes + 1; i++ ) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % n4th) == 0 ) {
+				if (m_nResolution >= 4) {
+					p.setPen( QPen( res_1, 0 ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n8th) == 0 ) {
+				if (m_nResolution >= 8) {
+					p.setPen( QPen( res_2, 0 ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n16th) == 0 ) {
+				if (m_nResolution >= 16) {
+					p.setPen( QPen( res_3, 0 ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n32th) == 0 ) {
+				if (m_nResolution >= 32) {
+					p.setPen( QPen( res_4, 0 ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+			else if ( (i % n64th) == 0 ) {
+				if (m_nResolution >= 64) {
+					p.setPen( QPen( res_5, 0 ) );
+					p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				}
+			}
+		}
+	}
+	else {	// Triplets
+		uint nCounter = 0;
+		int nSize = 4 * MAX_NOTES / (nBase * m_nResolution);
+
+		for ( int i = 0; i < nNotes + 1; i++ ) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % nSize) == 0) {
+				if ((nCounter % 3) == 0) {
+					p.setPen( QPen( res_1, 0 ) );
+				}
+				else {
+					p.setPen( QPen( res_3, 0 ) );
+				}
+				p.drawLine(x, 1, x, m_nEditorHeight - 1);
+				nCounter++;
+			}
+		}
+	}
+
+
+	// fill the first half of the rect with a solid color
+	static const QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	static const QColor selectedRowColor( pStyle->m_patternEditor_selectedRowColor.getRed(), pStyle->m_patternEditor_selectedRowColor.getGreen(), pStyle->m_patternEditor_selectedRowColor.getBlue() );
+	int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	int nInstruments = pSong->get_instrument_list()->get_size();
+	for ( uint i = 0; i < (uint)nInstruments; i++ ) {
+		uint y = m_nGridHeight * i + 1;
+		if ( i == (uint)nSelectedInstrument ) {
+			p.fillRect( 0, y, (20 + nNotes * m_nGridWidth), (int)( m_nGridHeight * 0.7 ), selectedRowColor );
+		}
+		else {
+			p.fillRect( 0, y, (20 + nNotes * m_nGridWidth), (int)( m_nGridHeight * 0.7 ), backgroundColor );
+		}
+	}
+
+}
+
+
+void DrumPatternEditor::__create_background( QPainter& p)
+{
+	static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	static const QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	static const QColor alternateRowColor( pStyle->m_patternEditor_alternateRowColor.getRed(), pStyle->m_patternEditor_alternateRowColor.getGreen(), pStyle->m_patternEditor_alternateRowColor.getBlue() );
+	static const QColor lineColor( pStyle->m_patternEditor_lineColor.getRed(), pStyle->m_patternEditor_lineColor.getGreen(), pStyle->m_patternEditor_lineColor.getBlue() );
+
+	int nNotes = MAX_NOTES;
+	if ( m_pPattern ) {
+		nNotes = m_pPattern->get_length();
+	}
+
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	int nInstruments = pSong->get_instrument_list()->get_size();
+
+	if ( m_nEditorHeight != (int)( m_nGridHeight * nInstruments ) ) {
+		// the number of instruments is changed...recreate all
+		m_nEditorHeight = m_nGridHeight * nInstruments;
+		resize( width(), m_nEditorHeight );
+	}
+
+	p.fillRect(0, 0, 20 + nNotes * m_nGridWidth, height(), backgroundColor);
+	for ( uint i = 0; i < (uint)nInstruments; i++ ) {
+		uint y = m_nGridHeight * i;
+		if ( ( i % 2) != 0) {
+			p.fillRect( 0, y, (20 + nNotes * m_nGridWidth), m_nGridHeight, alternateRowColor );
+		}
+	}
+
+	// horizontal lines
+	p.setPen( lineColor );
+	for ( uint i = 0; i < (uint)nInstruments; i++ ) {
+		uint y = m_nGridHeight * i + m_nGridHeight;
+		p.drawLine( 0, y, (20 + nNotes * m_nGridWidth), y);
+	}
+
+	p.drawLine( 0, m_nEditorHeight, (20 + nNotes * m_nGridWidth), m_nEditorHeight );
+}
+
+
+
+void DrumPatternEditor::paintEvent( QPaintEvent* /*ev*/ )
+{
+	//INFOLOG( "paint" );
+	//QWidget::paintEvent(ev);
+	
+	QPainter painter( this );
+	__draw_pattern( painter );
+}
+
+
+
+
+
+
+void DrumPatternEditor::showEvent ( QShowEvent *ev )
+{
+	UNUSED( ev );
+	updateEditor();
+}
+
+
+
+void DrumPatternEditor::hideEvent ( QHideEvent *ev )
+{
+	UNUSED( ev );
+}
+
+
+
+void DrumPatternEditor::setResolution(uint res, bool bUseTriplets)
+{
+	this->m_nResolution = res;
+	this->m_bUseTriplets = bUseTriplets;
+
+	// redraw all
+	update( 0, 0, width(), height() );
+	m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
+	m_pPatternEditorPanel->getPanEditor()->updateEditor();
+	m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
+	m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
+	/// \todo [DrumPatternEditor::setResolution] aggiornare la risoluzione del Ruler in alto."
+}
+
+
+
+void DrumPatternEditor::zoom_in()
+{
+	if (m_nGridWidth >= 3){
+		m_nGridWidth *= 2;
+	}else
+	{
+		m_nGridWidth *= 1.5;
+	}
+	updateEditor();
+}
+
+
+
+void DrumPatternEditor::zoom_out()
+{
+	if ( m_nGridWidth > 1.5 ) {
+		if (m_nGridWidth > 3){
+			m_nGridWidth /= 2;
+		}else
+		{
+			m_nGridWidth /= 1.5;
+		}
+		updateEditor();
+	}
+}
+
+void DrumPatternEditor::selectedInstrumentChangedEvent()
+{
+	update( 0, 0, width(), height() );
+}
+
+
+/// This method is called from another thread (audio engine)
+void DrumPatternEditor::patternModifiedEvent()
+{
+	update( 0, 0, width(), height() );
+}
+
+
+void DrumPatternEditor::patternChangedEvent()
+{
+	updateEditor();
+}
+
+
+void DrumPatternEditor::selectedPatternChangedEvent()
+{
+	//cout << "selected pattern changed EVENT" << endl;
+	updateEditor();
+}
Index: /branches/tabbedInterface/gui/src/PatternEditor/NotePropertiesRuler.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternEditor/NotePropertiesRuler.cpp	(revision 1555)
+++ /branches/tabbedInterface/gui/src/PatternEditor/NotePropertiesRuler.cpp	(revision 1555)
@@ -0,0 +1,1250 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/note.h>
+using namespace H2Core;
+
+#include <cassert>
+
+#include "../HydrogenApp.h"
+
+#include "NotePropertiesRuler.h"
+#include "PatternEditorPanel.h"
+#include "DrumPatternEditor.h"
+#include "PianoRollEditor.h"
+
+NotePropertiesRuler::NotePropertiesRuler( QWidget *parent, PatternEditorPanel *pPatternEditorPanel, NotePropertiesMode mode )
+ : QWidget( parent )
+ , Object( "NotePropertiesRuler" )
+ , m_mode( mode )
+ , m_pPatternEditorPanel( pPatternEditorPanel )
+ , m_pPattern( NULL )
+{
+	//infoLog("INIT");
+	//setAttribute(Qt::WA_NoBackground);
+
+	m_nGridWidth = (Preferences::get_instance())->getPatternEditorGridWidth();
+	m_nEditorWidth = 20 + m_nGridWidth * ( MAX_NOTES * 4 );
+
+	if (m_mode == VELOCITY ) {
+		m_nEditorHeight = 100;
+	}
+	else if ( m_mode == PAN ) {
+		m_nEditorHeight = 100;
+	}
+	else if ( m_mode == LEADLAG ) {
+		m_nEditorHeight = 100;
+	}
+	else if ( m_mode == NOTEKEY ) {
+		m_nEditorHeight = 210;
+	}
+
+	resize( m_nEditorWidth, m_nEditorHeight );
+	setMinimumSize( m_nEditorWidth, m_nEditorHeight );
+
+	m_pBackground = new QPixmap( m_nEditorWidth, m_nEditorHeight );
+
+//m_pBackground->load("/patternEditor/Klaviaturklein.png");
+	updateEditor();
+	show();
+
+	HydrogenApp::get_instance()->addEventListener( this );
+}
+
+
+
+
+NotePropertiesRuler::~NotePropertiesRuler()
+{
+	//infoLog("DESTROY");
+}
+
+
+void NotePropertiesRuler::mousePressEvent(QMouseEvent *ev)
+{
+//	infoLog( "mousePressEvent()" );
+	if (m_pPattern == NULL) return;
+
+	DrumPatternEditor *pPatternEditor = m_pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if (pPatternEditor->isUsingTriplets()) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+	int width = (m_nGridWidth * 4 *  MAX_NOTES) / ( nBase * pPatternEditor->getResolution());
+	int x_pos = ev->x();
+	int column;
+	column = (x_pos - 20) + (width / 2);
+	column = column / width;
+	column = (column * 4 * MAX_NOTES) / ( nBase * pPatternEditor->getResolution() );
+	float val = height() - ev->y();
+	if (val > height()) {
+		val = height();
+	}
+	else if (val < 0.0) {
+		val = 0.0;
+	}
+	int keyval = val;
+	val = val / height();
+
+	int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+	Song *pSong = (Hydrogen::get_instance())->getSong();
+
+	std::multimap <int, Note*>::iterator pos;
+	for ( pos = m_pPattern->note_map.lower_bound( column ); pos != m_pPattern->note_map.upper_bound( column ); ++pos ) {
+		Note *pNote = pos->second;
+		assert( pNote );
+		assert( (int)pNote->get_position() == column );
+		if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+			continue;
+		}
+
+		if ( m_mode == VELOCITY && !pNote->get_noteoff() ) {
+			pNote->set_velocity( val );
+
+			char valueChar[100];
+			sprintf( valueChar, "%#.2f",  val);
+			HydrogenApp::get_instance()->setStatusBarMessage( QString("Set note velocity [%1]").arg( valueChar ), 2000 );
+		}
+		else if ( m_mode == PAN ){
+			float pan_L, pan_R;
+			if ( (ev->button() == Qt::MidButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::LeftButton) ) {
+				val = 0.5;
+			}
+			if ( val > 0.5 ) {
+				pan_L = 1.0 - val;
+				pan_R = 0.5;
+			}
+			else {
+				pan_L = 0.5;
+				pan_R = val;
+			}
+
+			pNote->set_pan_l( pan_L );
+			pNote->set_pan_r( pan_R );
+		}
+		else if ( m_mode == LEADLAG ){
+			if ( (ev->button() == Qt::MidButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::LeftButton) ) {
+				pNote->set_leadlag(0.0);
+			} else {
+				pNote->set_leadlag((val * -2.0) + 1.0);
+				char valueChar[100];
+				if (pNote->get_leadlag() < 0.0) {
+					sprintf( valueChar, "%.2f",  ( pNote->get_leadlag() * -5)); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
+					HydrogenApp::get_instance()->setStatusBarMessage( QString("Leading beat by: %1 ticks").arg( valueChar ), 2000 );
+				} else if (pNote->get_leadlag() > 0.0) {
+					sprintf( valueChar, "%.2f",  ( pNote->get_leadlag() * 5)); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
+					HydrogenApp::get_instance()->setStatusBarMessage( QString("Lagging beat by: %1 ticks").arg( valueChar ), 2000 );
+				} else {
+					HydrogenApp::get_instance()->setStatusBarMessage( QString("Note on beat"), 2000 );
+				}
+
+			}
+		}
+
+		else if ( m_mode == NOTEKEY ){
+			if ( (ev->button() == Qt::MidButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::LeftButton) ) {
+				;
+			} else {
+				//set the note hight
+				//QMessageBox::information ( this, "Hydrogen", trUtf8( "val: %1" ).arg(keyval)  );
+				if (keyval >= 6 && keyval <= 15 ){//note c
+					pNote->m_noteKey.m_key = H2Core::NoteKey::C;
+				}
+				if (keyval >= 16 && keyval <= 25 ){//note cis / cs
+					pNote->m_noteKey.m_key = H2Core::NoteKey::Cs;
+				}
+				if (keyval >= 26 && keyval <= 35 ){//note d
+					pNote->m_noteKey.m_key = H2Core::NoteKey::D;
+				}
+				if (keyval >= 36 && keyval <= 45 ){//note dis / ef
+					pNote->m_noteKey.m_key = H2Core::NoteKey::Ef;
+				}
+				if (keyval >= 46 && keyval <= 55 ){//note E
+					pNote->m_noteKey.m_key = H2Core::NoteKey::E;
+				}
+				if (keyval >= 56 && keyval <= 65 ){//note f
+					pNote->m_noteKey.m_key = H2Core::NoteKey::F;
+				}
+				if (keyval >= 66 && keyval <= 75 ){//note fis
+					pNote->m_noteKey.m_key = H2Core::NoteKey::Fs;
+				}
+				if (keyval >= 76 && keyval <= 85 ){//note g
+					pNote->m_noteKey.m_key = H2Core::NoteKey::G;
+				}
+				if (keyval >= 86 && keyval <= 95 ){//note gis / af
+					pNote->m_noteKey.m_key = H2Core::NoteKey::Af;
+				}
+				if (keyval >= 96 && keyval <= 105 ){//note a
+					pNote->m_noteKey.m_key = H2Core::NoteKey::A;
+				}
+				if (keyval >= 106 && keyval <= 115 ){//note his / bf
+					pNote->m_noteKey.m_key = H2Core::NoteKey::Bf;
+				}
+				if (keyval >= 116 && keyval <= 125 ){//note h / b
+					pNote->m_noteKey.m_key = H2Core::NoteKey::B;
+				}
+				
+				//set the note oktave 
+				if (keyval >= 135 && keyval <= 145 ){
+					pNote->m_noteKey.m_nOctave = -3;
+				}
+				else if( keyval >= 146 && keyval <= 155 ){
+					pNote->m_noteKey.m_nOctave = -2;
+				}
+				else if( keyval >= 156 && keyval <= 165 ){
+					pNote->m_noteKey.m_nOctave = -1;
+				}
+				else if( keyval >= 166 && keyval <= 175 ){
+					pNote->m_noteKey.m_nOctave = 0;
+				}
+				else if( keyval >= 176 && keyval <= 185 ){
+					pNote->m_noteKey.m_nOctave = 1;
+				}
+				else if( keyval >= 186 && keyval <= 195 ){
+					pNote->m_noteKey.m_nOctave = 2;
+				}
+				else if( keyval >= 196 && keyval <= 205 ){
+					pNote->m_noteKey.m_nOctave = 3;
+				}
+			}
+		}
+
+
+
+		pSong->__is_modified = true;
+		updateEditor();
+		break;
+	}
+		m_pPatternEditorPanel->getPianoRollEditor()->updateEditor();
+		pPatternEditor->updateEditor();
+}
+
+void NotePropertiesRuler::wheelEvent(QWheelEvent *ev)
+{
+//      infoLog( "mousePressEvent()" );
+	if (m_pPattern == NULL) return;
+
+	float delta;
+	if (ev->modifiers() == Qt::ControlModifier) {
+		delta = 0.01; // fine control
+	} else { 
+		delta = 0.05; // course control
+	}
+		
+	if ( ev->delta() < 0 ) {
+		delta = (delta * -1.0);
+	}
+
+	DrumPatternEditor *pPatternEditor = m_pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if (pPatternEditor->isUsingTriplets()) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+	int width = (m_nGridWidth * 4 *  MAX_NOTES) / ( nBase * pPatternEditor->getResolution());
+	int x_pos = ev->x();
+	int column;
+	column = (x_pos - 20) + (width / 2);
+	column = column / width;
+	column = (column * 4 * MAX_NOTES) / ( nBase * pPatternEditor->getResolution() );
+
+	int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+	Song *pSong = (Hydrogen::get_instance())->getSong();
+
+	std::multimap <int, Note*>::iterator pos;
+	for ( pos = m_pPattern->note_map.lower_bound( column ); pos != m_pPattern->note_map.upper_bound( column ); ++pos ) {
+		Note *pNote = pos->second;
+		assert( pNote );
+		assert( (int)pNote->get_position() == column );
+		if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+			continue;
+		}
+		if ( m_mode == VELOCITY && !pNote->get_noteoff() ) {
+			float val = pNote->get_velocity() + delta;
+			if (val > 1.0) {
+				val = 1.0;
+			}
+			else if (val < 0.0) {
+				val = 0.0;
+			}
+
+			pNote->set_velocity(val);
+
+			char valueChar[100];
+			sprintf( valueChar, "%#.2f",  val);
+			( HydrogenApp::get_instance() )->setStatusBarMessage( QString("Set note velocity [%1]").arg( valueChar ), 2000 );
+		}
+		else if ( m_mode == PAN ){
+			float pan_L, pan_R;
+
+			float val = (pNote->get_pan_r() - pNote->get_pan_l() + 0.5) + delta;
+			if (val > 1.0) {
+				val = 1.0;
+			}
+			else if (val < 0.0) {
+				val = 0.0;
+			}
+			if ( val > 0.5 ) {
+				pan_L = 1.0 - val;
+				pan_R = 0.5;
+			}
+			else {
+				pan_L = 0.5;
+				pan_R = val;
+			}
+
+			pNote->set_pan_l(pan_L);
+			pNote->set_pan_r(pan_R);
+		}
+		else if ( m_mode == LEADLAG ){
+			float val = (pNote->get_leadlag() - 1.0)/-2.0 + delta;
+			if (val > 1.0) {
+				val = 1.0;
+			}
+			else if (val < 0.0) {
+				val = 0.0;
+			}
+			pNote->set_leadlag((val * -2.0) + 1.0);
+			char valueChar[100];
+			if (pNote->get_leadlag() < 0.0) {
+				sprintf( valueChar, "%.2f",  ( pNote->get_leadlag() * -5)); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
+				HydrogenApp::get_instance()->setStatusBarMessage( QString("Leading beat by: %1 ticks").arg( valueChar ), 2000 );
+			} else if (pNote->get_leadlag() > 0.0) {
+				sprintf( valueChar, "%.2f",  ( pNote->get_leadlag() * 5)); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
+				HydrogenApp::get_instance()->setStatusBarMessage( QString("Lagging beat by: %1 ticks").arg( valueChar ), 2000 );
+			} else {
+				HydrogenApp::get_instance()->setStatusBarMessage( QString("Note on beat"), 2000 );
+			}
+		}
+
+		pSong->__is_modified = true;
+		updateEditor();
+		break;
+	}
+}
+
+
+ void NotePropertiesRuler::mouseMoveEvent( QMouseEvent *ev )
+{
+//	infoLog( "mouse move" );
+	mousePressEvent( ev );
+}
+
+
+
+void NotePropertiesRuler::paintEvent( QPaintEvent *ev)
+{
+	QPainter painter(this);
+	painter.drawPixmap( ev->rect(), *m_pBackground, ev->rect() );
+}
+
+
+
+void NotePropertiesRuler::createVelocityBackground(QPixmap *pixmap)
+{
+	if ( !isVisible() ) {
+		return;
+	}
+
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+
+	H2RGBColor valueColor(
+			(int)( pStyle->m_patternEditor_backgroundColor.getRed() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getGreen() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getBlue() * ( 1 - 0.3 ) )
+	);
+
+	QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
+	QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
+	QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
+	QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
+	QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
+
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	QColor horizLinesColor(
+			pStyle->m_patternEditor_backgroundColor.getRed() - 20,
+			pStyle->m_patternEditor_backgroundColor.getGreen() - 20,
+			pStyle->m_patternEditor_backgroundColor.getBlue() - 20
+	);
+
+	unsigned nNotes = MAX_NOTES;
+	if (m_pPattern) {
+		nNotes = m_pPattern->get_length();
+	}
+
+
+	QPainter p( pixmap );
+
+	p.fillRect( 0, 0, width(), height(), QColor(0,0,0) );
+	p.fillRect( 0, 0, 20 + nNotes * m_nGridWidth, height(), backgroundColor );
+
+
+	// vertical lines
+
+	DrumPatternEditor *pPatternEditor = m_pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if (pPatternEditor->isUsingTriplets()) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+
+	int n4th = 4 * MAX_NOTES / (nBase * 4);
+	int n8th = 4 * MAX_NOTES / (nBase * 8);
+	int n16th = 4 * MAX_NOTES / (nBase * 16);
+	int n32th = 4 * MAX_NOTES / (nBase * 32);
+	int n64th = 4 * MAX_NOTES / (nBase * 64);
+	int nResolution = pPatternEditor->getResolution();
+
+
+	if ( !pPatternEditor->isUsingTriplets() ) {
+
+		for (uint i = 0; i < nNotes + 1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % n4th) == 0 ) {
+				if (nResolution >= 4) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n8th) == 0 ) {
+				if (nResolution >= 8) {
+					p.setPen( QPen( res_2, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n16th) == 0 ) {
+				if (nResolution >= 16) {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n32th) == 0 ) {
+				if (nResolution >= 32) {
+					p.setPen( QPen( res_4, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n64th) == 0 ) {
+				if (nResolution >= 64) {
+					p.setPen( QPen( res_5, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+		}
+	}
+	else {	// Triplets
+		uint nCounter = 0;
+		int nSize = 4 * MAX_NOTES / (nBase * nResolution);
+
+		for (uint i = 0; i < nNotes + 1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % nSize) == 0) {
+				if ((nCounter % 3) == 0) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+				}
+				else {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+				}
+				p.drawLine(x, 0, x, m_nEditorHeight);
+				nCounter++;
+			}
+		}
+	}
+
+	p.setPen( horizLinesColor );
+	for (unsigned y = 0; y < m_nEditorHeight; y = y + (m_nEditorHeight / 10)) {
+		p.drawLine(20, y, 20 + nNotes * m_nGridWidth, y);
+	}
+
+	// draw velocity lines
+	if (m_pPattern != NULL) {
+		int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		Song *pSong = Hydrogen::get_instance()->getSong();
+
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); ++pos ) {
+			Note *pposNote = pos->second;
+			assert( pposNote );
+			uint pos = pposNote->get_position();
+
+			std::multimap <int, Note*>::iterator copos;
+			int xoffset = 0;
+			for ( copos = m_pPattern->note_map.lower_bound( pos ); copos != m_pPattern->note_map.upper_bound( pos ); ++copos ) {
+				Note *pNote = copos->second;
+				assert( pNote );
+				if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+					continue;
+				}
+
+				uint x_pos = 20 + pos * m_nGridWidth;
+	
+				uint line_end = height();
+	
+				uint velocity = (uint)(pNote->get_velocity() * height());
+				uint line_start = line_end - velocity;
+			
+				QColor centerColor = DrumPatternEditor::computeNoteColor( pNote->get_velocity() );
+	
+				int nLineWidth = 3;
+				p.fillRect( x_pos - 1 + xoffset, line_start, nLineWidth,  line_end - line_start , centerColor );
+				xoffset++;
+			}
+		}
+	}
+	p.setPen(res_1);
+	p.drawLine(0, 0, m_nEditorWidth, 0);
+	p.drawLine(0, m_nEditorHeight - 1, m_nEditorWidth, m_nEditorHeight - 1);
+}
+
+
+
+void NotePropertiesRuler::createPanBackground(QPixmap *pixmap)
+{
+	if ( !isVisible() ) {
+		return;
+	}
+
+
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+
+	//QColor backgroundColor( 255, 255, 255 );
+	QColor blackKeysColor( 240, 240, 240 );
+	QColor horizLinesColor(
+			pStyle->m_patternEditor_backgroundColor.getRed() - 20,
+			pStyle->m_patternEditor_backgroundColor.getGreen() - 20,
+			pStyle->m_patternEditor_backgroundColor.getBlue() - 20
+	);
+	H2RGBColor valueColor(
+			(int)( pStyle->m_patternEditor_backgroundColor.getRed() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getGreen() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getBlue() * ( 1 - 0.3 ) )
+	);
+
+	QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
+	QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
+	QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
+	QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
+	QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
+
+	QPainter p( pixmap );
+
+	p.fillRect( 0, 0, width(), height(), QColor(0, 0, 0) );
+
+	unsigned nNotes = MAX_NOTES;
+	if (m_pPattern) {
+		nNotes = m_pPattern->get_length();
+	}
+	p.fillRect( 0, 0, 20 + nNotes * m_nGridWidth, height(), backgroundColor );
+
+
+	// central line
+	p.setPen( horizLinesColor );
+	p.drawLine(0, height() / 2.0, m_nEditorWidth, height() / 2.0);
+
+
+
+	// vertical lines
+	DrumPatternEditor *pPatternEditor = m_pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if (pPatternEditor->isUsingTriplets()) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+
+	int n4th = 4 * MAX_NOTES / (nBase * 4);
+	int n8th = 4 * MAX_NOTES / (nBase * 8);
+	int n16th = 4 * MAX_NOTES / (nBase * 16);
+	int n32th = 4 * MAX_NOTES / (nBase * 32);
+	int n64th = 4 * MAX_NOTES / (nBase * 64);
+
+	int nResolution = pPatternEditor->getResolution();
+
+	if ( !pPatternEditor->isUsingTriplets() ) {
+
+		for (uint i = 0; i < nNotes +1 ; i++) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % n4th) == 0 ) {
+				if (nResolution >= 4) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n8th) == 0 ) {
+				if (nResolution >= 8) {
+					p.setPen( QPen( res_2, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n16th) == 0 ) {
+				if (nResolution >= 16) {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n32th) == 0 ) {
+				if (nResolution >= 32) {
+					p.setPen( QPen( res_4, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n64th) == 0 ) {
+				if (nResolution >= 64) {
+					p.setPen( QPen( res_5, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+		}
+	}
+	else {	// Triplets
+		uint nCounter = 0;
+		int nSize = 4 * MAX_NOTES / (nBase * nResolution);
+
+		for (uint i = 0; i < nNotes +1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % nSize) == 0) {
+				if ((nCounter % 3) == 0) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+				}
+				else {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+				}
+				p.drawLine(x, 0, x, m_nEditorHeight);
+				nCounter++;
+			}
+		}
+	}
+
+	if ( m_pPattern ) {
+		int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		Song *pSong = Hydrogen::get_instance()->getSong();
+
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); ++pos ) {
+			Note *pposNote = pos->second;
+			assert( pposNote );
+			uint pos = pposNote->get_position();
+
+			std::multimap <int, Note*>::iterator copos;
+			int xoffset = 0;
+			for ( copos = m_pPattern->note_map.lower_bound( pos ); copos != m_pPattern->note_map.upper_bound( pos ); ++copos ) {
+				Note *pNote = copos->second;
+				assert( pNote );
+				if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+					continue;
+				}
+
+				uint x_pos = 20 + pNote->get_position() * m_nGridWidth;
+
+	
+				QColor centerColor = DrumPatternEditor::computeNoteColor( pNote->get_velocity() );
+	
+				if (pNote->get_pan_r() == pNote->get_pan_l()) {
+					// pan value is centered - draw circle
+					int y_pos = (int)( height() * 0.5 );
+					p.setBrush(QColor( centerColor ));
+					p.drawEllipse( x_pos-4 + xoffset, y_pos-4, 8, 8);
+				} else {
+					int y_start = (int)( pNote->get_pan_l() * height() );
+					int y_end = (int)( height() - pNote->get_pan_r() * height() );
+	
+					int nLineWidth = 3;
+					p.fillRect( x_pos - 1 + xoffset, y_start, nLineWidth, y_end - y_start, QColor(  centerColor) );
+	
+					p.fillRect( x_pos - 1 + xoffset, ( height() / 2.0 ) - 2 , nLineWidth, 5, QColor(  centerColor ) );
+				}
+				xoffset++;
+			}
+		}
+	}
+
+	p.setPen(res_1);
+	p.drawLine(0, 0, m_nEditorWidth, 0);
+	p.drawLine(0, m_nEditorHeight - 1, m_nEditorWidth, m_nEditorHeight - 1);
+}
+
+void NotePropertiesRuler::createLeadLagBackground(QPixmap *pixmap) 
+{
+	if ( !isVisible() ) {   
+		return;
+	}
+ 
+ 
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	QColor blackKeysColor( 240, 240, 240 );
+	QColor horizLinesColor(
+			pStyle->m_patternEditor_backgroundColor.getRed() - 20,
+			pStyle->m_patternEditor_backgroundColor.getGreen() - 20,
+			pStyle->m_patternEditor_backgroundColor.getBlue() - 20
+	);
+	H2RGBColor valueColor(
+			(int)( pStyle->m_patternEditor_backgroundColor.getRed() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getGreen() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getBlue() * ( 1 - 0.3 ) )
+	);
+ 
+	QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
+	QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
+	QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
+	QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
+	QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
+ 
+	QPainter p( pixmap );
+ 
+	p.fillRect( 0, 0, width(), height(), QColor(0, 0, 0) );
+ 
+	unsigned nNotes = MAX_NOTES;
+	if (m_pPattern) {
+		nNotes = m_pPattern->get_length();
+	}
+	p.fillRect( 0, 0, 20 + nNotes * m_nGridWidth, height(), backgroundColor );
+ 
+ 
+	// central line
+	p.setPen( horizLinesColor );
+	p.drawLine(0, height() / 2.0, m_nEditorWidth, height() / 2.0);
+ 
+ 
+ 
+	// vertical lines
+	DrumPatternEditor *pPatternEditor = m_pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if (pPatternEditor->isUsingTriplets()) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+ 
+	int n4th = 4 * MAX_NOTES / (nBase * 4);
+	int n8th = 4 * MAX_NOTES / (nBase * 8);
+	int n16th = 4 * MAX_NOTES / (nBase * 16);
+	int n32th = 4 * MAX_NOTES / (nBase * 32);
+	int n64th = 4 * MAX_NOTES / (nBase * 64);
+ 
+	int nResolution = pPatternEditor->getResolution();
+ 
+	if ( !pPatternEditor->isUsingTriplets() ) {
+ 
+		for (uint i = 0; i < nNotes + 1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+ 
+			if ( (i % n4th) == 0 ) {
+				if (nResolution >= 4) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n8th) == 0 ) {
+				if (nResolution >= 8) {
+					p.setPen( QPen( res_2, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n16th) == 0 ) {
+				if (nResolution >= 16) {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n32th) == 0 ) {
+				if (nResolution >= 32) {
+					p.setPen( QPen( res_4, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n64th) == 0 ) {
+				if (nResolution >= 64) {
+					p.setPen( QPen( res_5, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+		}
+	}
+	else {  // Triplets
+		uint nCounter = 0;
+		int nSize = 4 * MAX_NOTES / (nBase * nResolution);
+ 
+		for (uint i = 0; i < nNotes + 1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+ 
+			if ( (i % nSize) == 0) {
+				if ((nCounter % 3) == 0) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+				}
+				else {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+				}
+				p.drawLine(x, 0, x, m_nEditorHeight);
+				nCounter++;
+			}
+		}
+	}
+ 
+	if ( m_pPattern ) {
+		int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		Song *pSong = Hydrogen::get_instance()->getSong();
+ 
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); ++pos ) {
+
+			Note *pposNote = pos->second;
+			assert( pposNote );
+			uint pos = pposNote->get_position();
+
+			std::multimap <int, Note*>::iterator copos;
+			int xoffset = 0;
+			for ( copos = m_pPattern->note_map.lower_bound( pos ); copos != m_pPattern->note_map.upper_bound( pos ); ++copos ) {
+				Note *pNote = copos->second;
+				assert( pNote );
+				if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+					continue;
+				}
+
+				uint x_pos = 20 + pNote->get_position() * m_nGridWidth;
+
+				int red1 = (int) (pNote->get_velocity() * 255);
+				int green1;
+				int blue1;
+				blue1 = ( 255 - (int) red1 )* .33;
+				green1 =  ( 255 - (int) red1 );
+	
+				if (pNote->get_leadlag() == 0) {
+				
+					// leadlag value is centered - draw circle
+					int y_pos = (int)( height() * 0.5 );
+					p.setBrush(QColor( 0 , 0 , 0 ));
+					p.drawEllipse( x_pos-4 + xoffset, y_pos-4, 8, 8);
+				} else {
+					int y_start = (int)( height() * 0.5 );
+					int y_end = y_start + ((pNote->get_leadlag()/2) * height());
+		
+					int nLineWidth = 3;
+					int red;
+					int green;
+					int blue = (int) (pNote->get_leadlag() * 255);
+					if (blue < 0)  {
+						red = blue *-1;
+						blue = (int) red * .33;
+						green = (int) red * .33;
+					} else {
+						red = (int) blue * .33;
+						green = (int) blue * .33;
+					}
+					p.fillRect( x_pos - 1 + xoffset, y_start, nLineWidth, y_end - y_start, QColor( red, green ,blue ) );
+		
+					p.fillRect( x_pos - 1 + xoffset, ( height() / 2.0 ) - 2 , nLineWidth, 5, QColor( red1, green1 ,blue1 ) );
+				}
+			xoffset++;
+ 			}
+		}
+	}
+ 
+	p.setPen(res_1);
+	p.drawLine(0, 0, m_nEditorWidth, 0);
+	p.drawLine(0, m_nEditorHeight - 1, m_nEditorWidth, m_nEditorHeight - 1);
+}
+
+
+
+void NotePropertiesRuler::createNoteKeyBackground(QPixmap *pixmap)
+{
+	if ( !isVisible() ) {
+		return;
+	}
+
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+
+	H2RGBColor valueColor(
+			(int)( pStyle->m_patternEditor_backgroundColor.getRed() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getGreen() * ( 1 - 0.3 ) ),
+			(int)( pStyle->m_patternEditor_backgroundColor.getBlue() * ( 1 - 0.3 ) )
+	);
+
+	QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
+	QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
+	QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
+	QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
+	QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
+
+	QColor backgroundColor( pStyle->m_patternEditor_backgroundColor.getRed(), pStyle->m_patternEditor_backgroundColor.getGreen(), pStyle->m_patternEditor_backgroundColor.getBlue() );
+	QColor horizLinesColor(
+			pStyle->m_patternEditor_backgroundColor.getRed() - 100,
+			pStyle->m_patternEditor_backgroundColor.getGreen() - 100,
+			pStyle->m_patternEditor_backgroundColor.getBlue() - 100
+	);
+
+	unsigned nNotes = MAX_NOTES;
+	if (m_pPattern) {
+		nNotes = m_pPattern->get_length();
+	}
+	QPainter p( pixmap );
+
+
+	p.fillRect( 0, 0, width(), height(), QColor(0,0,0) );
+	p.fillRect( 0, 0, 20 + nNotes * m_nGridWidth, height(), backgroundColor );
+
+
+	p.setPen( horizLinesColor );
+	for (unsigned y = 10; y < 80; y = y + 10 ) {
+		p.setPen( QPen( res_1, 1, Qt::DashLine ) );
+		if (y == 40) p.setPen( QPen( QColor(0,0,0), 1, Qt::SolidLine ) );
+		p.drawLine(20, y, 20 + nNotes * m_nGridWidth, y);
+/*		if (y == 20 )p.drawText ( 5, y +2 , QString("O")); 
+		if (y == 30 )p.drawText ( 6, y +2 , QString("c"));
+		if (y == 40 )p.drawText ( 7, y +2 , QString("t"));
+		if (y == 50 )p.drawText ( 5, y +2 , QString("a")); 
+		if (y == 60 )p.drawText ( 6, y +2 , QString("v"));
+		if (y == 70 )p.drawText ( 6, y +2 , QString("e"));
+*/
+	}
+
+	for (unsigned y = 90; y < 210; y = y + 10 ) {
+		p.setPen( QPen( QColor( 255, 255, 255 ), 9, Qt::SolidLine, Qt::FlatCap) );
+		if ( y == 100 ||y == 120 ||y == 140 ||y == 170 ||y == 190) 
+			p.setPen( QPen( QColor( 0, 0, 0 ), 7, Qt::SolidLine, Qt::FlatCap ) ); 
+		p.drawLine(20, y, 20 + nNotes * m_nGridWidth, y);
+/*		if (y == 100 )p.drawText ( 5, y +2 , QString("H")); 
+		if (y == 110 )p.drawText ( 6, y +2 , QString("a"));
+		if (y == 120 )p.drawText ( 7, y +2 , QString("l"));
+		if (y == 130 )p.drawText ( 5, y +2 , QString("f"));
+		if (y == 150 )p.drawText ( 5, y +2 , QString("s")); 
+		if (y == 160 )p.drawText ( 6, y +2 , QString("t"));
+		if (y == 170 )p.drawText ( 7, y +2 , QString("e"));
+		if (y == 180 )p.drawText ( 5, y +2 , QString("p"));
+		if (y == 190 )p.drawText ( 5, y +2 , QString("s"));
+*/
+	}
+
+	// vertical lines
+	DrumPatternEditor *pPatternEditor = m_pPatternEditorPanel->getDrumPatternEditor();
+	int nBase;
+	if (pPatternEditor->isUsingTriplets()) {
+		nBase = 3;
+	}
+	else {
+		nBase = 4;
+	}
+
+	int n4th = 4 * MAX_NOTES / (nBase * 4);
+	int n8th = 4 * MAX_NOTES / (nBase * 8);
+	int n16th = 4 * MAX_NOTES / (nBase * 16);
+	int n32th = 4 * MAX_NOTES / (nBase * 32);
+	int n64th = 4 * MAX_NOTES / (nBase * 64);
+	int nResolution = pPatternEditor->getResolution();
+
+
+	if ( !pPatternEditor->isUsingTriplets() ) {
+
+		for (uint i = 0; i < nNotes + 1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % n4th) == 0 ) {
+				if (nResolution >= 4) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n8th) == 0 ) {
+				if (nResolution >= 8) {
+					p.setPen( QPen( res_2, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n16th) == 0 ) {
+				if (nResolution >= 16) {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n32th) == 0 ) {
+				if (nResolution >= 32) {
+					p.setPen( QPen( res_4, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+			else if ( (i % n64th) == 0 ) {
+				if (nResolution >= 64) {
+					p.setPen( QPen( res_5, 0, Qt::DotLine ) );
+					p.drawLine(x, 0, x, m_nEditorHeight);
+				}
+			}
+		}
+	}
+	else {	// Triplets
+		uint nCounter = 0;
+		int nSize = 4 * MAX_NOTES / (nBase * nResolution);
+
+		for (uint i = 0; i < nNotes + 1; i++) {
+			uint x = 20 + i * m_nGridWidth;
+
+			if ( (i % nSize) == 0) {
+				if ((nCounter % 3) == 0) {
+					p.setPen( QPen( res_1, 0, Qt::DotLine ) );
+				}
+				else {
+					p.setPen( QPen( res_3, 0, Qt::DotLine ) );
+				}
+				p.drawLine(x, 0, x, m_nEditorHeight);
+				nCounter++;
+			}
+		}
+	}
+
+
+	p.setPen(res_1);
+	p.drawLine(0, 0, m_nEditorWidth, 0);
+	p.drawLine(0, m_nEditorHeight - 1, m_nEditorWidth, m_nEditorHeight - 1);
+
+//paint the oktave	
+	if ( m_pPattern ) {
+		int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		Song *pSong = Hydrogen::get_instance()->getSong();
+ 
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); ++pos ) {
+			Note *pNote = pos->second;
+			assert( pNote );
+			if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+				continue;
+			}
+			
+			//check the note type
+			if ( !pNote->get_noteoff() ) {	
+				uint x_pos = 20 + pNote->get_position() * m_nGridWidth;
+	
+				int oktave = 0;
+				if ( pNote ) oktave = pNote->m_noteKey.m_nOctave;
+	
+				if (pNote->m_noteKey.m_nOctave == -3){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 70-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_nOctave == -2){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 60-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_nOctave == -1){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 50-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_nOctave == 0){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 40-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_nOctave == 1){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 30-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_nOctave == 2){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 20-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_nOctave == 3){
+					p.setBrush(QColor( 99, 160, 233 ));
+					p.drawEllipse( x_pos-3, 10-3, 6, 6);
+				}
+			}
+		}
+	}
+
+//paint the note 
+	if ( m_pPattern ) {
+		int nSelectedInstrument = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		Song *pSong = Hydrogen::get_instance()->getSong();
+ 
+		std::multimap <int, Note*>::iterator pos;
+		for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); ++pos ) {
+			Note *pNote = pos->second;
+			assert( pNote );
+			if ( pNote->get_instrument() != pSong->get_instrument_list()->get( nSelectedInstrument ) ) {
+				continue;
+			}
+
+			if ( !pNote->get_noteoff() ) {
+				uint x_pos = 20 + pNote->get_position() * m_nGridWidth;
+	
+				int oktave = 0;
+				if ( pNote ) oktave = pNote->m_noteKey.m_nOctave;
+	
+				if (pNote->m_noteKey.m_key == 0 ){//note c
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 200-4, 8, 8);
+				}
+				if (pNote->m_noteKey.m_key == 1 ){//note cis
+					p.setBrush(QColor( 255, 255, 255  ));
+					p.drawEllipse( x_pos-3, 190-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_key == 2 ){//note d
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 180-4, 8, 8);
+				}
+				if (pNote->m_noteKey.m_key == 3 ){//note dis
+					p.setBrush(QColor( 255, 255, 255));
+					p.drawEllipse( x_pos-3, 170-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_key == 4 ){//note e
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 160-4, 8, 8);
+				}
+				if (pNote->m_noteKey.m_key == 5 ){//note f
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 150-4, 8, 8);
+				}
+				if (pNote->m_noteKey.m_key == 6 ){//note fis
+					p.setBrush(QColor( 255, 255, 255));
+					p.drawEllipse( x_pos-3, 140-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_key == 7 ){//note g
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 130-4, 8, 8);
+				}
+				if (pNote->m_noteKey.m_key == 8 ){//note gis
+					p.setBrush(QColor( 255, 255, 255));
+					p.drawEllipse( x_pos-3, 120-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_key == 9 ){//note a
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 110-4, 8, 8);
+				}
+				if (pNote->m_noteKey.m_key == 10 ){//note ais
+					p.setBrush(QColor( 255, 255, 255));
+					p.drawEllipse( x_pos-3, 100-3, 6, 6);
+				}
+				if (pNote->m_noteKey.m_key == 11 ){//note h
+					p.setBrush(QColor( 0, 0, 0));
+					p.drawEllipse( x_pos-4, 90-4, 8, 8);
+				}
+			}
+		}
+	}	
+}
+
+
+
+
+void NotePropertiesRuler::updateEditor()
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() ) ) {
+		m_pPattern = pPatternList->get( nSelectedPatternNumber );
+	}
+	else {
+		m_pPattern = NULL;
+	}
+
+
+	// update editor width
+	int editorWidth;
+	if ( m_pPattern ) {
+		editorWidth = 20 + m_pPattern->get_length() * m_nGridWidth;
+	}
+	else {
+		editorWidth =  20 + MAX_NOTES * m_nGridWidth;
+	}
+	resize( editorWidth, height() );
+		
+	delete m_pBackground;
+	m_pBackground = new QPixmap( editorWidth, m_nEditorHeight );
+
+	if ( m_mode == VELOCITY ) {
+		createVelocityBackground( m_pBackground );
+	}
+	else if ( m_mode == PAN ) {
+		createPanBackground( m_pBackground );
+	}
+	else if ( m_mode == LEADLAG ) {
+		createLeadLagBackground( m_pBackground );
+	}
+	else if ( m_mode == NOTEKEY ) {
+		createNoteKeyBackground( m_pBackground );
+	}
+
+	// redraw all
+	update();
+}
+
+
+
+void NotePropertiesRuler::zoomIn()
+{
+	if (m_nGridWidth >= 3){
+		m_nGridWidth *= 2;
+	}else
+	{
+		m_nGridWidth *= 1.5;
+	}
+	updateEditor();
+}
+
+
+
+void NotePropertiesRuler::zoomOut()
+{
+	if ( m_nGridWidth > 1.5 ) {
+		if (m_nGridWidth > 3){
+			m_nGridWidth /=  2;
+		}else
+		{
+			m_nGridWidth /= 1.5;
+		}
+	updateEditor();
+	}
+}
+
+
+void NotePropertiesRuler::selectedPatternChangedEvent()
+{
+	updateEditor();
+}
+
+
+
+void NotePropertiesRuler::selectedInstrumentChangedEvent()
+{
+	updateEditor();
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/Mixer/MixerLine.h
===================================================================
--- /branches/tabbedInterface/gui/src/Mixer/MixerLine.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/Mixer/MixerLine.h	(revision 377)
@@ -0,0 +1,295 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef MIXERLINE_H
+#define MIXERLINE_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+#include <hydrogen/globals.h>
+
+class Fader;
+class MasterFader;
+class PanFader;
+class Knob;
+class Button;
+class ToggleButton;
+class InstrumentPropertiesDialog;
+class InstrumentNameWidget;
+class LCDDisplay;
+class Rotary;
+
+#include "../widgets/PixmapWidget.h"
+
+
+class InstrumentNameWidget : public PixmapWidget
+{
+	Q_OBJECT
+	public:
+		InstrumentNameWidget(QWidget* parent);
+		~InstrumentNameWidget();
+
+		void setText(QString text);
+		QString text();
+
+		void mousePressEvent( QMouseEvent * e );
+		void mouseDoubleClickEvent( QMouseEvent * e );
+
+	signals:
+		void clicked();
+		void doubleClicked();
+
+	protected:
+		virtual void paintEvent(QPaintEvent *ev);
+
+	private:
+		int m_nWidgetWidth;
+		int m_nWidgetHeight;
+		QString m_sInstrName;
+		QFont m_mixerFont;
+};
+
+
+
+
+///
+/// A mixer strip
+///
+class MixerLine: public PixmapWidget
+{
+	Q_OBJECT
+	public:
+		MixerLine(QWidget* parent);
+		~MixerLine();
+
+		void updateMixerLine();
+
+		bool isMuteClicked();
+		void setMuteClicked(bool isClicked);
+
+		bool isSoloClicked();
+		void setSoloClicked(bool isClicked);
+
+		float getVolume();
+		void setVolume(float value);
+
+		void setPeak_L( float peak );
+		float getPeak_L();
+
+		void setPeak_R( float peak );
+		float getPeak_R();
+
+		void setName(QString name) {     m_pNameWidget->setText( name );        }
+		QString getName() {      return m_pNameWidget->text();        }
+
+		float getPan();
+		void setPan(float value);
+
+		int getActivity() {	return m_nActivity;	}
+		void setActivity( uint value ) {	m_nActivity = value;	}
+
+		void setPlayClicked( bool clicked );
+
+		void setFXLevel( uint nFX, float fValue );
+		float getFXLevel( uint nFX );
+
+		void setSelected( bool bIsSelected );
+
+	signals:
+		void muteBtnClicked(MixerLine *ref);
+		void soloBtnClicked(MixerLine *ref);
+		void volumeChanged(MixerLine *ref);
+		void instrumentNameClicked(MixerLine *ref);
+		void instrumentNameSelected(MixerLine *ref);
+		void noteOnClicked(MixerLine *ref);
+		void noteOffClicked(MixerLine *ref);
+		void panChanged(MixerLine *ref);
+		void knobChanged(MixerLine *ref, int nKnob);
+
+	public slots:
+		void click(Button *ref);
+		void rightClick(Button *ref);
+		void faderChanged(Fader *ref);
+		void panChanged(Rotary *ref);
+		void knobChanged(Knob *ref);
+		void nameClicked();
+		void nameSelected();
+
+	private:
+		uint m_nWidth;
+		uint m_nHeight;
+		bool m_bIsSelected;
+
+		uint m_nActivity;
+		uint m_nPeakTimer;
+		float m_fMaxPeak;
+		float m_nFalloff;
+		Fader *m_pFader;
+		Rotary *m_pPanRotary;
+		InstrumentNameWidget *m_pNameWidget;
+		ToggleButton *m_pMuteBtn;
+		ToggleButton *m_pSoloBtn;
+		Button *m_pPlaySampleBtn;
+		Button *m_pTriggerSampleLED;
+		Knob *m_pKnob[MAX_FX];
+
+		LCDDisplay *m_pPeakLCD;
+};
+
+
+
+
+class MasterMixerLine: public PixmapWidget
+{
+	Q_OBJECT
+	public:
+		MasterMixerLine(QWidget* parent);
+		~MasterMixerLine();
+
+		void updateMixerLine();
+
+		float getVolume();
+		void setVolume(float value);
+
+		void setPeak_L(float peak);
+		float getPeak_L();
+
+		void setPeak_R(float peak);
+		float getPeak_R();
+
+
+	signals:
+		void volumeChanged(MasterMixerLine *ref);
+
+
+	public slots:
+		void faderChanged(MasterFader * ref);
+		void rotaryChanged( Rotary *pRef );
+		void muteClicked(Button*);
+
+	private:
+		uint m_nWidth;
+		uint m_nHeight;
+
+		uint m_nPeakTimer;
+		float m_fMaxPeak;
+		float m_nFalloff;
+		Fader *m_pFader;
+		MasterFader *m_pMasterFader;
+
+		LCDDisplay *m_pPeakLCD;
+
+		Rotary *m_pSwingRotary;
+		Rotary *m_pHumanizeTimeRotary;
+		Rotary *m_pHumanizeVelocityRotary;
+
+		ToggleButton *m_pMuteBtn;
+};
+
+
+
+
+///
+/// Mixer strip for FX
+///
+class FxMixerLine: public PixmapWidget
+{
+	Q_OBJECT
+	public:
+		FxMixerLine(QWidget* parent);
+		~FxMixerLine();
+
+		float getVolume();
+		void setVolume(float value);
+
+		void setPeak_L(float peak);
+		float getPeak_L();
+
+		void setPeak_R(float peak);
+		float getPeak_R();
+
+		void setName(QString name) {     m_pNameWidget->setText( name );        }
+		QString getName() {      return m_pNameWidget->text();        }
+
+		bool isFxActive();
+		void setFxActive( bool active );
+
+	signals:
+		void volumeChanged( FxMixerLine *ref );
+		void instrumentNameClicked( FxMixerLine *ref );
+		void activeBtnClicked( FxMixerLine *ref );
+
+	public slots:
+		void click(Button *ref);
+		void faderChanged(Fader * ref);
+
+	private:
+		uint m_nWidth;
+		uint m_nHeight;
+
+		float m_fMaxPeak;
+		Fader *m_pFader;
+		InstrumentNameWidget *m_pNameWidget;
+		ToggleButton *activeBtn;
+
+		LCDDisplay *m_pPeakLCD;
+};
+
+
+
+
+class LadspaFXMixerLine : public PixmapWidget
+{
+	Q_OBJECT
+	public:
+		LadspaFXMixerLine(QWidget* parent);
+		~LadspaFXMixerLine();
+
+		bool isFxActive();
+		void setFxActive( bool active );
+		void setPeaks( float fPeak_L, float fPeak_R );
+		void getPeaks( float *fPeak_L, float *fPeak_R );
+		void setName( QString name );
+		float getVolume();
+		void setVolume( float value );
+
+	public slots:
+		void click(Button *ref);
+		void rotaryChanged(Rotary * ref);
+
+	signals:
+		void activeBtnClicked( LadspaFXMixerLine *ref );
+		void editBtnClicked( LadspaFXMixerLine *ref );
+		void volumeChanged( LadspaFXMixerLine *ref);
+
+	private:
+		float m_fMaxPeak;
+		ToggleButton *m_pActiveBtn;
+		Button *m_pEditBtn;
+		Rotary *m_pRotary;
+		LCDDisplay *m_pNameLCD;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/Mixer/Mixer.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/Mixer/Mixer.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/Mixer/Mixer.cpp	(revision 1244)
@@ -0,0 +1,796 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "Mixer.h"
+#include "MixerLine.h"
+
+#include "../Skin.h"
+#include "../HydrogenApp.h"
+#include "../LadspaFXProperties.h"
+#include "../InstrumentEditor/InstrumentEditorPanel.h"
+#include "../widgets/Button.h"
+#include "../widgets/PixmapWidget.h"
+
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/note.h>
+#include <hydrogen/fx/Effects.h>
+using namespace H2Core;
+
+#include <cassert>
+
+#define MIXER_STRIP_WIDTH	56
+#define MASTERMIXER_STRIP_WIDTH	126
+
+
+Mixer::Mixer( QWidget* pParent )
+ : QWidget( pParent )
+// : QWidget( pParent, Qt::WindowStaysOnTopHint )
+// : QWidget( pParent, Qt::Tool )
+ , Object( "Mixer" )
+{
+	setWindowTitle( trUtf8( "Mixer" ) );
+	setMaximumHeight( 284 );
+	setMinimumHeight( 284 );
+	setFixedHeight( 284 );
+	setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+// fader Panel
+	m_pFaderHBox = new QHBoxLayout();
+	m_pFaderHBox->setSpacing( 0 );
+	m_pFaderHBox->setMargin( 0 );
+
+	m_pFaderPanel = new QWidget( NULL );
+	m_pFaderPanel->resize( MIXER_STRIP_WIDTH * MAX_INSTRUMENTS, height() );
+
+	m_pFaderPanel->setLayout( m_pFaderHBox );
+
+	m_pFaderScrollArea = new QScrollArea( NULL );
+	m_pFaderScrollArea->setFrameShape( QFrame::NoFrame );
+	m_pFaderScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pFaderScrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
+	m_pFaderScrollArea->setMinimumWidth( MIXER_STRIP_WIDTH * 4 );
+	m_pFaderScrollArea->setWidget( m_pFaderPanel );
+
+	for ( uint i = 0; i < MAX_INSTRUMENTS; ++i ) {
+		m_pMixerLine[ i ] = NULL;
+	}
+
+//~ fader panel
+
+
+// fX frame
+	m_pFXFrame = new PixmapWidget( NULL );
+	m_pFXFrame->setFixedSize( 213, height() );
+	m_pFXFrame->setPixmap( "/mixerPanel/background_FX.png" );
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		m_pLadspaFXLine[nFX] = new LadspaFXMixerLine( m_pFXFrame );
+		m_pLadspaFXLine[nFX]->move( 13, 43 * nFX + 84 );
+		connect( m_pLadspaFXLine[nFX], SIGNAL( activeBtnClicked(LadspaFXMixerLine*) ), this, SLOT( ladspaActiveBtnClicked( LadspaFXMixerLine*) ) );
+		connect( m_pLadspaFXLine[nFX], SIGNAL( editBtnClicked(LadspaFXMixerLine*) ), this, SLOT( ladspaEditBtnClicked( LadspaFXMixerLine*) ) );
+		connect( m_pLadspaFXLine[nFX], SIGNAL( volumeChanged(LadspaFXMixerLine*) ), this, SLOT( ladspaVolumeChanged( LadspaFXMixerLine*) ) );
+	}
+
+	if ( Preferences::get_instance()->isFXTabVisible() ) {
+		m_pFXFrame->show();
+	}
+	else {
+		m_pFXFrame->hide();
+	}
+//~ fX frame
+
+
+// Master frame
+	m_pMasterLine = new MasterMixerLine( NULL );
+	m_pMasterLine->move( 0, 0 );
+	connect( m_pMasterLine, SIGNAL( volumeChanged(MasterMixerLine*) ), this, SLOT( masterVolumeChanged(MasterMixerLine*) ) );
+
+	m_pShowFXPanelBtn = new ToggleButton(
+			m_pMasterLine,
+			"/mixerPanel/showFX_on.png",
+			"/mixerPanel/showFX_off.png",
+			"/mixerPanel/showFX_over.png",
+			QSize(42, 13)
+	);
+	m_pShowFXPanelBtn->move( 67, 242 );
+	m_pShowFXPanelBtn->setPressed(false);
+	m_pShowFXPanelBtn->setToolTip( trUtf8( "Show FX panel" ) );
+	connect( m_pShowFXPanelBtn, SIGNAL(clicked(Button*)), this, SLOT( showFXPanelClicked(Button*)));
+	m_pShowFXPanelBtn->setPressed( Preferences::get_instance()->isFXTabVisible() );
+
+#ifndef LADSPA_SUPPORT
+	m_pShowFXPanelBtn->hide();
+#endif
+
+
+
+	m_pShowPeaksBtn = new ToggleButton(
+			m_pMasterLine,
+			"/mixerPanel/showPeaks_on.png",
+			"/mixerPanel/showPeaks_off.png",
+			"/mixerPanel/showPeaks_over.png",
+			QSize(42, 13)
+	);
+	m_pShowPeaksBtn->move( 67, 258 );
+	m_pShowPeaksBtn->setPressed( (Preferences::get_instance())->showInstrumentPeaks() );
+	m_pShowPeaksBtn->setToolTip( trUtf8( "Show instrument peaks" ) );
+	connect( m_pShowPeaksBtn, SIGNAL(clicked(Button*)), this, SLOT( showPeaksBtnClicked(Button*)));
+//~ Master frame
+
+
+
+
+	// LAYOUT!
+	QHBoxLayout *pLayout = new QHBoxLayout();
+	pLayout->setSpacing( 0 );
+	pLayout->setMargin( 0 );
+
+	pLayout->addWidget( m_pFaderScrollArea );
+	pLayout->addWidget( m_pFXFrame );
+	pLayout->addWidget( m_pMasterLine );
+	this->setLayout( pLayout );
+
+
+
+	m_pUpdateTimer = new QTimer( this );
+	connect( m_pUpdateTimer, SIGNAL( timeout() ), this, SLOT( updateMixer() ) );
+	m_pUpdateTimer->start(50);
+
+	HydrogenApp::get_instance()->addEventListener( this );
+}
+
+
+
+Mixer::~Mixer()
+{
+	m_pUpdateTimer->stop();
+}
+
+
+
+MixerLine* Mixer::createMixerLine()
+{
+	MixerLine *pMixerLine = new MixerLine( 0 );
+	pMixerLine->setVolume( 0.2 );
+	pMixerLine->setMuteClicked( false );
+	pMixerLine->setSoloClicked( false );
+
+	connect( pMixerLine, SIGNAL( noteOnClicked(MixerLine*) ), this, SLOT( noteOnClicked(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( noteOffClicked(MixerLine*) ), this, SLOT( noteOffClicked(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( muteBtnClicked(MixerLine*) ), this, SLOT( muteClicked(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( soloBtnClicked(MixerLine*) ), this, SLOT( soloClicked(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( volumeChanged(MixerLine*) ), this, SLOT( volumeChanged(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( instrumentNameClicked(MixerLine*) ), this, SLOT( nameClicked(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( instrumentNameSelected(MixerLine*) ), this, SLOT( nameSelected(MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( panChanged(MixerLine*) ), this, SLOT( panChanged( MixerLine*) ) );
+	connect( pMixerLine, SIGNAL( knobChanged(MixerLine*, int) ), this, SLOT( knobChanged( MixerLine*, int) ) );
+
+	return pMixerLine;
+}
+
+
+void Mixer::muteClicked(MixerLine* ref)
+{
+	int nLine = findMixerLineByRef(ref);
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+	bool isMuteClicked = ref->isMuteClicked();
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+
+	Instrument *pInstr = instrList->get(nLine);
+	pInstr->set_muted( isMuteClicked);
+	//(HydrogenApp::get_instance())->setSelectedInstrument(nLine);
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+void Mixer::soloClicked(MixerLine* ref)
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *pSong = pEngine->getSong();
+	InstrumentList *pInstrList = pSong->get_instrument_list();
+	int nInstruments = pInstrList->get_size();
+
+	int nLine = findMixerLineByRef(ref);
+	pEngine->setSelectedInstrumentNumber( nLine );
+	bool isSoloClicked = ref->isSoloClicked();
+
+	if (isSoloClicked) {
+		for ( int i = 0; i < nInstruments; ++i ) {
+			m_pMixerLine[i]->setSoloClicked( false );
+			m_pMixerLine[i]->setMuteClicked( true );
+			pInstrList->get( i )->set_muted( true );
+		}
+		m_pMixerLine[nLine]->setSoloClicked( true );
+		m_pMixerLine[nLine]->setMuteClicked( false );
+		pInstrList->get( nLine )->set_muted( false );
+	}
+	else {
+		for ( int i = 0; i < nInstruments; ++i ) {
+			m_pMixerLine[i]->setMuteClicked( false );
+			m_pMixerLine[i]->setSoloClicked( false );
+			pInstrList->get( i )->set_muted( false );
+		}
+	}
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+/// used in PatternEditorInstrumentList
+void Mixer::soloClicked(uint nLine)
+{
+	MixerLine * L = m_pMixerLine[ nLine ];
+	L->setSoloClicked( !L->isSoloClicked() );
+	soloClicked( L );
+// 	Hydrogen *pEngine = Hydrogen::get_instance();
+// 	Song *pSong = pEngine->getSong();
+// 	InstrumentList *pInstrList = pSong->get_instrument_list();
+// 	int nInstruments = pInstrList->get_size();
+// 
+// 	bool isSoloClicked = m_pMixerLine[ nLine ]->isSoloClicked();
+// 
+// 	if (!isSoloClicked) {
+// 		for ( int i = 0; i < nInstruments; i++ ) {
+// 			m_pMixerLine[i]->setSoloClicked( false );
+// 			m_pMixerLine[i]->setMuteClicked( true );
+// 			pInstrList->get( i )->set_muted( true );
+// 		}
+// 		m_pMixerLine[nLine]->setSoloClicked( true );
+// 		m_pMixerLine[nLine]->setMuteClicked( false );
+// 		pInstrList->get( nLine )->set_muted( false );
+// 	}
+// 	else {
+// 		for ( int i = 0; i < nInstruments; i++ ) {
+// 			m_pMixerLine[i]->setMuteClicked( false );
+// 			m_pMixerLine[i]->setSoloClicked( false );
+// 			pInstrList->get( i )->set_muted( false );
+// 		}
+// 	}
+
+}
+
+bool Mixer::isSoloClicked( uint n )
+{
+	if ( n >= MAX_INSTRUMENTS || m_pMixerLine[ n ] == NULL ) {
+		return false;
+	}
+	return m_pMixerLine[ n ]->isSoloClicked();
+}
+
+void Mixer::noteOnClicked( MixerLine* ref )
+{
+	int nLine = findMixerLineByRef( ref );
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+
+	const float fPitch = 0.0f;
+	Note *note = new Note( instrList->get(nLine), 0, 1.0, 0.5f, 0.5f, -1, fPitch );
+	AudioEngine::get_instance()->get_sampler()->note_on(note);
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+/// Play sample button, right-clicked (note off)
+ void Mixer::noteOffClicked( MixerLine* ref )
+{
+	int nLine = findMixerLineByRef( ref );
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+
+	const float fPitch = 0.0f;
+	Note *note = new Note( instrList->get( nLine ), 0, 1.0, 0.5, 0.5, -1, fPitch );
+	AudioEngine::get_instance()->get_sampler()->note_off(note);
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+uint Mixer::findMixerLineByRef(MixerLine* ref)
+{
+	for (uint i = 0; i < MAX_INSTRUMENTS; i++) {
+		if (m_pMixerLine[i] == ref) {
+			return i;
+		}
+	}
+	return 0;
+}
+
+
+
+void Mixer::volumeChanged(MixerLine* ref)
+{
+	int nLine = findMixerLineByRef(ref);
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+
+	Instrument *instr = instrList->get(nLine);
+
+	instr->set_volume( ref->getVolume() );
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+
+void Mixer::masterVolumeChanged(MasterMixerLine* ref)
+{
+	float volume = ref->getVolume();
+	Song *song = Hydrogen::get_instance()->getSong();
+	song->set_volume(volume);
+}
+
+
+
+void Mixer::updateMixer()
+{
+	Preferences *pPref = Preferences::get_instance();
+	bool bShowPeaks = pPref->showInstrumentPeaks();
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *pSong = pEngine->getSong();
+	InstrumentList *pInstrList = pSong->get_instrument_list();
+
+	uint nSelectedInstr = pEngine->getSelectedInstrumentNumber();
+
+	float fallOff = pPref->getMixerFalloffSpeed();
+
+	uint nMuteClicked = 0;
+	uint nInstruments = pInstrList->get_size();
+	for ( unsigned nInstr = 0; nInstr < MAX_INSTRUMENTS; ++nInstr ) {
+
+		if ( nInstr >= nInstruments ) {	// unused instrument! let's hide and destroy the mixerline!
+			if ( m_pMixerLine[ nInstr ] ) {
+				delete m_pMixerLine[ nInstr ];
+				m_pMixerLine[ nInstr ] = NULL;
+
+				int newWidth = MIXER_STRIP_WIDTH * nInstruments;
+				if ( m_pFaderPanel->width() != newWidth ) {
+					m_pFaderPanel->resize( newWidth, height() );
+				}
+			}
+			continue;
+		}
+		else {
+			if ( m_pMixerLine[ nInstr ] == NULL ) {
+				// the mixerline doesn't exists..I'll create a new one!
+				m_pMixerLine[ nInstr ] = createMixerLine();
+				m_pFaderHBox->addWidget( m_pMixerLine[ nInstr ] );
+
+				int newWidth = MIXER_STRIP_WIDTH * nInstruments;
+				if ( m_pFaderPanel->width() != newWidth ) {
+					m_pFaderPanel->resize( newWidth, height() );
+				}
+			}
+			MixerLine *pLine = m_pMixerLine[ nInstr ];
+
+			Instrument *pInstr = pInstrList->get( nInstr );
+			assert( pInstr );
+
+			float fNewPeak_L = pInstr->get_peak_l();
+			pInstr->set_peak_l( 0.0f );	// reset instrument peak
+
+			float fNewPeak_R = pInstr->get_peak_r();
+			pInstr->set_peak_r( 0.0f );	// reset instrument peak
+
+			float fNewVolume = pInstr->get_volume();
+			bool bMuted = pInstr->is_muted();
+
+			QString sName = pInstr->get_name();
+			float fPan_L = pInstr->get_pan_l();
+			float fPan_R = pInstr->get_pan_r();
+
+
+			// fader
+			float fOldPeak_L = pLine->getPeak_L();
+			float fOldPeak_R = pLine->getPeak_R();
+
+			if (!bShowPeaks) {
+				fNewPeak_L = 0.0f;
+				fNewPeak_R = 0.0f;
+			}
+
+			if ( fNewPeak_L >= fOldPeak_L) {	// LEFT peak
+				pLine->setPeak_L( fNewPeak_L );
+			}
+			else {
+				pLine->setPeak_L( fOldPeak_L / fallOff );
+			}
+			if ( fNewPeak_R >= fOldPeak_R) {	// Right peak
+				pLine->setPeak_R( fNewPeak_R );
+			}
+			else {
+				pLine->setPeak_R( fOldPeak_R / fallOff );
+			}
+
+			// fader position
+			pLine->setVolume( fNewVolume );
+
+			// mute
+			if ( bMuted ) {
+				nMuteClicked++;
+			}
+			pLine->setMuteClicked( bMuted );
+
+			// instr name
+			pLine->setName( sName );
+
+			// pan
+			float fPanValue = 0.0;
+			if (fPan_R == 1.0) {
+				fPanValue = 1.0 - (fPan_L / 2.0);
+			}
+			else {
+				fPanValue = fPan_R / 2.0;
+			}
+
+			pLine->setPan( fPanValue );
+
+			// activity
+			if ( pLine->getActivity() > 0 ) {
+				pLine->setActivity( m_pMixerLine[ nInstr ]->getActivity() - 30 );
+				pLine->setPlayClicked( true );
+			}
+			else {
+				pLine->setPlayClicked( false );
+			}
+
+			for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+				pLine->setFXLevel( nFX, pInstr->get_fx_level( nFX ) );
+			}
+
+			pLine->setSelected( nInstr == nSelectedInstr );
+
+			pLine->updateMixerLine();
+		}
+	}
+
+	if (nMuteClicked == nInstruments - 1 ) {
+		// find the not muted button
+		for (uint i = 0; i < nInstruments; i++) {
+			Instrument *instr = pInstrList->get(i);
+			if (instr->is_muted() == false) {
+				m_pMixerLine[i]->setSoloClicked(true);
+				break;
+			}
+		}
+	}
+	else {
+		for (uint i = 0; i < nInstruments; i++) {
+			m_pMixerLine[i]->setSoloClicked(false);
+		}
+	}
+
+
+	// update MasterPeak
+	float oldPeak_L = m_pMasterLine->getPeak_L();
+	float newPeak_L = pEngine->getMasterPeak_L();
+	pEngine->setMasterPeak_L(0.0);
+	float oldPeak_R = m_pMasterLine->getPeak_R();
+	float newPeak_R = pEngine->getMasterPeak_R();
+	pEngine->setMasterPeak_R(0.0);
+
+	if (!bShowPeaks) {
+		newPeak_L = 0.0;
+		newPeak_R = 0.0;
+	}
+
+	if (newPeak_L >= oldPeak_L) {
+		m_pMasterLine->setPeak_L( newPeak_L );
+	}
+	else {
+		m_pMasterLine->setPeak_L( oldPeak_L / fallOff );
+	}
+	if (newPeak_R >= oldPeak_R) {
+		m_pMasterLine->setPeak_R(newPeak_R);
+	}
+	else {
+		m_pMasterLine->setPeak_R( oldPeak_R / fallOff );
+	}
+
+
+
+
+	// set master fader position
+	float newVolume = pSong->get_volume();
+	float oldVolume = m_pMasterLine->getVolume();
+	if (oldVolume != newVolume) {
+		m_pMasterLine->setVolume(newVolume);
+	}
+	m_pMasterLine->updateMixerLine();
+
+
+#ifdef LADSPA_SUPPORT
+	// LADSPA
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		LadspaFX *pFX = Effects::get_instance()->getLadspaFX( nFX );
+		if ( pFX ) {
+			m_pLadspaFXLine[nFX]->setName( pFX->getPluginName() );
+			float fNewPeak_L = 0.0;
+			float fNewPeak_R = 0.0;
+
+			float fOldPeak_L = 0.0;
+			float fOldPeak_R = 0.0;
+			m_pLadspaFXLine[nFX]->getPeaks( &fOldPeak_L, &fOldPeak_R );
+
+			if (fNewPeak_L < fOldPeak_L)	fNewPeak_L = fOldPeak_L / fallOff;
+			if (fNewPeak_R < fOldPeak_R)	fNewPeak_R = fOldPeak_R / fallOff;
+			m_pLadspaFXLine[nFX]->setPeaks( fNewPeak_L, fNewPeak_R );
+			m_pLadspaFXLine[nFX]->setFxActive( pFX->isEnabled() );
+			m_pLadspaFXLine[nFX]->setVolume( pFX->getVolume() );
+		}
+		else {
+			m_pLadspaFXLine[nFX]->setName( "No plugin" );
+			m_pLadspaFXLine[nFX]->setFxActive( false );
+			m_pLadspaFXLine[nFX]->setVolume( 0.0 );
+		}
+	}
+	// ~LADSPA
+#endif
+}
+
+
+
+/// show event
+void Mixer::showEvent ( QShowEvent *ev )
+{
+	UNUSED( ev );
+	updateMixer();
+}
+
+
+
+/// hide event
+void Mixer::hideEvent ( QHideEvent *ev )
+{
+	UNUSED( ev );
+}
+
+
+
+void Mixer::nameClicked(MixerLine* ref)
+{
+	UNUSED( ref );
+	InstrumentEditorPanel::get_instance()->show();
+}
+
+
+
+void Mixer::nameSelected(MixerLine* ref)
+{
+	int nLine = findMixerLineByRef(ref);
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+void Mixer::panChanged(MixerLine* ref) {
+	float panValue = ref->getPan();
+
+	float pan_L;
+	float pan_R;
+
+	if (panValue >= 0.5) {
+		pan_L = (1.0 - panValue) * 2;
+		pan_R = 1.0;
+	}
+	else {
+		pan_L = 1.0;
+		pan_R = panValue * 2;
+	}
+
+	int nLine = findMixerLineByRef(ref);
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+
+	Instrument *instr = instrList->get(nLine);
+	instr->set_pan_l( pan_L );
+	instr->set_pan_r( pan_R );
+
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+void Mixer::knobChanged(MixerLine* ref, int nKnob) {
+	int nLine = findMixerLineByRef(ref);
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( nLine );
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	InstrumentList *instrList = song->get_instrument_list();
+	Instrument *pInstr = instrList->get(nLine);
+	pInstr->set_fx_level( ref->getFXLevel(nKnob), nKnob );
+	QString sInfo = trUtf8( "Set FX %1 level ").arg( nKnob + 1 );
+	( HydrogenApp::get_instance() )->setStatusBarMessage( sInfo+ QString( "[%1]" ).arg( ref->getFXLevel(nKnob), 0, 'f', 2 ), 2000 );
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber(nLine);
+}
+
+
+
+void Mixer::noteOnEvent( int nInstrument )
+{
+	if ( m_pMixerLine[ nInstrument ] ) {
+		m_pMixerLine[ nInstrument ]->setActivity( 100 );
+	}
+}
+
+
+
+void Mixer::resizeEvent ( QResizeEvent *ev )
+{
+	UNUSED( ev );
+/*
+	uint nMaster_X = width() - MASTERMIXER_STRIP_WIDTH;
+	int nFXFrameWidth = 213;
+
+	if ( m_pFXFrame->isVisible() ) {
+		int w = width() - MASTERMIXER_STRIP_WIDTH - nFXFrameWidth;
+		m_pFaderScrollArea->resize( w, m_nMixerHeight );
+	}
+	else {
+		int w = width() - MASTERMIXER_STRIP_WIDTH;
+		m_pFaderScrollArea->resize( w, m_nMixerHeight );
+	}
+
+	m_pFXFrame->move( nMaster_X - nFXFrameWidth, 0 );
+
+	m_pMasterLine->move( nMaster_X, 0);
+	m_pShowPeaksBtn->move( nMaster_X + 67, 242 );
+	m_pShowFXPanelBtn->move( nMaster_X + 67, 258 );
+
+	resize(width(), m_nMixerHeight);	// qt bug workaround
+*/
+}
+
+
+
+void Mixer::showFXPanelClicked(Button* ref)
+{
+	if ( ref->isPressed() ) {
+		m_pFXFrame->show();
+		Preferences::get_instance()->setFXTabVisible( true );
+	}
+	else {
+		m_pFXFrame->hide();
+		Preferences::get_instance()->setFXTabVisible( false );
+	}
+
+	resizeEvent( NULL ); 	// force an update
+}
+
+
+
+void Mixer::showPeaksBtnClicked(Button* ref)
+{
+	Preferences *pPref = Preferences::get_instance();
+
+	if ( ref->isPressed() ) {
+		pPref->setInstrumentPeaks( true );
+		( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Show instrument peaks = On"), 2000 );
+	}
+	else {
+		pPref->setInstrumentPeaks( false );
+		( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Show instrument peaks = Off"), 2000 );
+	}
+}
+
+
+
+void Mixer::ladspaActiveBtnClicked( LadspaFXMixerLine* ref )
+{
+#ifdef LADSPA_SUPPORT
+	bool bActive = ref->isFxActive();
+
+	//Hydrogen *engine = Hydrogen::get_instance();
+	//Song *song = engine->getSong();
+
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		if (ref == m_pLadspaFXLine[ nFX ] ) {
+			LadspaFX *pFX = Effects::get_instance()->getLadspaFX(nFX);
+			if (pFX) {
+				pFX->setEnabled( bActive );
+			}
+			break;
+		}
+	}
+#endif
+}
+
+
+
+void Mixer::ladspaEditBtnClicked( LadspaFXMixerLine *ref )
+{
+#ifdef LADSPA_SUPPORT
+
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		if (ref == m_pLadspaFXLine[ nFX ] ) {
+			HydrogenApp::get_instance()->getLadspaFXProperties(nFX)->hide();
+			HydrogenApp::get_instance()->getLadspaFXProperties(nFX)->show();
+		}
+	}
+	Hydrogen::get_instance()->getSong()->__is_modified = true;
+#endif
+}
+
+
+
+void Mixer::ladspaVolumeChanged( LadspaFXMixerLine* ref)
+{
+#ifdef LADSPA_SUPPORT
+	Song *pSong = (Hydrogen::get_instance() )->getSong();
+	pSong->__is_modified = true;
+
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		if (ref == m_pLadspaFXLine[ nFX ] ) {
+			LadspaFX *pFX = Effects::get_instance()->getLadspaFX(nFX);
+			if (pFX) {
+				pFX->setVolume( ref->getVolume() );
+				QString sInfo = trUtf8( "Set LADSPA FX ( %1 ) volume").arg( QString(pFX->getPluginName() ) );
+				HydrogenApp::get_instance()->setStatusBarMessage( sInfo+ QString( " [%1]" ).arg( ref->getVolume(), 0, 'f', 2 ), 2000 );
+			}
+		}
+	}
+#endif
+}
+
+
+
+
+void Mixer::getPeaksInMixerLine( uint nMixerLine, float& fPeak_L, float& fPeak_R )
+{
+	if ( nMixerLine < MAX_INSTRUMENTS ) {
+		fPeak_L = m_pMixerLine[ nMixerLine ]->getPeak_L();
+		fPeak_R = m_pMixerLine[ nMixerLine ]->getPeak_R();
+	}
+	else {
+		fPeak_L = 0;
+		fPeak_R = 0;
+	}
+}
Index: /branches/tabbedInterface/gui/src/Mixer/Mixer.h
===================================================================
--- /branches/tabbedInterface/gui/src/Mixer/Mixer.h	(revision 420)
+++ /branches/tabbedInterface/gui/src/Mixer/Mixer.h	(revision 420)
@@ -0,0 +1,103 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef MIXER_H
+#define MIXER_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+#include <hydrogen/globals.h>
+#include "../EventListener.h"
+
+class Button;
+class ToggleButton;
+class MixerLine;
+class FxMixerLine;
+class MasterMixerLine;
+class LadspaFXMixerLine;
+class PixmapWidget;
+
+class Mixer : public QWidget, public EventListener, public Object
+{
+	Q_OBJECT
+	public:
+		Mixer(QWidget* parent);
+		~Mixer();
+
+		void showEvent ( QShowEvent *ev );
+		void hideEvent ( QHideEvent *ev );
+		void resizeEvent ( QResizeEvent *ev );
+		void soloClicked(uint nLine);
+		bool isSoloClicked(uint nLine);
+
+		void getPeaksInMixerLine( uint nMixerLine, float& fPeak_L, float& fPeak_R );
+
+	public slots:
+		void noteOnClicked(MixerLine* ref);
+		void noteOffClicked(MixerLine* ref);
+		void muteClicked(MixerLine* ref);
+		void soloClicked(MixerLine* ref);
+		void volumeChanged(MixerLine* ref);
+		void panChanged(MixerLine* ref);
+		void knobChanged(MixerLine* ref, int nKnob);
+		void masterVolumeChanged(MasterMixerLine*);
+		void nameClicked(MixerLine* ref);
+		void nameSelected(MixerLine* ref);
+		void updateMixer();
+		void showFXPanelClicked(Button* ref);
+		void showPeaksBtnClicked(Button* ref);
+		void ladspaActiveBtnClicked( LadspaFXMixerLine* ref );
+		void ladspaEditBtnClicked( LadspaFXMixerLine *ref );
+		void ladspaVolumeChanged( LadspaFXMixerLine* ref);
+
+	private:
+		QHBoxLayout *m_pFaderHBox;
+		LadspaFXMixerLine *m_pLadspaFXLine[MAX_FX];
+
+		QScrollArea* m_pFaderScrollArea;
+		ToggleButton *m_pShowFXPanelBtn;
+		ToggleButton *m_pShowPeaksBtn;
+		MasterMixerLine *m_pMasterLine;
+
+		QWidget *m_pFaderPanel;
+		MixerLine *m_pMixerLine[MAX_INSTRUMENTS];
+
+		PixmapWidget *m_pFXFrame;
+
+		QTimer *m_pUpdateTimer;
+
+		uint findMixerLineByRef(MixerLine* ref);
+		MixerLine* createMixerLine();
+
+		// Implements EventListener interface
+		virtual void noteOnEvent( int nInstrument );
+		//~ Implements EventListener interface
+
+};
+
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/Mixer/MixerLine.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/Mixer/MixerLine.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/Mixer/MixerLine.cpp	(revision 1244)
@@ -0,0 +1,1145 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+
+#include <QPainter>
+
+#include "../InstrumentEditor/InstrumentEditor.h"
+#include "../widgets/Fader.h"
+#include "../HydrogenApp.h"
+#include "../Skin.h"
+#include "../widgets/Rotary.h"
+#include "../widgets/Button.h"
+#include "../widgets/LCD.h"
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/audio_engine.h>
+using namespace H2Core;
+
+#include "MixerLine.h"
+
+#define MIXERLINE_WIDTH			56
+#define MIXERLINE_HEIGHT		254
+#define MASTERMIXERLINE_WIDTH	126
+#define MASTERMIXERLINE_HEIGHT	284
+#define MIXERLINE_LABEL_H		115
+#define MASTERMIXERLINE_FADER_H	75
+
+using namespace H2Core;
+
+MixerLine::MixerLine(QWidget* parent)
+ : PixmapWidget( parent, "MixerLine" )
+{
+//	INFOLOG( "INIT" );
+
+	m_nWidth = MIXERLINE_WIDTH;
+	m_nHeight = MIXERLINE_HEIGHT;
+	m_fMaxPeak = 0.0;
+	m_nActivity = 0;
+	m_bIsSelected = false;
+	m_nPeakTimer = 0;
+
+	resize( m_nWidth, m_nHeight );
+	setFixedSize( m_nWidth, m_nHeight );
+
+	setPixmap( "/mixerPanel/mixerline_background.png" );
+
+	// Play sample button
+	m_pPlaySampleBtn = new Button(
+			this,
+			"/mixerPanel/btn_play_on.png",
+			"/mixerPanel/btn_play_off.png",
+			"/mixerPanel/btn_play_over.png",
+			QSize( 18, 13 )
+	);
+	m_pPlaySampleBtn->move( 8, 2 );
+	m_pPlaySampleBtn->setToolTip( trUtf8( "Play sample" ) );
+	connect(m_pPlaySampleBtn, SIGNAL(clicked(Button*)), this, SLOT(click(Button*)));
+	connect(m_pPlaySampleBtn, SIGNAL(rightClicked(Button*)), this, SLOT(rightClick(Button*)));
+
+	// Trigger sample LED
+	m_pTriggerSampleLED = new Button(
+			this,
+			"/mixerPanel/led_trigger_on.png",
+			"/mixerPanel/led_trigger_off.png",
+			"/mixerPanel/led_trigger_off.png",
+			QSize( 5, 13 )
+	);
+	m_pTriggerSampleLED->move( 26, 2 );
+	connect(m_pTriggerSampleLED, SIGNAL(clicked(Button*)), this, SLOT(click(Button*)));
+
+	// Mute button
+	m_pMuteBtn = new ToggleButton(
+			this,
+			"/mixerPanel/btn_mute_on.png",
+			"/mixerPanel/btn_mute_off.png",
+			"/mixerPanel/btn_mute_over.png",
+			QSize( 18, 13 )
+	);
+	m_pMuteBtn->move( 8, 17 );
+	m_pMuteBtn->setToolTip( trUtf8( "Mute" ) );
+	connect(m_pMuteBtn, SIGNAL(clicked(Button*)), this, SLOT(click(Button*)));
+
+	// Solo button
+	m_pSoloBtn = new ToggleButton(
+			this,
+			"/mixerPanel/btn_solo_on.png",
+			"/mixerPanel/btn_solo_off.png",
+			"/mixerPanel/btn_solo_over.png",
+			QSize( 18, 13 )
+	);
+	m_pSoloBtn->move( 30, 17);
+	m_pSoloBtn->setToolTip( trUtf8( "Solo" ) );
+	connect(m_pSoloBtn, SIGNAL(clicked(Button*)), this, SLOT(click(Button*)));
+
+	// pan rotary
+	m_pPanRotary = new Rotary( this, Rotary::TYPE_CENTER, trUtf8( "Pan" ), false, true);
+	m_pPanRotary->move( 14, 32 );
+	connect( m_pPanRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( panChanged(Rotary*) ) );
+
+	// FX send
+	uint y = 0;
+	for (uint i = 0; i < MAX_FX; i++) {
+		m_pKnob[i] = new Knob(this);
+		if ( (i % 2) == 0 ) {
+			m_pKnob[i]->move( 9, 63 + (20 * y) );
+		}
+		else {
+			m_pKnob[i]->move( 30, 63 + (20 * y) );
+			y++;
+		}
+		connect( m_pKnob[i], SIGNAL( valueChanged(Knob*) ), this, SLOT( knobChanged(Knob*) ) );
+	}
+
+	Preferences *pref = Preferences::get_instance();
+
+	QString family = pref->getMixerFontFamily();
+	int size = pref->getMixerFontPointSize();
+	QFont mixerFont( family, size );
+	float m_fFalloffTemp = pref->getMixerFalloffSpeed();
+	m_fFalloffTemp = (m_fFalloffTemp * 20) - 2;
+	m_nFalloff = (int)m_fFalloffTemp;
+
+	QPixmap textBackground;
+	bool ok = textBackground.load( Skin::getImagePath() + "/mixerPanel/mixerline_text_background.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	// instrument name widget
+	m_pNameWidget = new InstrumentNameWidget( this );
+	m_pNameWidget->move( 6, 128 );
+	m_pNameWidget->setToolTip( trUtf8( "Instrument name (double click to edit)" ) );
+	connect( m_pNameWidget, SIGNAL( doubleClicked () ), this, SLOT( nameClicked() ) );
+	connect( m_pNameWidget, SIGNAL( clicked () ), this, SLOT( nameSelected() ) );
+
+	// m_pFader
+	m_pFader = new Fader( this, false, false );
+	m_pFader->move( 23, 128 );
+	m_pFader->setMinValue( 0.0 );
+	m_pFader->setMaxValue( 1.5 );
+	connect( m_pFader, SIGNAL( valueChanged(Fader*) ), this, SLOT( faderChanged(Fader*) ) );
+
+
+	m_pPeakLCD = new LCDDisplay( this, LCDDigit::SMALL_BLUE, 4 );
+	m_pPeakLCD->move( 10, 106 );
+	m_pPeakLCD->setText( "0.00" );
+	QPalette lcdPalette;
+	lcdPalette.setColor( QPalette::Background, QColor( 49, 53, 61 ) );
+	m_pPeakLCD->setPalette( lcdPalette );
+}
+
+
+
+MixerLine::~MixerLine()
+{
+//	INFOLOG( "DESTROY" );
+	//delete m_pFader;
+}
+
+
+
+void MixerLine::updateMixerLine()
+{
+	if ( m_nPeakTimer > m_nFalloff ) {
+		if ( m_fMaxPeak > 0.05f ) {
+			m_fMaxPeak = m_fMaxPeak - 0.05f;
+		}
+		else {
+			m_fMaxPeak = 0.0f;
+			m_nPeakTimer = 0;
+		}
+		char tmp[20];
+		sprintf(tmp, "%#.2f", m_fMaxPeak );
+		m_pPeakLCD->setText(tmp);
+		if ( m_fMaxPeak > 1.0 ) {
+			m_pPeakLCD->setSmallRed();
+		}
+		else {
+			m_pPeakLCD->setSmallBlue();
+		}
+	}
+	m_nPeakTimer++;
+}
+
+
+
+void MixerLine::click(Button *ref) {
+	Song *song = (Hydrogen::get_instance())->getSong();
+
+	if (ref == m_pMuteBtn) {
+		song->__is_modified = true;
+		emit muteBtnClicked(this);
+	}
+	else if (ref == m_pSoloBtn) {
+		song->__is_modified = true;
+		emit soloBtnClicked(this);
+	}
+	else if (ref == m_pPlaySampleBtn) {
+		emit noteOnClicked(this);
+	}
+}
+
+
+
+void MixerLine::rightClick(Button *ref)
+{
+	if (ref == m_pPlaySampleBtn) {
+		emit noteOffClicked(this);
+	}
+
+}
+
+
+
+void MixerLine::faderChanged(Fader *ref)
+{
+	Song *song = (Hydrogen::get_instance())->getSong();
+	song->__is_modified = true;
+	emit volumeChanged(this);
+
+	char m_pFaderPos[100];
+	float value = ref->getValue();
+	sprintf( m_pFaderPos, "%#.2f",  value);
+	( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Set instrument volume [%1]" ).arg( m_pFaderPos ), 2000 );
+}
+
+
+
+bool MixerLine::isMuteClicked() {
+	return m_pMuteBtn->isPressed();
+}
+
+
+
+void MixerLine::setMuteClicked(bool isClicked) {
+	m_pMuteBtn->setPressed(isClicked);
+}
+
+
+
+bool MixerLine::isSoloClicked() {
+	return m_pSoloBtn->isPressed();
+}
+
+
+
+void MixerLine::setSoloClicked(bool isClicked) {
+	m_pSoloBtn->setPressed(isClicked);
+}
+
+
+
+float MixerLine::getVolume()
+{
+	return m_pFader->getValue();
+}
+
+
+
+void MixerLine::setVolume( float value )
+{
+	m_pFader->setValue( value );
+}
+
+
+
+void MixerLine::setPeak_L( float peak ) {
+	if (peak != getPeak_L() ) {
+		m_pFader->setPeak_L( peak );
+		if (peak > m_fMaxPeak) {
+			if ( peak < 0.1f ) {
+				peak = 0.0f;
+			}
+			char tmp[20];
+			sprintf(tmp, "%#.2f", peak);
+			m_pPeakLCD->setText( tmp );
+			if ( peak > 1.0 ) {
+				m_pPeakLCD->setSmallRed();
+			}
+			else {
+				m_pPeakLCD->setSmallBlue();
+			}
+			m_fMaxPeak = peak;
+			m_nPeakTimer = 0;
+		}
+	}
+}
+
+
+
+float MixerLine::getPeak_L() {
+	return m_pFader->getPeak_L();
+}
+
+
+
+void MixerLine::setPeak_R( float peak ) {
+	if (peak != getPeak_R() ) {
+		m_pFader->setPeak_R( peak );
+		if (peak > m_fMaxPeak) {
+			if ( peak < 0.1f ) {
+				peak = 0.0f;
+			}
+			char tmp[20];
+			sprintf(tmp, "%#.2f", peak);
+			m_pPeakLCD->setText( tmp );
+			if ( peak > 1.0 ) {
+				m_pPeakLCD->setSmallRed();
+			}
+			else {
+				m_pPeakLCD->setSmallBlue();
+			}
+			m_fMaxPeak = peak;
+			m_nPeakTimer = 0;
+		}
+	}
+}
+
+
+
+float MixerLine::getPeak_R() {
+	return m_pFader->getPeak_R();
+}
+
+
+
+
+
+void MixerLine::nameClicked() {
+	emit instrumentNameClicked(this);
+}
+
+
+
+void MixerLine::nameSelected() {
+	emit instrumentNameSelected(this);
+}
+
+
+
+
+
+void MixerLine::panChanged(Rotary *ref)
+{
+	Song *song = Hydrogen::get_instance()->getSong();
+	song->__is_modified = true;
+	emit panChanged( this );
+
+	float panValue = ref->getValue();
+	float pan_L, pan_R;
+	if (panValue > 0.5) {
+		pan_L = (1.0 - panValue) * 2.0;
+		pan_R = 1.0;
+	} else {
+		pan_L = 1.0;
+		pan_R = panValue * 2.0;
+	}
+
+	char m_pFaderPos[100];
+	sprintf( m_pFaderPos, "%#.2fL, %#.2fR",  pan_L, pan_R);
+	HydrogenApp::get_instance()->setStatusBarMessage( trUtf8( "Set instr. pan [%1]" ).arg( m_pFaderPos ), 2000 );
+
+	m_pPanRotary->setToolTip( QString("Pan ") + QString( m_pFaderPos ) );
+}
+
+
+
+float MixerLine::getPan()
+{
+	return m_pPanRotary->getValue();
+}
+
+
+
+void MixerLine::setPan(float fValue)
+{
+	if ( fValue != m_pPanRotary->getValue() ) {
+		m_pPanRotary->setValue( fValue );
+		float pan_L, pan_R;
+		if (fValue > 0.5) {
+			pan_L = (1.0 - fValue) * 2.0;
+			pan_R = 1.0;
+		} else {
+			pan_L = 1.0;
+			pan_R = fValue * 2.0;
+		}
+		char m_pFaderPos[100];
+		sprintf( m_pFaderPos, "Pan %#.2fL, %#.2fR",  pan_L, pan_R);
+		m_pPanRotary->setToolTip( QString( m_pFaderPos ) );
+	}
+}
+
+
+void MixerLine::setPlayClicked( bool clicked ) {
+	m_pTriggerSampleLED->setPressed( clicked );
+}
+
+
+void MixerLine::knobChanged(Knob* pRef)
+{
+//	infoLog( "knobChanged" );
+	for (uint i = 0; i < MAX_FX; i++) {
+		if (m_pKnob[i] == pRef) {
+			emit knobChanged( this, i );
+			break;
+		}
+	}
+}
+
+
+void MixerLine::setFXLevel( uint nFX, float fValue )
+{
+	if (nFX > MAX_FX) {
+		ERRORLOG( QString("[setFXLevel] nFX > MAX_FX (nFX=%1)").arg(nFX) );
+	}
+	m_pKnob[nFX]->setValue( fValue );
+}
+
+float MixerLine::getFXLevel(uint nFX)
+{
+	if (nFX > MAX_FX) {
+		ERRORLOG( QString("[setFXLevel] nFX > MAX_FX (nFX=%1)").arg(nFX) );
+	}
+	return m_pKnob[nFX]->getValue();
+}
+
+
+void MixerLine::setSelected( bool bIsSelected )
+{
+	if (m_bIsSelected == bIsSelected )	return;
+
+	m_bIsSelected = bIsSelected;
+	if (m_bIsSelected) {
+		setPixmap( "/mixerPanel/mixerline_background_on.png" );
+	}
+	else {
+		setPixmap( "/mixerPanel/mixerline_background.png" );
+	}
+
+}
+
+
+
+
+
+// ::::::::::::::::::::::::::::
+
+
+
+
+MasterMixerLine::MasterMixerLine(QWidget* parent)
+ : PixmapWidget( parent, "MasterMixerLine" )
+{
+	m_nWidth = MASTERMIXERLINE_WIDTH;
+	m_nHeight = MASTERMIXERLINE_HEIGHT;
+	m_nPeakTimer = 0;
+
+	setMinimumSize( m_nWidth, m_nHeight );
+	setMaximumSize( m_nWidth, m_nHeight );
+	resize( m_nWidth, m_nHeight );
+	QPalette defaultPalette;
+	defaultPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
+	this->setPalette( defaultPalette );
+
+	// Background image
+	setPixmap( "/mixerPanel/masterMixerline_background.png" );
+
+	Preferences *pref = Preferences::get_instance();
+	int size = pref->getMixerFontPointSize();
+	QString family = pref->getMixerFontFamily();
+	float m_fFalloffTemp = pref->getMixerFalloffSpeed();
+	m_fFalloffTemp = (m_fFalloffTemp * 20) - 2;
+	m_nFalloff = (int)m_fFalloffTemp;
+
+	m_pMasterFader = new MasterFader( this );
+	m_pMasterFader->setMin( 0.0 );
+	m_pMasterFader->setMax( 1.5 );
+	m_pMasterFader->move( 24, MASTERMIXERLINE_FADER_H );
+	connect( m_pMasterFader, SIGNAL( valueChanged(MasterFader*) ), this, SLOT( faderChanged(MasterFader*) ) );
+
+	QFont mixerFont( family, size );
+
+	m_pPeakLCD = new LCDDisplay( this, LCDDigit::SMALL_BLUE, 4 );
+	m_pPeakLCD->move( 23, 53 );
+	m_pPeakLCD->setText( "0.00" );
+	QPalette lcdPalette;
+	lcdPalette.setColor( QPalette::Background, QColor( 49, 53, 61 ) );
+	m_pPeakLCD->setPalette( lcdPalette );
+
+	m_pHumanizeVelocityRotary = new Rotary( this, Rotary::TYPE_NORMAL, trUtf8( "Humanize velocity" ), false, false );
+	m_pHumanizeVelocityRotary->move( 74, 88 );
+	connect( m_pHumanizeVelocityRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pHumanizeTimeRotary = new Rotary( this, Rotary::TYPE_NORMAL, trUtf8( "Humanize time" ), false, false );
+	m_pHumanizeTimeRotary->move( 74, 125 );
+	connect( m_pHumanizeTimeRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pSwingRotary = new Rotary( this,  Rotary::TYPE_NORMAL, trUtf8( "Swing" ), false, false );
+	m_pSwingRotary->move( 74, 162 );
+	connect( m_pSwingRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	// Mute btn
+	m_pMuteBtn = new ToggleButton(
+			this,
+			"/mixerPanel/master_mute_on.png",
+			"/mixerPanel/master_mute_off.png",
+			"/mixerPanel/master_mute_over.png",
+			QSize( 42, 13 )
+	);
+	m_pMuteBtn->move( 20, 32 );
+	connect( m_pMuteBtn, SIGNAL( clicked(Button*) ), this, SLOT( muteClicked(Button*) ) );
+
+}
+
+
+
+
+MasterMixerLine::~MasterMixerLine()
+{
+//	cout << "MixerLine destroy" << endl;
+	m_fMaxPeak = 0.0;
+}
+
+
+
+void MasterMixerLine::muteClicked(Button* pBtn)
+{
+	Hydrogen::get_instance()->getSong()->__is_muted = pBtn->isPressed();
+}
+
+
+
+void MasterMixerLine::faderChanged(MasterFader *ref)
+{
+	m_pMasterFader->setValue( ref->getValue() );
+
+	emit volumeChanged(this);
+
+	Song *song = Hydrogen::get_instance()->getSong();
+	song->__is_modified = true;
+
+	char m_pMasterFaderPos[100];
+	float value = ref->getValue();
+	sprintf( m_pMasterFaderPos, "%#.2f",  value);
+	( HydrogenApp::get_instance() )->setStatusBarMessage( trUtf8( "Set master volume [%1]" ).arg( m_pMasterFaderPos ), 2000 );
+}
+
+
+
+
+float MasterMixerLine::getVolume()
+{
+	return m_pMasterFader->getValue();
+}
+
+
+
+void MasterMixerLine::setVolume( float value )
+{
+	m_pMasterFader->setValue( value );
+}
+
+
+
+void MasterMixerLine::setPeak_L(float peak)
+{
+	if ( peak != getPeak_L() ) {
+		m_pMasterFader->setPeak_L(peak);
+		if (peak > m_fMaxPeak) {
+			if ( peak < 0.1f ) {
+				peak = 0.0f;
+			}
+			char tmp[20];
+			sprintf(tmp, "%#.2f", peak);
+			m_pPeakLCD->setText(tmp);
+			if ( peak > 1.0 ) {
+				m_pPeakLCD->setSmallRed();
+			}
+			else {
+				m_pPeakLCD->setSmallBlue();
+			}
+			m_fMaxPeak = peak;
+			m_nPeakTimer = 0;
+		}
+	}
+}
+
+
+
+
+float MasterMixerLine::getPeak_L() {
+	return m_pMasterFader->getPeak_L();
+}
+
+
+
+void MasterMixerLine::setPeak_R(float peak) {
+	if ( peak != getPeak_R() ) {
+		m_pMasterFader->setPeak_R(peak);
+		if (peak > m_fMaxPeak) {
+			if ( peak < 0.1f ) {
+				peak = 0.0f;
+			}
+			char tmp[20];
+			sprintf(tmp, "%#.2f", peak);
+			m_pPeakLCD->setText(tmp);
+			if ( peak > 1.0 ) {
+				m_pPeakLCD->setSmallRed();
+			}
+			else {
+				m_pPeakLCD->setSmallBlue();
+			}
+			m_fMaxPeak = peak;
+			m_nPeakTimer = 0;
+		}
+	}
+}
+
+
+
+float MasterMixerLine::getPeak_R() {
+	return m_pMasterFader->getPeak_R();
+}
+
+
+
+void MasterMixerLine::updateMixerLine()
+{
+
+	if ( m_nPeakTimer > m_nFalloff ) {
+		if ( m_fMaxPeak  > 0.05f ) {
+			m_fMaxPeak = m_fMaxPeak - 0.05f;
+		}
+		else {
+			m_fMaxPeak = 0.0f;
+			m_nPeakTimer = 0;
+		}
+		char tmp[20];
+		sprintf(tmp, "%#.2f", m_fMaxPeak );
+		m_pPeakLCD->setText(tmp);
+		if ( m_fMaxPeak > 1.0 ) {
+			m_pPeakLCD->setSmallRed();
+		}
+		else {
+			m_pPeakLCD->setSmallBlue();
+		}
+	}
+	m_nPeakTimer++;
+
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	if ( pSong ) {
+		m_pHumanizeTimeRotary->setValue( pSong->get_humanize_time_value() );
+		m_pHumanizeVelocityRotary->setValue( pSong->get_humanize_velocity_value() );
+		m_pSwingRotary->setValue( pSong->get_swing_factor() );
+	}
+	else {
+		WARNINGLOG( "pSong == NULL ");
+	}
+}
+
+
+void MasterMixerLine::rotaryChanged( Rotary *pRef )
+{
+	QString sMsg;
+	float fVal = pRef->getValue();
+	char sVal[100];
+	sprintf( sVal, "%#.2f", fVal);
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+	if ( pRef == m_pHumanizeTimeRotary ) {
+		pEngine->getSong()->set_humanize_time_value( fVal );
+		sMsg = trUtf8( "Set humanize time parameter [%1]").arg( sVal );
+	}
+	else if ( pRef == m_pHumanizeVelocityRotary ) {
+		pEngine->getSong()->set_humanize_velocity_value( fVal );
+		sMsg = trUtf8( "Set humanize velocity parameter [%1]").arg( sVal );
+	}
+	else if ( pRef == m_pSwingRotary ) {
+		pEngine->getSong()->set_swing_factor( fVal );
+		sMsg = trUtf8( "Set swing factor [%1]").arg( sVal );
+	}
+	else {
+		ERRORLOG( "[knobChanged] Unhandled knob" );
+	}
+
+	AudioEngine::get_instance()->unlock();
+
+	( HydrogenApp::get_instance() )->setStatusBarMessage( sMsg, 2000 );
+}
+
+
+
+
+/////////////////////////////////////////
+
+
+FxMixerLine::FxMixerLine(QWidget* parent)
+ : PixmapWidget( parent, "FxMixerLine" )
+{
+	m_nWidth = MIXERLINE_WIDTH;
+	m_nHeight = MIXERLINE_HEIGHT;
+
+	setMinimumSize( m_nWidth, m_nHeight );
+	setMaximumSize( m_nWidth, m_nHeight );
+	resize( m_nWidth, m_nHeight );
+//	QPalette defaultPalette;
+//	defaultPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
+//	this->setPalette( defaultPalette );
+	m_fMaxPeak = 0.0;
+
+	// MixerLine Background image
+	setPixmap( "/mixerPanel/mixerline_background.png" );
+
+	// MixerLine LABEL Background image
+//	QPixmap mixerLineLabelBackground;
+//	ok = mixerLineLabelBackground.load(Skin::getImagePath() + "/mixerPanel/mixerline_label_background.png");
+//	if( ok == false ){
+//		ERRORLOG( "Error loading pixmap" );
+//	}
+
+//	QPixmap textBackground;
+//	ok = textBackground.load( Skin::getImagePath() + "/mixerPanel/mixerline_text_background.png" );
+//	if( ok == false ){
+//		ERRORLOG( "Error loading pixmap" );
+//	}
+
+
+	// active button
+	activeBtn = new ToggleButton(
+			this,
+			"/mixerPanel/btn_on_on.png",
+			"/mixerPanel/btn_on_off.png",
+			"/mixerPanel/btn_on_over.png",
+			QSize( 18, 12 )
+	);
+	activeBtn->move( 2, 5 );
+	activeBtn->setToolTip( trUtf8( "FX on/off") );
+	connect( activeBtn, SIGNAL( clicked(Button*) ), this, SLOT( click(Button*) ) );
+
+	Preferences *pref = Preferences::get_instance();
+
+	// m_pFader
+	m_pFader = new Fader( this, false, false );
+	m_pFader->move( 22, 106 );
+	connect( m_pFader, SIGNAL( valueChanged(Fader*) ), this, SLOT( faderChanged(Fader*) ) );
+
+	QString family = pref->getMixerFontFamily();
+	int size = pref->getMixerFontPointSize();
+	QFont mixerFont( family, size );
+
+
+	m_pNameWidget = new InstrumentNameWidget( this );
+	m_pNameWidget->move( 2, 106 );
+	m_pNameWidget->setText( trUtf8( "Master output" ) );
+
+	m_pPeakLCD = new LCDDisplay( this, LCDDigit::SMALL_BLUE, 4 );
+	m_pPeakLCD->move( 2, MIXERLINE_LABEL_H );
+	m_pPeakLCD->setText( "0.00" );
+}
+
+
+
+FxMixerLine::~FxMixerLine()
+{
+	delete m_pFader;
+}
+
+
+
+void FxMixerLine::click(Button *ref) {
+	Song *song = Hydrogen::get_instance()->getSong();
+
+	if (ref == activeBtn ) {
+		song->__is_modified = true;
+		emit activeBtnClicked( this );
+	}
+}
+
+
+
+void FxMixerLine::faderChanged(Fader *ref)
+{
+	UNUSED( ref );
+
+	m_fMaxPeak = 0.0;
+	char tmp[20];
+	sprintf( tmp, "%#.2f", m_fMaxPeak );
+	m_pPeakLCD->setText( tmp );
+	if ( m_fMaxPeak > 1.0 ) {
+		m_pPeakLCD->setSmallRed();
+	}
+	else {
+		m_pPeakLCD->setSmallBlue();
+	}
+
+
+	Song *song = Hydrogen::get_instance()->getSong();
+	song->__is_modified = true;
+	emit volumeChanged( this );
+
+}
+
+
+
+float FxMixerLine::getVolume()
+{
+	return m_pFader->getValue();
+}
+
+
+
+void FxMixerLine::setVolume( float value )
+{
+	m_pFader->setValue( value );
+}
+
+
+
+void FxMixerLine::setPeak_L( float peak )
+{
+	if (peak != getPeak_L() ) {
+		m_pFader->setPeak_L( peak );
+		if (peak > m_fMaxPeak) {
+			char tmp[20];
+			sprintf(tmp, "%#.2f", peak);
+			m_pPeakLCD->setText(tmp);
+			if ( peak > 1.0 ) {
+				m_pPeakLCD->setSmallRed();
+			}
+			else {
+				m_pPeakLCD->setSmallBlue();
+			}
+
+			m_fMaxPeak = peak;
+		}
+	}
+}
+
+
+
+float FxMixerLine::getPeak_L()
+{
+	return m_pFader->getPeak_L();
+}
+
+
+
+
+void FxMixerLine::setPeak_R(float peak)
+{
+	if (peak != getPeak_R() ) {
+		m_pFader->setPeak_R( peak );
+		if (peak > m_fMaxPeak) {
+			char tmp[20];
+			sprintf(tmp, "%#.2f", peak);
+			m_pPeakLCD->setText(tmp);
+			if ( peak > 1.0 ) {
+				m_pPeakLCD->setSmallRed();
+			}
+			else {
+				m_pPeakLCD->setSmallBlue();
+			}
+
+			m_fMaxPeak = peak;
+		}
+	}
+}
+
+
+
+
+float FxMixerLine::getPeak_R()
+{
+	return m_pFader->getPeak_R();
+}
+
+
+
+
+bool FxMixerLine::isFxActive()
+{
+	return activeBtn->isPressed();
+}
+
+
+
+
+void FxMixerLine::setFxActive( bool active )
+{
+	activeBtn->setPressed( active );
+}
+
+
+
+
+
+
+////////////////////////////////
+
+//QPixmap* InstrumentNameWidget::m_pBackground = NULL;
+
+
+InstrumentNameWidget::InstrumentNameWidget(QWidget* parent)
+ : PixmapWidget( parent, "InstrumentNameWidget" )
+{
+//	infoLog( "INIT" );
+	m_nWidgetWidth = 17;
+	m_nWidgetHeight = 116;
+
+	Preferences *pref = Preferences::get_instance();
+	QString family = pref->getMixerFontFamily();
+	int size = pref->getMixerFontPointSize();
+	m_mixerFont.setFamily( family );
+	m_mixerFont.setPointSize( size );
+//	m_mixerFont.setBold( true );
+//	m_mixerFont.setItalic( true );
+
+	setPixmap( "/mixerPanel/mixerline_label_background.png" );
+
+	this->resize( m_nWidgetWidth, m_nWidgetHeight );
+}
+
+
+
+
+InstrumentNameWidget::~InstrumentNameWidget()
+{
+//	infoLog( "DESTROY" );
+}
+
+
+
+void InstrumentNameWidget::paintEvent( QPaintEvent* ev )
+{
+	PixmapWidget::paintEvent( ev );
+
+	QPainter p( this );
+
+	p.setPen( QColor(230, 230, 230) );
+	p.setFont( m_mixerFont );
+	p.rotate( -90 );
+	p.drawText( -m_nWidgetHeight + 5, 0, m_nWidgetHeight - 10, m_nWidgetWidth, Qt::AlignVCenter, m_sInstrName );
+}
+
+
+
+
+void InstrumentNameWidget::setText( QString text )
+{
+	if (m_sInstrName != text ) {
+		m_sInstrName = text;
+		update();
+	}
+}
+
+
+
+QString InstrumentNameWidget::text()
+{
+	return m_sInstrName;
+}
+
+
+
+void InstrumentNameWidget::mousePressEvent( QMouseEvent * e )
+{
+	UNUSED( e );
+	emit clicked();
+}
+
+
+
+void InstrumentNameWidget::mouseDoubleClickEvent( QMouseEvent * e )
+{
+	UNUSED( e );
+	emit doubleClicked();
+}
+
+
+
+// :::::::::::::::::::::
+
+
+
+LadspaFXMixerLine::LadspaFXMixerLine(QWidget* parent)
+ : PixmapWidget( parent, "LadspaFXMixerLine" )
+{
+	resize( 194, 43 );
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	setPixmap( "/mixerPanel/fxline_background.png" );
+
+	// active button
+	m_pActiveBtn = new ToggleButton(
+			this,
+			"/mixerPanel/bypass_on.png",
+			"/mixerPanel/bypass_off.png",
+			"/mixerPanel/bypass_over.png",
+			QSize( 30, 13 )
+	);
+	m_pActiveBtn->move( 55, 25 );
+	m_pActiveBtn->setToolTip( trUtf8( "FX bypass") );
+	connect( m_pActiveBtn, SIGNAL( clicked(Button*) ), this, SLOT( click(Button*) ) );
+
+	// edit button
+	m_pEditBtn = new Button(
+			this,
+			"/mixerPanel/edit_on.png",
+			"/mixerPanel/edit_off.png",
+			"/mixerPanel/edit_over.png",
+			QSize( 30, 13 )
+	);
+	m_pEditBtn->move( 87, 25 );
+	m_pEditBtn->setToolTip( trUtf8( "Edit FX parameters") );
+	connect( m_pEditBtn, SIGNAL( clicked(Button*) ), this, SLOT( click(Button*) ) );
+
+	// instrument name widget
+	m_pNameLCD = new LCDDisplay( this, LCDDigit::SMALL_BLUE, 13 );
+	m_pNameLCD->move( 11, 9 );
+	m_pNameLCD->setText( "No name" );
+	m_pNameLCD->setToolTip( trUtf8( "Ladspa FX name" ) );
+
+	// m_pRotary
+	m_pRotary = new Rotary( this,  Rotary::TYPE_NORMAL, trUtf8( "Effect return" ), false, false );
+	m_pRotary->move( 132, 4 );
+	connect( m_pRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+}
+
+
+
+LadspaFXMixerLine::~LadspaFXMixerLine()
+{
+//	infoLog( "DESTROY" );
+}
+
+
+
+void LadspaFXMixerLine::setName(QString name)
+{
+	m_pNameLCD->setText( name );
+}
+
+void LadspaFXMixerLine::click(Button *ref)
+{
+	if ( ref == m_pActiveBtn ) {
+		emit activeBtnClicked( this );
+	}
+	else if( ref == m_pEditBtn ) {
+		emit editBtnClicked( this );
+	}
+}
+
+
+
+bool LadspaFXMixerLine::isFxActive()
+{
+	return !m_pActiveBtn->isPressed();
+}
+
+
+
+
+void LadspaFXMixerLine::setFxActive( bool active )
+{
+	m_pActiveBtn->setPressed( !active );
+}
+
+
+
+void LadspaFXMixerLine::rotaryChanged(Rotary *ref)
+{
+	UNUSED( ref );
+	m_fMaxPeak = 0.0;
+//	char tmp[20];
+//	sprintf(tmp, "%#.1f", fMaxPeak);
+//	m_pVolumeLbl->setText(tmp);
+
+	Song *song = Hydrogen::get_instance()->getSong();
+	song->__is_modified = true;
+	emit volumeChanged(this);
+}
+
+
+
+void LadspaFXMixerLine::setPeaks( float fPeak_L, float fPeak_R )
+{
+	UNUSED( fPeak_L );
+	UNUSED( fPeak_R );
+/*
+	m_pPeakmeter->setPeak_L( fPeak_L );
+	m_pPeakmeter->setPeak_R( fPeak_R );
+	m_pPeakmeter->updateFader();
+*/
+}
+
+
+
+void LadspaFXMixerLine::getPeaks( float *fPeak_L, float *fPeak_R )
+{
+	UNUSED( fPeak_L );
+	UNUSED( fPeak_R );
+/*
+	(*fPeak_L) = m_pFader->getPeak_L();
+	(*fPeak_R) = m_pFader->getPeak_R();
+*/
+}
+
+
+
+float LadspaFXMixerLine::getVolume()
+{
+	return m_pRotary->getValue();
+}
+
+
+
+void LadspaFXMixerLine::setVolume(float value)
+{
+	m_pRotary->setValue( value );
+// 	m_pRotary->updateRotary();
+}
Index: /branches/tabbedInterface/gui/src/LadspaFXSelector.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/LadspaFXSelector.cpp	(revision 1367)
+++ /branches/tabbedInterface/gui/src/LadspaFXSelector.cpp	(revision 1367)
@@ -0,0 +1,291 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "LadspaFXSelector.h"
+#include "HydrogenApp.h"
+#include <hydrogen/hydrogen.h>
+#include "Skin.h"
+#include <hydrogen/Song.h>
+#include <hydrogen/Preferences.h>
+
+#include <hydrogen/fx/Effects.h>
+#include <hydrogen/fx/LadspaFX.h>
+
+using namespace std;
+using namespace H2Core;
+
+LadspaFXSelector::LadspaFXSelector(int nLadspaFX)
+ : QDialog( NULL )
+ , Object( "LadspaFXSelector" )
+ , m_pCurrentItem( NULL )
+{
+	//INFOLOG( "INIT" );
+
+	setupUi( this );
+
+	setFixedSize( width(), height() );
+
+	setWindowTitle( trUtf8( "Select LADSPA FX" ) );
+	setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	m_sSelectedPluginName = "";
+
+	m_nameLbl->setText( QString("") );
+	m_labelLbl->setText( QString("") );
+	m_typeLbl->setText( QString("") );
+	m_pIDLbl->setText( QString("") );
+	m_pMakerLbl->setText( QString("") );
+	m_pCopyrightLbl->setText( QString("") );
+	m_pPluginsListBox->clear();
+	m_pOkBtn->setEnabled(false);
+
+	m_pGroupsListView->setHeaderLabels( QStringList( trUtf8( "Groups" ) ) );
+
+#ifdef LADSPA_SUPPORT
+	//Song *pSong = Hydrogen::get_instance()->getSong();
+	LadspaFX *pFX = Effects::get_instance()->getLadspaFX(nLadspaFX);
+	if (pFX) {
+		m_sSelectedPluginName = pFX->getPluginName();
+	}
+	buildLadspaGroups();
+
+	m_pGroupsListView->setItemHidden( m_pGroupsListView->headerItem(), true );
+
+
+//	LadspaFXGroup* pFXGroup = LadspaFX::getLadspaFXGroup();
+//	vector<LadspaFXInfo*> list = findPluginsInGroup( m_sSelectedPluginName, pFXGroup );
+//	for (uint i = 0; i < list.size(); i++) {
+//		m_pPluginsListBox->addItem( list[i]->m_sName.c_str() );
+//	}
+#endif
+
+	connect( m_pPluginsListBox, SIGNAL( itemSelectionChanged () ), this, SLOT( pluginSelected() ) );
+	pluginSelected();
+// 	on_m_pGroupsListView_currentItemChanged( m_pGroupsListView->currentItem(), NULL );
+}
+
+
+
+LadspaFXSelector::~LadspaFXSelector()
+{
+	//INFOLOG( "DESTROY" );
+}
+
+
+
+void LadspaFXSelector::buildLadspaGroups()
+{
+#ifdef LADSPA_SUPPORT
+	m_pGroupsListView->clear();
+
+//	QTreeWidgetItem* pRootItem = new QTreeWidgetItem( );
+// 	pRootItem->setText( 0, trUtf8("Groups") );
+// 	m_pGroupsListView->addTopLevelItem( pRootItem );
+// 	m_pGroupsListView->setItemExpanded( pRootItem, true );
+	
+	H2Core::LadspaFXGroup* pFXGroup = Effects::get_instance()->getLadspaFXGroup();
+	for (uint i = 0; i < pFXGroup->getChildList().size(); i++) {
+		H2Core::LadspaFXGroup *pNewGroup = ( pFXGroup->getChildList() )[ i ];
+		addGroup( m_pGroupsListView, pNewGroup );
+	}
+	m_pGroupsListView->setCurrentItem( m_pCurrentItem );
+#endif
+}
+
+
+
+#ifdef LADSPA_SUPPORT
+void LadspaFXSelector::addGroup( QTreeWidget *parent, H2Core::LadspaFXGroup *pGroup )
+{
+	QTreeWidgetItem* pNewItem = new QTreeWidgetItem( parent );
+	QFont f = pNewItem->font( 0 );
+	f.setBold( true );
+	pNewItem->setFont( 0, f );
+	buildGroup( pNewItem, pGroup );
+}
+
+void LadspaFXSelector::addGroup( QTreeWidgetItem * parent, H2Core::LadspaFXGroup *pGroup )
+{
+	QTreeWidgetItem* pNewItem = new QTreeWidgetItem( parent );
+	buildGroup( pNewItem, pGroup );
+}
+
+void LadspaFXSelector::buildGroup( QTreeWidgetItem *pNewItem, H2Core::LadspaFXGroup *pGroup )
+{
+	QString sGroupName = pGroup->getName();
+	if (sGroupName == QString("Uncategorized")) {
+		sGroupName = trUtf8("Alphabetic List");
+	}
+	else if (sGroupName == QString("Categorized(LRDF)")) {
+		sGroupName = trUtf8("Categorized");
+	}
+	else if (sGroupName == QString("Recently Used")) {
+		sGroupName = trUtf8("Recently Used");
+	}
+	pNewItem->setText( 0, sGroupName );
+
+
+	for ( uint i = 0; i < pGroup->getChildList().size(); i++ ) {
+		H2Core::LadspaFXGroup *pNewGroup = ( pGroup->getChildList() )[ i ];
+
+		addGroup( pNewItem, pNewGroup );
+	}
+	for(uint i = 0; i < pGroup->getLadspaInfo().size(); i++) {
+		H2Core::LadspaFXInfo* pInfo = (pGroup->getLadspaInfo())[i];
+		if (pInfo->m_sName == m_sSelectedPluginName) {
+			m_pCurrentItem = pNewItem;
+			break;
+		}
+	}
+}
+#endif
+
+
+
+QString LadspaFXSelector::getSelectedFX()
+{
+	return m_sSelectedPluginName;
+}
+
+
+void LadspaFXSelector::pluginSelected()
+{
+#ifdef LADSPA_SUPPORT
+	//INFOLOG( "[pluginSelected]" );
+	//
+        
+	if ( m_pPluginsListBox->selectedItems().isEmpty() ) return;
+
+	QString sSelected = m_pPluginsListBox->currentItem()->text();
+	m_sSelectedPluginName = sSelected;
+
+
+	std::vector<H2Core::LadspaFXInfo*> pluginList = Effects::get_instance()->getPluginList();
+	for (uint i = 0; i < pluginList.size(); i++) {
+		H2Core::LadspaFXInfo *pFXInfo = pluginList[i];
+		if (pFXInfo->m_sName == m_sSelectedPluginName ) {
+
+			m_nameLbl->setText(  pFXInfo->m_sName );
+			m_labelLbl->setText( pFXInfo->m_sLabel );
+
+			if ( ( pFXInfo->m_nIAPorts == 2 ) && ( pFXInfo->m_nOAPorts == 2 ) ) {		// Stereo plugin
+				m_typeLbl->setText( trUtf8("Stereo") );
+			}
+			else if ( ( pFXInfo->m_nIAPorts == 1 ) && ( pFXInfo->m_nOAPorts == 1 ) ) {	// Mono plugin
+				m_typeLbl->setText( trUtf8("Mono") );
+			}
+			else {
+				// not supported
+				m_typeLbl->setText( trUtf8("Not supported") );
+			}
+
+			m_pIDLbl->setText( pFXInfo->m_sID );
+			m_pMakerLbl->setText( pFXInfo->m_sMaker );
+			m_pCopyrightLbl->setText( pFXInfo->m_sCopyright );
+
+			break;
+		}
+	}
+	m_pOkBtn->setEnabled(true);
+#endif
+}
+
+
+
+void LadspaFXSelector::on_m_pGroupsListView_currentItemChanged( QTreeWidgetItem * currentItem, QTreeWidgetItem * previous )
+{
+	UNUSED( previous );
+#ifdef LADSPA_SUPPORT
+	//INFOLOG( "new selection: " + currentItem->text(0).toLocal8Bit().constData() );
+
+	m_pOkBtn->setEnabled(false);
+	m_nameLbl->setText( QString("") );
+	m_labelLbl->setText( QString("") );
+	m_typeLbl->setText( QString("") );
+	m_pIDLbl->setText( QString("") );
+	m_pMakerLbl->setText( QString("") );
+	m_pCopyrightLbl->setText( QString("") );
+
+	// nothing was selected
+	if ( currentItem == NULL ) {
+		return;
+	}
+	
+	if ( currentItem->childCount() ) {
+		currentItem->setExpanded( true );
+	}
+
+	QString itemText = currentItem->text( 0 );
+
+	m_pPluginsListBox->clear(); // ... Why not anyway ? Jakob Lund
+
+// 	while( m_pPluginsListBox->count() != 0) {    // NOTE commented out:
+// 		m_pPluginsListBox->takeItem( 0 );    // This way of clearing the list causes multiple signal emissions,
+// 	}                                            // each time calling pluginSelected().  Jakob.
+
+	H2Core::LadspaFXGroup* pFXGroup = Effects::get_instance()->getLadspaFXGroup();
+
+	std::vector<H2Core::LadspaFXInfo*> pluginList = findPluginsInGroup( itemText, pFXGroup );
+	
+	int selectedIndex = -1;
+	for (int i = 0; i < (int)pluginList.size(); i++) {
+		//INFOLOG( "adding plugin: " + pluginList[ i ]->m_sName );
+		m_pPluginsListBox->addItem( pluginList[ i ]->m_sName );
+		if ( pluginList[ i ]->m_sName == m_sSelectedPluginName ) {
+			selectedIndex = i;
+		}
+	}
+	if ( selectedIndex >= 0 )
+		m_pPluginsListBox->setCurrentRow( selectedIndex );
+#endif
+}
+
+
+#ifdef LADSPA_SUPPORT
+std::vector<H2Core::LadspaFXInfo*> LadspaFXSelector::findPluginsInGroup( const QString& sSelectedGroup, H2Core::LadspaFXGroup *pGroup )
+{
+	//INFOLOG( "group: " + sSelectedGroup );
+	vector<H2Core::LadspaFXInfo*> list;
+
+	if ( pGroup->getName() == sSelectedGroup ) {
+		//INFOLOG( "found..." );
+		for ( uint i = 0; i < pGroup->getLadspaInfo().size(); ++i ) {
+			H2Core::LadspaFXInfo *pInfo = ( pGroup->getLadspaInfo() )[i];
+			list.push_back( pInfo );
+		}
+		return list;
+	}
+	else {
+		//INFOLOG( "not found...searching in the child groups" );
+		for ( uint i = 0; i < pGroup->getChildList().size(); ++i ) {
+			H2Core::LadspaFXGroup *pNewGroup = ( pGroup->getChildList() )[ i ];
+			list = findPluginsInGroup( sSelectedGroup, pNewGroup );
+			if (list.size() != 0) {
+				return list;
+			}
+		}
+	}
+
+	//WARNINGLOG( "[findPluginsInGroup] no group found ('" + sSelectedGroup + "')" );
+	return list;
+}
+#endif
Index: /branches/tabbedInterface/gui/src/SongPropertiesDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SongPropertiesDialog.cpp	(revision 180)
+++ /branches/tabbedInterface/gui/src/SongPropertiesDialog.cpp	(revision 180)
@@ -0,0 +1,73 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "SongPropertiesDialog.h"
+#include "Skin.h"
+#include <hydrogen/Song.h>
+#include <hydrogen/hydrogen.h>
+
+#include <QPixmap>
+
+using namespace H2Core;
+
+SongPropertiesDialog::SongPropertiesDialog(QWidget* parent)
+ : QDialog(parent)
+{
+	setupUi( this );
+
+	setMaximumSize( width(), height() );
+	setMinimumSize( width(), height() );
+
+	setWindowTitle( trUtf8( "Song properties" ) );
+//	setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	Song *song = Hydrogen::get_instance()->getSong();
+	songNameTxt->setText( song->__name );
+
+	authorTxt->setText( song->__author );
+	notesTxt->append( song->get_notes() );
+	licenseTxt->setText( song->get_license() );
+}
+
+
+
+SongPropertiesDialog::~SongPropertiesDialog()
+{
+}
+
+
+void SongPropertiesDialog::on_cancelBtn_clicked()
+{
+	reject();
+}
+
+void SongPropertiesDialog::on_okBtn_clicked()
+{
+	Song *song = Hydrogen::get_instance()->getSong();
+
+	song->__name = songNameTxt->text();
+	song->__author = authorTxt->text();
+	song->set_notes( notesTxt->toPlainText() );
+	song->set_license( licenseTxt->text() );
+
+	accept();
+}
Index: /branches/tabbedInterface/gui/src/PatternFillDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternFillDialog.cpp	(revision 377)
+++ /branches/tabbedInterface/gui/src/PatternFillDialog.cpp	(revision 377)
@@ -0,0 +1,97 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ */
+
+#include "PatternFillDialog.h"
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/Pattern.h>
+
+#include "Skin.h"
+
+
+PatternFillDialog::PatternFillDialog(QWidget* parent, FillRange* pRange)
+ : QDialog(parent)
+ , Object( "PatternFillDialog" )
+{
+	setupUi( this );
+
+	setFixedSize( width(), height() );
+	setWindowTitle( trUtf8( "Fill with selected pattern" ) );
+
+	__fill_range = pRange;
+	__text_changed();
+}
+
+
+
+PatternFillDialog::~PatternFillDialog()
+{
+}
+
+
+
+void PatternFillDialog::on_cancelBtn_clicked()
+{
+	reject();
+}
+
+
+
+void PatternFillDialog::on_okBtn_clicked()
+{
+	__fill_range->fromVal = fromText->text().toUInt();
+	__fill_range->toVal = toText->text().toUInt();
+	__fill_range->bInsert = fillRB->isChecked();
+	accept();
+}
+
+
+
+void PatternFillDialog::on_fromText_textChanged( const QString& )
+{
+	__text_changed();
+}
+
+
+void PatternFillDialog::on_toText_textChanged( const QString& )
+{
+	__text_changed();
+}
+
+
+
+void PatternFillDialog::__text_changed()
+{
+	int fromVal, toVal;
+
+	if ( ( fromVal = fromText->text().toUInt() ) &&
+	     ( toVal = toText->text().toUInt() )     &&
+	     ( toVal > fromVal ) ) {
+
+		okBtn->setEnabled(true);
+	}
+	else {
+		okBtn->setEnabled(false);
+	}
+}
Index: /branches/tabbedInterface/gui/src/VirtualPatternDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/VirtualPatternDialog.cpp	(revision 1318)
+++ /branches/tabbedInterface/gui/src/VirtualPatternDialog.cpp	(revision 1318)
@@ -0,0 +1,110 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ */
+
+#include "VirtualPatternDialog.h"
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/Pattern.h>
+
+#include "Skin.h"
+
+namespace
+{
+
+struct SimplePatternNode
+{
+    H2Core::Pattern *curPattern;
+    int colour;
+    std::set<H2Core::Pattern*> edges;
+};//SimplePatternNode
+    
+void addEdges(std::set<H2Core::Pattern*> &patternSet)
+{
+    std::set<H2Core::Pattern*> curPatternSet = patternSet;
+    
+    for (std::set<H2Core::Pattern*>::const_iterator setIter = curPatternSet.begin(); setIter != curPatternSet.end(); ++setIter) {
+	 for (std::set<H2Core::Pattern*>::const_iterator innerSetIter = (*setIter)->virtual_pattern_set.begin(); innerSetIter != (*setIter)->virtual_pattern_set.end(); ++innerSetIter) {
+	     patternSet.insert(*innerSetIter);
+	 }//for
+    }//for
+    
+    if (patternSet.size() != curPatternSet.size()) {
+	addEdges(patternSet);
+    }//if
+}//addEdges
+    
+}//anonymous namespace
+
+
+VirtualPatternDialog::VirtualPatternDialog(QWidget* parent)
+ : QDialog(parent)
+ , Object( "VirtualPatternDialog" )
+{
+	setupUi( this );
+
+	setFixedSize( width(), height() );
+	setWindowTitle( trUtf8( "Select virtual pattern" ) );
+}
+
+
+
+VirtualPatternDialog::~VirtualPatternDialog()
+{
+}
+
+
+
+void VirtualPatternDialog::on_cancelBtn_clicked()
+{
+	reject();
+}
+
+
+
+void VirtualPatternDialog::on_okBtn_clicked()
+{
+	accept();
+}
+
+void VirtualPatternDialog::computeVirtualPatternTransitiveClosure(H2Core::PatternList *pPatternList)
+{
+    //std::map<Pattern*, SimplePatternNode*> patternNodeGraph;
+    
+    int listsize = pPatternList->get_size();    
+    for (unsigned int index = 0; index < listsize; ++index) {
+	H2Core::Pattern *curPattern = pPatternList->get(index);
+	//SimplePatternNode *newNode = new SimplePatternNode();
+	//newNode->curPattern = curPattern;
+	//newNode->colour = 0;
+	//newNode->edges = curPattern->virtual_pattern_set;
+	
+	curPattern->virtual_pattern_transitive_closure_set = curPattern->virtual_pattern_set;
+	
+	addEdges(curPattern->virtual_pattern_transitive_closure_set);
+	
+	//patternNodeGraph[curPattern] = newNode;
+    }//for
+}//computeVirtualPatternTransitiveClosure
+
+
Index: /branches/tabbedInterface/gui/src/MainForm.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/MainForm.cpp	(revision 1567)
+++ /branches/tabbedInterface/gui/src/MainForm.cpp	(revision 1567)
@@ -0,0 +1,1638 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "version.h"
+
+#include <sys/socket.h>
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/playlist.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/smf/SMF.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/LocalFileMng.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/event_queue.h>
+using namespace H2Core;
+
+#include "AboutDialog.h"
+#include "AudioEngineInfoForm.h"
+#include "ExportSongDialog.h"
+#include "HydrogenApp.h"
+#include "InstrumentRack.h"
+#include "Skin.h"
+#include "MainForm.h"
+#include "PlayerControl.h"
+#include "HelpBrowser.h"
+#include "LadspaFXProperties.h"
+#include "SongPropertiesDialog.h"
+
+#include "MetroBlinker.h"
+#include "Mixer/Mixer.h"
+#include "InstrumentEditor/InstrumentEditorPanel.h"
+#include "PatternEditor/PatternEditorPanel.h"
+#include "SongEditor/SongEditor.h"
+#include "SongEditor/SongEditorPanel.h"
+#include "SoundLibrary/SoundLibraryPanel.h"
+#include "SoundLibrary/SoundLibraryImportDialog.h"
+#include "SoundLibrary/SoundLibrarySaveDialog.h"
+#include "SoundLibrary/SoundLibraryExportDialog.h"
+
+#include <QtGui>
+
+#ifndef WIN32
+	#include <sys/time.h>
+#endif
+
+#ifdef LASH_SUPPORT
+#include <lash-1.0/lash/lash.h>
+#include <hydrogen/LashClient.h>
+#endif
+
+#include <memory>
+#include <cassert>
+
+using namespace std;
+using namespace H2Core;
+
+int MainForm::sigusr1Fd[2];
+
+MainForm::MainForm( QApplication *app, const QString& songFilename )
+ : QMainWindow( 0, 0 )
+ , Object( "MainForm" )
+{
+	setMinimumSize( QSize( 1000, 600 ) );
+	setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigusr1Fd))
+	   qFatal("Couldn't create HUP socketpair");
+	snUsr1 = new QSocketNotifier(sigusr1Fd[1], QSocketNotifier::Read, this);
+	connect(snUsr1, SIGNAL(activated(int)), this, SLOT( handleSigUsr1() ));
+
+
+
+	m_pQApp = app;
+
+	m_pQApp->processEvents();
+
+	// Load default song
+	Song *song = NULL;
+	if ( !songFilename.isEmpty() ) {
+		song = Song::load( songFilename );
+		if (song == NULL) {
+			//QMessageBox::warning( this, "Hydrogen", trUtf8("Error loading song.") );
+			song = Song::get_empty_song();
+			song->set_filename( "" );
+		}
+	}
+	else {
+		Preferences *pref = Preferences::get_instance();
+		bool restoreLastSong = pref->isRestoreLastSongEnabled();
+		QString filename = pref->getLastSongFilename();
+		if ( restoreLastSong && ( !filename.isEmpty() )) {
+			song = Song::load( filename );
+			if (song == NULL) {
+				//QMessageBox::warning( this, "Hydrogen", trUtf8("Error restoring last song.") );
+				song = Song::get_empty_song();
+				song->set_filename( "" );
+			}
+		}
+		else {
+			song = Song::get_empty_song();
+			song->set_filename( "" );
+		}
+	}
+
+	h2app = new HydrogenApp( this, song );
+	h2app->addEventListener( this );
+
+	createMenuBar();
+
+	h2app->setStatusBarMessage( trUtf8("Hydrogen Ready."), 10000 );
+
+	initKeyInstMap();
+
+	// we need to do all this to support the keyboard playing
+	// for all the window modes
+	h2app->getMixer()->installEventFilter (this);
+	h2app->getPatternEditorPanel()->installEventFilter (this);
+	h2app->getPatternEditorPanel()->getPianoRollEditor()->installEventFilter (this);
+	h2app->getSongEditorPanel()->installEventFilter (this);
+	h2app->getPlayerControl()->installEventFilter(this);
+	InstrumentEditorPanel::get_instance()->installEventFilter(this);
+	h2app->getAudioEngineInfoForm()->installEventFilter(this);
+	h2app->getMetroBlinker()->installEventFilter(this);
+//	h2app->getPlayListDialog()->installEventFilter(this);
+	installEventFilter( this );
+
+	showDevelWarning();
+
+	connect( &m_autosaveTimer, SIGNAL(timeout()), this, SLOT(onAutoSaveTimer()));
+	m_autosaveTimer.start( 60 * 1000 );
+
+
+#ifdef LASH_SUPPORT
+
+	if ( Preferences::get_instance()->useLash() ){
+		LashClient* lashClient = LashClient::get_instance();
+		if (lashClient->isConnected())
+		{
+			// send alsa client id now since it can only be sent
+			// after the audio engine has been started.
+			Preferences *pref = Preferences::get_instance();
+			if ( pref->m_sMidiDriver == "ALSA" ) {
+	//			infoLog("[LASH] Sending alsa seq id to LASH server");
+				lashClient->sendAlsaClientId();
+			}
+			// start timer for polling lash events
+			lashPollTimer = new QTimer(this);
+			connect( lashPollTimer, SIGNAL( timeout() ), this, SLOT( onLashPollTimer() ) );
+			lashPollTimer->start(500);
+		}
+	}
+#endif
+
+	
+//playlist display timer
+	QTimer *playlistDisplayTimer = new QTimer(this);
+	connect( playlistDisplayTimer, SIGNAL( timeout() ), this, SLOT( onPlaylistDisplayTimer() ) );
+	playlistDisplayTimer->start(30000);	// update player control at 
+// ~ playlist display timer
+	
+//beatcouter
+	Hydrogen::get_instance()->setBcOffsetAdjust();
+// director
+	EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 );
+
+}
+
+
+
+MainForm::~MainForm()
+{
+	// remove the autosave file
+	QFile file( getAutoSaveFilename() );
+        file.remove();
+
+	if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	// remove the autosave file
+	m_autosaveTimer.stop();
+	QFile autosaveFile( "hydrogen_autosave.h2song" );
+	autosaveFile.remove();
+
+	hide();
+
+	if (h2app != NULL) {
+		delete Playlist::get_instance();
+		delete h2app;
+		h2app = NULL;
+	}
+
+}
+
+
+
+///
+/// Create the menubar
+///
+void MainForm::createMenuBar()
+{
+	// menubar
+	QMenuBar *m_pMenubar = new QMenuBar( this );
+	setMenuBar( m_pMenubar );
+
+	// FILE menu
+	QMenu *m_pFileMenu = m_pMenubar->addMenu( trUtf8( "&Project" ) );
+
+	m_pFileMenu->addAction( trUtf8( "&New" ), this, SLOT( action_file_new() ), QKeySequence( "Ctrl+N" ) );
+	m_pFileMenu->addAction( trUtf8( "Show &info" ), this, SLOT( action_file_songProperties() ), QKeySequence( "" ) );
+
+	m_pFileMenu->addSeparator();				// -----
+
+	m_pFileMenu->addAction( trUtf8( "&Open" ), this, SLOT( action_file_open() ), QKeySequence( "Ctrl+O" ) );
+	m_pFileMenu->addAction( trUtf8( "Open &Demo" ), this, SLOT( action_file_openDemo() ), QKeySequence( "Ctrl+D" ) );
+
+	m_pRecentFilesMenu = m_pFileMenu->addMenu( trUtf8( "Open &recent" ) );
+
+	m_pFileMenu->addSeparator();				// -----
+
+	m_pFileMenu->addAction( trUtf8( "&Save" ), this, SLOT( action_file_save() ), QKeySequence( "Ctrl+S" ) );
+	m_pFileMenu->addAction( trUtf8( "Save &as..." ), this, SLOT( action_file_save_as() ), QKeySequence( "Ctrl+Shift+S" ) );
+
+	m_pFileMenu->addSeparator();				// -----
+
+	m_pFileMenu->addAction ( trUtf8 ( "Open &Pattern" ), this, SLOT ( action_file_openPattern() ), QKeySequence ( "" ) );
+	m_pFileMenu->addAction( trUtf8( "Expor&t pattern as..." ), this, SLOT( action_file_export_pattern_as() ), QKeySequence( "Ctrl+P" ) );
+
+	m_pFileMenu->addSeparator();				// -----
+
+	m_pFileMenu->addAction( trUtf8( "Export &MIDI file" ), this, SLOT( action_file_export_midi() ), QKeySequence( "Ctrl+M" ) );
+	m_pFileMenu->addAction( trUtf8( "&Export song" ), this, SLOT( action_file_export() ), QKeySequence( "Ctrl+E" ) );
+
+
+#ifndef Q_OS_MACX
+	m_pFileMenu->addSeparator();				// -----
+
+	m_pFileMenu->addAction( trUtf8("&Quit"), this, SLOT( action_file_exit() ), QKeySequence( "Ctrl+Q" ) );
+#endif
+
+	updateRecentUsedSongList();
+	connect( m_pRecentFilesMenu, SIGNAL( triggered(QAction*) ), this, SLOT( action_file_open_recent(QAction*) ) );
+	//~ FILE menu
+
+
+	// INSTRUMENTS MENU
+	QMenu *m_pInstrumentsMenu = m_pMenubar->addMenu( trUtf8( "I&nstruments" ) );
+	m_pInstrumentsMenu->addAction( trUtf8( "&Add instrument" ), this, SLOT( action_instruments_addInstrument() ), QKeySequence( "" ) );
+	m_pInstrumentsMenu->addAction( trUtf8( "&Clear all" ), this, SLOT( action_instruments_clearAll() ), QKeySequence( "" ) );
+	m_pInstrumentsMenu->addAction( trUtf8( "&Save library" ), this, SLOT( action_instruments_saveLibrary() ), QKeySequence( "" ) );
+	m_pInstrumentsMenu->addAction( trUtf8( "&Export library" ), this, SLOT( action_instruments_exportLibrary() ), QKeySequence( "" ) );
+	m_pInstrumentsMenu->addAction( trUtf8( "&Import library" ), this, SLOT( action_instruments_importLibrary() ), QKeySequence( "" ) );
+
+
+
+
+	// Tools menu
+	QMenu *m_pToolsMenu = m_pMenubar->addMenu( trUtf8( "&Tools" ));
+
+//	if ( Preferences::get_instance()->getInterfaceMode() == Preferences::SINGLE_PANED ) {
+//		m_pWindowMenu->addAction( trUtf8("Show song editor"), this, SLOT( action_window_showSongEditor() ), QKeySequence( "" ) );
+//	}
+	m_pToolsMenu->addAction( trUtf8("Playlist &editor"), this, SLOT( action_window_showPlaylistDialog() ), QKeySequence( "" ) );
+	m_pToolsMenu->addAction( trUtf8("Director"), this, SLOT( action_window_show_MetronWidget() ), QKeySequence( "Alt+B" ) );
+
+	m_pToolsMenu->addAction( trUtf8("&Mixer"), this, SLOT( action_window_showMixer() ), QKeySequence( "Alt+M" ) );
+
+	m_pToolsMenu->addAction( trUtf8("&Instrument Rack"), this, SLOT( action_window_showDrumkitManagerPanel() ), QKeySequence( "Alt+I" ) );
+	m_pToolsMenu->addAction( trUtf8("&Preferences"), this, SLOT( showPreferencesDialog() ), QKeySequence( "Alt+P" ) );
+
+	//~ Tools menu
+
+        Logger *l = Logger::get_instance();
+        if ( l->get_log_level() == 15 ) {
+		// DEBUG menu
+		QMenu *m_pDebugMenu = m_pMenubar->addMenu( trUtf8("De&bug") );
+		m_pDebugMenu->addAction( trUtf8( "Show &audio engine info" ), this, SLOT( action_debug_showAudioEngineInfo() ) );
+		m_pDebugMenu->addAction( trUtf8( "Print Objects" ), this, SLOT( action_debug_printObjects() ) );
+		//~ DEBUG menu
+	}
+
+	// INFO menu
+	QMenu *m_pInfoMenu = m_pMenubar->addMenu( trUtf8( "&Info" ) );
+	m_pInfoMenu->addAction( trUtf8("&User manual"), this, SLOT( showUserManual() ), QKeySequence( "Ctrl+?" ) );
+	m_pInfoMenu->addSeparator();
+	m_pInfoMenu->addAction( trUtf8("&About"), this, SLOT( action_help_about() ), QKeySequence( trUtf8("", "Info|About") ) );
+	//~ INFO menu
+}
+
+
+
+
+void MainForm::onLashPollTimer()
+{
+#ifdef LASH_SUPPORT	
+if ( Preferences::get_instance()->useLash() ){
+	LashClient* client = LashClient::get_instance();
+	
+	if (!client->isConnected())
+	{
+		WARNINGLOG("[LASH] Not connected to server!");
+		return;
+	}
+	
+	bool keep_running = true;
+
+	lash_event_t* event;
+
+	string songFilename;
+	QString filenameSong;
+	Song *song = Hydrogen::get_instance()->getSong();
+	// Extra parentheses for -Wparentheses
+	while ( (event = client->getNextEvent()) ) {
+		
+		switch (lash_event_get_type(event)) {
+			
+			case LASH_Save_File:
+		
+				INFOLOG("[LASH] Save file");
+			
+				songFilename.append(lash_event_get_string(event));
+				songFilename.append("/hydrogen.h2song"); 
+				
+				filenameSong = QString::fromLocal8Bit( songFilename.c_str() );
+				song->set_filename( filenameSong );
+				action_file_save();
+			  
+				client->sendEvent(LASH_Save_File);
+			  
+				break;
+		
+			case LASH_Restore_File:
+		
+				songFilename.append(lash_event_get_string(event));
+				songFilename.append("/hydrogen.h2song"); 
+				
+				INFOLOG( QString("[LASH] Restore file: %1")
+					 .arg( songFilename.c_str() ) );
+
+				filenameSong = QString::fromLocal8Bit( songFilename.c_str() );
+							 
+				openSongFile( filenameSong );
+			 
+				client->sendEvent(LASH_Restore_File);
+			 
+				break;
+
+			case LASH_Quit:
+		
+//				infoLog("[LASH] Quit!");
+				keep_running = false;
+				
+				break;
+		
+			default:
+				;
+//				infoLog("[LASH] Got unknown event!");
+
+		}
+
+		lash_event_destroy(event);
+
+	}
+
+   if (!keep_running)
+   {
+	   lashPollTimer->stop();
+	   action_file_exit();
+   }
+}
+#endif
+}
+
+
+/// return true if the app needs to be closed.
+bool MainForm::action_file_exit()
+{
+	bool proceed = handleUnsavedChanges();
+	if(!proceed) {
+		return false;
+	}
+	closeAll();
+	return true;
+}
+
+
+
+void MainForm::action_file_new()
+{
+	if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	bool proceed = handleUnsavedChanges();
+	if(!proceed) {
+		return;
+	}
+
+	Hydrogen::get_instance()->m_timelinevector.clear();
+	Song * song = Song::get_empty_song();
+	song->set_filename( "" );
+	h2app->setSong(song);
+ 	Hydrogen::get_instance()->setSelectedPatternNumber( 0 );
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->update_background_color();
+	HydrogenApp::get_instance()->getSongEditorPanel()->updatePositionRuler();
+	Hydrogen::get_instance()->m_timelinetagvector.clear();
+	EventQueue::get_instance()->push_event( EVENT_METRONOME, 2 );
+}
+
+
+
+void MainForm::action_file_save_as()
+{
+	if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+        std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode( QFileDialog::AnyFile );
+	fd->setFilter( trUtf8("Hydrogen Song (*.h2song)") );
+        fd->setAcceptMode( QFileDialog::AcceptSave );
+        fd->setWindowTitle( trUtf8( "Save song" ) );
+
+	Song *song = Hydrogen::get_instance()->getSong();
+	QString defaultFilename;
+	QString lastFilename = song->get_filename();
+
+	if ( lastFilename.isEmpty() ) {
+		defaultFilename = Hydrogen::get_instance()->getSong()->__name;
+		defaultFilename += ".h2song";
+	}
+	else {
+		defaultFilename = lastFilename;
+	}
+
+	fd->selectFile( defaultFilename );
+
+	QString filename;
+	if (fd->exec() == QDialog::Accepted) {
+		filename = fd->selectedFiles().first();
+	}
+
+	if ( !filename.isEmpty() ) {
+		QString sNewFilename = filename;
+		if ( sNewFilename.endsWith(".h2song") == false ) {
+			filename += ".h2song";
+		}
+
+		song->set_filename(filename);
+		action_file_save();
+	}
+	h2app->setScrollStatusBarMessage( trUtf8("Song saved as.") + QString(" Into: ") + defaultFilename, 2000 );
+        h2app->setWindowTitle( filename );
+}
+
+
+
+void MainForm::action_file_save()
+{
+//	if ( ((Hydrogen::get_instance())->getState() == STATE_PLAYING) ) {
+//		(Hydrogen::get_instance())->stop();
+//	}
+
+	Song *song = Hydrogen::get_instance()->getSong();
+	QString filename = song->get_filename();
+
+	if ( filename.isEmpty() ) {
+		// just in case!
+		return action_file_save_as();
+	}
+
+	LocalFileMng mng;
+	bool saved = false;
+	saved = song->save( filename );
+	
+
+	if(! saved) {
+		QMessageBox::warning( this, "Hydrogen", trUtf8("Could not save song.") );
+	} else {
+		Preferences::get_instance()->setLastSongFilename( song->get_filename() );
+
+		// add the new loaded song in the "last used song" vector
+		Preferences *pPref = Preferences::get_instance();
+		vector<QString> recentFiles = pPref->getRecentFiles();
+		recentFiles.insert( recentFiles.begin(), filename );
+		pPref->setRecentFiles( recentFiles );
+
+		updateRecentUsedSongList();
+
+		h2app->setScrollStatusBarMessage( trUtf8("Song saved.") + QString(" Into: ") + filename, 2000 );
+	}
+}
+
+
+
+
+void MainForm::action_help_about() {
+	//QWidget *parent = this;
+//	if (workspace) {
+//		parent = workspace;
+//	}
+
+	// show modal dialog
+	AboutDialog *dialog = new AboutDialog( NULL );
+	dialog->exec();
+}
+
+
+
+
+void MainForm::showUserManual()
+{
+	h2app->getHelpBrowser()->hide();
+	h2app->getHelpBrowser()->show();
+}
+
+
+void MainForm::action_file_export_pattern_as()
+{
+	if ( ( Hydrogen::get_instance()->getState() == STATE_PLAYING ) )
+	{
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	int selectedpattern = engine->getSelectedPatternNumber();
+	Song *song = engine->getSong();
+	Pattern *pat = song->get_pattern_list()->get ( selectedpattern );
+
+	Instrument *instr = song->get_instrument_list()->get ( 0 );
+	assert ( instr );
+
+	QDir dir  = Preferences::get_instance()->__lastspatternDirectory;
+
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::AnyFile );
+	fd->setFilter ( trUtf8 ( "Hydrogen Pattern (*.h2pattern)" ) );
+	fd->setAcceptMode ( QFileDialog::AcceptSave );
+        fd->setWindowTitle ( trUtf8 ( "Save Pattern as ..." ) );
+	fd->setDirectory ( dir );
+
+
+
+	QString defaultPatternname = QString ( pat->get_name() );
+
+	fd->selectFile ( defaultPatternname );
+
+	LocalFileMng fileMng;
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted )
+	{
+		filename = fd->selectedFiles().first();
+		QString tmpfilename = filename;
+		QString toremove = tmpfilename.section( '/', -1 ); 
+		QString newdatapath =  tmpfilename.replace( toremove, "" );
+		Preferences::get_instance()->__lastspatternDirectory = newdatapath;
+	}
+
+	if ( !filename.isEmpty() )
+	{
+		QString sNewFilename = filename;
+		if(sNewFilename.endsWith( ".h2pattern" ) ){
+			sNewFilename += "";
+		}
+		else{
+			sNewFilename += ".h2pattern";
+		}
+		QString patternname = sNewFilename;
+		QString realpatternname = filename;
+		QString realname = realpatternname.mid( realpatternname.lastIndexOf( "/" ) + 1 );
+		if ( realname.endsWith( ".h2pattern" ) )
+			realname.replace( ".h2pattern", "" );
+		pat->set_name(realname);
+		HydrogenApp::get_instance()->getSongEditorPanel()->updateAll();
+		int err = fileMng.savePattern ( song , selectedpattern, patternname, realname, 2 );
+		if ( err != 0 )
+		{
+			QMessageBox::warning( this, "Hydrogen", trUtf8("Could not export pattern.") );
+			_ERRORLOG ( "Error saving the pattern" );
+			QMessageBox::warning( this, "Hydrogen", trUtf8("Could not export pattern.") ); 
+		}
+	}
+	h2app->setStatusBarMessage ( trUtf8 ( "Pattern saved." ), 10000 );
+	
+	//update SoundlibraryPanel
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->test_expandedItems();
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
+}
+
+
+
+void MainForm::action_file_open() {
+	if ( ((Hydrogen::get_instance())->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	bool proceed = handleUnsavedChanges();
+	if(!proceed) {
+		return;
+	}
+
+	static QString lastUsedDir = Preferences::get_instance()->getDataDirectory() + "/songs";
+	
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode(QFileDialog::ExistingFile);
+	fd->setFilter( trUtf8("Hydrogen Song (*.h2song)") );
+	fd->setDirectory( lastUsedDir );
+
+        fd->setWindowTitle( trUtf8( "Open song" ) );
+
+	/// \todo impostare il preview
+	/*
+	fd->setContentsPreviewEnabled( TRUE );
+	fd->setContentsPreview( "uno", "due" );
+	fd->setPreviewMode( QFileDialog::Contents );
+	*/
+
+	QString filename;
+	if (fd->exec() == QDialog::Accepted) {
+		filename = fd->selectedFiles().first();
+		lastUsedDir = fd->directory().absolutePath();
+	}
+
+
+	if ( !filename.isEmpty() ) {
+		openSongFile( filename );
+	}
+
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->update_background_color();
+}
+
+
+void MainForm::action_file_openPattern()
+{
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	PatternList *pPatternList = song->get_pattern_list();
+
+	Instrument *instr = song->get_instrument_list()->get ( 0 );
+	assert ( instr );
+
+	QDir dirPattern( Preferences::get_instance()->getDataDirectory() + "/patterns" );
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::ExistingFile );
+	fd->setFilter ( trUtf8 ( "Hydrogen Pattern (*.h2pattern)" ) );
+	fd->setDirectory ( dirPattern );
+
+	fd->setWindowTitle ( trUtf8 ( "Open Pattern" ) );
+
+
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted )
+	{
+		filename = fd->selectedFiles().first();
+	}
+	QString patternname = filename;
+
+
+	LocalFileMng mng;
+	LocalFileMng fileMng;
+	Pattern* err = fileMng.loadPattern ( patternname );
+	if ( err == 0 )
+	{
+		_ERRORLOG( "Error loading the pattern" );
+		_ERRORLOG( patternname );
+	}
+	else
+	{
+		H2Core::Pattern *pNewPattern = err;
+		pPatternList->add ( pNewPattern );
+		song->__is_modified = true;
+	}
+
+	HydrogenApp::get_instance()->getSongEditorPanel()->updateAll();
+}
+
+/// \todo parametrizzare il metodo action_file_open ed eliminare il seguente...
+void MainForm::action_file_openDemo()
+{
+	if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	bool proceed = handleUnsavedChanges();
+	if(!proceed) {
+		return;
+	}
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode(QFileDialog::ExistingFile);
+	fd->setFilter( trUtf8("Hydrogen Song (*.h2song)") );
+
+	fd->setWindowTitle( trUtf8( "Open song" ) );
+//	fd->setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	/// \todo impostare il preview
+	/*
+	fd->setContentsPreviewEnabled( TRUE );
+	fd->setContentsPreview( "uno", "due" );
+	fd->setPreviewMode( QFileDialog::Contents );
+	*/
+	fd->setDirectory( QString( Preferences::get_instance()->getDemoPath() ) );
+
+
+	QString filename;
+	if (fd->exec() == QDialog::Accepted) {
+		filename = fd->selectedFiles().first();
+	}
+
+
+	if ( !filename.isEmpty() ) {
+		openSongFile( filename );
+		Hydrogen::get_instance()->getSong()->set_filename( "" );
+	}
+}
+
+
+
+void MainForm::showPreferencesDialog()
+{
+	if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	h2app->showPreferencesDialog();
+}
+
+
+
+void MainForm::action_window_showPlaylistDialog()
+{
+	h2app->showPlaylistDialog();	
+}
+
+void MainForm::action_window_show_MetronWidget()
+{
+
+	h2app->showMetroBlinker();
+}
+
+void MainForm::action_window_showMixer()
+{
+	bool isVisible = HydrogenApp::get_instance()->getMixer()->isVisible();
+	h2app->showMixer( !isVisible );
+}
+
+
+
+void MainForm::action_debug_showAudioEngineInfo()
+{
+	h2app->showAudioEngineInfoForm();
+}
+
+
+
+///
+/// Shows the song editor
+///
+void MainForm::action_window_showSongEditor()
+{
+	bool isVisible = h2app->getSongEditorPanel()->isVisible();
+	h2app->getSongEditorPanel()->setHidden( isVisible );
+}
+
+
+
+void MainForm::action_instruments_addInstrument()
+{
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+	InstrumentList* pList = Hydrogen::get_instance()->getSong()->get_instrument_list();
+
+	// create a new valid ID for this instrument
+	int nID = -1;
+	for ( uint i = 0; i < pList->get_size(); ++i ) {
+		Instrument* pInstr = pList->get( i );
+		if ( pInstr->get_id().toInt() > nID ) {
+			nID = pInstr->get_id().toInt();
+		}
+	}
+	++nID;
+
+	Instrument *pNewInstr = new Instrument( QString::number( nID ), "New instrument", new ADSR());
+	pList->add( pNewInstr );
+	
+	#ifdef JACK_SUPPORT
+	Hydrogen::get_instance()->renameJackPorts();
+	#endif
+	
+	AudioEngine::get_instance()->unlock();
+
+	Hydrogen::get_instance()->setSelectedInstrumentNumber( pList->get_size() - 1 );
+
+	// Force an update
+	//EventQueue::get_instance()->pushEvent( EVENT_SELECTED_PATTERN_CHANGED, -1 );
+}
+
+
+
+void MainForm::action_instruments_clearAll()
+{
+	switch(
+	       QMessageBox::information( this,
+					 "Hydrogen",
+					 trUtf8("Clear all instruments?"),
+					 trUtf8("Ok"),
+					 trUtf8("Cancel"),
+					 0,      // Enter == button 0
+					 1 )) { // Escape == button 2
+	case 0:
+	  // ok btn pressed
+	  break;
+	case 1:
+	  // cancel btn pressed
+	  return;
+	}
+
+	// Remove all layers
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	InstrumentList* pList = pSong->get_instrument_list();
+	for (uint i = 0; i < pList->get_size(); i++) {
+		Instrument* pInstr = pList->get( i );
+		pInstr->set_name( (QString( trUtf8( "Instrument %1" ) ).arg( i + 1 )) );
+		// remove all layers
+		for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
+			InstrumentLayer* pLayer = pInstr->get_layer( nLayer );
+			delete pLayer;
+			pInstr->set_layer( NULL, nLayer );
+		}
+	}
+	AudioEngine::get_instance()->unlock();
+	EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
+}
+
+
+
+void MainForm::action_instruments_exportLibrary()
+{
+        SoundLibraryExportDialog exportDialog( this );
+ 	exportDialog.exec();
+}
+
+
+
+
+void MainForm::action_instruments_importLibrary()
+{
+	SoundLibraryImportDialog dialog( this );
+	dialog.exec();
+}
+
+
+
+void MainForm::action_instruments_saveLibrary()
+{
+	SoundLibrarySaveDialog dialog( this );
+	dialog.exec();
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->test_expandedItems();
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
+}
+
+
+
+
+
+
+
+///
+/// Window close event
+///
+void MainForm::closeEvent( QCloseEvent* ev )
+{
+	if ( action_file_exit() == false ) {
+		// don't close!!!
+		ev->ignore();
+		return;
+	}
+
+	ev->accept();
+}
+
+
+
+void MainForm::action_file_export() {
+	if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	ExportSongDialog *dialog = new ExportSongDialog(this);
+	dialog->exec();
+	delete dialog;
+}
+
+
+
+void MainForm::action_window_showDrumkitManagerPanel()
+{
+	InstrumentRack *pPanel = HydrogenApp::get_instance()->getInstrumentRack();
+	pPanel->setHidden( pPanel->isVisible() );
+}
+
+
+
+
+void MainForm::closeAll() {
+	// save window properties in the preferences files
+	Preferences *pref = Preferences::get_instance();
+
+	// mainform
+	WindowProperties mainFormProp;
+	mainFormProp.x = x();
+	mainFormProp.y = y();
+	mainFormProp.height = height();
+	mainFormProp.width = width();
+	pref->setMainFormProperties( mainFormProp );
+
+	// Save mixer properties
+	WindowProperties mixerProp;
+	mixerProp.x = h2app->getMixer()->x();
+	mixerProp.y = h2app->getMixer()->y();
+	mixerProp.width = h2app->getMixer()->width();
+	mixerProp.height = h2app->getMixer()->height();
+	mixerProp.visible = h2app->getMixer()->isVisible();
+	pref->setMixerProperties( mixerProp );
+
+	// save pattern editor properties
+	WindowProperties patternEditorProp;
+	patternEditorProp.x = h2app->getPatternEditorPanel()->x();
+	patternEditorProp.y = h2app->getPatternEditorPanel()->y();
+	patternEditorProp.width = h2app->getPatternEditorPanel()->width();
+	patternEditorProp.height = h2app->getPatternEditorPanel()->height();
+	patternEditorProp.visible = h2app->getPatternEditorPanel()->isVisible();
+	pref->setPatternEditorProperties( patternEditorProp );
+
+	// save song editor properties
+	WindowProperties songEditorProp;
+	songEditorProp.x = h2app->getSongEditorPanel()->x();
+	songEditorProp.y = h2app->getSongEditorPanel()->y();
+	songEditorProp.width = h2app->getSongEditorPanel()->width();
+	songEditorProp.height = h2app->getSongEditorPanel()->height();
+
+	QSize size = h2app->getSongEditorPanel()->frameSize();
+	songEditorProp.visible = h2app->getSongEditorPanel()->isVisible();
+	pref->setSongEditorProperties( songEditorProp );
+
+
+	// save audio engine info properties
+	WindowProperties audioEngineInfoProp;
+	audioEngineInfoProp.x = h2app->getAudioEngineInfoForm()->x();
+	audioEngineInfoProp.y = h2app->getAudioEngineInfoForm()->y();
+	audioEngineInfoProp.visible = h2app->getAudioEngineInfoForm()->isVisible();
+	pref->setAudioEngineInfoProperties( audioEngineInfoProp );
+
+
+#ifdef LADSPA_SUPPORT
+	// save LADSPA FX window properties
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		WindowProperties prop;
+		prop.x = h2app->getLadspaFXProperties(nFX)->x();
+		prop.y = h2app->getLadspaFXProperties(nFX)->y();
+		prop.visible= h2app->getLadspaFXProperties(nFX)->isVisible();
+		pref->setLadspaProperties(nFX, prop);
+	}
+#endif
+
+	m_pQApp->quit();
+}
+
+
+
+// keybindings..
+
+void MainForm::onPlayStopAccelEvent()
+{
+	int nState = Hydrogen::get_instance()->getState();
+	switch (nState) {
+		case STATE_READY:
+			Hydrogen::get_instance()->sequencer_play();
+			break;
+
+		case STATE_PLAYING:
+			Hydrogen::get_instance()->sequencer_stop();
+			break;
+
+		default:
+			ERRORLOG( "[MainForm::onPlayStopAccelEvent()] Unhandled case." );
+	}
+}
+
+
+
+void MainForm::onRestartAccelEvent()
+{
+	Hydrogen* pEngine = Hydrogen::get_instance();
+	pEngine->setPatternPos( 0 );
+}
+
+
+
+void MainForm::onBPMPlusAccelEvent()
+{
+	Hydrogen* pEngine = Hydrogen::get_instance();
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+	Song* pSong = pEngine->getSong();
+	if (pSong->__bpm  < 300) {
+		pEngine->setBPM( pSong->__bpm + 0.1 );
+	}
+	AudioEngine::get_instance()->unlock();
+}
+
+
+
+void MainForm::onBPMMinusAccelEvent()
+{
+	Hydrogen* pEngine = Hydrogen::get_instance();
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+	Song* pSong = pEngine->getSong();
+	if (pSong->__bpm > 40 ) {
+		pEngine->setBPM( pSong->__bpm - 0.1 );
+	}
+	AudioEngine::get_instance()->unlock();
+}
+
+
+
+void MainForm::onSaveAsAccelEvent()
+{
+	action_file_save_as();
+}
+
+
+
+void MainForm::onSaveAccelEvent()
+{
+	action_file_save();
+}
+
+
+
+void MainForm::onOpenAccelEvent()
+{
+	action_file_open();
+}
+
+
+
+void MainForm::updateRecentUsedSongList()
+{
+	m_pRecentFilesMenu->clear();
+
+	Preferences *pPref = Preferences::get_instance();
+	vector<QString> recentUsedSongs = pPref->getRecentFiles();
+
+	QString sFilename;
+
+	for ( uint i = 0; i < recentUsedSongs.size(); ++i ) {
+		sFilename = recentUsedSongs[ i ];
+
+		if ( !sFilename.isEmpty() ) {
+			QAction *pAction = new QAction( this  );
+			pAction->setText( sFilename );
+			m_pRecentFilesMenu->addAction( pAction );
+		}
+	}
+}
+
+
+
+void MainForm::action_file_open_recent(QAction *pAction)
+{
+//	INFOLOG( pAction->text() );
+	openSongFile( pAction->text() );
+}
+
+
+
+void MainForm::openSongFile( const QString& sFilename )
+{
+ 	Hydrogen *engine = Hydrogen::get_instance();
+	if ( engine->getState() == STATE_PLAYING ) {
+                engine->sequencer_stop();
+	}
+
+	engine->m_timelinetagvector.clear();
+
+	h2app->closeFXProperties();
+	LocalFileMng mng;
+	Song *pSong = Song::load( sFilename );
+	if ( pSong == NULL ) {
+		QMessageBox::information( this, "Hydrogen", trUtf8("Error loading song.") );
+		return;
+	}
+
+
+	// add the new loaded song in the "last used song" vector
+	Preferences *pPref = Preferences::get_instance();
+	vector<QString> recentFiles = pPref->getRecentFiles();
+	recentFiles.insert( recentFiles.begin(), sFilename );
+	pPref->setRecentFiles( recentFiles );
+
+	h2app->setSong( pSong );
+
+	updateRecentUsedSongList();
+	engine->setSelectedPatternNumber( 0 );
+	HydrogenApp::get_instance()->getSongEditorPanel()->updatePositionRuler();
+	EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 );
+}
+
+
+
+void MainForm::initKeyInstMap()
+{
+
+	QString loc = QLocale::system().name();
+	int instr = 0;
+
+///POSIX Locale
+//locale for keyboardlayout QWERTZ
+// de_DE, de_AT, de_LU, de_CH, de
+
+//locale for keyboardlayout AZERTY
+// fr_BE, fr_CA, fr_FR, fr_LU, fr_CH
+
+//locale for keyboardlayout QWERTY
+// en_GB, en_US, en_ZA, usw.
+
+	if ( loc.contains( "de" ) || loc.contains( "DE" )){ ///QWERTZ
+		keycodeInstrumentMap[Qt::Key_Y] = instr++;
+		keycodeInstrumentMap[Qt::Key_S] = instr++;
+		keycodeInstrumentMap[Qt::Key_X] = instr++;
+		keycodeInstrumentMap[Qt::Key_D] = instr++;
+		keycodeInstrumentMap[Qt::Key_C] = instr++;
+		keycodeInstrumentMap[Qt::Key_V] = instr++;
+		keycodeInstrumentMap[Qt::Key_G] = instr++;
+		keycodeInstrumentMap[Qt::Key_B] = instr++;
+		keycodeInstrumentMap[Qt::Key_H] = instr++;
+		keycodeInstrumentMap[Qt::Key_N] = instr++;
+		keycodeInstrumentMap[Qt::Key_J] = instr++;
+		keycodeInstrumentMap[Qt::Key_M] = instr++;
+	
+		keycodeInstrumentMap[Qt::Key_Q] = instr++;
+		keycodeInstrumentMap[Qt::Key_2] = instr++;
+		keycodeInstrumentMap[Qt::Key_W] = instr++;
+		keycodeInstrumentMap[Qt::Key_3] = instr++;
+		keycodeInstrumentMap[Qt::Key_E] = instr++;
+		keycodeInstrumentMap[Qt::Key_R] = instr++;
+		keycodeInstrumentMap[Qt::Key_5] = instr++;
+		keycodeInstrumentMap[Qt::Key_T] = instr++;
+		keycodeInstrumentMap[Qt::Key_6] = instr++;
+		keycodeInstrumentMap[Qt::Key_Z] = instr++;
+		keycodeInstrumentMap[Qt::Key_7] = instr++;
+		keycodeInstrumentMap[Qt::Key_U] = instr++;
+	}
+	else if ( loc.contains( "fr" ) || loc.contains( "FR" )){ ///AZERTY
+		keycodeInstrumentMap[Qt::Key_W] = instr++;
+		keycodeInstrumentMap[Qt::Key_S] = instr++;
+		keycodeInstrumentMap[Qt::Key_X] = instr++;
+		keycodeInstrumentMap[Qt::Key_D] = instr++;
+		keycodeInstrumentMap[Qt::Key_C] = instr++;
+		keycodeInstrumentMap[Qt::Key_V] = instr++;
+		keycodeInstrumentMap[Qt::Key_G] = instr++;
+		keycodeInstrumentMap[Qt::Key_B] = instr++;
+		keycodeInstrumentMap[Qt::Key_H] = instr++;
+		keycodeInstrumentMap[Qt::Key_N] = instr++;
+		keycodeInstrumentMap[Qt::Key_J] = instr++;
+		keycodeInstrumentMap[Qt::Key_Question] = instr++;
+	
+		keycodeInstrumentMap[Qt::Key_A] = instr++;
+		keycodeInstrumentMap[Qt::Key_2] = instr++;
+		keycodeInstrumentMap[Qt::Key_Z] = instr++;
+		keycodeInstrumentMap[Qt::Key_3] = instr++;
+		keycodeInstrumentMap[Qt::Key_E] = instr++;
+		keycodeInstrumentMap[Qt::Key_R] = instr++;
+		keycodeInstrumentMap[Qt::Key_5] = instr++;
+		keycodeInstrumentMap[Qt::Key_T] = instr++;
+		keycodeInstrumentMap[Qt::Key_6] = instr++;
+		keycodeInstrumentMap[Qt::Key_Y] = instr++;
+		keycodeInstrumentMap[Qt::Key_7] = instr++;
+		keycodeInstrumentMap[Qt::Key_U] = instr++;
+	}else
+	{ /// default QWERTY
+		keycodeInstrumentMap[Qt::Key_Z] = instr++;
+		keycodeInstrumentMap[Qt::Key_S] = instr++;
+		keycodeInstrumentMap[Qt::Key_X] = instr++;
+		keycodeInstrumentMap[Qt::Key_D] = instr++;
+		keycodeInstrumentMap[Qt::Key_C] = instr++;
+		keycodeInstrumentMap[Qt::Key_V] = instr++;
+		keycodeInstrumentMap[Qt::Key_G] = instr++;
+		keycodeInstrumentMap[Qt::Key_B] = instr++;
+		keycodeInstrumentMap[Qt::Key_H] = instr++;
+		keycodeInstrumentMap[Qt::Key_N] = instr++;
+		keycodeInstrumentMap[Qt::Key_J] = instr++;
+		keycodeInstrumentMap[Qt::Key_M] = instr++;
+	
+		keycodeInstrumentMap[Qt::Key_Q] = instr++;
+		keycodeInstrumentMap[Qt::Key_2] = instr++;
+		keycodeInstrumentMap[Qt::Key_W] = instr++;
+		keycodeInstrumentMap[Qt::Key_3] = instr++;
+		keycodeInstrumentMap[Qt::Key_E] = instr++;
+		keycodeInstrumentMap[Qt::Key_R] = instr++;
+		keycodeInstrumentMap[Qt::Key_5] = instr++;
+		keycodeInstrumentMap[Qt::Key_T] = instr++;
+		keycodeInstrumentMap[Qt::Key_6] = instr++;
+		keycodeInstrumentMap[Qt::Key_Y] = instr++;
+		keycodeInstrumentMap[Qt::Key_7] = instr++;
+		keycodeInstrumentMap[Qt::Key_U] = instr++;
+	}
+
+	/*
+	// QWERTY etc.... rows of the keyboard
+	keycodeInstrumentMap[Qt::Key_Q] = instr++;
+	keycodeInstrumentMap[Qt::Key_W] = instr++;
+	keycodeInstrumentMap[Qt::Key_E] = instr++;
+	keycodeInstrumentMap[Qt::Key_R] = instr++;
+	keycodeInstrumentMap[Qt::Key_T] = instr++;
+	keycodeInstrumentMap[Qt::Key_Y] = instr++;
+	keycodeInstrumentMap[Qt::Key_U] = instr++;
+	keycodeInstrumentMap[Qt::Key_I] = instr++;
+	keycodeInstrumentMap[Qt::Key_O] = instr++;
+	keycodeInstrumentMap[Qt::Key_P] = instr++;
+	keycodeInstrumentMap[Qt::Key_BracketLeft] = instr++;
+	keycodeInstrumentMap[Qt::Key_BracketRight] = instr++;
+	keycodeInstrumentMap[Qt::Key_A] = instr++;
+	keycodeInstrumentMap[Qt::Key_S] = instr++;
+	keycodeInstrumentMap[Qt::Key_D] = instr++;
+	keycodeInstrumentMap[Qt::Key_F] = instr++;
+	keycodeInstrumentMap[Qt::Key_G] = instr++;
+	keycodeInstrumentMap[Qt::Key_H] = instr++;
+	keycodeInstrumentMap[Qt::Key_J] = instr++;
+	keycodeInstrumentMap[Qt::Key_K] = instr++;
+	keycodeInstrumentMap[Qt::Key_L] = instr++;
+	keycodeInstrumentMap[Qt::Key_Semicolon] = instr++;
+	keycodeInstrumentMap[Qt::Key_Apostrophe] = instr++;
+	keycodeInstrumentMap[Qt::Key_Z] = instr++;
+	keycodeInstrumentMap[Qt::Key_X] = instr++;
+	keycodeInstrumentMap[Qt::Key_C] = instr++;
+	keycodeInstrumentMap[Qt::Key_V] = instr++;
+	keycodeInstrumentMap[Qt::Key_B] = instr++;
+	keycodeInstrumentMap[Qt::Key_N] = instr++;
+	keycodeInstrumentMap[Qt::Key_M] = instr++;
+	keycodeInstrumentMap[Qt::Key_Comma] = instr++;
+	keycodeInstrumentMap[Qt::Key_Period] = instr++;
+*/
+}
+
+
+
+bool MainForm::eventFilter( QObject *o, QEvent *e )
+{
+	UNUSED( o );
+
+	if ( e->type() == QEvent::KeyPress) {
+		// special processing for key press
+		QKeyEvent *k = (QKeyEvent *)e;
+
+		// qDebug( "Got key press for instrument '%c'", k->ascii() );
+		int songnumber = 0;
+
+		switch (k->key()) {
+			case Qt::Key_Space:
+				onPlayStopAccelEvent();
+				return TRUE; // eat event
+
+
+			case Qt::Key_Comma:
+				Hydrogen::get_instance()->handleBeatCounter();
+				return TRUE; // eat even
+				break;
+
+			case Qt::Key_Backspace:
+				onRestartAccelEvent();
+				return TRUE; // eat event
+				break;
+
+			case Qt::Key_Plus:
+				onBPMPlusAccelEvent();
+				return TRUE; // eat event
+				break;
+
+			case Qt::Key_Minus:
+				onBPMMinusAccelEvent();
+				return TRUE; // eat event
+				break;
+
+			case Qt::Key_Backslash:
+				Hydrogen::get_instance()->onTapTempoAccelEvent();
+				return TRUE; // eat event
+				break;
+
+			case  Qt::Key_S | Qt::CTRL:
+				onSaveAccelEvent();
+				return TRUE;
+				break;
+			
+			case  Qt::Key_F5 :
+				if( Hydrogen::get_instance()->m_PlayList.size() == 0)
+					break;
+				Playlist::get_instance()->setPrevSongPlaylist();
+				songnumber = Playlist::get_instance()->getActiveSongNumber();
+				HydrogenApp::get_instance()->setScrollStatusBarMessage( trUtf8( "Playlist: Set song No. %1" ).arg( songnumber +1 ), 5000 );
+				return TRUE;
+				break;
+
+			case  Qt::Key_F6 :
+				if( Hydrogen::get_instance()->m_PlayList.size() == 0)
+					break;
+				Playlist::get_instance()->setNextSongPlaylist();
+				songnumber = Playlist::get_instance()->getActiveSongNumber();
+				HydrogenApp::get_instance()->setScrollStatusBarMessage( trUtf8( "Playlist: Set song No. %1" ).arg( songnumber +1 ), 5000 );
+				return TRUE;
+				break;
+
+			case  Qt::Key_F12 : //panic button stop all playing notes
+				Hydrogen::get_instance()->__panic();
+//				QMessageBox::information( this, "Hydrogen", trUtf8( "Panic" ) );
+				return TRUE;
+				break;
+
+			case  Qt::Key_F9 : // Qt::Key_Left do not work. Some ideas ?
+				Hydrogen::get_instance()->setPatternPos( Hydrogen::get_instance()->getPatternPos() - 1 );
+				return TRUE;
+				break;
+
+			case  Qt::Key_F10 : // Qt::Key_Right do not work. Some ideas ?
+				Hydrogen::get_instance()->setPatternPos( Hydrogen::get_instance()->getPatternPos() + 1 );
+				return TRUE;
+				break;
+			
+			case Qt::Key_L :
+				Hydrogen::get_instance()->togglePlaysSelected();
+				QString msg = Preferences::get_instance()->patternModePlaysSelected() ? "Single pattern mode" : "Stacked pattern mode";
+				HydrogenApp::get_instance()->setStatusBarMessage( msg, 5000 );
+				HydrogenApp::get_instance()->getSongEditorPanel()->setModeActionBtn( Preferences::get_instance()->patternModePlaysSelected() );
+				HydrogenApp::get_instance()->getSongEditorPanel()->updateAll();
+				
+				return TRUE;
+			
+		// 	QAccel *a = new QAccel( this );
+// 	a->connectItem( a->insertItem(Key_S + CTRL), this, SLOT( onSaveAccelEvent() ) );
+// 	a->connectItem( a->insertItem(Key_O + CTRL), this, SLOT( onOpenAccelEvent() ) );
+
+		}
+
+		// virtual keyboard handling
+		map<int,int>::iterator found = keycodeInstrumentMap.find ( k->key() );
+		if (found != keycodeInstrumentMap.end()) {
+//			INFOLOG( "[eventFilter] virtual keyboard event" );
+			// insert note at the current column in time
+			// if event recording enabled
+			int row = (*found).second;
+			Hydrogen* engine = Hydrogen::get_instance();
+
+			float velocity = 0.8;
+			float pan_L = 1.0;
+			float pan_R = 1.0;
+
+			engine->addRealtimeNote (row, velocity, pan_L, pan_R, NULL, NULL, NULL , row + 36);
+
+			return TRUE; // eat event
+		}
+		else {
+			return FALSE; // let it go
+		}
+        }
+	else {
+		return FALSE; // standard event processing
+        }
+}
+
+
+
+
+
+/// print the object map
+void MainForm::action_debug_printObjects()
+{
+	INFOLOG( "[action_debug_printObjects]" );
+	Object::print_object_map();
+}
+
+
+
+
+
+
+void MainForm::action_file_export_midi()
+{
+	if ( ((Hydrogen::get_instance())->getState() == STATE_PLAYING) ) {
+		Hydrogen::get_instance()->sequencer_stop();
+	}
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode(QFileDialog::AnyFile);
+	fd->setFilter( trUtf8("Midi file (*.mid)") );
+	fd->setDirectory( QDir::homePath() );
+	fd->setWindowTitle( trUtf8( "Export MIDI file" ) );
+	fd->setAcceptMode( QFileDialog::AcceptSave );
+//	fd->setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	QString sFilename;
+	if ( fd->exec() == QDialog::Accepted ) {
+		sFilename = fd->selectedFiles().first();
+	}
+
+	if ( !sFilename.isEmpty() ) {
+		if ( sFilename.endsWith(".mid") == false ) {
+			sFilename += ".mid";
+		}
+
+		Song *pSong = Hydrogen::get_instance()->getSong();
+
+		// create the Standard Midi File object
+		SMFWriter *pSmfWriter = new SMFWriter();
+		pSmfWriter->save( sFilename, pSong );
+
+		delete pSmfWriter;
+	}
+}
+
+
+
+void MainForm::errorEvent( int nErrorCode )
+{
+	//ERRORLOG( "[errorEvent]" );
+
+	QString msg;
+	switch (nErrorCode) {
+		case Hydrogen::UNKNOWN_DRIVER:
+			msg = trUtf8( "Unknown audio driver" );
+			break;
+
+		case Hydrogen::ERROR_STARTING_DRIVER:
+			msg = trUtf8( "Error starting audio driver" );
+			break;
+
+		case Hydrogen::JACK_SERVER_SHUTDOWN:
+			msg = trUtf8( "Jack driver: server shutdown" );
+			break;
+
+		case Hydrogen::JACK_CANNOT_ACTIVATE_CLIENT:
+			msg = trUtf8( "Jack driver: cannot activate client" );
+			break;
+
+		case Hydrogen::JACK_CANNOT_CONNECT_OUTPUT_PORT:
+			msg = trUtf8( "Jack driver: cannot connect output port" );
+			break;
+
+		case Hydrogen::JACK_ERROR_IN_PORT_REGISTER:
+			msg = trUtf8( "Jack driver: error in port register" );
+			break;
+
+		default:
+			msg = QString( trUtf8( "Unknown error %1" ) ).arg( nErrorCode );
+	}
+	QMessageBox::information( this, "Hydrogen", msg );
+}
+
+
+void MainForm::action_file_songProperties()
+{
+	SongPropertiesDialog *pDialog = new SongPropertiesDialog( this );
+	if ( pDialog->exec() == QDialog::Accepted ) {
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+	}
+	delete pDialog;
+}
+
+
+void MainForm::action_window_showPatternEditor()
+{
+	bool isVisible = HydrogenApp::get_instance()->getPatternEditorPanel()->isVisible();
+	HydrogenApp::get_instance()->getPatternEditorPanel()->setHidden( isVisible );
+}
+
+
+void MainForm::showDevelWarning()
+{
+
+	//set this to 'false' for the case that you want to make a release..
+	if ( true ) {
+                Preferences *pref = Preferences::get_instance();
+                bool isDevelWarningEnabled = pref->getShowDevelWarning();
+                if(isDevelWarningEnabled) {
+
+                        QString msg = trUtf8( "You're using a development version of Hydrogen, please help us reporting bugs or suggestions in the hydrogen-devel mailing list.<br><br>Thank you!" );
+                        QMessageBox develMessageBox( this );
+                        develMessageBox.setText( msg );
+                        develMessageBox.addButton( QMessageBox::Ok );
+                        develMessageBox.addButton( trUtf8( "Don't show this message anymore" ) , QMessageBox::AcceptRole );
+
+                        if( develMessageBox.exec() == 0 ){
+                                //don't show warning again
+                                pref->setShowDevelWarning( false );
+                        }
+          }
+
+
+        }
+}
+
+
+
+QString MainForm::getAutoSaveFilename()
+{
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	assert( pSong );
+	QString sOldFilename = pSong->get_filename();
+	QString newName = "autosave.h2song";
+
+	if ( !sOldFilename.isEmpty() ) {
+		newName = sOldFilename.left( sOldFilename.length() - 7 ) + ".autosave.h2song";
+	}
+
+	return newName;
+}
+
+
+
+void MainForm::onAutoSaveTimer()
+{
+	//INFOLOG( "[onAutoSaveTimer]" );
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	assert( pSong );
+	QString sOldFilename = pSong->get_filename();
+
+	pSong->save( getAutoSaveFilename() );
+
+	pSong->set_filename(sOldFilename);
+
+/*
+	Song *pSong = h2app->getSong();
+	if (pSong->getFilename() == "") {
+		pSong->save( "autosave.h2song" );
+		return;
+	}
+
+	action_file_save();
+*/
+}
+
+
+void MainForm::onPlaylistDisplayTimer()
+{
+	if( Hydrogen::get_instance()->m_PlayList.size() == 0)
+		return;
+	int songnumber = Playlist::get_instance()->getActiveSongNumber();
+	QString songname;
+	if ( songnumber == -1 )
+			return;
+
+	if ( Hydrogen::get_instance()->getSong()->__name == "Untitled Song" ){
+		songname = Hydrogen::get_instance()->getSong()->get_filename(); 
+	}else
+	{
+		songname = Hydrogen::get_instance()->getSong()->__name;
+	}
+	QString message = (trUtf8("Playlist: Song No. %1").arg( songnumber + 1)) + QString("  ---  Songname: ") + songname + QString("  ---  Author: ") + Hydrogen::get_instance()->getSong()->__author;
+	HydrogenApp::get_instance()->setScrollStatusBarMessage( message, 2000 );
+}
+
+// Returns true if unsaved changes are successfully handled (saved, discarded, etc.)
+// Returns false if not (i.e. Cancel)
+bool MainForm::handleUnsavedChanges()
+{
+	bool done = false;
+	bool rv = true;
+	while ( !done && Hydrogen::get_instance()->getSong()->__is_modified ) {
+		switch(
+				QMessageBox::information( this, "Hydrogen",
+						trUtf8("\nThe document contains unsaved changes.\n"
+						"Do you want to save the changes?\n"),
+						trUtf8("&Save"), trUtf8("&Discard"), trUtf8("&Cancel"),
+						0,      // Enter == button 0
+						2 ) ) { // Escape == button 2
+			case 0: // Save clicked or Alt+S pressed or Enter pressed.
+				// If the save fails, the __is_modified flag will still be true
+			    if ( ! Hydrogen::get_instance()->getSong()->get_filename().isEmpty() ) {
+					action_file_save();
+				} else {
+					// never been saved
+					action_file_save_as();
+				}
+				// save
+				break;
+			case 1: // Discard clicked or Alt+D pressed
+				// don't save but exit
+				done = true;
+				break;
+			case 2: // Cancel clicked or Alt+C pressed or Escape pressed
+				// don't exit
+				done = true;
+				rv = false;
+				break;
+		}
+	}
+	return rv;
+}
+
+void MainForm::usr1SignalHandler(int)
+ {
+     char a = 1;
+     ::write(sigusr1Fd[0], &a, sizeof(a));
+ }
+
+void MainForm::handleSigUsr1()
+{
+    snUsr1->setEnabled(false);
+    char tmp;
+    ::read(sigusr1Fd[1], &tmp, sizeof(tmp));
+
+    action_file_save();
+    snUsr1->setEnabled(true);
+}
+
+
Index: /branches/tabbedInterface/gui/src/PatternPropertiesDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PatternPropertiesDialog.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/PatternPropertiesDialog.cpp	(revision 1244)
@@ -0,0 +1,166 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "PatternPropertiesDialog.h"
+#include "Skin.h"
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/Preferences.h>
+
+using namespace std;
+using namespace H2Core;
+
+PatternPropertiesDialog::PatternPropertiesDialog(QWidget* parent, Pattern *pattern, bool savepattern)
+ : QDialog(parent)
+{
+	setupUi( this );
+	setWindowTitle( trUtf8( "Pattern properties" ) );
+
+	this->pattern = pattern;
+
+	patternNameTxt->setText( pattern->get_name() );
+	patternNameTxt->selectAll();
+
+	QString category = pattern->get_category();
+	
+	if ( category == "" ){
+		category = "not_categorized";
+	}
+	categoryComboBox->addItem( category );
+
+	Preferences *pPref = H2Core::Preferences::get_instance();
+
+	std::list<QString>::const_iterator cur_patternCategories;
+	
+	if ( pPref->m_patternCategories.size() == 0 ) {
+		pPref->m_patternCategories.push_back( "not_categorized" );
+	}
+
+	//categoryComboBox->clear();
+
+	for( cur_patternCategories = pPref->m_patternCategories.begin(); cur_patternCategories != pPref->m_patternCategories.end(); ++cur_patternCategories )
+	{
+		if ( categoryComboBox->currentText() != *cur_patternCategories ){
+			categoryComboBox->addItem( *cur_patternCategories );
+		}
+	}
+
+	defaultNameCheck( pattern->get_name(), savepattern );
+	okBtn->setEnabled(true);
+}
+
+
+/**
+ * Destructor
+ */
+PatternPropertiesDialog::~PatternPropertiesDialog()
+{
+}
+
+
+void PatternPropertiesDialog::on_cancelBtn_clicked()
+{
+	reject();
+}
+
+
+void PatternPropertiesDialog::on_okBtn_clicked()
+{
+	QString pattName = patternNameTxt->text();
+	QString pattCategory = categoryComboBox->currentText();
+
+	Preferences *pPref = H2Core::Preferences::get_instance();
+	std::list<QString>::const_iterator cur_testpatternCategories;
+
+	bool test = true;
+	for( cur_testpatternCategories = pPref->m_patternCategories.begin(); cur_testpatternCategories != pPref->m_patternCategories.end(); ++cur_testpatternCategories )
+	{
+		if ( categoryComboBox->currentText() == *cur_testpatternCategories ){
+			test = false;
+		}
+	}
+
+	if (test == true ) {
+		pPref->m_patternCategories.push_back( pattCategory );
+	}
+
+	pattern->set_name(pattName);
+	pattern->set_category( pattCategory );
+	accept();
+}
+
+void PatternPropertiesDialog::defaultNameCheck( QString pattName, bool savepattern )
+{
+
+	PatternList *patternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
+	
+	for (uint i = 0; i < patternList->get_size(); i++) {
+		if ( patternList->get(i)->get_name() == pattName) {
+			if (savepattern){
+				patternNameTxt->setText( trUtf8( "%1#2").arg(patternList->get(i)->get_name()) );
+			}
+			else
+			{
+				patternNameTxt->setText( trUtf8( "%1").arg(patternList->get(i)->get_name()) );
+			}
+		}
+	}
+}
+
+
+bool PatternPropertiesDialog::nameCheck( QString pattName )
+{
+	if (pattName == "") {
+		return false;
+	}
+	PatternList *patternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
+	
+	for (uint i = 0; i < patternList->get_size(); i++) {
+		if ( patternList->get(i)->get_name() == pattName) {
+			return false;
+		}
+	}
+	return true;
+}
+
+
+void PatternPropertiesDialog::on_categoryComboBox_editTextChanged()
+{
+	if ( categoryComboBox->currentText() == pattern->get_category() ) {
+		okBtn->setEnabled( false );
+	}
+	else {
+		okBtn->setEnabled(true);
+	}
+}
+
+
+void PatternPropertiesDialog::on_patternNameTxt_textChanged()
+{
+	if ( nameCheck( patternNameTxt->text() ) ) {
+		okBtn->setEnabled( true );
+	}
+	else {
+		okBtn->setEnabled( false );
+	}
+}
Index: /branches/tabbedInterface/gui/src/InstrumentRack.h
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentRack.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/InstrumentRack.h	(revision 377)
@@ -0,0 +1,59 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef INSTRUMENT_RACK_H
+#define INSTRUMENT_RACK_H
+
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+
+class ToggleButton;
+class SoundLibraryPanel;
+
+class InstrumentRack : public QWidget, private Object
+{
+	Q_OBJECT
+	public:
+		InstrumentRack( QWidget *pParent );
+		~InstrumentRack();
+
+		SoundLibraryPanel* getSoundLibraryPanel() {	return m_pSoundLibraryPanel;	}
+
+	private slots:
+		void on_showSoundLibraryBtnClicked();
+		void on_showInstrumentEditorBtnClicked();
+
+
+	private:
+		/// button for showing the Sound Library
+		ToggleButton *m_pShowSoundLibraryBtn;
+
+		/// button for showing the Instrument Editor
+		ToggleButton *m_pShowInstrumentEditorBtn;
+
+		SoundLibraryPanel* m_pSoundLibraryPanel;
+
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/HydrogenApp.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/HydrogenApp.cpp	(revision 1459)
+++ /branches/tabbedInterface/gui/src/HydrogenApp.cpp	(revision 1459)
@@ -0,0 +1,499 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "version.h"
+
+#include "HydrogenApp.h"
+#include "Skin.h"
+#include "PreferencesDialog.h"
+#include "MainForm.h"
+#include "PlayerControl.h"
+#include "AudioEngineInfoForm.h"
+#include "HelpBrowser.h"
+#include "LadspaFXProperties.h"
+#include "InstrumentRack.h"
+
+#include "PatternEditor/PatternEditorPanel.h"
+#include "InstrumentEditor/InstrumentEditorPanel.h"
+#include "SongEditor/SongEditor.h"
+#include "SongEditor/SongEditorPanel.h"
+#include "PlaylistEditor/PlaylistDialog.h"
+#include "SampleEditor/SampleEditor.h"
+#include "MetroBlinker.h"
+
+#include "Mixer/Mixer.h"
+#include "Mixer/MixerLine.h"
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/fx/LadspaFX.h>
+#include <hydrogen/Preferences.h>
+//#include <hydrogen/sample.h>
+
+#include <QtGui>
+
+using namespace H2Core;
+
+HydrogenApp* HydrogenApp::m_pInstance = NULL;
+
+HydrogenApp::HydrogenApp( MainForm *pMainForm, Song *pFirstSong )
+ : Object( "HydrogenApp" )
+ , m_pMainForm( pMainForm )
+ , m_pMixer( NULL )
+ , m_pPatternEditorPanel( NULL )
+ , m_pAudioEngineInfoForm( NULL )
+ , m_pSongEditorPanel( NULL )
+ , m_pHelpBrowser( NULL )
+ , m_pFirstTimeInfo( NULL )
+ , m_pPlayerControl( NULL )
+ , m_pPlaylistDialog( NULL )
+ , m_pSampleEditor( NULL )
+ , m_pMetroBlinker( NULL )
+
+{
+	m_pInstance = this;
+
+	m_pEventQueueTimer = new QTimer(this);
+	connect( m_pEventQueueTimer, SIGNAL( timeout() ), this, SLOT( onEventQueueTimer() ) );
+	m_pEventQueueTimer->start(50);	// update at 20 fps
+
+
+	// Create the audio engine :)
+	Hydrogen::create_instance();
+	Hydrogen::get_instance()->setSong( pFirstSong );
+	Preferences::get_instance()->setLastSongFilename( pFirstSong->get_filename() );
+
+	// set initial title
+	QString qsSongName( pFirstSong->__name );
+	if( qsSongName == "Untitled Song" && !pFirstSong->get_filename().isEmpty() ){
+		qsSongName = pFirstSong->get_filename();
+		qsSongName = qsSongName.section( '/', -1 );
+	}
+
+        setWindowTitle( qsSongName  );
+
+	Preferences *pPref = Preferences::get_instance();
+
+	setupSinglePanedInterface();
+
+	// restore audio engine form properties
+	m_pAudioEngineInfoForm = new AudioEngineInfoForm( 0 );
+	WindowProperties audioEngineInfoProp = pPref->getAudioEngineInfoProperties();
+	m_pAudioEngineInfoForm->move( audioEngineInfoProp.x, audioEngineInfoProp.y );
+	if ( audioEngineInfoProp.visible ) {
+		m_pAudioEngineInfoForm->show();
+	}
+	else {
+		m_pAudioEngineInfoForm->hide();
+	}
+	
+	m_pPlaylistDialog = new PlaylistDialog( 0 );
+	m_pMetroBlinker = new MetroBlinker( 0 );
+//	m_pSampleEditor = new SampleEditor( 0 );
+	
+	showInfoSplash();	// First time information
+}
+
+
+
+HydrogenApp::~HydrogenApp()
+{
+	INFOLOG( "[~HydrogenApp]" );
+	m_pEventQueueTimer->stop();
+
+	delete m_pHelpBrowser;
+	delete m_pAudioEngineInfoForm;
+	delete m_pMixer;
+	delete m_pPlaylistDialog;
+	delete m_pMetroBlinker;
+	delete m_pSampleEditor;
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	if (engine) {
+		H2Core::Song * song = engine->getSong();
+		// Hydrogen calls removeSong on from its destructor, so here we just delete the objects:
+		delete engine;
+		delete song;
+	}
+
+	#ifdef LADSPA_SUPPORT
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		delete m_pLadspaFXProperties[nFX];
+	}
+	#endif
+	
+}
+
+
+
+/// Return an HydrogenApp m_pInstance
+HydrogenApp* HydrogenApp::get_instance() {
+	if (m_pInstance == NULL) {
+		std::cerr << "Error! HydrogenApp::get_instance (m_pInstance = NULL)" << std::endl;
+	}
+	return m_pInstance;
+}
+
+
+
+
+void HydrogenApp::setupSinglePanedInterface()
+{
+	Preferences *pPref = Preferences::get_instance();
+
+	// MAINFORM
+	WindowProperties mainFormProp = pPref->getMainFormProperties();
+	m_pMainForm->resize( mainFormProp.width, mainFormProp.height );
+	m_pMainForm->move( mainFormProp.x, mainFormProp.y );
+
+	QSplitter *pSplitter = new QSplitter( NULL );
+	pSplitter->setOrientation( Qt::Vertical );
+	pSplitter->setOpaqueResize( true );
+
+	// SONG EDITOR
+	m_pSongEditorPanel = new SongEditorPanel( pSplitter );
+	WindowProperties songEditorProp = pPref->getSongEditorProperties();
+	m_pSongEditorPanel->resize( songEditorProp.width, songEditorProp.height );
+
+	// this HBox will contain the InstrumentRack and the Pattern editor
+	QWidget *pSouthPanel = new QWidget( pSplitter );
+	QHBoxLayout *pEditorHBox = new QHBoxLayout();
+	pEditorHBox->setSpacing( 5 );
+	pEditorHBox->setMargin( 0 );
+	pSouthPanel->setLayout( pEditorHBox );
+
+	// INSTRUMENT RACK
+	m_pInstrumentRack = new InstrumentRack( NULL );
+
+	// PATTERN EDITOR
+	m_pPatternEditorPanel = new PatternEditorPanel( NULL );
+	WindowProperties patternEditorProp = pPref->getPatternEditorProperties();
+	m_pPatternEditorPanel->resize( patternEditorProp.width, patternEditorProp.height );
+
+	pEditorHBox->addWidget( m_pPatternEditorPanel );
+	pEditorHBox->addWidget( m_pInstrumentRack );
+
+	// PLayer control
+	m_pPlayerControl = new PlayerControl( NULL );
+
+
+	QWidget *mainArea = new QWidget( m_pMainForm );	// this is the main widget
+	m_pMainForm->setCentralWidget( mainArea );
+
+	// LAYOUT!!
+	QVBoxLayout *pMainVBox = new QVBoxLayout();
+	pMainVBox->setSpacing( 5 );
+	pMainVBox->setMargin( 0 );
+	pMainVBox->addWidget( m_pPlayerControl );
+	pMainVBox->addWidget( pSplitter );
+
+	mainArea->setLayout( pMainVBox );
+
+
+
+
+	// MIXER
+	m_pMixer = new Mixer(0);
+	WindowProperties mixerProp = pPref->getMixerProperties();
+	m_pMixer->resize( mixerProp.width, mixerProp.height );
+	m_pMixer->move( mixerProp.x, mixerProp.y );
+	m_pMixer->updateMixer();
+	if ( mixerProp.visible ) {
+		m_pMixer->show();
+	}
+	else {
+		m_pMixer->hide();
+	}
+
+
+	// HELP BROWSER
+	QString sDocPath = QString( DataPath::get_data_path() ) + "/doc";
+	QString sDocURI = sDocPath + "/manual.html";
+	m_pHelpBrowser = new SimpleHTMLBrowser( NULL, sDocPath, sDocURI, SimpleHTMLBrowser::MANUAL );
+
+#ifdef LADSPA_SUPPORT
+	// LADSPA FX
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		m_pLadspaFXProperties[nFX] = new LadspaFXProperties( NULL, nFX );
+		m_pLadspaFXProperties[nFX]->hide();
+		WindowProperties prop = pPref->getLadspaProperties(nFX);
+		m_pLadspaFXProperties[nFX]->move( prop.x, prop.y );
+		if ( prop.visible ) {
+			m_pLadspaFXProperties[nFX]->show();
+		}
+		else {
+			m_pLadspaFXProperties[nFX]->hide();
+		}
+	}
+#endif
+
+//	m_pMainForm->showMaximized();
+}
+
+
+void HydrogenApp::closeFXProperties()
+{
+#ifdef LADSPA_SUPPORT
+	for (uint nFX = 0; nFX < MAX_FX; nFX++) {
+		m_pLadspaFXProperties[nFX]->close();
+	}
+#endif
+}
+
+
+
+void HydrogenApp::setSong(Song* song)
+{
+
+
+	Song* oldSong = (Hydrogen::get_instance())->getSong();
+	if (oldSong != NULL) {
+		(Hydrogen::get_instance())->removeSong();
+		delete oldSong;
+		oldSong = NULL;
+	}
+
+	Hydrogen::get_instance()->setSong( song );
+	Preferences::get_instance()->setLastSongFilename( song->get_filename() );
+
+	m_pSongEditorPanel->updateAll();
+	m_pPatternEditorPanel->updateSLnameLabel();
+
+	QString songName( song->__name );
+	if( songName == "Untitled Song" && !song->get_filename().isEmpty() ){
+		songName = song->get_filename();
+		songName = songName.section( '/', -1 );
+	}
+        setWindowTitle( songName  );
+
+	m_pMainForm->updateRecentUsedSongList();
+}
+
+
+
+void HydrogenApp::showMixer(bool show)
+{
+	m_pMixer->setVisible( show );
+}
+
+
+
+void HydrogenApp::showPreferencesDialog()
+{
+	PreferencesDialog preferencesDialog(m_pMainForm);
+	preferencesDialog.exec();
+}
+
+
+
+
+void HydrogenApp::setStatusBarMessage( const QString& msg, int msec )
+{
+	getPlayerControl()->showMessage( msg, msec );
+}
+
+void HydrogenApp::setWindowTitle( const QString& title){
+    m_pMainForm->setWindowTitle( ( "Hydrogen " + QString( get_version().c_str()) + QString( " - " ) + title ) );
+}
+
+void HydrogenApp::setScrollStatusBarMessage( const QString& msg, int msec, bool test )
+{
+	getPlayerControl()->showScrollMessage( msg, msec , test);
+}
+
+
+
+void HydrogenApp::showAudioEngineInfoForm()
+{
+	m_pAudioEngineInfoForm->hide();
+	m_pAudioEngineInfoForm->show();
+}
+
+void HydrogenApp::showPlaylistDialog()
+{
+	m_pPlaylistDialog->hide();
+	m_pPlaylistDialog->show();
+}
+
+
+void HydrogenApp::showMetroBlinker()
+{
+	m_pMetroBlinker->hide();
+	m_pMetroBlinker->show();
+}
+
+
+void HydrogenApp::showSampleEditor( QString name, int mSelectedLayer )
+{
+
+	if ( m_pSampleEditor ){
+		QApplication::setOverrideCursor(Qt::WaitCursor);
+		m_pSampleEditor->close();
+		delete m_pSampleEditor;
+		m_pSampleEditor = NULL;
+		QApplication::restoreOverrideCursor();
+	}
+	QApplication::setOverrideCursor(Qt::WaitCursor);	
+	m_pSampleEditor = new SampleEditor( 0, mSelectedLayer, name);
+	m_pSampleEditor->show();
+	QApplication::restoreOverrideCursor();
+}
+
+
+
+void HydrogenApp::showInfoSplash()
+{
+	QString sDocPath( DataPath::get_data_path().append( "/doc/infoSplash" ) );
+
+	QDir dir(sDocPath);
+	if ( !dir.exists() ) {
+		ERRORLOG( QString("[showInfoSplash] Directory ").append( sDocPath ).append( " not found." ) );
+		return;
+	}
+
+	QString sFilename;
+	int nNewsID = 0;
+	QFileInfoList list = dir.entryInfoList();
+
+	for ( int i =0; i < list.size(); ++i ) {
+		QString sFile = list.at( i ).fileName();
+
+		if ( sFile == "." || sFile == ".." ) {
+			continue;
+		}
+
+		int nPos = sFile.lastIndexOf( "-" );
+		QString sNewsID = sFile.mid( nPos + 1, sFile.length() - nPos - 1 );
+		int nID = sNewsID.toInt();
+		if ( nID > nNewsID ) {
+			sFilename = sFile;
+		}
+//		INFOLOG( "news: " + sFilename + " id: " + sNewsID );
+	}
+	INFOLOG( "[showInfoSplash] Selected news: " + sFilename );
+
+	QString sLastRead = Preferences::get_instance()->getLastNews();
+	if ( sLastRead != sFilename && !sFilename.isEmpty() ) {
+		QString sDocURI = sDocPath;
+		sDocURI.append( "/" ).append( sFilename );
+		SimpleHTMLBrowser *m_pFirstTimeInfo = new SimpleHTMLBrowser( m_pMainForm, sDocPath, sDocURI, SimpleHTMLBrowser::WELCOME );
+		if ( m_pFirstTimeInfo->exec() == QDialog::Accepted ) {
+			Preferences::get_instance()->setLastNews( sFilename );
+		}
+	}
+}
+
+void HydrogenApp::onDrumkitLoad( QString name ){
+	setStatusBarMessage( trUtf8( "Drumkit loaded: [%1]" ).arg( name ), 2000 );
+	m_pPatternEditorPanel->updateSLnameLabel( );
+}
+
+void HydrogenApp::enableDestructiveRecMode(){
+	m_pPatternEditorPanel->displayorHidePrePostCB();
+}
+
+
+void HydrogenApp::onEventQueueTimer()
+{
+	// use the timer to do schedule instrument slaughter;
+	EventQueue *pQueue = EventQueue::get_instance();
+
+	Event event;
+	while ( ( event = pQueue->pop_event() ).type != EVENT_NONE ) {
+		for (int i = 0; i < (int)m_eventListeners.size(); i++ ) {
+			EventListener *pListener = m_eventListeners[ i ];
+
+			switch ( event.type ) {
+				case EVENT_STATE:
+					pListener->stateChangedEvent( event.value );
+					break;
+
+				case EVENT_PATTERN_CHANGED:
+					pListener->patternChangedEvent();
+					break;
+
+				case EVENT_PATTERN_MODIFIED:
+					pListener->patternModifiedEvent();
+					break;
+
+				case EVENT_SELECTED_PATTERN_CHANGED:
+					pListener->selectedPatternChangedEvent();
+					break;
+
+				case EVENT_SELECTED_INSTRUMENT_CHANGED:
+					pListener->selectedInstrumentChangedEvent();
+					break;
+
+				case EVENT_MIDI_ACTIVITY:
+					pListener->midiActivityEvent();
+					break;
+
+				case EVENT_NOTEON:
+					pListener->noteOnEvent( event.value );
+					break;
+
+				case EVENT_ERROR:
+					pListener->errorEvent( event.value );
+					break;
+
+				case EVENT_XRUN:
+					pListener->XRunEvent();
+					break;
+
+				case EVENT_METRONOME:
+					pListener->metronomeEvent( event.value );
+					break;
+
+				case EVENT_RECALCULATERUBBERBAND:
+					pListener->rubberbandbpmchangeEvent();
+					break;
+
+				case EVENT_PROGRESS:
+					pListener->progressEvent( event.value );
+					break;
+
+				default:
+					ERRORLOG( QString("[onEventQueueTimer] Unhandled event: %1").arg( event.type ) );
+			}
+
+		}
+	}
+}
+
+
+void HydrogenApp::addEventListener( EventListener* pListener )
+{
+	if (pListener) {
+		m_eventListeners.push_back( pListener );
+	}
+}
+
+
+void HydrogenApp::removeEventListener( EventListener* pListener )
+{
+	for ( uint i = 0; i < m_eventListeners.size(); i++ ) {
+		if ( pListener == m_eventListeners[ i ] ) {
+			m_eventListeners.erase( m_eventListeners.begin() + i );
+		}
+	}
+}
+
Index: /branches/tabbedInterface/gui/src/PreferencesDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PreferencesDialog.cpp	(revision 1499)
+++ /branches/tabbedInterface/gui/src/PreferencesDialog.cpp	(revision 1499)
@@ -0,0 +1,656 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "Skin.h"
+#include "PreferencesDialog.h"
+#include "HydrogenApp.h"
+#include "MainForm.h"
+
+#include "qmessagebox.h"
+#include "qstylefactory.h"
+
+#include <QPixmap>
+#include <QFontDialog>
+
+#include "widgets/midiTable.h"
+
+#include <hydrogen/midiMap.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/IO/MidiInput.h>
+#include <hydrogen/LashClient.h>
+
+using namespace H2Core;
+
+PreferencesDialog::PreferencesDialog(QWidget* parent)
+ : QDialog( parent )
+ , Object( "PreferencesDialog" )
+{
+	setupUi( this );
+
+	setWindowTitle( trUtf8( "Preferences" ) );
+//	setIcon( QPixmap( Skin::getImagePath()  + "/icon16.png" ) );
+
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	Preferences *pPref = Preferences::get_instance();
+	pPref->loadPreferences( false );	// reload user's preferences
+
+	driverComboBox->clear();
+	driverComboBox->addItem( "Auto" );
+	driverComboBox->addItem( "JACK" );
+	driverComboBox->addItem( "ALSA" );
+	driverComboBox->addItem( "OSS" );
+	driverComboBox->addItem( "PortAudio" );
+#ifdef Q_OS_MACX
+	driverComboBox->addItem( "CoreAudio" );
+#endif
+
+	// Selected audio Driver
+	QString sAudioDriver = pPref->m_sAudioDriver;
+	if (sAudioDriver == "Auto") {
+		driverComboBox->setCurrentIndex(0);
+	}
+	else if (sAudioDriver == "Jack") {
+		driverComboBox->setCurrentIndex(1);
+	}
+	else if ( sAudioDriver == "Alsa" ) {
+		driverComboBox->setCurrentIndex(2);
+	}
+	else if ( sAudioDriver == "Oss" ) {
+		driverComboBox->setCurrentIndex(3);
+	}
+	else if ( sAudioDriver == "PortAudio" ) {
+		driverComboBox->setCurrentIndex(4);
+	}
+	else if ( sAudioDriver == "CoreAudio" ) {
+		driverComboBox->setCurrentIndex(5);
+	}
+	else {
+		ERRORLOG( "Unknown audio driver from preferences [" + sAudioDriver + "]" );
+	}
+
+
+	m_pMidiDriverComboBox->clear();
+	m_pMidiDriverComboBox->addItem( "ALSA" );
+	m_pMidiDriverComboBox->addItem( "PortMidi" );
+	m_pMidiDriverComboBox->addItem( "CoreMidi" );
+
+	if ( pPref->m_sMidiDriver == "ALSA" ) {
+		m_pMidiDriverComboBox->setCurrentIndex(0);
+	}
+	else if ( pPref->m_sMidiDriver == "PortMidi" ) {
+		m_pMidiDriverComboBox->setCurrentIndex(1);
+	}
+	else if ( pPref->m_sMidiDriver == "CoreMidi" ) {
+		m_pMidiDriverComboBox->setCurrentIndex(2);
+	}
+	else {
+		ERRORLOG( "Unknown midi input from preferences [" + pPref->m_sMidiDriver + "]" );
+	}
+
+	m_pIgnoreNoteOffCheckBox->setChecked( pPref->m_bMidiNoteOffIgnore );
+
+	updateDriverInfo();
+
+
+	// metronome volume
+	uint metronomeVol = (uint)( pPref->m_fMetronomeVolume * 100.0 );
+	metronomeVolumeSpinBox->setValue(metronomeVol);
+
+	// max voices
+	maxVoicesTxt->setValue( pPref->m_nMaxNotes );
+
+	// JACK
+	trackOutsCheckBox->setChecked( pPref->m_bJackTrackOuts );
+	connectDefaultsCheckBox->setChecked( pPref->m_bJackConnectDefaults );
+	trackOutputComboBox->setCurrentIndex( pPref->m_nJackTrackOutputMode );
+	//~ JACK
+
+
+	bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
+
+	switch ( pPref->m_nSampleRate ) {
+		case 44100:
+			sampleRateComboBox->setCurrentIndex( 0 );
+			break;
+		case 48000:
+			sampleRateComboBox->setCurrentIndex( 1 );
+			break;
+		case 88200:
+			sampleRateComboBox->setCurrentIndex( 2 );
+			break;
+		case 96000:
+			sampleRateComboBox->setCurrentIndex( 3 );
+			break;
+		default:
+			ERRORLOG( QString("Wrong samplerate: %1").arg( pPref->m_nSampleRate ) );
+	}
+
+
+	// Appearance tab
+	QString applicationFamily = pPref->getApplicationFontFamily();
+	int applicationPointSize = pPref->getApplicationFontPointSize();
+
+	QFont applicationFont( applicationFamily, applicationPointSize );
+	applicationFontLbl->setFont( applicationFont );
+	applicationFontLbl->setText( applicationFamily + QString("  %1").arg( applicationPointSize ) );
+
+	QString mixerFamily = pPref->getMixerFontFamily();
+	int mixerPointSize = pPref->getMixerFontPointSize();
+	QFont mixerFont( mixerFamily, mixerPointSize );
+	mixerFontLbl->setFont( mixerFont );
+	mixerFontLbl->setText( mixerFamily + QString("  %1").arg( mixerPointSize ) );
+
+
+	float falloffSpeed = pPref->getMixerFalloffSpeed();
+	if (falloffSpeed == FALLOFF_SLOW) {
+		mixerFalloffComboBox->setCurrentIndex(0);
+	}
+	else if (falloffSpeed == FALLOFF_NORMAL) {
+		mixerFalloffComboBox->setCurrentIndex(1);
+	}
+	else if (falloffSpeed == FALLOFF_FAST) {
+		mixerFalloffComboBox->setCurrentIndex(2);
+	}
+	else {
+		ERRORLOG( QString("PreferencesDialog: wrong mixerFalloff value = %1").arg(falloffSpeed) );
+	}
+
+	// Style
+	QStringList list = QStyleFactory::keys();
+	uint i = 0;
+	for ( QStringList::Iterator it = list.begin(); it != list.end(); it++) {
+		styleComboBox->addItem( *it );
+		//INFOLOG( "QT Stile: " + *it   );
+		//string sStyle = (*it).latin1();
+		QString sStyle = (*it);
+		if (sStyle == pPref->getQTStyle() ) {
+			styleComboBox->setCurrentIndex( i );
+		}
+		i++;
+	}
+
+
+	// midi tab
+	midiPortChannelComboBox->setEnabled( false );
+	midiPortComboBox->setEnabled( false );
+	// list midi output ports
+	midiPortComboBox->clear();
+	midiPortComboBox->addItem( "None" );
+	if ( Hydrogen::get_instance()->getMidiInput() ) {
+		std::vector<QString> midiOutList = Hydrogen::get_instance()->getMidiInput()->getOutputPortList();
+
+		if ( midiOutList.size() != 0 ) {
+			midiPortComboBox->setEnabled( true );
+			midiPortChannelComboBox->setEnabled( true );
+		}
+		for (uint i = 0; i < midiOutList.size(); i++) {
+			QString sPortName = midiOutList[i];
+			midiPortComboBox->addItem( sPortName );
+
+			if ( sPortName == pPref->m_sMidiPortName ) {
+				midiPortComboBox->setCurrentIndex( i + 1 );
+			}
+		}
+	}
+
+	if ( pPref->m_nMidiChannelFilter == -1 ) {
+		midiPortChannelComboBox->setCurrentIndex( 0 );
+	}
+	else {
+		midiPortChannelComboBox->setCurrentIndex( pPref->m_nMidiChannelFilter + 1 );
+	}
+	
+
+	// General tab
+	restoreLastUsedSongCheckbox->setChecked( pPref->isRestoreLastSongEnabled() );
+
+
+	//restore the right m_bsetlash value 
+	if ( pPref->m_brestartLash == true ){ 
+		if (pPref->m_bsetLash == false ){ 
+		 	pPref->m_bsetLash = true ;
+			pPref->m_brestartLash = false;
+		}
+
+	}
+	useLashCheckbox->setChecked( pPref->m_bsetLash );	
+
+	sBcountOffset->setValue( pPref->m_countOffset );
+	sBstartOffset->setValue( pPref->m_startOffset );
+
+	sBmaxBars->setValue( pPref->getMaxBars() );
+
+	QString pathtoRubberband = pPref->m_rubberBandCLIexecutable;
+
+
+	rubberbandLineEdit->setText( pathtoRubberband );
+
+	m_bNeedDriverRestart = false;
+}
+
+
+
+
+PreferencesDialog::~PreferencesDialog()
+{	
+	INFOLOG("~PREFERENCES_DIALOG");	
+}
+
+
+
+void PreferencesDialog::on_cancelBtn_clicked()
+{
+	Preferences *preferencesMng = Preferences::get_instance();
+	preferencesMng->loadPreferences( false );	// reload old user's preferences
+
+	//restore the right m_bsetlash value
+	if ( preferencesMng->m_brestartLash == true ){ 
+		if (preferencesMng->m_bsetLash == false ){
+		 	preferencesMng->m_bsetLash = true ;
+			preferencesMng->m_brestartLash = false;
+		}
+
+	}
+
+	reject();
+}
+
+
+void PreferencesDialog::on_okBtn_clicked()
+{
+	m_bNeedDriverRestart = true;
+
+	Preferences *pPref = Preferences::get_instance();
+
+	midiTable->saveMidiTable();
+
+	// Selected audio driver
+	if (driverComboBox->currentText() == "Auto" ) {
+		pPref->m_sAudioDriver = "Auto";
+	}
+	else if (driverComboBox->currentText() == "JACK" ) {
+		pPref->m_sAudioDriver = "Jack";
+	}
+	else if (driverComboBox->currentText() == "ALSA" ) {
+		pPref->m_sAudioDriver = "Alsa";
+		pPref->m_sAlsaAudioDevice = m_pAudioDeviceTxt->text();
+	}
+	else if (driverComboBox->currentText() == "OSS" ) {
+		pPref->m_sAudioDriver = "Oss";
+		pPref->m_sOSSDevice = m_pAudioDeviceTxt->text();
+	}
+	else if (driverComboBox->currentText() == "PortAudio" ) {
+		pPref->m_sAudioDriver = "PortAudio";
+	}
+	else if (driverComboBox->currentText() == "CoreAudio" ) {
+		pPref->m_sAudioDriver = "CoreAudio";
+	}
+	else {
+		ERRORLOG( "[okBtnClicked] Invalid audio driver" );
+	}
+
+	// JACK
+	pPref->m_bJackTrackOuts = trackOutsCheckBox->isChecked();
+	pPref->m_bJackConnectDefaults = connectDefaultsCheckBox->isChecked();
+
+	
+	if (trackOutputComboBox->currentText() == "Post-Fader")
+	{
+		pPref->m_nJackTrackOutputMode = Preferences::POST_FADER;
+	} else {
+		pPref->m_nJackTrackOutputMode = Preferences::PRE_FADER;
+	}
+	//~ JACK
+
+	pPref->m_nBufferSize = bufferSizeSpinBox->value();
+	if ( sampleRateComboBox->currentText() == "44100" ) {
+		pPref->m_nSampleRate = 44100;
+	}
+	else if ( sampleRateComboBox->currentText() == "48000" ) {
+		pPref->m_nSampleRate = 48000;
+	}
+	else if ( sampleRateComboBox->currentText() == "88200" ) {
+		pPref->m_nSampleRate = 88200;
+	}
+	else if ( sampleRateComboBox->currentText() == "96000" ) {
+		pPref->m_nSampleRate = 96000;
+	}
+
+
+	// metronome
+	pPref->m_fMetronomeVolume = (metronomeVolumeSpinBox->value()) / 100.0;
+
+	// maxVoices
+	pPref->m_nMaxNotes = maxVoicesTxt->value();
+
+	if ( m_pMidiDriverComboBox->currentText() == "ALSA" ) {
+		pPref->m_sMidiDriver = "ALSA";
+	}
+	else if ( m_pMidiDriverComboBox->currentText() == "PortMidi" ) {
+		pPref->m_sMidiDriver = "PortMidi";
+	}
+	else if ( m_pMidiDriverComboBox->currentText() == "CoreMidi" ) {
+		pPref->m_sMidiDriver = "CoreMidi";
+	}
+
+	pPref->m_bMidiNoteOffIgnore = m_pIgnoreNoteOffCheckBox->isChecked();
+
+	// Mixer falloff
+	QString falloffStr = mixerFalloffComboBox->currentText();
+	if ( falloffStr== trUtf8("Slow") ) {
+		pPref->setMixerFalloffSpeed(FALLOFF_SLOW);
+	}
+	else if ( falloffStr == trUtf8("Normal") ) {
+		pPref->setMixerFalloffSpeed(FALLOFF_NORMAL);
+	}
+	else if ( falloffStr == trUtf8("Fast") ) {
+		pPref->setMixerFalloffSpeed(FALLOFF_FAST);
+	}
+	else {
+		ERRORLOG( "[okBtnClicked] Unknown mixerFallOffSpeed: " + falloffStr );
+	}
+
+	QString sNewMidiPortName = midiPortComboBox->currentText();
+
+	if ( pPref->m_sMidiPortName != sNewMidiPortName ) {
+		pPref->m_sMidiPortName = sNewMidiPortName;
+		m_bNeedDriverRestart = true;
+	}
+
+	if ( pPref->m_nMidiChannelFilter != midiPortChannelComboBox->currentIndex() - 1 ) {
+		m_bNeedDriverRestart = true;
+	}
+	pPref->m_nMidiChannelFilter = midiPortChannelComboBox->currentIndex() - 1;
+
+
+	// General tab
+	pPref->setRestoreLastSongEnabled( restoreLastUsedSongCheckbox->isChecked() );
+	pPref->m_bsetLash = useLashCheckbox->isChecked(); //restore m_bsetLash after saving pref. 
+
+	//path to rubberband
+	pPref-> m_rubberBandCLIexecutable = rubberbandLineEdit->text();
+
+	//check preferences 
+	if ( pPref->m_brestartLash == true ){ 
+		pPref->m_bsetLash = true ; 
+	}
+
+	pPref->m_countOffset = sBcountOffset->value();
+	pPref->m_startOffset = sBstartOffset->value();
+
+	pPref->setMaxBars( sBmaxBars->value() );
+
+	Hydrogen::get_instance()->setBcOffsetAdjust();
+
+	pPref->savePreferences();
+
+	
+
+	if (m_bNeedDriverRestart) {
+		(Hydrogen::get_instance())->restartDrivers();
+	}
+	accept();
+}
+
+
+
+void PreferencesDialog::on_driverComboBox_activated( int index )
+{
+	UNUSED( index );
+	QString selectedDriver = driverComboBox->currentText();
+	updateDriverInfo();
+	m_bNeedDriverRestart = true;
+}
+
+
+void PreferencesDialog::updateDriverInfo()
+{
+	Preferences *pPref = Preferences::get_instance();
+	QString info;
+
+	bool bJack_support = false;
+	#ifdef JACK_SUPPORT
+	bJack_support = true;
+	#endif
+
+	bool bAlsa_support = false;
+	#ifdef ALSA_SUPPORT
+	bAlsa_support = true;
+	#endif
+
+	bool bOss_support = false;
+	#ifdef OSS_SUPPORT
+	bOss_support = true;
+	#endif
+
+	bool bPortAudio_support = false;
+	#ifdef PORTAUDIO_SUPPORT
+	bPortAudio_support = true;
+	#endif
+
+	bool bCoreAudio_support = false;
+	#ifdef COREAUDIO_SUPPORT
+	bCoreAudio_support = true;
+	#endif
+
+
+	if ( driverComboBox->currentText() == "Auto" ) {
+		info += trUtf8("<b>Automatic driver selection</b>");
+
+		m_pAudioDeviceTxt->setEnabled(false);
+		m_pAudioDeviceTxt->setText( "" );
+		bufferSizeSpinBox->setEnabled( false );
+		sampleRateComboBox->setEnabled( false );
+		trackOutputComboBox->setEnabled( false );
+		connectDefaultsCheckBox->setEnabled( false );
+	}
+	else if ( driverComboBox->currentText() == "OSS" ) {	// OSS
+		info += trUtf8("<b>Open Sound System</b><br>Simple audio driver [/dev/dsp]");
+		if ( !bOss_support ) {
+			info += trUtf8("<br><b><font color=\"red\">Not compiled</font></b>");
+		}
+		m_pAudioDeviceTxt->setEnabled(true);
+		m_pAudioDeviceTxt->setText( pPref->m_sOSSDevice );
+		bufferSizeSpinBox->setEnabled(true);
+		sampleRateComboBox->setEnabled(true);
+		trackOutputComboBox->setEnabled( false );
+		trackOutsCheckBox->setEnabled( false );
+		connectDefaultsCheckBox->setEnabled(false);
+	}
+	else if ( driverComboBox->currentText() == "JACK" ) {	// JACK
+		info += trUtf8("<b>Jack Audio Connection Kit Driver</b><br>Low latency audio driver");
+		if ( !bJack_support ) {
+			info += trUtf8("<br><b><font color=\"red\">Not compiled</font></b>");
+		}
+		m_pAudioDeviceTxt->setEnabled(false);
+		m_pAudioDeviceTxt->setText( "" );
+		bufferSizeSpinBox->setEnabled(false);
+		sampleRateComboBox->setEnabled(false);
+		trackOutputComboBox->setEnabled( true );
+		connectDefaultsCheckBox->setEnabled(true);
+		trackOutsCheckBox->setEnabled( true );
+	}
+	else if ( driverComboBox->currentText() == "ALSA" ) {	// ALSA
+		info += trUtf8("<b>ALSA Driver</b><br>");
+		if ( !bAlsa_support ) {
+			info += trUtf8("<br><b><font color=\"red\">Not compiled</font></b>");
+		}
+		m_pAudioDeviceTxt->setEnabled(true);
+		m_pAudioDeviceTxt->setText( pPref->m_sAlsaAudioDevice );
+		bufferSizeSpinBox->setEnabled(true);
+		sampleRateComboBox->setEnabled(true);
+		trackOutputComboBox->setEnabled( false );
+		trackOutsCheckBox->setEnabled( false );
+		connectDefaultsCheckBox->setEnabled(false);
+	}
+	else if ( driverComboBox->currentText() == "PortAudio" ) {
+		info += trUtf8( "<b>PortAudio Driver</b><br>" );
+		if ( !bPortAudio_support ) {
+			info += trUtf8("<br><b><font color=\"red\">Not compiled</font></b>");
+		}
+		m_pAudioDeviceTxt->setEnabled(false);
+		m_pAudioDeviceTxt->setText( "" );
+		bufferSizeSpinBox->setEnabled(true);
+		sampleRateComboBox->setEnabled(true);
+		trackOutsCheckBox->setEnabled( false );
+		connectDefaultsCheckBox->setEnabled(false);
+	}
+	else if ( driverComboBox->currentText() == "CoreAudio" ) {
+		info += trUtf8( "<b>CoreAudio Driver</b><br>" );
+		if ( !bCoreAudio_support ) {
+			info += trUtf8("<br><b><font color=\"red\">Not compiled</font></b>");
+		}
+		m_pAudioDeviceTxt->setEnabled(false);
+		m_pAudioDeviceTxt->setText( "" );
+		bufferSizeSpinBox->setEnabled(true);
+		sampleRateComboBox->setEnabled(true);
+		trackOutputComboBox->setEnabled( false );
+		trackOutsCheckBox->setEnabled( false );
+		connectDefaultsCheckBox->setEnabled(false);
+	}
+	else {
+		QString selectedDriver = driverComboBox->currentText();
+		ERRORLOG( "Unknown driver = " + selectedDriver );
+	}
+
+	metronomeVolumeSpinBox->setEnabled(true);
+	bufferSizeSpinBox->setValue( pPref->m_nBufferSize );
+
+	driverInfoLbl->setText(info);
+}
+
+
+
+void PreferencesDialog::on_selectApplicationFontBtn_clicked()
+{
+	Preferences *preferencesMng = Preferences::get_instance();
+
+	QString family = preferencesMng->getApplicationFontFamily();
+	int pointSize = preferencesMng->getApplicationFontPointSize();
+
+	bool ok;
+	QFont font = QFontDialog::getFont( &ok, QFont( family, pointSize ), this );
+	if ( ok ) {
+		// font is set to the font the user selected
+		family = font.family();
+		pointSize = font.pointSize();
+		QString familyStr = family;
+		preferencesMng->setApplicationFontFamily(familyStr);
+		preferencesMng->setApplicationFontPointSize(pointSize);
+	} else {
+		// the user cancelled the dialog; font is set to the initial
+		// value, in this case Times, 12.
+	}
+
+	QFont newFont(family, pointSize);
+	applicationFontLbl->setFont(newFont);
+	applicationFontLbl->setText(family + QString("  %1").arg(pointSize));
+}
+
+
+
+
+void PreferencesDialog::on_bufferSizeSpinBox_valueChanged( int i )
+{
+	UNUSED( i );
+	m_bNeedDriverRestart = false;
+}
+
+
+
+
+void PreferencesDialog::on_sampleRateComboBox_editTextChanged( const QString&  )
+{
+	m_bNeedDriverRestart = true;
+}
+
+
+
+void PreferencesDialog::on_restartDriverBtn_clicked()
+{
+	Hydrogen::get_instance()->restartDrivers();
+	m_bNeedDriverRestart = false;
+}
+
+
+
+void PreferencesDialog::on_selectMixerFontBtn_clicked()
+{
+	Preferences *preferencesMng = Preferences::get_instance();
+
+	QString family = preferencesMng->getMixerFontFamily();
+	int pointSize = preferencesMng->getMixerFontPointSize();
+
+	bool ok;
+	QFont font = QFontDialog::getFont( &ok, QFont( family, pointSize ), this );
+	if ( ok ) {
+		// font is set to the font the user selected
+		family = font.family();
+		pointSize = font.pointSize();
+		QString familyStr = family;
+		preferencesMng->setMixerFontFamily(familyStr);
+		preferencesMng->setMixerFontPointSize(pointSize);
+	}
+	QFont newFont(family, pointSize);
+	mixerFontLbl->setFont(newFont);
+	mixerFontLbl->setText(family + QString("  %1").arg(pointSize));
+}
+
+
+
+void PreferencesDialog::on_midiPortComboBox_activated( int index )
+{
+	UNUSED( index );
+	m_bNeedDriverRestart = true;
+}
+
+
+
+void PreferencesDialog::on_styleComboBox_activated( int index )
+{
+	UNUSED( index );
+	QApplication *pQApp = (HydrogenApp::get_instance())->getMainForm()->m_pQApp;
+	QString sStyle = styleComboBox->currentText();
+	pQApp->setStyle( sStyle );
+
+	Preferences *pPref = Preferences::get_instance();
+	pPref->setQTStyle( sStyle );
+}
+
+
+
+void PreferencesDialog::on_useLashCheckbox_clicked()
+{
+	if ( useLashCheckbox->isChecked() ){
+		Preferences::get_instance()->m_brestartLash = true;
+	}
+	else
+	{
+		 Preferences::get_instance()->m_bsetLash = false ;
+	}
+	QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Please restart hydrogen to enable/disable LASH support" ) );
+}
+
Index: /branches/tabbedInterface/gui/src/main.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/main.cpp	(revision 1504)
+++ /branches/tabbedInterface/gui/src/main.cpp	(revision 1504)
@@ -0,0 +1,427 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QtGui>
+#include <QLibraryInfo>
+#include "config.h"
+#include "version.h"
+#include <getopt.h>
+
+#include "SplashScreen.h"
+#include "HydrogenApp.h"
+#include "MainForm.h"
+
+#ifdef LASH_SUPPORT
+#include <hydrogen/LashClient.h>
+#endif
+
+#include <hydrogen/midiMap.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/SoundLibrary.h>
+#include <hydrogen/globals.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/data_path.h>
+#include <hydrogen/h2_exception.h>
+
+#include <signal.h>
+#include <iostream>
+using namespace std;
+
+void showInfo();
+void showUsage();
+
+
+#define HAS_ARG 1
+static struct option long_opts[] = {
+	{"driver", required_argument, NULL, 'd'},
+	{"song", required_argument, NULL, 's'},
+	{"version", 0, NULL, 'v'},
+	{"nosplash", 0, NULL, 'n'},
+	{"verbose", optional_argument, NULL, 'V'},
+	{"help", 0, NULL, 'h'},
+	{"install", required_argument, NULL, 'i'},
+	{0, 0, 0, 0},
+};
+
+#define NELEM(a) ( sizeof(a)/sizeof((a)[0]) )
+
+
+//
+// Set the palette used in the application
+//
+void setPalette( QApplication *pQApp )
+{
+	// create the default palette
+	QPalette defaultPalette;
+
+	// A general background color.
+	defaultPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
+
+	// A general foreground color.
+	defaultPalette.setColor( QPalette::Foreground, QColor( 255, 255, 255 ) );
+
+	// Used as the background color for text entry widgets; usually white or another light color.
+	defaultPalette.setColor( QPalette::Base, QColor( 88, 94, 112 ) );
+
+	// Used as the alternate background color in views with alternating row colors
+	defaultPalette.setColor( QPalette::AlternateBase, QColor( 138, 144, 162 ) );
+
+	// The foreground color used with Base. This is usually the same as the Foreground, in which case it must provide good contrast with Background and Base.
+	defaultPalette.setColor( QPalette::Text, QColor( 255, 255, 255 ) );
+
+	// The general button background color. This background can be different from Background as some styles require a different background color for buttons.
+	defaultPalette.setColor( QPalette::Button, QColor( 88, 94, 112 ) );
+
+	// A foreground color used with the Button color.
+	defaultPalette.setColor( QPalette::ButtonText, QColor( 255, 255, 255 ) );
+
+
+	// Lighter than Button color.
+	defaultPalette.setColor( QPalette::Light, QColor( 138, 144, 162 ) );
+
+	// Between Button and Light.
+	defaultPalette.setColor( QPalette::Midlight, QColor( 128, 134, 152 ) );
+
+	// Darker than Button.
+	defaultPalette.setColor( QPalette::Dark, QColor( 58, 62, 72 ) );
+
+	// Between Button and Dark.
+	defaultPalette.setColor( QPalette::Mid, QColor( 81, 86, 99 ) );
+
+	// A very dark color. By default, the shadow color is Qt::black.
+	defaultPalette.setColor( QPalette::Shadow, QColor( 255, 255, 255 ) );
+
+
+	// A color to indicate a selected item or the current item.
+	defaultPalette.setColor( QPalette::Highlight, QColor( 116, 124, 149 ) );
+
+	// A text color that contrasts with Highlight.
+	defaultPalette.setColor( QPalette::HighlightedText, QColor( 255, 255, 255 ) );
+
+	pQApp->setPalette( defaultPalette );
+}
+
+
+static int setup_unix_signal_handlers()
+{
+    struct sigaction usr1, term;
+
+    usr1.sa_handler = MainForm::usr1SignalHandler;
+    sigemptyset(&usr1.sa_mask);
+    usr1.sa_flags = 0;
+    usr1.sa_flags |= SA_RESTART;
+
+    if (sigaction(SIGUSR1, &usr1, 0) > 0)
+       return 1;
+
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	try {
+		// Options...
+		char *cp;
+		struct option *op;
+		char opts[NELEM(long_opts) * 3 + 1];
+
+		// Build up the short option QString
+		cp = opts;
+		for (op = long_opts; op < &long_opts[NELEM(long_opts)]; op++) {
+			*cp++ = op->val;
+			if (op->has_arg)
+				*cp++ = ':';
+			if (op->has_arg == optional_argument )
+				*cp++ = ':';  // gets another one
+		}
+
+		QApplication* pQApp = new QApplication(argc, argv);
+
+		// Deal with the options
+		QString songFilename;
+		bool bNoSplash = false;
+		QString sSelectedDriver;
+		bool showVersionOpt = false;
+		const char* logLevelOpt = "Error";
+		QString drumkitName;
+		bool showHelpOpt = false;
+
+		int c;
+		for (;;) {
+			c = getopt_long(argc, argv, opts, long_opts, NULL);
+			if (c == -1)
+				break;
+
+			switch(c) {
+				case 'd':
+					sSelectedDriver = QString::fromLocal8Bit(optarg);
+					break;
+
+				case 's':
+					songFilename = QString::fromLocal8Bit(optarg);
+					break;
+
+				case 'v':
+					showVersionOpt = true;
+					break;
+
+				case 'i':
+					//install h2drumkit
+					drumkitName = QString::fromLocal8Bit( optarg );
+					break;
+
+				case 'V':
+					if( optarg ) {
+						logLevelOpt = optarg;
+					} else {
+						logLevelOpt = "Warning";
+					}
+					break;
+				case 'n':
+					bNoSplash = true;
+					break;
+
+				case 'h':
+				case '?':
+					showHelpOpt = true;
+					break;
+			}
+		}
+
+		setup_unix_signal_handlers();
+
+		if( showVersionOpt ) {
+			std::cout << get_version() << std::endl;
+			exit(0);
+		}
+		showInfo();
+		if( showHelpOpt ) {
+			showUsage();
+			exit(0);
+		}
+
+		// Man your battle stations... this is not a drill.
+		Logger::create_instance();
+		MidiMap::create_instance();
+		H2Core::Preferences::create_instance();
+		Object::set_logging_level( logLevelOpt );
+		// See below for H2Core::Hydrogen.
+
+
+		_INFOLOG( QString("Using QT version ") + QString( qVersion() ) );
+		_INFOLOG( "Using data path: " + H2Core::DataPath::get_data_path() );
+
+		H2Core::Preferences *pPref = H2Core::Preferences::get_instance();
+
+#ifdef LASH_SUPPORT
+
+		LashClient::create_instance("hydrogen", "Hydrogen", &argc, &argv);
+		LashClient* lashClient = LashClient::get_instance();
+
+#endif
+		if( ! drumkitName.isEmpty() ){
+		    H2Core::Drumkit::install( drumkitName );
+		    exit(0);
+		}
+
+		if (sSelectedDriver == "auto") {
+			pPref->m_sAudioDriver = "Auto";
+		}
+		else if (sSelectedDriver == "jack") {
+			pPref->m_sAudioDriver = "Jack";
+		}
+		else if ( sSelectedDriver == "oss" ) {
+			pPref->m_sAudioDriver = "Oss";
+		}
+		else if ( sSelectedDriver == "alsa" ) {
+			pPref->m_sAudioDriver = "Alsa";
+		}
+
+		QString family = pPref->getApplicationFontFamily();
+		pQApp->setFont( QFont( family, pPref->getApplicationFontPointSize() ) );
+
+		QTranslator qttor( 0 );
+		QTranslator tor( 0 );
+		QString sTranslationFile = QString("hydrogen.") + QLocale::system().name();
+		QString sLocale = QLocale::system().name();
+		if ( sLocale != "C") {
+			if (qttor.load( QString( "qt_" ) + sLocale,
+				QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+				pQApp->installTranslator( &qttor );
+                        else
+				_INFOLOG( QString("Warning: No Qt translation for locale %1 found.").arg(QLocale::system().name()));
+
+
+			QString sTranslationPath = "data/i18n";
+			QString total = sTranslationPath + "/" + sTranslationFile + ".qm";
+
+			bool bTransOk = tor.load( total, "." );
+			if ( bTransOk ) {
+				_INFOLOG( QString( "Using locale: %1/%2" ).arg( sTranslationPath ).arg( sTranslationFile ) );
+			}
+			else {
+				sTranslationPath = H2Core::DataPath::get_data_path() + "/i18n";
+				total = sTranslationPath + "/" + sTranslationFile + ".qm";
+				bTransOk = tor.load( total, "." );
+				if (bTransOk) {
+					_INFOLOG( "Using locale: " + sTranslationPath + "/" + sTranslationFile );
+				}
+				else {
+					_INFOLOG( "Warning: no locale found: " + sTranslationPath + "/" + sTranslationFile );
+				}
+			}
+			if (tor.isEmpty()) {
+				_INFOLOG( "Warning: error loading locale: " +  total );
+			}
+		}
+		pQApp->installTranslator( &tor );
+
+		QString sStyle = pPref->getQTStyle();
+		if ( !sStyle.isEmpty() ) {
+			pQApp->setStyle( sStyle );
+		}
+
+		setPalette( pQApp );
+
+		SplashScreen *pSplash = new SplashScreen();
+
+		if (bNoSplash) {
+			pSplash->hide();
+		}
+		else {
+			pSplash->show();
+		}
+
+#ifdef LASH_SUPPORT
+	if ( H2Core::Preferences::get_instance()->useLash() ){	
+		if (lashClient->isConnected())
+		{
+			lash_event_t* lash_event = lashClient->getNextEvent();
+			if (lash_event && lash_event_get_type(lash_event) == LASH_Restore_File)
+			{
+				// notify client that this project was not a new one
+				lashClient->setNewProject(false);
+				
+				songFilename = "";
+				songFilename.append( QString::fromLocal8Bit(lash_event_get_string(lash_event)) );
+				songFilename.append("/hydrogen.h2song"); 
+				
+//				Logger::get_instance()->log("[LASH] Restore file: " + songFilename);
+	
+				lash_event_destroy(lash_event);
+			}
+			else if (lash_event)
+			{
+//				Logger::get_instance()->log("[LASH] ERROR: Instead of restore file got event: " + lash_event_get_type(lash_event));
+				lash_event_destroy(lash_event);
+			}
+		}
+	}	
+#endif
+
+		// Hydrogen here to honor all preferences.
+		H2Core::Hydrogen::create_instance();
+		MainForm *pMainForm = new MainForm( pQApp, songFilename );
+		pMainForm->show();
+		pSplash->finish( pMainForm );
+
+		pQApp->exec();
+
+		delete pSplash;
+		delete pMainForm;
+		delete pQApp;
+		delete pPref;
+		delete H2Core::EventQueue::get_instance();
+		delete H2Core::AudioEngine::get_instance();
+
+		delete MidiMap::get_instance();
+		delete ActionManager::get_instance();
+
+		_INFOLOG( "Quitting..." );
+		cout << "\nBye..." << endl;
+		delete Logger::get_instance();
+
+		int nObj = Object::get_objects_number();
+		if (nObj != 0) {
+			std::cerr << "\n\n\n " << nObj << " alive objects\n\n" << std::endl << std::endl;
+			Object::print_object_map();
+		}
+
+		//	pQApp->dumpObjectTree();
+
+	}
+	catch ( const H2Core::H2Exception& ex ) {
+		std::cerr << "[main] Exception: " << ex.what() << std::endl;
+	}
+	catch (...) {
+		std::cerr << "[main] Unknown exception X-(" << std::endl;
+	}
+
+	return 0;
+}
+
+
+
+/**
+ * Show some information
+ */
+void showInfo()
+{
+	cout << "\nHydrogen " + get_version() + " [" + __DATE__ + "]  [http://www.hydrogen-music.org]" << endl;
+	cout << "Copyright 2002-2008 Alessandro Cominu" << endl;
+//	_INFOLOG( "Compiled modules: " + QString(COMPILED_FEATURES) << endl;
+
+	if ( Object::is_using_verbose_log() ) {
+		cout << "\nVerbose log mode = active" << endl;
+	}
+
+	cout << "\nHydrogen comes with ABSOLUTELY NO WARRANTY" << endl;
+	cout << "This is free software, and you are welcome to redistribute it" << endl;
+	cout << "under certain conditions. See the file COPYING for details\n" << endl;
+}
+
+
+
+/**
+ * Show the correct usage
+ */
+void showUsage()
+{
+	std::cout << "Usage: hydrogen [-v] [-h] -s file" << std::endl;
+	std::cout << "   -d, --driver AUDIODRIVER - Use the selected audio driver (jack, alsa, oss)" << std::endl;
+	std::cout << "   -s, --song FILE - Load a song (*.h2song) at startup" << std::endl;
+	std::cout << "   -k, --kit drumkit_name - Load a drumkit at startup" << std::endl;
+	std::cout << "   -i, --install FILE - install a drumkit (*.h2drumkit)" << std::endl;
+#ifdef LASH_SUPPORT
+	std::cout << "   --lash-no-start-server - If LASH server not running, don't start" << endl
+		  << "                            it (LASH 0.5.3 and later)." << std::endl;
+	std::cout << "   --lash-no-autoresume - Tell LASH server not to assume I'm returning" << std::endl
+		  << "                          from a crash." << std::endl;
+#endif
+	std::cout << "   -n, --nosplash - Hide splash screen" << std::endl;
+	std::cout << "   -V[Level], --verbose[=Level] - Print a lot of debugging info" << std::endl;
+        std::cout << "                 Level, if present, may be None, Error, Warning, Info, Debug or 0xHHHH" << std::endl;
+	std::cout << "   -v, --version - Show version info" << std::endl;
+	std::cout << "   -h, --help - Show this help message" << std::endl;
+}
Index: /branches/tabbedInterface/gui/src/LadspaFXProperties.h
===================================================================
--- /branches/tabbedInterface/gui/src/LadspaFXProperties.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/LadspaFXProperties.h	(revision 377)
@@ -0,0 +1,75 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef LADSPA_FX_PROPERTIES_H
+#define LADSPA_FX_PROPERTIES_H
+
+#include <vector>
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+class Fader;
+class LCDDisplay;
+class InstrumentNameWidget;
+
+class LadspaFXProperties : public QWidget, public Object {
+	Q_OBJECT
+
+	public:
+		LadspaFXProperties(QWidget* parent, uint nLadspaFX);
+		~LadspaFXProperties();
+
+		void updateControls();
+
+		void showEvent ( QShowEvent *ev );
+		void closeEvent( QCloseEvent *ev );
+
+	public slots:
+		void faderChanged( Fader* ref );
+		void selectFXBtnClicked();
+		void activateBtnClicked();
+		void updateOutputControls();
+
+	private:
+		uint m_nLadspaFX;
+
+		QLabel *m_pNameLbl;
+
+		std::vector<Fader*> m_pInputControlFaders;
+		std::vector<InstrumentNameWidget*> m_pInputControlNames;
+		std::vector<LCDDisplay*> m_pInputControlLabel;
+
+		std::vector<Fader*> m_pOutputControlFaders;
+		std::vector<InstrumentNameWidget*> m_pOutputControlNames;
+
+		QScrollArea* m_pScrollArea;
+		QFrame* m_pFrame;
+
+		QPushButton *m_pSelectFXBtn;
+		QPushButton *m_pActivateBtn;
+
+		QTimer* m_pTimer;
+};
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/AudioFileBrowser/SampleWaveDisplay.h
===================================================================
--- /branches/tabbedInterface/gui/src/AudioFileBrowser/SampleWaveDisplay.h	(revision 570)
+++ /branches/tabbedInterface/gui/src/AudioFileBrowser/SampleWaveDisplay.h	(revision 570)
@@ -0,0 +1,51 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SAMPLE_WAVE_DISPLAY
+#define SAMPLE_WAVE_DISPLAY
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+
+
+
+class SampleWaveDisplay : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		SampleWaveDisplay(QWidget* pParent);
+		~SampleWaveDisplay();
+
+		void updateDisplay( QString filename );
+
+		void paintEvent(QPaintEvent *ev);
+
+	private:
+		QPixmap m_background;
+		QString m_sSampleName;
+		int *m_pPeakData;
+};
+
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser.cpp	(revision 1558)
+++ /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser.cpp	(revision 1558)
@@ -0,0 +1,453 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "AudioFileBrowser.h"
+#include "../HydrogenApp.h"
+#include "InstrumentEditor/InstrumentEditor.h"
+#include "SampleWaveDisplay.h"
+#include "../widgets/Button.h"
+#include "../Skin.h"
+
+#include <hydrogen/data_path.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/sample.h>
+#include <hydrogen/audio_engine.h>
+
+#include <QModelIndex>
+#include <QTreeWidget>
+#include <QMessageBox>
+
+using namespace H2Core;
+using namespace std;
+
+AudioFileBrowser::AudioFileBrowser ( QWidget* pParent )
+		: QDialog ( pParent )
+		, Object ( "AudioFileBrowser" )
+{
+	setupUi ( this );
+	INFOLOG ( "INIT" );
+	setWindowTitle ( trUtf8 ( "Audio File Browser" ) );
+	setFixedSize ( width(), height() );
+
+        model = new QDirModel();
+	model->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
+	model->setNameFilters( QStringList() << "*.wav" << "*.WAV" << "*.flac"<< "*.FLAC" << "*.aiff" << "*.AIFF"<< "*.au" << "*.AU" );
+	model->setSorting( QDir::DirsFirst |QDir::Name );
+	__index = model->index( QDir::currentPath() );
+	
+	m_pPlayBtn->setEnabled( false );
+	m_pStopBtn->setEnabled( false );
+	openBTN->setEnabled( false );
+
+        tree = new QTreeView( treeView );
+        tree->setModel( model );
+	tree->resize( 799, 310 );
+	tree->header()->resizeSection( 0, 405 );
+	tree->setAlternatingRowColors( true );
+	tree->setRootIndex( model->index( Preferences::get_instance()->__lastsampleDirectory ) );
+	
+	pathLineEdit->setText( Preferences::get_instance()->__lastsampleDirectory );
+	m_psamplefilename = "";	
+	m_pselectedFile << "false" << "false";
+
+	sEmptySampleFilename = DataPath::get_data_path() + "/emptySample.wav";
+
+	m_pPathUptoolButton->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/go-up.png"));
+	m_pPathUptoolButton->setToolTip( QString("Parent Folder"));
+	m_pPathHometoolButton->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/go-home.png"));
+	m_pPathHometoolButton->setToolTip( QString("Home"));
+
+	m_pPlayBtn->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/player_play.png"));
+	m_pPlayBtn->setToolTip( QString("Play selected"));
+	m_pStopBtn->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/player_stop.png"));
+	m_pStopBtn->setToolTip( QString("Stop"));
+
+	m_pSampleWaveDisplay = new SampleWaveDisplay( waveformview );
+	m_pSampleWaveDisplay->updateDisplay( sEmptySampleFilename );
+	m_pSampleWaveDisplay->move( 3, 3 );
+
+	playSamplescheckBox->setChecked( Preferences::get_instance()->__playsamplesonclicking );
+	//get the kde or gnome environment variable for mouse double or single clicking
+	singleClick = false;
+	getEnvironment();
+
+	connect( tree, SIGNAL( clicked( const QModelIndex&) ), SLOT( clicked( const QModelIndex& ) ) );
+	connect( tree, SIGNAL( doubleClicked( const QModelIndex&) ), SLOT( doubleClicked( const QModelIndex& ) ) );
+	connect( pathLineEdit, SIGNAL( returnPressed() ), SLOT( updateModelIndex() ) );	
+}
+
+
+
+AudioFileBrowser::~AudioFileBrowser()
+{
+	Sample *pNewSample = Sample::load( sEmptySampleFilename );
+	AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, 100 );
+	INFOLOG ( "DESTROY" );
+}
+
+
+void AudioFileBrowser::getEnvironment()
+{
+	QString desktopSession  = getenv("DESKTOP_SESSION");
+//kde
+	if(desktopSession == "kde"){
+		QFile envfile( QDir::homePath() + "/.kde/share/config/kdeglobals");
+	
+		if (!envfile.open(QIODevice::ReadOnly | QIODevice::Text))
+			return;
+		
+		QTextStream envin( &envfile );
+		while ( !envin.atEnd() ) {
+			QString envline = envin.readLine();
+			if(envline == QString("SingleClick=true") ){
+				singleClick = true;
+				break;
+			}		
+		}
+	}
+
+//for gnome, xfce and all others we use double click as default
+
+	
+	
+}
+
+
+
+void AudioFileBrowser::keyPressEvent (QKeyEvent *ev)
+{
+	if( ev->modifiers()==Qt::ControlModifier ){
+		tree->setSelectionMode( QAbstractItemView::MultiSelection );
+		openBTN->setEnabled( true );
+	}	
+}
+
+
+
+void AudioFileBrowser::keyReleaseEvent (QKeyEvent *ev)
+{
+	tree->setSelectionMode( QAbstractItemView::SingleSelection );
+}
+
+
+
+void AudioFileBrowser::updateModelIndex()
+{
+	QString toremove;
+	QString newpath = pathLineEdit->text();
+
+	if( QDir( newpath ).exists() ){
+		tree->setRootIndex( model->index( newpath ) );
+	}else
+	{
+		toremove = newpath.section( '/', -1 );
+//		QMessageBox::information ( this, "Hydrogen", newpath + toremove);
+		newpath.replace( toremove, "" );
+		tree->setRootIndex( model->index( newpath ) );
+	}
+
+}
+
+
+
+void AudioFileBrowser::clicked( const QModelIndex& index )
+{
+	QString path = model->filePath( index );
+
+	if( singleClick )
+		browseTree( index );
+
+	if 	(
+		( path.endsWith( ".wav" ) ) ||
+		( path.endsWith( ".WAV" ) ) ||
+		( path.endsWith( ".au" ) ) ||
+		( path.endsWith( ".AU" ) ) ||
+		( path.endsWith( ".aiff" ) ) ||
+		( path.endsWith( ".AIFF" ) ) ||
+		( path.endsWith( ".flac" ) ) ||
+		( path.endsWith( ".FLAC" ) )
+		) {
+		browseTree( index );
+	}
+
+}
+
+
+
+void AudioFileBrowser::doubleClicked( const QModelIndex& index )
+{
+	if(!singleClick)
+		browseTree( index );
+}
+
+
+
+void AudioFileBrowser::browseTree( const QModelIndex& index )
+{
+
+	QString path = model->filePath( index );
+	pathLineEdit->setText( path );
+	m_pSampleWaveDisplay->updateDisplay( sEmptySampleFilename );
+
+	updateModelIndex(); //with this you have a navigation like konqueror 
+
+	if ( model->isDir( index ) ){
+		m_pPlayBtn->setEnabled( false );
+		openBTN->setEnabled( false );
+		return;
+	}
+
+	QString name = path.section( '/', -1 ); 
+	
+	QString path2 = path;
+	QString onlypath = path;
+	if ( name != "" ){
+		onlypath = path.replace( name, "" );
+	}
+		
+	name = name.left( '.' );
+
+	QString message = "Name: " + name;
+	pathLineEdit->setText( onlypath );
+
+	QStringList path2List = path2.split("/");
+	QString fleTxt = path2List.last();
+
+	QApplication::setOverrideCursor(Qt::WaitCursor);
+
+	if 	(
+		( path2.endsWith( ".wav" ) ) ||
+		( path2.endsWith( ".WAV" ) ) ||
+		( path2.endsWith( ".au" ) ) ||
+		( path2.endsWith( ".AU" ) ) ||
+		( path2.endsWith( ".aiff" ) ) ||
+		( path2.endsWith( ".AIFF" ) ) ||
+		( path2.endsWith( ".flac" ) ) ||
+		( path2.endsWith( ".FLAC" ) )
+		) {
+	
+			filelineedit->setText( fleTxt );
+			Sample *pNewSample = Sample::load( path2 );
+
+			if ( pNewSample ) {
+				m_pNBytesLable->setText( trUtf8( "Size: %1 bytes" ).arg( pNewSample->get_size() / 2 ) );
+				m_pSamplerateLable->setText( trUtf8( "Samplerate: %1" ).arg( pNewSample->get_sample_rate() ) );
+				float sec = ( float )( pNewSample->get_n_frames() / (float)pNewSample->get_sample_rate() );
+				QString qsec;
+				qsec.sprintf( "%2.2f", sec );
+				m_pLengthLable->setText( trUtf8( "Sample length: " ) + qsec + trUtf8( " s" ) );
+				
+				delete pNewSample;
+				m_psamplefilename = path2;
+
+				m_pSampleWaveDisplay->updateDisplay( path2 );
+				m_pPlayBtn->setEnabled( true );
+				openBTN->setEnabled( true );
+
+				//important this will only working correct if m_pSampleWaveDisplay->updateDisplay( file )
+				//is ready with painting the wav file. else the playing sample get crackled sound!!
+				if (playSamplescheckBox->isChecked()){
+					if ( sec <= 600.00){
+						on_m_pPlayBtn_clicked();
+					}else
+					{
+						QMessageBox::information ( this, "Hydrogen", trUtf8( "Please do not preview samples which are longer than 10 minutes!" )  );
+					}
+				}
+			}
+		
+			m_pNameLabel->setText( message );
+		}else{
+			m_pNameLabel->setText( trUtf8( "Name:"));
+			m_pNBytesLable->setText( trUtf8( "Size:" ) );
+			m_pSamplerateLable->setText( trUtf8( "Samplerate:" ) );
+			m_pLengthLable->setText( trUtf8( "Sample length:" ) );
+			m_pSampleWaveDisplay->updateDisplay( sEmptySampleFilename );
+			m_pPlayBtn->setEnabled( false );
+			m_pStopBtn->setEnabled( false );
+			openBTN->setEnabled( false );
+			m_psamplefilename = "";
+		}
+	QApplication::restoreOverrideCursor();
+}
+
+
+
+void AudioFileBrowser::on_m_pPlayBtn_clicked()
+{
+
+	if( QFile( m_psamplefilename ).exists() == false )
+		return;
+	m_pStopBtn->setEnabled( true );
+	Sample *pNewSample = Sample::load( m_psamplefilename );
+	if ( pNewSample ){
+		int length = ( ( pNewSample->get_n_frames() / pNewSample->get_sample_rate() + 1) * 100 );
+		AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, length );
+	}
+}
+
+
+
+void AudioFileBrowser::on_m_pStopBtn_clicked()
+{
+	Sample *pNewSample = Sample::load( sEmptySampleFilename );
+	AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, 100 );
+	m_pStopBtn->setEnabled( false );
+}
+
+
+
+void AudioFileBrowser::on_cancelBTN_clicked()
+{
+	Preferences::get_instance()->__lastsampleDirectory = pathLineEdit->text();
+	m_pselectedFile << "false" << "false" << "";
+	reject();
+}
+
+
+
+void AudioFileBrowser::on_openBTN_clicked()
+{
+
+	if( tree->selectionModel()->selectedIndexes().size() / 4 > 0){
+
+		QList<QModelIndex>::iterator i;
+		QList<QModelIndex> list = tree->selectionModel()->selectedIndexes();	
+
+    		for (i = list.begin(); i != list.end(); ++i){
+			QString path2 = (*i).data().toString();
+			if 	(
+			( path2.endsWith( ".wav" ) ) ||
+			( path2.endsWith( ".WAV" ) ) ||
+			( path2.endsWith( ".au" ) ) ||
+			( path2.endsWith( ".AU" ) ) ||
+			( path2.endsWith( ".aiff" ) ) ||
+			( path2.endsWith( ".AIFF" ) ) ||
+			( path2.endsWith( ".flac" ) ) ||
+			( path2.endsWith( ".FLAC" ) )
+			) {
+				QString path = pathLineEdit->text();
+				QString act_filename = path + path2;
+				m_pselectedFile << act_filename ;
+		
+			}
+			++i;++i;++i;
+		}
+	}
+	Preferences::get_instance()->__lastsampleDirectory = pathLineEdit->text();
+	accept();
+}
+
+
+
+void AudioFileBrowser::on_playSamplescheckBox_clicked()
+{
+	Preferences::get_instance()->__playsamplesonclicking = playSamplescheckBox->isChecked();
+}
+
+
+
+QStringList AudioFileBrowser::selectedFile()
+{
+	if ( useNameCheckBox->isChecked() ){
+		 m_pselectedFile[0] = "true";
+	}
+	if ( autoVelCheckBox->isChecked() ){
+		 m_pselectedFile[1] = "true";
+	}
+	return m_pselectedFile;
+}
+
+
+
+void AudioFileBrowser::on_m_pPathHometoolButton_clicked()
+{
+
+	QString path = pathLineEdit->text();
+	QStringList pathlist = path.split("/");
+
+	while( path != QDir::rootPath() ){
+
+		if( pathlist.isEmpty () )
+			break;
+		pathlist.removeLast();
+		QString updir = pathlist.join("/");
+
+		pathLineEdit->setText( updir );
+		tree->setRootIndex( model->index( updir ) );
+		tree->collapse( model->index( updir  ) );
+		tree->setExpanded( model->index(updir), false  );
+		path = pathLineEdit->text();
+	}
+
+	pathLineEdit->setText( QDir::homePath() );
+	tree->setRootIndex( model->index( QDir::homePath() ) );
+
+	tree->collapse( model->index( QDir::homePath())  );
+}
+
+
+
+void AudioFileBrowser::on_m_pPathUptoolButton_clicked()
+{
+	QString path = pathLineEdit->text();
+	QStringList pathlist = path.split("/");
+
+	if( pathlist.isEmpty () ){
+		return;
+	}
+
+	if( path.endsWith( "/" ) ){
+		pathlist.removeLast();
+		QString tmpupdir = pathlist.join("/");
+		tree->setRootIndex( model->index( tmpupdir ) );
+		tree->collapse( model->index( tmpupdir  ) );
+		tree->setExpanded( model->index( tmpupdir ), false  );
+	}
+
+	pathlist.removeLast();
+
+	QString updir = pathlist.join("/");
+	if ( updir == "" ){
+		pathLineEdit->setText( QString("/") );	
+	}else
+	{
+		pathLineEdit->setText( updir );
+	}
+
+	tree->setRootIndex( model->index( updir ) );
+	tree->collapse( model->index( updir  ) );
+	tree->setExpanded( model->index(updir), false  );
+}
+
+
+
+void AudioFileBrowser::on_hiddenCB_clicked()
+{
+	if ( hiddenCB->isChecked() ){
+	 	model->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden );
+	}else
+	{
+	 	model->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
+		tree->setRootIndex( model->index( pathLineEdit->text() ) );
+	}
+}
Index: /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser.h
===================================================================
--- /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser.h	(revision 1335)
+++ /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser.h	(revision 1335)
@@ -0,0 +1,94 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef AUDIOFILEBROWSER_H
+#define AUDIOFILEBROWSER_H
+
+#include "config.h"
+#include "ui_AudioFileBrowser_UI.h"
+#include "InstrumentEditor/InstrumentEditor.h"
+
+#include <QDialog>
+#include <hydrogen/Object.h>
+#include <hydrogen/Preferences.h>
+
+
+class Button;
+class SampleWaveDisplay;
+
+///
+/// This dialog is used to preview audiofiles
+///
+class AudioFileBrowser : public QDialog, public Ui_AudioFileBrowser_UI, public Object
+
+{
+	Q_OBJECT
+	public:
+		
+		AudioFileBrowser( QWidget* pParent );
+		~AudioFileBrowser();
+		QStringList selectedFile();
+		QString setDir( QString dir );
+
+
+
+	private slots:
+		void on_cancelBTN_clicked();
+		void on_openBTN_clicked();
+		void clicked( const QModelIndex& index );
+		void doubleClicked( const QModelIndex& index );
+		void on_m_pPlayBtn_clicked();
+		void on_m_pStopBtn_clicked();
+		void updateModelIndex();
+		void on_m_pPathHometoolButton_clicked();
+		void on_m_pPathUptoolButton_clicked();
+		void on_playSamplescheckBox_clicked();
+		void on_hiddenCB_clicked();
+		
+		virtual void keyPressEvent (QKeyEvent *ev);
+		virtual void keyReleaseEvent (QKeyEvent *ev);
+
+
+	private:
+		InstrumentEditor* m_pInstrumentEditor;
+		QString m_psamplefilename;
+		QStringList m_pselectedFile;
+
+		void browseTree( const QModelIndex& index );
+		
+		void getEnvironment();
+		bool singleClick;
+		QDirModel *model;
+		QTreeView *tree;
+		QModelIndex __index;
+
+
+		SampleWaveDisplay *m_pSampleWaveDisplay;
+		QString sEmptySampleFilename;
+		QStringList filters;
+		
+
+
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/AudioFileBrowser/SampleWaveDisplay.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/AudioFileBrowser/SampleWaveDisplay.cpp	(revision 1060)
+++ /branches/tabbedInterface/gui/src/AudioFileBrowser/SampleWaveDisplay.cpp	(revision 1060)
@@ -0,0 +1,135 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "config.h"
+
+#include <hydrogen/sample.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/instrument.h>
+using namespace H2Core;
+
+#include "SampleWaveDisplay.h"
+#include "../Skin.h"
+
+
+SampleWaveDisplay::SampleWaveDisplay(QWidget* pParent)
+ : QWidget( pParent )
+ , Object( "SampleWaveDisplay" )
+ , m_sSampleName( "" )
+{
+//	setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG( "INIT" );
+	int w = 445;
+	int h = 85;
+	resize( w, h );
+
+	bool ok = m_background.load( Skin::getImagePath() + "/waveDisplay/bgsamplewavedisplay.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	m_pPeakData = new int[ w ];
+
+}
+
+
+
+
+SampleWaveDisplay::~SampleWaveDisplay()
+{
+	//INFOLOG( "DESTROY" );
+
+	delete[] m_pPeakData;
+}
+
+
+
+void SampleWaveDisplay::paintEvent(QPaintEvent *ev)
+{
+	QPainter painter( this );
+	painter.setRenderHint( QPainter::Antialiasing );
+	painter.drawPixmap( ev->rect(), m_background, ev->rect() );
+
+	painter.setPen( QColor( 102, 150, 205 ) );
+	int VCenter = height() / 2;
+	for ( int x = 0; x < width(); x++ ) {
+		painter.drawLine( x, VCenter, x, m_pPeakData[x] + VCenter );
+		painter.drawLine( x, VCenter, x, -m_pPeakData[x] + VCenter );
+	}
+
+	QFont font;
+	font.setWeight( 63 );
+	painter.setFont( font );
+	painter.setPen( QColor( 255 , 255, 255, 200 ) );
+	painter.drawText( 0, 0, width(), 20, Qt::AlignCenter, m_sSampleName );
+}
+
+
+
+void SampleWaveDisplay::updateDisplay( QString filename )
+{
+
+	Sample *pNewSample = Sample::load( filename );
+
+	if ( pNewSample ) {
+		// Extract the filename from the complete path
+		QString sName = filename;
+		int nPos = sName.lastIndexOf( "/" );
+
+		if ( sName.endsWith("emptySample.wav")){
+			m_sSampleName = "";
+		}else
+		{
+			m_sSampleName = sName.mid( nPos + 1, sName.length() );
+		}
+
+//		INFOLOG( "[updateDisplay] sample: " + m_sSampleName  );
+
+		int nSampleLength = pNewSample->get_n_frames();
+		float nScaleFactor = nSampleLength / width();
+
+		float fGain = height() / 2.0 * 1.0;
+
+		float *pSampleData = pNewSample->get_data_l();
+
+		int nSamplePos =0;
+		int nVal;
+		for ( int i = 0; i < width(); ++i ){
+			nVal = 0;
+			for ( int j = 0; j < nScaleFactor; ++j ) {
+				if ( j < nSampleLength ) {
+					int newVal = static_cast<int>( pSampleData[ nSamplePos ] * fGain );
+					if ( newVal > nVal ) {
+						nVal = newVal;
+					}
+				}
+				++nSamplePos;
+			}
+			m_pPeakData[ i ] = nVal;
+		}
+	}
+
+	delete pNewSample;
+	update();
+
+}
+
Index: /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser_UI.ui
===================================================================
--- /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser_UI.ui	(revision 1354)
+++ /branches/tabbedInterface/gui/src/AudioFileBrowser/AudioFileBrowser_UI.ui	(revision 1354)
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AudioFileBrowser_UI</class>
+ <widget class="QDialog" name="AudioFileBrowser_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>821</width>
+    <height>564</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <widget class="QFrame" name="waveformview">
+   <property name="geometry">
+    <rect>
+     <x>360</x>
+     <y>390</y>
+     <width>451</width>
+     <height>91</height>
+    </rect>
+   </property>
+   <property name="frameShape">
+    <enum>QFrame::StyledPanel</enum>
+   </property>
+   <property name="frameShadow">
+    <enum>QFrame::Raised</enum>
+   </property>
+  </widget>
+  <widget class="QFrame" name="infoframe">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>390</y>
+     <width>341</width>
+     <height>131</height>
+    </rect>
+   </property>
+   <property name="frameShape">
+    <enum>QFrame::StyledPanel</enum>
+   </property>
+   <property name="frameShadow">
+    <enum>QFrame::Raised</enum>
+   </property>
+   <widget class="QWidget" name="layoutWidget">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>10</y>
+      <width>321</width>
+      <height>111</height>
+     </rect>
+    </property>
+    <layout class="QVBoxLayout" name="verticalLayout_3">
+     <item>
+      <widget class="QLabel" name="m_pNameLabel">
+       <property name="text">
+        <string>Name:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="m_pSamplerateLable">
+       <property name="text">
+        <string>Samplerate:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="m_pNBytesLable">
+       <property name="text">
+        <string>Size:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="m_pLengthLable">
+       <property name="text">
+        <string>Length:</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </widget>
+  </widget>
+  <widget class="QCheckBox" name="playSamplescheckBox">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>530</y>
+     <width>216</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Pla&amp;y samples by clicking</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="layoutWidget2">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>801</width>
+     <height>28</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="horizontalLayout">
+    <item>
+     <widget class="QLineEdit" name="pathLineEdit"/>
+    </item>
+    <item>
+     <widget class="QRadioButton" name="hiddenCB">
+      <property name="toolTip">
+       <string>View hidden folders</string>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QToolButton" name="m_pPathUptoolButton">
+      <property name="toolTip">
+       <string/>
+      </property>
+      <property name="text">
+       <string>&amp;Up</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QToolButton" name="m_pPathHometoolButton">
+      <property name="toolTip">
+       <string/>
+      </property>
+      <property name="text">
+       <string>&amp;Home</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QToolButton" name="m_pPlayBtn">
+   <property name="geometry">
+    <rect>
+     <x>360</x>
+     <y>490</y>
+     <width>71</width>
+     <height>26</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&amp;Play Sample</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="layoutWidget3">
+   <property name="geometry">
+    <rect>
+     <x>11</x>
+     <y>41</y>
+     <width>801</width>
+     <height>341</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QTreeView" name="treeView"/>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLineEdit" name="filelineedit"/>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="layoutWidget4">
+   <property name="geometry">
+    <rect>
+     <x>550</x>
+     <y>490</y>
+     <width>261</width>
+     <height>56</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout_2">
+    <item>
+     <widget class="QCheckBox" name="useNameCheckBox">
+      <property name="text">
+       <string>&amp;Filename to instrument name</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_3">
+      <item>
+       <widget class="QPushButton" name="openBTN">
+        <property name="text">
+         <string>Open</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="cancelBTN">
+        <property name="text">
+         <string>Cancel</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QToolButton" name="m_pStopBtn">
+   <property name="geometry">
+    <rect>
+     <x>440</x>
+     <y>490</y>
+     <width>51</width>
+     <height>26</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&amp;Stop</string>
+   </property>
+  </widget>
+  <widget class="QCheckBox" name="autoVelCheckBox">
+   <property name="geometry">
+    <rect>
+     <x>360</x>
+     <y>530</y>
+     <width>171</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="toolTip">
+    <string>Be careful, this change all Layer velocity settings </string>
+   </property>
+   <property name="text">
+    <string>Set automatic velocity</string>
+   </property>
+  </widget>
+ </widget>
+ <tabstops>
+  <tabstop>pathLineEdit</tabstop>
+  <tabstop>hiddenCB</tabstop>
+  <tabstop>m_pPathUptoolButton</tabstop>
+  <tabstop>m_pPathHometoolButton</tabstop>
+  <tabstop>treeView</tabstop>
+  <tabstop>filelineedit</tabstop>
+  <tabstop>m_pPlayBtn</tabstop>
+  <tabstop>m_pStopBtn</tabstop>
+  <tabstop>useNameCheckBox</tabstop>
+  <tabstop>playSamplescheckBox</tabstop>
+  <tabstop>autoVelCheckBox</tabstop>
+  <tabstop>openBTN</tabstop>
+  <tabstop>cancelBTN</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: /branches/tabbedInterface/gui/src/MetroBlinker_UI.ui
===================================================================
--- /branches/tabbedInterface/gui/src/MetroBlinker_UI.ui	(revision 1378)
+++ /branches/tabbedInterface/gui/src/MetroBlinker_UI.ui	(revision 1378)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MetroBlinker_UI</class>
+ <widget class="QDialog" name="MetroBlinker_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>423</width>
+    <height>377</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog.cpp	(revision 1496)
+++ /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog.cpp	(revision 1496)
@@ -0,0 +1,989 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "PlaylistDialog.h"
+#include "../HydrogenApp.h"
+#include "../InstrumentRack.h"
+#include "SoundLibrary/SoundLibraryPanel.h"
+#include "widgets/PixmapWidget.h"
+
+#include <hydrogen/LocalFileMng.h>
+#include <hydrogen/h2_exception.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/playlist.h>
+
+#include "../widgets/Button.h"
+
+#include <QTreeWidget>
+#include <QDomDocument>
+#include <QMessageBox>
+#include <QHeaderView>
+#include <QFileDialog>
+#include <vector>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+using namespace H2Core;
+using namespace std;
+
+PlaylistDialog::PlaylistDialog ( QWidget* pParent )
+		: QDialog ( pParent )
+		, Object ( "PlayListDialog" )
+{
+
+	setupUi ( this );
+	INFOLOG ( "INIT" );
+	setWindowTitle ( trUtf8 ( "Play List Browser" ) + QString(" - ") + QString( Playlist::get_instance()->__playlistName  ) );
+	setFixedSize ( width(), height() );
+
+	installEventFilter( this );
+
+	// menubar
+	QMenuBar *m_pMenubar = new QMenuBar( this );
+//	setMenuBar( m_pMenubar );
+
+	// Playlist menu
+	QMenu *m_pPlaylistMenu = m_pMenubar->addMenu( trUtf8( "&Playlist" ) );
+
+	m_pPlaylistMenu->addAction( trUtf8( "Add song to Play&list" ), this, SLOT( addSong() ), QKeySequence( "" ) );
+	m_pPlaylistMenu->addAction( trUtf8( "Add &current song to Playlist" ), this, SLOT( addCurrentSong() ), QKeySequence( "" ) );
+	m_pPlaylistMenu->addSeparator();				// -----
+	m_pPlaylistMenu->addAction( trUtf8( "&Remove selected song from Playlist" ), this, SLOT( removeFromList() ), QKeySequence( "" ) );
+	m_pPlaylistMenu->addAction( trUtf8( "Remove all songs from &Playlist" ), this, SLOT( clearPlaylist() ), QKeySequence( "" ) );
+	m_pPlaylistMenu->addSeparator();
+	m_pPlaylistMenu->addAction( trUtf8( "&Open Playlist" ), this, SLOT( loadList() ), QKeySequence( "" ) );
+	m_pPlaylistMenu->addSeparator();
+	m_pPlaylistMenu->addAction( trUtf8( "&Save Playlist" ), this, SLOT( saveList() ), QKeySequence( "" ) );
+	m_pPlaylistMenu->addAction( trUtf8( "Save Playlist &as" ), this, SLOT( saveListAs() ), QKeySequence( "" ) );
+
+#ifdef WIN32
+	//no scripts under windows
+#else
+	// Script menu
+	QMenu *m_pScriptMenu = m_pMenubar->addMenu( trUtf8( "&Scripts" ) );
+
+	m_pScriptMenu->addAction( trUtf8( "&Add Script to selected song" ), this, SLOT( loadScript() ), QKeySequence( "" ) );
+	m_pScriptMenu->addAction( trUtf8( "&Edit selected Script" ), this, SLOT( editScript() ), QKeySequence( "" ) );
+	m_pScriptMenu->addSeparator();
+	m_pScriptMenu->addAction( trUtf8( "&Remove selected Script" ), this, SLOT( removeScript() ), QKeySequence( "" ) );
+	m_pScriptMenu->addSeparator();
+	m_pScriptMenu->addAction( trUtf8( "&Create a new Script" ), this, SLOT( newScript() ), QKeySequence( "" ) );
+#endif
+
+
+// CONTROLS
+	PixmapWidget *pControlsPanel = new PixmapWidget( NULL );
+	pControlsPanel->setFixedSize( 119, 32 );
+	pControlsPanel->setPixmap( "/playerControlPanel/playlist_background_Control.png" );
+	vboxLayout->addWidget( pControlsPanel );
+	
+
+
+	// Rewind button
+	m_pRwdBtn = new Button(
+			pControlsPanel,
+			"/playerControlPanel/btn_rwd_on.png",
+			"/playerControlPanel/btn_rwd_off.png",
+			"/playerControlPanel/btn_rwd_over.png",
+			QSize(21, 15)
+	);
+	m_pRwdBtn->move(6, 6);
+	m_pRwdBtn->setToolTip( trUtf8("Rewind") );
+	connect(m_pRwdBtn, SIGNAL(clicked(Button*)), this, SLOT(rewindBtnClicked(Button*)));
+
+
+	// Play button
+	m_pPlayBtn = new ToggleButton(
+			pControlsPanel,
+			"/playerControlPanel/btn_play_on.png",
+			"/playerControlPanel/btn_play_off.png",
+			"/playerControlPanel/btn_play_over.png",
+			QSize(33, 17)
+	);
+	m_pPlayBtn->move(33, 6);
+	m_pPlayBtn->setPressed(false);
+	m_pPlayBtn->setToolTip( trUtf8("Play/ Pause/ Load selected song") );
+	connect(m_pPlayBtn, SIGNAL(clicked(Button*)), this, SLOT(nodePlayBTN(Button*)));
+
+	// Stop button
+	m_pStopBtn = new Button(
+			pControlsPanel,
+			"/playerControlPanel/btn_stop_on.png",
+			"/playerControlPanel/btn_stop_off.png",
+			"/playerControlPanel/btn_stop_over.png",
+			QSize(21, 15)
+	);
+	m_pStopBtn->move(65, 6);
+	m_pStopBtn->setToolTip( trUtf8("Stop") );
+	connect(m_pStopBtn, SIGNAL(clicked(Button*)), this, SLOT(nodeStopBTN(Button*)));
+
+	// Fast forward button
+	m_pFfwdBtn = new Button(
+			pControlsPanel,
+			"/playerControlPanel/btn_ffwd_on.png",
+			"/playerControlPanel/btn_ffwd_off.png",
+			"/playerControlPanel/btn_ffwd_over.png",
+			QSize(21, 15)
+	);
+	m_pFfwdBtn->move(92, 6);
+	m_pFfwdBtn->setToolTip( trUtf8("Fast Forward") );
+	connect(m_pFfwdBtn, SIGNAL(clicked(Button*)), this, SLOT(ffWDBtnClicked(Button*)));
+
+
+#ifdef WIN32
+	QStringList headers;
+	headers << trUtf8 ( "Song list" );
+	QTreeWidgetItem* header = new QTreeWidgetItem ( headers );
+	m_pPlaylistTree->setHeaderItem ( header );
+	m_pPlaylistTree->setAlternatingRowColors( true );
+
+	addSongBTN->setEnabled ( true );
+	loadListBTN->setEnabled ( true );
+	removeFromListBTN->setEnabled ( false );
+	removeFromListBTN->setEnabled ( false );
+	saveListBTN->setEnabled ( false );
+	saveListAsBTN->setEnabled ( false );
+	loadScriptBTN->hide();
+	removeScriptBTN->hide();
+	editScriptBTN->hide();
+	newScriptBTN->hide();
+	clearPlBTN->setEnabled ( false );
+
+	QVBoxLayout *sideBarLayout = new QVBoxLayout(sideBarWidget);
+	sideBarLayout->setSpacing(0);
+	sideBarLayout->setMargin(0);
+
+#else	
+	QStringList headers;
+	headers << trUtf8 ( "Song list" ) << trUtf8 ( "Script" ) << trUtf8 ( "exec Script" );
+	QTreeWidgetItem* header = new QTreeWidgetItem ( headers );
+	m_pPlaylistTree->setHeaderItem ( header );
+	m_pPlaylistTree->header()->resizeSection ( 0, 405 );
+	m_pPlaylistTree->header()->resizeSection ( 1, 405 );
+	m_pPlaylistTree->header()->resizeSection ( 2, 15 );
+	m_pPlaylistTree->setAlternatingRowColors( true );
+
+
+	QVBoxLayout *sideBarLayout = new QVBoxLayout(sideBarWidget);
+	sideBarLayout->setSpacing(0);
+	sideBarLayout->setMargin(0);
+#endif
+
+	// zoom-in btn
+	Button *up_btn = new Button(
+			NULL,
+			"/songEditor/btn_up_on.png",
+			"/songEditor/btn_up_off.png",
+			"/songEditor/btn_up_over.png",
+			QSize(18, 13)
+	);
+
+	up_btn->setFontSize(7);
+	up_btn->setToolTip( trUtf8( "sort" ) );
+	connect(up_btn, SIGNAL(clicked(Button*)), this, SLOT(o_upBClicked()) );
+	sideBarLayout->addWidget(up_btn);
+
+	// zoom-in btn
+	Button *down_btn = new Button(
+			NULL,
+			"/songEditor/btn_down_on.png",
+			"/songEditor/btn_down_off.png",
+			"/songEditor/btn_down_over.png",
+			QSize(18, 13)
+	);
+
+	down_btn->setFontSize(7);
+	down_btn->setToolTip( trUtf8( "sort" ) );
+	connect(down_btn, SIGNAL(clicked(Button*)), this, SLOT(o_downBClicked()));
+	sideBarLayout->addWidget(down_btn);
+	
+
+//restore the playlist
+	if( Hydrogen::get_instance()->m_PlayList.size() > 0 ){
+		for ( uint i = 0; i < Hydrogen::get_instance()->m_PlayList.size(); ++i ){
+			QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
+			m_pPlaylistItem->setText ( 0, Hydrogen::get_instance()->m_PlayList[i].m_hFile );
+			m_pPlaylistItem->setText ( 1, Hydrogen::get_instance()->m_PlayList[i].m_hScript );
+			if ( Hydrogen::get_instance()->m_PlayList[i].m_hScriptEnabled == "Use Script" ) {
+				m_pPlaylistItem->setCheckState( 2, Qt::Checked );
+			}else{
+				m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
+			}
+		}
+
+
+		//restore the selected item		
+		int selected = Playlist::get_instance()->getActiveSongNumber();
+		int Selected = Playlist::get_instance()->getSelectedSongNr();
+		if( selected == -1 && Selected == -1 ) return;
+		
+		int aselected = 0;
+		if( selected == -1 ){
+			aselected = Selected;
+		}else
+		{
+			aselected = selected ;
+		}
+		QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+		QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( aselected );
+		m_pPlaylistItem->setBackgroundColor ( 0, QColor( 50, 50, 50) );
+		m_pPlaylistItem->setBackgroundColor ( 1, QColor( 50, 50, 50) );
+		m_pPlaylistItem->setBackgroundColor ( 2, QColor( 50, 50, 50) );
+		}
+
+	timer = new QTimer( this );
+	connect(timer, SIGNAL(timeout() ), this, SLOT( updateActiveSongNumber() ) );
+	timer->start( 1000 );	// update player control at 1 fps
+
+}
+
+
+PlaylistDialog::~PlaylistDialog()
+{
+	INFOLOG ( "DESTROY" );
+}
+
+
+void PlaylistDialog::addSong()
+{
+	static QString songDir = Preferences::get_instance()->getDataDirectory()  + "/songs";;
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::ExistingFile );
+	fd->setFilter ( "Hydrogen song (*.h2song)" );
+	fd->setDirectory ( songDir );
+
+	fd->setWindowTitle ( trUtf8 ( "Add Song to PlayList" ) );
+
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted ){
+		filename = fd->selectedFiles().first();
+		updatePlayListNode ( filename );
+	}
+
+
+}
+
+
+void PlaylistDialog::addCurrentSong()
+{
+	Song *song = Hydrogen::get_instance()->getSong();
+	QString filename = song->get_filename();
+	
+
+	if (filename == "") {
+		// just in case!
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Please save your song first" ));
+		return;
+	}
+//	filename += ".h2song";
+	updatePlayListNode ( filename );
+}
+
+
+void PlaylistDialog::removeFromList()
+{
+
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+	int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
+	QTreeWidgetItem * m_pItem = m_pPlaylist->topLevelItem ( 1 );
+
+
+	if (m_pPlaylistItem == NULL){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Song selected!" ));
+		return;
+	}else
+	{
+		if (m_pItem == 0){
+			m_pPlaylist->clear();
+			Hydrogen::get_instance()->m_PlayList.clear();
+			Playlist::get_instance()->setSelectedSongNr( -1 );
+			Playlist::get_instance()->setActiveSongNumber( -1 );
+			Playlist::get_instance()->__playlistName = "";
+			setWindowTitle ( trUtf8 ( "Play List Browser" ) );
+			return;
+		}else
+		{	
+			///avoid segfault if the last item will be removed!!
+			delete m_pPlaylistItem;
+			updatePlayListVector();
+			if (  Playlist::get_instance()->getActiveSongNumber() == index ){
+				Playlist::get_instance()->setActiveSongNumber( -1 );
+			}else if (  Playlist::get_instance()->getActiveSongNumber() > index  ){
+				Playlist::get_instance()->setActiveSongNumber(  Playlist::get_instance()->getActiveSongNumber() -1 );
+			}
+			
+		}
+	}
+}
+
+
+void PlaylistDialog::clearPlaylist()
+{
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	
+	m_pPlaylist->clear();
+	Hydrogen::get_instance()->m_PlayList.clear();
+	Playlist::get_instance()->setSelectedSongNr( -1 );
+	Playlist::get_instance()->setActiveSongNumber( -1 );
+	Playlist::get_instance()->__playlistName = "";
+	setWindowTitle ( trUtf8 ( "Play List Browser" ) );
+	return;	
+}
+
+
+void PlaylistDialog::updatePlayListNode ( QString file )
+{
+
+	QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
+	m_pPlaylistItem->setText ( 0, file );
+	m_pPlaylistItem->setText ( 1, "no Script" );
+	m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
+
+	updatePlayListVector();
+
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
+
+}
+
+
+void PlaylistDialog::loadList()
+{
+
+	static QString sDirectory =  Preferences::get_instance()->getDataDirectory()  + "playlists/" ;
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::ExistingFile );
+	fd->setDirectory ( sDirectory );
+
+	fd->setWindowTitle ( trUtf8 ( "Load Playlist" ) );
+
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted ){
+		filename = fd->selectedFiles().first();
+
+		LocalFileMng fileMng;
+		int err = fileMng.loadPlayList( filename.toLocal8Bit().constData() );
+		if ( err != 0 ) {
+			_ERRORLOG( "Error saving the playlist" );
+		}
+
+	
+		if(Hydrogen::get_instance()->m_PlayList.size() > 0){
+
+			QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+			m_pPlaylist->clear();
+
+			for ( uint i = 0; i < Hydrogen::get_instance()->m_PlayList.size(); ++i ){
+				QTreeWidgetItem* m_pPlaylistItem = new QTreeWidgetItem ( m_pPlaylistTree );
+				m_pPlaylistItem->setText ( 0, Hydrogen::get_instance()->m_PlayList[i].m_hFile );
+				m_pPlaylistItem->setText ( 1, Hydrogen::get_instance()->m_PlayList[i].m_hScript );
+				if ( Hydrogen::get_instance()->m_PlayList[i].m_hScriptEnabled == "Use Script" ) {
+					m_pPlaylistItem->setCheckState( 2, Qt::Checked );
+				}else{
+					m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
+				}
+			}
+
+			QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( 0 );
+			m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
+			Playlist::get_instance()->setSelectedSongNr( 0 );
+			Playlist::get_instance()->__playlistName = filename;
+			setWindowTitle ( trUtf8 ( "Play List Browser" ) + QString(" - ") + QString( Playlist::get_instance()->__playlistName  ) );
+		}
+
+	}
+}
+
+
+void PlaylistDialog::newScript()
+{
+
+	Preferences *pPref = Preferences::get_instance();
+
+	QString sDirectory = ( Preferences::get_instance()->getDataDirectory()  + "scripts/");
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::AnyFile );
+	fd->setFilter ( trUtf8 ( "Hydrogen Scripts (*.sh)" ) );
+	fd->setAcceptMode ( QFileDialog::AcceptSave );
+	fd->setWindowTitle ( trUtf8 ( "New Script" ) );
+	fd->setDirectory ( sDirectory );
+
+	QString defaultFilename;
+
+		defaultFilename += ".sh";
+
+
+	fd->selectFile ( defaultFilename );
+
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted )
+	{
+		filename = fd->selectedFiles().first();
+	}else
+	{
+		return;
+	}
+
+	if( filename.contains(" ", Qt::CaseInsensitive)){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Script name or path to the script contains whitespaces.\nIMPORTANT\nThe path to the script and the scriptname must without whitespaces.") );
+		return;
+	}
+	
+
+	QFile chngPerm ( filename );
+	if (!chngPerm.open(QIODevice::WriteOnly | QIODevice::Text))
+		return;
+
+	QTextStream out(&chngPerm);
+	out <<  "#!/bin/sh\n\n#have phun";
+	chngPerm.close();
+
+
+	if (chngPerm.exists() ) {
+		chngPerm.setPermissions( QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner );
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "WARNING, the new file is executable by the owner of the file!" ) );
+	}
+	
+	if( pPref->getDefaultEditor().isEmpty() ){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Default Editor Set. Please set your Default Editor\nDo not use a console based Editor\nSorry, but this will not work for the moment." ) );
+
+		static QString lastUsedDir = "/usr/bin/";
+	
+		std::auto_ptr<QFileDialog> fd( new QFileDialog );
+		fd->setFileMode ( QFileDialog::ExistingFile );
+		fd->setDirectory ( lastUsedDir );
+	
+		fd->setWindowTitle ( trUtf8 ( "Set your Default Editor" ) );
+	
+		QString filename;
+		if ( fd->exec() == QDialog::Accepted ){
+			filename = fd->selectedFiles().first();
+	
+			pPref->setDefaultEditor( filename );
+		}		
+	}
+
+	QString  openfile = pPref->getDefaultEditor() + " " + filename + "&";
+
+	char *ofile;
+	ofile = new char[openfile.length() + 1];
+	strcpy(ofile, openfile.toAscii());
+	std::system( ofile ); 
+	delete [] ofile;
+	return;
+
+	
+}
+
+
+void PlaylistDialog::saveListAs()
+{
+
+	QString sDirectory =  Preferences::get_instance()->getDataDirectory()  + "playlists/";
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::AnyFile );
+	fd->setFilter ( trUtf8 ( "Hydrogen Playlist (*.h2playlist)" ) );
+	fd->setAcceptMode ( QFileDialog::AcceptSave );
+	fd->setWindowTitle ( trUtf8 ( "Save Playlist" ) );
+	fd->setDirectory ( sDirectory );
+
+
+	QString defaultFilename;
+
+		defaultFilename += ".h2playlist";
+
+
+	fd->selectFile ( defaultFilename );
+
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted )
+	{
+		filename = fd->selectedFiles().first();
+	}else
+	{
+		return;
+	}
+
+	LocalFileMng fileMng;
+	int err = fileMng.savePlayList( filename.toLocal8Bit().constData() );
+	if ( err != 0 ) {
+		_ERRORLOG( "Error saving the playlist" );
+	}else
+	{
+		Playlist::get_instance()->__playlistName = filename;
+		setWindowTitle ( trUtf8 ( "Play List Browser" ) + QString(" - ") + QString( Playlist::get_instance()->__playlistName  ) );
+	}
+}
+
+
+void PlaylistDialog::saveList()
+{
+
+	if ( Playlist::get_instance()->__playlistName == "") {
+		// just in case!
+		return saveListAs();
+	}
+
+	LocalFileMng fileMng;
+	int err = fileMng.savePlayList( Playlist::get_instance()->__playlistName.toStdString() );
+	if ( err != 0 ) {
+		_ERRORLOG( "Error saving the playlist" );
+	}
+
+}
+
+
+void PlaylistDialog::loadScript()
+{
+	
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+	if ( m_pPlaylistItem == NULL ){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Song in List or no Song selected!" ) );
+		return;
+	}
+
+	static QString lastUsedDir =  Preferences::get_instance()->getDataDirectory()  + "scripts/";
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode ( QFileDialog::ExistingFile );
+	fd->setDirectory ( lastUsedDir );
+	fd->setFilter ( trUtf8 ( "Hydrogen Playlist (*.sh)" ) );
+	fd->setWindowTitle ( trUtf8 ( "Add Script to selected Song" ) );
+
+	QString filename;
+	if ( fd->exec() == QDialog::Accepted ){
+		filename = fd->selectedFiles().first();
+//		filename = filename.simplified();
+
+		if( filename.contains(" ", Qt::CaseInsensitive)){
+			QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Script name or path to the script contains whitespaces.\nIMPORTANT\nThe path to the script and the scriptname must without whitespaces.") );
+			return;
+		}
+
+		m_pPlaylistItem->setText ( 1, filename );
+		updatePlayListVector();
+
+	}
+}
+
+
+void PlaylistDialog::removeScript()
+{
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+
+
+	if (m_pPlaylistItem == NULL){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Song selected!" ));
+		return;
+	}else{
+		QString selected;
+		selected = m_pPlaylistItem->text ( 1 );
+		if( selected == "no Script"){
+			QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Script in use!" ));
+			return;
+		}else
+		{
+			m_pPlaylistItem->setText ( 1, "no Script" );
+			m_pPlaylistItem->setCheckState( 2, Qt::Unchecked );
+			updatePlayListVector();
+		}
+	}
+
+}
+
+
+void PlaylistDialog::editScript()
+{
+	Preferences *pPref = Preferences::get_instance();
+	if( pPref->getDefaultEditor().isEmpty() ){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Default Editor Set. Please set your Default Editor\nDo not use a console based Editor\nSorry, but this will not work for the moment." ) );
+
+		static QString lastUsedDir = "/usr/bin/";
+	
+		std::auto_ptr<QFileDialog> fd( new QFileDialog );
+		fd->setFileMode ( QFileDialog::ExistingFile );
+		fd->setDirectory ( lastUsedDir );
+	
+		fd->setWindowTitle ( trUtf8 ( "Set your Default Editor" ) );
+	
+		QString filename;
+		if ( fd->exec() == QDialog::Accepted ){
+			filename = fd->selectedFiles().first();
+	
+			pPref->setDefaultEditor( filename );
+		}		
+	}
+
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+
+	if ( m_pPlaylistItem == NULL ){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Song selected!" ) );
+		return;
+	}
+	QString selected;
+	selected = m_pPlaylistItem->text ( 1 );
+
+	QString filename = pPref->getDefaultEditor() + " " + selected + "&";
+
+	if( selected == "no Script"){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Script selected!" ));
+		return;
+	}
+
+	char *file;
+	file = new char[ filename.length() + 1 ];
+	strcpy( file , filename.toAscii() );
+	std::system( file ); 
+	delete [] file;
+	return;
+
+}
+
+
+void PlaylistDialog::o_upBClicked()
+{	
+	timer->stop();
+
+	Playlist* pList = Playlist::get_instance();
+
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+	int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
+
+	if (index == 0 ){
+		timer->start( 1000 ); 
+		return;
+	}
+
+	QTreeWidgetItem* tmpPlaylistItem = m_pPlaylist->takeTopLevelItem ( index );
+
+	m_pPlaylist->insertTopLevelItem ( index -1, tmpPlaylistItem );
+	m_pPlaylist->setCurrentItem ( tmpPlaylistItem ); 
+
+	if ( pList->getSelectedSongNr() >= 0 )
+		pList->setSelectedSongNr( pList->getSelectedSongNr() -1 );
+
+	if ( pList->getActiveSongNumber() == index ){
+		pList->setActiveSongNumber( pList->getActiveSongNumber() -1 );
+	}else if ( pList->getActiveSongNumber() == index -1 ){
+		pList->setActiveSongNumber( pList->getActiveSongNumber() +1 );
+	}
+
+	updatePlayListVector();
+
+}
+
+
+void PlaylistDialog::o_downBClicked()
+{
+	timer->stop();
+	Playlist* pList = Playlist::get_instance();
+
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	int length = m_pPlaylist->topLevelItemCount();
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+	int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
+
+	if ( index == length - 1){
+		timer->start( 1000 );
+		return;
+	}
+
+
+	QTreeWidgetItem* tmpPlaylistItem = m_pPlaylist->takeTopLevelItem ( index );
+
+	m_pPlaylist->insertTopLevelItem ( index +1, tmpPlaylistItem );
+	m_pPlaylist->setCurrentItem ( tmpPlaylistItem ); 
+
+	if ( pList->getSelectedSongNr() >= 0 )
+		pList->setSelectedSongNr( pList->getSelectedSongNr() +1 );
+
+	if (pList ->getActiveSongNumber() == index ){
+		pList->setActiveSongNumber( pList->getActiveSongNumber() +1 );
+	}else if ( pList->getActiveSongNumber() == index +1 ){
+		pList->setActiveSongNumber( pList->getActiveSongNumber() -1 );
+	}
+	updatePlayListVector();
+
+}
+
+
+void PlaylistDialog::on_m_pPlaylistTree_itemClicked ( QTreeWidgetItem * item, int column )
+{
+	if ( column == 2 ){ 
+		QString selected;
+		selected = item->text ( 1 );
+
+		if( selected == "no Script"){
+			QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Script!" ));
+			item->setCheckState( 2, Qt::Unchecked );
+			return;
+		}
+		updatePlayListVector();
+	}
+	return;
+}
+
+
+void PlaylistDialog::nodePlayBTN( Button* ref )
+{
+	Hydrogen *engine = Hydrogen::get_instance();
+	HydrogenApp *pH2App = HydrogenApp::get_instance();
+
+	if (ref->isPressed()) {
+		QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+		if ( m_pPlaylistItem == NULL ){
+			QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Song selected!" ) );
+			m_pPlayBtn->setPressed(false);
+			return;
+		}
+		QString selected = "";
+		selected = m_pPlaylistItem->text ( 0 );
+
+		if( selected == engine->getSong()->get_filename()){
+			engine->sequencer_play();
+			return;	
+		}		
+	
+		if ( engine->getState() == STATE_PLAYING ){
+			engine->sequencer_stop();
+		}
+	
+		LocalFileMng mng;
+		Song *pSong = Song::load ( selected );
+		if ( pSong == NULL ){
+			QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Error loading song." ) );
+			m_pPlayBtn->setPressed(false);
+			return;
+		}
+
+		QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+		int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
+		Playlist::get_instance()->setActiveSongNumber( index );
+	
+		pH2App->setSong ( pSong );
+		engine->setSelectedPatternNumber ( 0 );
+	
+		engine->sequencer_play();
+	}else 
+	{
+		engine->sequencer_stop();
+		pH2App->setStatusBarMessage(trUtf8("Pause."), 5000);
+	}
+}
+
+
+void PlaylistDialog::nodeStopBTN( Button* ref )
+{
+	UNUSED( ref );
+	m_pPlayBtn->setPressed(false);
+	Hydrogen::get_instance()->sequencer_stop();
+	Hydrogen::get_instance()->setPatternPos ( 0 );
+}
+
+
+void PlaylistDialog::ffWDBtnClicked( Button* ref)
+{
+	UNUSED( ref );
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	pEngine->setPatternPos( pEngine->getPatternPos() + 1 );
+}
+
+
+void PlaylistDialog::rewindBtnClicked( Button* ref )
+{
+	UNUSED( ref );
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	pEngine->setPatternPos( pEngine->getPatternPos() - 1 );
+}
+
+
+void PlaylistDialog::on_m_pPlaylistTree_itemDoubleClicked ()
+{
+
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylistTree->currentItem();
+	if ( m_pPlaylistItem == NULL ){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Song selected!" ) );
+		return;
+	}
+	QString selected;
+	selected = m_pPlaylistItem->text ( 0 );
+
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	int index = m_pPlaylist->indexOfTopLevelItem ( m_pPlaylistItem );
+	Playlist::get_instance()->setSelectedSongNr( index );
+	Playlist::get_instance()->setActiveSongNumber( index );
+	
+	HydrogenApp *pH2App = HydrogenApp::get_instance();
+	Hydrogen *engine = Hydrogen::get_instance();
+	
+
+	if ( engine->getState() == STATE_PLAYING ){
+		engine->sequencer_stop();
+	}
+
+	m_pPlayBtn->setPressed(false);
+
+	LocalFileMng mng;
+	Song *pSong = Song::load ( selected );
+	if ( pSong == NULL ){
+		QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Error loading song." ) );
+		return;
+	}
+
+	pH2App->setSong ( pSong );
+	engine->setSelectedPatternNumber ( 0 );
+
+
+	pH2App->setStatusBarMessage( trUtf8( "Playlist: Set song No. %1" ).arg( index +1 ), 5000 );
+
+	HydrogenApp::get_instance()->getInstrumentRack()->getSoundLibraryPanel()->update_background_color();
+
+///exec script
+///this is very very simple and only an experiment
+#ifdef WIN32
+	//I know nothing about windows scripts -wolke-
+	return;
+#else
+	QString execscript;
+	selected = m_pPlaylistItem->text ( 1 );
+	bool execcheckbox = m_pPlaylistItem->checkState ( 2 );
+
+	if( execcheckbox == false){
+		//QMessageBox::information ( this, "Hydrogen", trUtf8 ( "No Script selected!" ));
+		return;
+	}
+
+	if( execscript == "Script not used"){
+		//QMessageBox::information ( this, "Hydrogen", trUtf8 ( "Script not in use!" ));
+		return;
+	}
+
+	char *file;
+	file = new char[ selected.length() + 1 ];
+	strcpy( file , selected.toAscii() );
+	std::system( file ); 
+	delete [] file;
+	return;
+#endif
+
+}
+
+
+void PlaylistDialog::updatePlayListVector()
+{
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+	int length = m_pPlaylist->topLevelItemCount();
+
+	Hydrogen::get_instance()->m_PlayList.clear();
+
+
+
+	for (int i = 0 ;i < length; i++){
+		QTreeWidgetItem * m_pPlaylistItem = m_pPlaylist->topLevelItem ( i );	
+		
+		QString execval;
+		bool execcheckbox = m_pPlaylistItem->checkState ( 2 );
+		if ( execcheckbox == true ) {
+			execval = "Use Script";
+		}else{
+			execval = "Script not used";
+		} 
+		Hydrogen::HPlayListNode playListItem;
+		playListItem.m_hFile = m_pPlaylistItem->text ( 0 );
+		playListItem.m_hScript = m_pPlaylistItem->text ( 1 );
+		playListItem.m_hScriptEnabled = execval;
+
+		Hydrogen::get_instance()->m_PlayList.push_back( playListItem );
+	}
+	timer->start( 1000 );
+}
+
+
+void PlaylistDialog::updateActiveSongNumber()
+{
+	QTreeWidget* m_pPlaylist = m_pPlaylistTree;
+
+	for ( uint i = 0; i < Hydrogen::get_instance()->m_PlayList.size(); ++i ){
+		if ( !m_pPlaylist->topLevelItem( i ) )
+			break;
+		( m_pPlaylist->topLevelItem( i ) )->setBackground( 0, QBrush() );
+		( m_pPlaylist->topLevelItem( i ) )->setBackground( 1, QBrush() );
+		( m_pPlaylist->topLevelItem( i ) )->setBackground( 2, QBrush() );
+		
+	}
+		
+	int selected = Playlist::get_instance()->getActiveSongNumber();
+	if ( selected == -1 )
+		return;
+	
+	QTreeWidgetItem* m_pPlaylistItem = m_pPlaylist->topLevelItem ( selected );
+	if ( m_pPlaylistItem != NULL ){
+	    //m_pPlaylist->setCurrentItem ( m_pPlaylistItem );
+	    m_pPlaylistItem->setBackgroundColor ( 0, QColor( 50, 50, 50) );
+	    m_pPlaylistItem->setBackgroundColor ( 1, QColor( 50, 50, 50) );
+	    m_pPlaylistItem->setBackgroundColor ( 2, QColor( 50, 50, 50) );
+	}
+}
+
+
+bool PlaylistDialog::eventFilter ( QObject *o, QEvent *e )
+{
+	
+	UNUSED ( o );
+	if ( e->type() == QEvent::KeyPress )
+	{	
+		QKeyEvent *k = ( QKeyEvent * ) e;
+
+		switch ( k->key() )
+		{
+			case  Qt::Key_F5 :
+				if( Hydrogen::get_instance()->m_PlayList.size() == 0)
+					break;
+				Playlist::get_instance()->setPrevSongPlaylist();
+				return TRUE;
+				break;
+
+			case  Qt::Key_F6 :
+				if( Hydrogen::get_instance()->m_PlayList.size() == 0)
+					break;
+				Playlist::get_instance()->setNextSongPlaylist();
+				return TRUE;
+				break;
+		}
+
+	}
+	else
+	{
+		return FALSE; // standard event processing
+	}
+
+return NULL;
+}
+
Index: /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog.h	(revision 1319)
+++ /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog.h	(revision 1319)
@@ -0,0 +1,93 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PLAYLIST_DIALOG_H
+#define PLAYLIST_DIALOG_H
+
+#include "config.h"
+
+#include <QDialog>
+#include "ui_PlaylistDialog_UI.h"
+#include <hydrogen/Object.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/playlist.h>
+
+
+class Button;
+class ToggleButton;
+class PixmapWidget;
+
+///
+/// This dialog is used to use the H2PlayList
+///
+class PlaylistDialog : public QDialog, public Ui_PlaylistDialog_UI, public Object
+
+{
+	Q_OBJECT
+	public:
+		
+		PlaylistDialog( QWidget* pParent );
+		~PlaylistDialog();
+	
+
+
+	private slots:
+		void addSong();
+		void addCurrentSong();
+		void removeFromList();
+		void removeScript();
+		void clearPlaylist();
+		void loadList();
+		void saveListAs();
+		void saveList();
+		void loadScript();
+		void ffWDBtnClicked(Button* ref);
+		void nodePlayBTN( Button* ref );
+		void nodeStopBTN( Button* ref );
+		void rewindBtnClicked(Button *ref);
+		void editScript();
+		void newScript();
+		void on_m_pPlaylistTree_itemClicked ( QTreeWidgetItem * item, int column );
+		void o_upBClicked();
+		void o_downBClicked();
+		void on_m_pPlaylistTree_itemDoubleClicked ();
+		void updateActiveSongNumber();
+		bool eventFilter ( QObject *o, QEvent *e );
+
+
+	private:
+
+		void updatePlayListNode( QString file );
+		void updatePlayListVector();
+		void setFirstItemCurrent();
+		Button *zoom_in_btn;
+		QTimer *timer;
+
+		Button *m_pRwdBtn;
+		ToggleButton *m_pPlayBtn;
+		Button *m_pStopBtn;
+		Button *m_pFfwdBtn;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog_UI.ui
===================================================================
--- /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog_UI.ui	(revision 1394)
+++ /branches/tabbedInterface/gui/src/PlaylistEditor/PlaylistDialog_UI.ui	(revision 1394)
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PlaylistDialog_UI</class>
+ <widget class="QDialog" name="PlaylistDialog_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>961</width>
+    <height>397</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>PlayList Browser</string>
+  </property>
+  <widget class="QTreeWidget" name="m_pPlaylistTree">
+   <property name="geometry">
+    <rect>
+     <x>12</x>
+     <y>29</y>
+     <width>921</width>
+     <height>321</height>
+    </rect>
+   </property>
+   <property name="minimumSize">
+    <size>
+     <width>0</width>
+     <height>271</height>
+    </size>
+   </property>
+   <property name="acceptDrops">
+    <bool>false</bool>
+   </property>
+   <property name="verticalScrollBarPolicy">
+    <enum>Qt::ScrollBarAsNeeded</enum>
+   </property>
+   <property name="horizontalScrollBarPolicy">
+    <enum>Qt::ScrollBarAsNeeded</enum>
+   </property>
+   <property name="tabKeyNavigation">
+    <bool>true</bool>
+   </property>
+   <property name="showDropIndicator" stdset="0">
+    <bool>false</bool>
+   </property>
+   <property name="dragEnabled">
+    <bool>false</bool>
+   </property>
+   <property name="dragDropOverwriteMode">
+    <bool>false</bool>
+   </property>
+   <property name="dragDropMode">
+    <enum>QAbstractItemView::NoDragDrop</enum>
+   </property>
+   <property name="rootIsDecorated">
+    <bool>true</bool>
+   </property>
+   <property name="uniformRowHeights">
+    <bool>true</bool>
+   </property>
+   <property name="itemsExpandable">
+    <bool>false</bool>
+   </property>
+   <property name="sortingEnabled">
+    <bool>false</bool>
+   </property>
+   <property name="move" stdset="0">
+    <stringlist/>
+   </property>
+   <column>
+    <property name="text">
+     <string>Song list</string>
+    </property>
+   </column>
+  </widget>
+  <widget class="QWidget" name="sideBarWidget" native="true">
+   <property name="geometry">
+    <rect>
+     <x>940</x>
+     <y>30</y>
+     <width>16</width>
+     <height>311</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QWidget" name="verticalLayout">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>350</y>
+     <width>181</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout"/>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: /branches/tabbedInterface/gui/src/ExportSongDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/ExportSongDialog.cpp	(revision 1474)
+++ /branches/tabbedInterface/gui/src/ExportSongDialog.cpp	(revision 1474)
@@ -0,0 +1,353 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QFileDialog>
+#include <QProgressBar>
+#include <QLabel>
+#include <QPixmap>
+
+#include "ExportSongDialog.h"
+#include "Skin.h"
+#include "HydrogenApp.h"
+#include <hydrogen/Song.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/IO/AudioOutput.h>
+
+#include <memory>
+
+using namespace H2Core;
+
+ExportSongDialog::ExportSongDialog(QWidget* parent)
+ : QDialog(parent)
+ , Object( "ExportSongDialog" )
+ , m_bExporting( false )
+{
+	setupUi( this );
+	setModal( true );
+	setWindowTitle( trUtf8( "Export song" ) );
+//	setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	HydrogenApp::get_instance()->addEventListener( this );
+
+	m_pProgressBar->setValue( 0 );
+	srComboBox->setCurrentIndex(1);
+	sdComboBox->setCurrentIndex(1);
+
+	QString defaultFilename( Hydrogen::get_instance()->getSong()->get_filename() );
+	if( Hydrogen::get_instance()->getSong()->get_filename().isEmpty() )
+		defaultFilename = Hydrogen::get_instance()->getSong()->__name;
+	defaultFilename.replace( '*', "_" );
+	defaultFilename.replace( ".h2song", "" );	
+	defaultFilename += ".wav";
+	exportNameTxt->setText(defaultFilename);
+	b_QfileDialog = false;
+
+}
+
+
+
+ExportSongDialog::~ExportSongDialog()
+{
+	HydrogenApp::get_instance()->removeEventListener( this );
+}
+
+
+
+/// \todo: memorizzare l'ultima directory usata
+void ExportSongDialog::on_browseBtn_clicked()
+{
+//	static QString lastUsedDir = "";
+	static QString lastUsedDir = QDir::homePath();
+
+
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode(QFileDialog::AnyFile);
+	//fd->setFilter( trUtf8("Wave file (*.wav)") );
+	fd->setNameFilters( QStringList() << "Microsoft WAV (*.wav *.WAV)"
+         				  << "Apple AIFF (*.aiff *.AIFF)"
+         				  << "Lossless  Flac (*.flac *.FLAC)"
+					  << "Compressed Ogg (*.ogg *.OGG)" );
+         				 // << "Any files (*)");
+
+	fd->setDirectory( lastUsedDir );
+	fd->setAcceptMode( QFileDialog::AcceptSave );
+	fd->setWindowTitle( trUtf8( "Export song" ) );
+//	fd->setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	QString defaultFilename = exportNameTxt->text();
+
+	fd->selectFile(defaultFilename);
+
+	QString filename = "";
+	if (fd->exec()) {
+		filename = fd->selectedFiles().first();
+		b_QfileDialog = true;
+	}
+
+	if ( ! filename.isEmpty() ) {
+		lastUsedDir = fd->directory().absolutePath();
+		QString sNewFilename = filename;
+//		if ( sNewFilename.endsWith( ".wav" ) == false ) {
+//			filename += ".wav";
+//		}
+
+		exportNameTxt->setText(filename);
+	}
+
+	if( filename.endsWith( ".ogg" ) || filename.endsWith( ".OGG" ) ){
+		srComboBox->hide();
+		sdComboBox->hide();
+		label->hide();
+		label_2->hide();
+	}
+		
+}
+
+
+
+void ExportSongDialog::on_okBtn_clicked()
+{
+	if (m_bExporting) {
+		return;
+	}
+
+	m_pSamplerateLbl->setText( trUtf8( "Sample rate: %1" ).arg( sdComboBox->currentText() ) );
+	QString filename = exportNameTxt->text();
+	if ( QFile( filename ).exists() == true && b_QfileDialog == false ) {
+		int res = QMessageBox::information( this, "Hydrogen", tr( "The file %1 exists. \nOverwrite the existing file?").arg(filename), tr("&Ok"), tr("&Cancel"), 0, 1 );
+		if (res == 1 ) return;
+	}
+	m_bExporting = true;
+	
+	Hydrogen::get_instance()->startExportSong( filename, srComboBox->currentText().toInt(), sdComboBox->currentText().toInt() );
+}
+
+
+
+void ExportSongDialog::on_closeBtn_clicked()
+{
+	Hydrogen::get_instance()->stopExportSong();
+	m_bExporting = false;
+	accept();
+
+}
+
+
+void ExportSongDialog::on_taplatescomboBox_currentIndexChanged(int index )
+{
+	/**index
+	 * 0 = wav 44100 | 16
+	 * 1 = wav 48000 | 16
+	 * 2 = wav 48000 | 24
+	 * 3 = wav 22050 | 8
+	 * 4 = wav 96000 | 32
+	 * 5 = aiff 44100 | 16
+	 * 6 = aiff 48000 | 16
+	 * 7 = aiff 48000 | 24
+	 * 8 = flac 48000 
+	 * 9 = ogg VBR , disable comboboxes
+	 **/
+//	QMessageBox::information( this, "Hydrogen", trUtf8("index %1").arg(index) );
+	QString filename;
+	QStringList splitty;
+	switch ( index ) {
+	case 0:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 1 ); //44100hz
+		sdComboBox->setCurrentIndex ( 1 ); //16bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".wav";
+		exportNameTxt->setText(filename);
+		break;
+	case 1:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 2 ); //48000hz
+		sdComboBox->setCurrentIndex ( 1 ); //16bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".wav";
+		exportNameTxt->setText(filename);
+		break;
+	case 2:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 2 ); //48000hz
+		sdComboBox->setCurrentIndex ( 2 ); //24bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".wav";
+		exportNameTxt->setText(filename);
+		break;
+	case 3:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 0 ); //22050hz
+		sdComboBox->setCurrentIndex ( 0 ); //8bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".wav";
+		exportNameTxt->setText(filename);
+		break;
+	case 4:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 3 ); //96000hz
+		sdComboBox->setCurrentIndex ( 3 ); //32bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".wav";
+		exportNameTxt->setText(filename);
+		break;
+	case 5:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 1 ); //44100hz
+		sdComboBox->setCurrentIndex ( 1 ); //16bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".aiff";
+		exportNameTxt->setText(filename);
+		break;
+	case 6:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 2 ); //48000hz
+		sdComboBox->setCurrentIndex ( 1 ); //16bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".aiff";
+		exportNameTxt->setText(filename);
+		break;
+	case 7:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 2 ); //48000hz
+		sdComboBox->setCurrentIndex ( 2 ); //24bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".aiff";
+		exportNameTxt->setText(filename);
+		break;
+	case 8:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 2 ); //48000hz
+		sdComboBox->setCurrentIndex ( 2 ); //24bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".flac";
+		exportNameTxt->setText(filename);
+		break;
+	case 9:
+		srComboBox->hide();
+		sdComboBox->hide();
+		label->hide();
+		label_2->hide();
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".ogg";
+		exportNameTxt->setText(filename);
+		break;
+
+	default:
+		srComboBox->show();
+		sdComboBox->show();
+		srComboBox->setCurrentIndex ( 1 ); //44100hz
+		sdComboBox->setCurrentIndex ( 1 ); //16bit
+		filename = exportNameTxt->text();
+		splitty = filename.split(".");
+		splitty.removeLast();
+		filename = splitty.join( "." );
+		filename += ".wav";
+		exportNameTxt->setText(filename);
+		;
+	}
+
+
+}
+
+
+void ExportSongDialog::on_exportNameTxt_textChanged( const QString& )
+{
+	QString filename = exportNameTxt->text();
+	if ( ! filename.isEmpty() ) {
+		okBtn->setEnabled(true);
+	}
+	else {
+		okBtn->setEnabled(false);
+	}
+
+	if( filename.endsWith( ".ogg" ) || filename.endsWith( ".OGG" ) ){
+		taplatescomboBox->setCurrentIndex( 9 );//ogg	
+	}
+	else if( filename.endsWith( ".flac" ) || filename.endsWith( ".FLAC" ) ){
+		label->show();
+		label_2->show();
+		taplatescomboBox->setCurrentIndex( 8 );//flac	
+	}
+	else if( filename.endsWith( ".aiff" ) || filename.endsWith( ".AIFF" ) ){
+		label->show();
+		label_2->show();
+		taplatescomboBox->setCurrentIndex( 5 );//aiff	
+	}
+	else if( filename.endsWith( ".wav" ) || filename.endsWith( ".WAV" ) ){
+		label->show();
+		label_2->show();
+		taplatescomboBox->setCurrentIndex( 0 );//wav	
+	}
+}
+
+
+void ExportSongDialog::progressEvent( int nValue )
+{
+        m_pProgressBar->setValue( nValue );
+	if ( nValue == 100 ) {
+		m_bExporting = false;
+		QFile check( exportNameTxt->text() );
+		if ( ! check.exists() ) {
+			QMessageBox::information( this, "Hydrogen", trUtf8("Export failed!") );
+		}
+	}
+}
Index: /branches/tabbedInterface/gui/src/AboutDialog.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/AboutDialog.cpp	(revision 1416)
+++ /branches/tabbedInterface/gui/src/AboutDialog.cpp	(revision 1416)
@@ -0,0 +1,142 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "config.h"
+#include "version.h"
+#include "AboutDialog.h"
+#include "Skin.h"
+
+#include <hydrogen/globals.h>
+
+#include <vector>
+
+
+
+AboutDialog::AboutDialog(QWidget* parent)
+ : QDialog( parent )
+{
+	setupUi( this );
+
+	setWindowTitle( tr( "About" ) );
+	setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+	move( 240, 100 );
+
+	QString about;
+	about += QString("<center><b>Hydrogen Drum Machine %1 [%2] </b><br>").arg( get_version().c_str() ).arg( __DATE__ );
+	about += tr( "<b>Website</b><br>" );
+	about += "http://www.hydrogen-music.org<br><br>";
+	about += tr( "<b>Project page</b><br>");
+	about += "http://sourceforge.net/projects/hydrogen<br><br>";
+	about += tr( "<b>Mailing lists</b><br>");
+	about += "http://lists.sourceforge.net/lists/listinfo/hydrogen-announce<br>";
+	about += "http://lists.sourceforge.net/lists/listinfo/hydrogen-devel<br>";
+	aboutTxt->setText( about );
+
+
+
+	std::vector<Author> authorList;
+	authorList.push_back( Author( "Antonio Piraino", "", "Italian manual" ) );
+	authorList.push_back( Author( "Artemiy Pavlov (aka Artemio)", "www.artemiolabs.com", "Drum kits, demo patterns, web site" ) );
+	authorList.push_back( Author( "Alexandre Prokoudine", "", "Russian translation" ) );
+	authorList.push_back( Author( "Ben Powers", "", "Docs" ) );
+	authorList.push_back( Author( "Benjamin Flaming", "", "Jack patches, bug fix" ) );
+	authorList.push_back( Author( "Carlo Impagliazzo (aka Truijllo)", "", "Testing, ideas.." ) );
+	authorList.push_back( Author( "Chris Wareham", "", "NetBSD patch" ) );
+	authorList.push_back( Author( "Christian Vorhof", "", "Interface design concept" ) );
+	authorList.push_back( Author( "Daniil Kolpakov", "", "" ) );
+	authorList.push_back( Author( "Daniel Tonda Castillo", "", "Spanish manual" ) );
+	authorList.push_back( Author( "Dave Fancella", "", "" ) );
+	authorList.push_back( Author( "Dave Phillips", "", "Bug reports, ideas" ) );
+	authorList.push_back( Author( "Derrick Karpo", "", "Patches, testing" ) );
+	authorList.push_back( Author( "Dmitry Ivanov", "", "" ) );
+	authorList.push_back( Author( "Ede Wolf", "", "Faq, testing" ) );
+	authorList.push_back( Author( "Elizeu Santos-Neto", "", "Portuguese(Brazil) translation" ) );
+	authorList.push_back( Author( "Emiliano Grilli (aka Emillo)", "www.emillo.net", "Drum kits, demo patterns" ) );
+	authorList.push_back( Author( "Esben Stien", "", "" ) );
+	authorList.push_back( Author( "Francesco Cabras", "", "Patches, testing" ) );
+	authorList.push_back( Author( "Gabriel M. Beddingfield", "gabriel@teuton.org", "Patches, ideas" ) );
+	authorList.push_back( Author( "Gene", "", "Patches, testing" ) );
+	authorList.push_back( Author( "Jakob Lund", "jlund05@imada.sdu.dk", " coding" ) );
+	authorList.push_back( Author( "Jason Schaefer", "schaefer.jason@gmail.com", " Patches, lead/lag feature" ) );
+	authorList.push_back( Author( "Jesse Chappel", "", "Jack patches" ) );
+	authorList.push_back( Author( "Jonas Melzer", "", "German manual" ) );
+	authorList.push_back( Author( "Jonathan Dempsey", "jonathandempsey@fastmail.fm", "Mac OSX port" ) );
+	authorList.push_back( Author( "Journeyman", "jman-@masternet.it", " manual") );
+	authorList.push_back( Author( "Kevin Dahan (aka Unet)", "", "French translation" ) );
+	authorList.push_back( Author( "Lee Revell", "", "Patches" ) );
+	authorList.push_back( Author( "Matt Walker", "", "" ) );
+	authorList.push_back( Author( "Michael Wolkstein", "m.wolkstein@gmx.de", "coding" ) );
+	authorList.push_back( Author( "Paul Dorman", "", "" ) );
+	authorList.push_back( Author( "Pieter Van Isacker (aka aikie)", "", "Dutch manual and translation" ) );
+	authorList.push_back( Author( "Samuel Mimram", "", "Packages" ) );
+	authorList.push_back( Author( "Sebastian Moors (aka mauser)", "mauser@smoors.de", "coding" ) );
+	authorList.push_back( Author( "Sergio Gil Perez de la Manga", "", "Spanish translation" ) );
+	authorList.push_back( Author( "Simon Donike", "", "German translation" ) );
+	authorList.push_back( Author( "Torben Hohn", "", "Bug fix, test" ) );
+	authorList.push_back( Author( "Yamasaki Yutaka", "yamasaki@good-day.co.jp", "Japanese translation" ) );
+	authorList.push_back( Author( "Willie Sippel", "willie@zeitgeistmedia.net", "GUI graphics, coding" ) );
+
+	QString sAuthors;
+	sAuthors += tr( "<b>Main coder and mantainer:</b><br>" );
+	sAuthors += "<ul><li><p>Alessandro Cominu (aka Comix)<br>";
+	sAuthors += "<i><comix@users.sourceforge.net></i></p></li></ul>";
+
+	sAuthors += QString( "<b>" ) + trUtf8( "Translator:%1Alessandro Cominu" ).arg( "</b><br><ul><li><p>" ) + QString( "</p></li></ul>" );
+
+	sAuthors += "<b>Thanks to:</b>";
+
+	sAuthors += "<ul>";
+
+	for ( uint i = 0; i < authorList.size(); ++i ) {
+		Author a = authorList.at( i );
+		sAuthors += "<li><p>";
+		sAuthors += "<i>" + a.m_sName + "</i>";
+		sAuthors += "</p></li>";
+	}
+	sAuthors += "</ul>";
+
+
+	authorsTxt->append( sAuthors );
+
+	logoLabel->setPixmap( QPixmap( Skin::getImagePath() +"/about/aboutLogo.png" ) );
+}
+
+
+
+
+AboutDialog::~AboutDialog()
+{
+}
+
+
+
+
+/**
+ * Close the dialog
+ */
+void AboutDialog::on_okBtn_clicked()
+{
+	accept();
+}
Index: /branches/tabbedInterface/gui/src/AudioEngineInfoForm.h
===================================================================
--- /branches/tabbedInterface/gui/src/AudioEngineInfoForm.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/AudioEngineInfoForm.h	(revision 377)
@@ -0,0 +1,63 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef AUDIO_ENGINE_INFO_FORM_H
+#define AUDIO_ENGINE_INFO_FORM_H
+
+#include "config.h"
+#include <hydrogen/Object.h>
+
+#include "EventListener.h"
+#include "ui_AudioEngineInfoForm_UI.h"
+
+#include <QtGui>
+
+/**
+ * Audio Engine information form
+ */
+class AudioEngineInfoForm : public QWidget, public Ui_AudioEngineInfoForm_UI, public EventListener, public Object
+{
+	Q_OBJECT
+	private:
+		QTimer *timer;
+
+		virtual void updateAudioEngineState();
+
+		// EventListener implementation
+		virtual void stateChangedEvent(int nState);
+		virtual void patternChangedEvent();
+		//~ EventListener implementation
+
+	public:
+		AudioEngineInfoForm(QWidget* parent);
+		~AudioEngineInfoForm();
+
+		void showEvent ( QShowEvent *ev );
+		void hideEvent ( QHideEvent *ev );
+
+	public slots:
+		void updateInfo();
+};
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/MetroBlinker.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/MetroBlinker.cpp	(revision 1567)
+++ /branches/tabbedInterface/gui/src/MetroBlinker.cpp	(revision 1567)
@@ -0,0 +1,183 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+ /**
+ **
+ ** this dialog is used to use show a director.
+ ** for example to play live without a click in your ears.
+ ** here you get a: 
+ ** 	- visual metronome 
+ ** 	- bar position info
+ ** 	- beat position info
+ **	- bar position tags *
+ ** *this will implemented at timeline. rightclick on timeline open a dioalog to add position tags. this director displayed this tags.
+ ** *first row will display the current tag, second row display next bar tag.
+ **
+ **	-------------------------------------------
+ **	|                     |                     |
+ **	|        Bar          |       Beat          |	
+ **	|                     |                     |	
+ **	-------------------------------------------
+ **	|                                           |
+ **	|            current bar tag                |
+ **	|                                           |	
+ **	-------------------------------------------
+ **	|                                           |
+ **	|              next bar tag                 |
+ **	|                                           |
+ **	-------------------------------------------
+ **/
+
+
+#include "MetroBlinker.h"
+#include "HydrogenApp.h"
+#include "widgets/PixmapWidget.h"
+
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <QRect>
+
+
+using namespace H2Core;
+using namespace std;
+
+MetroBlinker::MetroBlinker ( QWidget* pParent )
+		: QDialog ( pParent )
+		, Object ( "MetroBlinker" )
+{
+
+	HydrogenApp::get_instance()->addEventListener( this );
+	setupUi ( this );
+	INFOLOG ( "INIT" );
+	setWindowTitle ( trUtf8 ( "Director" ) );
+
+	p_counter = 1;	// to compute the right beat
+	p_fadealpha = 255;	//default alpha
+	p_bar = 1;	// default bar
+	p_wechselblink = 0;
+
+	p_bpm = Hydrogen::get_instance()->getSong()->__bpm;
+	timer = new QTimer( this );
+	connect( timer, SIGNAL( timeout() ), this, SLOT( updateMetronomBackground() ) );
+}
+
+
+MetroBlinker::~MetroBlinker()
+{
+	INFOLOG ( "DESTROY" );
+}
+
+
+void MetroBlinker::metronomeEvent( int nValue )
+{
+	//bpm
+	p_bpm = Hydrogen::get_instance()->getSong()->__bpm; 
+	//bar
+	p_bar = Hydrogen::get_instance()->getPatternPos() +1;
+	if ( p_bar <= 0 )
+		p_bar = 1;
+	// 1000 ms / bpm / 60s
+	timer->start( static_cast<int>( 1000 / ( p_bpm / 60 )) / 2 );
+	p_wechselblink = 0;
+	p_fadealpha = 255;
+	if ( nValue == 2 ){
+		p_fadealpha = 0;
+		update();
+		TAG="";
+		TAG2="";
+		return;
+	}
+	if ( nValue == 1 ) {	//foregroundcolor "rect" for first blink
+		p_color = QColor( 255, 50, 1 ,255 );
+		p_counter = 1;		
+	}
+	else {	//foregroundcolor "rect" for all other blinks
+		p_counter++;
+		if( p_counter %2 == 0 ) 
+			p_wechselblink = width() / 2;
+
+		p_color = QColor( 24, 250, 31, 255 );
+
+	}
+
+	//get tags
+
+	if(Hydrogen::get_instance()->m_timelinetagvector.size() >= 1 ){
+		for ( int t = 0; t < static_cast<int>(Hydrogen::get_instance()->m_timelinetagvector.size()); t++){
+			if ( Hydrogen::get_instance()->m_timelinetagvector[t].m_htimelinetagbeat == p_bar ){
+				TAG2 =  Hydrogen::get_instance()->m_timelinetagvector[t].m_htimelinetag ;
+			}
+			else if ( Hydrogen::get_instance()->m_timelinetagvector[t].m_htimelinetagbeat == p_bar - 1){
+				TAG =  Hydrogen::get_instance()->m_timelinetagvector[t].m_htimelinetag ;
+			}
+		}
+	}else
+	{
+		TAG="";
+		TAG2="";
+	}
+
+	update();
+}
+
+
+void MetroBlinker::updateMetronomBackground()
+{
+	p_color.setAlpha( 0 );
+	timer->stop();
+	update();
+}
+
+
+void MetroBlinker::paintEvent( QPaintEvent* ev )
+{
+	//draw the metronome
+	QPainter painter(this);
+	painter.setPen( QPen(QColor( 249, 235, 116, 200 ) ,1 , Qt::SolidLine ) );
+	painter.setBrush( p_color );
+	painter.drawRect (  width() / 50 + p_wechselblink, height() / 50 , width() -  width() / 25 -  width() / 2, height() / 2 -  height() / 25 );
+
+	//draw bars
+	painter.setPen(Qt::white);
+	painter.setFont(QFont("Arial", height() / 4 ));
+	QRect r1(QPoint( width() * 1 / 16 , height() * 1 / 16 ), QSize( width() / 3, height() / 3));
+	painter.drawText( r1, Qt::AlignCenter, QString("%1").arg( p_bar) );
+
+	//draw beats
+	QRect r2(QPoint( width() * 9 / 16 , height() * 1 / 16 ), QSize( width() / 3, height() / 3));
+	painter.drawText( r2, Qt::AlignCenter, QString("%1").arg( p_counter) );
+
+	if( TAG == TAG2 )
+		 TAG2 = "";
+	//draw current bar tag
+	painter.setPen(Qt::white);
+	painter.setFont(QFont("Arial", height() / 13 ));
+	QRect r3(QPoint ( width() * 1 / 50 , height() * 8 / 16 ), QSize( width() - width() / 25, height() / 3));
+	painter.drawText( r3, Qt::AlignCenter, QString( (TAG) ) );
+
+	//draw next bar tag
+	painter.setPen(Qt::gray);
+	painter.setFont(QFont("Arial", height() / 15 ));
+	QRect r4(QPoint ( width() * 1 / 50 , height() * 11 / 16 ), QSize( width() - width() / 25, height() / 3));
+	painter.drawText( r4, Qt::AlignCenter, QString( TAG2 ) );
+}
Index: /branches/tabbedInterface/gui/src/PlayerControl.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/PlayerControl.cpp	(revision 1487)
+++ /branches/tabbedInterface/gui/src/PlayerControl.cpp	(revision 1487)
@@ -0,0 +1,1231 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "Skin.h"
+#include "PlayerControl.h"
+#include "InstrumentRack.h"
+	#include "HydrogenApp.h"
+
+#include "widgets/LCD.h"
+#include "widgets/Button.h"
+#include "widgets/CpuLoadWidget.h"
+#include "widgets/MidiActivityWidget.h"
+#include "widgets/PixmapWidget.h"
+
+#include "Mixer/Mixer.h"
+#include "SongEditor/SongEditorPanel.h"
+#include "PatternEditor/PatternEditorPanel.h"
+#include "InstrumentEditor/InstrumentEditorPanel.h"
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/IO/JackOutput.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/event_queue.h>
+using namespace H2Core;
+
+
+//beatconter global
+int bcDisplaystatus = 0;
+//~ beatcounter
+
+PlayerControl::PlayerControl(QWidget *parent)
+ : QLabel(parent)
+ , Object( "PlayerControl" )
+{
+	// Background image
+	setPixmap( QPixmap( Skin::getImagePath() + "/playerControlPanel/background.png" ) );
+	setScaledContents( true );
+
+	QHBoxLayout *hbox = new QHBoxLayout();
+	hbox->setSpacing( 0 );
+	hbox->setMargin( 0 );
+	setLayout( hbox );
+
+
+
+// CONTROLS
+	PixmapWidget *pControlsPanel = new PixmapWidget( NULL );
+	pControlsPanel->setFixedSize( 344, 43 );
+	pControlsPanel->setPixmap( "/playerControlPanel/background_Control.png" );
+	hbox->addWidget( pControlsPanel );
+
+	m_pTimeDisplayH = new LCDDisplay( pControlsPanel, LCDDigit::LARGE_GRAY, 2 );
+	m_pTimeDisplayH->move( 27, 12 );
+	m_pTimeDisplayH->setText( "00" );
+
+	m_pTimeDisplayM = new LCDDisplay( pControlsPanel, LCDDigit::LARGE_GRAY, 2 );
+	m_pTimeDisplayM->move( 61, 12 );
+	m_pTimeDisplayM->setText( "00" );
+
+	m_pTimeDisplayS = new LCDDisplay( pControlsPanel, LCDDigit::LARGE_GRAY, 2 );
+	m_pTimeDisplayS->move( 95, 12 );
+	m_pTimeDisplayS->setText( "00" );
+
+	m_pTimeDisplayMS = new LCDDisplay( pControlsPanel, LCDDigit::SMALL_GRAY, 3 );
+	m_pTimeDisplayMS->move( 122, 16 );
+	m_pTimeDisplayMS->setText( "000" );
+
+	// Rewind button
+	m_pRwdBtn = new Button(
+			pControlsPanel,
+			"/playerControlPanel/btn_rwd_on.png",
+			"/playerControlPanel/btn_rwd_off.png",
+			"/playerControlPanel/btn_rwd_over.png",
+			QSize(21, 15)
+	);
+	m_pRwdBtn->move(168, 17);
+	m_pRwdBtn->setToolTip( trUtf8("Rewind") );
+	connect(m_pRwdBtn, SIGNAL(clicked(Button*)), this, SLOT(RewindBtnClicked(Button*)));
+
+	// Record button
+	m_pRecBtn = new ToggleButton(
+			pControlsPanel,
+			"/playerControlPanel/btn_rec_on.png",
+			"/playerControlPanel/btn_rec_off.png",
+			"/playerControlPanel/btn_rec_over.png",
+			QSize(21, 15)
+	);
+	m_pRecBtn->move(195, 17);
+	m_pRecBtn->setPressed(false);
+	m_pRecBtn->setHidden(false);
+	m_pRecBtn->setToolTip( trUtf8("Record") );
+	connect(m_pRecBtn, SIGNAL(clicked(Button*)), this, SLOT(recBtnClicked(Button*)));
+	connect(m_pRecBtn, SIGNAL(rightClicked(Button*)), this, SLOT(recBtnRightClicked(Button*)));
+
+	// Record+delete button
+	m_pRecDelBtn = new ToggleButton(
+			pControlsPanel,
+			"/playerControlPanel/btn_recdel_on.png",
+			"/playerControlPanel/btn_recdel_off.png",
+			"/playerControlPanel/btn_recdel_over.png",
+			QSize(21, 15)
+	);
+	m_pRecDelBtn->move(195, 17);
+	m_pRecDelBtn->setPressed(false);
+	m_pRecDelBtn->setHidden(true);
+	m_pRecDelBtn->setToolTip( trUtf8("Destructive Record") );
+	connect(m_pRecDelBtn, SIGNAL(clicked(Button*)), this, SLOT(recBtnClicked(Button*)));
+	connect(m_pRecDelBtn, SIGNAL(rightClicked(Button*)), this, SLOT(recBtnRightClicked(Button*)));
+	
+
+
+	// Play button
+	m_pPlayBtn = new ToggleButton(
+			pControlsPanel,
+			"/playerControlPanel/btn_play_on.png",
+			"/playerControlPanel/btn_play_off.png",
+			"/playerControlPanel/btn_play_over.png",
+			QSize(26, 17)
+	);
+	m_pPlayBtn->move(222, 17);
+	m_pPlayBtn->setPressed(false);
+	m_pPlayBtn->setToolTip( trUtf8("Play/ Pause") );
+	connect(m_pPlayBtn, SIGNAL(clicked(Button*)), this, SLOT(playBtnClicked(Button*)));
+
+	// Stop button
+	m_pStopBtn = new Button(
+			pControlsPanel,
+			"/playerControlPanel/btn_stop_on.png",
+			"/playerControlPanel/btn_stop_off.png",
+			"/playerControlPanel/btn_stop_over.png",
+			QSize(21, 15)
+	);
+	m_pStopBtn->move(254, 17);
+	m_pStopBtn->setToolTip( trUtf8("Stop") );
+	connect(m_pStopBtn, SIGNAL(clicked(Button*)), this, SLOT(stopBtnClicked(Button*)));
+
+	// Fast forward button
+	m_pFfwdBtn = new Button(
+			pControlsPanel,
+			"/playerControlPanel/btn_ffwd_on.png",
+			"/playerControlPanel/btn_ffwd_off.png",
+			"/playerControlPanel/btn_ffwd_over.png",
+			QSize(21, 15)
+	);
+	m_pFfwdBtn->move(281, 17);
+	m_pFfwdBtn->setToolTip( trUtf8("Fast Forward") );
+	connect(m_pFfwdBtn, SIGNAL(clicked(Button*)), this, SLOT(FFWDBtnClicked(Button*)));
+
+	// Loop song button button
+	m_pSongLoopBtn = new ToggleButton(
+			pControlsPanel,
+			"/playerControlPanel/btn_loop_on.png",
+			"/playerControlPanel/btn_loop_off.png",
+			"/playerControlPanel/btn_loop_over.png",
+			QSize(21, 15)
+	);
+	m_pSongLoopBtn->move(310, 17);
+	m_pSongLoopBtn->setToolTip( trUtf8("Loop song") );
+	connect( m_pSongLoopBtn, SIGNAL( clicked(Button*) ), this, SLOT( songLoopBtnClicked(Button*) ) );
+//~ CONTROLS
+
+
+// MODE
+	PixmapWidget *pModePanel = new PixmapWidget( NULL );
+	pModePanel->setFixedSize( 90, 43 );
+	pModePanel->setPixmap( "/playerControlPanel/background_Mode.png" );
+	hbox->addWidget( pModePanel );
+
+	// Live mode button
+	m_pLiveModeBtn = new ToggleButton(
+			pModePanel,
+			"/playerControlPanel/statusLED_on.png",
+			"/playerControlPanel/statusLED_off.png",
+			"/playerControlPanel/statusLED_off.png",
+			QSize(11, 9)
+	);
+	m_pLiveModeBtn->move(10, 4);
+	m_pLiveModeBtn->setPressed(true);
+	m_pLiveModeBtn->setToolTip( trUtf8("Pattern Mode") );
+	connect(m_pLiveModeBtn, SIGNAL(clicked(Button*)), this, SLOT(liveModeBtnClicked(Button*)));
+
+	// Song mode button
+	m_pSongModeBtn = new ToggleButton(
+			pModePanel,
+			"/playerControlPanel/statusLED_on.png",
+			"/playerControlPanel/statusLED_off.png",
+			"/playerControlPanel/statusLED_off.png",
+			QSize(11, 9)
+	);
+	m_pSongModeBtn->move(10, 15);
+	m_pSongModeBtn->setPressed(false);
+	m_pSongModeBtn->setToolTip( trUtf8("Song Mode") );
+	connect(m_pSongModeBtn, SIGNAL(clicked(Button*)), this, SLOT(songModeBtnClicked(Button*)));
+
+	// Switch mode button
+	m_pSwitchModeBtn = new Button(
+			pModePanel,
+			"/playerControlPanel/btn_mode_on.png",
+			"/playerControlPanel/btn_mode_off.png",
+			"/playerControlPanel/btn_mode_over.png",
+			QSize(69, 13)
+	);
+	m_pSwitchModeBtn->move(10, 26);
+	m_pSwitchModeBtn->setToolTip( trUtf8("Switch Song/ Pattern Mode") );
+	connect(m_pSwitchModeBtn, SIGNAL(clicked(Button*)), this, SLOT(switchModeBtnClicked(Button*)));
+//~ MODE
+
+// BC on off
+	PixmapWidget *pControlsBBTBConoffPanel = new PixmapWidget( NULL );
+	pControlsBBTBConoffPanel->setFixedSize( 15, 43 );
+	pControlsBBTBConoffPanel->setPixmap( "/playerControlPanel/onoff.png" );
+	hbox->addWidget( pControlsBBTBConoffPanel );
+
+	m_pBConoffBtn = new ToggleButton(
+			pControlsBBTBConoffPanel,
+			"/playerControlPanel/bc_on.png",
+			"/playerControlPanel/bc_off.png",
+			"/playerControlPanel/bc_off.png",
+			QSize(10, 40)
+	);
+	m_pBConoffBtn->move(1, 1);
+	m_pBConoffBtn->setPressed(false);
+	m_pBConoffBtn->setToolTip( trUtf8("BeatCounter Panel on") );
+	connect(m_pBConoffBtn, SIGNAL(clicked(Button*)), this, SLOT(bconoffBtnClicked(Button*)));
+//~  BC on off
+
+//beatcounter
+	m_pControlsBCPanel = new PixmapWidget( NULL );
+	m_pControlsBCPanel->setFixedSize( 86, 43 );
+	m_pControlsBCPanel->setPixmap( "/playerControlPanel/beatConter_BG.png" );
+	hbox->addWidget( m_pControlsBCPanel );
+	
+
+	m_pBCDisplayZ = new LCDDisplay( m_pControlsBCPanel, LCDDigit::LARGE_GRAY, 2 );
+	m_pBCDisplayZ->move( 36, 8 );
+	m_pBCDisplayZ->setText( "--" );
+
+
+	m_pBCDisplayT = new LCDDisplay( m_pControlsBCPanel, LCDDigit::SMALL_GRAY, 1 );
+	m_pBCDisplayT->move( 23, 26 );
+	m_pBCDisplayT->setText( "4" );
+
+	m_pBCDisplayB = new LCDDisplay( m_pControlsBCPanel, LCDDigit::SMALL_GRAY, 2 );
+	m_pBCDisplayB->move( 39, 26 );
+// set display from 4 to 04. fix against qt4 transparent problem 
+//	m_pBCDisplayB->setText( "4" );
+	m_pBCDisplayB->setText( "04" );
+
+	m_pBCTUpBtn = new Button(
+			m_pControlsBCPanel,
+			"/lcd/LCDSpinBox_up_on.png",
+			"/lcd/LCDSpinBox_up_off.png",
+			"/lcd/LCDSpinBox_up_over.png",
+			QSize(16, 8)
+	);
+	m_pBCTUpBtn->move( 4, 6 );
+	connect( m_pBCTUpBtn, SIGNAL( clicked( Button* ) ), this, SLOT(bctButtonClicked( Button* ) ) );
+
+	m_pBCTDownBtn = new Button(
+			m_pControlsBCPanel,
+			"/lcd/LCDSpinBox_down_on.png",
+			"/lcd/LCDSpinBox_down_off.png",
+			"/lcd/LCDSpinBox_down_over.png",
+			QSize(16, 8)
+	);
+	m_pBCTDownBtn->move( 4, 16 );
+	connect( m_pBCTDownBtn, SIGNAL( clicked( Button* ) ), this, SLOT(bctButtonClicked( Button* ) ) );
+
+	m_pBCBUpBtn = new Button(
+			m_pControlsBCPanel,
+			"/lcd/LCDSpinBox_up_on.png",
+			"/lcd/LCDSpinBox_up_off.png",
+			"/lcd/LCDSpinBox_up_over.png",
+			QSize(16, 8)
+	);
+	m_pBCBUpBtn->move( 65, 6 );
+	connect( m_pBCBUpBtn, SIGNAL( clicked( Button* ) ), this, SLOT(bcbButtonClicked( Button* ) ) );
+
+	m_pBCBDownBtn = new Button(
+			m_pControlsBCPanel,
+			"/lcd/LCDSpinBox_down_on.png",
+			"/lcd/LCDSpinBox_down_off.png",
+			"/lcd/LCDSpinBox_down_over.png",
+			QSize(16, 8)
+	);
+	m_pBCBDownBtn->move( 65, 16 );
+	connect( m_pBCBDownBtn, SIGNAL( clicked( Button* ) ), this, SLOT(bcbButtonClicked( Button* ) ) );
+
+	m_pBCSetPlayBtn = new ToggleButton(
+			m_pControlsBCPanel,
+			"/playerControlPanel/btn_set_play_on.png",
+			"/playerControlPanel/btn_set_play_off.png",
+			"/playerControlPanel/btn_set_play_off.png",
+			QSize(15, 13)
+	);
+	m_pBCSetPlayBtn->move(67, 27);
+	m_pBCSetPlayBtn->setPressed(false);
+	m_pBCSetPlayBtn->setToolTip( trUtf8("Set BPM / Set BPM and play") );
+	connect(m_pBCSetPlayBtn, SIGNAL(clicked(Button*)), this, SLOT(bcSetPlayBtnClicked(Button*)));
+//~ beatcounter
+
+
+// BPM
+	PixmapWidget *pBPMPanel = new PixmapWidget( NULL );
+	pBPMPanel->setFixedSize( 145, 43 );
+	pBPMPanel->setPixmap( "/playerControlPanel/background_BPM.png" );
+	hbox->addWidget( pBPMPanel );
+
+	// LCD BPM SpinBox
+	m_pLCDBPMSpinbox = new LCDSpinBox( pBPMPanel, 6, LCDSpinBox::FLOAT, 30, 400 );
+	m_pLCDBPMSpinbox->move( 43, 6 );
+	connect( m_pLCDBPMSpinbox, SIGNAL(changed(LCDSpinBox*)), this, SLOT(bpmChanged()));
+	connect( m_pLCDBPMSpinbox, SIGNAL(spinboxClicked()), this, SLOT(bpmClicked()));
+
+	m_pBPMUpBtn = new Button(
+			pBPMPanel,
+			"/lcd/LCDSpinBox_up_on.png",
+			"/lcd/LCDSpinBox_up_off.png",
+			"/lcd/LCDSpinBox_up_over.png",
+			QSize(16, 8)
+	);
+	m_pBPMUpBtn->move( 12, 5 );
+	connect( m_pBPMUpBtn, SIGNAL( clicked( Button* ) ), this, SLOT(bpmButtonClicked( Button* ) ) );
+	connect( m_pBPMUpBtn, SIGNAL( mousePress( Button* ) ), this, SLOT(bpmButtonPressed( Button* ) ) );
+
+	m_pBPMDownBtn = new Button(
+			pBPMPanel,
+			"/lcd/LCDSpinBox_down_on.png",
+			"/lcd/LCDSpinBox_down_off.png",
+			"/lcd/LCDSpinBox_down_over.png",
+			QSize(16, 8)
+	);
+	m_pBPMDownBtn->move( 12, 14 );
+	connect( m_pBPMDownBtn, SIGNAL( clicked( Button* ) ), this, SLOT(bpmButtonClicked( Button* ) ) );
+	connect( m_pBPMDownBtn, SIGNAL( mousePress( Button* ) ), this, SLOT(bpmButtonPressed( Button* ) ) );
+
+	m_pRubberBPMChange = new ToggleButton(
+			pBPMPanel,
+			"/playerControlPanel/rubber_on.png",
+			"/playerControlPanel/rubber_off.png",
+			"/playerControlPanel/rubber_off.png",
+			QSize(9, 37)
+	);
+	m_pRubberBPMChange->move( 133, 3 );
+	m_pRubberBPMChange->setToolTip( trUtf8("Recalculate Rubberband modified samples if bpm will change") );
+	m_pRubberBPMChange->setPressed(false);
+	connect( m_pRubberBPMChange, SIGNAL( clicked( Button* ) ), this, SLOT(rubberbandButtonToggle( Button* ) ) );
+	QString program = Preferences::get_instance()->m_rubberBandCLIexecutable;
+	//test the path. if test fails, no button
+	if ( QFile( program ).exists() == false) {
+		m_pRubberBPMChange->hide();
+	}
+
+
+	m_pMetronomeWidget = new MetronomeWidget( pBPMPanel );
+	m_pMetronomeWidget->resize( 85, 5 );
+	m_pMetronomeWidget->move( 42, 25 );
+
+	m_pMetronomeBtn = new ToggleButton(
+			pBPMPanel,
+			"/playerControlPanel/btn_metronome_on.png",
+			"/playerControlPanel/btn_metronome_off.png",
+			"/playerControlPanel/btn_metronome_over.png",
+			QSize( 20, 13 )
+	);
+	m_pMetronomeBtn->move( 10, 26 );
+	connect( m_pMetronomeBtn, SIGNAL( clicked( Button* ) ), this, SLOT(metronomeButtonClicked( Button* ) ) );
+//~ BPM
+
+
+// JACK
+	PixmapWidget *pJackPanel = new PixmapWidget( NULL );
+	pJackPanel->setFixedSize( 113, 43 );
+	pJackPanel->setPixmap( "/playerControlPanel/background_Jack.png" );
+	hbox->addWidget( pJackPanel );
+
+	// Jack transport mode button
+	m_pJackTransportBtn = new ToggleButton(
+			pJackPanel,
+			"/playerControlPanel/jackTransportBtn_on.png",
+			"/playerControlPanel/jackTransportBtn_off.png",
+			"/playerControlPanel/jackTransportBtn_over.png",
+			QSize(45, 13)
+	);
+	m_pJackTransportBtn->hide();
+	m_pJackTransportBtn->setPressed(true);
+	m_pJackTransportBtn->setToolTip( trUtf8("Jack-transport on/off") );
+	connect(m_pJackTransportBtn, SIGNAL(clicked(Button*)), this, SLOT(jackTransportBtnClicked(Button*)));
+	m_pJackTransportBtn->move(10, 26);
+
+	//jack time master
+	m_pJackMasterBtn = new ToggleButton(
+			pJackPanel,
+			"/playerControlPanel/jackMasterBtn_on.png",
+			"/playerControlPanel/jackMasterBtn_off.png",
+			"/playerControlPanel/jackMasterBtn_over.png",
+			QSize(45, 13)
+	);
+	m_pJackMasterBtn->hide();
+	m_pJackMasterBtn->setPressed(true);
+	m_pJackMasterBtn->setToolTip( trUtf8("Jack-Time-Master on/off") );
+	connect(m_pJackMasterBtn, SIGNAL(clicked(Button*)), this, SLOT(jackMasterBtnClicked(Button*)));
+	m_pJackMasterBtn->move(56, 26);
+	//~ jack time master
+
+	m_pEngine = Hydrogen::get_instance();
+
+	// CPU load widget
+	m_pCpuLoadWidget = new CpuLoadWidget( pJackPanel );
+
+	// Midi Activity widget
+	m_pMidiActivityWidget = new MidiActivityWidget( pJackPanel );
+
+	m_pMidiActivityWidget->move( 10, 14 );
+	m_pCpuLoadWidget->move( 10, 4 );
+//~ JACK
+
+
+	PixmapWidget *pLcdBackGround = new PixmapWidget( NULL );
+	pLcdBackGround->setFixedSize( 256, 43 );
+	pLcdBackGround->setPixmap( "/playerControlPanel/lcd_background.png" );
+	hbox->addWidget( pLcdBackGround );
+
+	m_pShowMixerBtn = new ToggleButton(
+			pLcdBackGround,
+			"/skin_btn_on.png",
+			"/skin_btn_off.png",
+			"/skin_btn_over.png",
+			QSize( 80, 17 ),
+			true
+	);
+	m_pShowMixerBtn->move( 7, 6 );
+	m_pShowMixerBtn->setToolTip( trUtf8( "Show mixer" ) );
+	m_pShowMixerBtn->setText( trUtf8( "Mixer" ) );
+	connect(m_pShowMixerBtn, SIGNAL(clicked(Button*)), this, SLOT(showButtonClicked(Button*)));
+
+	m_pShowInstrumentRackBtn = new ToggleButton(
+			pLcdBackGround,
+			"/skin_btn_on.png",
+			"/skin_btn_off.png",
+			"/skin_btn_over.png",
+			QSize( 160, 17 ),
+			true
+	);
+	m_pShowInstrumentRackBtn->move( 88, 6 );
+	m_pShowInstrumentRackBtn->setToolTip( trUtf8( "Show Instrument Rack" ) );
+	m_pShowInstrumentRackBtn->setText( trUtf8( "Instrument rack" ) );
+	connect( m_pShowInstrumentRackBtn, SIGNAL( clicked(Button*) ), this, SLOT( showButtonClicked( Button*)) );
+
+	m_pStatusLabel = new LCDDisplay(pLcdBackGround , LCDDigit::SMALL_BLUE, 30, true );
+	m_pStatusLabel->move( 7, 25 );
+
+
+	hbox->addStretch( 1000 );	// this must be the last widget in the HBOX!!
+
+
+
+
+	QTimer *timer = new QTimer( this );
+	connect(timer, SIGNAL(timeout()), this, SLOT(updatePlayerControl()));
+	timer->start(100);	// update player control at 10 fps
+
+	m_pBPMTimer = new QTimer( this );
+	connect(m_pBPMTimer, SIGNAL(timeout()), this, SLOT(onBpmTimerEvent()));
+
+	m_pStatusTimer = new QTimer( this );
+	connect( m_pStatusTimer, SIGNAL( timeout() ), this, SLOT( onStatusTimerEvent() ) );
+
+	m_pScrollTimer = new QTimer( this );
+	connect( m_pScrollTimer, SIGNAL( timeout() ), this, SLOT( onScrollTimerEvent() ) );
+	m_pScrollMessage = "";
+}
+
+
+
+
+PlayerControl::~PlayerControl() {
+}
+
+
+
+
+
+void PlayerControl::updatePlayerControl()
+{
+	Preferences *pPref = Preferences::get_instance();
+	HydrogenApp *pH2App = HydrogenApp::get_instance();
+	m_pShowMixerBtn->setPressed( pH2App->getMixer()->isVisible() );
+	m_pShowInstrumentRackBtn->setPressed( pH2App->getInstrumentRack()->isVisible() );
+
+	int state = m_pEngine->getState();
+	if (state == STATE_PLAYING ) {
+		m_pPlayBtn->setPressed(true);
+	}
+	else {
+		m_pPlayBtn->setPressed(false);
+	}
+
+	if (pPref->getRecordEvents()) {
+		m_pRecBtn->setPressed(true);
+		m_pRecDelBtn->setPressed(true);
+	}
+	else {
+		m_pRecBtn->setPressed(false);
+		m_pRecDelBtn->setPressed(false);
+	}
+
+	if (pPref->getDestructiveRecord()) {
+		if (  m_pRecDelBtn->isHidden() ) {
+			m_pRecBtn->setHidden(true);
+			m_pRecDelBtn->setHidden(false);
+		}
+	}
+	else {
+		if (  m_pRecBtn->isHidden() ) {
+			m_pRecBtn->setHidden(false);
+			m_pRecDelBtn->setHidden(true);
+		}
+	}
+
+	Song *song = m_pEngine->getSong();
+
+	m_pSongLoopBtn->setPressed( song->is_loop_enabled() );
+
+	m_pLCDBPMSpinbox->setValue( song->__bpm );
+
+	if ( song->get_mode() == Song::PATTERN_MODE ) {
+		m_pLiveModeBtn->setPressed( true );
+		m_pSongModeBtn->setPressed( false );
+	}
+	else {
+		m_pLiveModeBtn->setPressed( false );
+		m_pSongModeBtn->setPressed( true );
+	}
+
+	//beatcounter
+	if ( pPref->m_bbc == Preferences::BC_OFF ) {
+		m_pControlsBCPanel->hide();
+		m_pBConoffBtn->setPressed(false);
+	}else
+	{
+		m_pControlsBCPanel->show();
+		m_pBConoffBtn->setPressed(true);
+	}
+
+	if ( pPref->m_mmcsetplay ==  Preferences::SET_PLAY_OFF) {
+		m_pBCSetPlayBtn->setPressed(false);
+	}else
+	{
+		m_pBCSetPlayBtn->setPressed(true);
+	}
+	//~ beatcounter
+
+
+
+
+	if ( pPref->m_sAudioDriver == "Jack" ) {
+		m_pJackTransportBtn->show();
+		switch ( pPref->m_bJackTransportMode ) {
+			case Preferences::NO_JACK_TRANSPORT:
+				m_pJackTransportBtn->setPressed(false);
+				// Jack Master Btn
+				m_pJackMasterBtn->setPressed(false);
+				break;
+
+			case Preferences::USE_JACK_TRANSPORT:
+				m_pJackTransportBtn->setPressed(true);
+				//m_pJackMasterBtn->setPressed(false);
+				break;
+		}
+	}
+	else {
+		m_pJackTransportBtn->hide();
+	}
+
+	//jack transport master
+#ifdef JACK_SUPPORT
+	if ( pPref->m_sAudioDriver == "Jack" ) {
+		m_pJackMasterBtn->show();
+		switch ( pPref->m_bJackMasterMode ) {
+			case Preferences::NO_JACK_TIME_MASTER:
+				m_pJackMasterBtn->setPressed(false);
+				break;
+
+			case Preferences::USE_JACK_TIME_MASTER:
+				if ( m_pJackTransportBtn->isPressed()){
+					m_pJackMasterBtn->setPressed(true);
+				}
+				else
+				{
+					m_pJackMasterBtn->setPressed(false);
+					Hydrogen::get_instance()->offJackMaster();	
+					pPref->m_bJackMasterMode = Preferences::NO_JACK_TIME_MASTER;
+				}
+				//m_pJackTransportBtn->setPressed(true);
+				break;
+		}
+	}
+	else {
+		m_pJackMasterBtn->hide();
+		
+	}
+#endif
+	//~ jack transport master
+
+	// time
+	float fFrames = m_pEngine->getAudioOutput()->m_transport.m_nFrames;
+	if ( Preferences::get_instance()->m_bJackTransportMode == Preferences::USE_JACK_TRANSPORT )
+		fFrames =  m_pEngine->getHumantimeFrames();
+	float fSampleRate = m_pEngine->getAudioOutput()->getSampleRate();
+	if ( fSampleRate != 0 ) {
+		float fSeconds = fFrames / fSampleRate;
+
+		int nMSec = (int)( (fSeconds - (int)fSeconds) * 1000.0 );
+		int nSeconds = ( (int)fSeconds ) % 60;
+		int nMins = (int)( fSeconds / 60.0 ) % 60;
+		int nHours = (int)( fSeconds / 3600.0 );
+
+		char tmp[100];
+		sprintf(tmp, "%02d", nHours );
+		m_pTimeDisplayH->setText( QString( tmp ) );
+
+		sprintf(tmp, "%02d", nMins );
+		m_pTimeDisplayM->setText( QString( tmp ) );
+
+		sprintf(tmp, "%02d", nSeconds );
+		m_pTimeDisplayS->setText( QString( tmp ) );
+
+		sprintf(tmp, "%03d", nMSec );
+		m_pTimeDisplayMS->setText( QString( tmp ) );
+	}
+
+	m_pMetronomeBtn->setPressed(pPref->m_bUseMetronome);
+
+
+	//beatcounter get BC message
+	char bcstatus[4];
+	int beatstocountondisplay = 1;
+	beatstocountondisplay = m_pEngine->getBcStatus();
+
+	switch (beatstocountondisplay){
+		case 1 :
+			if (bcDisplaystatus == 1){
+				Preferences::get_instance()->m_bbc = Preferences::BC_OFF;
+				bcDisplaystatus = 0;
+			}
+			sprintf(bcstatus, "R");
+				m_pBCDisplayZ->setText( QString (bcstatus) );
+				
+			break;
+		default:
+			if (Preferences::get_instance()->m_bbc == Preferences::BC_OFF){
+				Preferences::get_instance()->m_bbc = Preferences::BC_ON;
+				bcDisplaystatus = 1;
+			}
+			sprintf(bcstatus, "%02d ", beatstocountondisplay -1);
+			m_pBCDisplayZ->setText( QString (bcstatus) );
+
+	}
+	//~ beatcounter
+
+	//timeline check
+//	if( Preferences::get_instance()->__usetimeline ){
+//		m_pRubberBPMChange->setPressed( false );
+//		Preferences::get_instance()->m_useTheRubberbandBpmChangeEvent = false;
+//	}
+}
+
+
+
+/// Toggle record mode
+void PlayerControl::recBtnClicked(Button* ref) {
+	if ( m_pEngine->getState() != STATE_PLAYING ) {
+		if (ref->isPressed()) {
+			Preferences::get_instance()->setRecordEvents(true);
+			(HydrogenApp::get_instance())->setScrollStatusBarMessage(trUtf8("Record midi events = On" ), 2000 );
+		}
+		else {
+			Preferences::get_instance()->setRecordEvents(false);
+			(HydrogenApp::get_instance())->setScrollStatusBarMessage(trUtf8("Record midi events = Off" ), 2000 );
+		}
+	}
+}
+
+
+/// Toggle destructive/nondestructive move
+void PlayerControl::recBtnRightClicked(Button* ref) {
+	UNUSED( ref );
+	if ( Preferences::get_instance()->getDestructiveRecord() ) {
+		Preferences::get_instance()->setDestructiveRecord(false);
+		(HydrogenApp::get_instance())->setScrollStatusBarMessage(trUtf8("Destructive mode = Off" ), 2000 );
+	}
+	else {
+		Preferences::get_instance()->setDestructiveRecord(true);
+		(HydrogenApp::get_instance())->setScrollStatusBarMessage(trUtf8("Destructive mode = On" ), 2000 );
+	}
+	HydrogenApp::get_instance()->enableDestructiveRecMode();
+}
+
+
+/// Start audio engine
+void PlayerControl::playBtnClicked(Button* ref) {
+	if (ref->isPressed()) {
+		m_pEngine->sequencer_play();
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Playing."), 5000);
+	}
+	else {
+//		m_pPlayBtn->setPressed(true);
+		m_pEngine->sequencer_stop();
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Pause."), 5000);
+	}
+}
+
+
+
+
+/// Stop audio engine
+void PlayerControl::stopBtnClicked(Button* ref)
+{
+	UNUSED( ref );
+	m_pPlayBtn->setPressed(false);
+	m_pEngine->sequencer_stop();
+	m_pEngine->setPatternPos( 0 );
+	(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Stopped."), 5000);
+	Hydrogen::get_instance()->setTimelineBpm();
+}
+
+
+
+
+/// Switch mode
+void PlayerControl::switchModeBtnClicked(Button* ref)
+{
+	UNUSED( ref );
+
+	Song *song = m_pEngine->getSong();
+
+	m_pEngine->sequencer_stop();
+	m_pEngine->setPatternPos( 0 );	// from start
+	if( song->get_mode() == Song::PATTERN_MODE ) {
+		m_pEngine->getSong()->set_mode( Song::SONG_MODE );
+		m_pSongModeBtn->setPressed(true);
+		m_pLiveModeBtn->setPressed(false);
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Song mode selected."), 5000);
+	}
+	else {
+		m_pEngine->getSong()->set_mode( Song::PATTERN_MODE );
+		m_pSongModeBtn->setPressed(false);
+		m_pLiveModeBtn->setPressed(true);
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Pattern mode selected."), 5000);
+	}
+}
+
+
+
+
+/// Set Song mode
+void PlayerControl::songModeBtnClicked(Button* ref)
+{
+	UNUSED( ref );
+
+	m_pEngine->sequencer_stop();
+	m_pEngine->setPatternPos( 0 );	// from start
+	m_pEngine->getSong()->set_mode( Song::SONG_MODE );
+	m_pSongModeBtn->setPressed(true);
+	m_pLiveModeBtn->setPressed(false);
+	(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Song mode selected."), 5000);
+}
+
+
+
+
+///Set Live mode
+void PlayerControl::liveModeBtnClicked(Button* ref)
+{
+	UNUSED( ref );
+
+	m_pEngine->sequencer_stop();
+	m_pEngine->getSong()->set_mode( Song::PATTERN_MODE );
+	//m_pEngine->sequencer_setNextPattern( m_pEngine->getSelectedPatternNumber() );	// imposto il pattern correntemente selezionato come il prossimo da suonare
+	m_pSongModeBtn->setPressed(false);
+	m_pLiveModeBtn->setPressed(true);
+	(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Pattern mode selected."), 5000);
+}
+
+
+
+void PlayerControl::bpmChanged() {
+	float fNewBpmValue = m_pLCDBPMSpinbox->getValue();
+	if (fNewBpmValue < 30) {
+		fNewBpmValue = 30;
+	}
+	else if (fNewBpmValue > 400 ) {
+		fNewBpmValue = 400;
+	}
+
+	m_pEngine->getSong()->__is_modified = true;
+
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+	m_pEngine->setBPM( fNewBpmValue );
+	AudioEngine::get_instance()->unlock();
+}
+
+
+
+//beatcounter
+void PlayerControl::bconoffBtnClicked( Button* )
+{
+	Preferences *pPref = Preferences::get_instance();
+	if (m_pBConoffBtn->isPressed()) {
+		pPref->m_bbc = Preferences::BC_ON;
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8(" BC Panel on"), 5000);
+		m_pControlsBCPanel->show();
+		
+	}
+	else {
+		pPref->m_bbc = Preferences::BC_OFF;
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8(" BC Panel off"), 5000);
+		m_pControlsBCPanel->hide();
+	}
+	
+}
+
+void PlayerControl::bcSetPlayBtnClicked( Button* )
+{
+	Preferences *pPref = Preferences::get_instance();
+	if (m_pBCSetPlayBtn->isPressed()) {
+		pPref->m_mmcsetplay = Preferences::SET_PLAY_ON;
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8(" Count BPM and start PLAY"), 5000);
+		
+	}
+	else {
+		pPref->m_mmcsetplay = Preferences::SET_PLAY_OFF;
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8(" Count and set BPM"), 5000);
+	}
+		
+}
+
+
+void PlayerControl::rubberbandButtonToggle(Button* )
+{
+	Preferences *pPref = Preferences::get_instance();
+	if (m_pRubberBPMChange->isPressed()) {
+		EventQueue::get_instance()->push_event( EVENT_RECALCULATERUBBERBAND, -1);
+		pPref->m_useTheRubberbandBpmChangeEvent = true;
+		(HydrogenApp::get_instance())->setScrollStatusBarMessage(trUtf8("Recalculate all samples using Rubberband ON"), 2000);
+		
+	}
+	else {
+		pPref->m_useTheRubberbandBpmChangeEvent = false;
+		(HydrogenApp::get_instance())->setScrollStatusBarMessage(trUtf8("Recalculate all samples using Rubberband OFF"), 2000);
+	}
+}
+
+
+void PlayerControl::bcbButtonClicked( Button* bBtn)
+{
+	int tmp = m_pEngine->getbeatsToCount();
+	char tmpb[3];       // m_pBCBUpBtn
+		if ( bBtn == m_pBCBUpBtn ) {
+			tmp ++;
+			if (tmp > 16)
+				tmp = 2;
+//small fix against qt4 png transparent problem
+//think this will be solved in next time
+//			if (tmp < 10 ){
+//				sprintf(tmpb, "%01d", tmp );
+//			}else
+//			{
+				sprintf(tmpb, "%02d", tmp );
+//			}
+			m_pBCDisplayB->setText( QString( tmpb ) );
+			m_pEngine->setbeatsToCount( tmp );
+	}
+	else {		
+			tmp --;
+			if (tmp < 2 )
+				 tmp = 16;
+//small fix against qt4 png transparent problem
+//think this will be solved in next time
+//			if (tmp < 10 ){
+//				sprintf(tmpb, "%01d", tmp );
+//			}else
+//			{
+				sprintf(tmpb, "%02d", tmp );
+//			}
+			m_pBCDisplayB->setText( QString( tmpb ) );
+			m_pEngine->setbeatsToCount( tmp );
+	}
+}
+
+
+
+void PlayerControl::bctButtonClicked( Button* tBtn)
+{
+	float tmp = m_pEngine->getNoteLength() * 4; 
+	
+	if ( tBtn == m_pBCTUpBtn) {
+			tmp = tmp / 2 ;
+			if (tmp < 1)
+				tmp = 8;
+
+			m_pBCDisplayT->setText( QString::number( tmp ) );
+			m_pEngine->setNoteLength( (tmp) / 4 );
+	} else {		
+			tmp = tmp * 2;
+			if (tmp > 8 )
+				 tmp = 1;
+			m_pBCDisplayT->setText( QString::number(tmp) );
+			m_pEngine->setNoteLength( (tmp) / 4 );
+	}
+}
+//~ beatcounter 
+
+
+
+void PlayerControl::jackTransportBtnClicked( Button* )
+{
+	Preferences *pPref = Preferences::get_instance();
+
+	if (m_pJackTransportBtn->isPressed()) {
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		pPref->m_bJackTransportMode = Preferences::USE_JACK_TRANSPORT;
+		AudioEngine::get_instance()->unlock();
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Jack-transport mode = On"), 5000);
+	}
+	else {
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		pPref->m_bJackTransportMode = Preferences::NO_JACK_TRANSPORT;
+		AudioEngine::get_instance()->unlock();
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8("Jack-transport mode = Off"), 5000);
+	}
+
+	if (pPref->m_sAudioDriver != "Jack") {
+		QMessageBox::warning( this, "Hydrogen", trUtf8( "JACK-transport will work only with JACK driver." ) );
+	}
+}
+
+
+//jack time master
+void PlayerControl::jackMasterBtnClicked( Button* )
+{	
+#ifdef JACK_SUPPORT
+	Preferences *pPref = Preferences::get_instance();
+
+	if (m_pJackMasterBtn->isPressed()) {
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		pPref->m_bJackMasterMode = Preferences::USE_JACK_TIME_MASTER;
+		AudioEngine::get_instance()->unlock();
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8(" Jack-Time-Master mode = On"), 5000);
+		Hydrogen::get_instance()->onJackMaster();
+		
+	}
+	else {
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		pPref->m_bJackMasterMode = Preferences::NO_JACK_TIME_MASTER;
+		AudioEngine::get_instance()->unlock();
+		(HydrogenApp::get_instance())->setStatusBarMessage(trUtf8(" Jack-Time-Master mode = Off"), 5000);
+		//m_pControlsBBTPanel->hide();
+		Hydrogen::get_instance()->offJackMaster();
+	}
+
+	if (pPref->m_sAudioDriver != "Jack") {
+		QMessageBox::warning( this, "Hydrogen", trUtf8( "JACK-transport will work only with JACK driver." ) );
+	}
+#endif
+}
+//~ jack time master
+
+void PlayerControl::bpmClicked()
+{
+	bool bIsOkPressed;
+	double fNewVal= QInputDialog::getDouble( this, "Hydrogen", trUtf8( "New BPM value" ),  m_pLCDBPMSpinbox->getValue(), 10, 400, 2, &bIsOkPressed );
+	if ( bIsOkPressed  ) {
+		if ( fNewVal < 30 ) {
+			return;
+		}
+
+		m_pEngine->getSong()->__is_modified  = true;
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		m_pEngine->setBPM( fNewVal );
+		AudioEngine::get_instance()->unlock();
+	}
+	else {
+		// user entered nothing or pressed Cancel
+	}
+}
+
+
+void PlayerControl::bpmButtonPressed( Button* pBtn)
+{
+	if ( pBtn == m_pBPMUpBtn ) {
+		m_pLCDBPMSpinbox->upBtnClicked();
+		m_nBPMIncrement = 1;
+	}
+	else {
+		m_pLCDBPMSpinbox->downBtnClicked();
+		m_nBPMIncrement = -1;
+	}
+	m_pBPMTimer->start( 100 );
+}
+
+
+void PlayerControl::bpmButtonClicked( Button* )
+{
+	m_pBPMTimer->stop();
+}
+
+
+void PlayerControl::onBpmTimerEvent()
+{
+	if (m_nBPMIncrement == 1) {
+		m_pLCDBPMSpinbox->upBtnClicked();
+	}
+	else {
+		m_pLCDBPMSpinbox->downBtnClicked();
+	}
+}
+
+
+void PlayerControl::FFWDBtnClicked( Button* )
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	pEngine->setPatternPos( pEngine->getPatternPos() + 1 );
+	Hydrogen::get_instance()->setTimelineBpm();
+}
+
+
+
+void PlayerControl::RewindBtnClicked( Button* )
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	pEngine->setPatternPos( pEngine->getPatternPos() - 1 );
+	Hydrogen::get_instance()->setTimelineBpm();
+}
+
+
+void PlayerControl::songLoopBtnClicked( Button* )
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *song = pEngine->getSong();
+	song->set_loop_enabled( ! song->is_loop_enabled() );
+	song->__is_modified = true;
+
+	if ( song->is_loop_enabled() ) {
+		HydrogenApp::get_instance()->setStatusBarMessage(trUtf8("Loop song = On"), 5000);
+	}
+	else {
+		HydrogenApp::get_instance()->setStatusBarMessage(trUtf8("Loop song = Off"), 5000);
+	}
+}
+
+void PlayerControl::metronomeButtonClicked(Button* ref)
+{
+	Preferences::get_instance()->m_bUseMetronome = ref->isPressed();
+}
+
+
+void PlayerControl::showButtonClicked( Button* pRef )
+{
+	//INFOLOG( "[showButtonClicked]" );
+	HydrogenApp *pH2App = HydrogenApp::get_instance();
+
+	if ( pRef == m_pShowMixerBtn ) {
+		bool isVisible = pH2App->getMixer()->isVisible();
+		pH2App->showMixer( !isVisible );
+	}
+	else if ( pRef == m_pShowInstrumentRackBtn ) {
+		bool isVisible = pH2App->getInstrumentRack()->isVisible();
+		pH2App->getInstrumentRack()->setHidden( isVisible );
+	}
+}
+
+
+
+void PlayerControl::showMessage( const QString& msg, int msec )
+{
+	if ( m_pScrollTimer->isActive ())
+		m_pScrollTimer->stop();
+	m_pStatusLabel->setText( msg );
+	m_pStatusTimer->start( msec );
+
+
+}
+
+
+
+void PlayerControl::showScrollMessage( const QString& msg, int msec, bool test )
+{
+
+	if ( test == false ){
+		m_pStatusLabel->setText( msg );
+		m_pScrollTimer->start( msec );	
+	}else
+	{
+		m_pScrollMessage = msg;
+		m_pStatusLabel->setText( msg );
+		m_pStatusTimer->start( msec );
+		m_pScrollTimer->start( msec );	
+		
+	}
+	
+
+}
+
+void PlayerControl::onScrollTimerEvent()
+{
+	int lwl = 25;
+	int msgLength = m_pScrollMessage.length();
+	if ( msgLength > lwl)
+		m_pScrollMessage = m_pScrollMessage.right( msgLength - 1 );
+	m_pScrollTimer->stop();
+
+	if ( msgLength > lwl){
+		showScrollMessage( m_pScrollMessage, 150, false );
+	}else
+	{
+		showMessage( m_pScrollMessage, 2000 );
+	}
+}
+
+void PlayerControl::onStatusTimerEvent()
+{
+	m_pStatusTimer->stop();
+	m_pStatusLabel->setText( "" );
+}
+
+
+
+//::::::::::::::::::::::::::::::::::::::::::::::::
+
+
+
+MetronomeWidget::MetronomeWidget(QWidget *pParent)
+ : QWidget( pParent )
+ , Object( "MetronomeWidget" )
+ , m_nValue( 0 )
+ , m_state( METRO_OFF )
+{
+//	INFOLOG( "INIT" );
+	HydrogenApp::get_instance()->addEventListener( this );
+
+	m_metro_off.load( Skin::getImagePath() + "/playerControlPanel/metronome_off.png" );
+	m_metro_on_firstbeat.load( Skin::getImagePath() + "/playerControlPanel/metronome_up.png" );
+	m_metro_on.load( Skin::getImagePath() + "/playerControlPanel/metronome_down.png" );
+
+	QTimer *timer = new QTimer(this);
+	connect( timer, SIGNAL( timeout() ), this, SLOT( updateWidget() ) );
+	timer->start(50);	// update player control at 20 fps
+}
+
+
+MetronomeWidget::~MetronomeWidget()
+{
+//	INFOLOG( "DESTROY" );
+}
+
+
+void MetronomeWidget::metronomeEvent( int nValue )
+{
+	if (nValue == 2) // 2 = set pattern position is not needed here
+		return;
+	
+	if (nValue == 1) {
+		m_state = METRO_FIRST;
+		m_nValue = 5;
+	}
+	else {
+		m_state = METRO_ON;
+		m_nValue = 5;
+	}
+	updateWidget();
+}
+
+
+void MetronomeWidget::updateWidget()
+{
+	if ( m_nValue > 0 ) {
+		m_nValue -= 1;
+		if (m_nValue == 0 ) {
+			m_nValue = 0;
+			m_state = METRO_OFF;
+		}
+		update();
+	}
+}
+
+
+void MetronomeWidget::paintEvent( QPaintEvent* ev)
+{
+	QPainter painter(this);
+	switch( m_state ) {
+		case METRO_FIRST:
+			painter.drawPixmap( ev->rect(), m_metro_on_firstbeat, ev->rect() );
+			break;
+
+		case METRO_ON:
+			painter.drawPixmap( ev->rect(), m_metro_on, ev->rect() );
+			break;
+
+		case METRO_OFF:
+			painter.drawPixmap( ev->rect(), m_metro_off, ev->rect() );
+			break;
+	}
+}
+
+
+
+
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/LayerPreview.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/LayerPreview.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/LayerPreview.cpp	(revision 1244)
@@ -0,0 +1,328 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QtGui>
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/note.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/sampler/Sampler.h>
+using namespace H2Core;
+
+#include "../Skin.h"
+#include "../HydrogenApp.h"
+#include "InstrumentEditorPanel.h"
+#include "LayerPreview.h"
+
+
+LayerPreview::LayerPreview( QWidget* pParent )
+ : QWidget( pParent )
+ , Object( "LayerPreview" )
+ , m_pInstrument( NULL )
+ , m_nSelectedLayer( 0 )
+ , m_bMouseGrab( false )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG( "INIT" );
+
+	setMouseTracking( true );
+
+//
+	int w = 276;
+	if( MAX_LAYERS > 16)
+		w = 261;
+	int h = 20 + m_nLayerHeight * MAX_LAYERS;
+	resize( w, h );
+
+	m_speakerPixmap.load( Skin::getImagePath() + "/instrumentEditor/speaker.png" );
+
+	HydrogenApp::get_instance()->addEventListener( this );
+}
+
+
+
+LayerPreview::~ LayerPreview()
+{
+	//INFOLOG( "DESTROY" );
+}
+
+
+void LayerPreview::paintEvent(QPaintEvent *ev)
+{
+
+	QPainter p( this );
+	p.fillRect( ev->rect(), QColor( 58, 62, 72 ) );
+
+	int nLayers = 0;
+	for ( int i = 0; i < MAX_LAYERS; i++ ) {
+		if ( m_pInstrument ) {
+			InstrumentLayer *pLayer = m_pInstrument->get_layer( i );
+			if ( pLayer ) {
+				nLayers++;
+			}
+		}
+	}
+
+	int nLayer = 0;
+	for ( int i = MAX_LAYERS - 1; i >= 0; i-- ) {
+		int y = 20 + m_nLayerHeight * i;
+
+		if ( m_pInstrument ) {
+			InstrumentLayer *pLayer = m_pInstrument->get_layer( i );
+
+			if ( pLayer ) {
+				int x1 = (int)( pLayer->get_start_velocity() * width() );
+				int x2 = (int)( pLayer->get_end_velocity() * width() );
+
+				int red = (int)( 128.0 / nLayers * nLayer );
+				int green = (int)( 134.0 / nLayers * nLayer );
+				int blue = (int)( 152.0 / nLayers * nLayer );
+				QColor layerColor( red, green, blue );
+
+				p.fillRect( x1, 0, x2 - x1, 19, layerColor );
+				p.setPen( QColor( 230, 230, 230 ) );
+				p.drawText( x1, 0, x2 - x1, 20, Qt::AlignCenter, QString("%1").arg( i + 1 ) );
+
+				if ( m_nSelectedLayer == i ) {
+					p.setPen( QColor( 210, 0, 0 ) );
+				}
+				p.drawRect( x1, 1, x2 - x1 - 1, 18 );	// bordino in alto
+
+				// layer view
+				p.fillRect( 0, y, width(), m_nLayerHeight, QColor( 25, 44, 65 ) );
+				p.fillRect( x1, y, x2 - x1, m_nLayerHeight, QColor( 90, 160, 233 ) );
+
+				nLayer++;
+			}
+			else {
+				// layer view
+				p.fillRect( 0, y, width(), m_nLayerHeight, QColor( 59, 73, 96 ) );
+			}
+		}
+		else {
+			// layer view
+			p.fillRect( 0, y, width(), m_nLayerHeight, QColor( 59, 73, 96 ) );
+		}
+		p.setPen( QColor( 128, 134, 152 ) );
+		p.drawRect( 0, y, width() - 1, m_nLayerHeight );
+	}
+
+	// selected layer
+	p.setPen( QColor( 210, 0, 0 ) );
+	int y = 20 + m_nLayerHeight * m_nSelectedLayer;
+	p.drawRect( 0, y, width() - 1, m_nLayerHeight );
+
+
+}
+
+
+
+void LayerPreview::selectedInstrumentChangedEvent()
+{
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	if (pSong != NULL) {
+		InstrumentList *pInstrList = pSong->get_instrument_list();
+		int nInstr = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		if ( nInstr >= (int)pInstrList->get_size() ) {
+			nInstr = -1;
+		}
+
+		if (nInstr == -1) {
+			m_pInstrument = NULL;
+		}
+		else {
+			m_pInstrument = pInstrList->get( nInstr );
+		}
+	}
+	else {
+		m_pInstrument = NULL;
+	}
+	AudioEngine::get_instance()->unlock();
+
+	// select the last valid layer
+	if ( m_pInstrument ) {
+		for (int i = MAX_LAYERS - 1; i >= 0; i-- ) {
+			if ( m_pInstrument->get_layer( i ) ) {
+				m_nSelectedLayer = i;
+				break;
+			}
+		}
+	}
+	else {
+		m_nSelectedLayer = 0;
+	}
+
+	update();
+}
+
+
+
+void LayerPreview::mouseReleaseEvent(QMouseEvent *ev)
+{
+	UNUSED( ev );
+	m_bMouseGrab = false;
+	setCursor( QCursor( Qt::ArrowCursor ) );
+}
+
+
+
+void LayerPreview::mousePressEvent(QMouseEvent *ev)
+{
+	const unsigned nPosition = 0;
+	const float fPan_L = 0.5f;
+	const float fPan_R = 0.5f;
+	const int nLength = -1;
+	const float fPitch = 0.0f;
+
+	if ( !m_pInstrument ) {
+		return;
+	}
+	if ( ev->y() < 20 ) {
+		float fVelocity = (float)ev->x() / (float)width();
+
+		Note *note = new Note( m_pInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch );
+		note->set_instrument( m_pInstrument );
+		AudioEngine::get_instance()->get_sampler()->note_on(note);
+
+		for ( int i = 0; i < MAX_LAYERS; i++ ) {
+			InstrumentLayer *pLayer = m_pInstrument->get_layer( i );
+			if ( pLayer ) {
+				if ( ( fVelocity > pLayer->get_start_velocity()) && ( fVelocity < pLayer->get_end_velocity() ) ) {
+					if ( i != m_nSelectedLayer ) {
+						m_nSelectedLayer = i;
+						update();
+						InstrumentEditorPanel::get_instance()->selectLayer( m_nSelectedLayer );
+					}
+					break;
+				}
+			}
+		}
+	}
+	else {
+		m_nSelectedLayer = ( ev->y() - 20 ) / m_nLayerHeight;
+		InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+
+		update();
+		InstrumentEditorPanel::get_instance()->selectLayer( m_nSelectedLayer );
+
+		if ( m_pInstrument->get_layer( m_nSelectedLayer ) ) {
+			Note *note = new Note( m_pInstrument , nPosition, m_pInstrument->get_layer( m_nSelectedLayer )->get_end_velocity() - 0.01, fPan_L, fPan_R, nLength, fPitch );
+			AudioEngine::get_instance()->get_sampler()->note_on(note);
+		}
+
+		if ( pLayer ) {
+			int x1 = (int)( pLayer->get_start_velocity() * width() );
+			int x2 = (int)( pLayer->get_end_velocity() * width() );
+
+			if ( ( ev->x() < x1  + 5 ) && ( ev->x() > x1 - 5 ) ){
+				setCursor( QCursor( Qt::SizeHorCursor ) );
+				m_bGrabLeft = true;
+				m_bMouseGrab = true;
+			}
+			else if ( ( ev->x() < x2 + 5 ) && ( ev->x() > x2 - 5 ) ){
+				setCursor( QCursor( Qt::SizeHorCursor ) );
+				m_bGrabLeft = false;
+				m_bMouseGrab = true;
+			}
+			else {
+				setCursor( QCursor( Qt::ArrowCursor ) );
+			}
+		}
+	}
+}
+
+
+
+void LayerPreview::mouseMoveEvent( QMouseEvent *ev )
+{
+	if ( !m_pInstrument ) {
+		return;
+	}
+
+	int x = ev->pos().x();
+	int y = ev->pos().y();
+
+	float fVel = (float)x / (float)width();
+	if (fVel < 0 ) {
+		fVel = 0;
+	}
+	else  if (fVel > 1) {
+		fVel = 1;
+	}
+
+	if ( y < 20 ) {
+		setCursor( QCursor( m_speakerPixmap ) );
+		return;
+	}
+	if ( m_bMouseGrab ) {
+		InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+		if ( pLayer ) {
+			if ( m_bMouseGrab ) {
+				if ( m_bGrabLeft ) {
+					if ( fVel < pLayer->get_end_velocity()) {
+						pLayer->set_start_velocity(fVel);
+					}
+				}
+				else {
+					if ( fVel > pLayer->get_start_velocity()) {
+						pLayer->set_end_velocity( fVel );
+					}
+				}
+				update();
+			}
+		}
+	}
+	else {
+		m_nSelectedLayer = ( ev->y() - 20 ) / m_nLayerHeight;
+		if ( m_nSelectedLayer < MAX_LAYERS ) {
+			InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+			if ( pLayer ) {
+				int x1 = (int)( pLayer->get_start_velocity() * width() );
+				int x2 = (int)( pLayer->get_end_velocity() * width() );
+
+				if ( ( x < x1  + 5 ) && ( x > x1 - 5 ) ){
+					setCursor( QCursor( Qt::SizeHorCursor ) );
+				}
+				else if ( ( x < x2 + 5 ) && ( x > x2 - 5 ) ){
+					setCursor( QCursor( Qt::SizeHorCursor ) );
+				}
+				else {
+					setCursor( QCursor( Qt::ArrowCursor ) );
+				}
+			}
+			else {
+				setCursor( QCursor( Qt::ArrowCursor ) );
+			}
+		}
+	}
+}
+
+
+
+void LayerPreview::updateAll()
+{
+	update();
+}
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditor.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditor.cpp	(revision 1565)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditor.cpp	(revision 1565)
@@ -0,0 +1,915 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QtGui>
+
+#include <math.h>
+#include <assert.h>
+
+#include <hydrogen/Song.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/globals.h>
+#include <hydrogen/adsr.h>
+#include <hydrogen/sample.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/event_queue.h>
+using namespace H2Core;
+
+#include "../HydrogenApp.h"
+#include "../Skin.h"
+#include "../widgets/Rotary.h"
+#include "../widgets/ClickableLabel.h"
+#include "../widgets/Button.h"
+#include "../widgets/LCD.h"
+#include "../widgets/Fader.h"
+#include "InstrumentEditor.h"
+#include "WaveDisplay.h"
+#include "LayerPreview.h"
+#include "AudioFileBrowser/AudioFileBrowser.h"
+
+InstrumentEditor::InstrumentEditor( QWidget* pParent )
+ : QWidget( pParent )
+ , Object( "InstrumentEditor" )
+ , m_pInstrument( NULL )
+ , m_nSelectedLayer( 0 )
+{
+	setFixedWidth( 290 );
+
+// Instrument properties top
+	m_pInstrumentPropTop = new PixmapWidget( this );
+	m_pInstrumentPropTop->setPixmap( "/instrumentEditor/instrumentTab_top.png" );
+
+	m_pShowInstrumentBtn = new ToggleButton(
+			m_pInstrumentPropTop,
+			"/skin_btn_on.png",
+			"/skin_btn_off.png",
+			"/skin_btn_over.png",
+			QSize( 100, 17 ),
+			true
+	);
+	m_pShowInstrumentBtn->setText(trUtf8("General"));
+	m_pShowInstrumentBtn->setToolTip( trUtf8( "Show instrument properties" ) );
+	connect( m_pShowInstrumentBtn, SIGNAL( clicked(Button*) ), this, SLOT( buttonClicked(Button*) ) );
+	m_pShowInstrumentBtn->move( 40, 7 );
+	m_pShowInstrumentBtn->setPressed( true );
+
+
+	m_pShowLayersBtn = new ToggleButton(
+			m_pInstrumentPropTop,
+			"/skin_btn_on.png",
+			"/skin_btn_off.png",
+			"/skin_btn_over.png",
+			QSize( 100, 17 ),
+			true
+	);
+	m_pShowLayersBtn->setText( trUtf8("Layers") );
+	m_pShowLayersBtn->setToolTip( trUtf8( "Show layers properties" ) );
+	connect( m_pShowLayersBtn, SIGNAL( clicked(Button*) ), this, SLOT( buttonClicked(Button*) ) );
+	m_pShowLayersBtn->move( 144, 7 );
+
+
+// Instrument properties
+	m_pInstrumentProp = new PixmapWidget( this );
+	m_pInstrumentProp->move(0, 31);
+	m_pInstrumentProp->setPixmap( "/instrumentEditor/instrumentTab.png" );
+
+	m_pNameLbl = new ClickableLabel( m_pInstrumentProp );
+	m_pNameLbl->setGeometry( 8, 5, 275, 28 );
+	
+	/////////////
+	//Midi Out
+	
+	m_pMidiOutChannelLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 );
+	m_pMidiOutChannelLCD->move( 67, 243 );
+
+	m_pAddMidiOutChannelBtn = new Button(
+			m_pInstrumentProp,
+			"/lcd/LCDSpinBox_up_on.png",
+			"/lcd/LCDSpinBox_up_off.png",
+			"/lcd/LCDSpinBox_up_over.png",
+			QSize( 16, 8 )
+	);
+
+	m_pAddMidiOutChannelBtn->move( 109, 243 );
+	connect( m_pAddMidiOutChannelBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutChannelBtnClicked(Button*) ) );
+
+
+	m_pDelMidiOutChannelBtn = new Button(
+			m_pInstrumentProp,
+			"/lcd/LCDSpinBox_down_on.png",
+			"/lcd/LCDSpinBox_down_off.png",
+			"/lcd/LCDSpinBox_down_over.png",
+			QSize(16,8)
+	);
+	m_pDelMidiOutChannelBtn->move( 109, 251 );
+	connect( m_pDelMidiOutChannelBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutChannelBtnClicked(Button*) ) );
+	
+	///
+	m_pMidiOutNoteLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 );
+	m_pMidiOutNoteLCD->move( 160, 243 );
+
+	m_pAddMidiOutNoteBtn = new Button(
+			m_pInstrumentProp,
+			"/lcd/LCDSpinBox_up_on.png",
+			"/lcd/LCDSpinBox_up_off.png",
+			"/lcd/LCDSpinBox_up_over.png",
+			QSize( 16, 8 )
+	);
+
+	m_pAddMidiOutNoteBtn->move( 202, 243 );
+	connect( m_pAddMidiOutNoteBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutNoteBtnClicked(Button*) ) );
+
+
+	m_pDelMidiOutNoteBtn = new Button(
+			m_pInstrumentProp,
+			"/lcd/LCDSpinBox_down_on.png",
+			"/lcd/LCDSpinBox_down_off.png",
+			"/lcd/LCDSpinBox_down_over.png",
+			QSize(16,8)
+	);
+	m_pDelMidiOutNoteBtn->move( 202, 251 );
+	connect( m_pDelMidiOutNoteBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutNoteBtnClicked(Button*) ) );
+	
+	/////////////
+
+	QFont boldFont;
+	boldFont.setBold(true);
+	m_pNameLbl->setFont( boldFont );
+	connect( m_pNameLbl, SIGNAL( labelClicked(ClickableLabel*) ), this, SLOT( labelClicked(ClickableLabel*) ) );
+
+	m_pRandomPitchRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Random pitch factor" ), false, true );
+	m_pRandomPitchRotary->move( 117, 192 );
+	connect( m_pRandomPitchRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	// Filter
+	m_pFilterBypassBtn = new ToggleButton(
+			m_pInstrumentProp,
+			"/instrumentEditor/bypass_on.png",
+			"/instrumentEditor/bypass_off.png",
+			"/instrumentEditor/bypass_over.png",
+			QSize( 30, 13 )
+	);
+	connect( m_pFilterBypassBtn, SIGNAL( clicked(Button*) ), this, SLOT( filterActiveBtnClicked(Button*) ) );
+
+	m_pCutoffRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Filter Cutoff" ), false, true );
+	connect( m_pCutoffRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pResonanceRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Filter resonance" ), false, true );
+	connect( m_pResonanceRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pFilterBypassBtn->move( 70, 152 );
+	m_pCutoffRotary->move( 117, 146 );
+	m_pResonanceRotary->move( 170, 146 );
+	//~ Filter
+
+	// ADSR
+	m_pAttackRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Attack" ), false, true );
+	m_pDecayRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Decay" ), false, true );
+	m_pSustainRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Sustain" ), false, true );
+	m_pReleaseRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Release" ), false, true );
+	connect( m_pAttackRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+	connect( m_pDecayRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+	connect( m_pSustainRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+	connect( m_pReleaseRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+	m_pAttackRotary->move( 53, 52 );
+	m_pDecayRotary->move( 105, 52 );
+	m_pSustainRotary->move( 157, 52 );
+	m_pReleaseRotary->move( 209, 52 );
+	//~ ADSR
+
+	// instrument gain
+	m_pInstrumentGainLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 );
+	m_pInstrumentGain = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Instrument gain" ), false, false );
+	connect( m_pInstrumentGain, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+	m_pInstrumentGainLCD->move( 67, 105 );
+	m_pInstrumentGain->move( 117, 100 );
+
+
+	m_pMuteGroupLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 );
+	m_pMuteGroupLCD->move( 160, 105 );
+
+	m_pAddMuteGroupBtn = new Button(
+			m_pInstrumentProp,
+			"/lcd/LCDSpinBox_up_on.png",
+			"/lcd/LCDSpinBox_up_off.png",
+			"/lcd/LCDSpinBox_up_over.png",
+			QSize( 16, 8 )
+	);
+
+	m_pAddMuteGroupBtn->move( 202, 104 );
+	connect( m_pAddMuteGroupBtn, SIGNAL( clicked(Button*) ), this, SLOT( muteGroupBtnClicked(Button*) ) );
+
+
+	m_pDelMuteGroupBtn = new Button(
+			m_pInstrumentProp,
+			"/lcd/LCDSpinBox_down_on.png",
+			"/lcd/LCDSpinBox_down_off.png",
+			"/lcd/LCDSpinBox_down_over.png",
+			QSize(16,8)
+	);
+	m_pDelMuteGroupBtn->move( 202, 113 );
+	connect( m_pDelMuteGroupBtn, SIGNAL( clicked(Button*) ), this, SLOT( muteGroupBtnClicked(Button*) ) );
+
+	m_pIsStopNoteCheckBox = new QCheckBox ( QString( "Auto-Stop-Note" ), m_pInstrumentProp );
+	m_pIsStopNoteCheckBox->move( 15, 300 );
+	m_pIsStopNoteCheckBox->setToolTip( trUtf8( "Stop the current playing instrument-note before trigger the next note sample." ) );
+	connect( m_pIsStopNoteCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( onIsStopNoteCheckBoxClicked( bool ) ) );
+
+//~ Instrument properties
+
+
+
+
+
+// LAYER properties
+	m_pLayerProp = new PixmapWidget( this );
+	m_pLayerProp->move( 0, 31 );
+	m_pLayerProp->hide();
+	m_pLayerProp->setPixmap( "/instrumentEditor/layerTabnew.png" );
+
+
+
+	// Layer preview
+	m_pLayerPreview = new LayerPreview( NULL );
+ 
+	m_pLayerScrollArea = new QScrollArea( m_pLayerProp);
+	m_pLayerScrollArea->setFrameShape( QFrame::NoFrame );
+	m_pLayerScrollArea->move( 6, 4 );
+	m_pLayerScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	if ( MAX_LAYERS > 16)
+		m_pLayerScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
+	m_pLayerScrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pLayerScrollArea->setMaximumHeight( 182 );
+	m_pLayerScrollArea->setWidget( m_pLayerPreview  );
+
+
+	// Waveform display
+	m_pWaveDisplay = new WaveDisplay( m_pLayerProp );
+	m_pWaveDisplay->updateDisplay( NULL );
+	m_pWaveDisplay->move( 5, 201 );
+
+	m_pLoadLayerBtn = new Button(
+			m_pLayerProp,
+			"/instrumentEditor/loadLayer_on.png",
+			"/instrumentEditor/loadLayer_off.png",
+			"/instrumentEditor/loadLayer_over.png",
+			QSize( 90, 13 )
+	);
+
+	m_pRemoveLayerBtn = new Button(
+			m_pLayerProp,
+			"/instrumentEditor/deleteLayer_on.png",
+			"/instrumentEditor/deleteLayer_off.png",
+			"/instrumentEditor/deleteLayer_over.png",
+			QSize( 90, 13 )
+	);
+
+	m_pSamleEditorBtn = new Button(
+			m_pLayerProp,
+			"/instrumentEditor/editLayer_on.png",
+			"/instrumentEditor/editLayer_off.png",
+			"/instrumentEditor/editLayer_over.png",
+			QSize( 90, 13 )
+	);
+	m_pLoadLayerBtn->move( 48, 267 );
+	m_pRemoveLayerBtn->move( 145, 267 );
+
+
+
+	m_pLoadLayerBtn->move( 6, 266 );
+	m_pRemoveLayerBtn->move( 99, 266 );
+	m_pSamleEditorBtn->move( 191, 266 );
+
+	connect( m_pLoadLayerBtn, SIGNAL( clicked(Button*) ), this, SLOT( buttonClicked(Button*) ) );
+	connect( m_pRemoveLayerBtn, SIGNAL( clicked(Button*) ), this, SLOT( buttonClicked(Button*) ) );
+	connect( m_pSamleEditorBtn, SIGNAL( clicked(Button*) ), this, SLOT( buttonClicked(Button*) ) );
+	// Layer gain
+	m_pLayerGainLCD = new LCDDisplay( m_pLayerProp, LCDDigit::SMALL_BLUE, 4 );
+	m_pLayerGainRotary = new Rotary( m_pLayerProp,  Rotary::TYPE_NORMAL, trUtf8( "Layer gain" ), false, false );
+	connect( m_pLayerGainRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pLayerPitchCoarseLCD = new LCDDisplay( m_pLayerProp, LCDDigit::SMALL_BLUE, 4 );
+	m_pLayerPitchFineLCD = new LCDDisplay( m_pLayerProp, LCDDigit::SMALL_BLUE, 4 );
+
+	m_pLayerPitchCoarseRotary = new Rotary( m_pLayerProp, Rotary::TYPE_CENTER, trUtf8( "Layer pitch (Coarse)" ), true, false );
+	m_pLayerPitchCoarseRotary->setMin( -24.0 );
+	m_pLayerPitchCoarseRotary->setMax( 24.0 );
+	connect( m_pLayerPitchCoarseRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pLayerPitchFineRotary = new Rotary( m_pLayerProp, Rotary::TYPE_CENTER, trUtf8( "Layer pitch (Fine)" ), false, false );
+	m_pLayerPitchFineRotary->setMin( -50.0 );
+	m_pLayerPitchFineRotary->setMax( 50.0 );
+	connect( m_pLayerPitchFineRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) );
+
+	m_pLayerGainLCD->move( 54, 301 + 3 );
+	m_pLayerGainRotary->move( 102, 301 );
+
+	m_pLayerPitchCoarseLCD->move( 54, 360 + 3 );
+	m_pLayerPitchCoarseRotary->move( 102, 360 );
+
+	m_pLayerPitchFineLCD->move(  151, 360 + 3 );
+	m_pLayerPitchFineRotary->move( 199, 360 );
+//~ Layer properties
+
+
+
+
+
+
+
+
+	selectLayer( m_nSelectedLayer );
+
+	HydrogenApp::get_instance()->addEventListener(this);
+
+	selectedInstrumentChangedEvent(); 	// force an update
+}
+
+
+
+InstrumentEditor::~InstrumentEditor()
+{
+	//INFOLOG( "DESTROY" );
+}
+
+
+
+void InstrumentEditor::selectedInstrumentChangedEvent()
+{
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	if (pSong != NULL) {
+		InstrumentList *pInstrList = pSong->get_instrument_list();
+		int nInstr = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		if ( nInstr >= (int)pInstrList->get_size() ) {
+			nInstr = -1;
+		}
+
+		if (nInstr == -1) {
+			m_pInstrument = NULL;
+		}
+		else {
+			m_pInstrument = pInstrList->get( nInstr );
+			//INFOLOG( "new instr: " + m_pInstrument->m_sName );
+		}
+	}
+	else {
+		m_pInstrument = NULL;
+	}
+	AudioEngine::get_instance()->unlock();
+
+	// update layer list
+	if (m_pInstrument) {
+		m_pNameLbl->setText( m_pInstrument->get_name() );
+
+		// ADSR
+		m_pAttackRotary->setValue( sqrtf(m_pInstrument->get_adsr()->__attack / 100000.0) );
+		m_pDecayRotary->setValue( sqrtf(m_pInstrument->get_adsr()->__decay / 100000.0) );
+		m_pSustainRotary->setValue( m_pInstrument->get_adsr()->__sustain );
+		float fTmp = m_pInstrument->get_adsr()->__release - 256.0;
+		if( fTmp < 0.0 ) {
+			fTmp = 0.0;
+		}
+		m_pReleaseRotary->setValue( sqrtf(fTmp / 100000.0) );
+		//~ ADSR
+
+		// filter
+		m_pFilterBypassBtn->setPressed( !m_pInstrument->is_filter_active());
+		m_pCutoffRotary->setValue( m_pInstrument->get_filter_cutoff());
+		m_pResonanceRotary->setValue( m_pInstrument->get_filter_resonance());
+		//~ filter
+
+		// random pitch
+		m_pRandomPitchRotary->setValue( m_pInstrument->get_random_pitch_factor());
+
+		//Stop Note
+		m_pIsStopNoteCheckBox->setChecked( m_pInstrument->is_stop_notes() );
+
+		// instr gain
+		char tmp[20];
+		sprintf( tmp, "%#.2f", m_pInstrument->get_gain());
+		m_pInstrumentGainLCD->setText( tmp );
+		m_pInstrumentGain->setValue( m_pInstrument->get_gain()/ 5.0 );
+
+		// instr mute group
+		QString sMuteGroup = QString("%1").arg( m_pInstrument->get_mute_group() );
+		if (m_pInstrument->get_mute_group() == -1 ) {
+			sMuteGroup = "Off";
+		}
+                m_pMuteGroupLCD->setText( sMuteGroup );		
+		
+		// midi out
+		QString sMidiOutChannel = QString("%1").arg( m_pInstrument->get_midi_out_channel()+1);
+		if (m_pInstrument->get_midi_out_channel() == -1 ) {
+			sMidiOutChannel = "Off";
+		}
+		m_pMidiOutChannelLCD->setText( sMidiOutChannel );
+		
+		//Convert note id into notation
+		{
+			int note = m_pInstrument->get_midi_out_note();
+			int octave = (note / 12) - 2;
+			const char *noteStrs[12] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
+			QString sMidiOutNote = QString(noteStrs[note % 12]) + QString::number(octave);
+			m_pMidiOutNoteLCD->setText( sMidiOutNote );			
+		}
+
+		// select the last valid layer
+		for (int i = MAX_LAYERS - 1; i >= 0; i-- ) {
+			if ( m_pInstrument->get_layer( i ) ) {
+				m_nSelectedLayer = i;
+				break;
+			}
+		}
+		m_pWaveDisplay->updateDisplay( m_pInstrument->get_layer( m_nSelectedLayer ) );
+	}
+	else {
+		m_pNameLbl->setText( QString( "NULL Instrument..." ) );
+		m_pWaveDisplay->updateDisplay( NULL );
+		m_nSelectedLayer = 0;
+	}
+	selectLayer( m_nSelectedLayer );
+
+}
+
+
+
+void InstrumentEditor::rotaryChanged(Rotary *ref)
+{
+	float fVal = ref->getValue();
+
+	if ( m_pInstrument ) {
+		if ( ref == m_pRandomPitchRotary ){
+			m_pInstrument->set_random_pitch_factor( fVal );
+		}
+		else if ( ref == m_pCutoffRotary ) {
+			m_pInstrument->set_filter_cutoff( fVal );
+		}
+		else if ( ref == m_pResonanceRotary ) {
+			if ( fVal > 0.95f ) {
+				fVal = 0.95f;
+			}
+			m_pInstrument->set_filter_resonance( fVal );
+		}
+		else if ( ref == m_pAttackRotary ) {
+			m_pInstrument->get_adsr()->__attack = fVal * fVal * 100000;
+		}
+		else if ( ref == m_pDecayRotary ) {
+			m_pInstrument->get_adsr()->__decay = fVal * fVal * 100000;
+		}
+		else if ( ref == m_pSustainRotary ) {
+			m_pInstrument->get_adsr()->__sustain = fVal;
+		}
+		else if ( ref == m_pReleaseRotary ) {
+			m_pInstrument->get_adsr()->__release = 256.0 + fVal * fVal * 100000;
+		}
+		else if ( ref == m_pLayerGainRotary ) {
+			fVal = fVal * 5.0;
+			char tmp[20];
+			sprintf( tmp, "%#.2f", fVal );
+			m_pLayerGainLCD->setText( tmp );
+
+			H2Core::InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+			if ( pLayer ) {
+				pLayer->set_gain( fVal );
+				m_pWaveDisplay->updateDisplay( pLayer );
+			}
+		}
+		else if ( ref == m_pLayerPitchCoarseRotary ) {
+			//fVal = fVal * 24.0 - 12.0;
+			m_pLayerPitchCoarseLCD->setText( QString( "%1" ).arg( (int)fVal ) );
+			H2Core::InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+			if ( pLayer ) {
+				int nCoarse = (int)m_pLayerPitchCoarseRotary->getValue();
+				float fFine = m_pLayerPitchFineRotary->getValue() / 100.0;
+				pLayer->set_pitch( nCoarse + fFine );
+				INFOLOG( QString("pitch: %1").arg( pLayer->get_pitch() ) );
+			}
+		}
+		else if ( ref == m_pLayerPitchFineRotary ) {
+			m_pLayerPitchFineLCD->setText( QString( "%1" ).arg( fVal ) );
+			H2Core::InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+			if ( pLayer ) {
+				int nCoarse = (int)m_pLayerPitchCoarseRotary->getValue();
+				float fFine = m_pLayerPitchFineRotary->getValue() / 100.0;
+				pLayer->set_pitch( nCoarse + fFine );
+				INFOLOG( QString("pitch: %1").arg( pLayer->get_pitch()) );
+			}
+
+		}
+		else if ( ref == m_pInstrumentGain ) {
+			fVal = fVal * 5.0;
+			char tmp[20];
+			sprintf( tmp, "%#.2f", fVal );
+			m_pInstrumentGainLCD->setText( tmp );
+
+			m_pInstrument->set_gain( fVal );
+		}
+		else {
+			ERRORLOG( "[rotaryChanged] unhandled rotary" );
+		}
+	}
+}
+
+
+void InstrumentEditor::filterActiveBtnClicked(Button *ref)
+{
+	if ( m_pInstrument ) {
+		m_pInstrument->set_filter_active( !ref->isPressed() );
+	}
+}
+
+
+void InstrumentEditor::buttonClicked( Button* pButton )
+{
+
+	if ( pButton == m_pShowInstrumentBtn ) {
+		m_pShowInstrumentBtn->setPressed( true );
+		m_pShowLayersBtn->setPressed( false );
+		m_pInstrumentProp->show();
+		m_pLayerProp->hide();
+
+		m_pShowLayersBtn->show();
+		m_pShowInstrumentBtn->show();
+	}
+	else if ( pButton == m_pShowLayersBtn ) {
+		m_pShowLayersBtn->setPressed( true );
+		m_pShowInstrumentBtn->setPressed( false );
+		m_pLayerProp->show();
+		m_pInstrumentProp->hide();
+
+		m_pShowLayersBtn->show();
+		m_pShowInstrumentBtn->show();
+	}
+	else if ( pButton == m_pLoadLayerBtn ) {
+		loadLayer();
+	}
+	else if ( pButton == m_pRemoveLayerBtn ) {
+		//Hydrogen *pEngine = Hydrogen::get_instance();
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+		if ( m_pInstrument ) {
+			H2Core::InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+			if ( pLayer ) {
+				m_pInstrument->set_layer( NULL, m_nSelectedLayer );
+				delete pLayer;
+			}
+		}
+		AudioEngine::get_instance()->unlock();
+		selectedInstrumentChangedEvent();    // update all
+		m_pLayerPreview->updateAll();
+	}
+	else if ( pButton == m_pSamleEditorBtn ){
+		if ( m_pInstrument ) {
+			H2Core::InstrumentLayer *pLayer = m_pInstrument->get_layer( m_nSelectedLayer );
+			if ( pLayer ) {
+				Sample* pSample = pLayer->get_sample();
+				QString name = pSample->get_filename();
+				HydrogenApp::get_instance()->showSampleEditor( name, m_nSelectedLayer );
+			}
+		}
+		
+	}
+	else {
+		ERRORLOG( "[buttonClicked] unhandled button" );
+	}
+}
+
+
+
+void InstrumentEditor::loadLayer()
+{
+	static QString lastUsedDir = QDir::homePath();
+
+	Hydrogen *engine = Hydrogen::get_instance();
+
+	AudioFileBrowser *fb = new AudioFileBrowser( NULL );
+	QStringList filename;
+	filename << "false" << "false" << "";
+
+	if (fb->exec() == QDialog::Accepted) {
+		filename = fb->selectedFile();
+	}
+
+	delete fb;
+
+	if ( filename[2].isEmpty() ) return;
+
+	bool fnc = false;	
+	if ( filename[0] ==  "true" ){
+		fnc = true;
+	}
+
+	//use auto velocity if we want to work with multiple filenames
+	if ( filename.size() > 3) filename[1] = "true";
+
+	int selectedLayer =  m_nSelectedLayer;
+	int firstselection = selectedLayer;
+	
+	
+
+	if (filename.size() > 2) {
+		
+		for(int i=2;i < filename.size();++i) 
+		{
+			selectedLayer = m_nSelectedLayer + i - 2;
+			if( ( i-2 >= MAX_LAYERS ) || ( selectedLayer + 1  > MAX_LAYERS ) ) break;
+
+			Sample *newSample = Sample::load( filename[i] );
+	
+			H2Core::Instrument *pInstr = NULL;
+	
+			AudioEngine::get_instance()->lock( RIGHT_HERE );
+			Song *song = engine->getSong();
+			InstrumentList *instrList = song->get_instrument_list();
+			pInstr = instrList->get( engine->getSelectedInstrumentNumber() );
+	
+			/* 
+				if we're using multiple layers, we start inserting the first layer 
+				at m_nSelectedLayer and the next layer at m_nSelectedLayer+1
+		 	*/
+			
+			H2Core::InstrumentLayer *pLayer = pInstr->get_layer( selectedLayer );
+			if (pLayer != NULL) {
+				// delete old sample
+				Sample *oldSample = pLayer->get_sample();
+				delete oldSample;
+	
+				// insert new sample from newInstrument
+				pLayer->set_sample( newSample );
+			}
+			else {
+				pLayer = new H2Core::InstrumentLayer(newSample);
+				pInstr->set_layer( pLayer, selectedLayer );
+			}
+	
+			if ( fnc ){
+				QString newfilename = filename[i].section( '/', -1 );
+				newfilename.replace( "." + newfilename.section( '.', -1 ), "");
+				m_pInstrument->set_name( newfilename );
+			}
+	
+			//set automatic velocity
+			if ( filename[1] ==  "true" ){
+				setAutoVelocity();
+			}
+	
+			pInstr->set_drumkit_name( "" );   // external sample, no drumkit info
+	
+			AudioEngine::get_instance()->unlock();
+
+		}
+	}
+
+	selectedInstrumentChangedEvent();    // update all
+	selectLayer( firstselection );
+	m_pLayerPreview->updateAll();
+}
+
+
+void InstrumentEditor::setAutoVelocity()
+{
+	int layerinuse[ MAX_LAYERS ] = {0};
+	int layers = 0;
+	for ( int i = 0; i < MAX_LAYERS ; i++ ) {
+		InstrumentLayer *pLayers = m_pInstrument->get_layer( i );
+		if ( pLayers ) {
+			layers++;
+			layerinuse[i] = i;
+		}
+	}
+
+	float velocityrange = 1.0 / layers;
+
+	for ( int i = 0; i < MAX_LAYERS ; i++ ) {
+		if ( layerinuse[i] == i ){
+			layers--;
+			InstrumentLayer *pLayer = m_pInstrument->get_layer( i );
+			if ( pLayer ) {
+				pLayer->set_start_velocity( layers * velocityrange);
+				pLayer->set_end_velocity( layers * velocityrange + velocityrange );
+			}
+		}
+	}
+}
+
+
+void InstrumentEditor::labelClicked( ClickableLabel* pRef )
+{
+	UNUSED( pRef );
+
+	if (m_pInstrument) {
+		QString sOldName = m_pInstrument->get_name();
+		bool bIsOkPressed;
+		QString sNewName = QInputDialog::getText( this, "Hydrogen", trUtf8( "New instrument name" ), QLineEdit::Normal, sOldName, &bIsOkPressed );
+		if ( bIsOkPressed  ) {
+			m_pInstrument->set_name( sNewName );
+			selectedInstrumentChangedEvent();
+
+			// this will force an update...
+			EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
+
+		}
+		else {
+			// user entered nothing or pressed Cancel
+		}
+	}
+}
+
+
+void InstrumentEditor::selectLayer( int nLayer )
+{
+	if (!m_pInstrument) {
+		return;
+	}
+	m_nSelectedLayer = nLayer;
+
+	H2Core::InstrumentLayer *pLayer = m_pInstrument->get_layer( nLayer );
+	m_pWaveDisplay->updateDisplay( pLayer );
+	if (pLayer) {
+		char tmp[20];
+
+		// Layer GAIN
+		m_pLayerGainRotary->setValue( pLayer->get_gain() / 5.0 );
+		sprintf( tmp, "%#.2f", pLayer->get_gain() );
+		m_pLayerGainLCD->setText( tmp );
+
+		// Layer PITCH
+		//int nCoarsePitch = pLayer->m_fPitch / 24 + 0.5;
+		int nCoarsePitch = (int) ::round(pLayer->get_pitch());
+		float fFinePitch = pLayer->get_pitch() - nCoarsePitch;
+		//INFOLOG( "fine pitch: " + to_string( fFinePitch ) );
+		m_pLayerPitchCoarseRotary->setValue( nCoarsePitch );
+		m_pLayerPitchFineRotary->setValue( fFinePitch * 100 );
+
+		m_pLayerPitchCoarseLCD->setText( QString( "%1" ).arg( nCoarsePitch ) );
+		m_pLayerPitchFineLCD->setText( QString( "%1" ).arg( fFinePitch * 100 ) );
+	}
+	else {
+		// Layer GAIN
+		m_pLayerGainRotary->setValue( 1.0 );
+		m_pLayerGainLCD->setText( "" );
+
+		// Layer PITCH
+		m_pLayerPitchCoarseRotary->setValue( 0.0 );
+		m_pLayerPitchFineRotary->setValue( 0.0 );
+
+		m_pLayerPitchCoarseLCD->setText( "" );
+		m_pLayerPitchFineLCD->setText( "" );
+	}
+}
+
+
+
+void InstrumentEditor::muteGroupBtnClicked(Button *pRef)
+{
+	assert( m_pInstrument );
+
+	if (pRef == m_pAddMuteGroupBtn ) {
+		m_pInstrument->set_mute_group( m_pInstrument->get_mute_group() + 1);
+	}
+	else if (pRef == m_pDelMuteGroupBtn ) {
+		m_pInstrument->set_mute_group( m_pInstrument->get_mute_group() - 1);
+	}
+
+	selectedInstrumentChangedEvent();	// force an update
+}
+
+void InstrumentEditor::onIsStopNoteCheckBoxClicked( bool on )
+{
+	m_pInstrument->set_stop_note( on );
+}
+
+void InstrumentEditor::midiOutChannelBtnClicked(Button *pRef)
+{
+	assert( m_pInstrument );
+
+	if (pRef == m_pAddMidiOutChannelBtn ) {
+		m_pInstrument->set_midi_out_channel( m_pInstrument->get_midi_out_channel() + 1);
+	}
+	else if (pRef == m_pDelMidiOutChannelBtn ) {
+		m_pInstrument->set_midi_out_channel( m_pInstrument->get_midi_out_channel() - 1);
+	}
+
+	selectedInstrumentChangedEvent();	// force an update
+}
+
+void InstrumentEditor::midiOutNoteBtnClicked(Button *pRef)
+{
+	assert( m_pInstrument );
+
+	if (pRef == m_pAddMidiOutNoteBtn ) {
+		m_pInstrument->set_midi_out_note( m_pInstrument->get_midi_out_note() + 1);
+	}
+	else if (pRef == m_pDelMidiOutNoteBtn ) {
+		m_pInstrument->set_midi_out_note( m_pInstrument->get_midi_out_note() - 1);
+	}
+
+	selectedInstrumentChangedEvent();	// force an update
+}
+
+
+ void InstrumentEditor::rubberbandbpmchangeEvent()
+{
+	if( !Preferences::get_instance()->m_useTheRubberbandBpmChangeEvent /*&& Preferences::get_instance()->__usetimeline */){
+		//we return also if time-line is activated. this wont work.
+//		INFOLOG( "Tempo change: Recomputing rubberband samples is disabled" );
+		return;
+	}
+//	INFOLOG( "Tempo change: Recomputing rubberband samples." );
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *song = pEngine->getSong();
+	assert(song);
+	if(song){
+		InstrumentList *songInstrList = song->get_instrument_list();
+		assert(songInstrList);
+		for ( unsigned nInstr = 0; nInstr < songInstrList->get_size(); ++nInstr ) {
+			Instrument *pInstr = songInstrList->get( nInstr );
+			assert( pInstr );
+			if ( pInstr ){
+				for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
+					InstrumentLayer *pLayer = pInstr->get_layer( nLayer );
+					if ( pLayer ) {
+						Sample *pSample = pLayer->get_sample();
+						if ( pSample ) {
+							if(pSample->get_use_rubber()){
+								//INFOLOG( QString("Instrument %1 Layer %2" ).arg(nInstr).arg(nLayer));
+	
+								QString filename = pSample->get_filename();
+								unsigned startframe = pSample->get_start_frame();
+								unsigned loopframe = pSample->get_loop_frame();
+								unsigned endframe = pSample->get_end_frame();
+								int loops = pSample->get_repeats();
+								QString	mode = pSample->get_sample_mode();
+								bool userubber = pSample->get_use_rubber();
+								float rd = pSample->get_rubber_divider();
+								int csettings = pSample->get_rubber_C_settings();
+								float rpitch = pSample->get_rubber_pitch();
+
+								Hydrogen::HVeloVector velovector;
+								pEngine->m_volumen.clear();
+								for( int i = 0 ; i < static_cast<int>(pSample->__velo_pan.m_Samplevolumen.size()); i++){
+									velovector.m_hxframe = pSample->__velo_pan.m_Samplevolumen[i].m_SampleVeloframe;
+									velovector.m_hyvalue = pSample->__velo_pan.m_Samplevolumen[i].m_SampleVelovalue;
+									pEngine->m_volumen.push_back( velovector );	
+								}
+
+								Hydrogen::HPanVector panvector;
+								pEngine->m_pan.clear();
+								for( int i = 0 ; i < static_cast<int>(pSample->__velo_pan.m_SamplePan.size()); i++){
+									panvector.m_hxframe = pSample->__velo_pan.m_SamplePan[i].m_SamplePanframe;
+									panvector.m_hyvalue = pSample->__velo_pan.m_SamplePan[i].m_SamplePanvalue;
+									pEngine->m_pan.push_back( panvector );
+								}
+			
+								Sample *newSample = Sample::load_edit_wave( filename,
+													startframe,
+													loopframe,
+													endframe,
+													loops,
+													mode,
+													userubber,
+													rd,
+													csettings,
+													rpitch);
+	
+								if( !newSample  ){
+									continue;
+								}	
+								delete pSample;
+
+								// insert new sample from newInstrument
+								AudioEngine::get_instance()->lock( RIGHT_HERE );
+								pLayer->set_sample( newSample );
+								AudioEngine::get_instance()->unlock();
+	
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+}
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditorPanel.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditorPanel.cpp	(revision 1330)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditorPanel.cpp	(revision 1330)
@@ -0,0 +1,86 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QLabel>
+#include <QPixmap>
+#include <QGridLayout>
+
+
+#include "InstrumentEditorPanel.h"
+#include "../Skin.h"
+
+
+InstrumentEditorPanel* InstrumentEditorPanel::m_pInstance = NULL;
+
+InstrumentEditorPanel* InstrumentEditorPanel::get_instance()
+{
+	if ( m_pInstance == NULL  ) {
+		m_pInstance = new InstrumentEditorPanel( NULL );
+	}
+	return m_pInstance;
+}
+
+
+
+InstrumentEditorPanel::InstrumentEditorPanel( QWidget *pParent )
+ : Object( "InstrumentEditorPanel" )
+{
+	UNUSED( pParent );
+
+	INFOLOG( "INIT" );
+
+	m_pInstance = this;
+	m_pInstrumentEditor = new InstrumentEditor( 0 );
+
+	// LAYOUT
+	QGridLayout *vbox = new QGridLayout();
+	vbox->setSpacing( 0 );
+	vbox->setMargin( 0 );
+
+	vbox->addWidget( m_pInstrumentEditor, 0, 0 );
+
+	this->setLayout( vbox );
+	m_player = 0;
+}
+
+
+
+InstrumentEditorPanel::~InstrumentEditorPanel()
+{
+	INFOLOG( "DESTROY" );
+}
+
+
+void InstrumentEditorPanel::updateInstrumentEditor()
+{
+	m_pInstrumentEditor->selectedInstrumentChangedEvent();
+}
+
+void InstrumentEditorPanel::selectLayer( int nLayer )
+{
+	m_pInstrumentEditor->selectLayer( nLayer );
+	m_player = nLayer;
+}
+
+
+
+
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/LayerPreview.h
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/LayerPreview.h	(revision 162)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/LayerPreview.h	(revision 162)
@@ -0,0 +1,60 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef LAYER_PREVIEW_H
+#define LAYER_PREVIEW_H
+
+#include "config.h"
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+#include <hydrogen/instrument.h>
+#include "../EventListener.h"
+
+
+class LayerPreview : public QWidget, public Object, public EventListener
+{
+	Q_OBJECT
+
+	public:
+		LayerPreview(QWidget* pParent);
+		~LayerPreview();
+
+		void updateAll();
+
+		void paintEvent(QPaintEvent *ev);
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+		virtual void mouseMoveEvent ( QMouseEvent *ev );
+
+	private:
+		static const int m_nLayerHeight = 10;
+		QPixmap m_speakerPixmap;
+		H2Core::Instrument *m_pInstrument;
+		int m_nSelectedLayer;
+		bool m_bMouseGrab;
+		bool m_bGrabLeft;
+
+		virtual void selectedInstrumentChangedEvent();
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditor.h
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditor.h	(revision 1459)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditor.h	(revision 1459)
@@ -0,0 +1,154 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef INSTRUMENT_EDITOR_DIALOG_H
+#define INSTRUMENT_EDITOR_DIALOG_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include <hydrogen/instrument.h>
+#include <hydrogen/Object.h>
+
+#include "../EventListener.h"
+#include "../widgets/PixmapWidget.h"
+
+class Fader;
+class LCDDisplay;
+class Button;
+class ToggleButton;
+class ClickableLabel;
+class Rotary;
+class WaveDisplay;
+class LayerPreview;
+
+
+///
+/// Instrument Editor
+///
+class InstrumentEditor : public QWidget, public Object, public EventListener
+{
+	Q_OBJECT
+
+	public:
+		InstrumentEditor( QWidget* parent );
+		~InstrumentEditor();
+
+		void selectLayer( int nLayer );
+		void setFileforLayer(QString filename );
+
+		// implements EventListener interface
+		virtual void selectedInstrumentChangedEvent();
+		virtual void rubberbandbpmchangeEvent();
+		//~ implements EventListener interface
+
+	private slots:
+		void rotaryChanged(Rotary *ref);
+		void filterActiveBtnClicked(Button *ref);
+		void buttonClicked(Button*);
+		void labelClicked( ClickableLabel* pRef );
+
+		void muteGroupBtnClicked(Button *pRef);
+		void onIsStopNoteCheckBoxClicked( bool on );
+		void midiOutChannelBtnClicked(Button *pRef);
+		void midiOutNoteBtnClicked(Button *pRef);
+
+	private:
+		H2Core::Instrument *m_pInstrument;
+		int m_nSelectedLayer;
+
+		ToggleButton *m_pShowInstrumentBtn;
+		ToggleButton *m_pShowLayersBtn;
+
+		// Instrument properties
+		PixmapWidget *m_pInstrumentProp;
+		PixmapWidget *m_pInstrumentPropTop;
+		ClickableLabel *m_pNameLbl;
+
+		// ADSR
+		Rotary *m_pAttackRotary;
+		Rotary *m_pDecayRotary;
+		Rotary *m_pSustainRotary;
+		Rotary *m_pReleaseRotary;
+
+		// Random pitch
+		Rotary *m_pRandomPitchRotary;
+
+		// Low pass filter
+		ToggleButton *m_pFilterBypassBtn;
+		Rotary *m_pCutoffRotary;
+		Rotary *m_pResonanceRotary;
+
+		// Instrument gain
+		LCDDisplay *m_pInstrumentGainLCD;
+		Rotary *m_pInstrumentGain;
+
+		// Instrument mute group
+		LCDDisplay *m_pMuteGroupLCD;
+		Button *m_pAddMuteGroupBtn;
+		Button *m_pDelMuteGroupBtn;
+		
+		// Instrument midi out
+		LCDDisplay *m_pMidiOutChannelLCD;
+		Button *m_pAddMidiOutChannelBtn;
+		Button *m_pDelMidiOutChannelBtn;
+		
+		LCDDisplay *m_pMidiOutNoteLCD;
+		Button *m_pAddMidiOutNoteBtn;
+		Button *m_pDelMidiOutNoteBtn;		
+
+
+		//~ Instrument properties
+
+		// Layer properties
+		LayerPreview *m_pLayerPreview;
+		QScrollArea *m_pLayerScrollArea;
+		
+
+		PixmapWidget *m_pLayerProp;
+		Rotary *m_pLayerGainRotary;
+		LCDDisplay *m_pLayerGainLCD;
+
+		Rotary *m_pLayerPitchCoarseRotary;
+		Rotary *m_pLayerPitchFineRotary;
+
+		LCDDisplay *m_pLayerPitchCoarseLCD;
+		LCDDisplay *m_pLayerPitchFineLCD;
+
+		WaveDisplay *m_pWaveDisplay;
+
+		Button *m_pLoadLayerBtn;
+		Button *m_pRemoveLayerBtn;
+		Button *m_pSamleEditorBtn;
+		QCheckBox *m_pIsStopNoteCheckBox;
+		//~ Layer properties
+
+
+
+
+		void loadLayer();
+		void setAutoVelocity();
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditorPanel.h
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditorPanel.h	(revision 1330)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/InstrumentEditorPanel.h	(revision 1330)
@@ -0,0 +1,57 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef INSTRUMENT_EDITOR_PANEL_H
+#define INSTRUMENT_EDITOR_PANEL_H
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+#include "InstrumentEditor.h"
+
+///
+/// Container for the Instrument Editor (Singleton).
+///
+class InstrumentEditorPanel : public QWidget, private Object
+{
+	Q_OBJECT
+	public:
+		static InstrumentEditorPanel* get_instance();
+		~InstrumentEditorPanel();
+
+		void updateInstrumentEditor();
+		void selectLayer( int nLayer );
+		
+		int getselectedLayer() {
+			return m_player;
+		}
+
+	private:
+		static InstrumentEditorPanel* m_pInstance;
+		InstrumentEditor* m_pInstrumentEditor;
+
+		InstrumentEditorPanel( QWidget *pParent );
+		int m_player;
+		
+};
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/WaveDisplay.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/WaveDisplay.cpp	(revision 834)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/WaveDisplay.cpp	(revision 834)
@@ -0,0 +1,130 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "config.h"
+
+#include <hydrogen/sample.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/instrument.h>
+using namespace H2Core;
+
+#include "WaveDisplay.h"
+#include "../Skin.h"
+
+
+WaveDisplay::WaveDisplay(QWidget* pParent)
+ : QWidget( pParent )
+ , Object( "WaveDisplay" )
+ , m_sSampleName( "" )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG( "INIT" );
+	int w = 277;
+	int h = 58;
+	resize( w, h );
+
+	bool ok = m_background.load( Skin::getImagePath() + "/waveDisplay/background.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	m_pPeakData = new int[ w ];
+
+}
+
+
+
+
+WaveDisplay::~WaveDisplay()
+{
+	//INFOLOG( "DESTROY" );
+
+	delete[] m_pPeakData;
+}
+
+
+
+void WaveDisplay::paintEvent(QPaintEvent *ev)
+{
+	QPainter painter( this );
+	painter.setRenderHint( QPainter::Antialiasing );
+	painter.drawPixmap( ev->rect(), m_background, ev->rect() );
+
+	painter.setPen( QColor( 102, 150, 205 ) );
+	int VCenter = height() / 2;
+	for ( int x = 0; x < width(); x++ ) {
+		painter.drawLine( x, VCenter, x, m_pPeakData[x] + VCenter );
+		painter.drawLine( x, VCenter, x, -m_pPeakData[x] + VCenter );
+	}
+
+	QFont font;
+	font.setWeight( 63 );
+	painter.setFont( font );
+	painter.setPen( QColor( 255 , 255, 255, 200 ) );
+	painter.drawText( 0, 0, width(), 20, Qt::AlignCenter, m_sSampleName );
+}
+
+
+
+void WaveDisplay::updateDisplay( H2Core::InstrumentLayer *pLayer )
+{
+	if ( pLayer && pLayer->get_sample() ) {
+		// Extract the filename from the complete path
+		QString sName = pLayer->get_sample()->get_filename();
+		int nPos = sName.lastIndexOf( "/" );
+		m_sSampleName = sName.mid( nPos + 1, sName.length() );
+
+//		INFOLOG( "[updateDisplay] sample: " + m_sSampleName  );
+
+		int nSampleLength = pLayer->get_sample()->get_n_frames();
+		float nScaleFactor = nSampleLength / width();
+
+		float fGain = height() / 2.0 * pLayer->get_gain();
+
+		float *pSampleData = pLayer->get_sample()->get_data_l();
+
+		int nSamplePos =0;
+		int nVal;
+		for ( int i = 0; i < width(); ++i ){
+			nVal = 0;
+			for ( int j = 0; j < nScaleFactor; ++j ) {
+				if ( j < nSampleLength ) {
+					int newVal = (int)( pSampleData[ nSamplePos ] * fGain );
+					if ( newVal > nVal ) {
+						nVal = newVal;
+					}
+				}
+				++nSamplePos;
+			}
+			m_pPeakData[ i ] = nVal;
+		}
+	}
+	else {
+		m_sSampleName = "-";
+		for ( int i =0; i < width(); ++i ){
+			m_pPeakData[ i ] = 0;
+		}
+	}
+
+	update();
+}
+
Index: /branches/tabbedInterface/gui/src/InstrumentEditor/WaveDisplay.h
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentEditor/WaveDisplay.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/InstrumentEditor/WaveDisplay.h	(revision 377)
@@ -0,0 +1,53 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef WAVE_DISPLAY
+#define WAVE_DISPLAY
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+
+namespace H2Core
+{
+	class InstrumentLayer;
+}
+
+class WaveDisplay : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		WaveDisplay(QWidget* pParent);
+		~WaveDisplay();
+
+		void updateDisplay( H2Core::InstrumentLayer *pLayer );
+
+		void paintEvent(QPaintEvent *ev);
+
+	private:
+		QPixmap m_background;
+		QString m_sSampleName;
+		int *m_pPeakData;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/SplashScreen.h
===================================================================
--- /branches/tabbedInterface/gui/src/SplashScreen.h	(revision 127)
+++ /branches/tabbedInterface/gui/src/SplashScreen.h	(revision 127)
@@ -0,0 +1,59 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef SPLASH_SCREEN_H
+#define SPLASH_SCREEN_H
+
+#include <QLabel>
+#include <QSplashScreen>
+#include <QTimer>
+#include <QPixmap>
+
+#include "HydrogenApp.h"
+
+#include <hydrogen/Object.h>
+
+/**
+ * Fader and VuMeter widget
+ */
+class SplashScreen : public QSplashScreen, public Object
+{
+	Q_OBJECT
+	public:
+		SplashScreen();
+		~SplashScreen();
+
+	private slots:
+		void onCloseTimer();
+//		virtual void drawContents ( QPainter * painter );
+
+	private:
+		QPixmap *m_pBackground;
+		static const uint width = 400;
+		static const uint height = 300;
+		//QTimer m_closeTimer;
+
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/HelpBrowser.h
===================================================================
--- /branches/tabbedInterface/gui/src/HelpBrowser.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/HelpBrowser.h	(revision 377)
@@ -0,0 +1,67 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef HELPBROWSER_H
+#define HELPBROWSER_H
+
+#include "config.h"
+
+#include <iostream>
+#include <string>
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+class SimpleHTMLBrowser : public QDialog, public Object
+{
+	Q_OBJECT
+	public:
+		enum SimpleHTMLBrowserType {
+			WELCOME,
+			MANUAL
+		};
+
+		SimpleHTMLBrowser( QWidget *pParent, const QString& sDataPath, const QString& sFilename, SimpleHTMLBrowserType type );
+		~SimpleHTMLBrowser();
+
+	public slots:
+		void dontShowAnymoreBtnClicked();
+		void closeWindow();
+		void docIndex();
+
+	private:
+		SimpleHTMLBrowserType m_type;
+		QTextBrowser *m_pBrowser;
+		QPushButton *m_pDontShowAnymoreBtn;
+		QPushButton *m_pCloseWindowBtn;
+		QPushButton *m_pDocHomeBtn;
+
+		QString m_sDataPath;
+		QString m_sFilename;
+
+		virtual void showEvent ( QShowEvent *ev );
+		virtual void resizeEvent( QResizeEvent *ev );
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/SampleEditor/MainSampleWaveDisplay.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/MainSampleWaveDisplay.cpp	(revision 1448)
+++ /branches/tabbedInterface/gui/src/SampleEditor/MainSampleWaveDisplay.cpp	(revision 1448)
@@ -0,0 +1,297 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "config.h"
+
+#include <hydrogen/sample.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/instrument.h>
+#include "HydrogenApp.h"
+#include "SampleEditor.h"
+using namespace H2Core;
+
+#include "MainSampleWaveDisplay.h"
+#include "../Skin.h"
+
+
+MainSampleWaveDisplay::MainSampleWaveDisplay(QWidget* pParent)
+ : QWidget( pParent )
+ , Object( "MainSampleWaveDisplay" )
+{
+//	setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG( "INIT" );
+	int w = 624;
+	int h = 265;
+	resize( w, h );
+
+	bool ok = m_background.load( Skin::getImagePath() + "/waveDisplay/mainsamplewavedisplay.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	m_pPeakDatal = new int[ w ];
+	m_pPeakDatar = new int[ w ];
+
+	m_pStartFramePosition = 25;
+	m_pLoopFramePosition = 25;
+	m_pEndFramePosition = width() -25;
+	m_pmove = false;
+	m_plocator = -1;
+	m_pupdateposi = false;
+
+	__startsliderismoved = false;
+	__loopsliderismoved = false;
+	__endsliderismoved = false;
+}
+
+
+
+
+MainSampleWaveDisplay::~MainSampleWaveDisplay()
+{
+	//INFOLOG( "DESTROY" );
+
+	delete[] m_pPeakDatal;
+	delete[] m_pPeakDatar;
+}
+
+void MainSampleWaveDisplay::paintLocatorEvent( int pos, bool updateposi)
+{
+	m_pupdateposi = updateposi;
+	if ( !updateposi ){
+		m_plocator = -1;
+	}else
+	{
+		m_plocator = pos;
+	}
+	update();
+}
+
+void MainSampleWaveDisplay::paintEvent(QPaintEvent *ev)
+{
+	QPainter painter( this );
+	painter.setRenderHint( QPainter::HighQualityAntialiasing );
+
+	bool issmaller = false;
+
+	painter.drawPixmap( ev->rect(), m_background, ev->rect() );
+	painter.setPen( QColor( 230, 230, 230 ) );
+	int VCenterl = height() / 4;
+	int VCenterr = height() / 4 + height() / 2;
+
+	if ( width() >= m_pSampleLength  ) issmaller = true;
+
+	for ( int x = 25; x < width() -25; x++ ) {
+		if ( !issmaller || x <= m_pSampleLength){ 
+			painter.drawLine( x, -m_pPeakDatal[x -25] +VCenterl, x, -m_pPeakDatal[x -24] +VCenterl  );
+			painter.drawLine( x, -m_pPeakDatar[x -25] +VCenterr, x, -m_pPeakDatar[x -24] +VCenterr  );	
+		}else
+		{
+			painter.drawLine( x, 0 +VCenterl, x, 0 +VCenterl  );
+			painter.drawLine( x, 0 +VCenterr, x, 0 +VCenterr  );
+		}
+	
+	}
+
+
+	painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+	painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::DotLine ) );
+	painter.drawLine( 23, 4, 23, height() -4 );
+	painter.drawLine( width() -23, 4,width() -23, height() -4 );
+	painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::SolidLine ) );
+	painter.drawLine( m_plocator, 4, m_plocator, height() -4);
+	painter.drawLine( 0, VCenterl, width(),VCenterl );
+	painter.drawLine( 0, VCenterr, width(),VCenterr );
+
+	QFont font;
+	font.setWeight( 63 );
+	painter.setFont( font );
+//start frame pointer
+	painter.setPen( QColor( 32, 173, 0, 200 ) );
+	painter.drawLine( m_pStartFramePosition, 4, m_pStartFramePosition, height() -4 );	
+	painter.drawText( m_pStartFramePosition -10, 250, 10,20, Qt::AlignRight, "S" );
+//endframe pointer
+	painter.setPen( QColor( 217, 68, 0, 200 ) );
+	painter.drawLine( m_pEndFramePosition, 4, m_pEndFramePosition, height() -4 );
+	painter.drawText( m_pEndFramePosition -10, 123, 10, 20, Qt::AlignRight, "E" );
+//loopframe pointer
+	painter.setPen( QColor( 93, 170, 254, 200 ) );
+	painter.drawLine( m_pLoopFramePosition, 4, m_pLoopFramePosition, height() -4 );
+	painter.drawText( m_pLoopFramePosition , 0, 10, 20, Qt::AlignLeft, "L" );
+
+
+}
+
+
+
+void MainSampleWaveDisplay::updateDisplayPointer()
+{
+	update();
+}
+
+
+
+void MainSampleWaveDisplay::updateDisplay( const QString& filename )
+{
+
+	Sample *pNewSample = Sample::load( filename );
+	
+	if ( pNewSample ) {
+
+		int nSampleLength = pNewSample->get_n_frames();
+		m_pSampleLength = nSampleLength;
+		float nScaleFactor = nSampleLength / (width() -50);
+		if ( nScaleFactor < 1 ){ 
+			nScaleFactor = 1;
+		}
+
+		float fGain = height() / 4.0 * 1.0;
+
+		float *pSampleDatal = pNewSample->get_data_l();
+		float *pSampleDatar = pNewSample->get_data_r();
+
+		unsigned nSamplePos = 0;
+		int nVall = 0;
+		int nValr = 0;
+		int newVall = 0;
+		int newValr = 0;
+		for ( int i = 0; i < width(); ++i ){
+			for ( int j = 0; j < nScaleFactor; ++j ) {
+				if ( j < nSampleLength && nSamplePos < nSampleLength) {
+					if ( pSampleDatal[ nSamplePos ] && pSampleDatar[ nSamplePos ] ){
+						newVall = static_cast<int>( pSampleDatal[ nSamplePos ] * fGain );
+						newValr = static_cast<int>( pSampleDatar[ nSamplePos ] * fGain );
+						nVall = newVall;
+						nValr = newValr;
+					}else
+					{
+						nVall = 0;	
+						nValr = 0;
+					}
+				}
+				++nSamplePos;
+			}
+			m_pPeakDatal[ i ] = nVall;
+			m_pPeakDatar[ i ] = nValr;
+		}
+	}
+	delete pNewSample;
+	pNewSample = NULL;
+	update();
+
+}
+
+
+
+void MainSampleWaveDisplay::testPositionFromSampleeditor()
+{
+	testPosition( NULL );
+	update();
+}
+
+
+
+void MainSampleWaveDisplay::mouseMoveEvent(QMouseEvent *ev)
+{
+	testPosition( ev );
+	update();
+}
+
+
+
+void MainSampleWaveDisplay::mousePressEvent(QMouseEvent *ev)
+{
+	testPosition( ev );
+	update();
+}
+
+
+void MainSampleWaveDisplay::testPosition( QMouseEvent *ev )
+{
+//startframepointer
+	if  (ev->y()>=200 ) {
+		m_pStartFramePosition = ev->x() ;
+		__startsliderismoved = true;
+		if ( m_pStartFramePosition > m_pLoopFramePosition ){ 
+			m_pLoopFramePosition = m_pStartFramePosition;
+			__loopsliderismoved = true;
+		}
+		if ( m_pStartFramePosition > m_pEndFramePosition ){
+			m_pEndFramePosition = m_pStartFramePosition;
+			__endsliderismoved = true;
+		}
+//		update();
+	}
+
+//loopframeposition
+	else if  (ev->y()<=65 ) {
+		m_pLoopFramePosition = ev->x() ;
+		__loopsliderismoved = true;		
+		if ( m_pLoopFramePosition < m_pStartFramePosition ){
+			m_pStartFramePosition = m_pLoopFramePosition;
+			__startsliderismoved = true;
+		}
+		if ( m_pLoopFramePosition > m_pEndFramePosition ){
+			m_pEndFramePosition = m_pLoopFramePosition;
+			__endsliderismoved = true;
+		}
+//		update();
+	}
+//endframeposition
+	else if  ( ev->y() >= 86 && ev->y() <= 179  ) {
+		m_pEndFramePosition = ev->x() ;
+		__endsliderismoved = true;
+		if ( m_pEndFramePosition <  m_pLoopFramePosition ){
+			m_pLoopFramePosition = m_pEndFramePosition;
+			__loopsliderismoved = true;
+		}
+		if ( m_pEndFramePosition <  m_pStartFramePosition ){
+			m_pStartFramePosition = m_pEndFramePosition;
+			__startsliderismoved = true;
+		}
+//		update();
+	}
+
+	if ( ( m_pStartFramePosition ) >= width() -25 ) m_pStartFramePosition =width() -25;
+	if ( ( m_pLoopFramePosition ) >= width() -25 ) m_pLoopFramePosition =width() -25;
+	if ( ( m_pEndFramePosition ) >= width() -25 ) m_pEndFramePosition =width() -25;
+	if ( ( m_pStartFramePosition ) <= 25 ) m_pStartFramePosition = 25;
+	if ( ( m_pLoopFramePosition ) <= 25 ) m_pLoopFramePosition = 25;
+	if ( ( m_pEndFramePosition ) <= 25 ) m_pEndFramePosition = 25;
+}
+
+
+void MainSampleWaveDisplay::mouseReleaseEvent(QMouseEvent *ev)
+{
+	update();
+	bool test = HydrogenApp::get_instance()->getSampleEditor()->returnAllMainWaveDisplayValues();
+
+	if (test){
+		__startsliderismoved = false;
+		__loopsliderismoved = false;
+		__endsliderismoved = false;
+	}
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/SampleEditor/TargetWaveDisplay.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/TargetWaveDisplay.cpp	(revision 1449)
+++ /branches/tabbedInterface/gui/src/SampleEditor/TargetWaveDisplay.cpp	(revision 1449)
@@ -0,0 +1,448 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "config.h"
+
+#include <hydrogen/sample.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/instrument.h>
+#include <hydrogen/hydrogen.h>
+
+#include "HydrogenApp.h"
+#include "SampleEditor.h"
+
+using namespace H2Core;
+
+#include <vector>
+#include <algorithm>
+#include "TargetWaveDisplay.h"
+#include "../Skin.h"
+
+
+TargetWaveDisplay::TargetWaveDisplay(QWidget* pParent)
+ : QWidget( pParent )
+ , Object( "TargetWaveDisplay" )
+ , m_sSampleName( "" )
+{
+//	setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG( "INIT" );
+	int w = 841;
+	int h = 91;
+	resize( w, h );
+
+	bool ok = m_background.load( Skin::getImagePath() + "/waveDisplay/targetsamplewavedisplay.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	m_pPeakDatal = new int[ w ];
+	m_pPeakDatar = new int[ w ];
+	m_pvmove = false;
+	m_info = "";
+	m_x = -10;
+	m_y = -10;
+	m_plocator = -1;
+	m_pupdateposi = false;
+}
+
+
+
+
+TargetWaveDisplay::~TargetWaveDisplay()
+{
+	//INFOLOG( "DESTROY" );
+
+	delete[] m_pPeakDatal;
+	delete[] m_pPeakDatar;
+}
+
+
+
+void TargetWaveDisplay::paintEvent(QPaintEvent *ev)
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	QPainter painter( this );
+	painter.setRenderHint( QPainter::HighQualityAntialiasing );
+	painter.drawPixmap( ev->rect(), m_background, ev->rect() );
+
+	painter.setPen( QColor( 252, 142, 73 ));
+	int VCenter = height() / 2;
+	int lcenter = VCenter -4;
+	int rcenter = VCenter +4;
+	for ( int x = 0; x < width(); x++ ) {
+		painter.drawLine( x, lcenter, x, -m_pPeakDatal[x +1] +lcenter  );
+	}
+
+	painter.setPen( QColor( 116, 186, 255 ));
+	for ( int x = 0; x < width(); x++ ) {
+		painter.drawLine( x, rcenter, x, -m_pPeakDatar[x +1] +rcenter  );
+	}
+
+	QFont font;
+	font.setWeight( 63 );
+	painter.setFont( font );
+//start frame pointer
+//	painter.setPen( QColor( 99, 175, 254, 200 ) );
+//	painter.drawLine( m_pFadeOutFramePosition, 4, m_pFadeOutFramePosition, height() -4 );	
+//	painter.drawText( m_pFadeOutFramePosition , 1, 10,20, Qt::AlignRight, "F" );
+
+	for ( int i = 0; i < static_cast<int>(pEngine->m_volumen.size()) -1; i++){
+		//volume line
+		painter.setPen( QPen(QColor( 255, 255, 255, 200 ) ,1 , Qt::SolidLine) );
+		painter.drawLine( pEngine->m_volumen[i].m_hxframe, pEngine->m_volumen[i].m_hyvalue, pEngine->m_volumen[i + 1].m_hxframe, pEngine->m_volumen[i +1].m_hyvalue );
+		painter.setBrush(QColor( 99, 160, 233 ));
+		painter.drawEllipse ( pEngine->m_volumen[i].m_hxframe - 6/2, pEngine->m_volumen[i].m_hyvalue  - 6/2, 6, 6 );
+	}
+
+	for ( int i = 0; i < static_cast<int>(pEngine->m_pan.size()) -1; i++){
+		//pan line
+		painter.setPen( QPen(QColor( 249, 235, 116, 200 ) ,1 , Qt::SolidLine) );
+		painter.drawLine( pEngine->m_pan[i].m_hxframe, pEngine->m_pan[i].m_hyvalue, pEngine->m_pan[i + 1].m_hxframe, pEngine->m_pan[i +1].m_hyvalue );
+		painter.setBrush(QColor( 77, 189, 55 ));
+		painter.drawEllipse ( pEngine->m_pan[i].m_hxframe - 6/2, pEngine->m_pan[i].m_hyvalue  - 6/2, 6, 6 );
+	}
+
+
+	painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+	painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::SolidLine ) );
+	painter.drawLine( m_plocator, 4, m_plocator, height() -4);
+
+	//volume line
+	//first rect 
+	painter.setPen( QPen(QColor( 255, 255, 255, 200 ) ,1 , Qt::SolidLine) );
+	painter.setBrush(QColor( 99, 160, 233 ));
+	painter.drawRect ( pEngine->m_volumen[0].m_hxframe - 12/2, pEngine->m_volumen[0].m_hyvalue  - 6/2, 12, 6 );
+	//last rect 
+	painter.drawRect ( pEngine->m_volumen[pEngine->m_volumen.size() -1].m_hxframe - 12/2, pEngine->m_volumen[pEngine->m_volumen.size() -1].m_hyvalue  - 6/2, 12, 6 );
+
+	//pan line
+	//first rect 
+	painter.setPen( QPen(QColor( 249, 235, 116, 200 ) ,1 , Qt::SolidLine) );
+	painter.setBrush(QColor( 77, 189, 55 ));
+	painter.drawRect ( pEngine->m_pan[0].m_hxframe - 12/2, pEngine->m_pan[0].m_hyvalue  - 6/2, 12, 6 );
+	//last rect 
+	painter.drawRect ( pEngine->m_pan[pEngine->m_pan.size() -1].m_hxframe - 12/2, pEngine->m_pan[pEngine->m_pan.size() -1].m_hyvalue  - 6/2, 12, 6 );
+
+
+	painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::DotLine ) );
+	painter.drawLine( 0, lcenter, 841, lcenter );	
+	painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::DotLine ) );
+	painter.drawLine( 0, rcenter, 841, rcenter );
+
+	if (m_y < 50){
+		if (m_x < 790){
+			painter.drawText( m_x +5, m_y, 60, 20, Qt::AlignLeft, QString( m_info ) );
+		}else
+		{
+			painter.drawText( m_x - 65, m_y, 60, 20, Qt::AlignRight, QString( m_info ) );
+		}
+		
+	}else
+	{
+		if (m_x < 790){
+			painter.drawText( m_x +5, m_y -20, 60, 20, Qt::AlignLeft, QString( m_info ) );
+		}else
+		{
+			painter.drawText( m_x - 65, m_y -20, 60, 20, Qt::AlignRight, QString( m_info ) );
+		}
+	}
+
+}
+
+
+void TargetWaveDisplay::updateDisplayPointer()
+{
+	update();
+}
+
+void TargetWaveDisplay::paintLocatorEventTargetDisplay( int pos, bool updateposi)
+{
+	m_pupdateposi = updateposi;
+	if ( !updateposi ){
+		m_plocator = -1;
+	}else
+	{
+		m_plocator = pos;
+	}
+	update();
+}
+
+void TargetWaveDisplay::updateDisplay( H2Core::InstrumentLayer *pLayer )
+{
+	if ( pLayer && pLayer->get_sample() ) {
+
+		int nSampleLength = pLayer->get_sample()->get_n_frames();
+		float nScaleFactor = nSampleLength / width();
+
+		float fGain = (height() - 8) / 2.0 * pLayer->get_gain();
+
+		float *pSampleDatal = pLayer->get_sample()->get_data_l();
+		float *pSampleDatar = pLayer->get_sample()->get_data_r();
+		int nSamplePos = 0;
+		int nVall;
+		int nValr;
+		for ( int i = 0; i < width(); ++i ){
+			nVall = 0;
+			nValr = 0;
+			for ( int j = 0; j < nScaleFactor; ++j ) {
+				if ( j < nSampleLength ) {
+					if ( pSampleDatal[ nSamplePos ] < 0 ){
+						int newVal = static_cast<int>( pSampleDatal[ nSamplePos ] * -fGain );
+						nVall = newVal;
+					}else
+					{
+						int newVal = static_cast<int>( pSampleDatal[ nSamplePos ] * fGain );
+						nVall = newVal;
+					}
+					if ( pSampleDatar[ nSamplePos ] > 0 ){
+						int newVal = static_cast<int>( pSampleDatar[ nSamplePos ] * -fGain );
+						nValr = newVal;
+					}else
+					{
+						int newVal = static_cast<int>( pSampleDatar[ nSamplePos ] * fGain );
+						nValr = newVal;
+					}
+				}
+				++nSamplePos;
+			}
+			m_pPeakDatal[ i ] = nVall;
+			m_pPeakDatar[ i ] = nValr;
+		}
+	}
+
+	update();
+
+}
+
+
+void TargetWaveDisplay::mouseMoveEvent(QMouseEvent *ev)
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	int snapradius = 10;
+	QString editType = HydrogenApp::get_instance()->getSampleEditor()->EditTypeComboBox->currentText();
+
+
+
+	///edit volume points
+	if( editType == "volume" ){
+		m_pvmove = true;
+	
+		if ( ev->x() <= 0 || ev->x() >= 841 || ev->y() < 0 || ev->y() > 91 ){
+			update();
+			m_pvmove = false;
+			return;
+		}
+		float info = (91 - ev->y()) / 91.0;
+		m_info.setNum( info, 'g', 2 );
+		m_x = ev->x();
+		m_y = ev->y();
+	
+		for ( int i = 0; i < static_cast<int>(pEngine->m_volumen.size()); i++){
+			if ( pEngine->m_volumen[i].m_hxframe >= ev->x() - snapradius && pEngine->m_volumen[i].m_hxframe <= ev->x() + snapradius ){
+				pEngine->m_volumen.erase( pEngine->m_volumen.begin() + i);
+				Hydrogen::HVeloVector velovector;
+				if ( i == 0 ){
+					velovector.m_hxframe = 0;
+					velovector.m_hyvalue = ev->y();
+				}
+				else if ( i == static_cast<int>(pEngine->m_volumen.size()) ){
+					velovector.m_hxframe = pEngine->m_volumen[i].m_hxframe;
+					velovector.m_hyvalue = ev->y();
+					
+				}else
+				{
+					velovector.m_hxframe = ev->x();
+					velovector.m_hyvalue = ev->y();
+				}
+	
+				pEngine->m_volumen.push_back( velovector );
+				pEngine->sortVolVectors();	
+				update();
+				return;
+			}else
+			{
+				m_pvmove = false;	
+			}
+		}
+	///edit panorama points
+	}else if( editType == "panorama" ){
+		m_pvmove = true;
+	
+		if ( ev->x() <= 0 || ev->x() >= 841 || ev->y() < 0 || ev->y() > 91 ){
+			update();
+			m_pvmove = false;
+			return;
+		}
+		float info = (45 - ev->y()) / 45.0;
+		m_info.setNum( info, 'g', 2 );
+		m_x = ev->x();
+		m_y = ev->y();
+	
+		for ( int i = 0; i < static_cast<int>(pEngine->m_pan.size()); i++){
+			if ( pEngine->m_pan[i].m_hxframe >= ev->x() - snapradius && pEngine->m_pan[i].m_hxframe <= ev->x() + snapradius ){
+				pEngine->m_pan.erase( pEngine->m_pan.begin() + i);
+				Hydrogen::HPanVector panvector;
+				if ( i == 0 ){
+					panvector.m_hxframe = 0;
+					panvector.m_hyvalue = ev->y();
+				}
+				else if ( i == static_cast<int>(pEngine->m_pan.size()) ){
+					panvector.m_hxframe = pEngine->m_pan[i].m_hxframe;
+					panvector.m_hyvalue = ev->y();
+					
+				}else
+				{
+					panvector.m_hxframe = ev->x();
+					panvector.m_hyvalue = ev->y();
+				}
+	
+				pEngine->m_pan.push_back( panvector );
+				pEngine->sortPanVectors();	
+				update();
+				return;
+			}else
+			{
+				m_pvmove = false;	
+			}
+		}
+	}
+
+	update();
+	HydrogenApp::get_instance()->getSampleEditor()->setTrue();
+}
+
+
+
+void TargetWaveDisplay::mousePressEvent(QMouseEvent *ev)
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	int snapradius = 6;
+	bool newpoint = true;
+
+	// add new point
+	QString editType = HydrogenApp::get_instance()->getSampleEditor()->EditTypeComboBox->currentText();
+
+
+	///edit volume points
+	if( editType == "volume" ){
+		// test if there is already a point
+		for ( int i = 0; i < static_cast<int>(pEngine->m_volumen.size()); ++i){
+			if ( pEngine->m_volumen[i].m_hxframe >= ev->x() - snapradius && pEngine->m_volumen[i].m_hxframe <= ev->x() + snapradius ){
+				newpoint = false;
+			}
+		}
+		int x = ev->x();
+		int y = ev->y();	
+		if (ev->button() == Qt::LeftButton && !m_pvmove && newpoint){
+			float info = (91 - ev->y()) / 91.0;
+			m_info.setNum( info, 'g', 2 );
+			m_x = ev->x();
+			m_y = ev->y();
+			Hydrogen::HVeloVector velovector;
+			if ( ev->y() <= 0 ) y = 0;
+			if ( ev->y() >= 91 ) y = 91;
+			if ( ev->x() <= 6 ) x = 6;
+			if ( ev->x() >= 835 ) x = 835;
+			velovector.m_hxframe = x;
+			velovector.m_hyvalue = y;
+			pEngine->m_volumen.push_back( velovector );
+			pEngine->sortVolVectors();		
+		}
+	
+	
+		//remove point
+		snapradius = 10;
+		if (ev->button() == Qt::RightButton ){
+	
+			if ( ev->x() <= 0 || ev->x() >= 841 ){
+				update();
+				return;
+			}
+			m_info = "";
+
+			for ( int i = 0; i < static_cast<int>(pEngine->m_volumen.size()); i++){
+				if ( pEngine->m_volumen[i].m_hxframe >= ev->x() - snapradius && pEngine->m_volumen[i].m_hxframe <= ev->x() + snapradius ){
+					if ( pEngine->m_volumen[i].m_hxframe == 0 || pEngine->m_volumen[i].m_hxframe == 841) return;
+					pEngine->m_volumen.erase( pEngine->m_volumen.begin() +  i);
+				}
+			}	
+		}
+	}
+	///edit panorama points
+	else if( editType == "panorama" ){
+		// test if there is already a point
+		for ( int i = 0; i < static_cast<int>(pEngine->m_pan.size()); ++i){
+			if ( pEngine->m_pan[i].m_hxframe >= ev->x() - snapradius && pEngine->m_pan[i].m_hxframe <= ev->x() + snapradius ){
+				newpoint = false;
+			}
+		}
+		int x = ev->x();
+		int y = ev->y();	
+		if (ev->button() == Qt::LeftButton && !m_pvmove && newpoint){
+			float info = (45 - ev->y()) / 45.0;
+			m_info.setNum( info, 'g', 2 );
+			m_x = ev->x();
+			m_y = ev->y();
+			Hydrogen::HPanVector panvector;
+			if ( ev->y() <= 0 ) y = 0;
+			if ( ev->y() >= 91 ) y = 91;
+			if ( ev->x() <= 6 ) x = 6;
+			if ( ev->x() >= 835 ) x = 835;
+			panvector.m_hxframe = x;
+			panvector.m_hyvalue = y;
+			pEngine->m_pan.push_back( panvector );
+			pEngine->sortPanVectors();		
+		}
+	
+	
+		//remove point
+		snapradius = 10;
+		if (ev->button() == Qt::RightButton ){
+	
+			if ( ev->x() <= 0 || ev->x() >= 841 ){
+				update();
+				return;
+			}
+			m_info = "";
+
+			for ( int i = 0; i < static_cast<int>(pEngine->m_pan.size()); i++){
+				if ( pEngine->m_pan[i].m_hxframe >= ev->x() - snapradius && pEngine->m_pan[i].m_hxframe <= ev->x() + snapradius ){
+					if ( pEngine->m_pan[i].m_hxframe == 0 || pEngine->m_pan[i].m_hxframe == 841) return;
+					pEngine->m_pan.erase( pEngine->m_pan.begin() +  i);
+				}
+			}	
+		}
+	}
+
+	update();
+	HydrogenApp::get_instance()->getSampleEditor()->setTrue();
+}
+
+
+
+
+
+void TargetWaveDisplay::mouseReleaseEvent(QMouseEvent *ev)
+{
+	update();
+	HydrogenApp::get_instance()->getSampleEditor()->returnAllTargetDisplayValues();
+}
Index: /branches/tabbedInterface/gui/src/SampleEditor/DetailWaveDisplay.h
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/DetailWaveDisplay.h	(revision 638)
+++ /branches/tabbedInterface/gui/src/SampleEditor/DetailWaveDisplay.h	(revision 638)
@@ -0,0 +1,59 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef DETAIL_WAVE_DISPLAY
+#define DETAIL_WAVE_DISPLAY
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+
+namespace H2Core
+{
+	class Sample;
+}
+
+class DetailWaveDisplay : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		DetailWaveDisplay(QWidget* pParent);
+		~DetailWaveDisplay();
+
+		void updateDisplay( QString filename );
+
+		void paintEvent(QPaintEvent *ev);
+		void setDetailSamplePosition( unsigned posi, float zoomfactor, QString type);
+
+	private:
+		QPixmap m_background;
+		QString m_sSampleName;
+		int *m_pPeakDatal;
+		int *m_pPeakDatar;
+		int m_pDetailSamplePosition; 
+		int m_pnormalimagedetailframes;
+		float m_pzoomFactor;
+		QString m_ptype;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor_UI.ui
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor_UI.ui	(revision 1497)
+++ /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor_UI.ui	(revision 1497)
@@ -0,0 +1,736 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SampleEditor_UI</class>
+ <widget class="QDialog" name="SampleEditor_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>858</width>
+    <height>543</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <widget class="QFrame" name="targetSampleView">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>440</y>
+     <width>841</width>
+     <height>94</height>
+    </rect>
+   </property>
+   <property name="cursor">
+    <cursorShape>CrossCursor</cursorShape>
+   </property>
+   <property name="frameShape">
+    <enum>QFrame::Box</enum>
+   </property>
+   <property name="frameShadow">
+    <enum>QFrame::Raised</enum>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="ClosePushButton">
+   <property name="geometry">
+    <rect>
+     <x>775</x>
+     <y>295</y>
+     <width>81</width>
+     <height>26</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&amp;Close</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="layoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>5</x>
+     <y>295</y>
+     <width>621</width>
+     <height>30</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="spinboxesLayout">
+    <item>
+     <widget class="QSpinBox" name="StartFrameSpinBox">
+      <property name="minimumSize">
+       <size>
+        <width>140</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="toolTip">
+       <string>Adjust sample start frame</string>
+      </property>
+      <property name="maximum">
+       <number>1000000000</number>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QSpinBox" name="LoopFrameSpinBox">
+      <property name="minimumSize">
+       <size>
+        <width>140</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="toolTip">
+       <string>Adjust sample loop begin frame</string>
+      </property>
+      <property name="maximum">
+       <number>1000000000</number>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QComboBox" name="ProcessingTypeComboBox">
+      <property name="minimumSize">
+       <size>
+        <width>82</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="toolTip">
+       <string>set processing</string>
+      </property>
+      <item>
+       <property name="text">
+        <string>forward</string>
+       </property>
+      </item>
+      <item>
+       <property name="text">
+        <string>reverse</string>
+       </property>
+      </item>
+      <item>
+       <property name="text">
+        <string>pingpong</string>
+       </property>
+      </item>
+     </widget>
+    </item>
+    <item>
+     <widget class="QSpinBox" name="LoopCountSpinBox">
+      <property name="minimumSize">
+       <size>
+        <width>60</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="toolTip">
+       <string>loops</string>
+      </property>
+      <property name="minimum">
+       <number>0</number>
+      </property>
+      <property name="maximum">
+       <number>10000</number>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QSpinBox" name="EndFrameSpinBox">
+      <property name="minimumSize">
+       <size>
+        <width>140</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="toolTip">
+       <string>Adjust sample end &amp; loop end frame</string>
+      </property>
+      <property name="maximum">
+       <number>1000000000</number>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="layoutWidget_2">
+   <property name="geometry">
+    <rect>
+     <x>5</x>
+     <y>10</y>
+     <width>843</width>
+     <height>276</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="mainSampleViewLayout">
+    <item>
+     <widget class="QFrame" name="mainSampleview">
+      <property name="minimumSize">
+       <size>
+        <width>624</width>
+        <height>265</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>624</width>
+        <height>265</height>
+       </size>
+      </property>
+      <property name="cursor">
+       <cursorShape>SplitHCursor</cursorShape>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Raised</enum>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QFrame" name="mainSampleAdjustView">
+      <property name="minimumSize">
+       <size>
+        <width>180</width>
+        <height>265</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>180</width>
+        <height>265</height>
+       </size>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Raised</enum>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QSlider" name="verticalzoomSlider">
+      <property name="value">
+       <number>1</number>
+      </property>
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QFrame" name="RubberbandCframe">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>330</y>
+     <width>841</width>
+     <height>71</height>
+    </rect>
+   </property>
+   <property name="frameShape">
+    <enum>QFrame::StyledPanel</enum>
+   </property>
+   <property name="frameShadow">
+    <enum>QFrame::Raised</enum>
+   </property>
+   <widget class="QWidget" name="">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>10</y>
+      <width>821</width>
+      <height>51</height>
+     </rect>
+    </property>
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <widget class="QLabel" name="rubberbandLabel">
+       <property name="text">
+        <string>&quot;Rubberband Audio Processor&quot; Change the tempo(sample length) and pitch of audio. </string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <item>
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string>Sample length to beat:</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QComboBox" name="rubberComboBox">
+         <property name="maximumSize">
+          <size>
+           <width>75</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <item>
+          <property name="text">
+           <string>off</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1/64</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1/32</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1/16</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1/8</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1/4</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1/2</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>1</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>2</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>3</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>4</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>5</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>6</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>7</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>8</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>9</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>10</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>11</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>12</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>13</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>14</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>15</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>16</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>17</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>18</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>19</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>20</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>21</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>22</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>23</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>24</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>25</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>26</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>27</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>28</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>29</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>30</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>31</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>32</string>
+          </property>
+         </item>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="ratiolabel">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>150</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="text">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="pitchlabel">
+         <property name="text">
+          <string>Pitch: (Semitone,Cent)</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QDoubleSpinBox" name="pitchdoubleSpinBox">
+         <property name="maximumSize">
+          <size>
+           <width>75</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Pitch the sample in semitones, cents</string>
+         </property>
+         <property name="minimum">
+          <double>-36.000000000000000</double>
+         </property>
+         <property name="maximum">
+          <double>36.000000000000000</double>
+         </property>
+         <property name="singleStep">
+          <double>0.010000000000000</double>
+         </property>
+         <property name="value">
+          <double>0.000000000000000</double>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QLabel" name="r_c_label">
+           <property name="maximumSize">
+            <size>
+             <width>100</width>
+             <height>16777215</height>
+            </size>
+           </property>
+           <property name="text">
+            <string>Crispness: </string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="rubberbandCsettingscomboBox">
+           <property name="minimumSize">
+            <size>
+             <width>0</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>45</width>
+             <height>16777215</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&quot;Crispness&quot; levels:&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;  0   equivalent to --no-transients --no-lamination --window-long&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;  1   equivalent to --no-transients --no-lamination&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;  2   equivalent to --no-transients&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;  3   equivalent to --bl-transients&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;  4   default processing options&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;  5   equivalent to --no-lamination --window-short (may be good for drums)&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;more informations about you can find here:&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.breakfastquay.com/rubberband/ &quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.breakfastquay.com/rubberband/ &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+           </property>
+           <item>
+            <property name="text">
+             <string>0</string>
+            </property>
+           </item>
+           <item>
+            <property name="text">
+             <string>1</string>
+            </property>
+           </item>
+           <item>
+            <property name="text">
+             <string>2</string>
+            </property>
+           </item>
+           <item>
+            <property name="text">
+             <string>3</string>
+            </property>
+           </item>
+           <item>
+            <property name="text">
+             <string>4</string>
+            </property>
+           </item>
+           <item>
+            <property name="text">
+             <string>5</string>
+            </property>
+           </item>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </widget>
+  </widget>
+  <widget class="QWidget" name="">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>410</y>
+     <width>841</width>
+     <height>27</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="horizontalLayout_3">
+    <item>
+     <widget class="QPushButton" name="PrevChangesPushButton">
+      <property name="text">
+       <string>&amp;Apply Changes</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer name="horizontalSpacer">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::Maximum</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>13</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QPushButton" name="PlayPushButton">
+      <property name="text">
+       <string>&amp;Play</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer name="horizontalSpacer_2">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::Minimum</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>13</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QPushButton" name="PlayOrigPushButton">
+      <property name="text">
+       <string>P&amp;lay original sample</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLabel" name="newlengthLabel">
+      <property name="minimumSize">
+       <size>
+        <width>300</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="text">
+       <string>new sample length:</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QComboBox" name="EditTypeComboBox">
+      <property name="minimumSize">
+       <size>
+        <width>60</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="toolTip">
+       <string>fade-out type</string>
+      </property>
+      <item>
+       <property name="text">
+        <string>volume</string>
+       </property>
+      </item>
+      <item>
+       <property name="text">
+        <string>panorama</string>
+       </property>
+      </item>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <zorder>targetSampleView</zorder>
+  <zorder>PlayOrigPushButton</zorder>
+  <zorder>PrevChangesPushButton</zorder>
+  <zorder>ClosePushButton</zorder>
+  <zorder>layoutWidget</zorder>
+  <zorder>layoutWidget_2</zorder>
+  <zorder>PlayPushButton</zorder>
+  <zorder>newlengthLabel</zorder>
+  <zorder>EditTypeComboBox</zorder>
+  <zorder>layoutWidget</zorder>
+  <zorder>pitchdoubleSpinBox</zorder>
+  <zorder>pitchlabel</zorder>
+  <zorder>ratiolabel</zorder>
+  <zorder>rubberbandLabel</zorder>
+  <zorder>rubberComboBox</zorder>
+  <zorder>label</zorder>
+  <zorder>horizontalSpacer</zorder>
+  <zorder>horizontalSpacer_2</zorder>
+  <zorder>RubberbandCframe</zorder>
+  <zorder>rubberbandLabel</zorder>
+ </widget>
+ <tabstops>
+  <tabstop>StartFrameSpinBox</tabstop>
+  <tabstop>LoopFrameSpinBox</tabstop>
+  <tabstop>ProcessingTypeComboBox</tabstop>
+  <tabstop>LoopCountSpinBox</tabstop>
+  <tabstop>EndFrameSpinBox</tabstop>
+  <tabstop>PrevChangesPushButton</tabstop>
+  <tabstop>PlayOrigPushButton</tabstop>
+  <tabstop>ClosePushButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: /branches/tabbedInterface/gui/src/SampleEditor/MainSampleWaveDisplay.h
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/MainSampleWaveDisplay.h	(revision 1447)
+++ /branches/tabbedInterface/gui/src/SampleEditor/MainSampleWaveDisplay.h	(revision 1447)
@@ -0,0 +1,70 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef MAIN_SAMPLE_WAVE_DISPLAY
+#define MAIN_SAMPLE_WAVE_DISPLAY
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+#include "SampleEditor.h"
+class SampleEditor;
+
+class MainSampleWaveDisplay : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		MainSampleWaveDisplay(QWidget* pParent);
+		~MainSampleWaveDisplay();
+
+		void updateDisplay( const QString& filename );
+		void updateDisplayPointer();
+
+		void paintLocatorEvent( int pos, bool last_event);
+		void paintEvent(QPaintEvent *ev);
+		int m_pStartFramePosition;
+		int m_pLoopFramePosition;
+		int m_pEndFramePosition;
+		bool m_pmove;
+		void testPositionFromSampleeditor();
+		bool __startsliderismoved;
+		bool __loopsliderismoved;
+		bool __endsliderismoved;
+
+
+	private:
+		QPixmap m_background;
+		int *m_pPeakDatal;
+		int *m_pPeakDatar;
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+		void testPosition( QMouseEvent *ev );
+		int m_pSampleLength;
+		int m_plocator;
+		bool m_pupdateposi;
+
+};
+
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/SampleEditor/TargetWaveDisplay.h
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/TargetWaveDisplay.h	(revision 1449)
+++ /branches/tabbedInterface/gui/src/SampleEditor/TargetWaveDisplay.h	(revision 1449)
@@ -0,0 +1,70 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef TARGET_WAVE_DISPLAY
+#define TARGET_WAVE_DISPLAY
+
+#include <QtGui>
+#include <hydrogen/Object.h>
+#include <hydrogen/sample.h>
+
+class SampleEditor;
+
+namespace H2Core
+{
+	class InstrumentLayer;
+}
+
+class TargetWaveDisplay : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		TargetWaveDisplay(QWidget* pParent);
+		~TargetWaveDisplay();
+
+		void updateDisplay( H2Core::InstrumentLayer *pLayer );
+		void updateDisplayPointer();
+		void paintLocatorEventTargetDisplay( int pos, bool last_event);
+		void paintEvent(QPaintEvent *ev);
+//		int m_pFadeOutFramePosition;
+
+	private:
+		QPixmap m_background;
+		QString m_sSampleName;
+		int *m_pPeakDatal;
+		int *m_pPeakDatar;
+		unsigned m_pSampleLength;
+		bool m_pvmove;
+		QString m_info;
+		int m_x;
+		int m_y;
+		int m_plocator;
+		bool m_pupdateposi;
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+		
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor.cpp	(revision 1497)
+++ /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor.cpp	(revision 1497)
@@ -0,0 +1,934 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "SampleEditor.h"
+#include "../HydrogenApp.h"
+#include "../InstrumentEditor/InstrumentEditor.h"
+#include "../InstrumentEditor/InstrumentEditorPanel.h"
+#include "../widgets/Button.h"
+
+#include "MainSampleWaveDisplay.h"
+#include "DetailWaveDisplay.h"
+#include "TargetWaveDisplay.h"
+
+#include <hydrogen/data_path.h>
+#include <hydrogen/h2_exception.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/sample.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/hydrogen.h>
+
+#include <QModelIndex>
+#include <QTreeWidget>
+#include <QMessageBox>
+#include <algorithm>
+
+using namespace H2Core;
+using namespace std;
+
+SampleEditor::SampleEditor ( QWidget* pParent, int nSelectedLayer, QString mSamplefilename )
+		: QDialog ( pParent )
+		, Object ( "SampleEditor" )
+{
+	setupUi ( this );
+	INFOLOG ( "INIT" );
+
+	m_pTimer = new QTimer(this);
+	connect(m_pTimer, SIGNAL(timeout()), this, SLOT(updateMainsamplePostionRuler()));
+	m_pTargetDisplayTimer = new QTimer(this);
+	connect(m_pTargetDisplayTimer, SIGNAL(timeout()), this, SLOT(updateTargetsamplePostionRuler()));
+
+	m_pSampleEditorStatus = true;
+	m_pSamplefromFile = NULL;
+	m_pSelectedLayer = nSelectedLayer;
+	m_samplename = mSamplefilename;
+	m_pzoomfactor = 1;
+	m_pdetailframe = 0;
+	m_plineColor = "default";
+	m_ponewayStart = false;
+	m_ponewayLoop = false;
+	m_ponewayEnd = false;
+	m_pslframes = 0;
+	m_pPositionsRulerPath = NULL;
+	m_pPlayButton = false;
+	m_pratio = 1.0;
+	m_ppitch = 0.0;
+	m_pRubberbandCsettings = 4;
+
+	QString newfilename = mSamplefilename.section( '/', -1 );
+
+	//init Displays
+	m_pMainSampleWaveDisplay = new MainSampleWaveDisplay( mainSampleview );
+	m_pSampleAdjustView = new DetailWaveDisplay( mainSampleAdjustView );
+	m_pTargetSampleView = new TargetWaveDisplay( targetSampleView );
+
+	setWindowTitle ( QString( "SampleEditor " + newfilename) );
+	setFixedSize ( width(), height() );
+
+//this new sample give us the not changed real samplelength 
+	m_pSamplefromFile = Sample::load( mSamplefilename );
+	if (!m_pSamplefromFile) reject();
+
+	unsigned slframes = m_pSamplefromFile->get_n_frames();
+
+	LoopCountSpinBox->setRange(0, 20000 );
+	StartFrameSpinBox->setRange(0, slframes );
+	LoopFrameSpinBox->setRange(0, slframes );
+	EndFrameSpinBox->setRange(0, slframes );
+	EndFrameSpinBox->setValue( slframes );
+	rubberbandCsettingscomboBox->setCurrentIndex( 4 );
+	rubberComboBox->setCurrentIndex( 0 );
+
+	m_pUseRubber = false;
+	m_pRubberDivider = 1.0;
+	openDisplays();
+	getAllFrameInfos();
+
+	if ( QFile( Preferences::get_instance()->m_rubberBandCLIexecutable ).exists() == false ){
+		RubberbandCframe->setDisabled ( true );
+//pitchdoubleSpinBox
+		m_pUseRubber = false;
+		m_pSampleEditorStatus = true;
+	}
+
+}
+
+
+
+SampleEditor::~SampleEditor()
+{
+	m_pMainSampleWaveDisplay->close();
+	delete m_pMainSampleWaveDisplay;
+	m_pMainSampleWaveDisplay = NULL;
+
+	m_pSampleAdjustView->close();
+	delete m_pSampleAdjustView;
+	m_pSampleAdjustView = NULL;
+
+	m_pTargetSampleView->close();
+	delete m_pTargetSampleView;
+	m_pTargetSampleView = NULL;
+
+	delete m_pSamplefromFile;
+	m_pSamplefromFile = NULL;
+
+	INFOLOG ( "DESTROY" );
+}
+
+
+void SampleEditor::closeEvent(QCloseEvent *event)
+{
+	if ( !m_pSampleEditorStatus ){
+		int err = QMessageBox::information( this, "Hydrogen", tr( "Unsaved changes left. This changes will be lost. \nAre you sure?"), tr("&Ok"), tr("&Cancel"), 0, 1 );
+		if ( err == 0 ){
+			m_pSampleEditorStatus = true;
+			accept();	
+		}else
+		{
+			return;
+		}
+	}else
+	{
+		accept();
+	}
+}
+
+
+void SampleEditor::getAllFrameInfos()
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	H2Core::Instrument *pInstrument = NULL;
+	Sample* pSample = NULL;
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	if (pSong != NULL) {
+		InstrumentList *pInstrList = pSong->get_instrument_list();
+		int nInstr = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		if ( nInstr >= static_cast<int>(pInstrList->get_size()) ) {
+			nInstr = -1;
+		}
+
+		if (nInstr == -1) {
+			pInstrument = NULL;
+		}
+		else {
+			pInstrument = pInstrList->get( nInstr );
+			//INFOLOG( "new instr: " + pInstrument->m_sName );
+		}
+	}
+	H2Core::InstrumentLayer *pLayer = pInstrument->get_layer( m_pSelectedLayer );
+	if ( pLayer ) {
+		pSample = pLayer->get_sample();
+	}
+
+//this values are needed if we restore a sample from from disk if a new song with sample changes will load 
+	m_sample_is_modified = pSample->get_sample_is_modified();
+	m_sample_mode = pSample->get_sample_mode();
+	m_start_frame = pSample->get_start_frame();
+	m_loop_frame = pSample->get_loop_frame();
+	m_repeats = pSample->get_repeats();
+	m_end_frame = pSample->get_n_frames();
+	m_pUseRubber = pSample->get_use_rubber();
+	m_pRubberDivider = pSample->get_rubber_divider();
+	m_pSamplerate = pSample->get_sample_rate();
+	m_pRubberbandCsettings = pSample->get_rubber_C_settings();
+	m_ppitch = pSample->get_rubber_pitch();
+
+	Hydrogen::HVeloVector velovector;
+	//velovector
+	if ( pSample->__velo_pan.m_Samplevolumen[0].m_SampleVeloframe == -1 ){
+		pEngine->m_volumen.clear();
+		velovector.m_hxframe = 0;
+		velovector.m_hyvalue = 0;
+		pEngine->m_volumen.push_back( velovector );
+		velovector.m_hxframe = 841;
+		velovector.m_hyvalue = 0;
+		pEngine->m_volumen.push_back( velovector );
+	}else
+	{
+		pEngine->m_volumen.clear();
+		for( int i = 0 ; i < static_cast<int>(pSample->__velo_pan.m_Samplevolumen.size()); i++){
+			velovector.m_hxframe = pSample->__velo_pan.m_Samplevolumen[i].m_SampleVeloframe;
+			velovector.m_hyvalue = pSample->__velo_pan.m_Samplevolumen[i].m_SampleVelovalue;
+			pEngine->m_volumen.push_back( velovector );	
+		}
+	}
+
+	Hydrogen::HPanVector panvector;
+	if ( pSample->__velo_pan.m_SamplePan[0].m_SamplePanframe == -1 ){
+		pEngine->m_pan.clear();
+		panvector.m_hxframe = 0;
+		panvector.m_hyvalue = 45;
+		pEngine->m_pan.push_back( panvector );
+		panvector.m_hxframe = 841;
+		panvector.m_hyvalue = 45;
+		pEngine->m_pan.push_back( panvector );
+	}else
+	{
+		pEngine->m_pan.clear();
+		for( int i = 0 ; i < static_cast<int>(pSample->__velo_pan.m_SamplePan.size()); i++){
+			panvector.m_hxframe = pSample->__velo_pan.m_SamplePan[i].m_SamplePanframe;
+			panvector.m_hyvalue = pSample->__velo_pan.m_SamplePan[i].m_SamplePanvalue;
+			pEngine->m_pan.push_back( panvector );
+		}
+	}
+
+	if (m_sample_is_modified) {
+		m_end_frame = pSample->get_end_frame();
+		if ( m_sample_mode == "forward" ) 
+			ProcessingTypeComboBox->setCurrentIndex ( 0 );
+		if ( m_sample_mode == "reverse" ) 
+			ProcessingTypeComboBox->setCurrentIndex ( 1 );
+		if ( m_sample_mode == "pingpong" ) 
+			ProcessingTypeComboBox->setCurrentIndex ( 2 );
+
+		StartFrameSpinBox->setValue( m_start_frame );
+		LoopFrameSpinBox->setValue( m_loop_frame );
+		EndFrameSpinBox->setValue( m_end_frame );
+		LoopCountSpinBox->setValue( m_repeats );
+
+		m_pMainSampleWaveDisplay->m_pStartFramePosition = m_start_frame / m_divider + 25 ;
+		m_pMainSampleWaveDisplay->updateDisplayPointer();
+		m_pMainSampleWaveDisplay->m_pLoopFramePosition =  m_loop_frame / m_divider + 25 ;
+		m_pMainSampleWaveDisplay->updateDisplayPointer();
+		m_pMainSampleWaveDisplay->m_pEndFramePosition =  m_end_frame / m_divider + 25 ;
+		m_pMainSampleWaveDisplay->updateDisplayPointer();
+
+		if( !m_pUseRubber )rubberComboBox->setCurrentIndex( 0 );
+		rubberbandCsettingscomboBox->setCurrentIndex( m_pRubberbandCsettings );
+		if( !m_pUseRubber )rubberbandCsettingscomboBox->setCurrentIndex( 4 );
+		pitchdoubleSpinBox->setValue( m_ppitch );
+		if( !m_pUseRubber ) pitchdoubleSpinBox->setValue( 0.0 );
+
+		if( m_pRubberDivider == 1.0/64.0) rubberComboBox->setCurrentIndex( 1 );
+		else if( m_pRubberDivider == 1.0/32.0) rubberComboBox->setCurrentIndex( 2 );
+		else if( m_pRubberDivider == 1.0/16.0) rubberComboBox->setCurrentIndex( 3 );
+		else if( m_pRubberDivider == 1.0/8.0) rubberComboBox->setCurrentIndex( 4 );
+		else if( m_pRubberDivider == 1.0/4.0) rubberComboBox->setCurrentIndex( 5 );
+		else if( m_pRubberDivider == 1.0/2.0) rubberComboBox->setCurrentIndex( 6 );
+		else if( m_pUseRubber && ( m_pRubberDivider >= 1.0 ) ) rubberComboBox->setCurrentIndex(  (int)(m_pRubberDivider + 6) );
+		setSamplelengthFrames();
+		checkRatioSettings();
+
+	}
+	m_pTargetSampleView->updateDisplay( pLayer );
+
+	connect( StartFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedStartFrameSpinBox(int) ) );
+	connect( LoopFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedLoopFrameSpinBox(int) ) );
+	connect( EndFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedEndFrameSpinBox(int) ) );
+	connect( LoopCountSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedLoopCountSpinBox( int ) ) );
+	connect( ProcessingTypeComboBox, SIGNAL( currentIndexChanged ( const QString )  ), this, SLOT( valueChangedProcessingTypeComboBox( const QString ) ) );
+	connect( rubberComboBox, SIGNAL( currentIndexChanged ( const QString )  ), this, SLOT( valueChangedrubberComboBox( const QString ) ) );
+	connect( rubberbandCsettingscomboBox, SIGNAL( currentIndexChanged ( const QString )  ), this, SLOT( valueChangedrubberbandCsettingscomboBox( const QString ) ) );
+	connect( pitchdoubleSpinBox, SIGNAL ( valueChanged( double )  ), this, SLOT( valueChangedpitchdoubleSpinBox( double ) ) );
+}
+
+void SampleEditor::getAllLocalFrameInfos()
+{
+	m_start_frame = StartFrameSpinBox->value();
+	m_loop_frame = LoopFrameSpinBox->value();
+	m_repeats = LoopCountSpinBox->value();
+	m_end_frame = EndFrameSpinBox->value();
+}
+
+
+
+void SampleEditor::openDisplays()
+{
+	H2Core::Instrument *pInstrument = NULL;
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	if (pSong != NULL) {
+		InstrumentList *pInstrList = pSong->get_instrument_list();
+		int nInstr = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+		if ( nInstr >= static_cast<int>(pInstrList->get_size()) ) {
+			nInstr = -1;
+		}
+
+		if (nInstr == -1) {
+			pInstrument = NULL;
+		}
+		else {
+			pInstrument = pInstrList->get( nInstr );
+			//INFOLOG( "new instr: " + pInstrument->m_sName );
+		}
+	}
+
+
+
+// wavedisplays
+	m_divider = m_pSamplefromFile->get_n_frames() / 574.0F;
+	m_pMainSampleWaveDisplay->updateDisplay( m_samplename );
+	m_pMainSampleWaveDisplay->move( 1, 1 );
+
+	m_pSampleAdjustView->updateDisplay( m_samplename );
+	m_pSampleAdjustView->move( 1, 1 );
+
+	m_pTargetSampleView->move( 1, 1 );
+
+
+}
+
+
+
+void SampleEditor::on_ClosePushButton_clicked()
+{
+	if ( !m_pSampleEditorStatus ){
+		int err = QMessageBox::information( this, "Hydrogen", tr( "Unsaved changes left. This changes will be lost. \nAre you sure?"), tr("&Ok"), tr("&Cancel"), 0, 1 );
+		if ( err == 0 ){
+			m_pSampleEditorStatus = true;
+			accept();	
+		}else
+		{
+			return;
+		}
+	}else
+	{
+		accept();
+	}
+}
+
+
+
+void SampleEditor::on_PrevChangesPushButton_clicked()
+{
+	QApplication::setOverrideCursor(Qt::WaitCursor);	
+	getAllLocalFrameInfos();	
+	createNewLayer();
+	m_pSampleEditorStatus = true;
+	QApplication::restoreOverrideCursor();	
+}
+
+
+
+bool SampleEditor::getCloseQuestion()
+{
+	bool close = false;
+	int err = QMessageBox::information( this, "Hydrogen", tr( "Close dialog! maybe there is some unsaved work on sample.\nAre you sure?"), tr("&Ok"), tr("&Cancel"), 0, 1 );
+	if ( err == 0 ) close = true;
+	
+	return close;
+}
+
+
+
+void SampleEditor::createNewLayer()
+{
+
+	if ( !m_pSampleEditorStatus ){
+
+		Sample *editSample = Sample::load_edit_wave( m_samplename,
+							    m_start_frame,
+							    m_loop_frame,
+							    m_end_frame,
+							    m_repeats,
+							    m_sample_mode,
+							    m_pUseRubber,
+							    m_pRubberDivider,
+							    m_pRubberbandCsettings,
+							    m_ppitch);
+
+		if( editSample == NULL ){
+			return;
+		}
+
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+		H2Core::Instrument *pInstrument = NULL;
+		Song *pSong = Hydrogen::get_instance()->getSong();
+		if (pSong != NULL) {
+			InstrumentList *pInstrList = pSong->get_instrument_list();
+			int nInstr = Hydrogen::get_instance()->getSelectedInstrumentNumber();
+			if ( nInstr >= static_cast<int>(pInstrList->get_size()) ) {
+				nInstr = -1;
+			}
+	
+			if (nInstr == -1) {
+				pInstrument = NULL;
+			}
+			else {
+				pInstrument = pInstrList->get( nInstr );
+			}
+		}
+	
+		H2Core::InstrumentLayer *pLayer = pInstrument->get_layer( m_pSelectedLayer );
+
+		Sample *oldSample = pLayer->get_sample();
+		delete oldSample;
+	
+		// insert new sample from newInstrument
+		pLayer->set_sample( editSample );
+
+		AudioEngine::get_instance()->unlock();
+		m_pTargetSampleView->updateDisplay( pLayer );
+		}
+		
+}
+
+
+
+void SampleEditor::mouseReleaseEvent(QMouseEvent *ev)
+{
+
+}
+
+
+
+bool SampleEditor::returnAllMainWaveDisplayValues()
+{
+	testpTimer();
+//	QMessageBox::information ( this, "Hydrogen", trUtf8 ( "jep %1" ).arg(m_pSample->get_n_frames()));
+	m_sample_is_modified = true;
+	if( m_pMainSampleWaveDisplay->__startsliderismoved ) m_start_frame = m_pMainSampleWaveDisplay->m_pStartFramePosition * m_divider - 25 * m_divider;
+	if( m_pMainSampleWaveDisplay->__loopsliderismoved ) m_loop_frame = m_pMainSampleWaveDisplay->m_pLoopFramePosition  * m_divider - 25 * m_divider;
+	if( m_pMainSampleWaveDisplay->__endsliderismoved ) m_end_frame = m_pMainSampleWaveDisplay->m_pEndFramePosition  * m_divider - 25 * m_divider ;
+	StartFrameSpinBox->setValue( m_start_frame );
+	LoopFrameSpinBox->setValue( m_loop_frame );
+	EndFrameSpinBox->setValue( m_end_frame );
+	m_ponewayStart = true;	
+	m_ponewayLoop = true;
+	m_ponewayEnd = true;
+	setSamplelengthFrames();
+
+	return true;
+}
+
+
+void SampleEditor::returnAllTargetDisplayValues()
+{
+	setSamplelengthFrames();
+	m_sample_is_modified = true;
+
+}
+
+
+
+void SampleEditor::setTrue()
+{
+	m_pSampleEditorStatus = false;
+}
+
+
+
+void SampleEditor::valueChangedStartFrameSpinBox( int )
+{
+	testpTimer();
+	m_pdetailframe = StartFrameSpinBox->value();
+	m_plineColor = "Start";
+	if ( !m_ponewayStart ){
+		m_pMainSampleWaveDisplay->m_pStartFramePosition = StartFrameSpinBox->value() / m_divider + 25 ;
+		m_pMainSampleWaveDisplay->updateDisplayPointer();
+		m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor , m_plineColor);
+		m_start_frame = StartFrameSpinBox->value();
+				
+	}else
+	{
+		m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor , m_plineColor);
+		m_ponewayStart = false;
+	}
+	testPositionsSpinBoxes();
+	m_pSampleEditorStatus = false;
+	//QMessageBox::information ( this, "Hydrogen", trUtf8 ( "jep %1" ).arg(StartFrameSpinBox->value() / m_divider + 25 ));
+	setSamplelengthFrames();
+}
+
+
+
+void SampleEditor::valueChangedLoopFrameSpinBox( int )
+{
+	testpTimer();	
+	m_pdetailframe = LoopFrameSpinBox->value();
+	m_plineColor = "Loop";
+	if ( !m_ponewayLoop ){
+		m_pMainSampleWaveDisplay->m_pLoopFramePosition = LoopFrameSpinBox->value() / m_divider + 25 ;
+		m_pMainSampleWaveDisplay->updateDisplayPointer();
+		m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor , m_plineColor);
+		m_loop_frame = LoopFrameSpinBox->value();
+	}else
+	{
+		m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor , m_plineColor);
+		m_ponewayLoop = false;
+	}
+	testPositionsSpinBoxes();
+	m_pSampleEditorStatus = false;
+	setSamplelengthFrames();
+}
+
+
+
+void SampleEditor::valueChangedEndFrameSpinBox( int )
+{
+	testpTimer();
+	m_pdetailframe = EndFrameSpinBox->value();
+	m_plineColor = "End";
+	if ( !m_ponewayEnd ){
+		m_pMainSampleWaveDisplay->m_pEndFramePosition = EndFrameSpinBox->value() / m_divider + 25 ;
+		m_pMainSampleWaveDisplay->updateDisplayPointer();
+		m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor , m_plineColor);
+		m_end_frame = EndFrameSpinBox->value();
+	}else
+	{
+		m_ponewayEnd = false;
+		m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor , m_plineColor);
+	}
+	testPositionsSpinBoxes();
+	m_pSampleEditorStatus = false;
+	setSamplelengthFrames();
+}
+
+
+
+void SampleEditor::on_PlayPushButton_clicked()
+{
+	if (PlayPushButton->text() == "Stop" ){
+		testpTimer();
+		return;
+	}
+	const int selectedlayer = InstrumentEditorPanel::get_instance()->getselectedLayer();
+	const float pan_L = 0.5f;
+	const float pan_R = 0.5f;
+	const int nLength = -1;
+	const float fPitch = 0.0f;
+	Song *pSong = Hydrogen::get_instance()->getSong();
+	
+	Instrument *pInstr = pSong->get_instrument_list()->get( Hydrogen::get_instance()->getSelectedInstrumentNumber() );
+	
+	Note *pNote = new Note( pInstr, 0, pInstr->get_layer( selectedlayer )->get_end_velocity() - 0.01, pan_L, pan_R, nLength, fPitch);
+	AudioEngine::get_instance()->get_sampler()->note_on(pNote);
+
+	setSamplelengthFrames();
+	createPositionsRulerPath();
+	m_pPlayButton = true;
+	m_pMainSampleWaveDisplay->paintLocatorEvent( StartFrameSpinBox->value() / m_divider + 24 , true);
+	m_pSampleAdjustView->setDetailSamplePosition( m_start_frame, m_pzoomfactor , 0);
+
+	if( m_pUseRubber == false ){
+		m_pTimer->start(40);	// update ruler at 25 fps
+	}
+
+
+	m_prealtimeframeend = Hydrogen::get_instance()->getRealtimeFrames() + m_pslframes;
+
+	//calculate the new rubberband sample length
+	
+//	double durationtime = 60.0 / Hydrogen::get_instance()->getNewBpmJTM() * m_pRubberDivider;
+//	double induration = (double) m_pslframes / (double) m_pSamplerate;
+//	if (induration != 0.0) m_pratio = durationtime / induration;
+	if( m_pUseRubber ){
+		m_prealtimeframeendfortarget = Hydrogen::get_instance()->getRealtimeFrames() + (m_pslframes * m_pratio + 0.1);
+	}else
+	{
+		m_prealtimeframeendfortarget = m_prealtimeframeend;
+	}
+	m_pTargetDisplayTimer->start(40);	// update ruler at 25 fps
+	PlayPushButton->setText( QString( "Stop") ); 
+	
+}
+
+
+
+void SampleEditor::on_PlayOrigPushButton_clicked()
+{
+	if (PlayOrigPushButton->text() == "Stop" ){
+		testpTimer();
+		return;
+	}
+	Sample *pNewSample = Sample::load( m_samplename );
+	if ( pNewSample ){
+		int length = ( ( pNewSample->get_n_frames() / pNewSample->get_sample_rate() + 1) * 100 );
+		AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, length );
+	}
+
+	m_pslframes = pNewSample->get_n_frames();
+	m_pMainSampleWaveDisplay->paintLocatorEvent( StartFrameSpinBox->value() / m_divider + 24 , true);
+	m_pSampleAdjustView->setDetailSamplePosition( m_start_frame, m_pzoomfactor , 0);
+	m_pTimer->start(40);	// update ruler at 25 fps	
+	m_prealtimeframeend = Hydrogen::get_instance()->getRealtimeFrames() + m_pslframes;
+	PlayOrigPushButton->setText( QString( "Stop") ); 
+}
+
+
+
+void SampleEditor::updateMainsamplePostionRuler()
+{
+	unsigned long realpos = Hydrogen::get_instance()->getRealtimeFrames();
+	if ( realpos < m_prealtimeframeend ){
+		unsigned frame = m_pslframes - ( m_prealtimeframeend  - realpos );
+		if ( m_pPlayButton == true ){
+			m_pMainSampleWaveDisplay->paintLocatorEvent( m_pPositionsRulerPath[frame] / m_divider + 25 , true);
+			m_pSampleAdjustView->setDetailSamplePosition( m_pPositionsRulerPath[frame], m_pzoomfactor , 0);
+		}else{
+			m_pMainSampleWaveDisplay->paintLocatorEvent( frame / m_divider + 25 , true);
+			m_pSampleAdjustView->setDetailSamplePosition( frame, m_pzoomfactor , 0);
+		}
+//		ERRORLOG( QString("sampleval: %1").arg(frame) );
+	}else
+	{
+		m_pMainSampleWaveDisplay->paintLocatorEvent( -1 , false);
+		m_pTimer->stop();
+		PlayPushButton->setText( QString("&Play") );
+		PlayOrigPushButton->setText( QString( "P&lay original sample") ); 
+		m_pPlayButton = false;
+	}
+}
+
+
+void SampleEditor::updateTargetsamplePostionRuler()
+{
+	unsigned long realpos = Hydrogen::get_instance()->getRealtimeFrames();
+	unsigned targetsamplelength;
+	if( m_pUseRubber ){
+		targetsamplelength =  m_pslframes * m_pratio + 0.1;
+	}else
+	{
+		targetsamplelength =  m_pslframes;
+	}
+	if ( realpos < m_prealtimeframeendfortarget ){
+		unsigned pos = targetsamplelength - ( m_prealtimeframeendfortarget - realpos );
+		m_pTargetSampleView->paintLocatorEventTargetDisplay( (841 * pos /targetsamplelength), true);
+//		ERRORLOG( QString("sampleval: %1").arg(frame) );
+	}else
+	{
+		m_pTargetSampleView->paintLocatorEventTargetDisplay( -1 , false);
+		m_pTargetDisplayTimer->stop();
+		PlayPushButton->setText(QString( "&Play") );
+		PlayOrigPushButton->setText( QString( "P&lay original sample") ); 
+		m_pPlayButton = false;
+	}
+}
+
+
+
+void SampleEditor::createPositionsRulerPath()
+{
+	setSamplelengthFrames();
+
+	unsigned onesamplelength =  m_end_frame - m_start_frame;
+	unsigned looplength =  m_end_frame - m_loop_frame;
+	unsigned repeatslength = looplength * m_repeats;
+	unsigned newlength = 0;
+	if (onesamplelength == looplength){	
+		newlength = onesamplelength + onesamplelength * m_repeats ;
+	}else
+	{
+		newlength =onesamplelength + repeatslength;
+	}
+
+	unsigned  normallength = m_pSamplefromFile->get_n_frames();
+
+	unsigned *normalframes = new unsigned[ normallength ];
+
+
+	for ( unsigned i = 0; i < normallength; i++ ) {
+		normalframes[i] = i;
+	}
+
+	unsigned *tempframes = new unsigned[ newlength ];
+	unsigned *loopframes = new unsigned[ looplength ];
+
+	QString loopmode = m_sample_mode;
+	long int z = m_loop_frame;
+	long int y = m_start_frame;
+
+	for ( unsigned i = 0; i < newlength; i++){ //first vector
+		tempframes[i] = 0;
+	}
+
+	for ( unsigned i = 0; i < onesamplelength; i++, y++){ //first vector
+
+		tempframes[i] = normalframes[y];
+	}
+
+	for ( unsigned i = 0; i < looplength; i++, z++){ //loop vector
+
+		loopframes[i] = normalframes[z];
+	}
+	
+	if ( loopmode == "reverse" ){
+		reverse(loopframes, loopframes + looplength);
+	}
+
+	if ( loopmode == "reverse" && m_repeats > 0 && m_start_frame == m_loop_frame ){
+		reverse( tempframes, tempframes + onesamplelength );		
+		}
+
+	if ( loopmode == "pingpong" &&  m_start_frame == m_loop_frame){
+		reverse(loopframes, loopframes + looplength);
+	}
+	
+	for ( int i = 0; i< m_repeats ;i++){			
+		unsigned tempdataend = onesamplelength + ( looplength * i );
+		if ( m_start_frame == m_loop_frame ){
+			copy( loopframes, loopframes+looplength ,tempframes+ tempdataend );
+		}
+		if ( loopmode == "pingpong" && m_repeats > 1){
+			reverse(loopframes, loopframes + looplength);
+		}
+		if ( m_start_frame != m_loop_frame ){		
+			copy( loopframes, loopframes+looplength ,tempframes+ tempdataend );
+		}
+
+	}
+
+	
+	if ( m_repeats == 0 && loopmode == "reverse" ){
+		reverse( tempframes + m_loop_frame, tempframes + newlength);		
+	}
+
+	m_pPositionsRulerPath = tempframes;
+}
+
+
+
+void SampleEditor::setSamplelengthFrames()
+{
+	getAllLocalFrameInfos();
+	unsigned onesamplelength =  m_end_frame - m_start_frame;
+	unsigned looplength =  m_end_frame - m_loop_frame ;
+	unsigned repeatslength = looplength * m_repeats;
+	unsigned newlength = 0;
+	if (onesamplelength == looplength){	
+		newlength = onesamplelength + onesamplelength * m_repeats ;
+	}else
+	{
+		newlength =onesamplelength + repeatslength;
+	}
+	m_pslframes = newlength;
+	newlengthLabel->setText(QString("new sample length: %1 frames").arg(newlength));
+	checkRatioSettings();
+}
+
+
+
+void SampleEditor::valueChangedLoopCountSpinBox( int )
+{
+	testpTimer();
+	if ( m_pslframes > Hydrogen::get_instance()->getAudioOutput()->getSampleRate() * 60 ){
+		AudioEngine::get_instance()->get_sampler()->stop_playing_notes();
+		m_pMainSampleWaveDisplay->paintLocatorEvent( -1 , false);
+		m_pTimer->stop();
+		m_pPlayButton = false;
+	}
+	m_repeats = LoopCountSpinBox->value() ;
+	m_pSampleEditorStatus = false;
+	setSamplelengthFrames();
+	if ( m_pslframes > Hydrogen::get_instance()->getAudioOutput()->getSampleRate() * 60 * 30){ // >30 min
+		LoopCountSpinBox->setMaximum(LoopCountSpinBox->value() -1);	
+	}
+	
+}
+
+
+
+void SampleEditor::valueChangedrubberbandCsettingscomboBox( const QString  )
+{
+	m_pRubberbandCsettings = rubberbandCsettingscomboBox->currentIndex();
+	m_pSampleEditorStatus = false;
+}
+
+
+
+void SampleEditor::valueChangedpitchdoubleSpinBox( double )
+{
+	m_ppitch = pitchdoubleSpinBox->value();
+	m_pSampleEditorStatus = false;
+}
+
+
+void SampleEditor::valueChangedrubberComboBox( const QString  )
+{
+
+	if( rubberComboBox->currentText() != "off" ){
+		m_pUseRubber = true;
+	}else
+	{
+		m_pUseRubber = false;
+		m_pRubberDivider = 1.0;
+	}
+
+
+	switch ( rubberComboBox->currentIndex() ){
+	case 0 :// 
+		m_pRubberDivider = 4.0;
+		break;
+	case 1 :// 
+		m_pRubberDivider = 1.0/64.0;
+		break;
+	case 2 :// 
+		m_pRubberDivider = 1.0/32.0;
+		break;
+	case 3 :// 
+		m_pRubberDivider = 1.0/16.0;
+		break;
+	case 4 :// 
+		m_pRubberDivider = 1.0/8.0;
+		break;
+	case 5 :// 
+		m_pRubberDivider = 1.0/4.0;
+		break;
+	case 6 :// 
+		m_pRubberDivider = 1.0/2.0;
+		break;
+	case 7 :// 
+		m_pRubberDivider = 1.0;
+		break;
+	default:
+		m_pRubberDivider = (float)rubberComboBox->currentIndex() - 6.0;
+	}
+//	QMessageBox::information ( this, "Hydrogen", trUtf8 ( "divider %1" ).arg( m_pRubberDivider ));
+//	float m_pRubberDivider;
+	setSamplelengthFrames();
+
+
+	m_pSampleEditorStatus = false;
+}
+
+void SampleEditor::checkRatioSettings()
+{
+
+	//calculate ration 
+	double durationtime = 60.0 / Hydrogen::get_instance()->getNewBpmJTM() * m_pRubberDivider;
+	double induration = (double) m_pslframes / (double) m_pSamplerate;
+	if (induration != 0.0) m_pratio = durationtime / induration;
+
+	//my personal ratio quality settings
+	//ratios < 0.1 || > 3.0 are bad (red) or experimental sounds
+	//ratios > 0.1 - 0.5 || > 2.0 are middle (yellow)
+	//ratios < 0.5 || < 2.0 are good (green)
+
+	bool is_green = false;
+	//green ratio
+	if( (m_pratio >= 0.5) && (m_pratio <= 2.0) ){
+		rubberComboBox->setStyleSheet("QComboBox { background-color: green; }");
+		is_green = true;
+	}
+	//yellow ratio
+	if( ( (m_pratio > 0.1) || ( m_pratio <=  3.0 ) )&& (!is_green)){
+		rubberComboBox->setStyleSheet("QComboBox { background-color: yellow; }");
+	}
+	//red ratio
+	if( ( m_pratio <= 0.1 ) || ( m_pratio > 3.0 ) && (!is_green) ){
+		rubberComboBox->setStyleSheet("QComboBox { background-color: red; }");
+	}
+	QString text = QString( " RB-Ratio = %1").arg(m_pratio);
+	ratiolabel->setText( text );
+
+	//no rubberband = default
+	if( !m_pUseRubber ){
+		rubberComboBox->setStyleSheet("QComboBox { background-color: 58, 62, 72; }");
+		ratiolabel->setText( "" );
+	}
+}
+
+
+void SampleEditor::valueChangedProcessingTypeComboBox( const QString unused )
+{
+	switch ( ProcessingTypeComboBox->currentIndex() ){
+		case 0 :// 
+			m_sample_mode = "forward";
+			break;
+		case 1 :// 
+			m_sample_mode = "reverse";
+			break;
+		case 2 :// 
+			m_sample_mode = "pingpong";
+			break;
+		default:
+			m_sample_mode = "forward";
+	}
+	m_pSampleEditorStatus = false;
+}
+
+
+
+void SampleEditor::on_verticalzoomSlider_valueChanged( int value )
+{
+	m_pzoomfactor = value / 10 +1;
+	m_pSampleAdjustView->setDetailSamplePosition( m_pdetailframe, m_pzoomfactor, m_plineColor );
+}
+
+
+
+void SampleEditor::testPositionsSpinBoxes()
+{
+	if (  m_start_frame > m_loop_frame ) m_loop_frame = m_start_frame;
+	if (  m_start_frame > m_end_frame ) m_end_frame = m_start_frame;
+	if (  m_loop_frame > m_end_frame ) m_end_frame = m_loop_frame;
+	if (  m_end_frame < m_loop_frame ) m_loop_frame = m_end_frame;
+	if (  m_end_frame < m_start_frame ) m_start_frame = m_end_frame;
+	StartFrameSpinBox->setValue( m_start_frame );
+	LoopFrameSpinBox->setValue( m_loop_frame );
+	EndFrameSpinBox->setValue( m_end_frame );
+}
+
+
+
+void SampleEditor::testpTimer()
+{
+	if ( m_pTimer->isActive() || m_pTargetDisplayTimer->isActive() ){
+		m_pMainSampleWaveDisplay->paintLocatorEvent( -1 , false);
+		m_pTimer->stop();
+		m_pTargetDisplayTimer->stop();
+		PlayPushButton->setText( QString( "&Play" ) );
+		PlayOrigPushButton->setText( QString( "P&lay original sample") ); 
+		AudioEngine::get_instance()->get_sampler()->stop_playing_notes();
+		m_pPlayButton = false;
+	}
+}
Index: /branches/tabbedInterface/gui/src/SampleEditor/DetailWaveDisplay.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/DetailWaveDisplay.cpp	(revision 1060)
+++ /branches/tabbedInterface/gui/src/SampleEditor/DetailWaveDisplay.cpp	(revision 1060)
@@ -0,0 +1,156 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "config.h"
+
+#include <hydrogen/sample.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/instrument.h>
+using namespace H2Core;
+
+#include "DetailWaveDisplay.h"
+#include "../Skin.h"
+
+
+DetailWaveDisplay::DetailWaveDisplay(QWidget* pParent )
+ : QWidget( pParent )
+ , Object( "DetailWaveDisplay" )
+ , m_sSampleName( "" )
+{
+//	setAttribute(Qt::WA_NoBackground);
+
+	//INFOLOG( "INIT" );
+	int w = 180;
+	int h = 265;
+	resize( w, h );
+
+	bool ok = m_background.load( Skin::getImagePath() + "/waveDisplay/detailsamplewavedisplay.png" );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	m_pnormalimagedetailframes = 180;	
+	m_pDetailSamplePosition = 0;
+	m_pzoomFactor = 1;
+
+}
+
+
+
+
+DetailWaveDisplay::~DetailWaveDisplay()
+{
+	//INFOLOG( "DESTROY" );
+	delete[] m_pPeakDatal;
+	delete[] m_pPeakDatar;
+}
+
+
+void DetailWaveDisplay::setDetailSamplePosition( unsigned posi, float zoomfactor, QString type)
+{
+	m_pDetailSamplePosition = posi ;
+	m_pzoomFactor = zoomfactor;
+	m_ptype = type;
+	update();
+}
+
+void DetailWaveDisplay::paintEvent(QPaintEvent *ev)
+{
+	QPainter painter( this );
+	painter.setRenderHint( QPainter::HighQualityAntialiasing );
+	painter.drawPixmap( ev->rect(), m_background, ev->rect() );
+
+	painter.setPen( QColor( 230, 230, 230 ) );
+	int VCenterl = height() / 4;
+	int VCenterr = height() / 4 + height() / 2;
+
+//	int imagedetailframes = m_pnormalimagedetailframes / m_pzoomFactor;
+	int startpos = m_pDetailSamplePosition  - m_pnormalimagedetailframes / 2 ;
+
+	for ( int x = 0; x < width() ; x++ ) {
+		if ( (startpos) > 0 ){
+			painter.drawLine( x, (-m_pPeakDatal[startpos -1] *m_pzoomFactor) +VCenterl, x, (-m_pPeakDatal[startpos ] *m_pzoomFactor)+VCenterl );
+			painter.drawLine( x, (-m_pPeakDatar[startpos -1] *m_pzoomFactor) +VCenterr, x, (-m_pPeakDatar[startpos ] *m_pzoomFactor)+VCenterr );
+			//ERRORLOG( QString("startpos: %1").arg(startpos) )
+		}
+		else
+		{
+			painter.drawLine( x, 0 +VCenterl, x, 0+VCenterl );
+			painter.drawLine( x, 0 +VCenterr, x, 0+VCenterr );
+		}
+		startpos++;
+		
+	}
+
+
+	painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::DotLine ) );
+	painter.drawLine( 0, VCenterl, width(),VCenterl );
+	painter.drawLine( 0, VCenterr, width(),VCenterr );
+	QColor _color;
+	if ( m_ptype == "Start" )
+		 _color = QColor( 32, 173, 0 );
+	else if ( m_ptype == "Loop" )
+		_color = QColor( 93, 170, 254 );
+	else if ( m_ptype == "End" )
+		_color = QColor( 217, 68, 0 );
+	else 
+		_color = QColor(  255, 255, 255 );
+
+	painter.setPen( QPen( _color, 1, Qt::SolidLine ) );
+	painter.drawLine( 90, 0, 90,265 );
+}
+
+
+
+void DetailWaveDisplay::updateDisplay( QString filename )
+{
+
+	Sample *pNewSample = Sample::load( filename );
+
+	if ( pNewSample ) {
+
+		int mSampleLength = pNewSample->get_n_frames();
+
+		m_pPeakDatal = new int[ mSampleLength + m_pnormalimagedetailframes /2 ];
+		m_pPeakDatar = new int[ mSampleLength + m_pnormalimagedetailframes /2 ];
+
+		for ( int i = 0 ; i < mSampleLength + m_pnormalimagedetailframes /2 ; i++){
+			m_pPeakDatal[ i ] = 0;
+			m_pPeakDatar[ i ] = 0;
+		}
+
+		float fGain = height() / 4.0 * 1.0;
+
+		float *pSampleDatal = pNewSample->get_data_l();
+		float *pSampleDatar = pNewSample->get_data_r();
+
+		for ( int i = 0; i < mSampleLength; i++ ){
+			m_pPeakDatal[ i ] = static_cast<int>( pSampleDatal[ i ] * fGain );
+			m_pPeakDatar[ i ] = static_cast<int>( pSampleDatar[ i ] * fGain );
+		}
+
+
+	}
+	delete pNewSample;
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor.h
===================================================================
--- /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor.h	(revision 1497)
+++ /branches/tabbedInterface/gui/src/SampleEditor/SampleEditor.h	(revision 1497)
@@ -0,0 +1,140 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SAMPLEEDITOR_H
+#define SAMPLEEDITOR_H
+
+#include "config.h"
+#include "ui_SampleEditor_UI.h"
+#include "../InstrumentEditor/InstrumentEditor.h"
+
+#include <QDialog>
+#include <hydrogen/Object.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/sample.h>
+#include <hydrogen/instrument.h>
+
+
+class Button;
+class 	MainSampleWaveDisplay;
+class	TargetWaveDisplay;
+class	DetailWaveDisplay;
+
+///
+/// This dialog is used to preview audiofiles
+///
+class SampleEditor : public QDialog, public Ui_SampleEditor_UI, public Object
+
+{
+	Q_OBJECT
+	public:
+		
+		SampleEditor( QWidget* pParent, int nSelectedLayer, QString nSampleFilename );
+		~SampleEditor();
+
+		void setSampleName( QString name);
+		bool getCloseQuestion();
+		bool m_pSampleEditorStatus;
+		bool returnAllMainWaveDisplayValues();
+		void returnAllTargetDisplayValues();
+		void setTrue();
+
+		//this values come from the real sample to restore a frm song loaded sample
+		bool m_sample_is_modified;	///< true if sample is modified
+		QString m_sample_mode;		///< loop mode
+		int m_repeats;			///< repats from the loop section
+		unsigned m_start_frame;		///< start frame
+		unsigned m_loop_frame;		///< beginn of the loop section
+		unsigned m_end_frame; 		///< sample end frame
+
+
+	private slots:
+		void valueChangedLoopCountSpinBox( int );
+		void valueChangedProcessingTypeComboBox( const QString );
+		void valueChangedrubberComboBox( const QString  );
+		void valueChangedrubberbandCsettingscomboBox( const QString );
+		void valueChangedpitchdoubleSpinBox( double );
+		void on_ClosePushButton_clicked();
+		void on_PrevChangesPushButton_clicked();
+		void valueChangedStartFrameSpinBox( int );
+		void valueChangedLoopFrameSpinBox( int );
+		void valueChangedEndFrameSpinBox( int );
+		void on_PlayPushButton_clicked();
+		void on_PlayOrigPushButton_clicked();
+		void on_verticalzoomSlider_valueChanged ( int value );
+		void updateMainsamplePostionRuler();
+		void updateTargetsamplePostionRuler();
+
+
+
+	private:
+
+		H2Core::Sample *m_pSamplefromFile;
+		int m_pSelectedLayer;
+		QString m_samplename;
+	
+		double m_divider;
+
+		void openDisplays();
+		void getAllFrameInfos();
+		void getAllLocalFrameInfos();
+		void setAllSampleProps();
+		void testPositionsSpinBoxes();
+		void createNewLayer();
+		void setSamplelengthFrames();
+		void createPositionsRulerPath();
+		void testpTimer();
+		void closeEvent(QCloseEvent *event);
+		void checkRatioSettings();
+
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+	
+		MainSampleWaveDisplay *m_pMainSampleWaveDisplay;
+		TargetWaveDisplay *m_pTargetSampleView;
+		DetailWaveDisplay *m_pSampleAdjustView; 
+
+		float m_pzoomfactor;
+		unsigned m_pdetailframe;
+		QString m_plineColor;
+		bool m_ponewayStart;
+		bool m_ponewayLoop;
+		bool m_ponewayEnd;
+		unsigned long m_prealtimeframeend;
+		unsigned long m_prealtimeframeendfortarget;
+		unsigned m_pslframes;
+		unsigned m_pSamplerate;
+		QTimer *m_pTimer;
+		QTimer *m_pTargetDisplayTimer;
+		unsigned *m_pPositionsRulerPath;
+		bool m_pPlayButton;
+		bool m_pUseRubber;
+		float m_pRubberDivider;
+		float m_pratio;
+		float m_ppitch;
+		int m_pRubberbandCsettings;
+
+		
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/precompiled.h
===================================================================
--- /branches/tabbedInterface/gui/src/precompiled.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/precompiled.h	(revision 377)
@@ -0,0 +1,42 @@
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cstdio>
+#include <cassert>
+#include <cmath>
+
+#include <pthread.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+// STL
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+
+// QT
+#include <QtGui>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cstdio>
+#include <cassert>
+#include <cmath>
+
+#include <pthread.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+// STL
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+
+// QT
+#include <QLibrary>
+#include <QDir>
+
+
Index: /branches/tabbedInterface/gui/src/SongPropertiesDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/SongPropertiesDialog.h	(revision 162)
+++ /branches/tabbedInterface/gui/src/SongPropertiesDialog.h	(revision 162)
@@ -0,0 +1,50 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SONG_PROPERTIES_DIALOG_H
+#define SONG_PROPERTIES_DIALOG_H
+
+#include "config.h"
+
+#include "ui_SongPropertiesDialog_UI.h"
+#include "HydrogenApp.h"
+
+/**
+ * Song Properties Dialog
+ */
+class SongPropertiesDialog : public QDialog, private Ui_SongPropertiesDialog_UI
+{
+	Q_OBJECT
+
+	public:
+		SongPropertiesDialog(QWidget* parent);
+		~SongPropertiesDialog();
+
+	private slots:
+		void on_cancelBtn_clicked();
+		void on_okBtn_clicked();
+
+};
+
+#endif
+
+
Index: /branches/tabbedInterface/gui/src/LadspaFXSelector.h
===================================================================
--- /branches/tabbedInterface/gui/src/LadspaFXSelector.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/LadspaFXSelector.h	(revision 377)
@@ -0,0 +1,72 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef LADSPA_FX_SELECTOR_H
+#define LADSPA_FX_SELECTOR_H
+
+#include "config.h"
+
+#include "ui_LadspaFXSelector_UI.h"
+
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+#include <string>
+#include <vector>
+
+namespace H2Core {
+	class LadspaFXInfo;
+	class LadspaFXGroup;
+}
+
+class LadspaFXSelector : public QDialog, public Ui_LadspaFXSelector_UI, public Object
+{
+	Q_OBJECT
+
+	public:
+		LadspaFXSelector(int nLadspaFX);
+		~LadspaFXSelector();
+
+		QString getSelectedFX();
+
+	private slots:
+		void on_m_pGroupsListView_currentItemChanged( QTreeWidgetItem * current, QTreeWidgetItem * previous );
+		void pluginSelected();
+
+	private:
+		QTreeWidgetItem* m_pCurrentItem;
+		QString m_sSelectedPluginName;
+		void buildLadspaGroups();
+
+#ifdef LADSPA_SUPPORT
+		void addGroup(QTreeWidgetItem *parent, H2Core::LadspaFXGroup *pGroup);
+		void addGroup( QTreeWidget *parent, H2Core::LadspaFXGroup *pGroup );
+		void buildGroup(QTreeWidgetItem *pNewItem, H2Core::LadspaFXGroup *pGroup);
+
+		std::vector<H2Core::LadspaFXInfo*> findPluginsInGroup( const QString& sSelectedGroup, H2Core::LadspaFXGroup *pGroup );
+#endif
+
+};
+
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/PatternFillDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternFillDialog.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/PatternFillDialog.h	(revision 377)
@@ -0,0 +1,75 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PATTERN_FILL_DIALOG_H
+#define PATTERN_FILL_DIALOG_H
+
+#include "config.h"
+
+#include <QtGui>
+#include "ui_PatternFillDialog_UI.h"
+
+#include <hydrogen/Object.h>
+
+namespace H2Core
+{
+	class Pattern;
+}
+
+struct FillRange {
+
+        int fromVal;
+        int toVal;
+        bool bInsert;
+};
+
+
+///
+/// Pattern Fill Dialog
+///
+class PatternFillDialog : public QDialog, public Ui_PatternFillDialog_UI, public Object
+{
+	Q_OBJECT
+	public:
+		PatternFillDialog( QWidget* parent, FillRange* range );
+		~PatternFillDialog();
+
+	private slots:
+		void on_cancelBtn_clicked();
+		void on_okBtn_clicked();
+		void on_fromText_textChanged(const QString & text);
+		void on_toText_textChanged(const QString & text);
+
+	private:
+		H2Core::Pattern* __pattern;
+		FillRange* __fill_range;
+
+		/// Does some name check
+		void __text_changed();
+
+
+};
+
+
+#endif
+
+
Index: /branches/tabbedInterface/gui/src/InstrumentRack.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/InstrumentRack.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/InstrumentRack.cpp	(revision 1244)
@@ -0,0 +1,129 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "InstrumentRack.h"
+#include "Skin.h"
+#include "widgets/Button.h"
+#include "InstrumentEditor/InstrumentEditorPanel.h"
+#include "SoundLibrary/SoundLibraryPanel.h"
+
+#include <QGridLayout>
+
+
+InstrumentRack::InstrumentRack( QWidget *pParent )
+ : QWidget( pParent )
+ , Object( "InstrumentRack" )
+{
+	INFOLOG( "INIT" );
+
+	resize( 290, 450 );
+	setMinimumSize( width(), height() );
+	setFixedWidth( width() );
+
+
+// TAB buttons
+	QWidget *pTabButtonsPanel = new QWidget( NULL );
+	pTabButtonsPanel->setFixedHeight( 24 );
+	pTabButtonsPanel->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
+
+	// instrument editor button
+	m_pShowInstrumentEditorBtn = new ToggleButton(
+			pTabButtonsPanel,
+			"/instrumentEditor/instrument_show_on.png",
+			"/instrumentEditor/instrument_show_off.png",
+			"/instrumentEditor/instrument_show_off.png",
+			QSize( 130, 24 )
+	);
+	m_pShowInstrumentEditorBtn->setToolTip( trUtf8( "Show Instrument editor" ) );
+	m_pShowInstrumentEditorBtn->setText( trUtf8( "Instrument" ) );
+	connect( m_pShowInstrumentEditorBtn, SIGNAL( clicked( Button* ) ), this, SLOT( on_showInstrumentEditorBtnClicked() ) );
+
+	// show sound library button
+	m_pShowSoundLibraryBtn = new ToggleButton(
+			pTabButtonsPanel,
+			"/instrumentEditor/library_show_on.png",
+			"/instrumentEditor/library_show_off.png",
+			"/instrumentEditor/library_show_off.png",
+			QSize( 150, 24 )
+	);
+	m_pShowSoundLibraryBtn->setToolTip( trUtf8( "Show sound library" ) );
+	m_pShowSoundLibraryBtn->setText( trUtf8( "Sound library" ) );
+	connect( m_pShowSoundLibraryBtn, SIGNAL( clicked( Button* ) ), this, SLOT( on_showSoundLibraryBtnClicked() ) );
+
+	QHBoxLayout *pTabHBox = new QHBoxLayout();
+	pTabHBox->setSpacing( 0 );
+	pTabHBox->setMargin( 0 );
+	pTabHBox->addWidget( m_pShowInstrumentEditorBtn );
+	pTabHBox->addWidget( m_pShowSoundLibraryBtn );
+
+	pTabButtonsPanel->setLayout( pTabHBox );
+
+//~ TAB buttons
+
+
+	InstrumentEditorPanel::get_instance()->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
+
+	m_pSoundLibraryPanel = new SoundLibraryPanel( NULL );
+
+	// LAYOUT
+	QGridLayout *pGrid = new QGridLayout();
+	pGrid->setSpacing( 0 );
+	pGrid->setMargin( 0 );
+
+	pGrid->addWidget( pTabButtonsPanel, 0, 0, 1, 3 );
+	pGrid->addWidget( InstrumentEditorPanel::get_instance(), 2, 1 );
+	pGrid->addWidget( m_pSoundLibraryPanel, 2, 1 );
+
+	this->setLayout( pGrid );
+
+	on_showInstrumentEditorBtnClicked();	// show the instrument editor as default
+}
+
+
+
+InstrumentRack::~InstrumentRack()
+{
+	INFOLOG( "DESTROY" );
+}
+
+
+
+void InstrumentRack::on_showSoundLibraryBtnClicked()
+{
+	m_pShowSoundLibraryBtn->setPressed( true );
+	m_pShowInstrumentEditorBtn->setPressed( false );
+
+	m_pSoundLibraryPanel->show();
+	InstrumentEditorPanel::get_instance()->hide();
+}
+
+
+
+void InstrumentRack::on_showInstrumentEditorBtnClicked()
+{
+	m_pShowInstrumentEditorBtn->setPressed( true );
+	m_pShowSoundLibraryBtn->setPressed( false );
+
+	InstrumentEditorPanel::get_instance()->show();
+	m_pSoundLibraryPanel->hide();
+}
+
Index: /branches/tabbedInterface/gui/src/Skin.h
===================================================================
--- /branches/tabbedInterface/gui/src/Skin.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/Skin.h	(revision 377)
@@ -0,0 +1,43 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef H2_SKIN_H
+#define H2_SKIN_H
+
+#include <QString>
+#include <hydrogen/data_path.h>
+
+///
+/// Skin support
+///
+class Skin
+{
+	public:
+		static QString getImagePath()
+		{
+			QString sSkin = "gray";
+			return QString( H2Core::DataPath::get_data_path() ).append( "/img/" ).append( sSkin );
+		}
+
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/VirtualPatternDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/VirtualPatternDialog.h	(revision 1318)
+++ /branches/tabbedInterface/gui/src/VirtualPatternDialog.h	(revision 1318)
@@ -0,0 +1,64 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef VIRTUAL_PATTERN_DIALOG_H
+#define VIRTUAL_PATTERN_DIALOG_H
+
+#include "config.h"
+
+#include <QtGui>
+#include "ui_VirtualPatternDialog_UI.h"
+
+#include <hydrogen/Object.h>
+
+namespace H2Core
+{
+	class Pattern;
+	class PatternList;
+}
+
+
+///
+/// Virtual Pattern Dialog
+///
+class VirtualPatternDialog : public QDialog, public Ui_VirtualPatternDialog_UI, public Object
+{
+	Q_OBJECT
+	public:
+		VirtualPatternDialog( QWidget* parent );
+		~VirtualPatternDialog();
+		static void computeVirtualPatternTransitiveClosure(H2Core::PatternList *pPatternList);
+
+	private slots:
+		void on_cancelBtn_clicked();
+		void on_okBtn_clicked();
+
+	private:
+
+
+
+};
+
+
+#endif
+
+
Index: /branches/tabbedInterface/gui/src/MainForm.h
===================================================================
--- /branches/tabbedInterface/gui/src/MainForm.h	(revision 1505)
+++ /branches/tabbedInterface/gui/src/MainForm.h	(revision 1505)
@@ -0,0 +1,154 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef MAINFORM_H
+#define MAINFORM_H
+
+#include <QtNetwork>
+#include <QtGui>
+
+#include <map>
+
+#include "EventListener.h"
+#include "config.h"
+
+#include <hydrogen/Object.h>
+
+class HydrogenApp;
+
+///
+/// Main window
+///
+class MainForm : public QMainWindow, public EventListener, public Object
+{
+	Q_OBJECT
+
+	public:
+		QApplication* m_pQApp;
+
+		MainForm( QApplication *app, const QString& songFilename );
+		~MainForm();
+
+		void updateRecentUsedSongList();
+
+		virtual void errorEvent( int nErrorCode );
+		static void usr1SignalHandler(int unused);
+
+
+	public slots:
+		void showPreferencesDialog();
+		void showUserManual();
+
+		void action_file_new();
+		void action_file_open();
+		void action_file_openDemo();
+		void action_file_save();
+		void action_file_save_as();
+		void action_file_openPattern();
+		void action_file_export_pattern_as();
+		bool action_file_exit();
+
+		void action_file_export();
+		void action_file_export_midi();
+		void action_file_songProperties();
+
+		void action_help_about();
+
+		void action_instruments_addInstrument();
+		void action_instruments_clearAll();
+		void action_instruments_saveLibrary();
+		void action_instruments_exportLibrary();
+		void action_instruments_importLibrary();
+
+
+		void action_window_showMixer();
+		void action_window_showPlaylistDialog();
+		void action_window_show_MetronWidget();
+		void action_window_showSongEditor();
+		void action_window_showPatternEditor();
+		void action_window_showDrumkitManagerPanel();
+
+		void action_debug_printObjects();
+		void action_debug_showAudioEngineInfo();
+
+		void closeEvent( QCloseEvent* ev );
+
+		void onPlayStopAccelEvent();
+		void onRestartAccelEvent();
+		void onBPMPlusAccelEvent();
+		void onBPMMinusAccelEvent();
+		void onSaveAsAccelEvent();
+		void onSaveAccelEvent();
+		void onOpenAccelEvent();
+
+		void action_file_open_recent( QAction *pAction );
+		void showDevelWarning();
+		void onLashPollTimer();
+
+		void handleSigUsr1();
+
+	private slots:
+		void onAutoSaveTimer();
+		void onPlaylistDisplayTimer();
+
+	protected:
+		// Returns true if handled, false if aborted.
+		bool handleUnsavedChanges();
+
+	private:
+		HydrogenApp* h2app;
+
+		static int sigusr1Fd[2];
+		QSocketNotifier *snUsr1;
+
+
+
+		QMenu *m_pRecentFilesMenu;
+		QAction *m_pRecentFileAction0;
+		QAction *m_pRecentFileAction1;
+		QAction *m_pRecentFileAction2;
+		QAction *m_pRecentFileAction3;
+		QAction *m_pRecentFileAction4;
+
+		QHttp m_http;
+
+		QTimer m_autosaveTimer;
+
+		/** Create the menubar */
+		void createMenuBar();
+
+		void closeAll();
+		void openSongFile( const QString& sFilename );
+
+		bool eventFilter( QObject *o, QEvent *e );
+
+		std::map<int,int>  keycodeInstrumentMap;
+		void initKeyInstMap();
+
+		QString getAutoSaveFilename();
+	#ifdef LASH_SUPPORT
+		QTimer *lashPollTimer;
+	#endif
+
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/PatternPropertiesDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/PatternPropertiesDialog.h	(revision 1129)
+++ /branches/tabbedInterface/gui/src/PatternPropertiesDialog.h	(revision 1129)
@@ -0,0 +1,65 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PATTERN_PROPERTIES_DIALOG_H
+#define PATTERN_PROPERTIES_DIALOG_H
+
+#include "config.h"
+
+#include <QtGui>
+#include "ui_PatternPropertiesDialog_UI.h"
+
+namespace H2Core
+{
+	class Pattern;
+}
+
+///
+///Pattern Properties Dialog
+///
+class PatternPropertiesDialog : public QDialog, public Ui_PatternPropertiesDialog_UI
+{
+	Q_OBJECT
+	public:
+		PatternPropertiesDialog( QWidget* parent, H2Core::Pattern* pattern, bool save );
+
+		~PatternPropertiesDialog();
+
+		/// Does some name check
+		static bool nameCheck( QString );
+		void defaultNameCheck( QString , bool);
+
+	private slots:
+		void on_cancelBtn_clicked();
+		void on_okBtn_clicked();
+		void on_patternNameTxt_textChanged();
+		void on_categoryComboBox_editTextChanged();
+
+	private:
+		H2Core::Pattern *pattern;
+
+};
+
+
+#endif
+
+
Index: /branches/tabbedInterface/gui/src/LadspaFXProperties.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/LadspaFXProperties.cpp	(revision 1367)
+++ /branches/tabbedInterface/gui/src/LadspaFXProperties.cpp	(revision 1367)
@@ -0,0 +1,437 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/Song.h>
+#include <hydrogen/fx/Effects.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/IO/AudioOutput.h>
+
+
+#include "LadspaFXProperties.h"
+#include "HydrogenApp.h"
+#include "LadspaFXSelector.h"
+#include "Skin.h"
+#include "widgets/Fader.h"
+#include "widgets/LCD.h"
+
+#include "Mixer/Mixer.h"
+#include "Mixer/MixerLine.h"
+
+using namespace std;
+using namespace H2Core;
+
+LadspaFXProperties::LadspaFXProperties(QWidget* parent, uint nLadspaFX)
+ : QWidget( parent )
+ , Object( "LadspaFXProperties" )
+{
+//	INFOLOG( "INIT" );
+
+	m_nLadspaFX = nLadspaFX;
+
+	resize( 500, 200 );
+	setMinimumSize( width(), height() );
+	setFixedHeight( height() );
+	setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	QHBoxLayout *hbox = new QHBoxLayout();
+	hbox->setSpacing( 0 );
+	hbox->setMargin( 0 );
+	setLayout( hbox );
+
+
+	// Background image
+	QPixmap background;
+	bool ok = background.load( Skin::getImagePath() + "/mixerPanel/mixer_background.png" );
+	if( !ok ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+
+	m_pScrollArea = new QScrollArea( NULL );
+	hbox->addWidget( m_pScrollArea );
+
+	m_pScrollArea->move( 0, 0 );
+	m_pScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pScrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
+	m_pScrollArea->resize( width(), height() );
+
+	m_pFrame = new QFrame( this );
+	m_pFrame->resize( width(), height() );
+
+	m_pScrollArea->setWidget( m_pFrame );
+
+	m_pNameLbl = new QLabel(this);
+	m_pNameLbl->move( 10, 10 );
+	m_pNameLbl->resize( 270, 24 );
+
+	QFont boldFont;
+	boldFont.setBold(true);
+	m_pNameLbl->setFont( boldFont );
+
+	m_pSelectFXBtn = new QPushButton( trUtf8("Select FX"), this);
+	m_pSelectFXBtn->move( 280, 10 );
+	m_pSelectFXBtn->resize( 100, 24 );
+	connect( m_pSelectFXBtn, SIGNAL(clicked()), this, SLOT(selectFXBtnClicked()) );
+
+
+	m_pActivateBtn = new QPushButton( trUtf8("Activate"), this);
+	m_pActivateBtn->move( 390, 10 );
+	m_pActivateBtn->resize( 100, 24 );
+	connect( m_pActivateBtn, SIGNAL(clicked()), this, SLOT(activateBtnClicked()) );
+
+
+	m_pTimer = new QTimer( this );
+	connect(m_pTimer, SIGNAL( timeout() ), this, SLOT( updateOutputControls() ) );
+}
+
+
+LadspaFXProperties::~LadspaFXProperties()
+{
+//	INFOLOG( "DESTROY" );
+}
+
+
+
+void LadspaFXProperties::showEvent ( QShowEvent* )
+{
+	updateControls();
+}
+
+
+
+void LadspaFXProperties::closeEvent( QCloseEvent *ev )
+{
+	ev->accept();
+}
+
+
+void LadspaFXProperties::faderChanged( Fader * ref )
+{
+	ref->setPeak_L( ref->getValue() );
+	ref->setPeak_R( ref->getValue() );
+
+	Song *pSong = (Hydrogen::get_instance() )->getSong();
+
+#ifdef LADSPA_SUPPORT
+	LadspaFX *pFX = Effects::get_instance()->getLadspaFX( m_nLadspaFX );
+
+	for ( uint i = 0; i < m_pInputControlFaders.size(); i++ ) {
+		if (ref == m_pInputControlFaders[ i ] ) {
+			LadspaControlPort *pControl = pFX->inputControlPorts[ i ];
+
+			pControl->fControlValue = ref->getValue();
+			//float fInterval = pControl->fUpperBound - pControl->fLowerBound;
+			//pControl->fControlValue = pControl->fLowerBound + fValue * fInterval;
+
+			QString sValue;
+			if (pControl->fControlValue < 1.0 ) {
+				sValue = QString("%1").arg( pControl->fControlValue, 0, 'f', 2 );
+			}
+			else if ( pControl->fControlValue < 100.0 ) {
+				sValue = QString("%1").arg( pControl->fControlValue, 0, 'f', 1 );
+			}
+			else {
+				sValue = QString("%1").arg( pControl->fControlValue, 0, 'f', 0 );
+			}
+			m_pInputControlLabel[ i ]->setText( sValue );
+		}
+	}
+	pSong->__is_modified = true;
+#endif
+}
+
+
+
+void LadspaFXProperties::updateControls()
+{
+#ifdef LADSPA_SUPPORT
+	INFOLOG( "*** [updateControls] ***" );
+	m_pTimer->stop();
+
+	LadspaFX *pFX = Effects::get_instance()->getLadspaFX( m_nLadspaFX );
+
+	// svuoto i vettori..
+	if ( m_pInputControlNames.size() != 0 ) {
+		for (uint i = 0; i < m_pInputControlNames.size(); i++) {
+			delete m_pInputControlNames[ i ];
+		}
+		m_pInputControlNames.clear();
+	}
+	if ( m_pInputControlLabel.size() != 0 ) {
+		for (uint i = 0; i < m_pInputControlLabel.size(); i++) {
+			delete m_pInputControlLabel[ i ];
+		}
+		m_pInputControlLabel.clear();
+	}
+	if ( m_pInputControlFaders.size() != 0 ) {
+		for (uint i = 0; i < m_pInputControlFaders.size(); i++) {
+			delete m_pInputControlFaders[ i ];
+		}
+		m_pInputControlFaders.clear();
+	}
+
+	if ( m_pOutputControlFaders.size() != 0 ) {
+		for (uint i = 0; i < m_pOutputControlFaders.size(); i++) {
+			delete m_pOutputControlFaders[ i ];
+		}
+		m_pOutputControlFaders.clear();
+	}
+	if ( m_pOutputControlNames.size() != 0 ) {
+		for (uint i = 0; i < m_pOutputControlNames.size(); i++) {
+			delete m_pOutputControlNames[ i ];
+		}
+		m_pOutputControlNames.clear();
+	}
+
+	if (pFX) {
+		QString sPluginName = pFX->getPluginLabel();
+		setWindowTitle( trUtf8( "[%1] LADSPA FX Properties" ).arg( sPluginName ) );
+
+		int nControlsFrameWidth = 10 + 45 * (pFX->inputControlPorts.size() + pFX->outputControlPorts.size()) + 10 + 45;
+		if ( nControlsFrameWidth < width() ) {
+			nControlsFrameWidth = width();
+		}
+		m_pFrame->resize( nControlsFrameWidth, height() );
+
+		m_pActivateBtn->setEnabled(true);
+		if (pFX->isEnabled()) {
+			m_pActivateBtn->setText( trUtf8("Deactivate") );
+		}
+		else {
+			m_pActivateBtn->setText( trUtf8("Activate") );
+		}
+
+		QString mixerline_text_path = Skin::getImagePath() + "/mixerPanel/mixer_background.png";
+		QPixmap textBackground;
+		if( textBackground.load( mixerline_text_path ) == false ){
+			ERRORLOG( "Error loading pixmap"  );
+		}
+
+		// input controls
+		uint nInputControl_X = 0;
+		for (uint i = 0; i < pFX->inputControlPorts.size(); i++) {
+			LadspaControlPort *pControlPort = pFX->inputControlPorts[ i ];
+
+			nInputControl_X = 10 + 45 * i;
+
+			if (pControlPort->isToggle){	// toggle button
+				WARNINGLOG( "[updateControls] LADSPA toggle controls not implemented yet");
+			}
+
+			// peak volume label
+			QString sValue;
+			if (pControlPort->fControlValue < 1.0 ) {
+				sValue = QString("%1").arg( pControlPort->fControlValue, 0, 'f', 2);
+			}
+			else if ( pControlPort->fControlValue < 100.0 ) {
+				sValue = QString("%1").arg( pControlPort->fControlValue, 0, 'f', 1);
+			}
+			else {
+				sValue = QString("%1").arg( pControlPort->fControlValue, 0, 'f', 0);
+			}
+
+			LCDDisplay *pLCD = new LCDDisplay( m_pFrame, LCDDigit::SMALL_BLUE, 4 );
+			pLCD->move( nInputControl_X, 40 );
+			pLCD->setText( sValue );
+			pLCD->show();
+			QPalette lcdPalette;
+			lcdPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
+			pLCD->setPalette( lcdPalette );
+
+			m_pInputControlLabel.push_back( pLCD );
+
+			InstrumentNameWidget *pName = new InstrumentNameWidget( m_pFrame );
+			pName->move( nInputControl_X, 60 );
+			pName->show();
+			pName->setText( pControlPort->sName );
+			m_pInputControlNames.push_back( pName );
+			pName->setToolTip( pName->text() );
+
+
+			// fader
+			Fader *pFader = new Fader( m_pFrame, pControlPort->m_bIsInteger, false );
+			connect( pFader, SIGNAL( valueChanged(Fader*) ), this, SLOT( faderChanged(Fader*) ) );
+			m_pInputControlFaders.push_back( pFader );
+			pFader->move( nInputControl_X + 20, 60 );
+			pFader->show();
+			pFader->setMaxValue( pControlPort->fUpperBound );
+			pFader->setMinValue( pControlPort->fLowerBound );
+			pFader->setMaxPeak( pControlPort->fUpperBound );
+			pFader->setMinPeak( pControlPort->fLowerBound );
+			pFader->setValue( pControlPort->fControlValue );
+			pFader->setPeak_L( pControlPort->fControlValue );
+			pFader->setPeak_R( pControlPort->fControlValue );
+
+			//float fInterval = pControlPort->fUpperBound - pControlPort->fLowerBound;
+			//float fValue = ( pControlPort->fControlValue - pControlPort->fLowerBound ) / fInterval;
+			//pFader->setValue( fValue );
+			//pFader->setPeak_L( fValue );
+			//pFader->setPeak_R( fValue );
+
+			faderChanged( pFader );
+
+			m_pNameLbl->setText( pFX->getPluginName() );
+		}
+
+		nInputControl_X += 45;
+		for (uint i = 0; i < pFX->outputControlPorts.size(); i++) {
+			LadspaControlPort *pControl = pFX->outputControlPorts[ i ];
+
+			uint xPos = nInputControl_X + 10 + 45 * i;
+
+			InstrumentNameWidget *pName = new InstrumentNameWidget( m_pFrame );
+			pName->move( xPos, 60 );
+			pName->show();
+			pName->setText( pControl->sName );
+			m_pInputControlNames.push_back( pName );
+			pName->setToolTip( pName->text() );
+
+			// fader
+			Fader *pFader = new Fader( m_pFrame, true, true );	// without knob!
+			pFader->move( xPos + 20, 60 );
+			//float fInterval = pControl->fUpperBound - pControl->fLowerBound;
+			//float fValue = pControl->fControlValue / fInterval;
+			pFader->show();
+			pFader->setMaxValue( pControl->fUpperBound );
+			pFader->setMinValue( pControl->fLowerBound );
+			pFader->setMaxPeak( pControl->fUpperBound );
+			pFader->setMinPeak( pControl->fLowerBound );
+			pFader->setValue( pControl->fControlValue );
+			pFader->setPeak_L( pControl->fControlValue );
+			pFader->setPeak_R( pControl->fControlValue );
+
+			m_pOutputControlFaders.push_back( pFader );
+		}
+	}
+	else {
+		INFOLOG( "NULL PLUGIN" );
+		setWindowTitle( trUtf8( "LADSPA FX %1 Properties" ).arg( m_nLadspaFX) );
+		m_pNameLbl->setText( trUtf8("No plugin") );
+		m_pActivateBtn->setEnabled(false);
+	}
+
+	m_pTimer->start(100);
+#endif
+}
+
+
+
+void LadspaFXProperties::selectFXBtnClicked()
+{
+#ifdef LADSPA_SUPPORT
+	LadspaFXSelector fxSelector(m_nLadspaFX);
+	if (fxSelector.exec() == QDialog::Accepted) {
+		QString sSelectedFX = fxSelector.getSelectedFX();
+		if ( !sSelectedFX.isEmpty() ) {
+			LadspaFX *pFX = NULL;
+
+			vector<H2Core::LadspaFXInfo*> pluginList = Effects::get_instance()->getPluginList();
+			for (uint i = 0; i < pluginList.size(); i++) {
+				H2Core::LadspaFXInfo *pFXInfo = pluginList[i];
+				if (pFXInfo->m_sName == sSelectedFX ) {
+					int nSampleRate = Hydrogen::get_instance()->getAudioOutput()->getSampleRate();
+					pFX = LadspaFX::load( pFXInfo->m_sFilename, pFXInfo->m_sLabel, nSampleRate );
+					pFX->setEnabled( true );
+					break;
+				}
+			}
+			//AudioEngine::get_instance()->lock( RIGHT_HERE );
+			Song *pSong = (Hydrogen::get_instance() )->getSong();
+			pSong->__is_modified = true;
+
+			Effects::get_instance()->setLadspaFX( pFX, m_nLadspaFX );
+
+			//AudioEngine::get_instance()->unlock();
+			Hydrogen::get_instance()->restartLadspaFX();
+			updateControls();
+		}
+		else {	// no plugin selected
+			INFOLOG( "no plugin selected" );
+		}
+	}
+#endif
+}
+
+
+
+void LadspaFXProperties::updateOutputControls()
+{
+#ifdef LADSPA_SUPPORT
+
+//	INFOLOG( "[updateOutputControls]" );
+//	Song *pSong = (Hydrogen::get_instance() )->getSong();
+	LadspaFX *pFX = Effects::get_instance()->getLadspaFX(m_nLadspaFX);
+
+	if (pFX) {
+		m_pActivateBtn->setEnabled(true);
+		if (pFX->isEnabled()) {
+			m_pActivateBtn->setText( trUtf8("Deactivate") );
+		}
+		else {
+			m_pActivateBtn->setText( trUtf8("Activate") );
+		}
+
+		for (uint i = 0; i < pFX->outputControlPorts.size(); i++) {
+			LadspaControlPort *pControl = pFX->outputControlPorts[i];
+
+			vector<Fader*>::iterator it = m_pOutputControlFaders.begin() + i;
+			if (it != m_pOutputControlFaders.end() ) {
+				Fader *pFader = *it;
+				if (pFader == NULL) {
+					ERRORLOG( "[updateOutputControls] pFader = NULL" );
+					continue;
+				}
+
+				float fValue = pControl->fControlValue;
+				float fInterval = pControl->fUpperBound - pControl->fLowerBound;
+				fValue = pControl->fControlValue / fInterval;
+
+				if (fValue < 0) fValue = -fValue;
+
+				pFader->setPeak_L( fValue );
+				pFader->setPeak_R( fValue );
+			}
+		}
+	}
+	else {
+		m_pActivateBtn->setEnabled(false);
+	}
+#endif
+}
+
+
+
+
+void LadspaFXProperties::activateBtnClicked()
+{
+#ifdef LADSPA_SUPPORT
+//	Song *pSong = (Hydrogen::get_instance() )->getSong();
+	LadspaFX *pFX = Effects::get_instance()->getLadspaFX(m_nLadspaFX);
+	if (pFX) {
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		pFX->setEnabled( !pFX->isEnabled() );
+		AudioEngine::get_instance()->unlock();
+	}
+#endif
+}
Index: /branches/tabbedInterface/gui/src/HydrogenApp.h
===================================================================
--- /branches/tabbedInterface/gui/src/HydrogenApp.h	(revision 1415)
+++ /branches/tabbedInterface/gui/src/HydrogenApp.h	(revision 1415)
@@ -0,0 +1,139 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef HYDROGEN_APP_H
+#define HYDROGEN_APP_H
+
+#include "config.h"
+
+#include <hydrogen/Object.h>
+#include <hydrogen/globals.h>
+
+#include "EventListener.h"
+
+#include <iostream>
+#include <vector>
+#include <QtGui>
+
+namespace H2Core
+{
+	class Song;
+}
+
+class SongEditorPanel;
+class MainForm;
+class PlayerControl;
+class PatternEditorPanel;
+class InstrumentEditorPanel;
+class SongEditor;
+class Mixer;
+class AudioEngineInfoForm;
+class SimpleHTMLBrowser;
+class LadspaFXProperties;
+class LadspaFXInfo;
+class LadspaFXGroup;
+class InstrumentRack;
+class PlaylistDialog;
+class SampleEditor;
+class MetroBlinker;
+
+class HydrogenApp : public QObject, public Object
+{
+	Q_OBJECT
+	public:
+		HydrogenApp( MainForm* pMainForm, H2Core::Song *pFirstSong );
+
+		/// Returns the instance of HydrogenApp class
+		static HydrogenApp* get_instance();
+
+		virtual ~HydrogenApp();
+
+		void setSong( H2Core::Song* pSong );
+
+		void showPreferencesDialog();
+		void showMixer(bool bShow);
+		void showAudioEngineInfoForm();
+		void showPlaylistDialog();
+		void showMetroBlinker();
+		void showSampleEditor( QString name, int mSelectedLayer );
+
+		Mixer* getMixer() {	return m_pMixer;	}
+		MainForm* getMainForm() {	return m_pMainForm;	}
+		SongEditorPanel* getSongEditorPanel() {	return m_pSongEditorPanel;	}
+		AudioEngineInfoForm* getAudioEngineInfoForm() {	return m_pAudioEngineInfoForm;	}
+		PlaylistDialog* getPlayListDialog() {	return m_pPlaylistDialog;	}
+		MetroBlinker* getMetroBlinker() { return m_pMetroBlinker; }
+		SampleEditor* getSampleEditor() {  return m_pSampleEditor;	}
+		SimpleHTMLBrowser* getHelpBrowser() {	return m_pHelpBrowser;	}
+		PatternEditorPanel* getPatternEditorPanel() {	return m_pPatternEditorPanel;	}
+		PlayerControl* getPlayerControl() {	return m_pPlayerControl;	}
+		InstrumentRack* getInstrumentRack(){	return m_pInstrumentRack;	}
+
+
+		void setStatusBarMessage( const QString& msg, int msec = 0 );
+		void setScrollStatusBarMessage( const QString& msg, int msec = 0, bool test = true );
+                void setWindowTitle( const QString& title);
+
+#ifdef LADSPA_SUPPORT
+		LadspaFXProperties* getLadspaFXProperties(uint nFX) {	return m_pLadspaFXProperties[nFX];	}
+#endif
+		void addEventListener( EventListener* pListener );
+		void removeEventListener( EventListener* pListener );
+		void closeFXProperties();
+
+		void onDrumkitLoad( QString name );
+		void enableDestructiveRecMode();
+
+	public slots:
+		void onEventQueueTimer();
+
+	private:
+		static HydrogenApp *m_pInstance;	///< HydrogenApp instance
+
+#ifdef LADSPA_SUPPORT
+		LadspaFXProperties *m_pLadspaFXProperties[MAX_FX];
+#endif
+		MainForm *m_pMainForm;
+		Mixer *m_pMixer;
+		PatternEditorPanel* m_pPatternEditorPanel;
+		AudioEngineInfoForm *m_pAudioEngineInfoForm;
+		SongEditorPanel *m_pSongEditorPanel;
+		SimpleHTMLBrowser *m_pHelpBrowser;
+		SimpleHTMLBrowser *m_pFirstTimeInfo;
+		InstrumentRack* m_pInstrumentRack;
+		PlayerControl *m_pPlayerControl;
+		PlaylistDialog *m_pPlaylistDialog;
+		SampleEditor *m_pSampleEditor;
+		MetroBlinker *m_pMetroBlinker;
+		QTimer *m_pEventQueueTimer;
+		std::vector<EventListener*> m_eventListeners;
+
+		// implement EngineListener interface
+		void engineError(uint nErrorCode);
+
+		//void setupTopLevelInterface();
+		void setupSinglePanedInterface();
+		void showInfoSplash();
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/midiTable.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/midiTable.h	(revision 581)
+++ /branches/tabbedInterface/gui/src/widgets/midiTable.h	(revision 581)
@@ -0,0 +1,54 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef MIDI_TABLE_H
+#define MIDI_TABLE_H
+
+#include "config.h"
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+
+class MidiTable : public QTableWidget, public Object
+{
+	Q_OBJECT
+	public:
+		MidiTable( QWidget* pParent );
+		~MidiTable();
+
+		void setupMidiTable();
+		void saveMidiTable();
+		void insertNewRow(QString, QString, int, int);
+
+	private slots:
+		void updateTable();
+		void midiSensePressed( int );
+	
+	private:
+		int __row_count;
+		int currentMidiAutosenseRow;
+		QSignalMapper *signalMapper;
+		QTimer* m_pUpdateTimer;
+
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/CpuLoadWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/CpuLoadWidget.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/widgets/CpuLoadWidget.h	(revision 377)
@@ -0,0 +1,66 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef CPU_LOAD_WIDGET_H
+#define CPU_LOAD_WIDGET_H
+
+#include "config.h"
+
+#include <iostream>
+
+#include "../EventListener.h"
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+
+///
+/// Shows CPU load
+///
+class CpuLoadWidget : public QWidget, public EventListener, public Object
+{
+	Q_OBJECT
+
+	public:
+		CpuLoadWidget(QWidget *pParent );
+		~CpuLoadWidget();
+
+		void setValue( float newValue );
+		float getValue();
+
+		void mousePressEvent(QMouseEvent *ev);
+		void paintEvent(QPaintEvent *ev);
+
+		void XRunEvent();
+
+	public slots:
+		void updateCpuLoadWidget();
+
+	private:
+		float m_fValue;
+		uint m_nXRunValue;
+
+		QPixmap m_back;
+		QPixmap m_leds;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/PixmapWidget.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/PixmapWidget.cpp	(revision 127)
+++ /branches/tabbedInterface/gui/src/widgets/PixmapWidget.cpp	(revision 127)
@@ -0,0 +1,107 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "PixmapWidget.h"
+#include "../Skin.h"
+#include <QPainter>
+
+#include <hydrogen/Object.h>
+
+PixmapWidget::PixmapWidget( QWidget *pParent, const QString& sClassName )
+ : Object( sClassName )
+ , QWidget( pParent )
+ , m_sPixmapPath( "" )
+ , __expand_horiz(false)
+{
+	// draw the background: slower but useful with transparent images!
+	//setAttribute(Qt::WA_NoBackground);
+	__color = QColor(200, 0, 0);
+}
+
+
+
+PixmapWidget::~PixmapWidget()
+{
+}
+
+
+
+
+void PixmapWidget::setColor(const QColor& color)
+{
+	if (__color == color) {
+		return;
+	}
+	__color = color;
+	update();
+}
+
+
+
+void PixmapWidget::setPixmap( QString sPixmapPath, bool expand_horiz )
+{
+	if ( m_sPixmapPath == sPixmapPath ) {
+		return;
+	}
+	m_sPixmapPath = sPixmapPath;
+	__expand_horiz = expand_horiz;
+
+	bool ok = m_pixmap.load( Skin::getImagePath() + sPixmapPath );
+	if ( !ok ) {
+		_INFOLOG( QString( "Error loading: %1%2").arg( Skin::getImagePath() ).arg( sPixmapPath ) );
+	}
+
+	resize( m_pixmap.width(), m_pixmap.height() );
+	update();
+}
+
+
+
+void PixmapWidget::paintEvent( QPaintEvent* ev)
+{
+	QWidget::paintEvent(ev);
+
+	QPainter painter(this);
+	if ( m_pixmap.isNull() ) {
+		painter.fillRect( ev->rect(), __color );
+	}
+	else {
+		if (__expand_horiz) {
+			static int w = 10;
+			static int h = m_pixmap.height();
+
+			// central section, scaled
+			painter.drawPixmap( QRect(w, 0, width() - w * 2, h), m_pixmap, QRect(10, 0, w, h) );
+
+			// left side
+			painter.drawPixmap( QRect(0, 0, w, h), m_pixmap, QRect(0, 0, w, h) );
+
+			// right side
+			painter.drawPixmap( QRect(width() - w, 0, w, h), m_pixmap, QRect(m_pixmap.width() - w, 0, w, h) );
+		}
+		else {
+			painter.drawPixmap( ev->rect(), m_pixmap, ev->rect() );
+		}
+	}
+}
+
+
Index: /branches/tabbedInterface/gui/src/widgets/LCD.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/LCD.cpp	(revision 1367)
+++ /branches/tabbedInterface/gui/src/widgets/LCD.cpp	(revision 1367)
@@ -0,0 +1,439 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "LCD.h"
+
+#include "../Skin.h"
+
+#include <QtGui>
+
+#include <hydrogen/globals.h>
+
+QPixmap* LCDDigit::m_pSmallBlueFontSet = NULL;
+QPixmap* LCDDigit::m_pSmallRedFontSet = NULL;
+QPixmap* LCDDigit::m_pLargeGrayFontSet = NULL;
+QPixmap* LCDDigit::m_pSmallGrayFontSet = NULL;
+
+LCDDigit::LCDDigit( QWidget * pParent, LCDType type )
+ : QWidget( pParent )
+ , Object( "LCDDigit" )
+ , m_type( type )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	switch ( m_type ) {
+		case SMALL_BLUE:
+		case SMALL_RED:
+			resize( 8, 11 );
+			break;
+
+		case LARGE_GRAY:
+			resize( 14, 16 );
+			break;
+
+		case SMALL_GRAY:
+		resize( 12, 11 );
+		break;
+}
+
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	// Small blue FontSet image
+	if (m_pSmallBlueFontSet == NULL ) {
+		QString sSmallBlueFontSet = Skin::getImagePath() + "/lcd/LCDSmallBlueFontSet.png";
+		m_pSmallBlueFontSet = new QPixmap();
+		bool ok = m_pSmallBlueFontSet->load( sSmallBlueFontSet );
+		if( ok == false ) {
+			ERRORLOG( "Error loading pixmap");
+		}
+	}
+
+	// Small red FontSet image
+	if (m_pSmallRedFontSet == NULL ) {
+		QString sSmallRedFontSet = Skin::getImagePath() + "/lcd/LCDSmallRedFontSet.png";
+		m_pSmallRedFontSet = new QPixmap();
+		bool ok = m_pSmallRedFontSet->load( sSmallRedFontSet );
+		if( ok == false ) {
+			ERRORLOG( "Error loading pixmap" );
+		}
+	}
+
+	// Large gray FontSet image
+	if (m_pLargeGrayFontSet == NULL ) {
+		QString sLargeGrayFontSet = Skin::getImagePath() + "/lcd/LCDLargeGrayFontSet.png";
+		m_pLargeGrayFontSet = new QPixmap();
+		bool ok = m_pLargeGrayFontSet->load( sLargeGrayFontSet );
+		if( ok == false ) {
+			ERRORLOG( "Error loading pixmap" );
+		}
+	}
+
+	// Small gray FontSet image
+	if (m_pSmallGrayFontSet == NULL ) {
+		QString sSmallGrayFontSet = Skin::getImagePath() + "/lcd/LCDSmallGrayFontSet.png";
+		m_pSmallGrayFontSet = new QPixmap();
+		bool ok = m_pSmallGrayFontSet->load( sSmallGrayFontSet );
+		if( ok == false ) {
+			ERRORLOG( "Error loading pixmap" );
+		}
+	}
+
+	set( ' ' );
+}
+
+
+LCDDigit::~LCDDigit()
+{
+//	delete m_pSmallBlueFontSet;
+//	m_pSmallBlueFontSet = NULL;
+
+//	delete m_pSmallRedFontSet;
+//	m_pSmallRedFontSet = NULL;
+}
+
+
+//void LCDDigit::mousePressEvent(QMouseEvent *ev)
+void LCDDigit::mouseReleaseEvent(QMouseEvent* ev)
+{
+	UNUSED( ev );
+	emit digitClicked();
+}
+
+
+void LCDDigit::paintEvent(QPaintEvent *ev)
+{
+	UNUSED( ev );
+
+	int x = m_nCol * width();
+	int y = m_nRow * height();
+
+	QPainter painter(this);
+
+	switch ( m_type ) {
+		case SMALL_BLUE:
+			painter.drawPixmap( rect(), *m_pSmallBlueFontSet, QRect( x, y, width(), height() ) );
+			break;
+
+		case SMALL_RED:
+			painter.drawPixmap( rect(), *m_pSmallRedFontSet, QRect( x, y, width(), height() ) );
+			break;
+
+		case LARGE_GRAY:
+			painter.drawPixmap( rect(), *m_pLargeGrayFontSet, QRect( x, y, width(), height() ) );
+			break;
+
+		case SMALL_GRAY:
+			painter.drawPixmap( rect(), *m_pSmallGrayFontSet, QRect( x, y, width(), height() ) );
+			break;
+
+		default:
+			ERRORLOG( "[paint] Unhandled type" );
+			painter.setPen(Qt::blue);
+			painter.drawText(rect(), Qt::AlignCenter, "!");
+	}
+}
+
+
+void LCDDigit::set( char ch )
+{
+	int MAXCOL = 66;
+	const char keymap[] = {
+			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ',
+			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' ',
+			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ' ',
+			'-', ':', '/', '\\', ',', ';', '.', ' ', ' ', ' ', '#'
+	};
+	for ( int n = 0; n < 77; n++ ) { //73
+		if ( keymap[ n ] == ch ) {
+			m_nCol = n % MAXCOL;
+			m_nRow = n / MAXCOL;
+			break;
+		}
+	}
+
+	update();
+}
+
+
+void LCDDigit::setSmallRed()
+{
+	if ( m_type != SMALL_RED ) {
+		m_type = SMALL_RED;
+		update();
+	}
+}
+
+
+void LCDDigit::setSmallBlue()
+{
+	if ( m_type != SMALL_BLUE ) {
+		m_type = SMALL_BLUE;
+		update();
+	}
+}
+
+
+
+// ::::::::::::::::::
+
+
+
+
+LCDDisplay::LCDDisplay( QWidget * pParent, LCDDigit::LCDType type, int nDigits, bool leftAlign )
+ : QWidget( pParent )
+ , m_sMsg( "" )
+ , m_bLeftAlign( leftAlign )
+{
+
+	for ( int n = 0; n < nDigits; n++ ) {
+		LCDDigit *pDigit = new LCDDigit( this, type );
+		if ( ( type == LCDDigit::LARGE_GRAY ) || ( type == LCDDigit::SMALL_GRAY ) ) {
+			pDigit->move( pDigit->width() * n, 0 );
+		}
+		else {
+			pDigit->move( pDigit->width() * n + 2, 2 );
+		}
+		connect( pDigit, SIGNAL( digitClicked() ), this, SLOT( digitClicked() ) );
+		m_pDisplay.push_back( pDigit );
+	}
+
+	if ( ( type == LCDDigit::LARGE_GRAY ) || ( type == LCDDigit::SMALL_GRAY ) ) {
+		int w = m_pDisplay[ 0 ]->width() * nDigits;
+		int h = m_pDisplay[ 0 ]->height();
+
+		resize( w, h );
+	}
+	else {
+		int w = m_pDisplay[ 0 ]->width() * nDigits + 4;
+		int h = m_pDisplay[ 0 ]->height() + 4;
+
+		resize( w, h );
+	}
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	setText( "    ");
+
+	QPalette defaultPalette;
+	defaultPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
+	this->setPalette( defaultPalette );
+
+}
+
+
+
+
+LCDDisplay::~LCDDisplay() {
+//	for ( uint i = 0; i < m_pDisplay.size(); i++ ) {
+//		delete m_pDisplay[ i ];
+//	}
+}
+
+
+void LCDDisplay::setText( const QString& sMsg )
+{
+	if ( sMsg == m_sMsg ) {
+		return;
+	}
+
+	m_sMsg = sMsg;
+	int nLen = sMsg.length();
+
+
+
+	if ( m_bLeftAlign ) {
+		for ( int i = 0; i < (int)m_pDisplay.size(); ++i ) {
+			if ( i < nLen ) {
+                            m_pDisplay[ i ]->set( sMsg.toLocal8Bit().at(i) );
+			}
+			else {
+				m_pDisplay[ i ]->set( ' ' );
+			}
+		}
+	}
+	else {
+		// right aligned
+		int nPadding = 0;
+		if ( nLen < (int)m_pDisplay.size() ) {
+			nPadding = m_pDisplay.size() - nLen;
+		}
+		else {
+			nLen = m_pDisplay.size();
+		}
+
+		for ( int i = 0; i < nPadding; i++) {
+			m_pDisplay[ i ]->set( ' ' );
+		}
+
+		for ( int i = 0; i < nLen; i++ ) {
+			m_pDisplay[ i + nPadding ]->set( sMsg.toLocal8Bit().at(i) );
+		}
+	}
+}
+
+
+
+void LCDDisplay::setSmallRed()
+{
+	for ( uint i = 0; i < m_pDisplay.size(); i++) {
+		m_pDisplay[ i ]->setSmallRed();
+	}
+}
+
+void LCDDisplay::setSmallBlue()
+{
+	for ( uint i = 0; i < m_pDisplay.size(); i++) {
+		m_pDisplay[ i ]->setSmallBlue();
+	}
+}
+
+void LCDDisplay::digitClicked()
+{
+	emit displayClicked( this );
+}
+
+// :::::::::::::::::::
+
+
+
+// used in PlayerControl
+LCDSpinBox::LCDSpinBox( QWidget *pParent, int nDigits, LCDSpinBoxType type, int nMin, int nMax )
+ : QWidget( pParent )
+ , Object( "LCDSpinBox" )
+ , m_type( type )
+ , m_fValue( 0 )
+ , m_nMinValue( nMin )
+ , m_nMaxValue( nMax )
+{
+	m_pDisplay = new LCDDisplay( this, LCDDigit::LARGE_GRAY, nDigits );
+	connect( m_pDisplay, SIGNAL( displayClicked(LCDDisplay*) ), this, SLOT( displayClicked(LCDDisplay*) ) );
+
+	resize( m_pDisplay->width(), m_pDisplay->height() );
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	setValue( 0 );
+}
+
+
+
+LCDSpinBox::~LCDSpinBox()
+{
+	delete m_pDisplay;
+//	delete m_pUpBtn;
+//	delete m_pDownBtn;
+}
+
+
+void LCDSpinBox::upBtnClicked()
+{
+	switch( m_type ) {
+		case INTEGER:
+			if ( m_nMaxValue != -1 && m_fValue < m_nMaxValue ) {
+				setValue( m_fValue + 1);
+			}
+			break;
+		case FLOAT:
+			if ( m_nMaxValue != -1 && m_fValue < (float)m_nMaxValue ) {
+				setValue( m_fValue + 1.0);
+			}
+			break;
+	}
+
+	emit changed(this);
+}
+
+void LCDSpinBox::downBtnClicked()
+{
+	switch( m_type ) {
+		case INTEGER:
+			if ( m_nMinValue != -1 && m_fValue > m_nMinValue ) {
+				setValue( m_fValue -1);
+			}
+			break;
+		case FLOAT:
+			if ( m_nMinValue != -1 && m_fValue > m_nMinValue ) {
+				setValue( m_fValue - 1.0);
+			}
+			break;
+	}
+	emit changed(this);
+}
+
+
+void LCDSpinBox::setValue( float nValue )
+{
+	switch ( m_type ) {
+		case INTEGER:
+			if ( nValue != m_fValue ) {
+				m_fValue = (int)nValue;
+				m_pDisplay->setText( QString( "%1" ).arg( m_fValue ) );
+			}
+			break;
+
+		case FLOAT:
+			if ( nValue != m_fValue ) {
+				m_fValue = nValue;
+				QString floatString;
+ 				floatString.setNum( m_fValue , 'f' , 6 );
+				m_pDisplay->setText( floatString );
+			}
+			break;
+	}
+}
+
+void LCDSpinBox::displayClicked( LCDDisplay *pRef )
+{
+	UNUSED( pRef );
+	emit spinboxClicked();
+}
+
+
+void LCDSpinBox::wheelEvent ( QWheelEvent *ev )
+{
+	ev->accept();
+
+	if ( ev->delta() > 0 ) {
+		switch( m_type ) {
+			case INTEGER:
+				setValue( m_fValue + 1);
+				break;
+			case FLOAT:
+				setValue( m_fValue + 1.0);
+				break;
+		}
+
+		emit changed(this);
+	}
+	else {
+		switch( m_type ) {
+			case INTEGER:
+				setValue( m_fValue -1);
+				break;
+			case FLOAT:
+				setValue( m_fValue - 1.0);
+				break;
+		}
+		emit changed(this);
+	}
+}
Index: /branches/tabbedInterface/gui/src/widgets/MidiActivityWidget.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/MidiActivityWidget.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/widgets/MidiActivityWidget.cpp	(revision 1244)
@@ -0,0 +1,148 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "../Skin.h"
+#include "../HydrogenApp.h"
+#include "MidiActivityWidget.h"
+#include <hydrogen/hydrogen.h>
+
+#include <QTimer>
+#include <QPainter>
+#include <QMouseEvent>
+#include <QPaintEvent>
+
+MidiActivityWidget::MidiActivityWidget( QWidget * parent )
+ : QWidget( parent )
+ , Object( "MidiActivityWidget" )
+ , m_nValue( 0 )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	static const uint WIDTH = 58;
+	static const uint HEIGHT = 9;
+
+	resize( WIDTH, HEIGHT );
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	// Background image
+	bool ok = m_back.load( Skin::getImagePath() + "/playerControlPanel/midiActivity_back.png" );
+	if( ok == false ) {
+		ERRORLOG("Error loading pixmap");
+	}
+
+	// Leds image
+	ok = m_leds.load( Skin::getImagePath() + "/playerControlPanel/midiActivity_on.png" );
+	if( ok == false ) {
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	QTimer *timer = new QTimer(this);
+	connect( timer, SIGNAL( timeout() ), this, SLOT( updateMidiActivityWidget() ) );
+	timer->start(200);	// update at 5 fps
+
+	HydrogenApp::get_instance()->addEventListener(this);
+}
+
+
+
+
+/**
+ * Destructor
+ */
+MidiActivityWidget::~MidiActivityWidget()
+{
+}
+
+
+void MidiActivityWidget::mousePressEvent(QMouseEvent *ev)
+{
+	UNUSED( ev );
+}
+
+
+
+void MidiActivityWidget::setValue( int newValue )
+{
+	if (newValue > 100) {
+		newValue = 100;
+	}
+	else if (newValue < 0) {
+		newValue = 0;
+	}
+
+	if ( m_nValue != (uint)newValue ) {
+		m_nValue = newValue;
+		update();
+	}
+}
+
+
+
+
+uint MidiActivityWidget::getValue()
+{
+	return m_nValue;
+}
+
+
+
+void MidiActivityWidget::paintEvent( QPaintEvent*)
+{
+	if ( !isVisible() ) {
+		return;
+	}
+
+	QPainter painter(this);
+
+
+	if (m_nValue > 0 ) {
+//		bitBlt( this, 0, 0, &m_leds, 0, 0, width(), height(), CopyROP, true);
+		painter.drawPixmap( rect(), m_leds, rect() );
+	}
+	else {
+//		bitBlt( this, 0, 0, &m_back, 0, 0, width(), height(), CopyROP, true);
+		painter.drawPixmap( rect(), m_back, rect() );
+	}
+}
+
+
+
+void MidiActivityWidget::updateMidiActivityWidget()
+{
+	int newValue = m_nValue - 40;
+	if (newValue < 0 ) {
+		newValue = 0;
+	}
+	setValue( newValue );
+}
+
+
+
+void MidiActivityWidget::midiActivityEvent()
+{
+	setValue( 100 );
+	updateMidiActivityWidget();
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/widgets/PixmapWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/PixmapWidget.h	(revision 162)
+++ /branches/tabbedInterface/gui/src/widgets/PixmapWidget.h	(revision 162)
@@ -0,0 +1,49 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PIXMAP_WIDGET_H
+#define PIXMAP_WIDGET_H
+
+#include "config.h"
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+class PixmapWidget : public Object, public QWidget
+{
+	public:
+		PixmapWidget( QWidget *pParent, const QString& sClassName = "PixmapWidget" );
+		~PixmapWidget();
+
+		void setPixmap( QString sPixmapPath, bool expand_horiz = false );
+		void setColor( const QColor& color );
+
+	protected:
+		QString m_sPixmapPath;
+		QColor __color;
+		QPixmap m_pixmap;
+		bool __expand_horiz;
+
+		virtual void paintEvent( QPaintEvent* ev);
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/LCD.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/LCD.h	(revision 162)
+++ /branches/tabbedInterface/gui/src/widgets/LCD.h	(revision 162)
@@ -0,0 +1,135 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef LCD_H
+#define LCD_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+#include <vector>
+
+class LCDDigit : public QWidget, public Object
+{
+	Q_OBJECT
+	public:
+		enum LCDType {
+			SMALL_BLUE,
+			SMALL_RED,
+			LARGE_GRAY,
+			SMALL_GRAY
+		};
+
+		LCDDigit( QWidget *pParent, LCDType type );
+		~LCDDigit();
+
+		void set( char ch );
+
+		void setSmallRed();
+		void setSmallBlue();
+
+	signals:
+		void digitClicked();
+
+	private:
+		static QPixmap *m_pSmallBlueFontSet;
+		static QPixmap *m_pSmallRedFontSet;
+		static QPixmap *m_pLargeGrayFontSet;
+		static QPixmap *m_pSmallGrayFontSet;
+
+		int m_nCol;
+		int m_nRow;
+		LCDType m_type;
+
+		virtual void paintEvent(QPaintEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent* ev);
+};
+
+
+
+class LCDDisplay : public QWidget{
+	Q_OBJECT
+	public:
+		LCDDisplay( QWidget * pParent, LCDDigit::LCDType type, int nDigits, bool leftAlign = false );
+		~LCDDisplay();
+
+		void setText( const QString& sMsg );
+		QString getText() {	return m_sMsg;	}
+
+		void setSmallRed();
+		void setSmallBlue();
+
+	public slots:
+		void digitClicked();
+
+	signals:
+		void displayClicked( LCDDisplay* pRef );
+
+	private:
+		std::vector<LCDDigit*> m_pDisplay;
+		QString m_sMsg;
+		bool m_bLeftAlign;
+};
+
+
+class LCDSpinBox : public QWidget, public Object
+{
+	Q_OBJECT
+	public:
+		enum LCDSpinBoxType {
+			INTEGER,
+			FLOAT
+		};
+
+		LCDSpinBox( QWidget *pParent, int nDigits, LCDSpinBoxType type, int nMin = -1, int nMax = -1 );
+		~LCDSpinBox();
+
+		void setValue( float nValue );
+		float getValue() {	return m_fValue;	}
+
+		virtual void wheelEvent( QWheelEvent *ev );
+
+		// richiamati da PlayerControl
+		void upBtnClicked();
+		void downBtnClicked();
+
+	signals:
+		void changed(LCDSpinBox *pRef);
+		void spinboxClicked();
+
+	public slots:
+		void displayClicked( LCDDisplay *pRef );
+
+	private:
+		LCDSpinBoxType m_type;
+		LCDDisplay* m_pDisplay;
+
+		float m_fValue;
+		int m_nMinValue;
+		int m_nMaxValue;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/MidiActivityWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/MidiActivityWidget.h	(revision 162)
+++ /branches/tabbedInterface/gui/src/widgets/MidiActivityWidget.h	(revision 162)
@@ -0,0 +1,59 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef MIDI_ACTIVITY_WIDGET_H
+#define MIDI_ACTIVITY_WIDGET_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include "../EventListener.h"
+#include <hydrogen/Object.h>
+
+class MidiActivityWidget : public QWidget, public EventListener, public Object
+{
+	Q_OBJECT
+	public:
+		MidiActivityWidget(QWidget * parent);
+		~MidiActivityWidget();
+
+		void setValue( int newValue );
+		uint getValue();
+
+		void mousePressEvent(QMouseEvent *ev);
+		void paintEvent(QPaintEvent *ev);
+
+	public slots:
+		void updateMidiActivityWidget();
+
+	private:
+		uint m_nValue;
+
+		QPixmap m_back;
+		QPixmap m_leds;
+
+		virtual void midiActivityEvent();
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/ClickableLabel.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/ClickableLabel.cpp	(revision 73)
+++ /branches/tabbedInterface/gui/src/widgets/ClickableLabel.cpp	(revision 73)
@@ -0,0 +1,49 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "ClickableLabel.h"
+
+#include <QtGui>
+
+#include <hydrogen/globals.h>
+
+ClickableLabel::ClickableLabel( QWidget *pParent )
+ : QLabel( pParent )
+{
+
+	QPalette defaultPalette;
+	defaultPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
+	defaultPalette.setColor( QPalette::Foreground, QColor( 230, 230, 230 ) );
+	this->setPalette( defaultPalette );
+
+	this->setAlignment( Qt::AlignCenter );
+
+
+
+}
+
+
+void ClickableLabel::mousePressEvent( QMouseEvent * e )
+{
+	UNUSED( e );
+	emit labelClicked( this );
+}
Index: /branches/tabbedInterface/gui/src/widgets/Button.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/Button.cpp	(revision 1367)
+++ /branches/tabbedInterface/gui/src/widgets/Button.cpp	(revision 1367)
@@ -0,0 +1,306 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "Button.h"
+
+#include "PixmapWidget.h"
+#include "../Skin.h"
+
+#include <qglobal.h>	// for QT_VERSION
+
+#if QT_VERSION == 0x040100	// SVG renderer was introduced in QT4.1
+	#include <QSvgRenderer>
+#endif
+
+#include <hydrogen/globals.h>
+
+
+Button::Button( QWidget * pParent, const QString& sOnImage, const QString& sOffImage, const QString& sOverImage, QSize size, bool use_skin_style )
+ : QWidget( pParent )
+ , Object( "Button" )
+ , m_bPressed( false )
+ , m_onPixmap( size )
+ , m_offPixmap( size )
+ , m_overPixmap( size )
+ , m_bMouseOver( false )
+ , __use_skin_style(use_skin_style)
+{
+	// draw the background: slower but useful with transparent images!
+	//setAttribute(Qt::WA_NoBackground);
+
+	setMinimumSize( size );
+	setMaximumSize( size );
+	resize( size );
+
+	if ( loadImage( sOnImage, m_onPixmap ) == false ) {
+		m_onPixmap.fill( QColor( 0, 255, 0 ) );
+	}
+
+	if ( loadImage( sOffImage, m_offPixmap ) == false ) {
+		m_offPixmap.fill( QColor( 0, 100, 0 ) );
+	}
+
+	if ( loadImage( sOverImage, m_overPixmap ) == false ) {
+		m_overPixmap.fill( QColor( 0, 180, 0 ) );
+	}
+
+	// default text font
+	m_textFont.setPointSize( 10 );
+	m_textFont.setBold( true );
+}
+
+
+
+Button::~Button()
+{
+}
+
+
+
+bool Button::loadImage( const QString& sFilename, QPixmap& pixmap )
+{
+#if QT_VERSION == 0x040100	// SVG renderer was introduced in QT4.1
+  /*
+	if ( sFilename.endsWith( ".svg" ) ) {
+		ERRORLOG( "************* LOAD SVG!!" );
+		if ( !QFile::exists( sFilename ) ) {
+			return false;
+		}
+		QSvgRenderer doc( sFilename );
+		if ( doc.isValid() == false ) {
+			ERRORLOG( "error loading SVG image: '" + sFilename.toLocal8Bit().constData() + "'" );
+			return false;
+		}
+
+		QPainter p;
+		p.begin( &pixmap );
+		p.setViewport( 0, 0, width(), height() );
+		p.eraseRect( 0, 0, width(), height() );
+		doc.render( &p );
+		p.end();
+		return true;
+	}
+  */
+#endif
+	// load an image
+	if ( pixmap.load( Skin::getImagePath() + sFilename ) == false ) {
+		if ( !sFilename.isEmpty() ) {
+			ERRORLOG( QString( "Error loading image: '%1'" ).arg( sFilename ) );
+		}
+		return false;
+	}
+	return true;
+}
+
+
+void Button::mousePressEvent(QMouseEvent*) {
+	m_bPressed = true;
+	update();
+
+	emit mousePress(this);
+}
+
+
+
+void Button::mouseReleaseEvent(QMouseEvent* ev)
+{
+	setPressed( false );
+
+	if (ev->button() == Qt::LeftButton) {
+		emit clicked(this);
+	}
+	else if (ev->button() == Qt::RightButton) {
+		emit rightClicked(this);
+	}
+
+}
+
+void Button::setFontSize(int size)
+{
+	m_textFont.setPointSize(size);
+}
+
+void Button::setPressed(bool pressed)
+{
+	if (pressed != m_bPressed) {
+		m_bPressed = pressed;
+		update();
+	}
+}
+
+
+
+
+
+
+void Button::enterEvent(QEvent *ev)
+{
+	UNUSED( ev );
+	m_bMouseOver = true;
+	update();
+}
+
+
+
+void Button::leaveEvent(QEvent *ev)
+{
+	UNUSED( ev );
+	m_bMouseOver = false;
+	update();
+}
+
+
+
+void Button::paintEvent( QPaintEvent* ev)
+{
+	QPainter painter(this);
+
+	// background
+	if (m_bPressed) {
+		if (__use_skin_style) {
+			static int w = 5;
+			static int h = m_onPixmap.height();
+
+			// central section, scaled
+			painter.drawPixmap( QRect(w, 0, width() - w * 2, h), m_onPixmap, QRect(10, 0, w, h) );
+
+			// left side
+			painter.drawPixmap( QRect(0, 0, w, h), m_onPixmap, QRect(0, 0, w, h) );
+
+			// right side
+			painter.drawPixmap( QRect(width() - w, 0, w, h), m_onPixmap, QRect(m_onPixmap.width() - w, 0, w, h) );
+		}
+		else {
+			painter.drawPixmap( ev->rect(), m_onPixmap, ev->rect() );
+		}
+	}
+	else {
+		if (m_bMouseOver) {
+			if (__use_skin_style) {
+				static int w = 5;
+				static int h = m_overPixmap.height();
+
+				// central section, scaled
+				painter.drawPixmap( QRect(w, 0, width() - w * 2, h), m_overPixmap, QRect(10, 0, w, h) );
+
+				// left side
+				painter.drawPixmap( QRect(0, 0, w, h), m_overPixmap, QRect(0, 0, w, h) );
+
+				// right side
+				painter.drawPixmap( QRect(width() - w, 0, w, h), m_overPixmap, QRect(m_overPixmap.width() - w, 0, w, h) );
+			}
+			else {
+				painter.drawPixmap( ev->rect(), m_overPixmap, ev->rect() );
+			}
+		}
+		else {
+			if (__use_skin_style) {
+				static int w = 5;
+				static int h = m_offPixmap.height();
+
+				// central section, scaled
+				painter.drawPixmap( QRect(w, 0, width() - w * 2, h), m_offPixmap, QRect(10, 0, w, h) );
+
+				// left side
+				painter.drawPixmap( QRect(0, 0, w, h), m_offPixmap, QRect(0, 0, w, h) );
+
+				// right side
+				painter.drawPixmap( QRect(width() - w, 0, w, h), m_offPixmap, QRect(m_offPixmap.width() - w, 0, w, h) );
+			}
+			else {
+				painter.drawPixmap( ev->rect(), m_offPixmap, ev->rect() );
+			}
+		}
+	}
+
+
+	if ( !m_sText.isEmpty() ) {
+		painter.setFont( m_textFont );
+
+		QColor shadow(150, 150, 150, 100);
+		QColor text(10, 10, 10);
+
+		if (m_bMouseOver) {
+			shadow = QColor(150, 250, 150, 100);
+		}
+
+		// shadow
+		painter.setPen( shadow );
+		painter.drawText( 1, 1, width(), height(), Qt::AlignHCenter | Qt::AlignVCenter,  m_sText );
+
+		// text
+		painter.setPen( text );
+		painter.drawText( 0, 0, width(), height(), Qt::AlignHCenter | Qt::AlignVCenter,  m_sText );
+
+	}
+
+}
+
+
+
+void Button::setText( const QString& sText )
+{
+	m_sText = sText;
+	update();
+}
+
+
+
+// :::::::::::::::::::::::::
+
+
+
+ToggleButton::ToggleButton( QWidget *pParent, const QString& sOnImg, const QString& sOffImg, const QString& sOverImg, QSize size, bool use_skin_style )
+ : Button( pParent, sOnImg, sOffImg, sOverImg, size, use_skin_style )
+{
+
+}
+
+
+
+ToggleButton::~ToggleButton() {
+}
+
+
+
+void ToggleButton::mousePressEvent(QMouseEvent *ev) {
+	if (ev->button() == Qt::RightButton) {
+                emit rightClicked(this);
+        }
+	else {
+		if (m_bPressed) {
+			m_bPressed = false;
+		}
+		else {
+			m_bPressed = true;
+		}
+		update();
+
+		emit clicked(this);
+	}
+}
+
+
+
+void ToggleButton::mouseReleaseEvent(QMouseEvent*) {
+	// do nothing, this method MUST override Button's one
+}
Index: /branches/tabbedInterface/gui/src/widgets/DownloadWidget.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/DownloadWidget.cpp	(revision 1369)
+++ /branches/tabbedInterface/gui/src/widgets/DownloadWidget.cpp	(revision 1369)
@@ -0,0 +1,222 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "DownloadWidget.h"
+
+#include <cmath>
+
+
+Download::Download( QWidget* pParent, const QString& download_url, const QString& local_file )
+		: QDialog( pParent )
+		, Object( "Download" )
+		, __download_percent( 0 )
+		, __eta( 0 )
+		, __bytes_current( 0 )
+		, __bytes_total( 0 )
+		, __remote_url( download_url )
+		, __local_file( local_file )
+{
+	if ( !__local_file.isEmpty() ) {
+		INFOLOG( QString( "Downloading '%1' in '%2'" ).arg( __remote_url ).arg( __local_file ) );
+
+	} else {
+		INFOLOG( QString( "Downloading '%1'" ).arg( __remote_url ) );
+	}
+
+	QUrl url( __remote_url );
+
+	connect( &__http_client, SIGNAL( done( bool ) ), this, SLOT( __fetch_done( bool ) ) );
+	connect( &__http_client, SIGNAL( dataReadProgress( int, int ) ), this, SLOT( __fetch_progress( int, int ) ) );
+	connect( &__http_client, SIGNAL( requestFinished( int, bool ) ), this, SLOT( __http_request_finished( int, bool ) ) );
+	connect( &__http_client, SIGNAL( responseHeaderReceived( const QHttpResponseHeader& ) ), SLOT( __header_received( const QHttpResponseHeader& ) ) );
+
+	QString sPath = url.path();
+	sPath = sPath.replace( " ", "%20" );
+
+	QHttpRequestHeader header( "GET", sPath );
+	header.setValue( "Host", url.host() );
+
+	__time.start();
+
+	__http_client.setHost( url.host() );
+	__http_client.request( header );
+}
+
+
+
+Download::~Download()
+{
+}
+
+
+
+/// TODO: devo salvare il file sul disco su una dir temporanea e poi spostarlo se e' tutto ok.
+void Download::__fetch_done( bool bError )
+{
+	if ( bError ) {
+		ERRORLOG( "Error retrieving the resource." );
+		reject();
+		return;
+	}
+
+	if ( !__redirect_url.isEmpty() ) {
+		reject();
+		return;
+	}
+
+	INFOLOG( "Download completed. " );
+
+	if ( __local_file.isEmpty() ) {
+		// store the text received only when not using the file.
+		__feed_xml_string = __http_client.readAll();
+	} else {
+		QFile file( __local_file );
+
+		if ( !file.open( QIODevice::WriteOnly ) ) {
+			ERRORLOG( QString( "Unable to save %1" ).arg( __local_file ) );
+
+		} else {
+			file.write( __http_client.readAll() );
+			file.flush();
+			file.close();
+		}
+	}
+	accept();
+}
+
+
+
+void Download::__fetch_progress ( int done, int total )
+{
+	__bytes_current = done;
+	__bytes_total = total;
+
+	__download_percent = ( float )done / ( float )total * 100.0;
+}
+
+
+
+void Download::__http_request_finished( int requestId, bool error )
+{
+	if ( error ) {
+		ERRORLOG( "Error: " + __http_client.errorString() );
+		return;
+	}
+}
+
+
+
+void Download::__header_received( const QHttpResponseHeader& res )
+{
+	//INFOLOG( "Header received: " + to_string( res.statusCode() ) );
+	if ( ( res.statusCode() == 301 ) || ( res.statusCode() == 302 ) || ( res.statusCode() == 307 ) ) {
+		__redirect_url = res.value( "location" );
+		INFOLOG( "Received redirect to: " + __redirect_url );
+		//__http_client.abort();
+	}
+}
+
+
+// :::::::::::::::::::..
+
+
+
+DownloadWidget::DownloadWidget( QWidget* parent, const QString& title, const QString& __remote_url, const QString& local_file )
+		: Download( parent, __remote_url, local_file )
+{
+	setWindowTitle( title );
+	setModal( true );
+
+	setFixedSize( 500, 100 );
+
+	QFont boldFont;
+	boldFont.setBold( true );
+
+	__url_label = new QLabel( NULL );
+	__url_label->setFont( boldFont );
+	__url_label->setAlignment( Qt::AlignCenter );
+	__url_label->setText( QFileInfo( __remote_url ).fileName() );
+
+	__progress_bar = new QProgressBar( NULL );
+
+	__progress_bar->setMinimum( 0 );
+	__progress_bar->setMaximum( 100 );
+
+	__eta_label = new QLabel( NULL );
+// __eta_label->setFont( boldFont );
+	__eta_label->setAlignment( Qt::AlignHCenter );
+
+
+	QVBoxLayout* pVBox = new QVBoxLayout();
+	pVBox->addWidget( __url_label );
+	pVBox->addWidget( __progress_bar );
+	pVBox->addWidget( __eta_label );
+
+
+	setLayout( pVBox );
+
+	__update_timer = new QTimer( this );
+	connect( __update_timer, SIGNAL( timeout() ), this, SLOT( updateStats() ) );
+
+	__close_timer = new QTimer( this );
+	connect( __close_timer, SIGNAL( timeout() ), this, SLOT( close() ) );
+
+	__update_timer->start( 100 );
+}
+
+
+
+DownloadWidget::~DownloadWidget()
+{
+	__update_timer->stop();
+	__close_timer->stop();
+}
+
+
+
+void DownloadWidget::updateStats()
+{
+	if ( __download_percent > 0 ) {
+		__eta = ( int )( round( ( __time.elapsed() / __download_percent * ( 100 - __download_percent ) ) / 1000 ) );
+	}
+
+	__progress_bar->setValue( get_percent_done() );
+
+	QString hours = QString( "%1" ).arg( __eta / 60 / 60 );
+	QString minutes = QString( "%1" ).arg( ( __eta / 60 ) % 60 );
+	QString seconds = QString( "%1" ).arg( __eta % 60 );
+
+	hours = hours.rightJustified( 2, '0' );
+	minutes = minutes.rightJustified( 2, '0' );
+	seconds = seconds.rightJustified( 2, '0' );
+
+	QString sETA = hours + ":" + minutes + ":" + seconds;
+
+	__eta_label->setText( trUtf8( "(%1/%2 KiB) - ETA %3" ).arg( __bytes_current / 1024 ).arg( __bytes_total / 1024 ).arg( sETA ) );
+
+	if ( __download_percent == 100 ) {
+		__update_timer->stop();
+
+		__close_timer->start( 1000 ); // close the window after 1 second
+	}
+}
+
Index: /branches/tabbedInterface/gui/src/widgets/ClickableLabel.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/ClickableLabel.h	(revision 162)
+++ /branches/tabbedInterface/gui/src/widgets/ClickableLabel.h	(revision 162)
@@ -0,0 +1,44 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef CLICKABLE_LABEL_H
+#define CLICKABLE_LABEL_H
+
+#include "config.h"
+#include <QtGui>
+
+
+class ClickableLabel : public QLabel
+{
+	Q_OBJECT
+
+	public:
+		ClickableLabel( QWidget *pParent );
+		void mousePressEvent( QMouseEvent * e );
+
+	signals:
+		void labelClicked( ClickableLabel* pLabel );
+};
+
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/widgets/Rotary.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/Rotary.cpp	(revision 377)
+++ /branches/tabbedInterface/gui/src/widgets/Rotary.cpp	(revision 377)
@@ -0,0 +1,263 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "Rotary.h"
+#include "LCD.h"
+#include "../Skin.h"
+
+#include <hydrogen/globals.h>
+
+RotaryTooltip::RotaryTooltip( QPoint pos )
+//  : QWidget( 0, "RotaryTooltip", Qt::WStyle_Customize| Qt::WStyle_NoBorder | Qt::WStyle_StaysOnTop| Qt::WX11BypassWM )
+  : QWidget( 0, Qt::ToolTip )
+{
+	UNUSED( pos );
+
+	m_pDisplay = new LCDDisplay( this, LCDDigit::SMALL_BLUE, 4);
+	m_pDisplay->move( 0, 0 );
+	resize( m_pDisplay->size() );
+
+	QPalette defaultPalette;
+	defaultPalette.setColor( QPalette::Background, QColor( 49, 53, 61 ) );
+	this->setPalette( defaultPalette );
+
+}
+
+
+void RotaryTooltip::showTip( QPoint pos, QString sText )
+{
+	move( pos );
+	m_pDisplay->setText( sText );
+	show();
+}
+
+RotaryTooltip::~RotaryTooltip()
+{
+//	delete m_pDisplay;
+}
+
+
+
+
+
+///////////////////
+
+QPixmap* Rotary::m_background_normal = NULL;
+QPixmap* Rotary::m_background_center = NULL;
+
+
+Rotary::Rotary( QWidget* parent, RotaryType type, QString sToolTip, bool bUseIntSteps, bool bUseValueTip )
+ : QWidget( parent )
+ , Object( "Rotary" )
+ , m_bUseIntSteps( bUseIntSteps )
+ , m_type( type )
+ , m_fMin( 0.0 )
+ , m_fMax( 1.0 )
+ , m_bShowValueToolTip( bUseValueTip )
+{
+	setAttribute(Qt::WA_NoBackground);
+	setToolTip( sToolTip );
+
+	m_pValueToolTip = new RotaryTooltip( mapToGlobal( QPoint( 0, 0 ) ) );
+
+	m_nWidgetWidth = 28;
+	m_nWidgetHeight = 26;
+	m_fValue = 0.0;
+
+	if ( m_background_normal == NULL ) {
+		m_background_normal = new QPixmap();
+		if ( m_background_normal->load( Skin::getImagePath() + "/mixerPanel/rotary_images.png" ) == false ){
+			ERRORLOG( "Error loading pixmap" );
+		}
+	}
+	if ( m_background_center == NULL ) {
+		m_background_center = new QPixmap();
+		if ( m_background_center->load( Skin::getImagePath() + "/mixerPanel/rotary_center_images.png" ) == false ){
+			ERRORLOG( "Error loading pixmap" );
+		}
+	}
+
+	resize( m_nWidgetWidth, m_nWidgetHeight );
+//	m_temp.resize( m_nWidgetWidth, m_nWidgetHeight );
+}
+
+
+
+Rotary::~ Rotary()
+{
+	delete m_pValueToolTip;
+}
+
+
+
+void Rotary::paintEvent( QPaintEvent* ev )
+{
+	UNUSED( ev );
+	QPainter painter(this);
+
+	float fRange = abs( m_fMax ) + abs( m_fMin );
+	float fValue = abs( m_fMin ) + m_fValue;
+
+	int nFrame;
+	if ( m_bUseIntSteps ) {
+		nFrame = (int)( 63.0 * ( (int)fValue / fRange ) );
+	}
+	else {
+		nFrame = (int)( 63.0 * ( fValue / fRange ) );
+	}
+
+//	INFOLOG( "\nrange: " + toString( fRange ) );
+//	INFOLOG( "norm value: " + toString( fValue ) );
+//	INFOLOG( "frame: " + toString( nFrame ) );
+
+	if ( m_type == TYPE_NORMAL ) {
+
+		int xPos = m_nWidgetWidth * nFrame;
+		painter.drawPixmap( rect(), *m_background_normal, QRect( xPos, 0, m_nWidgetWidth, m_nWidgetHeight ) );
+	}
+	else {
+		// the image is broken...
+		if ( nFrame > 62 ) {
+			nFrame = 62;
+		}
+		int xPos = m_nWidgetWidth * nFrame;
+		painter.drawPixmap( rect(), *m_background_center, QRect( xPos, 0, m_nWidgetWidth, m_nWidgetHeight ) );
+
+	}
+}
+
+
+
+void Rotary::setValue( float fValue )
+{
+	if ( fValue == m_fValue ) {
+		return;
+	}
+
+	if ( fValue < m_fMin ) {
+		fValue = m_fMin;
+	}
+	else if ( fValue > m_fMax ) {
+		fValue = m_fMax;
+	}
+
+	if ( fValue != m_fValue ) {
+		m_fValue = fValue;
+		update();
+	}
+}
+
+
+
+void Rotary::mousePressEvent(QMouseEvent *ev)
+{
+	setCursor( QCursor( Qt::SizeVerCursor ) );
+
+	m_fMousePressValue = m_fValue;
+	m_fMousePressY = ev->y();
+
+	if ( m_bShowValueToolTip ) {
+		char tmp[20];
+		sprintf( tmp, "%#.2f", m_fValue );
+		m_pValueToolTip->showTip( mapToGlobal( QPoint( -38, 1 ) ), QString( tmp ) );
+	}
+}
+
+
+
+
+void Rotary::mouseReleaseEvent( QMouseEvent *ev )
+{
+	UNUSED( ev );
+
+	setCursor( QCursor( Qt::ArrowCursor ) );
+	m_pValueToolTip->hide();
+}
+
+
+
+
+void Rotary::wheelEvent ( QWheelEvent *ev )
+{
+	ev->accept();
+
+	float stepfactor = 5.0; // course adjustment
+	float delta = 1.0;
+
+	// Control Modifier = fine adjustment
+	if (ev->modifiers() == Qt::ControlModifier) {
+		stepfactor = 1.0;
+	}
+	if ( !m_bUseIntSteps ) {
+		float fRange = abs( m_fMax ) + abs( m_fMin );
+		delta = fRange / 100.0;
+	}
+	if ( ev->delta() < 0 ) {
+		delta = delta * -1.0;
+	}
+	setValue( getValue() + (delta * stepfactor) );
+	emit valueChanged(this);
+}
+
+
+
+ void Rotary::mouseMoveEvent( QMouseEvent *ev ) {
+	float fRange = abs( m_fMax ) + abs( m_fMin );
+
+	float deltaY = ev->y() - m_fMousePressY;
+	float fNewValue = ( m_fMousePressValue - ( deltaY / 100.0 * fRange ) );
+
+	setValue( fNewValue );
+	emit valueChanged(this);
+
+	if ( m_bShowValueToolTip ) {
+		char tmp[20];
+		sprintf( tmp, "%#.2f", m_fValue );
+		m_pValueToolTip->showTip( mapToGlobal( QPoint( -38, 1 ) ), QString( tmp ) );
+	}
+}
+
+
+
+void Rotary::setMin( float fMin )
+{
+	m_fMin = fMin;
+	update();
+}
+
+float Rotary::getMin()
+{
+	return m_fMin;
+}
+
+
+
+void Rotary::setMax( float fMax )
+{
+	m_fMax = fMax;
+	update();
+}
+
+
+float Rotary::getMax()
+{
+	return m_fMax;
+}
Index: /branches/tabbedInterface/gui/src/widgets/Button.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/Button.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/widgets/Button.h	(revision 377)
@@ -0,0 +1,107 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef BUTTON_H
+#define BUTTON_H
+
+#include "config.h"
+
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+
+class PixmapWidget;
+
+/**
+ * Generic Button with pixmaps and text.
+ */
+class Button : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		Button(
+				QWidget *pParent,
+				const QString& sOnImg,
+				const QString& sOffImg,
+				const QString& sOverImg,
+				QSize size,
+				bool use_skin_style = false
+		);
+		virtual ~Button();
+
+		bool isPressed() {	return m_bPressed;	}
+		void setPressed(bool pressed);
+
+		void setText( const QString& sText );
+		void setFontSize( int size );
+
+	signals:
+		void clicked(Button *pBtn);
+		void rightClicked(Button *pBtn);
+		void mousePress(Button *pBtn);
+
+	protected:
+		bool m_bPressed;
+
+		QFont m_textFont;
+		QString m_sText;
+
+		QPixmap m_onPixmap;
+		QPixmap m_offPixmap;
+		QPixmap m_overPixmap;
+
+	private:
+		bool m_bMouseOver;
+		bool __use_skin_style;
+
+		void mousePressEvent(QMouseEvent *ev);
+		void mouseReleaseEvent(QMouseEvent *ev);
+		void enterEvent(QEvent *ev);
+		void leaveEvent(QEvent *ev);
+		void paintEvent( QPaintEvent* ev);
+
+		bool loadImage( const QString& sFilename, QPixmap& pixmap );
+};
+
+
+
+
+/**
+ * A ToggleButton (On/Off).
+ */
+class ToggleButton : public Button
+{
+	Q_OBJECT
+
+	public:
+		ToggleButton( QWidget *pParent, const QString& sOnImg, const QString& sOffImg, const QString& sOverImg, QSize size, bool use_skin_style = false );
+		~ToggleButton();
+
+	private:
+		void mousePressEvent( QMouseEvent *ev );
+		void mouseReleaseEvent( QMouseEvent *ev );
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/DownloadWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/DownloadWidget.h	(revision 446)
+++ /branches/tabbedInterface/gui/src/widgets/DownloadWidget.h	(revision 446)
@@ -0,0 +1,89 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef DOWNLOAD_WIDGET_H
+#define DOWNLOAD_WIDGET_H
+
+#include "config.h"
+
+#include <QtGui>
+#include <QtNetwork>
+
+#include <hydrogen/Object.h>
+
+class Download : public QDialog, public Object
+{
+Q_OBJECT
+
+public:
+	Download( QWidget* parent, const QString& download_url, const QString& local_file );
+	~Download();
+
+	int get_percent_done() {	return (int)__download_percent;	}
+	const QString& get_xml_content() {	return __feed_xml_string;	}
+
+private slots:
+	void __fetch_done( bool bError );
+	void __fetch_progress( int done, int total );
+	void __http_request_finished( int requestId, bool error );
+	void __header_received( const QHttpResponseHeader& res );
+
+protected:
+	QHttp __http_client;
+	QTime __time;
+
+	float __download_percent;
+	int __eta;
+	int __bytes_current;
+	int __bytes_total;
+	QString __remote_url;
+	QString __local_file;
+	QString __feed_xml_string;
+
+	QString __redirect_url;
+};
+
+
+
+class DownloadWidget : public Download
+{
+Q_OBJECT
+
+public:
+	DownloadWidget( QWidget* parent, const QString& title, const QString& download_url, const QString& local_file = "" );
+	~DownloadWidget();
+
+	QString get_redirect_url() {	return __redirect_url;	}
+
+private slots:
+	void updateStats();
+
+private:
+	QTimer* __update_timer;
+	QTimer* __close_timer;
+	QLabel* __url_label;
+	QLabel* __eta_label;
+	QProgressBar* __progress_bar;
+};
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/widgets/Fader.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/Fader.cpp	(revision 862)
+++ /branches/tabbedInterface/gui/src/widgets/Fader.cpp	(revision 862)
@@ -0,0 +1,608 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "../Skin.h"
+#include "Fader.h"
+#include "LCD.h"
+
+#include <QtGui>
+#include <hydrogen/globals.h>
+
+Fader::Fader( QWidget *pParent, bool bUseIntSteps, bool bWithoutKnob )
+ : QWidget( pParent )
+ , Object( "Fader" )
+ , m_bWithoutKnob( bWithoutKnob )
+ , m_bUseIntSteps( bUseIntSteps )
+ , m_fPeakValue_L( 0.0 )
+ , m_fPeakValue_R( 0.0 )
+ , m_fMinPeak( 0.01f )
+ , m_fMaxPeak( 1.0 )
+ , m_fValue( 0.0 )
+ , m_fMinValue( 0.0 )
+ , m_fMaxValue( 1.0 )
+{
+	setAttribute( Qt::WA_NoBackground );
+	setMinimumSize( 23, 116 );
+	setMaximumSize( 23, 116);
+	resize( 23, 116 );
+
+	// Background image
+	QString background_path = Skin::getImagePath() + "/mixerPanel/fader_background.png";
+	bool ok = m_back.load( background_path );
+	if( ok == false ) {
+		ERRORLOG("Fader: Error loading pixmap");
+	}
+
+	// Leds image
+	QString leds_path = Skin::getImagePath()  + "/mixerPanel/fader_leds.png";
+	ok = m_leds.load( leds_path );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	// Knob image
+	QString knob_path = Skin::getImagePath() + "/mixerPanel/fader_knob.png";
+	ok = m_knob.load( knob_path );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+}
+
+
+
+Fader::~Fader()
+{
+	//infoLog( "[Destroy]" );
+}
+
+
+
+void Fader::mouseMoveEvent( QMouseEvent *ev )
+{
+	float fVal = (float)( height() - ev->y() ) / (float)height();
+	fVal = fVal * ( m_fMaxValue - m_fMinValue );
+
+	fVal = fVal + m_fMinValue;
+
+	setValue( fVal );
+	emit valueChanged(this);
+}
+
+
+
+void Fader::mousePressEvent(QMouseEvent *ev)
+{
+	mouseMoveEvent( ev );
+}
+
+
+
+void Fader::wheelEvent ( QWheelEvent *ev )
+{
+	ev->accept();
+
+	if ( m_bUseIntSteps ) {
+		if ( ev->delta() > 0 ) {
+			setValue( m_fValue + 1 );
+		}
+		else {
+			setValue( m_fValue - 1 );
+		}
+	}
+	else {
+		float step = ( m_fMaxValue - m_fMinValue ) / 50.0;
+
+		if ( ev->delta() > 0 ) {
+			setValue( m_fValue + step );
+		}
+		else {
+			setValue( m_fValue - step );
+		}
+	}
+
+	emit valueChanged(this);
+}
+
+
+
+void Fader::setValue( float fVal )
+{
+	if ( fVal > m_fMaxValue ) {
+		//WARNINGLOG( toString( fVal ) + " > " + toString( m_fMax ) );
+		fVal = m_fMaxValue;
+	}
+	else if ( fVal < m_fMinValue ) {
+		//WARNINGLOG( toString( fVal ) + " < " + toString( m_fMin ) );
+		fVal = m_fMinValue;
+	}
+
+	if ( m_bUseIntSteps ) {
+		fVal = (int)fVal;
+	}
+
+	if ( m_fValue != fVal ) {
+		//INFOLOG( "new value: " + toString( fVal ) );
+		m_fValue = fVal;
+		update();
+	}
+}
+
+
+
+float Fader::getValue()
+{
+	return m_fValue;
+}
+
+
+
+///
+/// Set peak value (0.0 .. 1.0)
+///
+void Fader::setPeak_L( float fPeak )
+{
+	if ( fPeak <  m_fMinPeak ) {
+		fPeak = m_fMinPeak;
+	}
+	else if ( fPeak > m_fMaxPeak ) {
+		fPeak = m_fMaxPeak;
+	}
+
+	if ( m_fPeakValue_L != fPeak) {
+		m_fPeakValue_L = fPeak;
+		update();
+	}
+}
+
+
+
+
+///
+/// Set peak value (0.0 .. 1.0)
+///
+void Fader::setPeak_R( float fPeak )
+{
+	if ( fPeak <  m_fMinPeak ) {
+		fPeak = m_fMinPeak;
+	}
+	else if ( fPeak > m_fMaxPeak ) {
+		fPeak = m_fMaxPeak;
+	}
+
+	if ( m_fPeakValue_R != fPeak ) {
+		m_fPeakValue_R = fPeak;
+		update();
+	}
+}
+
+
+
+void Fader::paintEvent( QPaintEvent *ev)
+{
+	UNUSED( ev );
+
+	QPainter painter(this);
+
+	// background
+//	painter.drawPixmap( rect(), m_back, QRect( 0, 0, 23, 116 ) );
+	painter.drawPixmap( ev->rect(), m_back, ev->rect() );
+
+
+	// peak leds
+	//float fRange = abs( m_fMaxPeak ) + abs( m_fMinPeak );
+
+	float realPeak_L = m_fPeakValue_L - m_fMinPeak;
+	//int peak_L = 116 - ( realPeak_L / fRange ) * 116.0;
+	int peak_L = 116 - ( realPeak_L / ( m_fMaxPeak - m_fMinPeak ) ) * 116.0;
+
+	if ( peak_L > 116 ) {
+		peak_L = 116;
+	}
+	painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), m_leds, QRect( 0, peak_L, 11, 116 - peak_L ) );
+
+
+	float realPeak_R = m_fPeakValue_R - m_fMinPeak;
+	int peak_R = 116 - ( realPeak_R / ( m_fMaxPeak - m_fMinPeak ) ) * 116.0;
+	if ( peak_R > 116 ) {
+		peak_R = 116;
+	}
+	painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), m_leds, QRect( 11, peak_R, 11, 116 - peak_R ) );
+
+	if ( m_bWithoutKnob == false ) {
+		// knob
+		static const uint knob_height = 29;
+		static const uint knob_width = 15;
+
+		float fRange = m_fMaxValue - m_fMinValue;
+
+		float realVal = m_fValue - m_fMinValue;
+
+//		uint knob_y = (uint)( 116.0 - ( 86.0 * ( m_fValue / fRange ) ) );
+		uint knob_y = (uint)( 116.0 - ( 86.0 * ( realVal / fRange ) ) );
+
+
+
+		painter.drawPixmap( QRect( 4, knob_y - knob_height, knob_width, knob_height), m_knob, QRect( 0, 0, knob_width, knob_height ) );
+	}
+}
+
+
+
+void Fader::setMinValue( float fMin )
+{
+	m_fMinValue = fMin;
+}
+
+
+
+
+void Fader::setMaxValue( float fMax )
+{
+	m_fMaxValue = fMax;
+}
+
+
+
+void Fader::setMaxPeak( float fMax )
+{
+	m_fMaxPeak = fMax;
+}
+
+
+
+void Fader::setMinPeak( float fMin )
+{
+	m_fMinPeak = fMin;
+}
+
+
+
+
+//////////////////////////////////
+
+
+
+MasterFader::MasterFader(QWidget *pParent, bool bWithoutKnob)
+ : QWidget( pParent )
+ , Object( "MasterFader" )
+ , m_bWithoutKnob( bWithoutKnob )
+ , m_fPeakValue_L( 0.0 )
+ , m_fPeakValue_R( 0.0 )
+ , m_fValue( 0.0 )
+ , m_fMin( 0.0 )
+ , m_fMax( 1.0 )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	setMinimumSize( 34, 190 );
+	setMaximumSize( 34, 190);
+	resize( 34, 190 );
+
+	// Background image
+	QString background_path = Skin::getImagePath() + "/mixerPanel/masterMixer_background.png";
+	bool ok = m_back.load( background_path );
+	if( ok == false ) {
+		ERRORLOG("Fader: Error loading pixmap");
+	}
+
+	// Leds image
+	QString leds_path = Skin::getImagePath() + "/mixerPanel/masterMixer_leds.png";
+	ok = m_leds.load( leds_path );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+
+	// Knob image
+	QString knob_path = Skin::getImagePath() + "/mixerPanel/fader_knob.png";
+	ok = m_knob.load( knob_path );
+	if( ok == false ){
+		ERRORLOG( "Error loading pixmap" );
+	}
+}
+
+
+
+MasterFader::~MasterFader()
+{
+//	infoLog( "[~MasterFader]" );
+}
+
+
+
+void MasterFader::wheelEvent ( QWheelEvent *ev )
+{
+	ev->accept();
+
+	float step = ( m_fMax - m_fMin ) / 50.0;
+
+	if ( ev->delta() > 0 ) {
+		setValue( m_fValue + step );
+	}
+	else {
+		setValue( m_fValue - step );
+	}
+	emit valueChanged(this);
+}
+
+
+
+void MasterFader::mouseMoveEvent( QMouseEvent *ev )
+{
+	float fVal = (float)( height() - ev->y() ) / (float)height();
+	fVal = fVal * ( m_fMax - m_fMin );
+
+	setValue( fVal );
+	emit valueChanged(this);
+}
+
+
+
+void MasterFader::mousePressEvent(QMouseEvent *ev)
+{
+	mouseMoveEvent( ev );
+}
+
+
+
+void MasterFader::setValue( float newValue )
+{
+	if ( newValue > m_fMax ) {
+		newValue = m_fMax;
+	}
+	else if ( newValue < m_fMin ) {
+		newValue = m_fMin;
+	}
+
+	if ( m_fValue != newValue) {
+		m_fValue = newValue;
+		update();
+	}
+}
+
+
+
+float MasterFader::getValue()
+{
+	return m_fValue;
+}
+
+
+
+///
+/// Set peak value (0.0 .. 1.0)
+///
+void MasterFader::setPeak_L( float peak )
+{
+	if ( peak < 0.01f ) {
+		peak = 0.01f;
+	}
+	else if (peak > 1.0f ) {
+		peak = 1.0f;
+	}
+
+	if ( m_fPeakValue_L != peak ) {
+		m_fPeakValue_L = peak;
+		update();
+	}
+}
+
+
+
+
+///
+/// Set peak value (0.0 .. 1.0)
+///
+void MasterFader::setPeak_R( float peak )
+{
+	if ( peak < 0.01f ) {
+		peak = 0.01f;
+	}
+	else if ( peak > 1.0f ) {
+		peak = 1.0f;
+	}
+
+	if ( m_fPeakValue_R != peak ) {
+		m_fPeakValue_R = peak;
+		update();
+	}
+}
+
+
+
+void MasterFader::paintEvent( QPaintEvent* ev )
+{
+	QPainter painter(this);
+
+	// background
+	painter.drawPixmap( ev->rect(), m_back, ev->rect() );
+
+	// leds
+	float peak_L = m_fPeakValue_L * 190.0;
+	uint offset_L = (uint)( 190.0 - peak_L );
+	painter.drawPixmap( QRect( 0, offset_L, 9, 190 - offset_L), m_leds, QRect( 0, offset_L, 9, 190 - offset_L) );
+
+	float peak_R = m_fPeakValue_R * 190.0;
+	uint offset_R = (uint)( 190.0 - peak_R );
+	painter.drawPixmap( QRect( 9, offset_R, 9, 190 - offset_R), m_leds, QRect( 9, offset_R, 9, 190 - offset_R) );
+
+	if (m_bWithoutKnob == false) {
+		// knob
+		static const uint knob_height = 29;
+		static const uint knob_width = 15;
+		uint knob_y = (uint)( 190.0 - ( 159.0 * ( m_fValue / ( m_fMax - m_fMin ) ) ) );
+		painter.drawPixmap( QRect( 19, knob_y - knob_height, knob_width, knob_height), m_knob, QRect( 0, 0, knob_width, knob_height ) );
+	}
+
+
+/*
+	if ( m_bWithoutKnob == false ) {
+		// knob
+		static const uint knob_height = 29;
+		static const uint knob_width = 15;
+		uint knob_y = (uint)( 116.0 - ( 86.0 * ( m_fValue / ( m_fMax - m_fMin ) ) ) );
+		painter.drawPixmap( QRect( 4, knob_y - knob_height, knob_width, knob_height), knob, QRect( 0, 0, knob_width, knob_height ) );
+	}
+*/
+}
+
+
+
+void MasterFader::setMin( float fMin )
+{
+	m_fMin = fMin;
+}
+
+
+
+
+void MasterFader::setMax( float fMax )
+{
+	m_fMax = fMax;
+}
+
+
+
+
+
+///////////////////
+
+
+
+
+
+QPixmap* Knob::m_background = NULL;
+
+
+///
+/// Constructor
+///
+Knob::Knob( QWidget* pParent )
+ : QWidget( pParent )
+ , Object( "Knob" )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	m_nWidgetWidth = 18;
+	m_nWidgetHeight = 18;
+	m_fValue = 0.0;
+
+	if ( m_background == NULL ) {
+		QString sBackground_path = Skin::getImagePath() + "/mixerPanel/knob_images.png";
+		m_background = new QPixmap();
+		if ( m_background->load( sBackground_path ) == false ){
+			ERRORLOG( "Error loading pixmap" );
+		}
+	}
+
+	resize( m_nWidgetWidth, m_nWidgetHeight );
+}
+
+
+
+///
+/// Destructor
+///
+Knob::~ Knob()
+{
+}
+
+
+
+void Knob::paintEvent( QPaintEvent* ev )
+{
+	UNUSED( ev );
+
+	QPainter painter(this);
+
+	int nFrame = (int)(31.0 * m_fValue);
+	int xPos = m_nWidgetWidth * nFrame;
+//	bitBlt(&m_temp, 0, 0, m_background, xPos, 0, m_nWidgetWidth, m_nWidgetHeight, CopyROP);
+	painter.drawPixmap( rect(), *m_background, QRect( xPos, 0, m_nWidgetWidth, m_nWidgetHeight ) );
+}
+
+
+
+void Knob::setValue( float fValue )
+{
+	if ( fValue == m_fValue ) {
+		return;
+	}
+
+	if ( fValue < 0.0 ) {
+		fValue = 0.0;
+//		warningLog( "[setValue] fValue < 0" );
+	}
+	else if ( fValue > 1.0 ) {
+		fValue = 1.0;
+//		warningLog( "[setValue] fValue > 1" );
+	}
+
+	if ( fValue != m_fValue ) {
+		m_fValue = fValue;
+		update();
+	}
+}
+
+
+
+void Knob::mousePressEvent(QMouseEvent *ev)
+{
+	setCursor( QCursor( Qt::SizeVerCursor ) );
+
+	m_fMousePressValue = m_fValue;
+	m_fMousePressY = ev->y();
+}
+
+
+
+void Knob::mouseReleaseEvent( QMouseEvent *ev )
+{
+	UNUSED( ev );
+	setCursor( QCursor( Qt::ArrowCursor ) );
+}
+
+
+
+ void Knob::mouseMoveEvent( QMouseEvent *ev ) {
+	float y = ev->y() - m_fMousePressY;
+	float fNewValue = m_fMousePressValue - ( y / 100.0 );
+	setValue( fNewValue );
+	emit valueChanged(this);
+}
+
+
+void Knob::wheelEvent ( QWheelEvent *ev )
+{
+	ev->accept();
+
+	if ( ev->delta() > 0 ) {
+		setValue( m_fValue + 0.025 );
+	}
+	else {
+		setValue( m_fValue - 0.025 );
+	}
+	emit valueChanged(this);
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/widgets/LCDCombo.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/LCDCombo.cpp	(revision 390)
+++ /branches/tabbedInterface/gui/src/widgets/LCDCombo.cpp	(revision 390)
@@ -0,0 +1,205 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "LCDCombo.h"
+
+#include "../Skin.h"
+#include "LCD.h"
+#include "Button.h"
+
+#include <hydrogen/globals.h>
+
+const QString LCDCombo::SEPARATOR("--sep--");
+
+LCDCombo::LCDCombo(QWidget *pParent, int digits)
+ : QWidget(pParent)
+ , Object( "LCDCombo") //, SEPARATOR("--sep--")
+{
+	INFOLOG( "INIT" );
+
+	QStringList items;
+	display = new LCDDisplay( this, LCDDigit::SMALL_BLUE, digits, false);
+	button = new Button( this,
+			"/patternEditor/btn_dropdown_on.png",
+			"/patternEditor/btn_dropdown_off.png",
+			"/patternEditor/btn_dropdown_over.png",
+			QSize(13, 13)
+	);
+	pop = new QMenu( this );
+	size = digits;
+	active = 0;
+
+	button->move( ( digits * 8 ) + 5 , 1 );
+	setFixedSize( ( digits * 8 ) + 17, display->height() );
+
+	connect( button, SIGNAL( clicked( Button* ) ), this, SLOT( onClick( Button* ) ) );
+
+	update();
+
+	connect( pop, SIGNAL( triggered(QAction*) ), this, SLOT( changeText(QAction*) ) );
+	//_WARNINGLOG("items:"+items[0]);
+}
+
+
+
+
+LCDCombo::~LCDCombo()
+{
+}
+
+
+QString LCDCombo::getText()
+{
+	return display->getText();
+};
+
+
+void LCDCombo::changeText(QAction* pAction)
+{
+	//_WARNINGLOG("triggered");
+// 	display->setText(pAction->text());
+// 	emit valueChanged( pAction->text() );
+	set_text( pAction->text() );
+}
+
+
+
+void LCDCombo::onClick(Button*)
+{
+	pop->popup( display->mapToGlobal( QPoint( 1, display->height() + 2 ) ) );
+}
+
+
+
+int LCDCombo::length()
+{
+	return size;
+}
+
+
+
+void LCDCombo::update()
+{
+	//INFOLOG ( "update: "+toString(items.size()) );
+	pop->clear();
+
+	for( int i = 0; i < items.size(); i++ ) {
+		if ( items.at(i) != SEPARATOR ){
+			pop->addAction( items.at(i) );
+		}else{
+			pop->addSeparator();
+		}
+	}
+
+}
+
+
+
+int LCDCombo::count()
+{
+	return items.size();
+}
+
+
+
+bool LCDCombo::addItem( const QString &text )
+{
+	//INFOLOG( "add item" );
+
+	if ( text.size() <= size ){
+		items.append( text );
+		return true;
+	}else{
+		return false;
+	}
+}
+
+
+
+void LCDCombo::addSeparator()
+{
+	items.append( SEPARATOR );
+}
+
+
+
+inline void LCDCombo::insertItem( int index, const QString &text )
+{
+	if(text.size()<=length()){
+		items.insert(index,text);
+		update();
+	}
+}
+
+
+
+void LCDCombo::mousePressEvent(QMouseEvent *ev)
+{
+	UNUSED( ev );
+	pop->popup( display->mapToGlobal( QPoint( 1, display->height() + 2 ) ) );
+}
+
+void LCDCombo::wheelEvent( QWheelEvent * ev )
+{
+	ev->ignore();
+	const int n = items.size();
+	const int d = ( ev->delta() > 0 ) ? -1: 1;
+	active = ( n + active + d ) % n;
+	if ( items.at( active ) == SEPARATOR )
+		active = ( n + active + d ) % n;
+	set_text( items.at( active ) );
+}
+
+
+void LCDCombo::set_text( const QString &text)
+{
+	if (display->getText() == text) {
+		return;
+	}
+	//INFOLOG( text );
+	display->setText( text );
+	for ( int i = 0; i < items.size(); i++ ) {
+		if ( items.at(i) == text )
+			active = i;
+	}
+	
+	emit valueChanged( text );
+
+}
+
+void LCDCombo::set_text( const QString &text, bool emit_on_change)
+{
+	if (display->getText() == text) {
+		return;
+	}
+	//INFOLOG( text );
+	display->setText( text );
+	for ( int i = 0; i < items.size(); i++ ) {
+		if ( items.at(i) == text )
+			active = i;
+	}
+	
+	if(emit_on_change)
+		emit valueChanged( text );
+}
+
+
Index: /branches/tabbedInterface/gui/src/widgets/MidiSenseWidget.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/MidiSenseWidget.cpp	(revision 1367)
+++ /branches/tabbedInterface/gui/src/widgets/MidiSenseWidget.cpp	(revision 1367)
@@ -0,0 +1,65 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "MidiSenseWidget.h"
+#include <hydrogen/hydrogen.h>
+
+
+MidiSenseWidget::MidiSenseWidget(QWidget* pParent) : QDialog( pParent ) , Object("MidiSenseWidget")
+{
+	setWindowTitle( "Waiting.." );
+	setFixedSize( 200, 100 );	
+	
+	m_pURLLabel = new QLabel( this );
+	m_pURLLabel->setAlignment( Qt::AlignCenter );
+	m_pURLLabel->setText( "Waiting for midi input..." );
+	
+	
+	QVBoxLayout* pVBox = new QVBoxLayout( this );
+	pVBox->addWidget( m_pURLLabel );
+	setLayout( pVBox );
+	
+	H2Core::Hydrogen *pEngine = H2Core::Hydrogen::get_instance();
+	pEngine->lastMidiEvent = "";
+	pEngine->lastMidiEventParameter = 0;
+	
+	m_pUpdateTimer = new QTimer( this );
+	connect( m_pUpdateTimer, SIGNAL( timeout() ), this, SLOT( updateMidi() ) );
+
+	m_pUpdateTimer->start( 100 );
+};
+
+MidiSenseWidget::~MidiSenseWidget(){
+	INFOLOG("DESTROY");
+	m_pUpdateTimer->stop();
+}
+
+void MidiSenseWidget::updateMidi(){
+	H2Core::Hydrogen *pEngine = H2Core::Hydrogen::get_instance();
+	if(	!pEngine->lastMidiEvent.isEmpty() ){
+		lastMidiEvent = pEngine->lastMidiEvent;
+		lastMidiEventParameter = pEngine->lastMidiEventParameter;
+		close();
+	}
+
+}
+
Index: /branches/tabbedInterface/gui/src/widgets/Rotary.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/Rotary.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/widgets/Rotary.h	(revision 377)
@@ -0,0 +1,104 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ROTARY_H
+#define ROTARY_H
+
+#include "config.h"
+#include <QtGui>
+
+class LCDDisplay;
+
+#include <hydrogen/Object.h>
+
+class RotaryTooltip : public QWidget
+{
+	public:
+		RotaryTooltip( QPoint pos );
+		~RotaryTooltip();
+		void showTip( QPoint pos, QString sText );
+
+	private:
+		LCDDisplay *m_pDisplay;
+};
+
+
+
+class Rotary : public QWidget, public Object
+{
+	Q_OBJECT
+	public:
+		enum RotaryType {
+			TYPE_NORMAL,
+			TYPE_CENTER
+		};
+
+		Rotary( QWidget* parent, RotaryType type, QString sToolTip, bool bUseIntSteps, bool bUseValueTip );
+		~Rotary();
+
+		void setMin( float fMin );
+		float getMin();
+
+		void setMax( float fMax );
+		float getMax();
+
+		void setValue( float fValue );
+		float getValue() {
+			if ( m_bUseIntSteps ) {
+				int val = (int)m_fValue;
+				return val;
+			}
+			else
+				return m_fValue;
+		}
+
+	signals:
+		void valueChanged(Rotary *ref);
+
+	private:
+		bool m_bUseIntSteps;
+		RotaryType m_type;
+		static QPixmap* m_background_normal;
+		static QPixmap* m_background_center;
+
+		int m_nWidgetWidth;
+		int m_nWidgetHeight;
+
+		float m_fMin;
+		float m_fMax;
+		float m_fValue;
+
+		float m_fMousePressValue;
+		float m_fMousePressY;
+
+		RotaryTooltip *m_pValueToolTip;
+		bool m_bShowValueToolTip;
+
+		virtual void paintEvent(QPaintEvent *ev);
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent( QMouseEvent *ev );
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void wheelEvent( QWheelEvent *ev );
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/Fader.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/Fader.h	(revision 377)
+++ /branches/tabbedInterface/gui/src/widgets/Fader.h	(revision 377)
@@ -0,0 +1,170 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef FADER_H
+#define FADER_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+///
+/// Fader and VuMeter widget
+///
+class Fader : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		Fader(QWidget *pParent, bool bUseIntSteps, bool bWithoutKnob );
+		~Fader();
+
+		void setMinValue( float fMin );
+		void setMaxValue( float fMax );
+		float getMinValue() {	return m_fMinValue;	}
+		float getMaxValue() {	return m_fMaxValue;	}
+
+		void setValue( float fVal );
+		float getValue();
+
+
+		void setMaxPeak( float fMax );
+		void setMinPeak( float fMin );
+
+		void setPeak_L( float peak );
+		float getPeak_L() {	return m_fPeakValue_L;	}
+
+		void setPeak_R( float peak );
+		float getPeak_R() {	return m_fPeakValue_R;	}
+
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void wheelEvent( QWheelEvent *ev );
+		virtual void paintEvent(QPaintEvent *ev);
+
+	signals:
+		void valueChanged(Fader *ref);
+
+	private:
+		bool m_bWithoutKnob;
+		bool m_bUseIntSteps;
+
+		float m_fPeakValue_L;
+		float m_fPeakValue_R;
+		float m_fMinPeak;
+		float m_fMaxPeak;
+
+		float m_fValue;
+		float m_fMinValue;
+		float m_fMaxValue;
+
+		QPixmap m_back;
+		QPixmap m_leds;
+		QPixmap m_knob;
+};
+
+
+
+
+class MasterFader : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		MasterFader(QWidget *pParent, bool bWithoutKnob = false);
+		~MasterFader();
+
+		void setMin( float fMin );
+		void setMax( float fMax );
+		float getMin() {	return m_fMin;	}
+		float getMax() {	return m_fMax;	}
+
+		void setValue( float newValue );
+		float getValue();
+
+		void setPeak_L( float peak );
+		float getPeak_L() {	return m_fPeakValue_L;	}
+
+		void setPeak_R( float peak );
+		float getPeak_R() {	return m_fPeakValue_R;	}
+
+		virtual void mousePressEvent( QMouseEvent *ev );
+		virtual void mouseMoveEvent( QMouseEvent *ev );
+		virtual void paintEvent( QPaintEvent *ev );
+		virtual void wheelEvent( QWheelEvent *ev );
+
+	signals:
+		void valueChanged( MasterFader *ref );
+
+	private:
+		bool m_bWithoutKnob;
+		float m_fPeakValue_L;
+		float m_fPeakValue_R;
+
+		float m_fValue;
+		float m_fMin;
+		float m_fMax;
+
+		QPixmap m_back;
+		QPixmap m_leds;
+		QPixmap m_knob;
+
+
+};
+
+
+
+class Knob : public QWidget, public Object
+{
+	Q_OBJECT
+	public:
+		Knob( QWidget* parent );
+		~Knob();
+
+		void setValue( float fValue );
+		float getValue() {	return m_fValue;	}
+
+	signals:
+		void valueChanged( Knob *ref );
+
+	private:
+		static QPixmap *m_background;
+
+		int m_nWidgetWidth;
+		int m_nWidgetHeight;
+
+		float m_fValue;
+		float m_fMousePressValue;
+		float m_fMousePressY;
+
+		virtual void paintEvent( QPaintEvent *ev );
+		virtual void mousePressEvent( QMouseEvent *ev );
+		virtual void mouseReleaseEvent( QMouseEvent *ev );
+		virtual void mouseMoveEvent( QMouseEvent *ev );
+		virtual void wheelEvent( QWheelEvent *ev );
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/LCDCombo.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/LCDCombo.h	(revision 390)
+++ /branches/tabbedInterface/gui/src/widgets/LCDCombo.h	(revision 390)
@@ -0,0 +1,74 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef LCDCOMBO_H
+#define LCDCOMBO_H
+
+#include "config.h"
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+
+class Button;
+class LCDDisplay;
+
+class LCDCombo : public QWidget, public Object
+{
+	Q_OBJECT
+	public:
+		LCDCombo(QWidget *pParent, int digits = 5);
+		~LCDCombo();
+
+		int count();
+		int length();
+		void update();
+		QString getText();
+		bool addItem(const QString &text );
+		void addSeparator();
+		inline void insertItem(int index, const QString &text );
+		void set_text( const QString &text );
+		void set_text( const QString &text, bool );
+
+
+	private slots:
+		void changeText(QAction*);
+		void onClick(Button*);
+
+	signals:
+		void valueChanged( QString str );
+
+	private:
+		QStringList items;
+		LCDDisplay *display;
+		Button *button;
+		QMenu *pop;
+		int size;
+		int active;
+		static const QString SEPARATOR;
+
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void wheelEvent( QWheelEvent * ev );
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/MidiSenseWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/MidiSenseWidget.h	(revision 581)
+++ /branches/tabbedInterface/gui/src/widgets/MidiSenseWidget.h	(revision 581)
@@ -0,0 +1,47 @@
+	/*
+	 * Hydrogen
+	 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+	 *
+	 * http://www.hydrogen-music.org
+	 *
+	 * This program is free software; you can redistribute it and/or modify
+	 * it under the terms of the GNU General Public License as published by
+	 * the Free Software Foundation; either version 2 of the License, or
+	 * (at your option) any later version.
+	 *
+	 * This program is distributed in the hope that it will be useful,
+	 * but WITHOUT ANY WARRANTY, without even the implied warranty of
+	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	 * GNU General Public License for more details.
+	 *
+	 * You should have received a copy of the GNU General Public License
+	 * along with this program; if not, write to the Free Software
+	 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+	 *
+	 */
+	#ifndef MIDISENSE_WIDGET_H
+	#define MIDISENSE_WIDGET_H
+
+	#include <QtGui>
+
+	#include <hydrogen/Object.h>
+
+	class MidiSenseWidget : public QDialog ,public Object
+	{
+	Q_OBJECT
+	public:
+		MidiSenseWidget(QWidget*);
+		~MidiSenseWidget();
+
+		QString lastMidiEvent;
+		int lastMidiEventParameter;
+	
+	private slots:
+		void updateMidi();
+
+	private:
+		QTimer* m_pUpdateTimer;
+		QLabel* m_pURLLabel;
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/widgets/midiTable.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/midiTable.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/widgets/midiTable.cpp	(revision 1244)
@@ -0,0 +1,251 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "../Skin.h"
+#include "MidiSenseWidget.h"
+#include "midiTable.h"
+
+#include <hydrogen/midiMap.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/globals.h>
+#include <hydrogen/action.h>
+#include <hydrogen/hydrogen.h>
+
+MidiTable::MidiTable( QWidget *pParent )
+ : QTableWidget( pParent )
+ , Object( "MidiTable" )
+{
+	__row_count = 0;
+	setupMidiTable();
+
+	m_pUpdateTimer = new QTimer( this );
+	currentMidiAutosenseRow = 0;
+}
+
+
+MidiTable::~MidiTable()
+{
+	for( int myRow = 0; myRow <=  __row_count ; myRow++ ) {
+		delete cellWidget( myRow, 0 );
+		delete cellWidget( myRow, 1 );
+		delete cellWidget( myRow, 2 );
+		delete cellWidget( myRow, 3 );
+	}
+}
+
+void MidiTable::midiSensePressed( int row ){
+
+	currentMidiAutosenseRow = row;
+	MidiSenseWidget mW( this );
+	mW.exec();
+
+	QComboBox * eventCombo =  dynamic_cast <QComboBox *> ( cellWidget( row, 1 ) );
+	QSpinBox * eventSpinner = dynamic_cast <QSpinBox *> ( cellWidget( row, 2 ) );
+
+
+	eventCombo->setCurrentIndex( eventCombo->findText( mW.lastMidiEvent ) );
+	eventSpinner->setValue( mW.lastMidiEventParameter );
+
+	m_pUpdateTimer->start( 100 );	
+}
+
+
+void MidiTable::updateTable()
+{
+	if( __row_count > 0 ) {
+		QComboBox * eventCombo =  dynamic_cast <QComboBox *> ( cellWidget( __row_count - 1, 1 ) );
+		QComboBox * actionCombo = dynamic_cast <QComboBox *> ( cellWidget( __row_count - 1, 3 ) );
+
+		if( eventCombo == NULL || actionCombo == NULL) return;
+
+		if( actionCombo->currentText() != "" && eventCombo->currentText() != "" ) {
+			insertNewRow("", "", 0, 0);
+		}
+	}
+}
+
+
+void MidiTable::insertNewRow(QString actionString , QString eventString, int eventParameter , int actionParameter)
+{
+	ActionManager *aH = ActionManager::get_instance();
+
+	insertRow( __row_count );
+	
+	int oldRowCount = __row_count;
+
+	++__row_count;
+
+	
+
+	QPushButton *midiSenseButton = new QPushButton(this);
+	midiSenseButton->setIcon(QIcon(Skin::getImagePath() + "/preferencesDialog/rec.png"));
+	midiSenseButton->setToolTip( trUtf8("press button to record midi event") );
+
+	QSignalMapper *signalMapper = new QSignalMapper(this);
+
+	connect(midiSenseButton, SIGNAL( clicked()), signalMapper, SLOT( map() ));
+	signalMapper->setMapping( midiSenseButton, oldRowCount );
+	connect( signalMapper, SIGNAL(mapped( int ) ),
+         this, SLOT( midiSensePressed(int) ) );
+	setCellWidget( oldRowCount, 0, midiSenseButton );
+
+
+
+	QComboBox *eventBox = new QComboBox();
+	connect( eventBox , SIGNAL( currentIndexChanged( int ) ) , this , SLOT( updateTable() ) );
+	eventBox->insertItems( oldRowCount , aH->getEventList() );
+	eventBox->setCurrentIndex( eventBox->findText(eventString) );
+	setCellWidget( oldRowCount, 1, eventBox );
+	
+	
+	QSpinBox *eventParameterSpinner = new QSpinBox();
+	setCellWidget( oldRowCount , 2, eventParameterSpinner );
+	eventParameterSpinner->setMaximum( 999 );
+	eventParameterSpinner->setValue( eventParameter );
+
+
+	QComboBox *actionBox = new QComboBox();
+	connect( actionBox , SIGNAL( currentIndexChanged( int ) ) , this , SLOT( updateTable() ) );
+	actionBox->insertItems( oldRowCount, aH->getActionList());
+	actionBox->setCurrentIndex ( actionBox->findText( actionString ) );
+	setCellWidget( oldRowCount , 3, actionBox );
+	
+
+	QSpinBox *actionParameterSpinner = new QSpinBox();
+	
+	setCellWidget( oldRowCount , 4, actionParameterSpinner );
+	actionParameterSpinner->setValue( actionParameter);
+	actionParameterSpinner->setMaximum( 999 );
+
+
+}
+
+void MidiTable::setupMidiTable()
+{
+	MidiMap *mM = MidiMap::get_instance();
+
+	QStringList items;
+	items << "" << trUtf8("Event")  <<  trUtf8("Param.")  <<  trUtf8("Action") <<  trUtf8("Param.") ;
+
+	setRowCount( 0 );
+    	setColumnCount( 5 );
+
+	verticalHeader()->hide();
+
+	setHorizontalHeaderLabels( items );
+	
+	
+	setFixedWidth( 500 );
+
+	setColumnWidth( 0 , 25 );
+	setColumnWidth( 1 , 155 );
+	setColumnWidth( 2, 73 );
+	setColumnWidth( 3, 175 );
+	setColumnWidth( 4 , 73 );
+
+
+	bool ok;
+	std::map< QString , Action* > mmcMap = mM->getMMCMap();
+	std::map< QString , Action* >::iterator dIter( mmcMap.begin() );
+
+	
+	for( dIter = mmcMap.begin(); dIter != mmcMap.end(); dIter++ ) {
+		Action * pAction = dIter->second;
+		QString actionParameter;
+		int actionParameterInteger = 0;
+
+		actionParameter = pAction->getParameter1();
+		actionParameterInteger = actionParameter.toInt(&ok,10);
+		
+		insertNewRow(pAction->getType() , dIter->first , 0 , actionParameterInteger );
+	}
+
+	for( int note = 0; note < 128; note++ ) {
+		Action * pAction = mM->getNoteAction( note );
+		QString actionParameter;
+		int actionParameterInteger = 0;
+
+		actionParameter = pAction->getParameter1();
+		actionParameterInteger = actionParameter.toInt(&ok,10);
+		
+
+		if ( pAction->getType() == "NOTHING" ) continue;
+
+		insertNewRow(pAction->getType() , "NOTE" , note , actionParameterInteger );
+	}
+
+	for( int parameter = 0; parameter < 128; parameter++ ){
+		Action * pAction = mM->getCCAction( parameter );
+		QString actionParameter;
+		int actionParameterInteger = 0;
+
+		actionParameter = pAction->getParameter1();
+		actionParameterInteger = actionParameter.toInt(&ok,10);
+
+		if ( pAction->getType() == "NOTHING" ) continue;
+
+		insertNewRow(pAction->getType() , "CC" , parameter , actionParameterInteger );
+	}
+	
+	insertNewRow( "", "", 0, 0 );
+}
+
+
+void MidiTable::saveMidiTable()
+{
+	MidiMap *mM = MidiMap::get_instance();
+	
+	for ( int row = 0; row < __row_count; row++ ) {
+
+		QComboBox * eventCombo =  dynamic_cast <QComboBox *> ( cellWidget( row, 1 ) );
+		QSpinBox * eventSpinner = dynamic_cast <QSpinBox *> ( cellWidget( row, 2 ) );
+		QComboBox * actionCombo = dynamic_cast <QComboBox *> ( cellWidget( row, 3 ) );
+		QSpinBox * actionSpinner = dynamic_cast <QSpinBox *> ( cellWidget( row, 4 ) );
+
+		QString eventString;
+		QString actionString;
+
+		if( eventCombo->currentText() != "" && actionCombo->currentText() != "" ){
+			eventString = eventCombo->currentText();
+
+			actionString = actionCombo->currentText();
+		
+			Action* pAction = new Action( actionString );
+
+			if( actionSpinner->cleanText() != ""){
+				pAction->setParameter1( actionSpinner->cleanText() );
+			}
+	
+			if( eventString.left(2) == "CC" ){
+				mM->registerCCEvent( eventSpinner->cleanText().toInt() , pAction );
+			}
+
+			if( eventString.left(3) == "MMC" ){
+				mM->registerMMCEvent( eventString , pAction );
+			}
+			
+			if( eventString.left(4) == "NOTE" ){
+				mM->registerNoteEvent( eventSpinner->cleanText().toInt() , pAction );
+			}
+		}
+	}
+}
Index: /branches/tabbedInterface/gui/src/widgets/CpuLoadWidget.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/widgets/CpuLoadWidget.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/widgets/CpuLoadWidget.cpp	(revision 1244)
@@ -0,0 +1,164 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "CpuLoadWidget.h"
+#include <hydrogen/hydrogen.h>
+
+#include "../Skin.h"
+#include "../HydrogenApp.h"
+
+#include <QTimer>
+#include <QMouseEvent>
+#include <QPaintEvent>
+#include <QPainter>
+
+
+CpuLoadWidget::CpuLoadWidget( QWidget *pParent )
+ : QWidget( pParent )
+ , Object( "CPULoadQWidget" )
+ , m_fValue( 0 )
+{
+	setAttribute(Qt::WA_NoBackground);
+
+	static const uint WIDTH = 92;
+	static const uint HEIGHT = 8;
+
+	resize( WIDTH, HEIGHT );
+	setMinimumSize( width(), height() );
+	setMaximumSize( width(), height() );
+
+	m_nXRunValue = 0;
+
+	// Background image
+	QString background_path = Skin::getImagePath().append( "/playerControlPanel/cpuLoad_back.png" );
+	bool ok = m_back.load( background_path );
+	if( !ok ) {
+		ERRORLOG( "Error loading pixmap " + background_path );
+	}
+
+	// Leds image
+	QString leds_path = Skin::getImagePath().append( "/playerControlPanel/cpuLoad_leds.png" );
+	ok = m_leds.load( leds_path );
+	if( !ok ) {
+		ERRORLOG( "Error loading pixmap " + leds_path );
+	}
+
+	QTimer *timer = new QTimer(this);
+	connect( timer, SIGNAL( timeout() ), this, SLOT( updateCpuLoadWidget() ) );
+	timer->start(200);	// update player control at 5 fps
+
+	HydrogenApp::get_instance()->addEventListener( this );
+}
+
+
+
+CpuLoadWidget::~CpuLoadWidget()
+{
+}
+
+
+
+void CpuLoadWidget::mousePressEvent(QMouseEvent *ev)
+{
+	UNUSED( ev );
+}
+
+
+
+void CpuLoadWidget::setValue(float newValue)
+{
+	if ( newValue > 1.0 ) {
+		newValue = 1.0;
+	}
+	else if (newValue < 0.0) {
+		newValue = 0.0;
+	}
+
+	if (m_fValue != newValue) {
+		m_fValue = newValue;
+	}
+}
+
+
+
+float CpuLoadWidget::getValue()
+{
+	return m_fValue;
+}
+
+
+
+void CpuLoadWidget::paintEvent( QPaintEvent*)
+{
+	if (!isVisible()) {
+		return;
+	}
+
+	QPainter painter(this);
+
+	// background
+//	bitBlt( &m_temp, 0, 0, &m_back, 0, 0, width(), height(), CopyROP );
+	painter.drawPixmap( rect(), m_back, QRect( 0, 0, width(), height() ) );
+
+	// leds
+	int pos = (int)( 3 + m_fValue * ( width() - 3 * 2 ) );
+//	bitBlt( &m_temp, 0, 0, &m_leds, 0, 0, pos, height(), CopyROP );
+	painter.drawPixmap( QRect( 0, 0, pos, height() ), m_leds, QRect( 0, 0, pos, height() ) );
+
+	if (m_nXRunValue > 0) {
+		// xrun led
+//		bitBlt( &m_temp, 90, 0, &m_leds, 90, 0, width(), height(), CopyROP );
+		painter.drawPixmap( QRect( 90, 0, width(), height() ), m_leds, QRect( 90, 0, width(), height() ) );
+	}
+}
+
+
+
+void CpuLoadWidget::updateCpuLoadWidget()
+{
+	// Process time
+	H2Core::Hydrogen *engine = H2Core::Hydrogen::get_instance();
+	int perc = 0;
+	if ( engine->getMaxProcessTime() != 0.0 ) {
+		perc = (int)( engine->getProcessTime() / ( engine->getMaxProcessTime() / 100.0 ) );
+	}
+	setValue( perc / 100.0 );
+
+	if (m_nXRunValue > 0) {
+		m_nXRunValue -= 5;
+	}
+
+	update();
+}
+
+
+
+void CpuLoadWidget::XRunEvent()
+{
+	INFOLOG( "[xRunEvent]" );
+	m_nXRunValue = 100;
+	update();
+}
+
+
+
Index: /branches/tabbedInterface/gui/src/PreferencesDialog.h
===================================================================
--- /branches/tabbedInterface/gui/src/PreferencesDialog.h	(revision 1286)
+++ /branches/tabbedInterface/gui/src/PreferencesDialog.h	(revision 1286)
@@ -0,0 +1,62 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef PREFERENCES_DIALOG_H
+#define PREFERENCES_DIALOG_H
+
+#include "config.h"
+
+#include "ui_PreferencesDialog_UI.h"
+
+#include <hydrogen/Object.h>
+
+///
+/// Preferences Dialog
+///
+class PreferencesDialog : public QDialog, private Ui_PreferencesDialog_UI, public Object
+{
+	Q_OBJECT
+	public:
+		PreferencesDialog( QWidget* parent );
+		~PreferencesDialog();
+
+	private slots:
+		void on_okBtn_clicked();
+		void on_cancelBtn_clicked();
+		void on_selectApplicationFontBtn_clicked();
+		void on_selectMixerFontBtn_clicked();
+		void on_restartDriverBtn_clicked();
+		void on_driverComboBox_activated( int index );
+		void on_bufferSizeSpinBox_valueChanged( int i );
+		void on_sampleRateComboBox_editTextChanged( const QString& text );
+		void on_midiPortComboBox_activated( int index );
+		void on_styleComboBox_activated( int index );
+		void on_useLashCheckbox_clicked();
+
+	private:
+		bool m_bNeedDriverRestart;
+
+		void updateDriverInfo();
+};
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/AudioEngineInfoForm.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/AudioEngineInfoForm.cpp	(revision 1244)
+++ /branches/tabbedInterface/gui/src/AudioEngineInfoForm.cpp	(revision 1244)
@@ -0,0 +1,265 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "AudioEngineInfoForm.h"
+
+#include <QtGui>
+
+#include "HydrogenApp.h"
+
+#include <hydrogen/Pattern.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/IO/MidiInput.h>
+#include <hydrogen/IO/AudioOutput.h>
+#include <hydrogen/sampler/Sampler.h>
+#include <hydrogen/audio_engine.h>
+using namespace H2Core;
+
+#include "Skin.h"
+
+AudioEngineInfoForm::AudioEngineInfoForm(QWidget* parent)
+ : QWidget( parent )
+ , Object( "AudioEngineInfoForm" )
+{
+	setupUi( this );
+
+	setMinimumSize( width(), height() );	// not resizable
+	setMaximumSize( width(), height() );	// not resizable
+
+	setWindowTitle( trUtf8( "Audio Engine Info" ) );
+
+	updateInfo();
+	//currentPatternLbl->setText("NULL pattern");
+
+	timer = new QTimer(this);
+	connect(timer, SIGNAL(timeout()), this, SLOT(updateInfo()));
+
+	HydrogenApp::get_instance()->addEventListener( this );
+	updateAudioEngineState();
+}
+
+
+
+/**
+ * Destructor
+ */
+AudioEngineInfoForm::~AudioEngineInfoForm()
+{
+}
+
+
+
+
+/**
+ * show event
+ */
+void AudioEngineInfoForm::showEvent ( QShowEvent* )
+{
+	updateInfo();
+	timer->start(200);
+}
+
+
+
+
+/**
+ * hide event
+ */
+void AudioEngineInfoForm::hideEvent ( QHideEvent* )
+{
+	timer->stop();
+}
+
+
+
+
+void AudioEngineInfoForm::updateInfo()
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *song = pEngine->getSong();
+
+	// Song position
+	QString sSongPos = "N/A";
+	if ( pEngine->getPatternPos() != -1 ) {
+		sSongPos = QString::number( pEngine->getPatternPos() );
+	}
+	m_pSongPositionLbl->setText( sSongPos );
+
+
+	// Audio engine Playing notes
+	char tmp[100];
+
+	// Process time
+	int perc = 0;
+	if ( pEngine->getMaxProcessTime() != 0.0 ) {
+		perc= (int)( pEngine->getProcessTime() / ( pEngine->getMaxProcessTime() / 100.0 ) );
+	}
+	sprintf(tmp, "%#.2f / %#.2f  (%d%%)", pEngine->getProcessTime(), pEngine->getMaxProcessTime(), perc );
+	processTimeLbl->setText(tmp);
+
+	// Song state
+	if (song == NULL) {
+		songStateLbl->setText( "NULL song" );
+	}
+	else {
+		if (song->__is_modified) {
+			songStateLbl->setText( "Modified" );
+		}
+		else {
+			songStateLbl->setText( "Saved" );
+		}
+	}
+
+	// tick number
+	sprintf(tmp, "%03d", (int)pEngine->getTickPosition() );
+	nTicksLbl->setText(tmp);
+
+
+
+	// Audio driver info
+	AudioOutput *driver = pEngine->getAudioOutput();
+	if (driver) {
+		QString audioDriverName = driver->get_class_name();
+		driverLbl->setText(audioDriverName);
+
+		// Audio driver buffer size
+		sprintf(tmp, "%d", driver->getBufferSize());
+		bufferSizeLbl->setText(QString(tmp));
+
+		// Audio driver sampleRate
+		sprintf(tmp, "%d", driver->getSampleRate());
+		sampleRateLbl->setText(QString(tmp));
+
+		// Number of frames
+		sprintf(tmp, "%d", (int)driver->m_transport.m_nFrames );
+		nFramesLbl->setText(tmp);
+	}
+	else {
+		driverLbl->setText( "NULL driver" );
+		bufferSizeLbl->setText( "N/A" );
+		sampleRateLbl->setText( "N/A" );
+		nFramesLbl->setText( "N/A" );
+	}
+	nRealtimeFramesLbl->setText( QString( "%1" ).arg( pEngine->getRealtimeFrames() ) );
+
+
+	// Midi driver info
+	MidiInput *pMidiDriver = pEngine->getMidiInput();
+	if (pMidiDriver) {
+		midiDriverName->setText( pMidiDriver->get_class_name() );
+	}
+	else {
+		midiDriverName->setText("No MIDI driver support");
+	}
+
+	m_pMidiDeviceName->setText( Preferences::get_instance()->m_sMidiPortName );
+
+
+	int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
+	if (nSelectedPatternNumber == -1) {
+		selectedPatLbl->setText( "N/A");
+	}
+	else {
+		selectedPatLbl->setText( QString("%1").arg(nSelectedPatternNumber) );
+	}
+
+	int nSelectedInstrumentNumber = pEngine->getSelectedInstrumentNumber();
+	if (nSelectedInstrumentNumber == -1) {
+		m_pSelectedInstrLbl->setText( "N/A" );
+	}
+	else {
+		m_pSelectedInstrLbl->setText( QString("%1").arg(nSelectedInstrumentNumber) );
+	}
+
+
+	QString currentPatternName;
+	PatternList *pPatternList = Hydrogen::get_instance()->getCurrentPatternList();
+	if (pPatternList) {
+		currentPatternLbl->setText( QString::number(pPatternList->get_size()) );
+	}
+	else {
+		currentPatternLbl->setText( "N/A" );
+	}
+
+	// SAMPLER
+	Sampler *pSampler = AudioEngine::get_instance()->get_sampler();
+	sampler_playingNotesLbl->setText(QString( "%1 / %2" ).arg(pSampler->get_playing_notes_number()).arg(Preferences::get_instance()->m_nMaxNotes));
+
+	// Synth
+	Synth *pSynth = AudioEngine::get_instance()->get_synth();
+	synth_playingNotesLbl->setText( QString( "%1" ).arg( pSynth->getPlayingNotesNumber() ) );
+}
+
+
+
+
+
+
+/**
+ * Update engineStateLbl with the current audio engine state
+ */
+void AudioEngineInfoForm::updateAudioEngineState() {
+	// Audio Engine state
+	QString stateTxt;
+	int state = Hydrogen::get_instance()->getState();
+	switch (state) {
+	case STATE_UNINITIALIZED:
+		stateTxt = "Uninitialized";
+		break;
+
+	case STATE_INITIALIZED:
+		stateTxt = "Initialized";
+		break;
+
+	case STATE_PREPARED:
+		stateTxt = "Prepared";
+		break;
+
+	case STATE_READY:
+		stateTxt = "Ready";
+		break;
+
+	case STATE_PLAYING:
+		stateTxt = "Playing";
+		break;
+
+	default:
+		stateTxt = "Unknown!?";
+		break;
+	}
+	engineStateLbl->setText(stateTxt);
+}
+
+
+void AudioEngineInfoForm::stateChangedEvent( int )
+{
+	updateAudioEngineState();
+}
+
+
+void AudioEngineInfoForm::patternChangedEvent()
+{
+	updateAudioEngineState();
+}
+
+
Index: /branches/tabbedInterface/gui/src/SplashScreen.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SplashScreen.cpp	(revision 1478)
+++ /branches/tabbedInterface/gui/src/SplashScreen.cpp	(revision 1478)
@@ -0,0 +1,87 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "config.h"
+#include "version.h"
+#include "SplashScreen.h"
+
+#include <QPainter>
+#include <QLabel>
+#include <QApplication>
+#include <QDesktopWidget>
+
+#include "Skin.h"
+
+
+
+SplashScreen::SplashScreen()
+// : QWidget( NULL, Qt::SplashScreen )
+ : QSplashScreen( NULL )
+ , Object( "SplashScreen" )
+{
+	//INFOLOG( "SplashScreen" );
+
+	//resize(width, height);
+	setFixedSize(width, height);
+
+	m_pBackground = new QPixmap( Skin::getImagePath() + "/splash/splash.png" );
+
+	QFont font;
+	font.setPointSize( 10 );
+	font.setBold( true );
+
+	QPainter p;
+	p.begin( m_pBackground );
+	p.setFont( font );
+	p.setPen( QColor( 20, 20, 20 ) );
+
+	QString version = QString( "v%1 (%2)" ).arg( get_version().c_str() ).arg( __DATE__ );
+	p.drawText( 5, 5, width - 10, 40, Qt::AlignRight | Qt::AlignTop, version );
+
+//	p.drawText( 5, height - 45, width - 10, 40, Qt::AlignHCenter | Qt::AlignBottom, QString( trUtf8( "Modules: %1" ) ).arg( COMPILED_FEATURES ) );
+	p.end();
+
+	setPixmap( *m_pBackground );
+
+
+	// Center on screeen
+	QRect rect( QApplication::desktop()->screenGeometry() );
+	move( rect.center() - this->rect().center() );
+
+	QTimer::singleShot( 5000, this, SLOT( onCloseTimer() ) );
+}
+
+
+
+
+SplashScreen::~SplashScreen()
+{
+	//INFOLOG( "~SplashScreen" );
+	delete m_pBackground;
+}
+
+
+
+void SplashScreen::onCloseTimer()
+{
+	hide();
+}
Index: /branches/tabbedInterface/gui/src/EventListener.h
===================================================================
--- /branches/tabbedInterface/gui/src/EventListener.h	(revision 1459)
+++ /branches/tabbedInterface/gui/src/EventListener.h	(revision 1459)
@@ -0,0 +1,48 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef EVENT_LISTENER
+#define EVENT_LISTENER
+
+#include <hydrogen/globals.h>
+
+class EventListener
+{
+	public:
+		virtual void stateChangedEvent(int nState) { UNUSED( nState ); }
+		virtual void patternChangedEvent() {}
+		virtual void patternModifiedEvent() {}
+		virtual void selectedPatternChangedEvent() {}
+		virtual void selectedInstrumentChangedEvent() {}
+		virtual void midiActivityEvent() {}
+		virtual void noteOnEvent( int nInstrument ) { UNUSED( nInstrument ); }
+		virtual void XRunEvent() {}
+		virtual void errorEvent( int nErrorCode ) { UNUSED( nErrorCode ); }
+		virtual void metronomeEvent( int nValue ) { UNUSED( nValue ); }
+		virtual void rubberbandbpmchangeEvent() {}
+		virtual void progressEvent( int nValue ) { UNUSED( nValue ); }
+
+		virtual ~EventListener() {}
+};
+
+
+#endif
+
Index: /branches/tabbedInterface/gui/src/HelpBrowser.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/HelpBrowser.cpp	(revision 1367)
+++ /branches/tabbedInterface/gui/src/HelpBrowser.cpp	(revision 1367)
@@ -0,0 +1,162 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "HelpBrowser.h"
+#include "Skin.h"
+
+#include <QtGui>
+#include <hydrogen/globals.h>
+
+SimpleHTMLBrowser::SimpleHTMLBrowser( QWidget *pParent, const QString& sDataPath, const QString& sFilename, SimpleHTMLBrowserType type )
+ : QDialog( pParent )
+ , Object( "SimpleHTMLBrowser" )
+ , m_type( type )
+ , m_sDataPath( sDataPath )
+ , m_sFilename( sFilename )
+{
+//	INFOLOG( "INIT" );
+//	INFOLOG( "Data path:" + m_sDataPath );
+//	INFOLOG( "Filename:" + m_sFilename );
+	setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	if (m_type == MANUAL ) {
+		setWindowTitle( trUtf8( "Manual" ) );
+		resize( 800, 600 );
+		setMinimumSize( 300, 200 );
+		setStyleSheet("color:#000000;");
+	}
+	else {
+		setWindowTitle( trUtf8( "Welcome to Hydrogen" ) );
+		resize( 800, 650 );
+		setMinimumSize( width(), height() );
+		setMaximumSize( width(), height() );
+		// is not present in qt 3.0?
+		//setModal( true );
+	}
+
+	m_pDontShowAnymoreBtn = new QPushButton( trUtf8( "Don't show this message anymore"), this );
+	connect( m_pDontShowAnymoreBtn, SIGNAL( clicked() ), this, SLOT( dontShowAnymoreBtnClicked() ) );
+	m_pDontShowAnymoreBtn->resize( 300, 25 );
+	m_pDontShowAnymoreBtn->hide();
+
+	m_pCloseWindowBtn = new QPushButton( trUtf8( "Ok" ), this );
+	connect( m_pCloseWindowBtn, SIGNAL( clicked() ), this, SLOT( closeWindow() ) );
+	m_pCloseWindowBtn->resize( 100, 25 );
+	m_pCloseWindowBtn->hide();
+
+	m_pDocHomeBtn = new QPushButton( trUtf8( "Documentation index" ), this );
+	connect( m_pDocHomeBtn, SIGNAL( clicked() ), this, SLOT( docIndex() ) );
+	m_pDocHomeBtn->resize( 300, 25 );
+	m_pDocHomeBtn->hide();
+
+/*	Q3MimeSourceFactory * bodyformat = new Q3MimeSourceFactory;
+	bodyformat->setExtensionType("html", "text/html");
+	bodyformat->setExtensionType( "png", "image/png" );
+	bodyformat->setFilePath( QStringList( m_sDataPath.c_str() ) );
+*/
+	m_pBrowser = new QTextBrowser( this );
+//	m_pBrowser->setMimeSourceFactory( bodyformat );
+	m_pBrowser->setReadOnly( true );
+	m_pBrowser->setSearchPaths( QStringList( m_sDataPath ) );
+	//m_pBrowser->setStyleSheet("background-color:#000000;");
+
+//	setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
+
+	QFile file( m_sFilename.toLocal8Bit() ); // Read the text from a file
+	if ( file.open( QIODevice::ReadOnly ) ) {
+		QTextStream stream( &file );
+		m_pBrowser->setHtml( stream.readAll() );
+	}
+
+	QRect rect( QApplication::desktop()->screenGeometry() );
+	move( rect.center() - this->rect().center() );
+}
+
+
+
+SimpleHTMLBrowser::~SimpleHTMLBrowser()
+{
+//	INFOLOG( "DESTROY" );
+}
+
+
+
+void SimpleHTMLBrowser::showEvent ( QShowEvent *ev )
+{
+	UNUSED( ev );
+//	INFOLOG( "[showEvent]" );
+}
+
+
+
+void SimpleHTMLBrowser::resizeEvent( QResizeEvent *ev )
+{
+	UNUSED( ev );
+
+	if ( m_type == MANUAL ) {
+		m_pBrowser->move( 0, 29 );
+		m_pBrowser->resize( width(), height() - 29 );
+
+		m_pDocHomeBtn->move( 5, 3 );
+		m_pDocHomeBtn->show();
+
+		m_pDontShowAnymoreBtn->hide();
+		m_pCloseWindowBtn->hide();
+	}
+	else if ( m_type == WELCOME ) {
+		m_pBrowser->move( 0, 0 );
+		m_pBrowser->resize( width(), height() - 29 );
+
+		m_pDontShowAnymoreBtn->move( width() - m_pDontShowAnymoreBtn->width() - m_pCloseWindowBtn->width() - 5 - 5, height() - 27 );
+		m_pDontShowAnymoreBtn->show();
+
+		m_pCloseWindowBtn->move( width() - m_pCloseWindowBtn->width() - 5, height() - 27 );
+		m_pCloseWindowBtn->show();
+		m_pCloseWindowBtn->setDefault(true);
+
+		m_pDocHomeBtn->hide();
+	}
+}
+
+
+void SimpleHTMLBrowser::dontShowAnymoreBtnClicked()
+{
+	accept();
+}
+
+void SimpleHTMLBrowser::closeWindow()
+{
+	reject();
+}
+
+void SimpleHTMLBrowser::docIndex()
+{
+	INFOLOG( "[docIndex]" );
+
+	QFile file( m_sFilename ); // Read the text from a file
+	if ( file.open( QIODevice::ReadOnly ) ) {
+		QTextStream stream( &file );
+		m_pBrowser->setHtml( stream.readAll() );
+	}
+
+}
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget.cpp	(revision 1233)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget.cpp	(revision 1233)
@@ -0,0 +1,132 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QtGui>
+
+
+#include "../HydrogenApp.h"
+#include "SongEditorPanelBpmWidget.h"
+#include "SongEditorPanel.h"
+#include "SongEditor.h"
+#include <hydrogen/hydrogen.h>
+
+namespace H2Core
+{
+
+SongEditorPanelBpmWidget::SongEditorPanelBpmWidget( QWidget* pParent, int beat )
+	: QDialog( pParent )
+	, Object( "SongEditorPanelBpmWidget" )
+	, m_stimelineposition ( beat )
+{
+	setupUi( this );
+	INFOLOG( "INIT" );
+	setWindowTitle( trUtf8( "BPM" ) );	
+	setFixedSize( width(), height() );
+
+	lineEditBeat->setText(QString("%1").arg( m_stimelineposition + 1) );
+	deleteBtn->setEnabled ( false );
+
+	Hydrogen* engine = Hydrogen::get_instance();
+	std::vector<Hydrogen::HTimelineVector> timelineVector = engine->m_timelinevector;
+
+	//restore the bpm value
+	if( timelineVector.size() > 0 ){
+		for ( int t = 0; t < timelineVector.size(); t++ ){
+//			ERRORLOG(QString("%1 %2").arg(Hydrogen::get_instance()->m_timelinevector[t].m_htimelinebeat).arg(m_stimelineposition));
+			if ( timelineVector[t].m_htimelinebeat == m_stimelineposition ) {
+				lineEditBpm->setText( QString("%1").arg( timelineVector[t].m_htimelinebpm ) );
+				deleteBtn->setEnabled ( true );
+				return;
+			}
+			else
+			{
+				lineEditBpm->setText( QString("%1").arg( engine->getNewBpmJTM()) );
+			}
+		}
+	}else
+	{
+		lineEditBpm->setText( QString("%1").arg( engine->getNewBpmJTM() ) );
+	}
+}
+
+
+
+
+SongEditorPanelBpmWidget::~SongEditorPanelBpmWidget()
+{
+	INFOLOG( "DESTROY" );
+}
+
+
+
+void SongEditorPanelBpmWidget::on_CancelBtn_clicked()
+{
+	reject();
+}
+
+
+
+void SongEditorPanelBpmWidget::on_okBtn_clicked()
+{
+	Hydrogen* engine = Hydrogen::get_instance();
+	
+	//erase the value to set the new value
+	if( engine->m_timelinevector.size() >= 1 ){
+		for ( int t = 0; t < engine->m_timelinevector.size(); t++){
+			if ( engine->m_timelinevector[t].m_htimelinebeat == ( QString( lineEditBeat->text() ).toInt() ) -1 ) {
+				engine->m_timelinevector.erase( engine->m_timelinevector.begin() +  t);
+			}
+		}
+	}
+
+	Hydrogen::HTimelineVector tlvector;
+
+	tlvector.m_htimelinebeat = ( QString( lineEditBeat->text() ).toInt() ) -1 ;
+	float bpm;
+	bpm = QString( lineEditBpm->text() ).toFloat();
+	if( bpm < 30.0 ) bpm = 30.0;
+	if( bpm > 500.0 ) bpm = 500.0;	
+	tlvector.m_htimelinebpm = bpm;
+	engine->m_timelinevector.push_back( tlvector );
+	engine->sortTimelineVector();
+	accept();
+}
+
+
+void SongEditorPanelBpmWidget::on_deleteBtn_clicked()
+{
+	Hydrogen* engine = Hydrogen::get_instance();
+	std::vector<Hydrogen::HTimelineVector> timelineVector = engine->m_timelinevector;
+	
+	if( timelineVector.size() > 0 ){
+		for ( int t = 0; t < timelineVector.size(); t++){
+			if ( timelineVector[t].m_htimelinebeat == m_stimelineposition ) {
+				timelineVector.erase( timelineVector.begin() +  t);
+			}
+		}
+	}
+	
+	engine->m_timelinevector = timelineVector;
+	accept();
+}
+
+}
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditor.h
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditor.h	(revision 1498)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditor.h	(revision 1498)
@@ -0,0 +1,192 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SONG_EDITOR_H
+#define SONG_EDITOR_H
+
+#include <vector>
+
+#include <QtGui>
+
+#include <hydrogen/Object.h>
+#include "../EventListener.h"
+#include "../PatternFillDialog.h"
+
+class Button;
+class ToggleButton;
+class SongEditor;
+class SongEditorPatternList;
+class SongEditorPositionRuler;
+
+
+static const uint SONG_EDITOR_MIN_GRID_WIDTH = 8;
+static const uint SONG_EDITOR_MAX_GRID_WIDTH = 16;
+
+///
+/// Song editor
+///
+class SongEditor : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		SongEditor( QWidget *parent );
+		~SongEditor();
+
+		void createBackground();
+
+		void cleanUp();
+
+		int getGridWidth ();
+		void setGridWidth( uint width);
+
+	private:
+		unsigned m_nGridHeight;
+		unsigned m_nGridWidth;
+		unsigned m_nMaxPatternSequence;
+		bool m_bSequenceChanged;
+		bool m_bIsMoving;
+		bool m_bIsCtrlPressed;
+
+		QPixmap *m_pBackgroundPixmap;
+		QPixmap *m_pSequencePixmap;
+
+		std::vector<QPoint> m_selectedCells;
+		std::vector<QPoint> m_movingCells;
+		QPoint m_clickPoint;	// Usato come riferimento per le operazioni di spostamento
+		bool m_bShowLasso;
+		QRect m_lasso;
+
+		virtual void mousePressEvent(QMouseEvent *ev);
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void keyPressEvent (QKeyEvent *ev);
+		virtual void paintEvent(QPaintEvent *ev);
+
+		void drawSequence();
+		void drawPattern( int pos, int number, bool invertColour );
+};
+
+
+
+
+///
+/// Song editor pattern list
+///
+class SongEditorPatternList : public QWidget, public Object, public EventListener
+{
+	Q_OBJECT
+
+	public:
+		SongEditorPatternList( QWidget *parent );
+		~SongEditorPatternList();
+
+		void updateEditor();
+		void createBackground();
+
+	public slots:
+		void patternPopup_edit();
+		void patternPopup_save();
+		void patternPopup_load();
+		void patternPopup_properties();
+		void patternPopup_delete();
+		void patternPopup_copy();
+		void patternPopup_fill();
+		void patternPopup_virtualPattern();
+		void inlineEditingFinished();
+		void inlineEditingEntered();
+		virtual void dragEnterEvent(QDragEnterEvent *event);
+		virtual void dropEvent(QDropEvent *event);
+
+
+	private:
+		uint m_nGridHeight;
+		uint m_nWidth;
+		static const uint m_nInitialHeight = 10;
+
+		QPixmap *m_pBackgroundPixmap;
+
+		QPixmap m_labelBackgroundLight;
+		QPixmap m_labelBackgroundDark;
+		QPixmap m_labelBackgroundSelected;
+		QPixmap m_playingPattern_on_Pixmap;
+		QPixmap m_playingPattern_off_Pixmap;
+
+		QMenu *m_pPatternPopup;
+		QLineEdit *line;
+		H2Core::Pattern *patternBeingEdited;
+		void inlineEditPatternName( int row );
+
+		virtual void mousePressEvent( QMouseEvent *ev );
+		virtual void mouseDoubleClickEvent( QMouseEvent *ev );
+		virtual void paintEvent( QPaintEvent *ev );
+
+		void fillRangeWithPattern(FillRange* r, int nPattern);
+		void togglePattern( int );
+
+		virtual void patternChangedEvent();
+		void mouseMoveEvent(QMouseEvent *event);
+		void movePatternLine(int,int);
+		QPoint __drag_start_position;
+
+};
+
+
+// class SongEditorPatternListener : public EventListener {
+//
+// }
+//
+
+class SongEditorPositionRuler : public QWidget, public Object
+{
+	Q_OBJECT
+
+	public:
+		SongEditorPositionRuler( QWidget *parent );
+		~SongEditorPositionRuler();
+
+		void createBackground();
+
+		uint getGridWidth();
+		void setGridWidth (uint width);
+
+	public slots:
+		void updatePosition();
+
+	private:
+		QTimer *m_pTimer;
+		uint m_nGridWidth;
+		uint m_nMaxPatternSequence;
+		uint m_nInitialWidth;
+		static const uint m_nHeight = 50;
+
+		QPixmap *m_pBackgroundPixmap;
+		QPixmap m_tickPositionPixmap;
+		virtual void mouseMoveEvent(QMouseEvent *ev);
+		virtual void mousePressEvent( QMouseEvent *ev );
+		virtual void mouseReleaseEvent(QMouseEvent *ev);
+		virtual void paintEvent( QPaintEvent *ev );
+                bool m_bRightBtnPressed;
+};
+
+
+#endif
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanel.h
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanel.h	(revision 1207)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanel.h	(revision 1207)
@@ -0,0 +1,118 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SONG_EDITOR_PANEL_H
+#define SONG_EDITOR_PANEL_H
+
+
+#include "../EventListener.h"
+#include <hydrogen/Object.h>
+
+#include <QtGui>
+
+class Button;
+class SongEditor;
+class SongEditorPatternList;
+class SongEditorPositionRuler;
+class ToggleButton;
+
+
+enum SongEditorActionMode
+{
+	SELECT_ACTION,
+	DRAW_ACTION
+};
+
+
+class SongEditorPanel : public QWidget, public EventListener, public Object
+{
+	Q_OBJECT
+
+	public:
+		SongEditorPanel( QWidget *parent );
+		~SongEditorPanel();
+
+		void updateAll();
+		void updatePositionRuler();
+		void setModeActionBtn( bool mode );
+		SongEditorActionMode getActionMode() {	return m_actionMode;	}
+
+		// Implements EventListener interface
+		virtual void selectedPatternChangedEvent();
+		//~ Implements EventListener interface
+		
+
+	private slots:
+		void on_patternListScroll();
+		void on_EditorScroll();
+		void syncToExternalScrollBar();
+
+		void newPatBtnClicked( Button* );
+		void upBtnClicked( Button* );
+		void downBtnClicked( Button* );
+		void clearSequence( Button* );
+		void updatePlayHeadPosition();
+
+		void pointerActionBtnPressed( Button* pBtn );
+		void drawActionBtnPressed( Button* pBtn );
+		void timeLineBtnPressed( Button* pBtn );
+		void modeActionBtnPressed( );
+
+		void zoomInBtnPressed( Button* pBtn );
+		void zoomOutBtnPressed( Button* pBtn );
+
+
+	private:
+		SongEditorActionMode m_actionMode;
+
+		uint m_nInitialWidth;
+		uint m_nInitialHeight;
+
+		static const int m_nPatternListWidth = 200;
+
+		QScrollArea* m_pEditorScrollView;
+		QScrollArea* m_pPatternListScrollView;
+		QScrollArea* m_pPositionRulerScrollView;
+		QScrollBar *m_pVScrollBar;
+		QScrollBar *m_pHScrollBar;
+
+
+		SongEditor* m_pSongEditor;
+		SongEditorPatternList *m_pPatternList;
+		SongEditorPositionRuler *m_pPositionRuler;
+
+		Button *m_pUpBtn;
+		Button *m_pDownBtn;
+		Button *m_pClearPatternSeqBtn;
+		ToggleButton *m_pPointerActionBtn;
+		ToggleButton *m_pModeActionBtn;
+		ToggleButton *m_pDrawActionBtn;
+		ToggleButton *m_pTimeLineToggleBtn;
+
+		QTimer* m_pTimer;
+
+
+		virtual void resizeEvent( QResizeEvent *ev );
+		void resyncExternalScrollBar();
+};
+
+#endif
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelTagWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelTagWidget.h	(revision 1430)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelTagWidget.h	(revision 1430)
@@ -0,0 +1,61 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SONG_EDITOR_PANEL_TAG_WIDGET_H
+#define SONG_EDITOR_PANEL_TAG_WIDGET_H
+
+#include <QDialog>
+#include "config.h"
+#include "ui_SongEditorPanelTagWidget_UI.h"
+#include <hydrogen/Object.h>
+
+///
+///
+namespace H2Core
+{
+
+
+class SongEditorPanelTagWidget : public QDialog, public Ui_SongEditorPanelTagWidget_UI, public Object
+{
+
+//lineEditBEAT
+//lineEditBPM
+//deleteBtn
+
+	Q_OBJECT
+	public:
+		SongEditorPanelTagWidget( QWidget* pParent, int beat );
+		~SongEditorPanelTagWidget();
+
+	private slots:
+
+		void on_CancelBtn_clicked();
+		void on_okBtn_clicked();
+		void on_tagTableWidget_currentItemChanged( QTableWidgetItem * current, QTableWidgetItem * previous );
+
+	private:
+		int m_stimelineposition;
+		void createTheTagTableWidget();
+};
+
+}
+#endif
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget.h
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget.h	(revision 1430)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget.h	(revision 1430)
@@ -0,0 +1,60 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SONG_EDITOR_PANEL_BPM_WIDGET_H
+#define SONG_EDITOR_PANEL_BPM_WIDGET_H
+
+#include <QDialog>
+#include "config.h"
+#include "ui_SongEditorPanelBpmWidget_UI.h"
+#include <hydrogen/Object.h>
+
+///
+///
+namespace H2Core
+{
+
+
+class SongEditorPanelBpmWidget : public QDialog, public Ui_SongEditorPanelBpmWidget_UI, public Object
+{
+
+//lineEditBEAT
+//lineEditBPM
+//deleteBtn
+
+	Q_OBJECT
+	public:
+		SongEditorPanelBpmWidget( QWidget* pParent, int beat );
+		~SongEditorPanelBpmWidget();
+
+	private slots:
+
+		void on_CancelBtn_clicked();
+		void on_okBtn_clicked();
+		void on_deleteBtn_clicked();
+
+	private:
+		int m_stimelineposition;
+};
+
+}
+#endif
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelTagWidget_UI.ui
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelTagWidget_UI.ui	(revision 1390)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelTagWidget_UI.ui	(revision 1390)
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SongEditorPanelTagWidget_UI</class>
+ <widget class="QWidget" name="SongEditorPanelTagWidget_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>289</width>
+    <height>417</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QTableWidget" name="tagTableWidget">
+     <property name="dragDropMode">
+      <enum>QAbstractItemView::InternalMove</enum>
+     </property>
+     <column>
+      <property name="text">
+       <string>Tag</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <layout class="QGridLayout" name="gridLayout"/>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QPushButton" name="CancelBtn">
+         <property name="toolTip">
+          <string/>
+         </property>
+         <property name="text">
+          <string>Cancel</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="okBtn">
+         <property name="text">
+          <string>Ok</string>
+         </property>
+         <property name="default">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>CancelBtn</tabstop>
+  <tabstop>okBtn</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget_UI.ui
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget_UI.ui	(revision 1233)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditorPanelBpmWidget_UI.ui	(revision 1233)
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SongEditorPanelBpmWidget_UI</class>
+ <widget class="QWidget" name="SongEditorPanelBpmWidget_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>195</width>
+    <height>151</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <widget class="QWidget" name="layoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>180</width>
+     <height>135</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="1" column="2">
+       <widget class="QLineEdit" name="lineEditBpm">
+        <property name="toolTip">
+         <string>Edit the bpm value for current beat</string>
+        </property>
+        <property name="text">
+         <string>500,55</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <widget class="QLineEdit" name="lineEditBeat">
+        <property name="toolTip">
+         <string>Edit beat in timeline</string>
+        </property>
+        <property name="text">
+         <string>500</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Bar</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>BPM</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QPushButton" name="deleteBtn">
+      <property name="toolTip">
+       <string>Delete this BPM Marker</string>
+      </property>
+      <property name="text">
+       <string>Delete BPM Marker</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QPushButton" name="CancelBtn">
+        <property name="toolTip">
+         <string/>
+        </property>
+        <property name="text">
+         <string>Cancel</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="okBtn">
+        <property name="text">
+         <string>Ok</string>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <tabstops>
+  <tabstop>lineEditBpm</tabstop>
+  <tabstop>lineEditBeat</tabstop>
+  <tabstop>deleteBtn</tabstop>
+  <tabstop>CancelBtn</tabstop>
+  <tabstop>okBtn</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: /branches/tabbedInterface/gui/src/SongEditor/SongEditor.cpp
===================================================================
--- /branches/tabbedInterface/gui/src/SongEditor/SongEditor.cpp	(revision 1498)
+++ /branches/tabbedInterface/gui/src/SongEditor/SongEditor.cpp	(revision 1498)
@@ -0,0 +1,1782 @@
+/*
+ * Hydrogen
+ * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
+ *
+ * http://www.hydrogen-music.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <assert.h>
+#include <algorithm>
+#include <memory>
+
+#include <hydrogen/Song.h>
+#include <hydrogen/hydrogen.h>
+#include <hydrogen/Preferences.h>
+#include <hydrogen/Pattern.h>
+#include <hydrogen/audio_engine.h>
+#include <hydrogen/event_queue.h>
+#include <hydrogen/instrument.h>
+using namespace H2Core;
+
+
+#include "SongEditor.h"
+#include "SongEditorPanel.h"
+#include "SongEditorPanelBpmWidget.h"
+#include "SongEditorPanelTagWidget.h"
+#include "SoundLibrary/SoundLibraryPanel.h"
+#include "../PatternEditor/PatternEditorPanel.h"
+#include "../HydrogenApp.h"
+#include "../InstrumentRack.h"
+#include "../widgets/Button.h"
+#include "../PatternFillDialog.h"
+#include "../PatternPropertiesDialog.h"
+#include "../SongPropertiesDialog.h"
+#include "../Skin.h"
+#include "../VirtualPatternDialog.h"
+#include <hydrogen/LocalFileMng.h>
+
+
+using namespace std;
+
+SongEditor::SongEditor( QWidget *parent )
+ : QWidget( parent )
+ , Object( "SongEditor" )
+ , m_bSequenceChanged( true )
+ , m_bIsMoving( false )
+ , m_bShowLasso( false )
+{
+	setAttribute(Qt::WA_NoBackground);
+	setFocusPolicy (Qt::StrongFocus);
+
+	m_nGridWidth = 16;
+	m_nGridHeight = 18;
+
+	Preferences *pref = Preferences::get_instance();
+	m_nMaxPatternSequence = pref->getMaxBars();
+
+
+	int m_nInitialWidth = 10 + m_nMaxPatternSequence * m_nGridWidth;
+	int m_nInitialHeight = 10;
+
+	this->resize( QSize(m_nInitialWidth, m_nInitialHeight) );
+
+	createBackground();	// create m_backgroundPixmap pixmap
+
+	update();
+}
+
+
+
+SongEditor::~SongEditor()
+{
+}
+
+
+
+int SongEditor::getGridWidth ()
+{
+	return m_nGridWidth;
+}
+
+
+
+void SongEditor::setGridWidth( uint width )
+{
+	if ( ( SONG_EDITOR_MIN_GRID_WIDTH <= width ) && ( SONG_EDITOR_MAX_GRID_WIDTH >= width ) ) {
+		m_nGridWidth = width;
+		this->resize ( 10 + m_nMaxPatternSequence * m_nGridWidth, height() );
+	}
+}
+
+
+
+void SongEditor::keyPressEvent ( QKeyEvent * ev )
+{
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	vector<PatternList*>* pColumns = pEngine->getSong()->get_pattern_group_vector();
+
+	if ( ev->key() == Qt::Key_Delete ) {
+		if ( m_selectedCells.size() != 0 ) {
+			AudioEngine::get_instance()->lock( RIGHT_HERE );
+			// delete all selected cells
+			for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
+				QPoint cell = m_selectedCells[ i ];
+				PatternList* pColumn = (*pColumns)[ cell.x() ];
+				pColumn->del(pPatternList->get( cell.y() ) );
+			}
+			AudioEngine::get_instance()->unlock();
+
+			m_selectedCells.clear();
+			m_bSequenceChanged = true;
+			update();
+		}
+		return;
+	}
+
+	ev->ignore();
+}
+
+
+
+void SongEditor::mousePressEvent( QMouseEvent *ev )
+{
+	if ( ev->x() < 10 ) {
+		return;
+	}
+	//WARNINGLOG( "editor-pressed" );
+
+	int nRow = ev->y() / m_nGridHeight;
+	int nColumn = ( (int)ev->x() - 10 ) / (int)m_nGridWidth;
+
+	if ( ev->modifiers() == Qt::ControlModifier ) {
+		INFOLOG( "[mousePressEvent] CTRL pressed!" );
+		m_bIsCtrlPressed = true;
+	}
+	else {
+		m_bIsCtrlPressed = false;
+	}
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *pSong = pEngine->getSong();
+	PatternList *pPatternList = pSong->get_pattern_list();
+
+	// don't lock the audio driver before checking that...
+	if ( nRow >= (int)pPatternList->get_size() || nRow < 0 || nColumn < 0 ) { return; }
+	AudioEngine::get_instance()->lock( RIGHT_HERE );
+
+
+	SongEditorActionMode actionMode = HydrogenApp::get_instance()->getSongEditorPanel()->getActionMode();
+	if ( actionMode == SELECT_ACTION ) {
+
+		bool bOverExistingPattern = false;
+		for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
+			QPoint cell = m_selectedCells[ i ];
+			if ( cell.x() == nColumn && cell.y() == nRow ) {
+				bOverExistingPattern = true;
+				break;
+			}
+		}
+
+		if ( bOverExistingPattern ) {
+			// MOVE PATTERNS
+//			INFOLOG( "[mousePressEvent] Move patterns" );
+			m_bIsMoving = true;
+			m_bShowLasso = false;
+			m_movingCells = m_selectedCells;
+
+			m_clickPoint.setX( nColumn );
+			m_clickPoint.setY( nRow );
+		}
+		else {
+//			INFOLOG( "[mousePressEvent] Select patterns" );
+			// select patterns
+			m_bShowLasso = true;
+			m_lasso.setCoords( ev->x(), ev->y(), ev->x(), ev->y() );
+			setCursor( QCursor( Qt::CrossCursor ) );
+			m_selectedCells.clear();
+			m_selectedCells.push_back( QPoint( nColumn, nRow ) );
+		}
+	}
+	else if ( actionMode == DRAW_ACTION ) {
+		H2Core::Pattern *pPattern = pPatternList->get( nRow );
+		vector<PatternList*> *pColumns = pSong->get_pattern_group_vector();	// E' la lista di "colonne" di pattern
+		if ( nColumn < (int)pColumns->size() ) {
+			PatternList *pColumn = ( *pColumns )[ nColumn ];
+
+			bool bFound = false;
+			unsigned nColumnIndex = 0;
+			for ( nColumnIndex = 0; nColumnIndex < pColumn->get_size(); nColumnIndex++) {
+				if ( pColumn->get( nColumnIndex ) == pPattern ) { // il pattern e' gia presente
+					bFound = true;
+					break;
+				}
+			}
+
+			if ( bFound ) {
+				// DELETE PATTERN
+//				INFOLOG( "[mousePressEvent] delete pattern" );
+				pColumn->del( nColumnIndex );
+
+				// elimino le colonne vuote
+				for ( int i = pColumns->size() - 1; i >= 0; i-- ) {
+					PatternList *pColumn = ( *pColumns )[ i ];
+					if ( pColumn->get_size() == 0 ) {
+						pColumns->erase( pColumns->begin() + i );
+						delete pColumn;
+					}
+					else {
+						break;
+					}
+				}
+			}
+			else {
+				if ( nColumn < (int)pColumns->size() ) {
+					// ADD PATTERN
+//					INFOLOG( "[mousePressEvent] add pattern" );
+					m_selectedCells.clear();
+					pColumn->add( pPattern );
+				}
+			}
+		}
+		else {
+			// ADD PATTERN (with spaces..)
+			m_selectedCells.clear();
+			int nSpaces = nColumn - pColumns->size();
+//			INFOLOG( "[mousePressEvent] add pattern (with " + to_string( nSpaces ) + " spaces)" );
+
+			PatternList *pColumn = new PatternList();
+			pColumns->push_back( pColumn );
+
+			for ( int i = 0; i < nSpaces; i++ ) {
+				pColumn = new PatternList();
+				pColumns->push_back( pColumn );
+			}
+			pColumn->add( pPattern );
+		}
+		pSong->__is_modified = true;
+	}
+
+	AudioEngine::get_instance()->unlock();
+
+	// update
+	m_bSequenceChanged = true;
+	update();
+}
+
+
+
+void SongEditor::mouseMoveEvent(QMouseEvent *ev)
+{
+	int nRow = ev->y() / m_nGridHeight;
+	int nColumn = ( (int)ev->x() - 10 ) / (int)m_nGridWidth;
+	PatternList *pPatternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
+	vector<PatternList*>* pColumns = Hydrogen::get_instance()->getSong()->get_pattern_group_vector();
+
+	if ( m_bIsMoving ) {
+//		WARNINGLOG( "[mouseMoveEvent] Move patterns not implemented yet" );
+
+		int nRowDiff = nRow  - m_clickPoint.y();
+		int nColumnDiff = nColumn - m_clickPoint.x();
+
+//		INFOLOG( "[mouseMoveEvent] row diff: "+ to_string( nRowDiff ) );
+//		INFOLOG( "[mouseMoveEvent] col diff: "+ to_string( nColumnDiff ) );
+
+		for ( int i = 0; i < (int)m_movingCells.size(); i++ ) {
+			QPoint cell = m_movingCells[ i ];
+			m_movingCells[ i ].setX( m_selectedCells[ i ].x() + nColumnDiff );
+			m_movingCells[ i ].setY( m_selectedCells[ i ].y() + nRowDiff );
+		}
+
+		m_bSequenceChanged = true;
+		update();
+		return;
+	}
+
+	if ( m_bShowLasso ) {
+		// SELECTION
+		setCursor( QCursor( Qt::CrossCursor ) );
+		int x = ev->x();
+		int y = ev->y();
+		if ( x < 0 ) {
+			x = 0;
+		}
+		if ( y < 0 ) {
+			y = 0;
+		}
+		m_lasso.setBottomRight( QPoint( x, y ) );
+
+		// aggiorno la lista di celle selezionate
+		m_selectedCells.clear();
+
+		int nStartColumn = (int)( ( m_lasso.left() - 10.0 ) / m_nGridWidth );
+		int nEndColumn = nColumn;
+		if ( nStartColumn > nEndColumn ) {
+			int nTemp = nEndColumn;
+			nEndColumn = nStartColumn;
+			nStartColumn = nTemp;
+		}
+
+		int nStartRow = m_lasso.top() / m_nGridHeight;
+		int nEndRow = nRow;
+		if ( nStartRow > nEndRow ) {
+			int nTemp = nEndRow;
+			nEndRow = nStartRow;
+			nStartRow = nTemp;
+		}
+
+		for ( int nRow = nStartRow; nRow <= nEndRow; nRow++ ) {
+			for ( int nCol = nStartColumn; nCol <= nEndColumn; nCol++ ) {
+				if ( nRow >= (int)pPatternList->get_size() || nRow < 0 || nCol < 0 ) {
+					return;
+				}
+				H2Core::Pattern *pPattern = pPatternList->get( nRow );
+
+				if ( nCol < (int)pColumns->size() ) {
+					PatternList *pColumn = ( *pColumns )[ nCol ];
+
+					for ( uint i = 0; i < pColumn->get_size(); i++) {
+						if ( pColumn->get(i) == pPattern ) { // esiste un pattern in questa posizione
+							m_selectedCells.push_back( QPoint( nCol, nRow ) );
+						}
+					}
+				}
+			}
+		}
+
+		m_bSequenceChanged = true;
+		update();
+	}
+
+}
+
+
+
+void SongEditor::mouseReleaseEvent( QMouseEvent *ev )
+{
+	UNUSED( ev );
+//	INFOLOG( "[mouseReleaseEvent]" );
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+
+	PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
+	vector<PatternList*>* pColumns = pEngine->getSong()->get_pattern_group_vector();
+
+	if ( m_bIsMoving ) {	// fine dello spostamento dei pattern
+		AudioEngine::get_instance()->lock( RIGHT_HERE );
+		// create the new patterns
+		for ( uint i = 0; i < m_movingCells.size(); i++ ) {
+			QPoint cell = m_movingCells[ i ];
+			if ( cell.x() < 0 || cell.y() < 0 || cell.y() >= (int)pPatternList->get_size() ) {
+				// skip
+				continue;
+			}
+			// aggiungo un pattern per volta
+			PatternList* pColumn = NULL;
+			if ( cell.x() < (int)pColumns->size() ) {
+				pColumn = (*pColumns)[ cell.x() ];
+			}
+			else {
+				// creo dei patternlist vuoti
+				int nSpaces = cell.x() - pColumns->size();
+				for ( int i = 0; i <= nSpaces; i++ ) {
+					pColumn = new PatternList();
+					pColumns->push_back( pColumn );
+				}
+			}
+			pColumn->add( pPatternList->get( cell.y() ) );
+		}
+
+		if ( m_bIsCtrlPressed ) {	// COPY
+		}
+		else {	// MOVE
+			// remove the old patterns
+			for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
+				QPoint cell = m_selectedCells[ i ];
+				PatternList* pColumn = NULL;
+				if ( cell.x() < (int)pColumns->size() ) {
+					pColumn = (*pColumns)[ cell.x() ];
+				}
+				else {
+					pColumn = new PatternList();
+					pColumns->push_back( pColumn );
+				}
+				pColumn->del(pPatternList->get( cell.y() ) );
+			}
+		}
+
+		// remove the empty patternlist at the end of the song
+		for ( int i = pColumns->size() - 1; i != 0 ; i-- ) {
+			PatternList *pList = (*pColumns)[ i ];
+			int nSize = pList->get_size();
+			if ( nSize == 0 ) {
+				pColumns->erase( pColumns->begin() + i );
+				delete pList;
+			}
+			else {
+				break;
+			}
+		}
+
+
+		pEngine->getSong()->__is_modified = true;
+		AudioEngine::get_instance()->unlock();
+
+		m_bIsMoving = false;
+		m_movingCells.clear();
+		m_selectedCells.clear();
+	}
+
+	setCursor( QCursor( Qt::ArrowCursor ) );
+
+	m_bShowLasso = false;
+	m_bSequenceChanged = true;
+	m_bIsCtrlPressed = false;
+	update();
+}
+
+
+
+void SongEditor::paintEvent( QPaintEvent *ev )
+{
+/*	INFOLOG(
+			"[paintEvent] x: " + to_string( ev->rect().x() ) +
+			" y: " + to_string( ev->rect().y() ) +
+			" w: " + to_string( ev->rect().width() ) +
+			" h: " + to_string( ev->rect().height() )
+	);
+*/
+
+	// ridisegno tutto solo se sono cambiate le note
+	if (m_bSequenceChanged) {
+		m_bSequenceChanged = false;
+		drawSequence();
+	}
+
+	QPainter painter(this);
+	painter.drawPixmap( ev->rect(), *m_pSequencePixmap, ev->rect() );
+
+	if ( m_bShowLasso ) {
+		QPen pen( Qt::white );
+		pen.setStyle( Qt::DotLine );
+		painter.setPen( pen );
+		painter.drawRect( m_lasso );
+	}
+}
+
+
+
+void SongEditor::createBackground()
+{
+	UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
+	QColor backgroundColor( pStyle->m_songEditor_backgroundColor.getRed(), pStyle->m_songEditor_backgroundColor.getGreen(), pStyle->m_songEditor_backgroundColor.getBlue() );
+	QColor alternateRowColor( pStyle->m_songEditor_alternateRowColor.getRed(), pStyle->m_songEditor_alternateRowColor.getGreen(), pStyle->m_songEditor_alternateRowColor.getBlue() );
+	QColor linesColor( pStyle->m_songEditor_lineColor.getRed(), pStyle->m_songEditor_lineColor.getGreen(), pStyle->m_songEditor_lineColor.getBlue() );
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *pSong = pEngine->getSong();
+
+	uint nPatterns = pSong->get_pattern_list()->get_size();
+
+	static int nOldHeight = -1;
+	int nNewHeight = m_nGridHeight * nPatterns;
+
+	if (nOldHeight != nNewHeight) {	
+		// cambiamento di dimensioni...
+		if (nNewHeight == 0) {
+			nNewHeight = 1;	// the pixmap should not be empty
+		}
+
+		m_pBackgroundPixmap = new QPixmap( width(), nNewHeight );	// initialize the pixmap
+		m_pSequencePixmap = new QPixmap( width(), nNewHeight );	// initialize the pixmap
+		this->resize( QSize( width(), nNewHeight ) );
+	}
+
+	m_pBackgroundPixmap->fill( alternateRowColor );
+
+	QPainter p( m_pBackgroundPixmap );
+	p.setPen( linesColor );
+
+/*	// sfondo per celle scure (alternato)
+	for (uint i = 0; i < nPatterns; i++) {
+		if ( ( i % 2) != 0) {
+			uint y = m_nGridHeight * i;
+			p.fillRect ( 0, y, m_nMaxPatternSequence * m_nGridWidth, 2, backgroundColor );
+			p.fillRect ( 0, y + 2, m_nMaxPatternSequence * m_nGridWidth, m_nGridHeight - 4, alternateRowColor );
+			p.fillRect ( 0, y + m_nGridHeight - 2, m_nMaxPatternSequence * m_nGridWidth, 2, backgroundColor );
+		}
+	}
+*/
+	// celle...
+	p.setPen( linesColor );
+
+	// vertical lines
+	for (uint i = 0; i < m_nMaxPatternSequence + 1; i++) {
+		uint x = 10 + i * m_nGridWidth;
+		int x1 = x;
+		int x2 = x + m_nGridWidth;
+
+		p.drawLine( x1, 0, x1, m_nGridHeight * nPatterns );
+		p.drawLine( x2, 0, x2, m_nGridHeight * nPatterns );
+	}
+
+	p.setPen( linesColor );
+	// horizontal lines
+	for (uint i = 0; i < nPatterns; i++) {
+		uint y = m_nGridHeight * i;
+
+		int y1 = y + 2;
+		int y2 = y + m_nGridHeight - 2;
+
+		p.drawLine( 0, y1, (m_nMaxPatternSequence * m_nGridWidth), y1 );
+		p.drawLine( 0, y2, (m_nMaxPatternSequence * m_nGridWidth), y2 );
+	}
+
+
+	p.setPen( backgroundColor );
+	// horizontal lines (erase..)
+	for (uint i = 0; i < nPatterns + 1; i++) {
+		uint y = m_nGridHeight * i;
+
+		p.fillRect( 0, y, m_nMaxPatternSequence * m_nGridWidth, 2, backgroundColor );
+		p.drawLine( 0, y + m_nGridHeight - 1, m_nMaxPatternSequence * m_nGridWidth, y + m_nGridHeight - 1 );
+	}
+
+	//~ celle
+	m_bSequenceChanged = true;
+}
+
+void SongEditor::cleanUp(){
+
+	delete m_pBackgroundPixmap;
+	delete m_pSequencePixmap;
+}
+
+void SongEditor::drawSequence()
+{
+	QPainter p;
+	p.begin( m_pSequencePixmap );
+	p.drawPixmap( rect(), *m_pBackgroundPixmap, rect() );
+	p.end();
+
+	Song* song = Hydrogen::get_instance()->getSong();
+	PatternList *patList = song->get_pattern_list();
+	vector<PatternList*>* pColumns = song->get_pattern_group_vector();
+	uint listLength = patList->get_size();
+	for (uint i = 0; i < pColumns->size(); i++) {
+		PatternList* pColumn = (*pColumns)[ i ];
+		
+		std::set<Pattern*> drawnAsVirtual;
+
+		for (uint nPat = 0; nPat < pColumn->get_size(); ++nPat) {
+			H2Core::Pattern *pat = pColumn->get( nPat );
+
+			if (drawnAsVirtual.find(pat) == drawnAsVirtual.end()) {
+			    int position = -1;
+			    // find the position in pattern list
+			    for (uint j = 0; j < listLength; j++) {
+				    H2Core::Pattern *pat2 = patList->get( j );
+				    if (pat == pat2) {
+					    position = j;
+					    break;
+				    }
+			    }
+			    if (position == -1) {
+				    WARNINGLOG( QString("[drawSequence] position == -1, group = %1").arg( i ) );
+			    }
+			    drawPattern( i, position, false );
+			}//if
+			
+			for (std::set<Pattern*>::const_iterator virtualIter = pat->virtual_pattern_transitive_closure_set.begin(); virtualIter != pat->virtual_pattern_transitive_closure_set.end(); ++virtualIter) {
+			    if (drawnAsVirtual.find(*virtualIter) == drawnAsVirtual.end()) {
+				int position = -1;
+				// find the position in pattern list
+				for (uint j = 0; j < listLength; j++) {
+				    H2Core::Pattern *pat2 = patList->get( j );
+				    if (*virtualIter == pat2) {
+					    position = j;
+					    break;
+				    }//if
+				}//for
+				if (position == -1) {
+				    WARNINGLOG( QString("[drawSequence] position == -1, group = %1").arg( i ) );
+				}
+				drawPattern( i, position, true );
+				
+				drawnAsVirtual.insert(*virtualIter);
+			    }//if
+			}//for
+		}
+	}
+
+	// Moving cells
+	p.begin( m_pSequencePixmap );
+//	p.setRasterOp( Qt::XorROP );
+
+// comix: this composition mode seems to be not available on Mac
+	p.setCompositionMode( QPainter::CompositionMode_Xor );
+	QPen pen( Qt::gray );
+	pen.setStyle( Qt::DotLine );
+	p.setPen( pen );
+	for ( uint i = 0; i < m_movingCells.size(); i++ ) {
+		int x = 10 + m_nGridWidth * ( m_movingCells[ i ] ).x();
+		int y = m_nGridHeight * ( m_movingCells[ i ] ).y();
+
+		QColor patternColor;
+		patternColor.setRgb( 255, 255, 255 );
+		p.fillRect( x + 2, y + 4, m_nGridWidth - 3, m_nGridHeight - 7, patternColor );
+	}
+
+}
+
+
+
+void SongEditor::drawPattern( int pos, int number, bool invertColour )
+{
+	Preferences *pref = Preferences::get_instance();
+	UIStyle *pStyle = pref->getDefaultUIStyle();
+	QPainter p( m_pSequencePixmap );
+	QColor patternColor( pStyle->m_songEditor_pattern1Color.getRed(), pStyle->m_songEditor_pattern1Color.getGreen(), pStyle->m_songEditor_pattern1Color.getBlue() );
+	
+	if (true == invertColour) {
+	    patternColor = patternColor.darker(200);
+	}//if
+
+	bool bIsSelected = false;
+	for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
+		QPoint point = m_selectedCells[ i ];
+		if ( point.x() == pos && point.y() == number ) {
+			bIsSelected = true;
+			break;
+		}
+	}
+
+	if ( bIsSelected ) {
+		patternColor = patternColor.dark( 130 );
+	}
+
+	int x = 10 + m_nGridWidth * pos;
+	int y = m_nGridHeight * number;
+
+// 	p.setPen( patternColor.light( 120 ) );  // willie - For the bevel - haven't yet figured how it's supposed to work...
+	p.fillRect( x + 1, y + 3, m_nGridWidth - 1, m_nGridHeight - 5, patternColor );
+}
+
+
+
+
+
+// :::::::::::::::::::
+
+
+
+
+
+SongEditorPatternList::SongEditorPatternList( QWidget *parent )
+ : QWidget( parent )
+ , Object( "SongEditorPatternList" )
+ , EventListener()
+ , m_pBackgroundPixmap( NULL )
+{
+	m_nWidth = 200;
+	m_nGridHeight = 18;
+	setAttribute(Qt::WA_NoBackground);
+	
+	setAcceptDrops(true);
+
+	patternBeingEdited = NULL;
+	
+	line = new QLineEdit( "Inline Pattern Name", this );
+	line->setFrame( false );
+	line->hide();
+	connect( line, SIGNAL(editingFinished()), this, SLOT(inlineEditingFinished()) );
+	connect( line, SIGNAL(returnPressed()), this, SLOT(inlineEditingEntered()) );
+
+	this->resize( m_nWidth, m_nInitialHeight );
+
+	m_labelBackgroundLight.load( Skin::getImagePath() + "/songEditor/songEditorLabelBG.png" );
+	m_labelBackgroundDark.load( Skin::getImagePath() + "/songEditor/songEditorLabelABG.png" );
+	m_labelBackgroundSelected.load( Skin::getImagePath() + "/songEditor/songEditorLabelSBG.png" );
+	m_playingPattern_on_Pixmap.load( Skin::getImagePath() + "/songEditor/playingPattern_on.png" );
+	m_playingPattern_off_Pixmap.load( Skin::getImagePath() + "/songEditor/playingPattern_off.png" );
+
+	m_pPatternPopup = new QMenu( this );
+	m_pPatternPopup->addAction( trUtf8("Edit"),  this, SLOT( patternPopup_edit() ) );
+	m_pPatternPopup->addAction( trUtf8("Copy"),  this, SLOT( patternPopup_copy() ) );
+	m_pPatternPopup->addAction( trUtf8("Delete"),  this, SLOT( patternPopup_delete() ) );
+	m_pPatternPopup->addAction( trUtf8("Fill/Clear ..."),  this, SLOT( patternPopup_fill() ) );
+	m_pPatternPopup->addAction( trUtf8("Properties"),  this, SLOT( patternPopup_properties() ) );
+	m_pPatternPopup->addAction( trUtf8("Load Pattern"),  this, SLOT( patternPopup_load() ) );
+	m_pPatternPopup->addAction( trUtf8("Save Pattern"),  this, SLOT( patternPopup_save() ) );
+	m_pPatternPopup->addAction( trUtf8("Virtual Pattern"), this, SLOT( patternPopup_virtualPattern() ) );
+
+	HydrogenApp::get_instance()->addEventListener( this );
+
+	createBackground();
+	update();
+}
+
+
+
+SongEditorPatternList::~SongEditorPatternList()
+{
+}
+
+
+void SongEditorPatternList::patternChangedEvent() {
+
+	createBackground();
+	update();
+	///here we check the timeline  && m_pSong->get_mode() == Song::SONG_MODE
+	Hydrogen *engine = Hydrogen::get_instance();
+	if ( ( Preferences::get_instance()->__usetimeline ) && ( engine->getSong()->get_mode() == Song::SONG_MODE ) ){
+		for ( int i = 0; i < static_cast<int>(engine->m_timelinevector.size()); i++){
+			if ( ( engine->m_timelinevector[i].m_htimelinebeat == engine->getPatternPos() )
+				&& ( engine->getNewBpmJTM() != engine->m_timelinevector[i].m_htimelinebpm ) ){
+				engine->setBPM( engine->m_timelinevector[i].m_htimelinebpm );
+			}//if
+		}//for
+	}//if
+}
+
+
+/// Single click, select the next pattern
+void SongEditorPatternList::mousePressEvent( QMouseEvent *ev )
+{
+	int row = (ev->y() / m_nGridHeight);
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	PatternList *patternList = song->get_pattern_list();
+
+	if ( row >= (int)patternList->get_size() ) {
+		return;
+	}
+
+	if ( (ev->button() == Qt::MidButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::RightButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::LeftButton) ){
+		togglePattern( row );
+	} else {
+		engine->setSelectedPatternNumber( row );
+		if (ev->button() == Qt::RightButton)  {
+	/*
+			if ( song->getMode() == Song::PATTERN_MODE ) {
+	
+				PatternList *pCurrentPatternList = engine->getCurrentPatternList();
+				if ( pCurrentPatternList->get_size() == 0 ) {
+					// nessun pattern e' attivo. seleziono subito questo.
+					pCurrentPatternList->add( patternList->get( row ) );
+				}
+				else {
+					engine->setNextPattern( row );
+				}
+			}
+	*/
+			m_pPatternPopup->popup( QPoint( ev->globalX(), ev->globalY() ) );
+		}
+	}
+
+	createBackground();
+	update();
+}
+
+
+///
+/// Start/stop playing a pattern in "pattern mode"
+///
+void SongEditorPatternList::togglePattern( int row ) {
+
+	Hydrogen *engine = Hydrogen::get_instance();
+/*	Song *song = engine->getSong();
+	PatternList *patternList = song->get_pattern_list();*/
+
+// 	PatternList *pCurrentPatternList = engine->getCurrentPatternList();
+
+// 	bool isPatternPlaying = false;
+	engine->sequencer_setNextPattern( row, false, true );
+
+// 	for ( uint i = 0; i < pCurrentPatternList->get_size(); ++i ) {
+// 		if ( pCurrentPatternList->get( i ) == patternList->get( row ) ) {
+// 			// the pattern is already playing, stop it!
+// 			isPatternPlaying = true;
+// 			break;
+// 		}
+// 	}
+//
+// 	if ( isPatternPlaying ) {
+// 		//pCurrentPatternList->del( patternList->get( row ) );
+// 		engine->sequencer_setNextPattern( row, false, true );	// remove from the playing pattern list
+// 	}
+// 	else {
+// 		// the pattern is not playing, add it to the list
+// 		//pCurrentPatternList->add( patternList->get( row ) );
+// 		engine->sequencer_setNextPattern( row, true, false );	// add to the playing pattern list
+// 	}
+
+	createBackground();
+	update();
+}
+
+
+void SongEditorPatternList::mouseDoubleClickEvent( QMouseEvent *ev )
+{
+	int row = (ev->y() / m_nGridHeight);
+	inlineEditPatternName( row );
+}
+
+void SongEditorPatternList::inlineEditPatternName( int row )
+{
+	Hydrogen *engine = Hydrogen::get_instance();
+	Song *song = engine->getSong();
+	PatternList *patternList = song->get_pattern_list();
+
+	if ( row >= (int)patternList->get_size() ) {
+		return;
+	}
+	patternBeingEdited = patternList->get( row );
+	line->setGeometry( 23, row * m_nGridHeight , m_nWidth - 23, m_nGridHeight  );
+	line->setText( patternBeingEdited->get_name() );
+	line->selectAll();
+	line->show();
+	line->setFocus();
+}
+
+void SongEditorPatternList::inlineEditingEntered()
+{
+	assert( patternBeingEdited != NULL );
+	if ( PatternPropertiesDialog::nameCheck( line->text() ) )
+	{
+		patternBeingEdited->set_name( line->text() );
+		Hydrogen::get_instance()->getSong()->__is_modified = true;
+		EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
+		createBackground();
+		update();
+	}
+// 	patternBeingEdited = NULL;
+}
+
+
+void SongEditorPatternList::inlineEditingFinished()
+{
+	patternBeingEdited = NULL;
+	line->hide();
+}
+
+
+void SongEditorPatternList::paintEvent( QPaintEvent *ev )
+{
+	QPainter painter(this);
+	painter.drawPixmap( ev->rect(), *m_pBackgroundPixmap, ev->rect() );
+}
+
+
+
+void SongEditorPatternList::updateEditor()
+{
+	if(!isVisible()) {
+		return;
+	}
+
+	update();
+}
+
+
+
+void SongEditorPatternList::createBackground()
+{
+	Preferences *pref = Preferences::get_instance();
+	UIStyle *pStyle = pref->getDefaultUIStyle();
+	QColor textColor( pStyle->m_songEditor_textColor.getRed(), pStyle->m_songEditor_textColor.getGreen(), pStyle->m_songEditor_textColor.getBlue() );
+
+	QString family = pref->getApplicationFontFamily();
+	int size = pref->getApplicationFontPointSize();
+	QFont textFont( family, size );
+
+	QFont boldTextFont( textFont);
+	boldTextFont.setPointSize(10);
+	boldTextFont.setBold( true );
+
+	Hydrogen *pEngine = Hydrogen::get_instance();
+	Song *pSong = pEngine->getSong();
+	int nPatterns = pSong->get_pattern_list()->get_size();
+	int nSelectedPattern = pEngine->getSelectedPatternNumber();
+
+	static int oldHeight = -1;
+	int newHeight = m_nGridHeight * nPatterns;
+
+	if (oldHeight != newHeight) {
+		if (newHeight == 0) {
+			newHeight = 1;	// the pixmap should not be empty
+		}
+		delete m_pBackgroundPixmap;
+		m_pBackgroundPixmap = new QPixmap( m_nWidth, newHeight );	// initialize the pixmap
+		this->resize( m_nWidth, newHeight );
+	}
+	m_pBackgroundPixmap->fill( Qt::black );
+
+	QPainter p( m_pBackgroundPixmap );
+	p.setFont( boldTextFont );
+
+	for ( int i = 0; i < nPatterns; i++ ) {
+		uint y = m_nGridHeight * i;
+		if ( i == nSelectedPattern ) {
+			p.drawPixmap( QPoint( 0, y ), m_labelBackgroundSelected );
+		}
+		else {
+			if ( ( i % 2) == 0 ) {
+				p.drawPixmap( QPoint( 0, y ), m_labelBackgroundDark );
+			}
+			else {
+				p.drawPixmap( QPoint( 0, y ), m_labelBackgroundLight );
+			}
+		}
+	}
+
+	PatternList *pCurrentPatternList = pEngine->getCurrentPatternList();
+
+	/// paint the foreground (pattern name etc.)
+	for ( int i = 0; i < nPatterns; i++ ) {
+		H2Core::Pattern *pPattern = pSong->get_pattern_list()->get(i);
+		//uint y = m_nGridHeight * i;
+
+		// Text
+		bool bNext = false, bActive = false;
+/*		for (uint j = 0; j < pCurrentPatternList->get_size(); j++) {
+			if ( pPattern == pCurrentPatternList->get(j) ) {
+				bActive = true;
+				break;
+			}
+		}*/
+		if ( pCurrentPatternList->index_of( pPattern ) != -1 ) bActive = true;
+		if ( pEngine->getNextPatterns()->index_of( pPattern ) != -1 ) bNext = true;
+
+		if ( i == nSelectedPattern ) {
+			p.setPen( QColor( 0,0,0 ) );
+		}
+		else {
+			p.setPen( textColor );
+		}
+
+		uint text_y = i * m_nGridHeight;
+		if ( bNext ) {
+			p.drawPixmap( QPoint( 5, text_y + 3 ), m_playingPattern_off_Pixmap );
+		}
+		else if (bActive) {
+//			p.drawText( 5, text_y - 1 - m_nGridHeight, m_nWidth - 25, m_nGridHeight + 2, Qt::AlignVCenter, ">" );
+		
+			//mark active pattern with triangular
+			if( ! pref->patternModePlaysSelected() ){
+				p.drawPixmap( QPoint( 5, text_y + 3 ), m_playingPattern_on_Pixmap );
+			}
+		}
+
+
+		p.drawText( 25, text_y - 1, m_nWidth - 25, m_nGridHeight + 2, Qt::AlignVCenter, pPattern->get_name() );
+	}
+
+}
+
+void SongEditorPatternList::patternPopup_virtualPattern()
+{
+    Hydrogen *pEngine = Hydrogen::get_instance();
+    int nSelectedPattern = pEngine->getSelectedPatternNumber();
+    VirtualPatternDialog *dialog = new VirtualPatternDialog( this );
+    SongEditorPanel *pSEPanel = HydrogenApp::get_instance()->getSongEditorPanel();
+    int tmpselectedpatternpos = pEngine->getSelectedPatternNumber();    
+
+    dialog->patternList->setSortingEnabled(1);
+    
+    Song *song = pEngine->getSong();
+    PatternList *pPatternList = song->get_pattern_list();
+    H2Core::Pattern *selectedPattern = pPatternList->get(tmpselectedpatternpos);
+    
+    std::map<QString, Pattern*> patternNameMap;
+    
+    int listsize = pPatternList->get_size();    
+    for (unsigned int index = 0; index < listsize; ++index) {
+	H2Core::Pattern *curPattern = pPatternList->get( index );
+	QString patternName = curPattern->get_name();
+	
+	if (patternName == selectedPattern->get_name()) {
+	    continue;
+	}//if
+	
+	patternNameMap[patternName] = curPattern;
+	
+	QListWidgetItem *newItem = new QListWidgetItem(patternName, dialog->patternList);
+	dialog->patternList->insertItem(0, newItem );
+	
+	if (selectedPattern->virtual_pattern_set.find(curPattern) != selectedPattern->virtual_pattern_set.end()) {
+	    dialog->patternList->setItemSelected(newItem, true);
+	}//if
+    }//for
+    
+    if ( dialog->exec() == QDialog::Accepted ) {
+	selectedPattern->virtual_pattern_set.clear();
+	for (unsigned int index = 0; index < listsize-1; ++index) {
+	    QListWidgetItem *listItem = dialog->patternList->item(index);
+	    if (dialog->patternList->isItemSelected(listItem) == true) {
+		if (patternNameMap.find(listItem->text()) != patternNameMap.end()) {
+		    selectedPattern->virtual_pattern_set.insert(patternNameMap[listItem->text()]);
+		}//if
+	    }//if
+	}//for
+	
+	pSEPanel->updateAll();
+    }//if
+    
+    dialog->computeVirtualPatternTransitiveClosure(pPatternList);
+
+    delete dialog;
+}//patternPopup_virtualPattern
+
+void SongEditorPatternList::patternPopup_load()
+{
+
+	Hydrogen *engine = Hydrogen::get_instance();
+	int tmpselectedpatternpos = engine->getSelectedPatternNumber();
+	Song *song = engine->getSong();
+	PatternList *pPatternList = song->get_pattern_list();
+	Instrument *instr = song->get_instrument_list()->get( 0 );
+	assert( instr );
+	
+	QDir dirPattern( Preferences::get_instance()->getDataDirectory() + "/patterns" );
+	std::auto_ptr<QFileDialog> fd( new QFileDialog );
+	fd->setFileMode(QFileDialog::ExistingFile);
+	fd->setFilter( trUtf8("Hydrogen Pattern (*.h2pattern)") );
+	fd->setDirectory(dirPattern );
+
+	fd->setWindowTitle( trUtf8( "Open Pattern" ) );
+
+	QString filename;
+	if (fd->exec() == QDialog::Accepted) {
+		filename = fd->selectedFiles().first();
+	}
+	else
+	{
+		return;
+	}
+
+	LocalFileMng mng;
+	LocalFileMng fileMng;
+	Pattern* err = fileMng.loadPattern( filename );
+	if ( err == 0 ) {
+		_ERRORLOG( "Erro