package org.herac.tuxguitar.gui.tools.custom.converter;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import org.apache.log4j.Logger;
import org.herac.tuxguitar.gui.editors.chord.ChordSelector;
import org.herac.tuxguitar.io.base.TGFileFormatException;
import org.herac.tuxguitar.io.base.TGFileFormatManager;
import org.herac.tuxguitar.io.base.TGLocalFileExporter;
import org.herac.tuxguitar.io.base.TGLocalFileImporter;
import org.herac.tuxguitar.io.base.TGOutputStreamBase;
import org.herac.tuxguitar.io.base.TGRawImporter;
import org.herac.tuxguitar.song.managers.TGSongManager;
import org.herac.tuxguitar.song.models.TGSong;
public class TGConverter {
public static final int EXPORTER_NOT_FOUND = 590;
public static final int FILE_BAD = 403;
public static final int FILE_COULDNT_WRITE = 401;
public static final int FILE_NOT_FOUND = 404;
public static final int FILE_OK = 250;
public static final int OUT_OF_MEMORY = 500;
// This value will delay the process something like 1 minute for 3000 files.
public static final int SLEEP_TIME = 20;
public static final int UNKNOWN_ERROR = 666;
/** The Logger for this class. */
public static final transient Logger LOG = Logger
.getLogger(TGConverter.class);
private boolean cancelled;
private String destinationFolder;
private TGConverterFormat format;
private TGConverterListener listener;
private String sourceFolder;
public TGConverter(String sourceFolder, String destinationFolder) {
this.sourceFolder = sourceFolder;
this.destinationFolder = destinationFolder;
}
private String checkIfExists(String convertFileName, int level) {
if (new File(convertFileName).exists()) {
String tmpName = convertFileName;
String tmpExtension = "";
String tmpLevel = "(" + (level + 1) + ")";
String lastLevel = "(" + (level) + ")";
int index = convertFileName.lastIndexOf((level == 0 ? "." : lastLevel
+ "."));
if (index != -1) {
tmpExtension = tmpName.substring(index
+ (level == 0 ? 0 : lastLevel.length()), tmpName.length());
tmpName = tmpName.substring(0, index);
}
return checkIfExists((tmpName + tmpLevel + tmpExtension), (level + 1));
}
return convertFileName;
}
public void convert(String fileName, String convertFileName) {
try {
this.getListener().notifyFileProcess(convertFileName);
TGSongManager manager = new TGSongManager();
TGSong song = null;
try {
song = TGFileFormatManager.instance().getLoader().load(
new FileInputStream(fileName));
} catch (TGFileFormatException e) {
song = importSong(fileName);
}
if (song != null) {
manager.setSong(song);
manager.autoCompleteSilences();
manager.orderBeats();
new File(new File(convertFileName).getParent()).mkdirs();
if (this.format != null
&& this.format.getExporter() instanceof TGOutputStreamBase) {
TGOutputStreamBase exporter = (TGOutputStreamBase) this.format
.getExporter();
exporter.init(new BufferedOutputStream(new FileOutputStream(
convertFileName)));
exporter.writeSong(song);
} else if (this.format != null
&& this.format.getExporter() instanceof TGLocalFileExporter) {
TGLocalFileExporter exporter = (TGLocalFileExporter) this.format
.getExporter();
exporter.configure(true);
exporter.init(new BufferedOutputStream(new FileOutputStream(
convertFileName)));
exporter.exportSong(manager.getSong());
}
this.getListener().notifyFileResult(convertFileName, FILE_OK);
} else {
this.getListener().notifyFileResult(fileName, FILE_BAD);
}
} catch (TGFileFormatException e) {
this.getListener().notifyFileResult(fileName, FILE_COULDNT_WRITE);
} catch (FileNotFoundException ex) {
this.getListener().notifyFileResult(fileName, FILE_NOT_FOUND);
} catch (OutOfMemoryError e) {
this.getListener().notifyFileResult(convertFileName, OUT_OF_MEMORY);
} catch (Throwable throwable) {
this.getListener().notifyFileResult(convertFileName, UNKNOWN_ERROR);
}
}
private String getConvertFileName(String path) {
String convertPath = (this.destinationFolder + File.separator + path
.substring(this.sourceFolder.length()));
int lastDot = convertPath.lastIndexOf(".");
if (lastDot != -1) {
convertPath = convertPath.substring(0, lastDot)
+ this.format.getExtension();
}
return checkIfExists(new File(convertPath).getAbsolutePath(), 0);
}
public TGConverterListener getListener() {
return this.listener;
}
private TGSong importSong(String filename) {
for (final TGRawImporter rawImporter : TGFileFormatManager.instance()
.getImporters()) {
try {
if (rawImporter instanceof TGLocalFileImporter) {
TGLocalFileImporter currentImporter = (TGLocalFileImporter) rawImporter;
currentImporter.configure(true);
if (isSupportedExtension(filename, currentImporter)) {
InputStream input = new BufferedInputStream(new FileInputStream(
filename));
currentImporter.init(input);
return currentImporter.importSong();
}
}
} catch (Throwable throwable) {
LOG.error(throwable);
}
}
return null;
}
public boolean isCancelled() {
return this.cancelled;
}
private boolean isSupportedExtension(String filename,
TGLocalFileImporter currentImporter) {
try {
String extension = filename.substring(filename.lastIndexOf("."), filename
.length());
extension = "*" + extension.toLowerCase();
String[] formats = currentImporter.getFileFormat().getSupportedFormats()
.split(";");
for (int i = 0; i < formats.length; i++)
if (formats[i].toLowerCase().equals(extension))
return true;
} catch (Exception ex) {
return false;
}
return false;
}
public void process() {
this.getListener().notifyStart();
this.process(new File(this.sourceFolder));
this.getListener().notifyFinish();
}
private void process(File folder) {
if (!isCancelled()) {
String[] fileNames = folder.list();
if (fileNames != null) {
for (int i = 0; i < fileNames.length; i++) {
File file = new File(folder.getPath() + "/" + fileNames[i]);
if (file.isDirectory()) {
process(file);
} else if (!isCancelled()) {
String fileName = file.getAbsolutePath();
String convertFileName = getConvertFileName(fileName);
convert(fileName, convertFileName);
// Just release the thread some milliseconds
sleep();
}
fileNames[i] = null;
}
}
}
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public void setFormat(TGConverterFormat format) {
this.format = format;
}
public void setListener(TGConverterListener listener) {
this.listener = listener;
}
private void sleep() {
try {
Thread.sleep(SLEEP_TIME);
} catch (Throwable throwable) {
LOG.error(throwable);
}
}
}