package org.herac.tuxguitar.io.ascii;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import org.herac.tuxguitar.song.managers.TGSongManager;
import org.herac.tuxguitar.song.models.TGBeat;
import org.herac.tuxguitar.song.models.TGDuration;
import org.herac.tuxguitar.song.models.TGMeasure;
import org.herac.tuxguitar.song.models.TGNote;
import org.herac.tuxguitar.song.models.TGSong;
import org.herac.tuxguitar.song.models.TGString;
import org.herac.tuxguitar.song.models.TGTrack;
public class ASCIITabOutputStream {
private static final int MAX_LINE_LENGTH = 80;
private static final String[] TONIC_NAMES = new String[] { "C", "C#", "D",
"D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
private TGSongManager manager;
private ASCIIOutputStream out;
private PrintStream stream;
public ASCIITabOutputStream(OutputStream stream) {
this(new PrintStream(stream));
}
public ASCIITabOutputStream(PrintStream stream) {
this.stream = stream;
}
public ASCIITabOutputStream(String fileName) throws FileNotFoundException {
this(new FileOutputStream(fileName));
}
private void drawMeasure(TGMeasure measure, TGString string) {
// Abro el compas
this.out.drawBarSegment();
this.out.drawStringSegments(1);
TGBeat beat = this.manager.getMeasureManager().getFirstBeat(
measure.getBeats());
while (beat != null) {
int outLength = 0;
// Si hay una nota en la misma cuerda, la dibujo
TGNote note = this.manager.getMeasureManager().getNote(beat,
string.getNumber());
if (note != null) {
outLength = (Integer.toString(note.getValue()).length() - 1);
this.out.drawNote(note.getValue());
}
// dejo el espacio
else {
this.out.drawStringSegments(1);
}
TGBeat nextBeat = this.manager.getMeasureManager().getNextBeat(
measure.getBeats(), beat);
long length = (nextBeat != null ? nextBeat.getStart() - beat.getStart()
: (measure.getStart() + measure.getLength()) - beat.getStart());
// Agrego espacios correspondientes hasta el proximo pulso.
this.out.drawStringSegments(getDurationScaping(length) - outLength);
beat = nextBeat;
// Agrego espacios correspondientes hasta el proximo pulso.
// this.out.drawStringSegments(getDurationScaping(beat.getDuration()) -
// outLength);
// beat = this.manager.getMeasureManager().getNextBeat( measure.getBeats()
// , beat);
}
}
private void drawSong() {
TGSong song = this.manager.getSong();
// Propiedades de cancion
this.out.drawStringLine("Title: " + song.getName());
this.out.drawStringLine("Artist: " + song.getArtist());
this.out.drawStringLine("Album: " + song.getAlbum());
this.out.drawStringLine("Author: " + song.getAuthor());
for (final TGTrack track : song.getTracks()) {
this.out.nextLine();
drawTrack(track);
this.out.nextLine();
}
}
private void drawTrack(TGTrack track) {
// Propiedades de pista
this.out.nextLine();
this.out.drawStringLine("Track " + track.getNumber() + ": "
+ track.getName());
// Obtengo los nombres de la afinacion, y el ancho maximo que ocupa
String[] tuning = new String[track.getStrings().size()];
int maxTuningLength = 1;
for (int i = 0; i < track.getStrings().size(); i++) {
TGString string = (TGString) track.getStrings().get(i);
tuning[i] = TONIC_NAMES[(string.getValue() % TONIC_NAMES.length)];
maxTuningLength = Math.max(maxTuningLength, tuning[i].length());
}
int nextMeasure = 0;
boolean eof = false;
while (!eof) {
this.out.nextLine();
int index = nextMeasure;
for (int i = 0; i < track.getStrings().size(); i++) {
TGString string = (TGString) track.getStrings().get(i);
// Dibujo la afinacion de la cuerda
this.out.drawTuneSegment(tuning[i], maxTuningLength);
int measureCount = track.countMeasures();
for (int j = index; j < measureCount; j++) {
TGMeasure measure = track.getMeasure(j);
drawMeasure(measure, string);
nextMeasure = (j + 1);
// Calculo si era el ultimo compas
eof = (this.manager.getTrackManager().isLastMeasure(measure));
// Si se supero el ancho maximo, bajo de linea
if (this.out.getPosX() > MAX_LINE_LENGTH) {
break;
}
}
// Cierro los compases
this.out.drawBarSegment();
this.out.nextLine();
}
this.out.nextLine();
}
this.out.nextLine();
}
/*
* private int getDurationScaping(TGDuration duration){ int spacing = 1;
*
* if(duration.getValue() >= TGDuration.SIXTEENTH){ spacing = 2; } else
* if(duration.getValue() >= TGDuration.EIGHTH){ spacing = 3; } else
* if(duration.getValue() >= TGDuration.QUARTER){ spacing = 4; } else
* if(duration.getValue() >= TGDuration.HALF){ spacing = 5; } else
* if(duration.getValue() >= TGDuration.WHOLE){ spacing = 6; } return spacing;
* }
*/
private int getDurationScaping(long length) {
int spacing = 6;
if (length <= (TGDuration.QUARTER_TIME / 8)) {
spacing = 1;
} else if (length <= (TGDuration.QUARTER_TIME / 4)) {
spacing = 2;
} else if (length <= (TGDuration.QUARTER_TIME / 2)) {
spacing = 3;
} else if (length <= TGDuration.QUARTER_TIME) {
spacing = 4;
} else if (length <= (TGDuration.QUARTER_TIME * 2)) {
spacing = 5;
}
return spacing;
}
public void writeSong(TGSong song) {
this.manager = new TGSongManager();
this.manager.setSong(song);
this.out = new ASCIIOutputStream(this.stream);
this.drawSong();
this.out.flush();
this.out.close();
}
}