/***************************************************************************
                          MIDIFileAnalyzer.h  -  description
                             -------------------
    begin                : Don Feb 3 2005
    copyright            : (C) 2005 by klaus frieler
    email                : kgf@omniversum.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef _LIBMELODY_MIDIFILENANALYZER_H
#define _LIBMELODY_MIDIFILENANALYZER_H

#include "types.h"

#include "jdkmidi/world.h"
#include "jdkmidi/fileread.h"
#include "jdkmidi/msg.h"

using namespace jdkmidi;

class TrackInfo{
   public:
      TrackInfo(
         uint nTrkNr = 0,
         const char *sInstName = "",
         const char *sTrackName = "",
         uint nNoteOns  = 0,
         uint nNoteOffs = 0,
         uint nTimeSigEvents = 0,
         uint nTempoEvents = 0,
         uint nKeySigEvents = 0,
         int  nChNr = -1,
         bool bPolyphonic = false):
            m_nTrkNr(nTrkNr),
            m_sInstName(sInstName),
            m_sTrackName(sTrackName),
            m_nNoteOns(nNoteOns),
            m_nNoteOffs(nNoteOffs),
            m_nTimeSigEvents(nTimeSigEvents),
            m_nTempoEvents(nTempoEvents),
            m_nKeySigEvents(nKeySigEvents),
            m_nChNr(nChNr),
            m_bPolyphonic(bPolyphonic)
         {}
      ~TrackInfo(){};

      //getter
      uint     getTrackNr()      { return m_nTrkNr;}
      int      getChNr()         { return m_nChNr;}
      string   getInstName()     { return m_sInstName;}
      string   getTrackName()    { return m_sTrackName;}

      uint     getNoteOns()      { return m_nNoteOns;}
      uint     getNoteOffs()     { return m_nNoteOffs;}
      uint     getTimeSigEvents(){ return m_nTimeSigEvents;}
      uint     getTempoEvents()  { return m_nTempoEvents;}
      uint     getKeySigEvents() { return m_nKeySigEvents;}
      bool     hasNotes()        { return m_nNoteOns>0;}
      bool     hasTimeSigEvent() { return m_nTimeSigEvents>0;}
      bool     hasTempoEvent()   { return m_nTempoEvents>0;}
      bool     hasKeySigEvent()  { return m_nKeySigEvents>0;}
      int      getChannel()      { return m_nChNr;}
      bool     isUsable()        { return hasNotes() && !m_bPolyphonic /*&& m_nTempoEvents<3*/; }
      bool     isSignatureTrack(){ return !hasNotes() && (hasTimeSigEvent() || hasTempoEvent() || hasKeySigEvent());}

      //setter
      void     setInstName(const char* sInstName)  { m_sInstName  = string(sInstName); }
      void     setTrackName(const char* sTrackName){ m_sTrackName = string(sTrackName);}
      void     setTrkNr(const uint nTrkNr){ m_nTrkNr = nTrkNr;}
      void     countNoteOns()       { m_nNoteOns++; }
      void     countNoteOffs()      { m_nNoteOffs++; }
      void     countTimeSigEvent()  { m_nTimeSigEvents++; }
      void     countTempoEvent()    { m_nTempoEvents++; }
      void     countKeySigEvent()   { m_nKeySigEvents++; }
      void     setChannel(uint ch)   { m_nChNr = ch;}
      void     setPolyphonic()      { m_bPolyphonic = true;}
      
      void     dump();
      
   protected:
      uint     m_nTrkNr;
      string   m_sInstName;
      string   m_sTrackName;
      uint     m_nNoteOns, m_nNoteOffs;
      uint     m_nTimeSigEvents;
      uint     m_nTempoEvents;
      uint     m_nKeySigEvents;
      uint     m_nChNr;
      bool     m_bPolyphonic;
      
};
typedef vector<TrackInfo> TrackInfoList;


class MIDIFileAnalyzer: public MIDIFileEvents
{
   public:
      MIDIFileAnalyzer(): m_nCurTrk(0), m_nSigTrkNum(nopos), m_sErrText(""), m_bIsWellFormed(false), m_state(other), m_curTime(0), m_nDivision(0)
{};
      ~MIDIFileAnalyzer(){}
      

      bool     analyze();
      bool     isWellFormed()       { return m_bIsWellFormed;}
      uint     getNumUsableTracks() { return (uint)m_usableTracks.size();}
      uint     getMaxTrackNr();
      int      selectTrack();
      uint     getSigTrkNum()       { return m_nSigTrkNum;}
      
      string   getErrText(){ return m_sErrText;}
      void dump(bool bUsables = false)
      {
         if(!bUsables){
            for(uint i = 0; i<m_trackInfos.size();++i){
               m_trackInfos[i].dump();
            }
         }
         else{
            for(uint i = 0; i<m_usableTracks.size();++i){
               m_usableTracks[i].dump();
            }
         }
      }
// The possible events in a MIDI Files
//
      virtual void    mf_note_on( const MIDITimedMessage &msg );
      virtual void    mf_note_off( const MIDITimedMessage &msg );

      virtual void    mf_timesig( MIDIClockTime time, int, int, int, int );
      virtual void    mf_tempo( MIDIClockTime time, unsigned long tempo );
      virtual void    mf_keysig(MIDIClockTime time, int, int );
      virtual void    mf_text( MIDIClockTime time, int, int, unsigned char * );

      virtual void    mf_error( char * );

      virtual void    mf_starttrack( int trk );
      virtual void    mf_endtrack( int trk );
      virtual void    mf_header( int, int, int );


protected:
      TrackInfoList     m_trackInfos;
      TrackInfoList     m_usableTracks;
      uint              m_nCurTrk;
      uint              m_nSigTrkNum;
      string            m_sErrText;
      bool              m_bIsWellFormed;
      MIDIState         m_state;
      uint              m_curTime;
      ulong             m_nDivision;

private:
    
};
#endif
