/***************************************************************************
 * powertab.h: implementation of PowerTab class
 *
 * This file is part of KTabEdit, a KDE tabulature editor
 *
 * copyright (C) 2003-2006 the KTabEdit development team <mrgwen@gmail.com>
 * copyright (C) 2002-2003 the KGuitar development team <mrgwen@gmail.com>
 ***************************************************************************/

/***************************************************************************
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * See the file COPYING for more information.
 ***************************************************************************/

#include "powertab.h"

#include <QDate>
#include <QtDebug>

#include "tablature/tabbeateffects.h"
#include "tablature/tabchord.h"
#include "tablature/tabduration.h"

#include "tablature/tabbend.h"
#include "tablature/tabdynamic.h"

#include "tablature/tabgracenotetransition.h"
#include "tablature/tabgracenote.h"

#include "tablature/tabharmonic.h"
#include "tablature/tabslide.h"
#include "tablature/tabtrill.h"
#include "tablature/tabnoteeffect.h"

#include "tablature/tabnote.h"

#include "tablature/songkey.h"
#include "tablature/timesignature.h"

#include "tablature/tabmixtablechanges.h"
#include "tablature/tabtimes.h"
#include "tablature/tabbarproperties.h"

#include "tablature/tabbar.h"

#include "tablature/tablyrics.h"
#include "tablature/tabproperties.h"

#include "tablature/tabsong.h"

#include "tablature/trackmidiproperties.h"
#include "tablature/trackproperties.h"

#include "tablature/tabtrack.h"

const uint PowerTab::nullTag = 0;
const uint PowerTab::newTagClass = 0xffff;
const uint PowerTab::tagClass = 0x8000;
const uint PowerTab::BigTagClass = 0x80000000;
const uint PowerTab::objectTag = 0x7fff;
const uint PowerTab::MaxMapCount = 0x3ffffffe;

PowerTab::PowerTab()
: version(0)
{
}

PowerTab::~PowerTab()
{
}

inline unsigned char PowerTab::readUChar(QFile& file) throw (const char*)
{
	int temp = 0;
	
	if ((temp = file.getch()) == -1)
		throw "[readUChar] Unable to read the file\n";
	
	return temp;
}

template <class T> inline const T PowerTab::readUCType(QFile& file) throw (const char*)
{
	int temp = 0;
	
	if ((temp = file.getch()) == -1)
		throw "[readUType] Unable to read the file\n";
	
	return static_cast<T>(temp);
}

inline unsigned int PowerTab::readUInt(QFile& file) throw (const char*)
{
	unsigned int temp = 0;
	
	if (file.readBlock(reinterpret_cast<char*>(&temp), 2) != 2)
		throw "[readUInt] Unable to read the file\n";
	
	return temp;
}

template <class T> inline const T PowerTab::readUIType(QFile& file) throw (const char*)
{
	return static_cast<T>(readUInt(file));
}

inline unsigned long PowerTab::readULong(QFile& file) throw (const char*)
{
	unsigned long temp = 0;
	
	if (file.readBlock(reinterpret_cast<char*>(&temp), 4) != 4)
		throw "[readULong] Unable to read the file\n";
	
	return temp;
}

inline unsigned long PowerTab::readMFCLength(QFile& file)
{
	unsigned long length = readUChar(file);
	if (length < 0xff)
		return length;
	
	length = readUInt(file);
	if (length < 0xffff)
		return length;
	
	length = readULong(file);
	
	return length;
}

inline QString PowerTab::readMFCString(QFile& file) throw (const char*)
{
	unsigned long length = readMFCLength(file);
	
	if (length) {
		QString tempString;
		char* temp = new char[length + 1];
		
		if (file.readBlock(temp, length) != length)
			 throw "[readMFCString] Unable to read the file\n";
		
		tempString = QString::fromLocal8Bit(temp, length);
		
		delete temp;
		
		return tempString;
	}
	
	return "";
}

int PowerTab::readHeaderItems(QFile& file, QString& name) throw (const char*)
{
	uint nbItems = 0;
	uint header = 0;
	
	name = "";
	
	nbItems = readUInt(file);
	
	if (nbItems == 0)
		return 0;
	
	header = readUInt(file);
	
	if (header == newTagClass) {
		QByteArray byteArray;
		QString section;
		int constValue = 0;
		int length = 0;
		
		constValue = readUInt(file);
		
		if (constValue != 1) {
			throw "[readHeaderItems] Unable to read the file\n";
		}
		
		length = readUInt(file);
		
		byteArray = file.readLine(length + 1);
		/*if (file.readLine(section, length + 1) == - 1) {
			throw "[readHeaderItems] Unable to read the file\n";
		}*/
		
		section = byteArray;
		
		name = section;
	}
	
	return nbItems;
}

inline void PowerTab::readItemNext(QFile& file) throw (const char*)
{
	int temp = readUInt(file);
	
	if (!(temp & 0x8000))
		throw "[readItemNext] Unable to read the file\n";
}

inline void PowerTab::callSection(QFile& file, int nbCall, TabSong* tabSong, void (PowerTab::*pf)(QFile&, TabSong*)) throw (const char*)
{
	for (int i = 0; i < nbCall; i++) {
		(this->*pf)(file, tabSong);
		
		if (i < nbCall - 1)
			readItemNext(file);
	}
}

inline void PowerTab::callSection(QFile& file, void (PowerTab::*pf)(QFile&)) throw (const char*)
{
	QString itemName;
	int itemCount = readHeaderItems(file, itemName);
	
	// CChordDiagram section
	//
	for (int i = 0; i < itemCount; i++) {
		(this->*pf)(file);
		
		if (i < itemCount - 1)
			readItemNext(file);
	}
}

void PowerTab::checkHeader(QFile& file) throw (const char*)
{
	const QString headerString("ptab");
	
	// Check if the header string is ptab
	//
	for (int i = 0; i < 4; i++) {
		if (headerString.ascii()[i] != file.getch())
			throw "[checkHeader] Unable to read the file\n";
	}
	
	version = readUInt(file);
	
	if (version < 1 || version > 4)
		throw "[checkHeader] Unable to read the file\n";
}

void PowerTab::readHeaderVersion1(QFile& file, TabSong* tabSong)
{
	bool live = false;
	int year = 0;
	QString comments, temp;
	release1::releaseType1 release;
	release1::authorType1 author;
	
	tabSong->setTitle(readMFCString(file));
	qDebug() << "title = " << tabSong->title() << "\n";
	
	tabSong->setArtist(readMFCString(file));
	qDebug() << "artist = " << tabSong->artist() << "\n";
	
	release = readUCType<release1::releaseType1>(file);
	qDebug() << "releaseOn = " << release << "\n";
	
	comments = "Release type is ";
	switch (release) {
		case release1::Single:
			comments+="single.\n";
			break;
		case release1::Ep:
			comments+="ep.\n";
			break;
		case release1::Lp:
			comments+="lp.\n";
			break;
		case release1::DoubleLp:
			comments+="double lp.\n";
			break;
		case release1::TripleLp:
			comments+="triple lp.\n";
			break;
		case release1::Boxset:
			comments+="boxset.\n";
			break;
		case release1::BootLeg:
			comments+="bootleg.\n";
			break;
		case release1::Demo:
			comments+="demo.\n";
			break;
		case release1::Soundtrack:
			comments+="sountrack.\n";
			break;
		case release1::Video:
			comments+="video.\n";
			break;
		case release1::None:
			comments+="no type.\n";
			break;
	}
	
	tabSong->setSubTitle(readMFCString(file));
	qDebug() << "release title = " << tabSong->subTitle() << "\n";
	
	if (live = readUChar(file))
		comments+="This was a live.\n";
	
	qDebug() << "live = " << live << "\n";
	
	tabSong->setAuthor(readMFCString(file));
	qDebug() << "composer = " << tabSong->author() << "\n";
	
	comments+="The lyricist name is " + readMFCString(file) + ".\n";
	qDebug() << "lyricist = " << comments << "\n";
	
	comments+="The arranger name is " + readMFCString(file) + ".\n";
	qDebug() << "arranger = " << comments << "\n";
	
	tabSong->setTranscriber(readMFCString(file));
	qDebug() << "guitar score transcriber = " << tabSong->transcriber() << "\n";
	
	year = readUInt(file);
	qDebug() << "year = " << year << "\n";
	
	comments+="Year is " + temp.setNum(year) + ".\n";
	
	author = readUCType<release1::authorType1>(file);
	qDebug() << "author type = " << author << "\n";
	
	if (author == release1::Traditional)
		comments+="Author is traditionnal.\n";
	
	tabSong->setCopyright(readMFCString(file));
	qDebug() << "copyright = " << tabSong->copyright() << "\n";
	
	comments+="The lyrics :\n" + readMFCString(file) + ".\n";
	qDebug() << "lyrics = " << comments << "\n";
	
	tabSong->setInstructions(readMFCString(file));
	qDebug() << "score notes = " << tabSong->instructions() << "\n";
	
	tabSong->setComments(comments);
}

void PowerTab::readHeaderVersion15(QFile& file, TabSong* tabSong)
{
	bool live = false;
	int year = 0;
	release1::releaseType1 release;
	release1::authorType1 author;
	QString comments, temp;
	
	tabSong->setTitle(readMFCString(file));
	qDebug() << "title = " << tabSong->title() << "\n";
	
	tabSong->setArtist(readMFCString(file));
	qDebug() << "artist = " << tabSong->artist() << "\n";
	
	release = readUCType<release1::releaseType1>(file);
	qDebug() << "releaseOn = " << release << "\n";
	
	comments = "Release type is ";
	switch (release) {
	case release1::Single:
		comments+="single.\n";
		break;
	case release1::Ep:
		comments+="ep.\n";
		break;
	case release1::Lp:
		comments+="lp.\n";
		break;
	case release1::DoubleLp:
		comments+="double lp.\n";
		break;
	case release1::TripleLp:
		comments+="triple lp.\n";
		break;
	case release1::Boxset:
		comments+="boxset.\n";
		break;
	case release1::BootLeg:
		comments+="bootleg.\n";
		break;
	case release1::Demo:
		comments+="demo.\n";
		break;
	case release1::Soundtrack:
		comments+="sountrack.\n";
		break;
	case release1::Video:
		comments+="video.\n";
		break;
	case release1::None:
		comments+="no type.\n";
		break;
	}
	
	tabSong->setSubTitle(readMFCString(file));
	qDebug() << "release title = " << tabSong->subTitle() << "\n";
	
	if (live = readUChar(file))
		comments+="This was a live.\n";
	
	qDebug() << "live = " << live << "\n";
	
	tabSong->setAuthor(readMFCString(file));
	qDebug() << "composer = " << tabSong->author() << "\n";
	
	comments+="The lyricist name is " + readMFCString(file) + ".\n";
	qDebug() << "lyricist = " << comments << "\n";
	
	comments+="The arranger name is " + readMFCString(file) + ".\n";
	qDebug() << "arranger = " << comments << "\n";
	
	year = readUInt(file);
	qDebug() << "year = " << year << "\n";
	
	comments+="Year is " + temp.setNum(year) + ".\n";
	
	author = readUCType<release1::authorType1>(file);
	qDebug() << "author type = " << author << "\n";
	
	if (author == release1::Traditional)
		comments+="Author is traditionnal.\n";
	    
	tabSong->setCopyright(readMFCString(file));
	qDebug() << "copyright = " << tabSong->copyright() << "\n";
	
	comments+="The lyrics :\n" + readMFCString(file) + ".\n";
	qDebug() << "lyrics = " << comments << "\n";
	
	tabSong->setComments(comments);
}

void PowerTab::readHeaderVersion17(QFile& file, TabSong* tabSong)
{
	release17::classificationSong classe;
	release1::authorType1 author;
	QString comments, temp;
	
	classe = readUCType<release17::classificationSong>(file);
	qDebug() << "classification " << classe << "\n";
	
	switch(classe) {
	case release17::song: {
		release17::contentType content;
		release17::releaseType release;
		
		content = readUCType<release17::contentType>(file);
		qDebug() << "content = " << content << "\n";
		
		comments = "This song contents ";
		switch (content) {
		case release17::None:
			comments+="no tracks.\n";
			break;
		case release17::Guitar:
			comments+="a guitar track.\n";
			break;
		case release17::Bass:
			comments+="a bass track.\n";
			break;
		case release17::Percussion:
			comments+="a percussion track.\n";
			break;
		case release17::All:
			comments+="a guitar, bass, and percussion track.\n";
			break;
		}
		
		tabSong->setTitle(readMFCString(file));
		qDebug() << "title = " << tabSong->title() << "\n";
		
		tabSong->setArtist(readMFCString(file));
		qDebug() << "artist = " << tabSong->artist() << "\n";
		
		release = readUCType<release17::releaseType>(file);
		qDebug() << "release type = " << release << "\n";
		
		comments+= "Release type is ";
		switch (release) {
		case release17::publicAudio: {
			int year = 0;
			bool live = false;
			release17::audioRelease audio;
			
			comments+="public audio.\n";
			
			audio = readUCType<release17::audioRelease>(file);
			qDebug() << "audio type = " << audio << "\n";
			
			comments+="The audio type is ";
			
			switch(audio) {
			case release17::Single:
				comments+="a single.\n";
				break;
			case release17::Ep:
				comments+="an EP.\n";
				break;
			case release17::Album:
				comments+="an album.\n";
				break;
			case release17::DoubleAlbum:
				comments+="a double album.\n";
				break;
			case release17::TripleAlbum:
				comments+="a triple album.\n";
				break;
			case release17::Boxset:
				comments+="a boxset.\n";
				break;
			}
			
			tabSong->setTitle(readMFCString(file));
			qDebug() << "album title = " << tabSong->title() << "\n";
			
			year = readUInt(file);
			qDebug() << "audio year = " << year << "\n";
			
			comments+="Year is " + temp.setNum(year) + ".\n";
			
			if (live = readUChar(file))
				comments+="This was a live.\n";
			
			qDebug() << "is live recording = " << live << "\n";
		} break;
		case release17::publicVideo: {
			bool live = false;
			
			comments+="public video.\n";
			
			tabSong->setTitle(readMFCString(file));
			qDebug() << "video title = " << tabSong->title() << "\n";
			
			if (live = readUChar(file))
				comments+="This was a live.\n";
			
			qDebug() << "is live recording = " << live << "\n";
		} break;
		case release17::bootleg: {
			bool live = false;
			int day = 0, month = 0, year = 0;
			QDate date;
			
			comments+="bootleg.\n";
			
			tabSong->setTitle(readMFCString(file));
			qDebug() << "bootleg title = " << tabSong->title() << "\n";
			
			if (live = readUChar(file))
				comments+="This was a live.\n";
			
			qDebug() << "is live recording = " << live << "\n";
			
			day = readUInt(file);
			month = readUInt(file);
			year = readUInt(file);
			
			date.setYMD(year, month, day);
			
			comments+="Date of recording " + date.toString("dddd MMMM d yy") + ".\n";
			
			qDebug() << "date = " << date.toString("dddd MMMM d yy") << "\n";
		} break;
		}
		
		author = readUCType<release1::authorType1>(file);
		qDebug() << "is original author unknown = " << author << "\n";
		
		if (author == release1::AuthorUnknown) {
			tabSong->setAuthor(readMFCString(file));
			qDebug() << "composer = " << tabSong->author() << "\n";
			
			comments+="The lyricist name is " + readMFCString(file) + ".\n";
			qDebug() << "lyricist = " << comments << "\n";
		}
		
		comments+="The arrenger is " + readMFCString(file) + ".\n";
		qDebug() << "arrenged by = " << comments << "\n";
		
		tabSong->setTranscriber(readMFCString(file));
		qDebug() << "guitar score transcriber = " << tabSong->transcriber() << "\n";
		
		comments+="The bass transcriber is " + readMFCString(file) + ".\n";
		qDebug() << "bass transcribed by = " << comments << "\n";
		
		tabSong->setCopyright(readMFCString(file));
		qDebug() << "copyright = " << tabSong->copyright() << "\n";
		
		comments+="The lyrics :\n" + readMFCString(file) + ".\n";
		qDebug() << "lyrics = " << comments << "\n";
		
		tabSong->setInstructions("Guitar : \n" + readMFCString(file) + ".\n\n");
		qDebug() << "guitar notes = " << tabSong->instructions() << "\n";
		
		tabSong->setInstructions(tabSong->instructions() + "Bass : \n" + readMFCString(file) + ".\n\n");
		qDebug() << "bass notes = " << tabSong->instructions() << "\n";
	} break;
	case release17::lesson: {
		release17::musicStyle style;
		release17::lessonLevel level;
		
		comments = "This is a lesson.\n";
		
		tabSong->setTitle(readMFCString(file));
		qDebug() << "title = " << tabSong->title() << "\n";
		
		tabSong->setArtist(readMFCString(file));
		qDebug() << "artist = " << tabSong->artist() << "\n";
		
		style = readUIType<release17::musicStyle>(file);
		qDebug() << "lesson style = " << style << "\n";
		
		comments+="The style of the lesson is ";
		switch(style) {
		case release17::Alternative:
			comments+="alternative.\n";
			break;
		case release17::BlueGrass:
			comments+="blue grass.\n";
			break;
		case release17::Blues:
			comments+="blues.\n";
			break;
		case release17::Country:
			comments+="country.\n";
			break;
		case release17::FingerPick:
			comments+="finger picking.\n";
			break;
		case release17::Flamenco:
			comments+="flamenco.\n";
			break;
		case release17::Folk:
			comments+="folk.\n";
			break;
		case release17::Funk:
			comments+="funk.\n";
			break;
		case release17::Fusion: 
			comments+="fusion.\n";
			break;
		case release17::General:
			comments+="general.\n";
			break;
		case release17::Jazz:
			comments+="jazz.\n";
			break;
		case release17::Metal:
			comments+="metal.\n";
			break;
		case release17::Other:
			comments+="other.\n";
			break;
		case release17::Pop:
			comments+="pop.\n";
			break;
		case release17::Progressive:
			comments+="progressive.\n";
			break;
		case release17::Punk:
			comments+="punk.\n";
			break;
		case release17::Reggae:
			comments+="reggae.\n";
			break;
		case release17::Rock:
			comments+="rock.\n";
			break;
		case release17::Swing:
			comments+="swing.\n";
			break;
		}
		
		level = readUCType<release17::lessonLevel>(file);
		qDebug() << "lesson level = " << level << "\n";
		
		comments+="Lesson level ";
		switch(level) {
		case release17::Beginner:
			comments+="beginner.\n";
			break;
		case release17::Intermediate:
			comments+="intermediate.\n";
			break;
		case release17::Advanced:
			comments+="advanced.\n";
			break;
		}
		
		tabSong->setAuthor(readMFCString(file));
		qDebug() << "lesson author = " << tabSong->author() << "\n";
		
		tabSong->setInstructions("Guitar : " + readMFCString(file) + ".\n");
		qDebug() << "guitar notes = " << tabSong->instructions() << "\n";
		
		tabSong->setCopyright(readMFCString(file));
		qDebug() << "copyright = " << tabSong->copyright() << "\n";
	} break;
	}
	
	tabSong->setComments(comments);
}

void PowerTab::readDataInstruments(QFile& file, TabSong* tabSong, uint trackNb) throw (const char*)
{
	int itemCount = 0;
	QString itemName;
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CGuitar section
	//
	callSection(file, itemCount, tabSong, &PowerTab::readTrackInfo);
/*	for (int j = 0; j < itemCount; j++) {
		readTrackInfo(file, tabSong);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	callSection(file, &PowerTab::readChord);
	
/*	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	qDebug() << "item name " << itemName << "\n";
	
	// CChordDiagram section
	//
	for (int j = 0; j < itemCount; j++) {
		readChord(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	callSection(file, &PowerTab::readFloattingText);
	
/*	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CFloatingText section
	//
	for (int j = 0; j < itemCount; j++) {
		readFloattingText(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	callSection(file, &PowerTab::readGuitarIn);
/*	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	qDebug() << "item name " << itemName << "\n";
	
	// CGuitarIn section
	//
	for (int j = 0; j < itemCount; j++) {
		readGuitarIn(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	callSection(file, &PowerTab::readTempoMarker);
/*	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	qDebug() << "item name " << itemName << "\n";
	
	// CTempoMarker
	//
	for (int j = 0; j < itemCount; j++) {
		readTempoMarker(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	callSection(file, &PowerTab::readDynamic);
/*	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	qDebug() << "item name " << itemName << "\n";
	
	// CDynamic section
	//
	for (int j = 0; j < itemCount; j++) {
		readDynamic(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	callSection(file, &PowerTab::readSectionSymbol);
/*	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	qDebug() << "item name " << itemName << "\n";
	
	// CSectionSymbol section
	//
	for (int j = 0; j < itemCount; j++) {
		readSectionSymbol(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}*/
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	qDebug() << "item name " << itemName << "\n";
	
	TabSong::iterator it(tabSong->begin());
	int i = 0;
	
	while (i < trackNb && it != tabSong->end()) {
		++it;
		i++;
	}
	
	if (it == tabSong->end()) {
		qDebug() << "[PowerTab::readDataInstruments] it == tabSong.end()\n";
		throw std::exception();
	}

	// CSection section
	//
	for (int j = 0; j < itemCount; j++) {
		readSection15(file, **it);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
}

void PowerTab::readTrackInfo(QFile& file, TabSong* tabSong) throw (const char*)
{
	uchar trackNumber = 0;
	TabTrack* tabTrack = new TabTrack();
	
	// Track initialisation
	//
	tabTrack->setMode(FretTab);
	tabTrack->setNbFrets(21);
	
	// Track info
	//
	trackNumber = readUChar(file);
	qDebug() << "number = " << trackNumber << "\n";
	
	tabTrack->setName(readMFCString(file));
	qDebug() << "description = " << tabTrack->name() << "\n";
	
	tabTrack->setPatch(readUChar(file));
	qDebug() << "preset = " << tabTrack->patch() << "\n";
	
	tabTrack->setVolume(readUChar(file));
	qDebug() << "initial volume = " << tabTrack->volume() << "\n";
	
	tabTrack->setBalance(readUChar(file));
	qDebug() << "pan = " << tabTrack->balance() << "\n";
	
	tabTrack->setReverb(readUChar(file));
	qDebug() << "reverb = " << tabTrack->reverb() << "\n";
	
	tabTrack->setChorus(readUChar(file));
	qDebug() << "chorus = " << tabTrack->chorus() << "\n";
	
	tabTrack->setTremolo(readUChar(file));
	qDebug() << "tremolo = " << tabTrack->tremolo() << "\n";
	
	tabTrack->setPhaser(readUChar(file));
	qDebug() << "phaser = " << tabTrack->phaser() << "\n";
	
	tabTrack->setCapo(readUChar(file));
	qDebug() << "capo = " << tabTrack->capo() << "\n";
	
	// Tuning
	//
	qDebug() << "tuning name = " << readMFCString(file) << "\n";
	qDebug() << "bit 7 = Music notation offset sign, bits 6 to 1 = Music notation offset value, bit 0 = display sharps or flats = " << readUChar(file) << "\n";
	
	tabTrack->setNbStrings(readUChar(file));
	qDebug() << "string count = " << tabTrack->nbStrings() << "\n";
	
	for (uint i = 0; i < tabTrack->nbStrings(); i++) {
		tabTrack->setTune(tabTrack->nbStrings()- i - 1, readUChar(file));
		qDebug() << "note = " << tabTrack->tune(i) << "\n";
	}
	
	tabSong->push_front(tabTrack);
}

void PowerTab::readChord(QFile& file)
{
	uchar stringCount = 0;
	int chordModification = 0;
	unsigned long chordKey = 0;
	
	// Chord key and bass note (hiword = tonic, loword = bass note; bits 5-6 = variation, bottom 4 bits = key)
	//
	chordKey = readULong(file);
	qDebug() << "Chord key and bass note (hiword = tonic, loword = bass note; bits 5-6 = variation, bottom 4 bits = key) = " << chordKey << "\n";
	
	// Core formula + flags (see formula and formulaFlags enums for values)
	//
	qDebug() << "Core formula + flags (see formula and formulaFlags enums for values) = " << readUChar(file) << "\n";
	
	// Stores the formula modifications (see formulaModifications enum for values)
	//
	chordModification = readULong(file);
	qDebug() << "Stores the formula modifications (see formulaModifications enum for values) = " << chordModification << "\n";
	
	// Stores the type and fret position data (top 3 bits = type, bottom 5 bits = position)
	//
	qDebug() << "Stores the type and fret position data (top 3 bits = type, bottom 5 bits = position) = " << readUChar(file) << "\n";
	
	// Fret represented at the top of the chord diagram
	//
	qDebug() << "Fret represented at the top of the chord diagram = " << readUChar(file) << "\n";
	
	stringCount = readUChar(file);
	
	for (uint j = 0; j < stringCount; j++) {
		// List of fret number offsets
		//
		qDebug() << "List of fret number offsets = " << readUChar(file) << "\n";
	}
}

void PowerTab::readFontSetting(QFile& file)
{
	int pointSize = 0;
	int weight = 0;
	int color = 0;
	
	qDebug() << "font name = " << readMFCString(file) << "\n";
	
	pointSize = readULong(file);
	qDebug() << "point size = " << pointSize << "\n";
	
	weight = readULong(file);
	qDebug() << "weight = " << weight << "\n";
	
	qDebug() << "italic = " << readUChar(file) << "\n";
	qDebug() << "underline = " << readUChar(file) << "\n";
	qDebug() << "strikeout = " << readUChar(file) << "\n";
	
	color = readULong(file);
	qDebug() << "color = " << color << "\n";
}

void PowerTab::readFloattingText(QFile& file)
{
	unsigned long left = 0, top = 0, right = 0, bottom = 0;
	
	// Floating text
	//
	qDebug() << "floating text = " << readMFCString(file) << "\n";
	
	// Read mfc rect
	//
	left   = readULong(file);
	top    = readULong(file);
	right  = readULong(file);
	bottom = readULong(file);
	
	qDebug() << "mfc rect = " << left << " " << top << " " << right << " " << bottom << "\n";
	
	// Flags representing alignment and borders (see flags below)
	//
	qDebug() << "Flags = " << readUChar(file) << "\n";
	
	// Font settings
	//
	readFontSetting(file);
}

void PowerTab::readGuitarIn(QFile& file)
{
	int system = 0;
	int data = 0;
	
	// Zero-based index of the system where the guitar in is anchored
	//
	system = readUInt(file);
	qDebug() << "Zero-based index of the system where the guitar in is anchored = " << system << "\n";
	
	// Zero-based index of the staff within the system where the guitar in is anchored
	//
	qDebug() << "Zero-based index of the staff within the system where the guitar in is anchored = " << readUChar(file) << "\n";
	
	// Zero-based index of the position within the system where the guitar in is anchored
	//
	qDebug() << "Zero-based index of the position within the system where the guitar in is anchored = " << readUChar(file) << "\n";
	
	// Bit map representing the guitar number of the active guitars (bit 1 = guitar 0, bit 2 = guitar 1, etc.)
	// High byte = staff guitars, low byte = rhythm slash guitars
	//
	data = readUInt(file);
	qDebug() << "Bit map representing the guitar number of the active guitars (bit 1 = guitar 0, bit 2 = guitar 1, etc.) = " << data << "\n";
}

void PowerTab::readTempoMarker(QFile& file)
{
	int system = 0;
	int data = 0;
	
	file.readBlock((char*)&system, 2);
	qDebug() << "Zero-based index of the system the symbol is anchored : " << system << "\n";
	
	qDebug() << "Zero-based index of the position within the system where the symbol is anchored = " << file.getch() << "\n";
	
	file.readBlock((char*)&data, 4);
	qDebug() << "Data used by the symbol (different for each symbol) : " << data << "\n";
	
	qDebug() << "description : " << readMFCString(file) << "\n";
}

void PowerTab::readDynamic(QFile& file)
{
	int system = 0;
	int data = 0;
	
	file.readBlock((char*)&system, 2);
	qDebug() << "Zero-based index of the system where the dynamic is anchored : " << system << "\n";
	
	qDebug() << "Zero-based index of the staff within the system where the dynamic is anchored : " << file.getch() << "\n";
	
	qDebug() << "Zero-based index of the position within the system where the dynamic is anchored : " << file.getch() << "\n";
	
	file.readBlock((char*)&data, 2);
	qDebug() << "Volume level (see volumeLevels enum for values; top byte = staff volume, bottom byte = dynamic volume) : " << data << "\n";
}

void PowerTab::readDirection(QFile& file)
{
	// Direction
	//
	qDebug() << "Zero-based index of the position within the system where the direction is anchored : " << file.getch() << "\n";
	
	int symboleCount = 0;
	symboleCount = file.getch();
	
	qDebug() << "symbole count : " << symboleCount << "\n";
	
	for (int i = 0; i < symboleCount; i++) {
		int word = 0;
		
		file.readBlock((char*)&word, 2);
		qDebug() << "Array of direction symbols (symbol: top byte = symbol type, next 2 bits = active symbol, next 6 bits = repeat number) : " << word << "\n";
	}
}

void PowerTab::readNote(QFile& file, TabTime* time) throw (const char*)
{
	uchar position = 0;
	int simpleData = 0;
	unsigned long complexSymbol = 0;
	TabNote* note;
	
	position = readUChar(file);
	note->setFret(position & 0x1f);
	qDebug() << "Top 3 bits = string, bottom 5 bits = fret number : " << position << "\n";
	
	file.readBlock((char*)&simpleData, 2);
	qDebug() << "Contains simple symbol flags : " << simpleData << "\n";
	
	int symbolCount = 0;
	symbolCount = file.getch();
	
	qDebug() << "symbol count " << symbolCount << "\n";
	
	for (int i = 0; i < symbolCount; i++) {
		file.readBlock((char*)&complexSymbol, 4);
		qDebug() << "Contains simple symbol flags : " << complexSymbol << "\n";
	}
	
	note = new TabNote(((position & 0xe0) >> 5) + 1);
	time->setString((position & 0xe0) >> 5, note);
}

void PowerTab::readPosition(QFile& file, TabBar* bar, uchar numberOfTime) throw (const char*)
{
	int itemCount = 0;
	QString itemName;
	TabTime* time = new TabTime(numberOfTime);
	
	// Position
	//
	unsigned int beaming = 0;
	unsigned long positionData = 0;
	
	qDebug() << "Zero-based index of the position within the system where the position is anchored : " << readUChar(file) << "\n";
	
	beaming = readUInt(file);
	qDebug() << "Beaming and irregular grouping timing data : " << beaming << "\n";
	
	positionData = readULong(file);
	qDebug() << "Duration and simple symbol flags : " << positionData << "\n";
	
	int complexCount = 0;
	complexCount = readUChar(file);
	qDebug() << "complexCount = "  << complexCount << "\n";
	
	for (int i = 0; i < complexCount; i++) {
		int symbolArray = 0;
		
		symbolArray = readULong(file);
		qDebug() << "Symbole array : " << symbolArray << "\n";
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CLineData
	//
	for (int j = 0; j < itemCount; j++) {
		readNote(file, time);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	if (itemCount == 0)
		time->setRest(true);
	
	// Set the duration
	//
	switch ((positionData & 0xff000000) >> 24) {
	case 1:
		time->setDuration(Whole);
		break;
	case 2:
		time->setDuration(Half);
		break;
	case 4:
		time->setDuration(Quarter);
		break;
	case 8:
		time->setDuration(Eighth);
		break;
	case 16:
		time->setDuration(Sixteenth);
		break;
	}
	
	// Check if time is dotted
	//
	if (positionData & 0x01)
		time->setDotted(true);
	
	bar->insertTime(time);
}

void PowerTab::readSectionSymbol(QFile& file)
{
	int system = 0;
	int data = 0;
	
	file.readBlock((char*)&system, 2);
	qDebug() << "Zero-based index of the system the symbol is anchored : " << system << "\n";
	
	qDebug() << "Zero-based index of the position within the system where the symbol is anchored = " << file.getch() << "\n";
	
	file.readBlock((char*)&data, 4);
	qDebug() << "Data used by the symbol (different for each symbol) : " << data << "\n";
}

void PowerTab::readChordText(QFile& file)
{
	// Chordtext
	//
	qDebug() << "Zero-based index of the position within the system where the chord text is anchored : " << file.getch() << "\n";
	
	int key = 0;
	file.readBlock((char*)&key, 2);
	qDebug() << "Chord key and bass note (hiword = tonic, loword = bass note; bits 5-6 = variation, bottom 4 bits = key) : " << key << "\n";
	
	qDebug() << "Core formula + flags (see formula and formulaFlags enums for values) ; " << file.getch() << "\n";
	
	int formulaModification = 0;
	file.readBlock((char*)&formulaModification, 2);
	qDebug() << "Stores the formula modifications (see formulaModifications enum for values) ; " << formulaModification << "\n";
	
	qDebug() << "Stores the type and fret position data (top 3 bits = type, bottom 5 bits = position) : " << file.getch() << "\n";
}

void PowerTab::readRhythmSlash(QFile& file)
{
	int rhythmData = 0;
	
	qDebug() << "Zero-based index of the position within the system where the rhythm slash is anchored : " << file.getch() << "\n";
	qDebug() << "Beaming and triplet data (top 3 bits = triplet flags, bottom 5 bits = beaming flags) : " << file.getch() << "\n";
	
	file.readBlock((char*)&rhythmData, 4);
	qDebug() << " Top byte = single note data, next 3 bits = duration type, remaining bits are flags: " << rhythmData << "\n";
}

void PowerTab::readStaff(QFile& file, TabTrack& tabTrack, uchar numberOfBar) throw (const char*)
{
	TabBar* bar = new TabBar(numberOfBar);
	int itemCount = 0;
	QString itemName;
	
	// Staff
	//
	qDebug() << "Top 4 bits = clef type, bottom 4 bits = tablature type : " << file.getch() << "\n";
	qDebug() << "Amount of space alloted from the top line of the standard notation staff : " << file.getch() << "\n";
	qDebug() << "Amount of space alloted from the last line of the standard notation staff : " << file.getch() << "\n";
	qDebug() << "Amount of space alloted for symbols located between the standard notation and tablature staff : " << file.getch() << "\n";
	qDebug() << "Amount of space alloted from the last line of the tablature staff : " << file.getch() << "\n";
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CPosition section
	//
	for (int j = 0; j < itemCount; j++) {
		readPosition(file, bar, j);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CPosition section
	//
	for (int j = 0; j < itemCount; j++) {
		readPosition(file, bar, j);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	tabTrack.addBar(bar);
}

void PowerTab::readKeySignature(QFile& file)
{
	qDebug() << "Stores all data required by the key signature (see the flags enum for the meaning of the individual bits) : " << file.getch() << "\n";
}

void PowerTab::readTimeSignature(QFile& file)
{
	unsigned long data = 0;
	
	file.readBlock((char*)&data, 4);
	qDebug() << "Stores the meter, beaming pattern and any flags (see flags enum for bit breakdown) : " << data << "\n";
	qDebug() << "Number of pulses in a measure : " << file.getch() << "\n";
}

void PowerTab::readRehearsalSign(QFile& file)
{
	qDebug() << "The letter used to uniquely identify the rehearsal sign (i.e. A, B, F, etc. - must be a capital letter) : " << file.getch() << "\n";
	
	qDebug() << "A description that indicates the passage the rehearsal sign is marking (i.e. Chorus, Intro, etc.) : " << readMFCString(file) << "\n";
}

void PowerTab::readBarLine(QFile& file)
{
	qDebug() << "Zero-based index of the position within the system where the barline is anchored : " << file.getch() << "\n";
	qDebug() << "Top 3 bits = type, bottom 5 = repeat number : " << file.getch() << "\n";
	
	readKeySignature(file);
	readTimeSignature(file);
	readRehearsalSign(file);
}

void PowerTab::readSection15(QFile& file, TabTrack& tabTrack) throw (const char*)
{
	int left = 0, top = 0, right = 0, bottom = 0;
	int itemCount = 0;
	QString itemName;
	
	// Read mfc rect
	//
	file.readBlock((char*)&left, 4);
	file.readBlock((char*)&top, 4);
	file.readBlock((char*)&right, 4);
	file.readBlock((char*)&bottom, 4);
	
	qDebug() << "mfc rect = " << left << " " << top << " " << right << " " << bottom << "\n";
	
	qDebug() << "end bar " << file.getch() << "\n";
	
	qDebug() << "Bounding rect for the system : " << file.getch() << "\n";
	
	qDebug() << "Spacing between each position in the system : " << file.getch() << "\n";
	
	qDebug() << "Spacing above the rhythm slashes : " << file.getch() << "\n";
	
	qDebug() << "Spacing below the rhythm slashes : " << file.getch() << "\n";
	
	// BarLine
	//
	qDebug() << "Zero-based index of the position within the system where the barline is anchored : " << file.getch() << "\n";
	
	qDebug() << "Top 3 bits = type, bottom 5 = repeat number : " << file.getch() << "\n";
	
	// KeySignature
	//
	qDebug() << "Stores all data required by the key signature (see the flags enum for the meaning of the individual bits) : " << file.getch() << "\n";
	
	// TimeSignature
	//
	int data = 0;
	
	file.readBlock((char*)&data, 4);
	qDebug() << "Stores the meter, beaming pattern and any flags (see flags enum for bit breakdown) : " << data << "\n";
	
	qDebug() << "Number of pulses in a measure : " << file.getch() << "\n";
	
	// ReHearsalSign
	//
	readRehearsalSign(file);
	
	// Direction array
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CDirection section
	//
	for (int j = 0; j < itemCount; j++) {
		readDirection(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// ChordText array
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CChordText section
	//
	for (int j = 0; j < itemCount; j++) {
		readChordText(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// Rythmslash
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CRhythmSlash section
	//
	for (int j = 0; j < itemCount; j++) {
		readRhythmSlash(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// Staff
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CStaff section
	//
	for (int j = 0; j < itemCount; j++) {
		readStaff(file, tabTrack, j);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// MusicBar
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CMusicBar section
	//
	for (int j = 0; j < itemCount; j++) {
		readBarLine(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
}

void PowerTab::readOldTimeSignature(QFile& file)
{
	uint system = 0;
	uchar position = 0;
	unsigned long data = 0;
	
	system = readUInt(file);
	position = readUChar(file);
	data = readULong(file);
}

void PowerTab::readDynamic1(QFile& file)
{
	uint system = 0;
	uchar staff = 0;
	uchar position = 0;
	uchar staffVolume = 0;
	
	system = readUInt(file);
	staff  = readUChar(file);
	position = readUChar(file);
	staffVolume = readUChar(file);
}

void PowerTab::readOldRehearsalSign(QFile& file)
{
	uint system = 0;
	uchar position = 0;
	unsigned long data = 0;
	uchar letter = 0;
	QString description;
	
	system = readUInt(file);
	position = readUChar(file);
	data = readULong(file);
	letter = readUChar(file);
	description = readMFCString(file);
}

void PowerTab::readSection1(QFile& file, TabTrack& tabTrack)
{
	int left = 0, top = 0, right = 0, bottom = 0;
	int itemCount = 0;
	QString itemName;
	
	// Read mfc rect
	//
	left = readULong(file);
	top = readULong(file);
	right = readULong(file);
	bottom = readULong(file);
	
	qDebug() << "mfc rect = " << left << " " << top << " " << right << " " << bottom << "\n";
	
	qDebug() << "key " << readUChar(file) << "\n";
	
	qDebug() << "end bar " << file.getch() << "\n";
	
	qDebug() << "Bounding rect for the system : " << file.getch() << "\n";
	
	qDebug() << "Spacing between each position in the system : " << file.getch() << "\n";
	
	qDebug() << "Spacing above the rhythm slashes : " << file.getch() << "\n";
	
	qDebug() << "Spacing below the rhythm slashes : " << file.getch() << "\n";
	
	// Direction array
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CDirection section
	//
	for (int j = 0; j < itemCount; j++) {
		readDirection(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// ChordText array
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CChordText section
	//
	for (int j = 0; j < itemCount; j++) {
		readChordText(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// Rythmslash
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CRhythmSlash section
	//
	for (int j = 0; j < itemCount; j++) {
		readRhythmSlash(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// Staff
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CStaff section
	//
	for (int j = 0; j < itemCount; j++) {
		readStaff(file, tabTrack, j);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	// MusicBar
	//
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "item name " << itemName << "\n";
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CMusicBar section
	//
	for (int j = 0; j < itemCount; j++) {
		readBarLine(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
}

void PowerTab::readFormatVersion1(QFile& file, TabSong* tabSong, uint trackNb)
{
	int itemCount = 0;
	QString itemName;
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CGuitar section
	//
	for (int j = 0; j < itemCount; j++) {
		readTrackInfo(file, tabSong);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CChordDiagram section
	//
	for (int j = 0; j < itemCount; j++) {
		readChord(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CFloatingText section
	//
	for (int j = 0; j < itemCount; j++) {
		readFloattingText(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CGuitarIn section
	//
	for (int j = 0; j < itemCount; j++) {
		readGuitarIn(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CTempoMarker section
	//
	for (int j = 0; j < itemCount; j++) {
		readTempoMarker(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CTimeSignature
	//
	for (int j = 0; j < itemCount; j++) {
		readOldTimeSignature(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CDynamic
	//
	for (int j = 0; j < itemCount; j++) {
		readDynamic1(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CSectionSymbol section
	//
	for (int j = 0; j < itemCount; j++) {
		readSectionSymbol(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	// CRehearsalSign section
	//
	for (int j = 0; j < itemCount; j++) {
		readOldRehearsalSign(file);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
	
	itemCount = readHeaderItems(file, itemName);
	
	qDebug() << "nbItems " << itemCount << "\n";
	
	TabSong::iterator it(tabSong->begin());
	int i = 0;
	
	while (i < trackNb && it != tabSong->end()) {
		++it;
		i++;
	}
	
	if (it == tabSong->end()) {
		qDebug() << "[PowerTab::readFormatVersion1] it == tabSong.end()\n";
		throw std::exception();
	}

	// CSection section
	//
	for (int j = 0; j < itemCount; j++) {
		readSection1(file, **it);
		
		if (j < itemCount - 1)
			readItemNext(file);
	}
}

bool PowerTab::loadFile(const QString &name) throw (const char*)
{
	// Open file
	//
	QFile file(name);
	TabSong* tabSong = new TabSong();
	
	if (!file.open(IO_ReadOnly))
		throw "[loadFile] Unable to open the file\n";
	
	checkHeader(file);
	
	switch (version) {
	case 1:
	case 2: {
		unsigned long lineSpace = 0;
		
		qDebug() << "Version 1.00 or 1.2\n";
		
		readHeaderVersion1(file, tabSong);
		
		lineSpace = readULong(file);
		qDebug() << "line spaces = " << lineSpace << "\n";
		
		// Fonts info
		//
		for (int i = 0; i < 3; i++) {
			readFontSetting(file);
		}
		
		readFormatVersion1(file, tabSong, 0);
		
		readFormatVersion1(file, tabSong, 1);
		
		// Fade in Fade out
		//
	} break;
	case 3:
		qDebug() << "Version 1.5\n";
		
		readHeaderVersion15(file, tabSong);
		
		// Guitar
		//
		readDataInstruments(file, tabSong, 0);
		
		// Bass
		//
		readDataInstruments(file, tabSong, 1);
		break;
	case 4:
		qDebug() << "Version 1.7\n";
		
		readHeaderVersion17(file, tabSong);
		
		// Guitar
		//
		readDataInstruments(file, tabSong, 0);
		
		// Bass
		//
		readDataInstruments(file, tabSong, 1);
		break;
	};
	
	setTabSong(tabSong);
	
	return true;
}

bool PowerTab::saveFile(const QString&, const TabSong&)
{
	return false;
}
