//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Thu Nov  9 17:08:28 PST 2000
// Last Modified: Sun Nov 12 18:54:06 PST 2000
// Filename:      ...sig/examples/all/pchlist.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/humdrum/pchlist.cpp
// Syntax:        C++; museinfo
//
// Description:   Generates a list of pitches in a Humdrum file and
//                the beat position and duration of the pitch.
//

#include "humdrum.h"

#include <string.h>

#ifndef OLDCPP
   #include <iostream>
   using namespace std;
#else
   #include <iostream.h>
#endif


// function declarations:
void      checkOptions(Options& opts, int argc, char** argv);
void      example(void);
void      preparePitch(char* buffer2, const char* buffer1);
void      printOutput(HumdrumFile& hfile);
void      usage(const char* command);

// User interface variables:
Options   options;
int       barlinesQ = 1;      // used with the -B option
int       midinoteQ = 0;      // used with the -m option
int       classQ    = 0;      // used with the -c option
int       base40Q   = 0;      // used with the -b option
int       trackQ    = 0;      // used with the -r option
int       tactusQ   = 0;      // used with the -t option

//////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv) {
   // process the command-line options
   checkOptions(options, argc, argv);

   HumdrumFile hfile(options.getArg(1));
   hfile.analyzeRhythm();
   printOutput(hfile);
   return 0;
}

//////////////////////////////////////////////////////////////////////////



//////////////////////////////
//
// checkOptions -- 
//

void checkOptions(Options& opts, int argc, char* argv[]) {
   opts.define("B|nobarlines=b", "don't display barlines");
   opts.define("m|midi|MIDI=b", "display pitches as MIDI note numbers");
   opts.define("c|class=b", "display pitches in pitch class notation");
   opts.define("b|base40=b", "display pitches in base40 notation");
   opts.define("r|track=b", "display track information");
   opts.define("t|tactus=b", "display metrical positions");

   opts.define("author=b",  "author of program"); 
   opts.define("version=b", "compilation info");
   opts.define("example=b", "example usages");   
   opts.define("h|help=b",  "short description");
   opts.process(argc, argv);
   
   // handle basic options:
   if (opts.getBoolean("author")) {
      cout << "Written by Craig Stuart Sapp, "
           << "craig@ccrma.stanford.edu, May 1998" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 3 July 1998" << endl;
      cout << "compiled: " << __DATE__ << endl;
      cout << MUSEINFO_VERSION << endl;
      exit(0);
   } else if (opts.getBoolean("help")) {
      usage(opts.getCommand());
      exit(0);
   } else if (opts.getBoolean("example")) {
      example();
      exit(0);
   }

   if (opts.getBoolean("nobarlines")) {
      barlinesQ = 0;
   } else {
      barlinesQ = 1;
   }

   if (opts.getBoolean("midi")) {
      midinoteQ = 1;
      base40Q = 0;
   } else {
      midinoteQ = 0;
   }

   if (opts.getBoolean("base40")) {
      base40Q = 1;
      midinoteQ = 0;
   } else {
      base40Q = 0;
   }

   if (opts.getBoolean("class")) {
      classQ = 1;
   } else {
      classQ = 0;
   }

   if (opts.getBoolean("tactus")) {
      tactusQ = 1;
   } else {
      tactusQ = 0;
   }

   if (opts.getBoolean("track")) {
      trackQ = 1;
   } else {
      trackQ = 0;
   }

}



//////////////////////////////
//
// example --
//

void example(void) {


}



//////////////////////////////
//
// printOutput --
//

void printOutput(HumdrumFile& hfile) {
   int i, j, k;
   char buffer1[1024] = {0};
   char buffer2[1024] = {0};
   double duration;
   for (i=0; i<hfile.getNumLines(); i++) {
      if ((hfile.getType(i) & 0xf0000) == 0x10000) {
         cout << hfile[i] << "\n";
      }
      if ((hfile.getType(i) & 0xf0000) == 0x00000) {
         cout << hfile[i] << "\n";
      }
      if (hfile.getType(i) == E_humrec_interpretation &&
           strncmp(hfile[i][0], "**", 2) == 0) {
         cout << "**abeat\t";
         if (midinoteQ) {
            cout << "**midi";
         } else if (base40Q) {
            cout << "**base40";
         } else {
            cout << "**kern";
         }
         cout << "\t**dur";
         if (tactusQ) {
            cout << "\t**takt";
         } 
         if (trackQ) {
            cout << "\t**track";
         }
         cout << "\n";
      }
      if (hfile.getType(i) == E_humrec_interpretation &&
           strcmp(hfile[i][0], "*-") == 0) {
         cout << "*-\t*-\t*-";
         if (tactusQ) {
            cout << "\t*-";
         }
         if (trackQ) {
            cout << "\t*-";
         }
         cout << "\n";
      }

      if (barlinesQ && hfile.getType(i) == E_humrec_data_measure) {
         if (hfile[i].equalFieldsQ("**kern")) {
            const char* mmarker;
            mmarker = hfile[i][0];
            cout << mmarker << "\t"
                 << mmarker << "\t"
                 << mmarker;
            if (tactusQ) {
               cout << "\t" << mmarker;
            }
            if (trackQ) {
               cout << "\t" << mmarker;
            }
            cout << "\n";
             
         } else {
            cout << "=\t=\t=";
            if (tactusQ) {
               cout << "\t=";
            }
            if (trackQ) {
               cout << "\t=";
            }
            cout << "\n";
         }
      }
      
      if (hfile.getType(i) != E_humrec_data) {
         continue;
      }

      for (j=0; j<hfile[i].getFieldCount(); j++) {
         if (hfile[i].getExInterpNum(j) != E_KERN_EXINT) {
            continue;
         }
         for (k=0; k<hfile[i].getTokenCount(j); k++) {
            if (strcmp(hfile[i][j], ".") == 0) {
               continue;
            }
            hfile[i].getToken(buffer1, j, k);
            if (strchr(buffer1, '_') != NULL) {
               // ignore notes which are tied
               continue;
            }
            if (strchr(buffer1, ']') != NULL) {
               // ignore notes which are tied
               continue;
            }

            preparePitch(buffer2, buffer1);
            duration = hfile.getTiedDuration(i, j, k);

            cout << hfile.getAbsBeat(i) << "\t";

            if (midinoteQ) {
               int note = Convert::kernToMidiNoteNumber(buffer2);
               if (classQ) {
                  note = note % 12;
               }
               cout << note << "\t";
            } else if (base40Q) {
               int note;
               if (classQ) {
                  note = Convert::kernToBase40Class(buffer2);
               } else {
                  note = Convert::kernToBase40(buffer2);
               }
               cout << note << "\t";
            } else {
               cout << buffer2 << "\t";
            }

            cout << duration << "\t";
 
            if (tactusQ) {
               cout << hfile.getBeat(i) << "\t";
            }

            if (trackQ) {
               cout << hfile[i].getSpineInfo(j);
            }

            cout << "\n";
         }
      }
   }
}



//////////////////////////////
//
// preparePitch --
//

void preparePitch(char* buffer2, const char* buffer1) {
   strcpy(buffer2, buffer1);
}


//////////////////////////////
//
// usage --
//

void usage(const char* command) {


}



// md5sum: 760c04f8bd29eb10df5a345601f852bd pchlist.cpp [20050403]