/*  SpiralSynth
 *  Copyright (C) 2000 David Griffiths <dave@blueammonite.f9.co.uk>
 *
 *  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 MAINSYNTH
#define MAINSYNTH

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Button.H>
#include <strstream>
#include "GUI/OscillatorGUI.h"
#include "GUI/EnvelopeGUI.h"
#include "GUI/FilterGUI.h"
#include "GUI/MixerGUI.h"
#include "GUI/DelayGUI.h"
#include "GUI/SequencerGUI.h"
#include "GUI/OutputGUI.h"
#include "GUI/ScopeGUI.h"
#include "GUI/PatchBankGUI.h"
#include "GUI/RouteGUI.h"
#include "Amp.h"
#include "Midi.h"
#include "SynthInfo.h"

const int NUM_PATCHES=100;
const int PATCH_STRINGSIZE=1024;

class Synth
{
public:
	Synth();
	~Synth();
	
	Fl_Window *CreateWindow();
	void       DoIdle();
	void       CloseMidi() {m_Midi.Close();}
	
	Fl_Window 	  *Window;
	
private:

	void AllocMem();
	void Trigger(int octave, int note, int vol);
	void UnTrigger(int octave, int note);

	int m_Oct;
	int m_CurrentVoice;
	
	// list of keys currently pressed down
	char *m_KeyVoice;
	
	// list of notes being played by each voice
	int *m_VoiceNote;
	int *m_VoiceOctave;

	// These buffers require malloc'ing
	short *m_Databuf;
	short *m_Databuf2;
	short *m_Databuf3;
	short *m_OscControlbuf1;
	short *m_OscControlbuf2;
	short *m_OscControlbuf3;
	short *m_EnvControlbuf;
    short *m_LFOControlbuf;
	short *m_BothControlbuf;
	
	// One per voice needed
	short **m_XModbuf1;
	short **m_XModbuf2;
	
	Oscillator	  m_Osc1;
	OscillatorGUI m_Osc1GUI;
	Oscillator	  m_Osc2;
	OscillatorGUI m_Osc2GUI;
	Oscillator	  m_Osc3;
	OscillatorGUI m_Osc3GUI;
	Envelope	  m_Env1;
	EnvelopeGUI   m_Env1GUI;
	Amp			  m_OscAmp1;
	Envelope	  m_Env2;
	EnvelopeGUI   m_Env2GUI;
	Amp		      m_OscAmp2;
	Envelope	  m_Env3;
	EnvelopeGUI   m_Env3GUI;
	Amp			  m_OscAmp3;
	Filter		  m_Filter;
	FilterGUI     m_FilterGUI;
	Mixer		  m_Mixer;
	MixerGUI      m_MixerGUI;
	Mixer		  m_Mixer2;
	MixerGUI      m_Mixer2GUI;
	Delay		  m_Delay;
	DelayGUI      m_DelayGUI;
	Envelope	  m_FilterEnv;
	EnvelopeGUI   m_FilterEnvGUI;
	Oscillator	  m_LFO;
	LFOGUI 		  m_LFOGUI;
	RouteGUI 	  m_LFORouteGUI;
	RouteGUI 	  m_EnvRouteGUI;
	
	PatchBankGUI  m_PatchBank;
	
	//Sequencer	    m_Seq;
	//SequencerGUI  m_SeqGUI;
	
	Output 	      m_Out;
	OutputGUI     m_OutGUI;

	ScopeGUI	  m_Scope;
	
	MidiDevice m_Midi;
	MidiEvent m_CurrentEvent;

	int m_CurrentPatch;
	
	void SavePatch(int n);
	void LoadPatch(int n);
		
	void WritePatch(int n, char *in);
	int  ReadPatch(int n, char *out);
	
	void Randomise();
	
	void UpdateValues();

	void Route();
	
	friend istream &operator>>(istream &s, Synth &o);
	friend ostream &operator<<(ostream &s, Synth &o);

	
};

istream &operator>>(istream &s, Synth &o);
ostream &operator<<(ostream &s, Synth &o);

#endif
