//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sat Oct 14 19:55:21 PDT 2006
// Last Modified: Sat Oct 14 19:55:30 PDT 2006
// Filename:      ...sig/examples/all/dynaplot.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/humdrum/dynaplot.cpp
// Syntax:        C++; museinfo
//
// Description:   Create displays of dynamics v timings of notes.
//

#include "humdrum.h"

#include <string.h>
#include <ctype.h>

#ifndef OLDCPP
   #include <sstream>
   #define SSTREAM stringstream
   #define CSTRING str().c_str()
   using namespace std;
#else
   #ifdef VISUAL
      #include <strstrea.h>     /* for windows 95 */
   #else
      #include <strstream.h>
   #endif
   #define SSTREAM strstream
   #define CSTRING str()
#endif
   

// function declarations
void      checkOptions(Options& opts, int argc, char* argv[]);
void      example(void);
void      usage(const char* command);
void      processFile(HumdrumFile& file);
double    getTimeFromLine(HumdrumFile& hfile, int line);
void      printMeasureData(Array<double>& times, Array<int>& labels);
double    getNextTime(HumdrumFile& hfile, int line);
void      getMeasureData(HumdrumFile& infile, Array<double>& times, 
                              Array<int>& labels);
void      getDynamicData(HumdrumFile& infile, 
                              Array<Array<double> >& times, 
			      Array<Array<double> >& dynamics, 
                              Array<Array<double> >& tracks);

// global variables
Options   options;            // database for command-line arguments
int       debugQ   = 0;       // used with --debug option


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

int main(int argc, char* argv[]) {
   HumdrumFile infile, outfile;

   // process the command-line options
   checkOptions(options, argc, argv);

   // if no command-line arguments read data file from standard input
   int numinputs = options.getArgCount();
   if (numinputs < 1) {
      infile.read(cin);
   } else {
      infile.read(options.getArg(1));
   }
   
   processFile(infile);

   return 0;
}


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



//////////////////////////////
//
// processFile --
//

void processFile(HumdrumFile& infile) {
   infile.analyzeRhythm();

   Array<double> measuretimes;   // time of first note in measure
   Array<int>    measurenumbers; // measure number of measure in score

   Array<Array<double> > times;
   Array<Array<double> > dynamics;
   Array<Array<double> > tracks;

   getMeasureData(infile, measuretimes, measurenumbers);
   getDynamicData(infile, times, dynamics, tracks);

   printMeasureData(measuretimes, measurenumbers);
}



//////////////////////////////
//
// getDynamicData --
//

void getDynamicData(HumdrumFile& infile, 
      Array<Array<double> >& times, Array<Array<double> >& dynamics, 
      Array<Array<double> >& tracks) {

   times.setSize(infile.getNumLines() * 10);
   times.setSize(0);
   dynamics.setSize(infile.getNumLines() * 10);
   dynamics.setSize(0);
   tracks.setSize(infile.getNumLines() * 10);
   tracks.setSize(0);

   int i;
   for (i=0; i<infile.getNumLines(); i++) {

//  do stuff here...

   }
}



//////////////////////////////
//
// getMeasureData --
//

void getMeasureData(HumdrumFile& infile, Array<double>& times, 
      Array<int>& labels) {

   times.setSize(infile.getNumLines());
   times.setSize(0);
   labels.setSize(infile.getNumLines());
   labels.setSize(0);

   double currenttime = 0.0;
   int    number = 0;

   int i;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() == E_humrec_data_measure) {
         if (sscanf(infile[i][0], "=%d", &number) == 1) {
            labels.append(number);
            currenttime = getNextTime(infile, i);
            times.append(currenttime);
         }
      }
   }
}



//////////////////////////////
//
// printMeasureData --
//


void printMeasureData(Array& times, Array& labels) {
   int i;
   cout << "measures = {\n";
   for (i=0; i<times.getSize(); i++) {
      cout << "{" << labels[i] << "," << times[i] << "}";
      if (i < times.getSize() - 1) {
         cout << ", ";
      }

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

}


//////////////////////////////
//
// getNextTime -- get the next time value on one of the following lines.
//

double getNextTime(HumdrumFile& hfile, int line) {
   double atime = -1.0;
   int foundtime = 0;

   while (!foundtime && line < hfile.getNumLines()) {
      line++;
      atime = getTimeFromLine(hfile, line);
      if (atime > 0.0) {
         break;
      }
   }

   return atime;
}



//////////////////////////////
//
// getTimeFromLine --
//

double getTimeFromLine(HumdrumFile& hfile, int line) {
   int i;
   double output;

   if (hfile[line].getType() != E_humrec_data) {
      return -1.0;
   }

   for (i=0; i<hfile[line].getFieldCount(); i++) {
      if (strcmp(hfile[line].getExInterp(i), "**time") == 0) {
         if (strcmp(hfile[line][i], ".") == 0) {
            return -1.0;
         }
         if (sscanf(hfile[line][i], "%lf", &output) == 1) {
            return output;
         } else {
            return -1.0;
         }
      }
   }
      
   return -1.0;
}



//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//

  
void checkOptions(Options& opts, int argc, char* argv[]) {

   opts.define("debug=b");                // print debug info
   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, Oct 2006" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 15 Oct 2006" << 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);
   }

   debugQ   = opts.getBoolean("debug");
}
  


//////////////////////////////
//
// example -- example usage of the quality program
//

void example(void) {
   cout <<
   "                                                                         \n"
   << endl;
}



//////////////////////////////
//
// usage -- gives the usage statement for the meter program
//

void usage(const char* command) {
   cout <<
   "                                                                         \n"
   << endl;
}

/*
MeasureLines[data_, min_, max_, color_] := 
  Module[{lines, ndata, labels, times, size, startpoints, endpoints, 
      allpoints},
    ndata = Transpose[data];
    labels = ndata[[1]];
    times = ndata[[2]];
    size = Length[times];
    startpoints = Table[{times[[i]], min}, {i, 1, size}];
    text = Table[ Text[ labels[[i]], startpoints[[i]], {0, 1}], {i, 1, size}];
    endpoints = Table[{times[[i]], max}, {i, 1, size}];
    allpoints = Transpose[{startpoints, endpoints}];
    lines = Map[Line, allpoints];
    {color, text, lines}
   ]




 */


// md5sum: c874ae93952a06a45796f2ea5dc6ef28 dynaplot.cpp [20090626]