//=========================================================
//  MusE
//  Linux Music Editor
//    $Id: synth.h,v 1.22.2.3 2005/01/08 22:54:10 spamatica Exp $
//  (C) Copyright 2000-2004 Werner Schweer (ws@seh.de)
//=========================================================

#ifndef __SYNTH_H__
#define __SYNTH_H__

#include <qfileinfo.h>
#include <vector>

#include "globals.h"
#include "node.h"
#include "instruments/minstrument.h"
#include "mididev.h"
#include "midiport.h"
#include "track.h"

class MidiEvent;
class Mess;
struct MESS;

class SynthI;
class SynthIF;

//---------------------------------------------------------
//   Synth
//    software synthesizer
//---------------------------------------------------------

class Synth {
   protected:
      QFileInfo info;
      int _instances;

   public:
      Synth(const QFileInfo& fi);
      virtual ~Synth() {}
      virtual const char* description() const { return ""; }
      virtual const char* version() const { return ""; }

      int instances() const       { return _instances; }
      virtual void incInstances(int val) { _instances += val; }
      QString baseName() const    { return info.baseName(); }
      QString path() const        { return info.dirPath(true); }
      virtual void* instantiate() = 0;
      virtual SynthIF* createSIF() const = 0;
      };

//---------------------------------------------------------
//   MessSynth
//---------------------------------------------------------

class MessSynth : public Synth {
      const MESS* descr;

   public:
      MessSynth(const QFileInfo& fi) : Synth(fi) { descr = 0; }
      virtual ~MessSynth() {}
      virtual const char* description() const;
      virtual const char* version() const;
      virtual void* instantiate();
      virtual SynthIF* createSIF() const;
      };

class Mess;

//---------------------------------------------------------
//   SynthIF
//    synth instance interface
//---------------------------------------------------------

class SynthIF {
   public:
      SynthIF() {}
      virtual bool guiVisible() const = 0;
      virtual void showGui(bool v) = 0;
      virtual bool hasGui() const = 0;
      virtual void getGeometry(int*, int*, int*, int*) const = 0;
      virtual void setGeometry(int, int, int, int) = 0;
      virtual iMPEvent getData(MidiPort*, MPEventList*, iMPEvent, unsigned pos, int ports, unsigned n, float** buffer) = 0;
      virtual bool putEvent(const MidiPlayEvent& ev) = 0;
      virtual MidiPlayEvent receiveEvent() = 0;
      virtual int eventsPending() const = 0;
      virtual bool init(Synth* s) = 0;
      virtual int channels() const = 0;
      virtual void deactivate3() = 0;
      virtual const char* getPatchName(int, int, int) const = 0;
      virtual const char* getPatchName(int, int, MType) = 0;
      virtual void populatePatchPopup(QPopupMenu*, int, MType) = 0;
      virtual void write(int level, Xml& xml) const = 0;
      virtual void setParameter(int idx, float value) = 0;
      virtual int getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max) = 0;
      };

//---------------------------------------------------------
//   SynthI
//    software synthesizer instance
//    Track
//    MidiDevice
//    MidiInstrument
//---------------------------------------------------------

class SynthI : public AudioTrack, public MidiDevice,
   public MidiInstrument
      {
      SynthIF* sif;

   protected:
      Synth* synthesizer;
      std::vector<float> initParams;

      bool getData(unsigned a, int b, unsigned c, float** data);
      bool putEvent(const MidiPlayEvent& ev) {
            return sif->putEvent(ev);
            }

      virtual QString open() { return QString("OK");}
      virtual void close()   {}
      virtual bool putMidiEvent(const MidiPlayEvent&) {return true;}
      virtual Track* newTrack() const { return 0; }

   public:
      SynthI();
      virtual ~SynthI();
      SynthI* clone() const { return new SynthI(*this); }

      bool initInstance(Synth* s, const QString& instanceName);

      void read(Xml&);
      virtual void write(int, Xml&) const;

      void setName(const QString& s);
      QString name() const          { return AudioTrack::name(); }

      Synth* synth() const          { return synthesizer; }
      virtual bool isSynti() const  { return true; }

      virtual const char* getPatchName(int ch, int prog, MType t) {
            return sif->getPatchName(ch, prog, t);
            }
      virtual void populatePatchPopup(QPopupMenu* m, int i, MType t) {
            sif->populatePatchPopup(m, i, t);
            }

      void setParameter(const char* name, const char* value) const;

      bool guiVisible() const { return sif->guiVisible(); }
      void showGui(bool v)    { sif->showGui(v); }
      bool hasGui() const     { return sif->hasGui(); }
      void getGeometry(int* x, int* y, int* w, int* h) const {
            sif->getGeometry(x, y, w, h);
            }
      void setGeometry(int x, int y, int w, int h) {
            sif->setGeometry(x, y, w, h);
            }

      MidiPlayEvent receiveEvent() { return sif->receiveEvent(); }
      int eventsPending() const    { return sif->eventsPending(); }
      void deactivate2();
      void deactivate3();
      bool isActivated() const         { return synthesizer && sif; }
      virtual bool hasAuxSend() const  { return true; }
      };

//---------------------------------------------------------
//   MessSynthIF
//    mess synthesizer instance
//---------------------------------------------------------

class MessSynthIF : public SynthIF {
      Mess* _mess;

   public:
      MessSynthIF() { _mess = 0; }
      virtual bool guiVisible() const;
      virtual void showGui(bool v);
      virtual bool hasGui() const;
      virtual void getGeometry(int*, int*, int*, int*) const;
      virtual void setGeometry(int, int, int, int);
      virtual iMPEvent getData(MidiPort*, MPEventList*, iMPEvent, unsigned pos, int ports, unsigned n, float** buffer);
      virtual bool putEvent(const MidiPlayEvent& ev);
      virtual MidiPlayEvent receiveEvent();
      virtual int eventsPending() const;
      virtual bool init(Synth* s);
      virtual int channels() const;
      virtual void deactivate3();
      virtual const char* getPatchName(int, int, int) const { return ""; }
      virtual const char* getPatchName(int, int, MType);
      virtual void populatePatchPopup(QPopupMenu*, int, MType);
      virtual void write(int level, Xml& xml) const;
      virtual void setParameter(int, float) {}
      virtual int getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max);
      };

extern std::vector<Synth*> synthis;  // array of available synthis
#endif

