/*
  ZynAddSubFX - a software synthesizer
 
  Part.h - Part implementation
  Copyright (C) 2002-2005 Nasca Octavian Paul
  Author: Nasca Octavian Paul

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License 
  as published by the Free Software Foundation.

  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 (version 2) for more details.

  You should have received a copy of the GNU General Public License (version 2)
  along with this program; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

*/

#ifndef PART_H
#define PART_H

#define MAX_INFO_TEXT_SIZE 1000

#include "../globals.h"
#include "../Params/ADnoteParameters.h"
#include "../Params/SUBnoteParameters.h"
#include "../Params/PADnoteParameters.h"
#include "../Synth/ADnote.h"
#include "../Synth/SUBnote.h"
#include "../Synth/PADnote.h"
#include "../Params/Controller.h"
#include "../Misc/Microtonal.h"
#include "../DSP/FFTwrapper.h"
#include "../Effects/EffectMgr.h"
#include "XMLwrapper.h"

class Master;

class Part{

    public:
      Part(Microtonal *microtonal_,FFTwrapper *fft_, Master* master);
      ~Part();

      /* Midi commands implemented */      
      void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); 
      void NoteOff(unsigned char note); 
      void AllNotesOff();//panic
      void SetController(unsigned int type,int par);
      void RelaseSustainedKeys();//this is called when the sustain pedal is relased 
      void RelaseAllKeys();//this is called on AllNotesOff controller

      /* The synthesizer part output */      
      void ComputePartSmps();//Part output
	
      //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank)


      //saves the instrument settings to a XML file
      //returns 0 for ok or <0 if there is an error
      int saveXML(char *filename);
      int loadXMLinstrument(const char *filename);

      void add2XML(XMLwrapper *xml);
      void add2XMLinstrument(XMLwrapper *xml);
      
      void defaults();
      void defaultsinstrument();
      
      void applyparameters();
      
      void getfromXML(XMLwrapper *xml);
      void getfromXMLinstrument(XMLwrapper *xml);

      void cleanup();

//      ADnoteParameters *ADPartParameters;
//      SUBnoteParameters *SUBPartParameters;

      //the part's kit
      struct {
        unsigned char Penabled,Pmuted,Pminkey,Pmaxkey;
	unsigned char *Pname;
	unsigned char Padenabled,Psubenabled,Ppadenabled;
	unsigned char Psendtoparteffect;
        ADnoteParameters *adpars;
        SUBnoteParameters *subpars;
        PADnoteParameters *padpars;
      } kit[NUM_KIT_ITEMS];

      
      //Part parameters
      void setkeylimit(unsigned char Pkeylimit);
      void setkititemstatus(int kititem,int Penabled_);

      unsigned char Penabled;//if the part is enabled
      unsigned char Pvolume;//part volume
      unsigned char Pminkey;//the minimum key that the part receives noteon messages
      unsigned char Pmaxkey;//the maximum key that the part receives noteon messages
      void setPvolume(char Pvolume);
      unsigned char Pkeyshift;//Part keyshift
      unsigned char Prcvchn;//from what midi channel it receive commnads
      unsigned char Ppanning;//part panning
      void setPpanning(char Ppanning);
      unsigned char Pvelsns;//velocity sensing (amplitude velocity scale)
      unsigned char Pveloffs;//velocity offset
      unsigned char Pnoteon;//if the part receives NoteOn messages
      unsigned char Pkitmode;//if the kitmode is enabled
      unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums)

      unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic
      unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased
      
      unsigned char *Pname; //name of the instrument
      struct{//instrument additional information
    	    unsigned char Ptype;
	    unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1];
	    unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1];
      } info;
      
      
      REALTYPE *partoutl;//Left channel output of the part
      REALTYPE *partoutr;//Right channel output of the part

      REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer

      enum NoteStatus{KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED};

      REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master
      REALTYPE panning;//this is applied by Master, too
      
      Controller ctl;//Part controllers

      EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument) 
      unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out)
      bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed
      

      Master* master;
      
      int lastnote;      
      
    private:
      void KillNotePos(int pos); 
      void RelaseNotePos(int pos);      
      int killallnotes;//is set to 1 if I want to kill all notes
      
      struct PartNotes{
        NoteStatus status;
        int note;//if there is no note playing, the "note"=-1
	int itemsplaying;
	struct {	
    	    ADnote *adnote;
    	    SUBnote *subnote;
    	    PADnote *padnote;
	    int sendtoparteffect;
	} kititem[NUM_KIT_ITEMS];
	int time;
      };
	
      PartNotes partnote[POLIPHONY];
      
      REALTYPE *tmpoutl;//used to get the note
      REALTYPE *tmpoutr;
	
      REALTYPE oldfreq;//this is used for portamento
      Microtonal *microtonal;
      FFTwrapper *fft;
};

#endif