Files
Work/guitar/backup/20030501/tablature.cpp
2024-08-07 09:16:27 -04:00

418 lines
10 KiB
C++

#include <guitar/Tablature.hpp>
#include <guitar/GlobalDefs.hpp>
#include <guitar/TabWriter.hpp>
#include <guitar/guitar.hpp>
#include <guitar/MessageBox.hpp>
#include <midiseq/midiout.hpp>
#include <common/file.hpp>
#include <common/profile.hpp>
#include <common/purehdc.hpp>
#include <common/guiwnd.hpp>
#include <common/diskinfo.hpp>
#include <common/versioninfo.hpp>
const TabEntries &Tablature::getTabEntries(void)const
{
return mTabEntries;
}
void Tablature::setTabEntries(const TabEntries &entries)
{
mTabEntries.remove();
for(int index=0;index<entries.size();index++)
{
mTabEntries.insert(&((TabEntries&)entries)[index]);
}
}
const TabRanges &Tablature::getTabRanges(void)const
{
return mTabRanges;
}
void Tablature::setTabRanges(const TabRanges &ranges)
{
mTabRanges=ranges;
}
bool Tablature::play(MIDIOutputDevice &midiDevice)
{
if(!midiDevice.hasDevice())return false;
for(int index=0;index<mTabEntries.size();index++)
{
TabEntry &tabEntry=mTabEntries[index];
::OutputDebugString(String(String().fromInt(index)+String(":")+tabEntry.toString()+String("\n")).str());
tabEntry.play(midiDevice);
}
return true;
}
String Tablature::getTypes(void)const
{
String strType;
for(int index=0;index<mTabEntries.size();index++)
{
TabEntry &tabEntry=((TabEntries&)mTabEntries)[index];
strType+=String("(")+String().fromInt(index)+String(",")+String().fromInt(tabEntry.getNoteType().toInt())+String(")");
}
return strType;
}
bool Tablature::setTypeAt(int index,const NoteType &noteType)
{
if(index>=mTabEntries.size())
{
GlobalDefs::outDebug("[Tablature::setTypeAt] index out of bounds : "+String().fromInt(index));
return false;
}
mTabEntries[index].setNoteType(noteType);
return true;
}
bool Tablature::open(const String &pathFileTablature)
{
mLastError=None;
mPathFileTablature=pathFileTablature;
if(mPathFileProject.isNull())mPathFileProject=pathFileTablature.betweenString(0,'.')+String(STRING_PRJEXTENSION);
if(!loadTabFile(pathFileTablature))return false;
mPathFileName=pathFileTablature;
if(!parseTab())return false;
return true;
}
bool Tablature::import(String pathFileTablature)
{
mLastError=None;
String strExtension;
String pathFileTablatureImport;
pathFileTablatureImport=pathFileTablature;
strExtension=Profile::getExtension(pathFileTablature);
strExtension.lower();
if(strExtension.isNull()||!(strExtension==String(STRING_TABEXTENSION)))return false;
pathFileTablature=Profile::removeExtension(pathFileTablature);
pathFileTablature+=String("_imp")+strExtension;
mPathFileTablature=pathFileTablature;
if(mPathFileProject.isNull())mPathFileProject=getPathFileProject(pathFileTablatureImport);
if(!loadTabFile(pathFileTablatureImport))return false;
mPathFileName=pathFileTablature;
if(!parseTab())return false;
saveAs(pathFileTablature);
return true;
}
String Tablature::getPathFileProject(const String &pathFileTablature)
{
return Profile::removeExtension(pathFileTablature)+String(STRING_PRJEXTENSION);
}
bool Tablature::saveAs(const String &pathFileTablature)
{
TabWriter tabWriter;
if(pathFileTablature.isNull())return false;
return tabWriter.write(mTabEntries,pathFileTablature);
}
bool Tablature::save(void)
{
if(mPathFileTablature.isNull())return false;
return saveAs(mPathFileTablature);
}
bool Tablature::openProject(const String &pathFileName)
{
DiskInfo diskInfo;
File inFile;
String strLine;
String strDirectory;
mPathFileProject=pathFileName;
strDirectory=mPathFileProject;
Profile::makeDirectoryName(strDirectory);
if(!diskInfo.setCurrentDirectory(strDirectory)||!inFile.open(pathFileName))
{
mLastError=FileOpenError;
return false;
}
if(!inFile.readLine(strLine))return false;
if(!(strLine=="WINTABV1.00"))return false;
if(!inFile.readLine(strLine))return false;
if(!(strLine.betweenString(0,'=')==String("TABLATURE")))return false;
strLine=strLine.betweenString('=',0);
if(strLine.isNull())
{
MessageBox::messageBox("Project does not contain a reference to any tablature.",strLine);
return false;
}
if(!open(strLine))return false;
while(inFile.readLine(strLine))
{
if(strLine.betweenString(0,'=')==String("TYPES"))parseTypes(strLine);
else if(strLine.betweenString(0,'=')==String("RANGE"))parseRange(strLine);
}
return true;
}
bool Tablature::saveProject(const String &pathFileName)
{
File outFile;
if(!pathFileName.isNull())mPathFileProject=pathFileName;
if(mPathFileProject.isNull())return false;
if(!outFile.open(mPathFileProject,"wb"))return false;
outFile.writeLine("WINTABV1.00");
if(mPathFileName.isNull())mPathFileName=Profile::removeExtension(mPathFileProject)+String(STRING_TABEXTENSION);
outFile.writeLine(String("TABLATURE=")+mPathFileName);
outFile.writeLine(String("TYPES=")+getTypes());
for(int index=0;index<mTabRanges.size();index++)
{
Range &range=mTabRanges[index];
String strLine="RANGE=";
strLine+=String().fromInt(range.getBeginRange());
strLine+=";";
strLine+=String().fromInt(range.getEndRange());
strLine+=";";
strLine+=range.getRangeName();
outFile.writeLine(strLine);
}
saveAs(mPathFileName);
return true;
}
void Tablature::parseRange(String strLine)
{
Range range;
range.setBeginRange(strLine.betweenString('=',';').toInt());
range.setEndRange(strLine.betweenString(';',';').toInt());
range.setRangeName(strLine.betweenString(';',0).betweenString(';',0));
mTabRanges.insert(&range);
}
void Tablature::parseTypes(String strLine)
{
String strIndex;
String strType;
strLine=strLine.betweenString('=',0);
char *ptr=strLine.str();
if(ptr)
{
ptr=::strtok(ptr,")");
while(true)
{
String str(ptr);
strIndex=str.betweenString('(',',');
strType=str.betweenString(',',0);
setTypeAt(strIndex.toInt(),NoteType().fromInt(strType.toInt()));
ptr=::strtok(0,")");
if(!ptr)break;
}
}
}
bool Tablature::parseTab(void)
{
int result;
int elapsedTime;
if(!mTablature.size())
{
mLastError=NoTabsParsedError;
return false;
}
elapsedTime=::GetTickCount();
for(int index=0;index<mTablature.size();index++)
{
TabLines &tabLines=mTablature[index];
TabEntry entry;
if(-1!=(result=tabLines.firstElement(entry,mFretboard)))
{
if(1==result)
{
mTabEntries.insert(&entry);
}
while(-1!=(result=tabLines.nextElement(entry,mFretboard)))
{
if(1==result)
{
mTabEntries.insert(&entry);
}
}
}
}
GlobalDefs::outDebug(String("Parsed ")+String().fromInt(mTabEntries.size())+String(" tabs in ")+String().fromInt((::GetTickCount()-elapsedTime)/1000)+String(" seconds."));
if(mTabEntries.size())return true;
mLastError=NoFrettedNotesError;
return false;
}
bool Tablature::loadTabFile(const String &pathFileName)
{
File inFile;
String strLine;
int length;
int startElement;
int elapsedTime;
if(!inFile.open(pathFileName,"rb"))
{
mLastError=FileOpenError;
return false;
}
mTablature.remove();
elapsedTime=::GetTickCount();
for(int line=0;inFile.readLine(strLine);line++)
{
length=strLine.length();
if(2>length)continue;
if(isTabLine(strLine,startElement))
{
mTablature.insert(&TabLines());
TabLines &tabLines=mTablature[mTablature.size()-1];
tabLines[0]=strLine.substr(startElement);
for(int string=1;string<6;string++,line++)
{
if(!inFile.readLine(strLine))break;
tabLines[string]=strLine.substr(startElement);
}
}
}
GlobalDefs::outDebug(String("[Tablature::loadTabFile] ")+String().fromInt(mTablature.size())+String(" tabs, in ")+String().fromInt((::GetTickCount()-elapsedTime)/1000)+String(" seconds."));
if(mTablature.size())return true;
mLastError=NoTabsParsedError;
return false;
}
bool Tablature::isTabLine(const String &strLine,int &startElement)const
{
int lineLength=strLine.length();
char charAt0;
char charAt1;
char charAt2;
char charAt3;
char charAt4;
char lastChar;
if(!lineLength)return false;
charAt0=lineLength?strLine.charAt(0):0;
charAt1=lineLength>=1?strLine.charAt(1):0;
charAt2=lineLength>=2?strLine.charAt(2):0;
charAt3=lineLength>=3?strLine.charAt(3):0;
charAt4=lineLength>=4?strLine.charAt(4):0;
lastChar=lineLength?strLine.charAt(lineLength-1):0;
if((charAt0=='e'||charAt0=='E')&&(charAt1==':'||charAt1=='|'))
{
startElement=2;
return true;
}
if(charAt0=='|'&&charAt1=='-')
{
startElement=1;
return true;
}
if(charAt0==':'&&(::isalnum(charAt1)||charAt1=='-'))
{
startElement=1;
return true;
}
if(charAt0==':'&&charAt1=='-')
{
startElement=1;
return true;
}
if((charAt0=='E'||charAt0=='e')&&charAt1==' '&&charAt2=='-')
{
startElement=2;
return true;
}
if(charAt0=='-')
{
startElement=0;
return true;
}
if(charAt0==' '&&charAt1==' '&&(charAt2=='E'||charAt2=='e')&&charAt3==' '&&charAt4=='|')
{
startElement=5;
return true;
}
if(charAt0==' '&&charAt1=='|')
{
startElement=2;
return true;
}
if(charAt0==' '&&charAt1=='-')
{
startElement=1;
return true;
}
if(charAt0==' '&&charAt1==' '&&charAt2=='I'&&charAt3=='-')
{
startElement=3;
return true;
}
if(charAt0==' '&&(charAt1=='E'||charAt1=='e')&&charAt2=='-')
{
startElement=2;
return true;
}
if((charAt0=='E'||charAt0=='e')&&charAt1=='-')
{
startElement=1;
return true;
}
if((charAt0=='E'||charAt0=='e')&&charAt1==' '&&charAt2=='|'&&charAt3=='-')
{
startElement=2;
return true;
}
if((charAt0=='E'||charAt0=='e')&&charAt1==' '&&charAt2=='|'&&charAt3=='-')
{
startElement=2;
return true;
}
if((charAt0=='E'||charAt0=='e')&&charAt1==']'&&charAt2=='-')
{
startElement=2;
return true;
}
if(charAt0==':'&&charAt1==' '&&charAt2=='-')
{
startElement=2;
return true;
}
if(charAt0==' '&&charAt1==' '&&charAt2=='-')
{
startElement=2;
return true;
}
if(::isdigit(charAt0)&&(lastChar=='-'||lastChar=='|'))
{
startElement=0;
return true;
}
if(charAt0==' '&&(charAt1=='E'||charAt1=='e')&&charAt2=='|')
{
startElement=2;
return true;
}
if(charAt0==' '&&(charAt1=='E'||charAt1=='e')&&charAt2==' '&&charAt3=='|')
{
startElement=3;
return true;
}
if(charAt0==' '&&charAt1==' '&&(charAt2=='E'||charAt2=='e')&&charAt3==' ')
{
startElement=4;
return true;
}
if((charAt0=='E'||charAt0=='e')&&charAt1==' '&&(charAt2=='|'||charAt2=='+')&&charAt3=='-')
{
startElement=3;
return true;
}
return false;
}