//=========================================================
//  MusE
//  Linux Music Editor
//  $Id: node.h,v 1.1.1.1 2003/10/29 10:05:11 wschweer Exp $
//
//  (C) Copyright 2001 Werner Schweer (ws@seh.de)
//=========================================================

#ifndef __AUDIONODE_H__
#define __AUDIONODE_H__

#include <list>
#include <qstring.h>
#include <asm/atomic.h>

class Xml;
class Pipeline;
class SndFile;

const int AUDIO_GROUPS = 4;
const int FIFO_BUFFER = 64;

//---------------------------------------------------------
//   Fifo
//---------------------------------------------------------

struct FifoBuffer {
      float* buffer;
      int size;
      int maxSize;
      int pos;
      int segs;

      FifoBuffer() {
            buffer  = 0;
            size    = 0;
            maxSize = 0;
            }
      };

class Fifo {
      int nbuffer;
      int ridx;               // read index; only touched by reader
      int widx;               // write index; only touched by writer
      atomic_t count;         // buffer count; writer increments, reader decrements
      FifoBuffer** buffer;

   public:
      Fifo();
      ~Fifo();
      void clear() {
            ridx = 0;
            widx = 0;
            atomic_set(&count, 0);
            }
      bool put(int, unsigned long, float** buffer, unsigned long pos);
      bool getWriteBuffer(int, unsigned long, float** buffer, unsigned long pos);
      void add();
      bool get(int&, unsigned long&, float** buffer, unsigned long& pos);
      void remove();
      };

//---------------------------------------------------------
//   SNode
//    sound node
//    common part for audio and midi tracks
//---------------------------------------------------------

class SNode {
      int _activity;
      int _lastActivity;      //tmp value

   protected:
      bool _recordFlag;
      bool _mute;
      bool _solo;
      bool _off;

   public:
      SNode();
      SNode(const SNode&);
      virtual void setMute(bool val);
      virtual void setOff(bool val);
      virtual void setSolo(bool val) = 0;
      bool solo() const                  { return _solo;         }
      bool mute() const                  { return _mute;         }
      bool off() const                   { return _off;          }
      virtual bool isMute() const = 0;
      virtual void addSolo() = 0;
      bool recordFlag() const            { return _recordFlag;   }
      virtual void setRecordFlag1(bool f) {}
      virtual void setRecordFlag2(bool f) { _recordFlag = f;      }
      int activity()                     { return _activity;     }
      void setActivity(int v)            { _activity = v;        }
      int lastActivity()                 { return _lastActivity; }
      void setLastActivity(int v)        { _lastActivity = v;    }
      void addActivity(int v)            { _activity += v;       }

      virtual bool soloMode() = 0;
      bool readProperty(Xml& xml, const QString& tag);
      };

//---------------------------------------------------------
//   MidiNode
//---------------------------------------------------------

class MidiNode : public SNode {
      static bool _soloMode;
      static std::list<MidiNode*> nodeList;

   public:
      MidiNode();
      virtual ~MidiNode();
      virtual bool isMute() const;
      virtual void setSolo(bool val);
      virtual void addSolo();
      virtual bool soloMode() { return _soloMode;     }
      };

//---------------------------------------------------------
//   AudioNode
//    a managed collection of audio ports
//    synth, track, group
//---------------------------------------------------------

class AudioNode : public SNode {
      static bool _soloMode;
      static std::list<AudioNode*> nodeList;

   public:
      std::list<AudioNode*> _inRoute;
      std::list<AudioNode*> _outRoute;

   private:
      void readRecfile(Xml& xml);

   protected:
      int _ports;                   // 1 - mono, 2 - stereo
      double _volume;
      double _pan;
      bool _prefader;               // prefader metering
      Pipeline* _efxPipe;

      int _meter[2];
      int _peak[2];
      SndFile* _recFile;
      Fifo fifo;                    // fifo -> _recFile

      virtual bool getData(int, unsigned long, float**);

   public:
      AudioNode();
      AudioNode(const AudioNode&);
      virtual ~AudioNode();

      virtual bool isMute() const;
      virtual void setSolo(bool val);
      virtual void addSolo();
      virtual bool soloMode()            { return _soloMode;     }

      void putFifo(int channels, unsigned long n, float** bp);

      SndFile* recFile() const           { return _recFile; }
      void setRecFile(SndFile* sf)       { _recFile = sf;   }
      void record();

      virtual void setRecordFlag1(bool f);
      virtual void setRecordFlag2(bool f);
      virtual void setMute(bool val);
      virtual void setOff(bool val);

      int ports() const                  { return _ports; }
      void setPorts(int n);
      double volume() const              { return _volume;   }
      void setVolume(double val)         { _volume = val;    }
      double pan() const                 { return _pan;      }
      void setPan(double val)            { _pan = val;       }
      bool prefader() const              { return _prefader; }
      void setPrefader(bool val);
      Pipeline* efxPipe()                { return _efxPipe;  }

      void writeConfiguration(int, Xml&) const;
      void readConfiguration(Xml&);
      void readVolume(Xml& xml);

      void connectIn(AudioNode* p);
      void connectOut(AudioNode* p);
      void disconnectIn(AudioNode* p);
      void disconnectOut(AudioNode* p);
      void connect();
      void disconnect();
      void disconnectClear();

      AudioNode* route() const;

      void segmentSizeChanged();

      void resetMeter();
      void resetPeaks();
      static void resetAllMeter();

      int meter(int ch) const  { return _meter[ch]; }
      int peak(int ch) const   { return _peak[ch]; }

      virtual void addData(int, unsigned long, float**);
      virtual void copyData(int, unsigned long, float**);

      bool canRecord() const;
      };

typedef std::list<AudioNode*>::iterator iAudioNode;
typedef std::list<AudioNode*>::const_iterator ciAudioNode;

//---------------------------------------------------------
//   AudioPort
//---------------------------------------------------------

class AudioPort : public AudioNode {
   public:
      AudioPort() : AudioNode() {}
      };

//---------------------------------------------------------
//   AudioOutputPort
//---------------------------------------------------------

class AudioOutputPort : public AudioPort {
   public:
      AudioOutputPort();
      ~AudioOutputPort();
      void process(unsigned long);
      };

//---------------------------------------------------------
//   AudioInputPort
//---------------------------------------------------------

class AudioInputPort : public AudioPort {
      virtual bool getData(int, unsigned long, float**);

   public:
      AudioInputPort();
      };

extern AudioOutputPort audioOutput;  // output device node
extern AudioInputPort audioInput;    // input device node

extern AudioNode audioGroups[AUDIO_GROUPS];
extern int mixerGroups;

extern void connectNodes(AudioNode* out, AudioNode* in);
extern void disconnectNodes(AudioNode* out, AudioNode* in);
extern AudioNode* name2Node(const QString&);
extern QString node2Name(const AudioNode*);

#endif

