//=========================================================
//  MusE
//  Linux Music Editor
//  $Id: track.h,v 1.2 2003/10/29 22:14:12 spamatica Exp $
//
//  (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
//=========================================================

#ifndef __TRACK_H__
#define __TRACK_H__

#include <qstring.h>
#include <vector>
#include <map>

#include "part.h"
#include "key.h"
#include "node.h"
#include "mixdowndialog.h"

class Pipeline;
class Xml;
class MidiDevice;
class SndFile;

enum StaffMode { Single, Split };

//---------------------------------------------------------
//   Track
//---------------------------------------------------------

class Track {
      static int snGen;
      QString _comment;
      int _outPort;
      int _outChannel;
      int _inPortMask;        // bitmask of accepted record ports
      int _inChannelMask;     // bitmask of accepted record channels
      QString _name;
      int _sn;
      int _y;
      int _height;            // visual height in arranger

   public:
      enum TrackType { MIDI=0, DRUM, WAVE };

   private:
      TrackType _type;
      bool _locked;
      bool _selected;
      PartList _parts;

      void init();

   public:
      Track(const Track&);
      Track(TrackType);
      Track(const QString&, TrackType);
      virtual ~Track();
      int sn() const                  { return _sn; }
      virtual void setSn(int n);
      int newSn()                     { return snGen++; }
      QString comment() const         { return _comment; }
      void setComment(const QString& s) { _comment = s; }

      int y() const;
      void setY(int n)                { _y = n;         }
      int height() const              { return _height; }
      void setHeight(int n)           { _height = n;    }

      bool selected() const           { return _selected; }
      void setSelected(bool f)        { _selected = f; }
      bool locked() const             { return _locked; }
      void setLocked(bool b)          { _locked = b; }

      const QString& name() const     { return _name; }
      void setName(const QString& s)  { _name = s; }

      TrackType type() const          { return _type; }
      void setType(TrackType t)       { _type = t; }
      PartList* parts()               { return &_parts; }
      const PartList* cparts() const  { return &_parts; }
      Part* findPart(int tick);
      iPart addPart(Part* p);

      virtual void read(Xml&);
      virtual void write(int, Xml&) const;
      virtual Track* newTrack() const = 0;
      virtual Track* clone() const    = 0;
      virtual void copy(const Track*) = 0;

      virtual bool recordFlag() const = 0;
      virtual void setRecordFlag1(bool f) = 0;
      virtual void setRecordFlag2(bool f) = 0;

      void setInChannelMask(int i);
      void setOutChannel(int i)       { _outChannel = i; }
      void setOutPort(int i)          { _outPort = i; }
      void setInPortMask(int i);
      int outPort() const             { return _outPort;     }
      int inPortMask() const          { return _inPortMask;  }
      int outChannel() const          { return _outChannel;  }
      int inChannelMask() const       { return _inChannelMask; }

      virtual Part* newPart(Part*p=0, bool clone = false) = 0;
      void dump() const;
      virtual void splitPart(Part*, int, Part*&, Part*&);
      virtual SNode* node() = 0;
      };

//---------------------------------------------------------
//   MidiTrack
//---------------------------------------------------------

class MidiTrack : public Track, public MidiNode {
      EventList* _events;     // tmp Events during midi import
                              // and recording
      bool _midiThruFlag;     // echo received events to outPort

   public:
      MidiTrack();
      MidiTrack(const MidiTrack&);
      MidiTrack(const QString&);
      virtual ~MidiTrack();

      void init();

      virtual SNode* node() { return this; }

      NKey key;               // Notenschlüssel
      Scale scale;            // Tonart
      NKey keyL;              // lower System (mode == Split)
      Scale scaleL;

      int noteQuant;          // Noten Darstellungs-Quantisierung
      int restQuant;          // Pausen Darstellungs-Quantisierung
      StaffMode mode;
      int splitpoint;

      // play parameter
      int transposition;
      int velocity;
      int delay;
      int len;
      int compression;

      virtual bool recordFlag() const    { return MidiNode::recordFlag(); }
      virtual void setRecordFlag1(bool f) { MidiNode::setRecordFlag1(f); }
      virtual void setRecordFlag2(bool f) { MidiNode::setRecordFlag2(f); }

      EventList* events() const          { return _events; }

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

      bool midiThruFlag() const     { return _midiThruFlag; }
      void setMidiThruFlag(bool f)  { _midiThruFlag = f; }

      virtual MidiTrack* newTrack() const { return new MidiTrack(); }
      virtual MidiTrack* clone() const;
      virtual void copy(const Track* t);
      virtual Part* newPart(Part*p=0, bool clone=false);

      MidiDevice* outDevice() const;
      MidiDevice* inDevice() const;
      };

//---------------------------------------------------------
//   WaveTrack
//---------------------------------------------------------

class WaveTrack : public Track, public AudioNode {
      void init();

      Fifo prefetchFifo;  // prefetch Fifo

   public:
      static bool firstWaveTrack;

   public:
      WaveTrack();
      WaveTrack(const WaveTrack&);
      virtual ~WaveTrack();
      WaveTrack(QString const& s);

      virtual SNode* node()              { return this; }
      virtual bool recordFlag() const    { return AudioNode::recordFlag(); }
      virtual void setRecordFlag1(bool f) {
            AudioNode::setRecordFlag1(f);
            }
      virtual void setRecordFlag2(bool f) {
            AudioNode::setRecordFlag2(f);
            }

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

      virtual WaveTrack* newTrack() const { return new WaveTrack(); }
      virtual WaveTrack* clone() const;
      virtual void copy(const Track* t);
      virtual Part* newPart(Part*p=0, bool clone=false);

      virtual void fetchData(int pos, unsigned long samples);
      virtual bool getData(int, unsigned long, float**);

      void clearPrefetchFifo() { prefetchFifo.clear(); }

      virtual void setSn(int n);
      };

//---------------------------------------------------------
//   TrackList
//---------------------------------------------------------

typedef std::list<Track*>::iterator iTrack;
typedef std::list<Track*>::const_iterator ciTrack;

class TrackList : std::list<Track*> {
   public:
      Track* add(Track*);
      void deselect();
      unsigned index(Track*);
      Track* sfind(int sn);     // search serial number
      Track* findIdx(int sn);   // search index
      iTrack find(int n);

      iTrack begin()           { return std::list<Track*>::begin(); }
      iTrack end()             { return std::list<Track*>::end(); }
      ciTrack begin() const    { return std::list<Track*>::begin(); }
      ciTrack end() const      { return std::list<Track*>::end(); }
      int size() const         { return std::list<Track*>::size(); }
      void push_back(Track* t) { std::list<Track*>::push_back(t); }
      bool empty() const       { return std::list<Track*>::empty(); }
      void insert(iTrack i, Track* t) { std::list<Track*>::insert(i, t); }
      Track* front() const     { return std::list<Track*>::front(); }
      Track* back() const      { return std::list<Track*>::back(); }
      void clear()             { std::list<Track*>::clear(); }
      void erase(iTrack i)     { std::list<Track*>::erase(i); }
      void erase(Track* t);
      void clearDelete();
      };

#endif

