//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Mon Oct 14 23:58:44  2002
// Last Modified: Mon Apr 25 11:30:20 PDT 2005
// Filename:      ...sig/examples/all/jointextract.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/humdrum/jointextract.cpp
// Syntax:        C++; museinfo
//
// Description:   Extract joint information from a spine related to multiple
//                **kern data spines.
//

#include "humdrum.h"

#include <string.h>
#include <stdio.h>

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


// function declarations:
void      checkOptions(Options& opts, int argc, char** argv);
void      example(void);
void      usage(const char* command);
void      processFile(HumdrumFile& infile);
int       findTargetSpine(HumdrumFile& infile, const char* targetstr);
void      printExtractedJointInfo(HumdrumFile& infile, int line, 
                                 int targetspine);

const char* interp = "**kern";
const char* target = "";

// User interface variables:
Options   options;
int       jointspine = 1;       // used with -j option
int       inlineq    = 0;       // used with -i option

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

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

   for (i=1; i<=options.getArgCount(); i++) {
      infile.clear();
      infile.read(options.getArg(i));
      processFile(infile);
   }

   return 0;
}

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


//////////////////////////////
//
// findTargetSpine -- 
//

int findTargetSpine(HumdrumFile& infile, const char* targetstr) {
   int i, j;

   for (i=0; i<infile.getNumLines(); i++) {
      if (strncmp(infile[i][0], "**", 2) != 0) {
         continue;
      }

      for (j=0; j<infile[i].getFieldCount(); j++) {
         if (strcmp(targetstr, infile[i][j]) == 0) {
            return infile[i].getPrimaryTrack(j);
         }
      }

      break;
   }

   return -1;

}



//////////////////////////////
//
// countNotes --
//

int countNotes(HumdrumRecord& dataline, int field) {
   if (strcmp(dataline[field], ".") == 0) {
      return 0;
   }

   int notecount = 0;

   int len = strlen(dataline[field]);
   char tempstr[len*2+1];

   int i;
   int tokencount = dataline.getTokenCount(field);

   for (i=0; i<tokencount; i++) {
      dataline.getToken(tempstr, field, i);
      if (strcmp(tempstr, ".") == 0) {
         continue;
      }
      if (strchr(tempstr, '_') != NULL) {   // ignore tied notes
         continue;
      }
      if (strchr(tempstr, ']') != NULL) {   // ignore tied notes
         continue;
      }
      if (strchr(tempstr, 'r') != NULL) {   // ignore rests
         continue;
      }

      if (strchr(tempstr, 'a') != NULL) {   // count an a note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'b') != NULL) {   // count a b note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'c') != NULL) {   // count a c note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'd') != NULL) {   // count a d note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'e') != NULL) {   // count an e note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'f') != NULL) {   // count an f note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'g') != NULL) {   // count a g note
         notecount++;
         continue;
      }

      if (strchr(tempstr, 'A') != NULL) {   // count an A note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'B') != NULL) {   // count a B note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'C') != NULL) {   // count a C note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'D') != NULL) {   // count a D note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'E') != NULL) {   // count an E note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'F') != NULL) {   // count an F note
         notecount++;
         continue;
      }
      if (strchr(tempstr, 'G') != NULL) {   // count a G note
         notecount++;
         continue;
      }

      cerr << "Warning: don't understand: " << dataline[field] << endl;


   }

   return notecount;
}



//////////////////////////////
//
// printExtractedJointInfo --
//

void printExtractedJointInfo(HumdrumFile& infile, int line, int targettrack) {
   
   Array<int> basecounts;
   basecounts.setSize(infile.getMaxTracks());
   basecounts.setSize(0);
   int count = 0;

   int targetindex = -1;

   int i, j;
   for (i=0; i<infile[line].getFieldCount(); i++) {
      if (infile[line].getExInterpNum(i) == E_KERN_EXINT) {
         count = countNotes(infile[line], i);
         basecounts.append(count);
      }
      if (strcmp(infile[line].getExInterp(i), target) == 0) {
         targetindex = i;
      }
   }


   int before = 0;
   for (i=0; i<jointspine; i++) {
      before += basecounts[i];
   }

   int len = strlen(infile[line][targetindex]);
   char tmpstr[len+1];
   
   if (inlineq) {
      for (i=0; i<infile[line].getFieldCount(); i++) {
         if (i != targetindex) {
            cout << infile[line][i];
         } else {
            if (basecounts[jointspine] <= 0) {
               cout << ".";
            } else {
               for (j=0; j<basecounts[jointspine]; j++) {
                  infile[line].getToken(tmpstr, targetindex, j + before);
                  cout << tmpstr;
                  if (j<basecounts[jointspine]-1) {
                     cout << " ";
                  }
               }
            }
         }
         if (i < infile[line].getFieldCount()-1) {
            cout << "\t";
         }
      }
   } else {
      if (basecounts[jointspine] <= 0) {
         cout << ".";
      } else {
         for (i=0; i<basecounts[jointspine]; i++) {
            infile[line].getToken(tmpstr, targetindex, i + before);
            cout << tmpstr;
            if (i<basecounts[jointspine]-1) {
               cout << " ";
            }
         }
      }
   }

}



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

void processFile(HumdrumFile& infile) {

   int i, j;
   int counter = 0;

   int targetspine = findTargetSpine(infile, target);

   for (i=0; i<infile.getNumLines(); i++) {
      counter = 0;
      switch (infile.getType(i)) {
         case E_humrec_data_comment:
         case E_humrec_data_kern_measure:
         case E_humrec_interpretation:
            if (!inlineq) {
               for (j=0; j<infile[i].getFieldCount(); j++) {
                  if (infile[i].getPrimaryTrack(j) == targetspine) {
                     counter++;
                     if (counter > 1) {
                        cout << "\t";
                     }
                     cout << infile[i][j];
                  }
               }
            } else {
               cout << infile[i];
            }
            cout << "\n";
            break;

         case E_humrec_data:
            printExtractedJointInfo(infile, i, targetspine);
            cout << "\n";
            break;

         case E_humrec_none:
         case E_humrec_empty:
         case E_humrec_global_comment:
         case E_humrec_bibliography:
         default:
            cout << infile[i] << "\n";
      }

   }


}



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

void checkOptions(Options& opts, int argc, char* argv[]) {
   opts.define("joint|j=i:1", "the joint spine to extract, starting at 1");
   opts.define("target|t=s", "the target interpretation to extract from");
   opts.define("inline|i=b", "extract the data inline with original input");

   opts.define("author=b",  "author of program"); 
   opts.define("version=b", "compilation info");
   opts.define("example=b", "example usages");   
   opts.define("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, Sep 2006" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 12 Sep 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);
   }

   jointspine = opts.getInteger("joint") - 1;
   if (jointspine < 0) {
      jointspine = 0;
   }

   target = opts.getString("target");
   inlineq = opts.getBoolean("inline");

}



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

void example(void) {


}



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

void usage(const char* command) {

}



// md5sum: b65954c7296d58a653820dd756cc20eb jointextract.cpp [20060915]