Index: psycle/plugin_interface.hpp
===================================================================
--- psycle/plugin_interface.hpp	(revision 1412)
+++ psycle/plugin_interface.hpp	(working copy)
@@ -1,140 +1,282 @@
+///\file \brief A COPY of the revision 5713 of the psycle plugin interface.
+///\see http://psycle.svn.sourceforge.net/viewvc/psycle/trunk/psycle-plugins/src/psycle/plugins/plugin_interface.hpp
+///\todo To keep this file up-to-date, use a svn:externals property to https://psycle.svn.sourceforge.net/svnroot/psycle/trunk/psycle-plugins/src/psycle/plugins
+
+///\interface psycle's native plugin interface api
+
 #pragma once
 
+// *** Note ***
+// Because this file may be used outside of the psycle project itself,
+// we should not introduce any dependency by including
+// anything that is not part of the c++ standard library.
+
+#include <cstdio> // This is NOT part of the interface. It would be better if plugins that want it included it themselves.
+
 namespace psycle
 {
-	int const MI_VERSION = 11;
-	int const SEQUENCER = 1;
-	int const EFFECT = 0;
-	int const GENERATOR = 3;
-	int const NOTE_MAX = 119;
-	int const NOTE_NO = 120;
-	int const NOTE_OFF = 255;
+	namespace plugin_interface
+	{
+		///\todo use #include <cstdint> for that!
+		typedef /* std::uint8_t  */ unsigned char      uint8;
+		typedef /* std::uint16_t */ unsigned short int uint16;
+		typedef /* std::uint32_t */ unsigned       int uint32;
 
-#if !defined MAX_TRACKS
-#define MAX_TRACKS 64
-#endif
+		/// machine interface version
+		int const MI_VERSION = 11;
 
-	// todo use #include <inttypes.h> for that!
-	typedef unsigned char uint8;
-	typedef unsigned short int uint16;
-	typedef unsigned long int uint32;
+		/// max number of pattern tracks
+		int const MAX_TRACKS = 64;
 
-	double const PI = 3.14159265358979323846;
+		/// max number of samples (per channel) that the Work function may ask to return
+		int const MAX_BUFFER_LENGTH = 256;
 
-	/// in number of samples (per channel).
-	int const MAX_BUFFER_LENGTH = 256;
+		///\name note values
+		///\{
+			/// value of B-9. NOTE: C-0 is note number 0!
+			int const NOTE_MAX = 119;
+			/// value of the "off" note
+			int const NOTE_NO = 120;
+			/// empty value
+			int const NOTE_OFF = 255;
+		///\}
 
-	/// CMachineParameter flags.
-	int const MPF_LABEL = 0;
+		/// the pi constant.
+		/// note: this is also defined in <psycle/helpers/math/pi.hpp> but we want no dependency here
+		double const pi = 
+			#if defined M_PI // on some systems, #include <cmath> defines M_PI but this is not standard
+				M_PI
+			#else
+				3.14159265358979323846
+			#endif
+		;
 
-	/// CMachineParameter flags.
-	int const MPF_STATE = 2;
-	//}
+		/*////////////////////////////////////////////////////////////////////////*/
 
-	class CMachineParameter
-	{
-	public:
+		/// class to define the modificable parameters of the machine
+		class CMachineParameter
+		{
+			public:
+				/// Short name: "Cutoff"
+				char const *Name;
+				/// Longer description: "Cutoff Frequency (0-7f)"
+				char const *Description;
+				/// >= 0
+				int MinValue;
+				/// <= 65535
+				int MaxValue;
+				/// flags.
+				int Flags;
+				/// default value for params that have MPF_STATE flag set
+				int DefValue;
+		};
 
-		/// Short name: "Cutoff"
-		char const *Name;
-		/// Longer description: "Cutoff Frequency (0-7f)"
-		char const *Description;
-		/// >= 0
-		int MinValue;
-		/// <= 65535
-		int MaxValue;
-		/// flags.
-		int Flags;
-		/// default value for params that have MPF_STATE flag set
-		int DefValue;
-	};
+		///\name CMachineParameter flags
+		///\{
+			/// shows a line with background
+			int const MPF_NULL = 0;
+			/// shows a line with the text in a centered label
+			int const MPF_LABEL = 1;
+			/// shows a tweakable knob and text
+			int const MPF_STATE = 2;
+		///\}
 
-	class CMachineInfo
-	{
-	public:
-		int Version;
-		int Flags;
-		int numParameters;
-		CMachineParameter const **Parameters;
-		/// "Rambo Delay"
-		char const *Name;
-		/// "Delay"
-		char const *ShortName;
-		/// "John Rambo"
-		char const *Author;
-		/// "About"
-		char const *Command;
-		/// number of columns
-		int numCols;
-	};
+		/*////////////////////////////////////////////////////////////////////////*/
 
-	class CFxCallback
-	{
-	public:
-		virtual void MessBox(char* ptxt,char*caption,unsigned int type){}
-		virtual int CallbackFunc(int cbkID,int par1,int par2,int par3){return 0;}
-		virtual float *GetWaveLData(int inst,int wave){return 0;} ///\todo USELESS if you cannot get the length!
-		virtual float *GetWaveRData(int inst,int wave){return 0;} ///\todo USELESS if you cannot get the length!
-		virtual int GetTickLength(){return 2048;}
-		virtual int GetSamplingRate(){return 44100;}
-		virtual int GetBPM(){return 125;}
-		virtual int GetTPB(){return 4;}
-		// Don't get fooled by the above return values.
-		// You get a pointer to a subclass of this one that returns the correct ones.
-	};
+		/// class defining the machine properties
+		class CMachineInfo
+		{
+		public:
+			int Version;
+			int Flags;
+			int numParameters;
+			CMachineParameter const **Parameters;
+			/// "Rambo Delay"
+			char const *Name;
+			/// "Delay"
+			char const *ShortName;
+			/// "John Rambo"
+			char const *Author;
+			/// "About"
+			char const *Command;
+			/// number of columns
+			int numCols;
+		};
 
-	class CMachineInterface
-	{
-	public:
-		virtual ~CMachineInterface() {}
-		virtual void Init() {}
-		virtual void SequencerTick() {}
-		virtual void ParameterTweak(int par, int val) {}
+		///\name CMachineInfo flags
+		///\{
+			int const EFFECT = 0;
+			///\todo: unused
+			int const SEQUENCER = 1;
+			int const GENERATOR = 3;
+			int const CUSTOM_GUI = 16;
+		///\}
 
-		/// Work function
-		virtual void Work(float *psamplesleft, float *psamplesright , int numsamples, int tracks) {}
+		/*////////////////////////////////////////////////////////////////////////*/
 
-		virtual void Stop() {}
+		/// callback functions to let plugins communicate with the host.
+		class CFxCallback
+		{
+			public:
+				virtual void MessBox(char* ptxt,char*caption,unsigned int type){}
+				virtual int CallbackFunc(int cbkID,int par1,int par2,int par3){return 0;}
+				/// unused slot kept for binary compatibility for (old) closed-source plugins on msvc++ on mswindows.
+				virtual float * unused0(int, int){return 0;}
+				/// unused slot kept for binary compatibility for (old) closed-source plugins on msvc++ on mswindows.
+				virtual float * unused1(int, int){return 0;}
+				virtual int GetTickLength(){return 2048;}
+				virtual int GetSamplingRate(){return 44100;}
+				virtual int GetBPM(){return 125;}
+				virtual int GetTPB(){return 4;}
+				// Don't get fooled by the above return values.
+				// You get a pointer to a subclass of this one that returns the correct ones.
+				virtual inline ~CFxCallback() throw() {}
+		};
 
-		///\name Export / Import
-		///\{
-		virtual void PutData(uint8 * pData) {}
-		virtual void GetData(uint8 * pData) {}
-		virtual int GetDataSize() { return 0; }
-		///\}
+		/*////////////////////////////////////////////////////////////////////////*/
+		
+		/// base machine class
+		class CMachineInterface
+		{
+			public:
+				virtual inline ~CMachineInterface() {}
+				///\todo doc
+				virtual void Init() {}
+				///\todo doc
+				virtual void SequencerTick() {}
+				///\todo doc
+				virtual void ParameterTweak(int par, int val) {}
 
-		virtual void Command() {}
+				/// Work function
+				virtual void Work(float *psamplesleft, float *psamplesright , int numsamples, int tracks) {}
 
-		virtual void MuteTrack(int const i) {} /// Not used (yet?)
-		virtual bool IsTrackMuted(int const i) const { return false; } 	// Not used (yet?)
+				///\todo doc
+				virtual void Stop() {}
 
-		virtual void MidiNote(int const channel, int const value, int const velocity) {} /// Not used (yet?)
-		virtual void Event(uint32 const data) {} /// Not used (yet?)
+				///\name Export / Import
+				///\{
+					///\todo doc
+					virtual void PutData(void * pData) {}
+					///\todo doc
+					virtual void GetData(void * pData) {}
+					///\todo doc
+					virtual int GetDataSize() { return 0; }
+				///\}
 
-		virtual bool DescribeValue(char* txt,int const param, int const value) { return false; }
+				///\todo doc
+				virtual void Command() {}
+				///\todo doc. not used (yet?)
+				virtual void MuteTrack(int const i) {}
+				///\todo doc. not used (yet?)
+				virtual bool IsTrackMuted(int const i) const { return false; }
+				///\todo doc. not used (yet?)
+				virtual void MidiNote(int const channel, int const value, int const velocity) {}
+				///\todo doc. not used (yet?)
+				virtual void Event(uint32 const data) {}
+				///\todo doc
+				virtual bool DescribeValue(char* txt,int const param, int const value) { return false; }
+				///\todo doc. not used (prolly never)
+				virtual bool PlayWave(int const wave, int const note, float const volume) { return false; }
+				///\todo doc
+				virtual void SeqTick(int channel, int note, int ins, int cmd, int val) {}
+				///\todo doc. not used (prolly never)
+				virtual void StopWave() {}
 
-		virtual bool PlayWave(int const wave, int const note, float const volume) { return false; } /// Not used (prolly never)
-		virtual void SeqTick(int channel, int note, int ins, int cmd, int val) {}
+			public:
+				/// initialize these members in the constructor
+				int *Vals;
 
-		virtual void StopWave() {} 	/// Not used (prolly never)
+				/// callback.
+				/// This member is initialized by the engine right after it calls CreateMachine().
+				/// Don't touch it in the constructor.
+				CFxCallback * pCB;
+		};
 
-	public:
-		// initialize these members in the constructor
-		int *Vals;
+		/*////////////////////////////////////////////////////////////////////////*/
+		namespace symbols
+		{
+			// spelling INSTANCIATOR -> INSTANTIATOR
+			#define PSYCLE__PLUGIN__INSTANCIATOR(typename, info) PSYCLE__PLUGIN__INSTANTIATOR(typename, info)
+			#define PSYCLE__PLUGIN__INSTANTIATOR(typename, info) \
+				extern "C" \
+				{ \
+					PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT \
+					psycle::plugin_interface::CMachineInfo const * const \
+					PSYCLE__PLUGIN__CALLING_CONVENTION \
+					PSYCLE__PLUGIN__SYMBOL_NAME__GET_INFO() { return &info; } \
+					\
+					PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT \
+					psycle::plugin_interface::CMachineInterface * \
+					PSYCLE__PLUGIN__CALLING_CONVENTION \
+					PSYCLE__PLUGIN__SYMBOL_NAME__CREATE_MACHINE() { return new typename; } \
+					\
+					PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT \
+					void \
+					PSYCLE__PLUGIN__CALLING_CONVENTION \
+					PSYCLE__PLUGIN__SYMBOL_NAME__DELETE_MACHINE(::CMachineInterface & plugin) { delete &plugin; } \
+				}
 
-		/// Callback.
-		/// this member is initialized by the
-		/// engine right after it calls CreateMachine()
-		/// don't touch it in the constructor
-		CFxCallback * pCB;
-	};
-};
+			#define PSYCLE__PLUGIN__SYMBOL_NAME__GET_INFO GetInfo
+			#define PSYCLE__PLUGIN__SYMBOL_NAME__CREATE_MACHINE CreateMachine
+			#define PSYCLE__PLUGIN__SYMBOL_NAME__DELETE_MACHINE DeleteMachine
+			
+			/// we don't use universalis/diversalis here because we want no dependency
+			#if !defined _WIN64 && !defined _WIN32 && !defined __CYGWIN__ && !defined __MSYS__ && !defined _UWIN
+				#define PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT
+				#define PSYCLE__PLUGIN__CALLING_CONVENTION
+			#elif defined __GNUG__
+				#define PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT __attribute__((dllexport))
+				#define PSYCLE__PLUGIN__CALLING_CONVENTION __attribute__((__cdecl__))
+			#elif defined _MSC_VER
+				#define PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT __declspec(dllexport)
+				#define PSYCLE__PLUGIN__CALLING_CONVENTION __cdecl
+			#else
+				#error please add definition for your compiler
+			#endif
 
+			#define PSYCLE__PLUGIN__DETAIL__STRINGIZED(x) PSYCLE__PLUGIN__DETAIL__STRINGIZED__NO_EXPANSION(x)
+			#define PSYCLE__PLUGIN__DETAIL__STRINGIZED__NO_EXPANSION(x) #x
+		
+			const char get_info_function_name[] =
+				PSYCLE__PLUGIN__DETAIL__STRINGIZED(PSYCLE__PLUGIN__SYMBOL_NAME__GET_INFO);
+			typedef
+				psycle::plugin_interface::CMachineInfo const * const
+				(PSYCLE__PLUGIN__CALLING_CONVENTION * get_info_function)
+				();
+			
+			const char create_machine_function_name[] =
+				PSYCLE__PLUGIN__DETAIL__STRINGIZED(PSYCLE__PLUGIN__SYMBOL_NAME__CREATE_MACHINE);
+			typedef
+				psycle::plugin_interface::CMachineInterface *
+				(PSYCLE__PLUGIN__CALLING_CONVENTION * create_machine_function)
+				();
 
-#define PSYCLE__PLUGIN__INSTANCIATOR(typename, info) \
-	extern "C" \
-	{ \
-		__declspec(dllexport) ::CMachineInfo const * const cdecl GetInfo() { return &info; } \
-		__declspec(dllexport) ::CMachineInterface * cdecl CreateMachine() { return new typename; } \
-		__declspec(dllexport) void cdecl DeleteMachine(::CMachineInterface & plugin) { delete &plugin; } \
+			const char delete_machine_function_name[] =
+				PSYCLE__PLUGIN__DETAIL__STRINGIZED(PSYCLE__PLUGIN__SYMBOL_NAME__DELETE_MACHINE);
+			typedef
+				void
+				(PSYCLE__PLUGIN__CALLING_CONVENTION * delete_machine_function)
+				(psycle::plugin_interface::CMachineInterface &);
+		}
 	}
+}
+
+// for plugins that aren't namespace-aware
+using psycle::plugin_interface::MI_VERSION;
+using psycle::plugin_interface::MAX_TRACKS;
+using psycle::plugin_interface::NOTE_MAX;
+using psycle::plugin_interface::NOTE_NO;
+using psycle::plugin_interface::NOTE_OFF;
+using psycle::plugin_interface::MAX_BUFFER_LENGTH;
+using psycle::plugin_interface::CMachineInfo;
+using psycle::plugin_interface::GENERATOR;
+using psycle::plugin_interface::EFFECT;
+using psycle::plugin_interface::SEQUENCER;
+using psycle::plugin_interface::CMachineInterface;
+using psycle::plugin_interface::CMachineParameter;
+using psycle::plugin_interface::MPF_LABEL;
+using psycle::plugin_interface::MPF_STATE;
+using psycle::plugin_interface::CFxCallback;
+using psycle::plugin_interface::uint8; // deprecated anyway
+using psycle::plugin_interface::uint16; // deprecated anyway
+using psycle::plugin_interface::uint32; // deprecated anyway
Index: other/autoptr.h
===================================================================
--- other/autoptr.h	(revision 1412)
+++ other/autoptr.h	(working copy)
@@ -1,307 +0,0 @@
-/* autoptr.h
-
-   Copyright (C) 2007 Frank Potulski (polac@gmx.de)
-
-   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 Street, Fifth Floor, Boston, MA 02110-1301
-   USA. */
-
-#ifndef ___AUTO_PTR_H
-#define ___AUTO_PTR_H
-
-#include <memory.h>
-
-//*****************************************************************************************************************************************************
-
-template <class TPtr> class TAutoPtrRef;
-
-template <class TPtr> class TAutoPtr
-{
-public:
-
-	TAutoPtr(TPtr *_ptr) : ptr(_ptr)
-	{
-	};
-
-	TAutoPtr(const TAutoPtr<TPtr> &other)
-	{
-		ptr = other.Release();
-	};
-
-	TAutoPtr(const TAutoPtrRef<TPtr> &ref)
-	{
-		ptr = ref.ref.Release();
-	};
-
-	~TAutoPtr() 
-	{ 
-		if (ptr)
-		{
-			delete ptr;
-		}
-	};	
-
-	const TAutoPtr &operator =(const TAutoPtr &other)
-	{
-		if (ptr!=other.ptr)
-		{
-			delete ptr;
-
-			ptr = other.Release();			
-		}		
-
-		return *this;
-	};	    
-
-	TPtr *Release(void)
-	{
-		TPtr *ret = ptr;
-
-		ptr = 0;
-
-		return ret;
-	};
-
-	void Reset(TPtr *_ptr=0)
-	{
-		if (_ptr!=ptr)
-		{
-			delete ptr;
-		}
-
-		ptr = _ptr;
-	};
-
-	inline operator bool(void) const
-	{
-		return (ptr!=0);
-	}
-
-	inline TPtr &operator *(void)
-	{
-		return *ptr;
-	};
-
-	inline const TPtr &operator *(void) const
-	{
-		return *ptr;
-	};
-
-	inline TPtr *operator->(void) 
-	{
-		return ptr;
-	};
-
-	inline const TPtr * const operator->(void) const 
-	{
-		return ptr; 
-	};
-
-private:	
-
-	TAutoPtr() : ptr(0)
-	{
-	};
-
-private:
-
-	TPtr *ptr;
-        
-};
-
-//*****************************************************************************************************************************************************
-
-template <class TPtr> class TAutoPtrRef
-{
-public:
-
-	friend class TAutoPtr;
-
-	TAutoPtrRef(TAutoPtr<TPtr> &r) : ref(r)
-	{
-	};
-	
-	inline TPtr &operator *(void)
-	{
-		return ref;
-	};
-
-	inline const TPtr &operator *(void) const
-	{
-		return ref;
-	};
-
-	inline TPtr *operator->(void) 
-	{
-		return ref;
-	};
-
-	inline const TPtr * const operator->(void) const 
-	{
-		return ref;
-	};
-
-private:
-
-	TAutoPtr<TPtr> &ref;
-
-};
-
-//*****************************************************************************************************************************************************
-
-template <class TPtr> class TAutoArrayPtr
-{
-public:	
-	
-	TAutoArrayPtr(const __int32 size,const bool initZero=false) : ptr( size>0 ? new TPtr[size] : 0 ), size(size)
-	{		
-		int test = sizeof(TPtr);
-
-		if ( ptr && initZero )
-		{
-			::memset(ptr,0,size*sizeof(TPtr));
-		}
-	};
-
-	TAutoArrayPtr(const TAutoArrayPtr<TPtr> &other) : size(other.size)
-	{
-		ptr = other.Release();
-	};	
-
-	~TAutoArrayPtr() 
-	{ 
-		if (ptr)
-		{
-			delete[] ptr;
-
-			ptr = 0;
-		}
-	};
-
-	inline __int32 Size(void) const
-	{
-		return size;	
-	};
-
-	inline __int32 SizeBytes(void) const
-	{
-		return size * sizeof(TPtr);	
-	};
-
-	void New(const __int32 size)
-	{
-		if (size>0)
-		{
-			if (ptr)
-			{
-				delete[] ptr;
-
-				ptr = 0;
-			}
-
-			this->size = 0;
-
-			ptr = new TPtr[size];
-
-			if (ptr)
-			{
-				this->size = size;
-			}			
-		}
-	};
-
-	const TAutoArrayPtr &operator =(const TAutoArrayPtr &other)
-	{
-		if (ptr!=other.ptr)
-		{
-			delete[] ptr;
-
-			ptr = other.Release();
-
-			size = other.size;
-		}		
-
-		return *this;
-	};	    
-
-	TPtr *Release(void)
-	{
-		TPtr *ret = ptr;
-
-		ptr = 0;
-
-		size = 0;
-
-		return ret;
-	};
-
-	void Reset(TPtr *_ptr=0)
-	{
-		if (_ptr!=ptr)
-		{
-			delete[] ptr;
-		}
-
-		ptr = _ptr;
-
-		size = 0;
-	};
-
-	template <class TPtrCast> TPtrCast *ToPtr(void)
-	{
-		return (TPtrCast *)ptr;
-	};
-
-	template <class TPtrCast> const TPtrCast *ToPtr(void) const
-	{
-		return (const TPtrCast *)ptr;
-	};
-
-	inline TPtr &operator[](const __int32 n)
-	{
-		return ptr[n];
-	};
-
-	inline const TPtr &operator[](const __int32 n) const
-	{
-		return ptr[n];
-	};
-
-	inline operator TPtr *(void)
-	{
-		return ptr;
-	};
-
-	inline operator const TPtr *(void) const
-	{
-		return ptr;
-	};	
-
-private:	
-
-	TAutoArrayPtr() : ptr(0)
-	{
-	};
-
-private:
-
-	TPtr *ptr;
-
-	__int32 size;
-        
-};
-
-//*****************************************************************************************************************************************************
-
-#endif
\ No newline at end of file
Index: SConscript
===================================================================
--- SConscript	(revision 1412)
+++ SConscript	(working copy)
@@ -20,6 +20,6 @@
 
 Import('pluginenv', 'build_plugin')
 
-build_plugin(pluginenv, 'graue_softsat', [
-	'main.cpp',
+build_plugin(pluginenv, 'psy2zzub', [
+	'psy2zzub.cpp',
 ])
Index: psy2zzub.cpp
===================================================================
--- psy2zzub.cpp	(revision 1412)
+++ psy2zzub.cpp	(working copy)
@@ -1,913 +1,624 @@
-/* psy2zzub.cpp
+// This source 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, or (at your option) any later version.
+// copyright 2007 Frank Potulski <polac@gmx.de>
+// copyright 2007 members of the psycle project http://psycle.sourceforge.net
 
-   Copyright (C) 2007 Frank Potulski (polac@gmx.de)
+#include "psy2zzub.h"
+#include <sstream>
 
-   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 Street, Fifth Floor, Boston, MA 02110-1301
-   USA. */
-
-#include "psy2zzub.h"
-
-//*****************************************************************************************************************************************************
-
-//__declspec(dllexport) ::CMachineInterface * cdecl CreateMachine() { return new typename; } \
-//__declspec(dllexport) void cdecl DeleteMachine(::CMachineInterface & plugin) { delete &plugin; } \
-
-typedef CMachineInfo const * const (* GetInfo)(void);
-typedef CMachineInterface *(* CreateMachine)(void);
-typedef void (* DeleteMachine)(CMachineInterface &plugin);
-
-BOOL APIENTRY DllMain(HINSTANCE hm,DWORD dw,LPVOID lp)
-{
-	switch (dw)
-	{
-
-	case DLL_PROCESS_ATTACH:
-		{
-			CPsycle::hInst = hm;			
-		}
-		break;
-
-	case DLL_PROCESS_DETACH:
-		{
-
-		}
-		break;
-	
-	}
-	
-	return TRUE;
-}
-
-float Normalize(const int val,const int min,const int max)
-{		
-	return float( val- min ) / float( max - min );
-};
+#if defined __unix__
+	#include <dlfcn.h>
+	#include <sys/stat.h>
+	#include <dirent.h>
+#elif defined _WIN64 || defined _WIN32
+	#include <windows.h>
+#else
+	#error unsupported platform
+#endif
+#include <iostream>
+#include <sstream>
 
-int Scale(float normal,const int min,const int max)
-{
-	return int( normal * float( max - min) + 0.5f ) + min;
-};
-
-//**** CPsycleCollection ******************************************************************************************************************************
-		
-CPsycleCollection::CPsycleInfo::CPsycleInfo() : info()
-{	
-}
-
-CPsycleCollection::CPsycleInfo::~CPsycleInfo()
-{
-}
-
-plugin *CPsycleCollection::CPsycleInfo::create_plugin(void) const
-{		
-	return new CPsycle(this);
-}
-	
-bool CPsycleCollection::CPsycleInfo::store_info(archive *arc) const
-{
-	return false;
-}
-
-
-CPsycleCollection::CPsycleCollection() : factory(0)
-{
-}
-
-CPsycleCollection::~CPsycleCollection()
-{	
-}
-
-void CPsycleCollection::initialize(pluginfactory *factory)
-{	
-	this->factory = factory;
+namespace zzub { namespace plugins { namespace psycle_to_zzub {
 
-	if (this->factory)
-	{
-		HMODULE hm = ::GetModuleHandle(NULL);
+	/*********************************************************************************************************************/
+	/// module handling
+	namespace module {
+		typedef 
+			#if defined _WIN64 || defined _WIN32
+				HMODULE
+			#else
+				void *
+			#endif
+			handle_type;
 
-		if (hm)
-		{
-			char path[ MAX_PATH + 32 ] = {0};
+		inline handle_type open(const char * filename) {
+			return
+				#if defined _WIN64 || defined _WIN32
+					::LoadLibrary(filename);
+				#else
+					::dlopen(filename, RTLD_NOW);
+				#endif
+		}
 
-			::GetModuleFileName(hm,path,MAX_PATH);		
+		inline void * sym(handle_type handle, const char * symbol) {
+			return
+				#if defined _WIN64 || defined _WIN32
+					::GetProcAddress
+				#else
+					::dlsym
+				#endif
+				(handle, symbol);
+		}
 
-			size_t n = ::strlen(path);
+		inline int close(handle_type handle) {
+			return
+				#if defined _WIN64 || defined _WIN32
+					::FreeLibrary(handle) != 0;
+				#else
+					::dlclose(handle);
+				#endif
+		}
+	}
 
-			if (n)
-			{
-				while (n--)
-				{
-					if (path[n]=='\\')
-					{
-						path[n] = 0;
-
+	/*********************************************************************************************************************/
+	///\name module initialisation / deinitialisation
+	///\{
+		#if defined _WIN64 || defined _WIN32
+			namespace {
+				static HINSTANCE hInst(0);
+			}
+			
+			BOOL APIENTRY DllMain(HINSTANCE hm,DWORD dw,LPVOID lp) {
+				switch(dw) {
+					case DLL_PROCESS_ATTACH:
+						hInst = hm; // hInst is never used, so why is this done?
 						break;
-					}
+					case DLL_PROCESS_DETACH:
+						break;
+					default: ;
 				}
-
-				::strcat(path,"\\Gear\\Psycle\\");
+				return TRUE;
+			}
+		#elif defined __GNUG__
+			namespace {
+				__attribute__((constructor))
+				void constructor() {
+				}
 				
-				ScanPlugins(path);
+				__attribute__((destructor))
+				void destructor() {
+				}
 			}
+		#else
+			///\todo
+		#endif
+	///\}
+
+	/*********************************************************************************************************************/
+	///\name misc
+	///\{
+		float normalize(const int val, const int min, const int max) {
+			return float(val - min) / (max - min);
 		}
-	}
-}
-		
-const info *CPsycleCollection::get_info(const char *uri,archive *arc)
-{	
-	if ( uri && arc )
-	{
-		
-	}
-	
-	return 0;
-}
 
-const char *CPsycleCollection::get_uri(void)
-{	
-	return 0;
-}
+		int scale(float normal, const int min, const int max)
+		{
+			return static_cast<int>(normal * (max - min) + 0.5f) + min;
+		}
 		
-void CPsycleCollection::configure(const char *key,const char *value)
-{
-	int i=0;	
-}
+		inline bool is_denormal(const float & f) {
+			return *reinterpret_cast<const unsigned int *>(&f) & 0x7f800000 == 0;
+		}
 		
-void CPsycleCollection::destroy(void)
-{		
-	if (plugins.size())
-	{
-		list<CPsycleInfo *>::iterator it = plugins.begin();
-		const list<CPsycleInfo *>::iterator end = plugins.end();
-
-		while (it!=end)
-		{
-			delete (*it);
-
-			++it;
-		}
-
-		plugins.clear();
-	}
-
-	factory = 0;
-
-	delete this;
-}
-
-
-void CPsycleCollection::ScanPlugins(char *path)
-{
-	if ( !path || !path[0] ) 
-	{
-		return;
-	}
-			
-	const int len = int(::strlen(path));
-
-	if ( path[len-1] == '\\' )
-	{
-		path[len-1] = 0;
-	}
-
-	char file[MAX_PATH] = {0};
-	char tmp[MAX_PATH] = {0};
-			
-	::sprintf(file,"%s\\*",path);
-	
-	WIN32_FIND_DATA x = {0};
-
-	HANDLE fHandle = INVALID_HANDLE_VALUE;
-
-	for (;;)
-	{
-		if (fHandle==INVALID_HANDLE_VALUE) fHandle = ::FindFirstFile(file,&x);
-		if (fHandle==INVALID_HANDLE_VALUE) break;
-
-		::sprintf(tmp,"%s\\%s",path,x.cFileName);
-		
-		if (::GetFileAttributes(tmp)&FILE_ATTRIBUTE_DIRECTORY)
-		{
-			if ( ::strcmp(x.cFileName,".") && ::strcmp(x.cFileName,"..") )
-			{								
-				ScanPlugins(tmp);
-			}
-		}
-
-		BOOL b = ::FindNextFile(fHandle,&x);
-		
-		if (!b) 
-		{
-			::FindClose(fHandle);
-
-			break;
-		}
-	}
-		
-	::sprintf(file,"%s\\*.dll",path);
-
-	fHandle = INVALID_HANDLE_VALUE;
-
-	for (;;)
-	{
-		if (fHandle==INVALID_HANDLE_VALUE) fHandle = ::FindFirstFile(file,&x);
-		if (fHandle==INVALID_HANDLE_VALUE) break;
-
-		::sprintf(tmp,"%s\\%s",path,x.cFileName);
-
-		AddPlugin(tmp);
-		
-		BOOL b = ::FindNextFile(fHandle,&x);
-
-		if (!b) 
-		{
-			::FindClose(fHandle);
-
-			return;
-		}	
-	}	
-}
-
-void CPsycleCollection::ReplaceChar(char *str,const char toReplace,const char replacedBy)
-{
-	if ( str && toReplace!=replacedBy )
-	{
-		while (*str)
-		{
-			char &cmp = *str;
-
-			if (cmp==toReplace)
-			{
-				cmp = replacedBy;
-			}
-
-			++str;
-		}			
-	}
-}
-
-void CPsycleCollection::AddPlugin(const char * const path)
-{
-	if ( !factory || !path || !path[0] ) 
-	{
-		return;
-	}
-
-	HMODULE hm = ::LoadLibrary(path);
-
-	if (hm)
-	{
-		GetInfo getInfo = GetInfo(::GetProcAddress(hm,"GetInfo"));
-
-		if (getInfo)
-		{
-			const CMachineInfo * const info = getInfo();	
-
-			if (info)
-			{
-				CPsycleInfo *p = new CPsycleInfo();
-
-				if (p)
-				{
-					p->type = (info->Flags==psycle::GENERATOR) ? zzub::plugin_type_generator : zzub::plugin_type_effect;
+		void replace_char(char *str,const char toReplace,const char replacedBy) {
+			if(!str || toReplace == replacedBy) return;
+			while(*str) {
+				char &cmp = *str;
+				if (cmp==toReplace) cmp = replacedBy;
+				++str;
+			}
+		}
 
-					p->version = zzub::version;
-					p->flags = zzub::plugin_flag_mono_to_stereo;					
-
-					p->psy_name = info->Name;
-					p->name = p->psy_name.c_str();
-
-					p->psy_label = info->ShortName;
-					p->short_name = p->psy_label.c_str();
-
-					p->psy_author = info->Author;
-					p->author = p->psy_author.c_str();
-
-					p->psy_command = info->Command;
-					p->psy_command += "\nAbout ";
-					p->psy_command += info->Name;
-					p->psy_command += "...";
-					p->commands = p->psy_command.c_str();
-
-					p->psy_uri = "@xlutop.com/psy2zzub/";					
-					p->psy_uri += p->psy_name;
-					ReplaceChar((char *)p->psy_uri.c_str(),' ','+');
-					ReplaceChar((char *)p->psy_uri.c_str(),'\t','+');
-					ReplaceChar((char *)p->psy_uri.c_str(),'\n','+');
-					ReplaceChar((char *)p->psy_uri.c_str(),'\r','+');
-					p->uri = p->psy_uri.c_str();
-
-					p->psy_path = path;
-
-					if ( info->numParameters>0 && info->Parameters )
-					{
-						const int n = info->numParameters;
-
-						p->psy_param.reserve(n);
-						
-						for (int i=0;i<n;++i)
-						{
-							zzub::parameter &dstParam = p->add_global_parameter();
-
-							const psycle::CMachineParameter &srcParam = (*info->Parameters[i]);
-
-							dstParam.set_word();
-
-							if (srcParam.Flags==MPF_STATE)
-							{
-								dstParam.set_flags(zzub::parameter_flag_state);
-							}
-							
-							if ( srcParam.MinValue>=CPsycle::eMinValue && srcParam.MaxValue<=CPsycle::eMaxValue )
-							{
-								dstParam.set_value_min(srcParam.MinValue);
-								dstParam.set_value_max(srcParam.MaxValue);
-								dstParam.set_value_default(srcParam.DefValue);
-							}
-							else if ( ( srcParam.MaxValue - srcParam.MinValue ) <= CPsycle::eMaxValue )
-							{
-								dstParam.set_value_min(0);
-								dstParam.set_value_max( srcParam.MaxValue - srcParam.MinValue );
-								dstParam.set_value_default( srcParam.DefValue - srcParam.MinValue );								
-							}
-							else
-							{
-								dstParam.set_value_min(CPsycle::eMinValue);
-								dstParam.set_value_max(CPsycle::eMaxValue);
-								dstParam.set_value_default( Scale( Normalize(srcParam.DefValue,srcParam.MinValue,srcParam.MaxValue) , dstParam.value_min , dstParam.value_max ) );
-							}	
-
-							if (dstParam.value_max<=0x01)
-							{
-								dstParam.type = parameter_type_switch;
-								dstParam.value_none = 0xff;
-							}							
-							else if (dstParam.value_max<0xff)
-							{
-								dstParam.type = parameter_type_byte;
-								dstParam.value_none = 0xff;
-							}
-
-							::strncpy(p->psy_param[i].name,srcParam.Name,32);
-							p->psy_param[i].name[31] = 0;
-							dstParam.set_name(p->psy_param[i].name);
-
-							::strncpy(p->psy_param[i].desc,srcParam.Description,32);
-							p->psy_param[i].desc[31] = 0;
-							dstParam.set_description(p->psy_param[i].desc);
-						}
-					}
-					
-					if (info->Flags==psycle::GENERATOR)
-					{
-						p->min_tracks = CPsycle::eMinTracks;
-						p->max_tracks = CPsycle::eMaxTracks;
-
-						zzub::parameter &paramNote = p->add_track_parameter();
-
-						paramNote.set_note();
-						paramNote.set_flags(zzub::parameter_flag_event_on_edit);
-
-						zzub::parameter &paramCommand = p->add_track_parameter();
-
-						paramCommand.set_word();
-						paramCommand.set_value_min(0x0001);
-						paramCommand.set_value_max(0xFFFF);
-						paramCommand.set_value_none(0x0000);
-						paramCommand.set_name("Note Command");
-						paramCommand.set_description("Note Command");
-					}
-					else
-					{
-						p->min_tracks = 0;
-						p->max_tracks = 0;
-					}
-
-					plugins.push_back(p);
-
-					factory->register_info(p);
-				}				
-			}
-		}
-
-		::FreeLibrary(hm);
-	}
-}
-
-//**** CPsycle ****************************************************************************************************************************************
-
-HINSTANCE CPsycle::hInst = 0;
-
-//CPsycle::CPsycle(const CPsycleCollection::CPsycleInfo *_info) : info((CPsycleCollection::CPsycleInfo *)_info), global( int(_info->global_parameters.size()) ), track( int(_info->track_parameters.size()) * eMaxTracks ), mi(0), pinfo(0), cm(0), numTracks(0), params(_info)
-CPsycle::CPsycle(const CPsycleCollection::CPsycleInfo *_info) : info((CPsycleCollection::CPsycleInfo *)_info), track( int(_info->track_parameters.size()) * eMaxTracks ), mi(0), pinfo(0), cm(0), numTracks(0), global(_info)
-{	
-	global_values = global.params;
-	track_values = track;
-
-	attributes = 0;
-}
-
-CPsycle::~CPsycle()
-{
-}
-
-bool CPsycle::Open(void)
-{
-	if (!info) return false;
-
-	Close();
-
-	hm = ::LoadLibrary(info->psy_path.c_str());	
-
-	if (!hm) return false;
-
-	GetInfo getInfo = (GetInfo)::GetProcAddress(hm,"GetInfo");
-
-	if (!getInfo)
-	{
-		::FreeLibrary(hm);
-
-		hm = 0;
-
-		return false;	
-	}
-
-	const CMachineInfo *minfo = getInfo();
-
-	if (!minfo)
-	{
-		::FreeLibrary(hm);
-
-		hm = 0;
-
-		return false;		
-	}
-
-	pinfo = minfo->Parameters;
-
-	CreateMachine createMachine = (CreateMachine)::GetProcAddress(hm,"CreateMachine");
-
-	if (!createMachine)
-	{
-		::FreeLibrary(hm);
-
-		hm = 0;
-
-		return false;
-	}	
-
-	mi = createMachine();
-
-	if (!mi)
-	{
-		::FreeLibrary(hm);
-
-		hm = 0;
-
-		return false;
-	}
-
-	mi->pCB = this;
-
-	mi->Init();
-
-	return true;
-}
-
-bool CPsycle::Close(void)
-{
-	if (mi)
-	{
-		try
-		{
-			DeleteMachine deleteMachine = (DeleteMachine)::GetProcAddress(hm,"DeleteMachine");
-
-			if (deleteMachine)
-			{		
-				deleteMachine(*mi);
-			}
-			else
-			{
-				delete mi;
-			}
-		}
-		catch(...)
-		{
-		}
-
-		mi = 0;
-	}
-	
-	if (hm)
-	{
-		try
-		{
-			::FreeLibrary(hm);
-		}
-		catch(...)
-		{
-		}
-
-		hm = 0;
-	}		
-
-	pinfo = 0;
-
-	return true;
-}
-
-//**** CFxCallback ************************************************************************************************************************************
-
-void CPsycle::MessBox(char *ptxt,char *caption,unsigned int type)
-{
-	::MessageBox(::GetForegroundWindow(),ptxt,caption,type);
-}
+		const int version = 1;
+		///\todo huh?
+		const int min_tracks = 8;
+		const int max_tracks = psycle::plugin_interface::MAX_TRACKS;
+	///\}
 
-int CPsycle::CallbackFunc(int cbkID,int par1,int par2,int par3)
-{
-	return 0;
-}
+	/*********************************************************************************************************************/
+	// plugin_collection
+	
+	void plugin_collection::initialize(zzub::pluginfactory * factory) {
+		this->factory = factory;
+		if(!this->factory) return;
+		#if defined _WIN64 || defined _WIN32
+			module::handle_type module_handle(::GetModuleHandle(0));
+			if(!module_handle) return;
+			char path[MAX_PATH + 32] = {0};
+			::GetModuleFileName(module_handle, path, MAX_PATH);
+			std::size_t n(std::strlen(path));
+			if(!n) return;
+			while(n--) {
+				if (path[n]=='\\') {
+					path[n] = 0;
+					break;
+				}
+			}
+			std::string s(path);
+			s += "\\Gear\\Psycle\\";
+			scan_plugins(s);
+		#else
+			///\todo use binreloc
+			char const * env(std::getenv("PSYCLE_PATH"));
+			if(!env) std::cerr << "Warning: You do not have a PSYCLE_PATH environment variable set." << std::endl;
+			else {
+				std::string s(env);
+				scan_plugins(s);
+			}
+		#endif
+	}
+			
+	void plugin_collection::destroy() {
+		delete this;
+	}
 
-float *CPsycle::GetWaveLData(int inst,int wave)
-{
-	return 0;
-}
+	plugin_collection::~plugin_collection() {
+		if(plugin_infos.size()) {
+			for(std::list<plugin_info*>::iterator i(plugin_infos.begin()); i != plugin_infos.end(); ++i) delete *i;
+			plugin_infos.clear();
+		}
+	}
+	
+	void plugin_collection::scan_plugins(std::string const & path) {
+		std::cout << "enumerating psycle plugins in: " << path << "\n";
+		std::string search_path(path);
+		#if defined _WIN64 || defined _WIN32
+			search_path += "*.dll";
+			WIN32_FIND_DATA fd;
+			HANDLE hFind=::FindFirstFile(search_path.c_str(), &fd);
+			while(hFind != INVALID_HANDLE_VALUE) {
+				std::string full_path(path + '\\' + fd.cFileName);
+				if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) scan_plugins(fullPath.c_str());
+				else {
+					char absolute_path[MAX_PATH];
+					::GetFullPathName(full_path.c_str(), MAX_PATH, absolute_path, 0);
+					add_plugins(absolute_path);
+				}
+				if (!::FindNextFile(hFind, &fd)) break;
+			}
+			::FindClose(hFind);
+		#else
+			struct dirent ** namelist;
+			struct stat statinfo;
+			/// beware, scandir is not in posix yet as of 2007
+			int n(scandir(search_path.c_str(), &namelist, 0, alphasort));
+			if(n < 0) {
+				perror("scandir");
+				return;
+			}
+			while(n--) {
+				std::string name(namelist[n]->d_name);
+				std::free(namelist[n]);
+				if(name == "." || name == "..") continue;
+				std::string full_path(path + '/' + name);
+				if(!stat(full_path.c_str(), &statinfo))
+					if(S_ISDIR(statinfo.st_mode)) scan_plugins(full_path);
+					else add_plugin(full_path);
+			}
+			std::free(namelist);
+		#endif
+	}
 
-float *CPsycle::GetWaveRData(int inst,int wave)
-{
-	return 0;
-}
+	void plugin_collection::add_plugin(std::string const & path) {
+		std::cout << "checking for psycle plugin: " << path << "\n";
+		if(!factory) return;
+		module::handle_type module_handle(module::open(path.c_str()));
+		if(!module_handle) {
+			std::cerr << "could not load module: " << path << std::endl;
+			return;
+		}
+		using namespace psycle::plugin_interface::symbols;
+		get_info_function get_info = (get_info_function) module::sym(module_handle, get_info_function_name);
+		if(!get_info) std::cerr << "not a psycle plugin: " << path << std::endl;
+		else {
+			const CMachineInfo * const psycle_info = get_info();
+			if(!psycle_info) std::cerr << "call to " << get_info_function_name << " failed" << std::endl;
+			else {
+				plugin_info * zzub_info(new plugin_info());
+				if(zzub_info) {
+					switch(psycle_info->Flags) {
+						case psycle::plugin_interface::GENERATOR:
+							zzub_info->type = zzub::plugin_type_generator;
+							break;
+						case psycle::plugin_interface::SEQUENCER:
+							///\todo
+							zzub_info->type = zzub::plugin_type_effect;
+							break;
+						case psycle::plugin_interface::EFFECT:
+						default:
+							zzub_info->type = zzub::plugin_type_effect;
+					}
 
-int CPsycle::GetTickLength(void)
-{
-	return _master_info->samples_per_tick;
-}
+					zzub_info->version = zzub::version;
+					zzub_info->flags = zzub::plugin_flag_mono_to_stereo;
 
-int CPsycle::GetSamplingRate(void)
-{
-	return _master_info->samples_per_second;
-}
+					zzub_info->psy_name = psycle_info->Name;
+					zzub_info->name = zzub_info->psy_name.c_str();
 
-int CPsycle::GetBPM(void)
-{
-	return _master_info->beats_per_minute;
-}
-
-int CPsycle::GetTPB(void)
-{
-	return _master_info->ticks_per_beat;
-}
-
-//**** plugin *****************************************************************************************************************************************
-
-void CPsycle::init(archive *arc)
-{	
-	if (!Open())
-	{
-		return;	
-	}
-
-	if (arc)
-	{
-		instream *istr = arc->get_instream("");
-		
-		if (istr)
-		{
-			int n = 0;
-			
-			istr->read<int>(n);
-
-			if (n==1)
-			{				
-				istr->read<int>(n);
-
-				if (n>0)
-				{
-					TAutoArrayPtr<psycle::uint8> data(n,true);
-
-					istr->read(data,n);
-
-					mi->PutData( data.ToPtr<psycle::uint8>() );				
-				}
-			}			
-		}		
-	}
-}
-
-void CPsycle::save(archive *arc)
-{		
-	if (!arc) return;
-	if (!mi) return;
-		
-	outstream *ostr = arc->get_outstream("");
-
-	if (ostr)					
-	{
-		const int sizeBytes = mi->GetDataSize();
-
-		if (sizeBytes>0)
-		{
-			TAutoArrayPtr<psycle::uint8> data(sizeBytes,true);
-
-			mi->GetData( data.ToPtr<psycle::uint8>() );
-
-			ostr->write<int>(eVersion);
-			ostr->write<int>(sizeBytes);
-			ostr->write(data,sizeBytes);
-		}
-	}
-}
-
-void CPsycle::destroy(void)
-{
-	Close();
+					zzub_info->psy_label = psycle_info->ShortName;
+					zzub_info->short_name = zzub_info->psy_label.c_str();
 
-	delete this;
-}
+					zzub_info->psy_author = psycle_info->Author;
+					zzub_info->author = zzub_info->psy_author.c_str();
 
-void CPsycle::process_events(void)
-{	
-	if (!mi) return;	
-
-	const int n = int(info->global_parameters.size());
-	
-	for (int i=0;i<n;++i)
-	{
-		const zzub::parameter &srcParam = *info->global_parameters[i];		
-		const psycle::CMachineParameter &dstParam = *pinfo[i];
+					zzub_info->psy_command = psycle_info->Command;
+					zzub_info->psy_command += "\nAbout ";
+					zzub_info->psy_command += psycle_info->Name;
+					zzub_info->psy_command += "...";
+					zzub_info->commands = zzub_info->psy_command.c_str();
 
-		const int val = global[i];
-				
-		if (val!=srcParam.value_none)
-		{						
-			mi->ParameterTweak( i , Scale( Normalize(val,srcParam.value_min,srcParam.value_max) , dstParam.MinValue, dstParam.MaxValue ) );
-		}
-	}
-	
-	for (i=0;i<numTracks;++i)
-	{
-		const STrackParam &param = track[i];
-
-		if (param.note!=zzub::note_value_none)
-		{			
-			if (param.note!=zzub::note_value_off)
-			{				
-				const int note = ( ( param.note >> 4 ) * 12 ) + ( param.note & 15 );
-
-				mi->SeqTick(i,note,0,param.command>>8,param.command&0xff);				
-			}
-			else
-			{								
-				mi->SeqTick(i,psycle::NOTE_NO,0,0,0);				
-			}
-		}			
-	}
-}
+					zzub_info->psy_uri = "@psycle.sourceforge.net/";
+					zzub_info->psy_uri += zzub_info->psy_name;
+					///\todo not a good idea to modify the underlying buffer
+					replace_char(const_cast<char*>(zzub_info->psy_uri.c_str()), ' ','+');
+					replace_char(const_cast<char*>(zzub_info->psy_uri.c_str()),'\t','+');
+					replace_char(const_cast<char*>(zzub_info->psy_uri.c_str()),'\n','+');
+					replace_char(const_cast<char*>(zzub_info->psy_uri.c_str()),'\r','+');
+					zzub_info->uri = zzub_info->psy_uri.c_str();
 
-bool CPsycle::process_stereo(float **pin,float **pout,int numsamples,int mode)
-{	
-	if (mi)
-	{
-		if (mode&process_mode_write)
-		{
-			float *ldst = pout[0];
-			float *rdst = pout[1];
+					zzub_info->psy_path = path;
 
-			const float *lsrc = pin[0];
-			const float *rsrc = pin[1];
+					if(psycle_info->numParameters > 0 && psycle_info->Parameters) {
+						const int n = psycle_info->numParameters;
+						zzub_info->psy_param.reserve(n);
+						for(int i(0) ; i < n; ++i) {
+							zzub::parameter & zzub_param(zzub_info->add_global_parameter());
+							const psycle::plugin_interface::CMachineParameter & psycle_param(*psycle_info->Parameters[i]);
+							zzub_param.set_word();
+							const int min_value = 0;
+							///\todo what about 0xffff?
+							const int max_value = 0xfffe;
+							if(psycle_param.Flags == psycle::plugin_interface::MPF_STATE)
+								zzub_param.set_flags(zzub::parameter_flag_state);
+							if(psycle_param.MinValue >= min_value && psycle_param.MaxValue <= max_value) {
+								zzub_param.set_value_min(psycle_param.MinValue);
+								zzub_param.set_value_max(psycle_param.MaxValue);
+								zzub_param.set_value_default(psycle_param.DefValue);
+							} else if(psycle_param.MaxValue - psycle_param.MinValue <= max_value ) {
+								zzub_param.set_value_min(0);
+								zzub_param.set_value_max(psycle_param.MaxValue - psycle_param.MinValue);
+								zzub_param.set_value_default(psycle_param.DefValue - psycle_param.MinValue);
+							} else {
+								zzub_param.set_value_min(min_value);
+								zzub_param.set_value_max(max_value);
+								zzub_param.set_value_default(zzub_param.scale(normalize(
+									psycle_param.DefValue, psycle_param.MinValue, psycle_param.MaxValue)));
+							}
+							if(zzub_param.value_max <= 0x01) {
+								zzub_param.type = zzub::parameter_type_switch;
+								zzub_param.value_none = 0xff;
+							} else if (zzub_param.value_max<0xff) {
+								zzub_param.type = zzub::parameter_type_byte;
+								zzub_param.value_none = 0xff;
+							}
+							std::strncpy(zzub_info->psy_param[i].name, psycle_param.Name, 32);
+							zzub_info->psy_param[i].name[31] = 0;
+							zzub_param.set_name(zzub_info->psy_param[i].name);
 
-			int n = numsamples;
-
-			while (--n>=0)
-			{
-				*ldst++ = *lsrc++ * 32768.0f;
-				*rdst++ = *rsrc++ * 32768.0f;		
-			}
-
-			mi->Work(pout[0],pout[1],numsamples,numTracks);
-
-			n = numsamples;
-
-			ldst = pout[0];
-			rdst = pout[1];
-
-			while (--n>=0)
-			{
-				*ldst++ /= 32768.0f;
-				*rdst++ /= 32768.0f;
-			}		
-
-			lsrc = pout[0];
-			rsrc = pout[1];
-
-			while (--numsamples>=0)
-			{
-				if ( !IsDenormal(*lsrc) || !IsDenormal(*rsrc) )
-				{
-					return true;
+							std::strncpy(zzub_info->psy_param[i].desc, psycle_param.Description, 32);
+							zzub_info->psy_param[i].desc[31] = 0;
+							zzub_param.set_description(zzub_info->psy_param[i].desc);
+						}
+					}
+					switch(psycle_info->Flags) {
+						case psycle::plugin_interface::GENERATOR:
+							{
+								zzub_info->min_tracks = min_tracks;
+								zzub_info->max_tracks = max_tracks;
+								zzub::parameter &paramNote = zzub_info->add_track_parameter();
+								paramNote.set_note();
+								paramNote.set_flags(zzub::parameter_flag_event_on_edit);
+								zzub::parameter &paramCommand = zzub_info->add_track_parameter();
+								paramCommand.set_word();
+								paramCommand.set_value_min(0x0001);
+								paramCommand.set_value_max(0xFFFF);
+								paramCommand.set_value_none(0x0000);
+								paramCommand.set_name("Note Command");
+								paramCommand.set_description("Note Command");
+							}
+							break;
+						case psycle::plugin_interface::SEQUENCER:
+							///\todo
+						case psycle::plugin_interface::EFFECT:
+						default:
+							zzub_info->min_tracks = 0;
+							zzub_info->max_tracks = 0;
+					}
+					plugin_infos.push_back(zzub_info);
+					factory->register_info(zzub_info);
+					std::cout << "registered psycle plugin: " << zzub_info->name << "\n";
 				}
-
-				++lsrc;
-				++rsrc;
-			}		
-		}				
+			}
+		}
+		module::close(module_handle);
 	}
 
-	return false;
-}
+	/*********************************************************************************************************************/
+	// plugin
 
-void CPsycle::stop(void)
-{
-	if (mi)
+	plugin::plugin(const plugin_info * info)
+	:
+		info(info),
+		global_params(info),
+		track_params(new track_param[info->track_parameters.size() * max_tracks]),
+		metaplugin(),
+		module_handle(),
+		psycle_plugin(),
+		psycle_plugin_param_info(),
+		track_count()
 	{
-		mi->Stop();
+		global_values = global_params.data;
+		track_values = track_params;
+		attributes = 0;
 	}
-}
 
-void CPsycle::attributes_changed(void)
-{
+	bool plugin::open() {
+		if(!info) return false;
+		close();
+		module_handle = module::open((info->psy_path.c_str())); if(!module_handle) return false;
+		using namespace psycle::plugin_interface::symbols;
+		get_info_function get_info = (get_info_function) module::sym(module_handle, get_info_function_name);
+		if(!get_info) {
+			std::cerr << "not a psycle plugin: " << info->name << std::endl;
+			module::close(module_handle);
+			module_handle = 0;
+			return false;
+		}
+		const psycle::plugin_interface::CMachineInfo * const psycle_info = get_info();
+		if(!psycle_info) {
+			std::cerr << "call to " << get_info_function_name << " failed" << std::endl;
+			module::close(module_handle);
+			module_handle = 0;
+			return false;
+		}
+		psycle_plugin_param_info = psycle_info->Parameters;
+		create_machine_function create_machine = (create_machine_function) module::sym(module_handle, create_machine_function_name);
+		if(!create_machine)
+		{
+			std::cerr << "not a psycle plugin: " << info->name << std::endl;
+			module::close(module_handle);
+			module_handle = 0;
+			return false;
+		}
+		psycle_plugin = create_machine();
+		if(!psycle_plugin) {
+			std::cerr << "call to " << create_machine_function_name << " failed" << std::endl;
+			module::close(module_handle);
+			module_handle = 0;
+			return false;
+		}
+		psycle_plugin->pCB = this;
+		psycle_plugin->Init();
+		return true;
+	}
 
-}
+	bool plugin::close() {
+		if(psycle_plugin) {
+			try {
+				using namespace psycle::plugin_interface::symbols;
+				delete_machine_function delete_machine = (delete_machine_function) module::sym(module_handle, delete_machine_function_name);
+				if(delete_machine) delete_machine(*psycle_plugin);
+				else delete psycle_plugin; // some early closed-source plugins might not have a DeleteMachine function
+			} catch(...) {}
+			psycle_plugin = 0;
+		}
+		psycle_plugin_param_info = 0;
+		if(module_handle) {
+			try {
+				module::close(module_handle);
+			} catch(...) {}
+			module_handle = 0;
+		}
+		return true;
+	}
 
-void CPsycle::command(int index)
-{
-	if (!mi) return;		
+	void plugin::destroy() {
+		delete this;
+	}
 
-	if (!index)
-	{
-		mi->Command();
+	plugin::~plugin() throw() {
+		close();
+		delete[] track_params;
 	}
-	else
-	{
-		char buffer[32] = {0};
-		string text;
 
-		text =  "Copyright (C) 2007 by Frank Potulski (polac@gmx.de)\n\n";
-		text += "now wrapping...\n\n";
-		text += "Name:\t\t";
-		text += info->name;
-		text += "\nLabel:\t\t";
-		text += info->short_name;
-		text += "\nAuthor:\t\t";
-		text += info->author;
-		text += "\n\nPath:\t\t";
-		text += info->psy_path;
+	/*********************************************************************************************************************/
+	// plugin ... implementation for psycle::plugin_interface::CFxCallback
 
-		text += "\n\nNumParams:\t";
-		::sprintf(buffer,"%d",info->global_parameters.size());
-		text += buffer;
-		
-		::MessageBox( ::GetForegroundWindow() , text.c_str() , "Polac Psycle Loader v0.01a" , MB_OK );
+	void plugin::MessBox(char *ptxt,char *caption,unsigned int type) {
+		#if defined _WIN64 || defined _WIN32
+			::MessageBox(::GetForegroundWindow(),ptxt,caption,type);
+		#else
+			///\todo
+		#endif
 	}
-}
 
-void CPsycle::set_track_count(int count)
-{
-	numTracks = count;
-}
+	/*********************************************************************************************************************/
+	// plugin ... implementation for zzub::plugin
 
-void CPsycle::mute_track(int index)
-{
-	if (mi)
-	{
-		mi->MuteTrack(index);
+	void plugin::init(zzub::archive * arc) {
+		if(!open()) return;
+		if(!arc) return;
+		zzub::instream * is = arc->get_instream("");
+		if(!is) return;
+		int read_version;
+		is->read<int>(read_version);
+		if(read_version != version) return; // version missmatch
+		int data_size;
+		is->read<int>(data_size);
+		if(!data_size) return;
+		unsigned char * const data(new unsigned char[data_size]);
+		is->read(data, data_size);
+		psycle_plugin->PutData(data);
+		delete[] data;
 	}
-}
 
-bool CPsycle::is_track_muted(int index) const
-{
-	if (mi)
-	{
-		return mi->IsTrackMuted(index);
+	void plugin::save(zzub::archive * arc) {
+		if(!arc) return;
+		if(!psycle_plugin) return;
+		zzub::outstream * os = arc->get_outstream("");
+		if(!os) return;
+		const int data_size = psycle_plugin->GetDataSize();
+		if(!data_size) return;
+		os->write<int>(version);
+		os->write<int>(data_size);
+		unsigned char * const data(new unsigned char[data_size]);
+		psycle_plugin->GetData(data);
+		os->write(data, data_size);
+		delete[] data;
 	}
 
-	return false;
-}
+	void plugin::process_events() {
+		if(!psycle_plugin) return;
+		const int n = int(info->global_parameters.size());
+		for (int i(0); i < n ; ++i) {
+			const zzub::parameter & zzub_param(*info->global_parameters[i]);
+			const psycle::plugin_interface::CMachineParameter & psycle_param(*psycle_plugin_param_info[i]);
+			const int val(global_params[i]);
+			if(val != zzub_param.value_none)
+				psycle_plugin->ParameterTweak(i, scale(
+					zzub_param.normalize(val),
+					psycle_param.MinValue, psycle_param.MaxValue));
+		}
+		for(int i(0); i < track_count; ++i) {
+			const track_param & param = track_params[i];
+			if(param.note!=zzub::note_value_none) {
+				if(param.note!=zzub::note_value_off) {
+					const int note = ((param.note >> 4) * 12) + (param.note & 15);
+					psycle_plugin->SeqTick(i, note, 0, param.command >> 8, param.command & 0xff);
+				}
+				else psycle_plugin->SeqTick(i,psycle::plugin_interface::NOTE_NO, 0, 0, 0);
+			}
+		}
+	}
 
-void CPsycle::midi_note(int channel,int value,int velocity)
-{
-	if (mi)
-	{
-		mi->MidiNote(channel,value,velocity);
+	bool plugin::process_stereo(float ** pin, float ** pout, int numsamples, int mode) {
+		if(!psycle_plugin) return false;
+		if(mode & zzub::process_mode_write) {
+			float * ldst = pout[0]; float * rdst = pout[1];
+			const float *lsrc = pin[0]; const float *rsrc = pin[1];
+			const float amp(32768);
+			int n = numsamples;
+			while(--n >= 0) {
+				*ldst++ = *lsrc++ * amp; *rdst++ = *rsrc++ * amp;
+			}
+			psycle_plugin->Work(pout[0], pout[1], numsamples, track_count);
+			ldst = pout[0]; rdst = pout[1];
+			const float deamp(1.0f / amp);
+			n = numsamples;
+			while(--n >= 0) {
+				*ldst++ *= deamp; *rdst++ *= deamp;
+			}
+			lsrc = pout[0]; rsrc = pout[1];
+			while(--numsamples >= 0) {
+				if(!is_denormal(*lsrc) || !is_denormal(*rsrc)) return true;
+				++lsrc; ++rsrc;
+			}
+		}
+		return false;
 	}
-}
 
-void CPsycle::midi_control_change(int ctrl,int channel,int value)
-{
-}
+	void plugin::command(int index) {
+		if(!psycle_plugin) return;
+		if(!index) psycle_plugin->Command();
+		else {
+			std::ostringstream s;
+			s
+				<< "copyright 2007 Frank Potulski <polac@gmx.de> and members of the psycle project http://psycle.sourceforge.net\n\n"
+				<< "now wrapping...\n\n"
+				<< "Name:\t\t" << info->name
+				<< "\nLabel:\t\t" << info->short_name
+				<< "\nAuthor:\t\t" << info->author
+				<< "\n\nPath:\t\t" << info->psy_path
+				<< "\n\nNumParams:\t" << info->global_parameters.size();
+				
+			#if defined _WIN64 || defined _WIN32
+				::MessageBox(::GetForegroundWindow(), s.str().c_str(), "Polac Psycle Loader v0.02a", MB_OK);
+			#else
+				///\todo
+			#endif
+		}
+	}
 
-void CPsycle::event(unsigned int data)
-{	
-}
-
-const char *CPsycle::describe_value(int param,int value)
-{
-	describe[0] = 0;
-
-	if (mi)
+	const char * plugin::describe_value(int param, int value) {
+		/// warning: not reentrant!
+		one_param_description[0] = 0;
+		if(!psycle_plugin) return one_param_description;
+		if(param < int(info->global_parameters.size())) {
+			const zzub::parameter & zzub_param = *info->global_parameters[param];
+			const psycle::plugin_interface::CMachineParameter & psycle_param(*psycle_plugin_param_info[param]);
+			value = scale(
+				zzub_param.normalize(value),
+				psycle_param.MinValue, psycle_param.MaxValue);
+			if(!psycle_plugin->DescribeValue(one_param_description, param, value))
+				std::sprintf(one_param_description, "%d", value);
+		} else std::sprintf(one_param_description, "%.2X %.2X", value >> 8 , value & 0xff);
+		return one_param_description;
+	}
+	
+	/*********************************************************************************************************************/
+	// plugin::global_params
+	
+	plugin::global_params_type::global_params_type(const plugin_info * info)
+	: data(), index(), size()
 	{
-		if ( param < int(info->global_parameters.size()) )
-		{
-			const zzub::parameter &srcParam = *info->global_parameters[param];		
-			const psycle::CMachineParameter &dstParam = *pinfo[param];			
-
-			value = Scale( Normalize(value,srcParam.value_min,srcParam.value_max) , dstParam.MinValue , dstParam.MaxValue );
-
-			if (!mi->DescribeValue(describe,param,value))
-			{
-				::sprintf(describe,"%d",value);
+		if(!info) return;
+		const int n(int(info->global_parameters.size()));
+		if(!n) return;
+		index = new int[n]; if(!index) return;
+		this->size = new char[n]; if(!this->size) return;
+		int size(0);
+		for(int i(0); i < n; ++i) {
+			const zzub::parameter &param = *info->global_parameters[i];
+			switch(param.type) {
+				case zzub::parameter_type_note:
+				case zzub::parameter_type_switch:
+				case zzub::parameter_type_byte:
+					index[i] = size;
+					this->size[i] = 1;
+					++size;
+					break;
+				case zzub::parameter_type_word:
+					index[i] = size;
+					this->size[i] = 2;
+					size += 2;
+					break;
+				default:
+					delete[] index; index = 0;
+					delete[] this->size; this->size = 0;
+					return;
 			}
 		}
-		else
-		{
-			::sprintf(describe,"%.2X %.2X", value >> 8 , value & 0xff );
-		}
+		if(size > 0) data = new unsigned char[size];
 	}
-	
-	return describe;
-}
 
-const envelope_info **CPsycle::get_envelope_infos(void)
-{
-	return 0;
-}
+	plugin::global_params_type::~global_params_type() {
+		delete[] data;
+		delete[] index;
+		delete[] size;
+	}
 
-bool CPsycle::play_wave(int wave,int note,float volume)
-{
-	return false;
-}
+	/*********************************************************************************************************************/
+	///\name explicit symbol exports
+	///\{
+		extern "C" {
+			PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT
+			const char *
+			PSYCLE__PLUGIN__CALLING_CONVENTION // unspecified by zzub interface but safer
+			zzub_get_signature() { return ZZUB_SIGNATURE; }
 
-void CPsycle::stop_wave(void)
-{
-
-}
-
-int CPsycle::get_wave_envelope_play_position(int env)
-{
-	return -1;
-}
-
-const char *CPsycle::describe_param(int param)
-{			
-	return 0;
-}
-
-bool CPsycle::set_instrument(const char *name)
-{
-	return false;
-}
-
-void CPsycle::get_sub_menu(int index,outstream *os)
-{
-
-}
-
-void CPsycle::add_input(const char *name)
-{
-
-}
-
-void CPsycle::delete_input(const char *name)
-{
-
-}
-
-void CPsycle::rename_input(const char *oldname,const char *newname)
-{
-
-}
-
-void CPsycle::input(float **samples,int size,float amp)
-{
-
-}
-
-bool CPsycle::handle_input(int index,int amp,int pan)
-{
-	return false;
-}
-
-//*****************************************************************************************************************************************************
-
-ZZUB_EXTERN_C const char *zzub_get_signature(void) {	
-	return ZZUB_SIGNATURE;
-}
-
-ZZUB_EXTERN_C plugincollection *zzub_get_plugincollection(void)
-{	
-	return new CPsycleCollection();
-}
-
-//*****************************************************************************************************************************************************
\ No newline at end of file
+			PSYCLE__PLUGIN__DYNAMIC_LINK__EXPORT
+			zzub::plugincollection *
+			PSYCLE__PLUGIN__CALLING_CONVENTION // unspecified by zzub interface but safer
+			zzub_get_plugincollection() { return new plugin_collection(); }
+		}
+	///\}
+}}}
Index: psy2zzub.h
===================================================================
--- psy2zzub.h	(revision 1412)
+++ psy2zzub.h	(working copy)
@@ -1,378 +1,171 @@
-/* psy2zzub.h
+// This source 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, or (at your option) any later version.
+// copyright 2007 Frank Potulski <polac@gmx.de>
+// copyright 2007 members of the psycle project http://psycle.sourceforge.net
 
-   Copyright (C) 2007 Frank Potulski (polac@gmx.de)
+#ifndef ZZUB__PLUGINS__PSYCLE_TO_ZZUB__INCLUDED
+#define ZZUB__PLUGINS__PSYCLE_TO_ZZUB__INCLUDED
+#pragma once
 
-   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 Street, Fifth Floor, Boston, MA 02110-1301
-   USA. */
-
-#ifndef ___PSY2ZZUB_H
-#define ___PSY2ZZUB_H
-
-#include <windows.h>
-
-#include <memory.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <string>
-#include <list>
-#include <vector>
-
-#include "other\autoptr.h"
-
-#include <zzub\plugin.h>
-#include <zzub\signature.h>
-
-#include "psycle\plugin_interface.hpp"
-
-using namespace zzub;
-using namespace psycle;
-using namespace std;
-
-#pragma intrinsic(memset)
-#pragma intrinsic(memcpy)
-
-#define _STRING_H_ 1
-
-//*****************************************************************************************************************************************************
-
-class CPsycleCollection : public plugincollection
-{
-public:
-
-	class CPsycleInfo : public info
-	{
-		friend class CPsycle;
-		friend class CPsycleCollection;		
-
-	public:
-
-		struct SParamInfo
-		{
-			SParamInfo()
-			{
-				name[0] = 0;
-				desc[0] = 0;
-			};
-
-			char name[32];
-			char desc[32];
-		};
-			
-		CPsycleInfo();
-		virtual ~CPsycleInfo();
-
-		bool operator <(const CPsycleInfo &other) const;
-		bool operator ==(const CPsycleInfo &other) const;
-
-		plugin *create_plugin(void) const;	
-		bool store_info(archive *arc) const;
-
-	private:		
-
-		string psy_name;
-		string psy_label;
-		string psy_path;
-		string psy_author;
-		string psy_uri;
-		string psy_command;
-
-		vector<SParamInfo> psy_param;
-	};	
-
-	CPsycleCollection();
-	virtual ~CPsycleCollection();
-
-	void ScanPlugins(char *path);
-	void AddPlugin(const char * const path);
-
-	void initialize(pluginfactory *factory);
-		
-	const info *get_info(const char *uri,archive *arc);
-		
-	const char *get_uri(void);
-		
-	void configure(const char *key,const char *value);
+#include <cstdlib>
+#include <cstdio>
+#include <string>
+#include <list>
+#include <vector>
 
-	void destroy(void);
-
-private:
-
-	static void ReplaceChar(char *str,const char toReplace,const char replacedBy);	
-
-private:
-
-	pluginfactory *factory;
-
-	list<CPsycleInfo *> plugins;
-};
-
-//*****************************************************************************************************************************************************
-
-class CPsycle : public plugin, public CFxCallback
-{
-	friend BOOL APIENTRY DllMain(HINSTANCE hm,DWORD dw,LPVOID lp);
-	friend const char *zzub_get_signature(void);
-	friend class CPsycleCollection::CPsycleInfo;
-	friend class CPsycleCollection;
-
-#pragma pack(1)
-
-	struct STrackParam
-	{		
-		unsigned char note;
-		unsigned short command;
-	};
-
-	/*struct SGlobalParam
-	{		
-		__forceinline operator unsigned short(void)
-		{
-			return param;
-		};
-		
-		unsigned short param;		
-	};*/
-
-	struct SGlobalParams
-	{
-		enum 
-		{
-			eSizeof_Byte=0,
-			eSizeof_Short
-		};
-
-		SGlobalParams(const CPsycleCollection::CPsycleInfo *info) : params(0), index(0), size(0)
-		{
-			if (info)
-			{
-				const int n = int(info->global_parameters.size());
-
-				if (n>0)
-				{
-					int size = 0;
-
-					index = (int *)::malloc( sizeof(int) * n );
-
-					this->size = (char *)::malloc( sizeof(char) * n );
-
-					if ( index && this->size )
-					{
-						for (int i=0;i<n;++i)
-						{
-							const parameter &param = *info->global_parameters[i];
-
-							switch (param.type)
-							{
-							
-							case zzub_parameter_type_note:
-							case zzub_parameter_type_switch:
-							case zzub_parameter_type_byte:
-								{
-									index[i] = size;
-
-									this->size[i] = eSizeof_Byte;
-									
-									++size;
-								}
-								break;
-
-							case zzub_parameter_type_word:
-								{
-									index[i] = size;
-
-									this->size[i] = eSizeof_Short;
-
-									size += 2;
-								}
-								break;
-
-							default:
-								{									
-									::free(index);
-
-									index = 0;
-
-									::free(this->size);
-
-									this->size = 0;
-
-									return;
-								}
-								break;
-
-							}
-						}
-
-						if (size>0)
-						{
-							params = (unsigned char *)::malloc(size);
-						}					
-					}									
-				}			
-			}
-		};
-
-		~SGlobalParams()
-		{
-			if (params)
-			{
-				::free(params);
-
-				params = 0;
-			}
-
-			if (index)
-			{
-				::free(index);
-
-				index = 0;
-			}
-
-			if (size)
-			{
-				::free(size);
-
-				size = 0;
-			}
-		};
-			
-		__forceinline int operator [](const int n) const
-		{			
-			//return int( params[ index[n] ] );
-
-			return (size[n]==eSizeof_Byte) ? int( params[ index[n] ] ) : int( *( (unsigned short *)&params[ index[n] ] ) );
-		};		
-
-		unsigned char *params;	
-
-		int *index;
-		
-		char *size;
-	};	
-
-#pragma pack()
-
-public:
-
-	enum 
-	{
-		eVersion = 1,
-		eMinTracks = 8,
-		eMaxTracks = 32,
-		eMinValue = 0,
-		eMaxValue = 0xFFFE		
-	};
-
-//**** CFxCallback ************************************************************************************************************************************
-
-	void MessBox(char *ptxt,char *caption,unsigned int type);
-	
-	int CallbackFunc(int cbkID,int par1,int par2,int par3);
-	
-	float *GetWaveLData(int inst,int wave);
-	float *GetWaveRData(int inst,int wave);
-	
-	int GetTickLength(void);
-	int GetSamplingRate(void);
-	int GetBPM(void);
-	int GetTPB(void);
-	
-//**** plugin *****************************************************************************************************************************************
-
-	void init(archive *arc);
-	void save(archive *arc);
-
-	void destroy(void);	
+#if defined _WIN64 || defined _WIN32
+	#include <windows.h> // for HMODULE
+#endif
 
-	void process_events(void);
-
-	bool process_stereo(float **pin,float **pout,int numsamples,int mode);
-	
-	void stop(void);
-	
-	void attributes_changed(void);
-	void command(int index);
-	
-	void set_track_count(int count);
-	
-	void mute_track(int index);	
-	bool is_track_muted(int index) const;
-	
-	void midi_note(int channel,int value,int velocity);
-	void midi_control_change(int ctrl,int channel,int value);
+#include <zzub/plugin.h>
+#include <zzub/signature.h>
 
-	void event(unsigned int data);
+#include "psycle/plugin_interface.hpp" ///\todo should be <psycle/plugin_interface.hpp>
+
+namespace zzub { namespace plugins { namespace psycle_to_zzub {
+
+	/// module handling
+	namespace module {
+		typedef 
+			#if defined _WIN64 || defined _WIN32
+				HMODULE
+			#else
+				void *
+			#endif
+			handle_type;
+	}
+
+	class plugin_info;
 	
-	const char * describe_value(int param,int value);
-	const envelope_info **get_envelope_infos(void);
-	bool play_wave(int wave,int note,float volume);
+	class plugin : public zzub::plugin, private psycle::plugin_interface::CFxCallback {
+		public:
+			///\name implementation for psycle::plugin_interface::CFxCallback
+			///\{
+				void MessBox(char *ptxt,char *caption,unsigned int type);
+				int CallbackFunc(int cbkID,int par1,int par2,int par3) { return 0; }
+				float * unused0(int, int) {return 0; }
+				float * unused1(int, int) { return 0; }
+				int GetTickLength() { return _master_info->samples_per_tick; }
+				int GetSamplingRate() { return _master_info->samples_per_second; }
+				int GetBPM() { return _master_info->beats_per_minute; }
+				int GetTPB() { return _master_info->ticks_per_beat; }
+			///\}
 	
-	void stop_wave(void);
-	
-	int get_wave_envelope_play_position(int env);
-
-	const char *describe_param(int param);
+			///\name implementation for zzub::plugin
+			///\{
+				void init(zzub::archive *arc);
+				void save(zzub::archive *arc);
+				void destroy();
+				void process_events();
+				bool process_stereo(float **pin,float **pout,int numsamples,int mode);
+				void stop() { if(psycle_plugin) psycle_plugin->Stop(); }
+				void attributes_changed() {}
+				void command(int index);
+				void set_track_count(int count) { track_count = count; }
+				void mute_track(int index) { if(psycle_plugin) psycle_plugin->MuteTrack(index); }
+				bool is_track_muted(int index) const { if(psycle_plugin) return psycle_plugin->IsTrackMuted(index); return false; }
+				void midi_note(int channel,int value,int velocity) { if(psycle_plugin) psycle_plugin->MidiNote(channel,value,velocity); }
+				void midi_control_change(int ctrl,int channel,int value) {}
+				void event(unsigned int data) {}
+				const char * describe_value(int param,int value);
+				const zzub::envelope_info **get_envelope_infos() { return 0; }
+				bool play_wave(int wave,int note,float volume) { return false; }
+				void stop_wave() {}
+				int get_wave_envelope_play_position(int env) { return -1; }
+				const char *describe_param(int param) { return 0; }
+				bool set_instrument(const char *name) { return false; }
+				void get_sub_menu(int index, zzub::outstream *) {}
+				void add_input(const char *name) {}
+				void delete_input(const char *name) {}
+				void rename_input(const char *oldname,const char *newname) {}
+				void input(float **samples,int size,float amp) {}
+				bool handle_input(int index,int amp,int pan) { return false; }
+			///\}
+			
+		private:
+			plugin(const plugin_info *);
+			virtual ~plugin() throw();
 
-	bool set_instrument(const char *name);
-	void get_sub_menu(int index,outstream *os);
+			bool open();
+			bool close();
+
+			const plugin_info * info;
+
+			class global_params_type {
+				public:
+					global_params_type(const plugin_info *);
+					~global_params_type();
+					
+					int operator[](const int n) const {
+						return (size[n] == 1) ?
+							data[index[n]] :
+							*reinterpret_cast<unsigned short int *>(&data[index[n]]);
+					}
+				
+				private:
+					unsigned char * data;
+					int * index;
+					char * size;
+					friend class plugin;
+			} global_params;
+
+			#pragma pack(push, 1)
+			struct track_param {
+				unsigned char note;
+				unsigned short command;
+			} * track_params;
+			#pragma pack(pop)
+
+			zzub::metaplugin * metaplugin;
+			module::handle_type module_handle;
+			psycle::plugin_interface::CMachineInterface * psycle_plugin;
+			psycle::plugin_interface::CMachineParameter const ** psycle_plugin_param_info;
+			int track_count;
+			char one_param_description[128];
+			
+			friend class plugin_collection;
+			friend class plugin_info;
+	};
 	
-	void add_input(const char *name);
-	void delete_input(const char *name);
-	void rename_input(const char *oldname,const char *newname);
-	void input(float **samples,int size,float amp);
-	bool handle_input(int index,int amp,int pan);
-
-//**** CPsycle ****************************************************************************************************************************************
-
-private:
-	
-	CPsycle(const CPsycleCollection::CPsycleInfo *_info);
-	virtual ~CPsycle();
-
-	bool Open(void);
-	bool Close(void);
-
-	__forceinline bool IsDenormal(const float &val) const
-	{		
-		return ( *((unsigned int *)&val) & 0x7f800000 ) == 0;
-	};
-
-private:	
-
-	static HINSTANCE hInst;	
-
-	CPsycleCollection::CPsycleInfo *info;
-
-	SGlobalParams global;
-
-	//TAutoArrayPtr<SGlobalParam> global;
-	TAutoArrayPtr<STrackParam> track;	
-
-	metaplugin *cm;
-
-	HMODULE hm;
-
-	CMachineInterface *mi;
-	const CMachineParameter **pinfo;
-
-	char describe[128];
-
-	int numTracks;
-};
-
-//*****************************************************************************************************************************************************
-
-#endif
\ No newline at end of file
+	class plugin_info : public zzub::info {
+		public:
+			///\name implementation for zzub::info
+			///\{
+				zzub::plugin * create_plugin() const { return new plugin(this); }
+				bool store_info(zzub::archive*) const { return false; }
+			///\}
+
+		private:
+			std::string psy_name, psy_label, psy_path, psy_author, psy_uri, psy_command;
+			struct param_info {
+				param_info() { name[0] = 0; desc[0] = 0; }
+				char name[32];
+				char desc[32];
+			};
+			std::vector<param_info> psy_param;
+			friend class plugin_collection;
+			friend class plugin;
+	};
+			
+	class plugin_collection : public zzub::plugincollection
+	{
+		public:
+			plugin_collection() : factory() {}
+			~plugin_collection();
+			
+			///\name implementation for zzub::plugincollection
+			///\{
+				void initialize(zzub::pluginfactory * factory);
+				const zzub::info * get_info(const char *uri, zzub::archive *arc) { return 0; }
+				const char * get_uri() { return 0; }
+				void configure(const char * key, const char * value) {}
+				void destroy();
+			///\}
+
+		private:
+			zzub::pluginfactory *factory;
+			void scan_plugins(std::string const & path);
+			void add_plugin(std::string const & path);
+			std::list<plugin_info*> plugin_infos;
+	};
+}}}
+#endif
