// Note: Instrumentation statements are highlighted in green 

#include <vobject.hpp>
#pragma hdrstop
#include "guitar_fretboard.hpp"

///////////////////////////////////////////////////////////////////////////////
// GuitarFretboard
///////////////////////////////////////////////////////////////////////////////

// Visual Member Definition 
VISIBILITY_START(GuitarFretboard, "Guitar Fretboard", 0)
VVARIABLE(GuitarFretboard, noteTable, "Musical notes", 0, 0)
VVCONTAINER(GuitarFretboard, fretTable, "Fret Table", 0, 0)
VVCONTAINER(GuitarFretboard, stringTable, "String Table", 0, 0)
VVARIABLE(GuitarFretboard, allFrettedNotes, "All Notes", 0, 0)
VVARIABLE(GuitarFretboard, activeFrettedNotes, "Active Notes ", 0, 0)
VISIBILITY_END

GuitarFretboard::GuitarFretboard(void) :
   currentNotePointer(NULL)
{
  CreateFretTable();
  CreateStringTable();
  CreateAllFrettedNotes();
}

GuitarFretboard::GuitarFretboard(const GuitarFretboard & fret_board) :
   currentNotePointer(NULL)
{
  *this = fret_board;
}

GuitarFretboard::~GuitarFretboard(void)
{
}

GuitarFretboard & GuitarFretboard::operator=(const GuitarFretboard & fret_board)
{
  fretTable = fret_board.fretTable;
  stringTable = fret_board.stringTable;
  noteTable = fret_board.noteTable;
  allFrettedNotes = fret_board.allFrettedNotes;
  activeFrettedNotes = fret_board.activeFrettedNotes;
   currentNotePointer = NULL;
  return *this;
}

void GuitarFretboard::CreateFretTable(void)
{
  fretTable.push_back(Fret(0, 15));
  fretTable.push_back(Fret(1, 64));
  fretTable.push_back(Fret(2, 111));
  fretTable.push_back(Fret(3, 156));
  fretTable.push_back(Fret(4, 199));
  fretTable.push_back(Fret(5, 241));
  fretTable.push_back(Fret(6, 282));
  fretTable.push_back(Fret(7, 321));
  fretTable.push_back(Fret(8, 359));
  fretTable.push_back(Fret(9, 396));
  fretTable.push_back(Fret(10, 432));
  fretTable.push_back(Fret(11, 465));
  fretTable.push_back(Fret(12, 499));
  fretTable.push_back(Fret(13, 530));
  fretTable.push_back(Fret(14, 562));
  fretTable.push_back(Fret(15, 591));
  fretTable.push_back(Fret(16, 621));
  fretTable.push_back(Fret(17, 649));
  fretTable.push_back(Fret(18, 676));
  fretTable.push_back(Fret(19, 701));
  fretTable.push_back(Fret(20, 726));
  fretTable.push_back(Fret(21, 751));
}

void GuitarFretboard::CreateStringTable(void)
{
  stringTable.push_back(GuitarString(*noteTable.GetAbsoluteNote("E3"), 10));
  stringTable.push_back(GuitarString(*noteTable.GetAbsoluteNote("A3"), 30));
  stringTable.push_back(GuitarString(*noteTable.GetAbsoluteNote("D4"), 50));
  stringTable.push_back(GuitarString(*noteTable.GetAbsoluteNote("G4"), 70));
  stringTable.push_back(GuitarString(*noteTable.GetAbsoluteNote("B4"), 90));
   stringTable.push_back(GuitarString(*noteTable.GetAbsoluteNote("E5"), 110));
}

template<class _Ty>
  struct Fret_compare {
  bool operator()(_Ty & _X, _Ty & _Y) const
    {return (_X.GetFretNumber() < _Y.GetFretNumber()); }
  };


void GuitarFretboard::CreateAllFrettedNotes(void)
{
  GuitarStringVector::iterator string_iter = stringTable.begin();
  while (string_iter != stringTable.end()) {
    MusicalNoteTable::iterator note_iter = noteTable.GetNoteIterator((*string_iter).openNote);
    FretVector::iterator fret_iter = fretTable.begin();
    while  (fret_iter != fretTable.end()) {
      allFrettedNotes.AddNote(FrettedNote(*note_iter, *fret_iter, *string_iter));
      fret_iter++;
      note_iter++;
    }
    string_iter++;
  }
  std::sort(allFrettedNotes.begin(), allFrettedNotes.end(),  Fret_compare<FrettedNote>());
}

void GuitarFretboard::CreateScale(unsigned short scale_flags, unsigned short key_flags,
                                  unsigned short first_fret, unsigned short last_fret)
{
  activeFrettedNotes.Clear();
  NoteVector valid_notes;
  noteTable.CreateValidNoteVector(scale_flags, key_flags, valid_notes);
  FrettedNoteTable::iterator fretted_note_iter = allFrettedNotes.begin();
  while(fretted_note_iter != allFrettedNotes.end()) {
    if (((*fretted_note_iter).GetFretNumber() >= first_fret) &&
        ((*fretted_note_iter).GetFretNumber() <= last_fret)) {
      if (noteTable.IsValidNote(*fretted_note_iter, valid_notes)) {
        if (noteTable.IsRootNote(*fretted_note_iter, valid_notes))
          (*fretted_note_iter).status |= ROOT;
        else
          (*fretted_note_iter).status &= ~ROOT;
        activeFrettedNotes.AddNote(*fretted_note_iter);
      }
    }
    fretted_note_iter++;
  }
}

void GuitarFretboard::DisplayNote(unsigned short midi_number)
{ 
  FrettedNote * new_note = allFrettedNotes.FindFrettedNote(midi_number);
  if (!currentNotePointer) {
    activeFrettedNotes.AddNote(*new_note);
    currentNotePointer = &(*activeFrettedNotes.begin());
  }
  else
    *currentNotePointer = *new_note;
  currentNotePointer->syncViews();
}

///////////////////////////////////////////////////////////////////////////////
// GuitarScaleViewer
///////////////////////////////////////////////////////////////////////////////

// Visual Member Definition 
VISIBILITY_START(GuitarScaleViewer, "Guitar ScaleViewer", 0)
VBITSET_VARIABLE(GuitarScaleViewer, scaleFlags, ScaleFlags, "Scale", 0, 0)
VBITSET_VARIABLE(GuitarScaleViewer, keyFlags, KeyFlags, "Key", 0, 0)
VVARIABLE(GuitarScaleViewer, firstFret, "First fret", 0, 0)
VVARIABLE(GuitarScaleViewer, lastFret, "Last fret", 0, 0)
VVARIABLE(GuitarScaleViewer, fretBoard, "Fretboard", 0, 0)
VVOID_FUNCTION(GuitarScaleViewer, CreateScale, "Create scale", 0, 0)
VVOID_FUNCTION(GuitarScaleViewer, ClearScale, "Clear scale", 0, 0)
VISIBILITY_END


GuitarScaleViewer::GuitarScaleViewer(void) :
  scaleFlags(MAJOR),
  keyFlags(E_KEY),
  firstFret(0),
  lastFret(21)
{
  CreateScale();        
}

GuitarScaleViewer::GuitarScaleViewer(const GuitarScaleViewer & scale_viewr)
{
  *this = scale_viewr;
}

GuitarScaleViewer::~GuitarScaleViewer(void)
{
}

GuitarScaleViewer & GuitarScaleViewer::operator=(const GuitarScaleViewer & scale_viewr)
{
  scaleFlags = scaleFlags;
  keyFlags = keyFlags;
  firstFret = firstFret;
  lastFret = lastFret;
  fretBoard = fretBoard;
  return *this;
}

void GuitarScaleViewer::CreateScale(void)
{
  fretBoard.CreateScale(scaleFlags, keyFlags, firstFret, lastFret);
}

void GuitarScaleViewer::ClearScale(void)
{
  fretBoard.activeFrettedNotes.Clear();
}

unsigned short GuitarScaleViewer::dataChangeNotification(void * member_ref, HVIEW h_view, unsigned short change_type)
{
  if ((change_type & DCN_INPUT) || (change_type & DCN_RESTORE))
    syncVariable(member_ref, h_view);
  if ((member_ref == &scaleFlags) || (member_ref == &keyFlags))
    CreateScale();        
  return VDATA_VALID;
}
Copyright 2002-2007 Outerface Technologies, Inc.