gt: 			header |= MEASURE_KEYSIGNATURE;
context: /*
   * Created on 16-dic-2005
   *
   * TODO To change the template for this generated file go to
   * Window - Preferences - Java - Code Style - Code Templates
   */
  package org.herac.tuxguitar.io.tg.v11;
  
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.util.Iterator;
  
  import org.herac.tuxguitar.gm.GMChannelRoute;
  import org.herac.tuxguitar.gm.GMChannelRouter;
  import org.herac.tuxguitar.gm.GMChannelRouterConfigurator;
  import org.herac.tuxguitar.io.base.TGFileFormat;
  import org.herac.tuxguitar.io.base.TGFileFormatException;
  import org.herac.tuxguitar.io.base.TGLocalFileExporter;
  import org.herac.tuxguitar.song.factory.TGFactory;
  import org.herac.tuxguitar.song.managers.TGSongManager;
  import org.herac.tuxguitar.song.models.TGBeat;
  import org.herac.tuxguitar.song.models.TGChannel;
  import org.herac.tuxguitar.song.models.TGChord;
  import org.herac.tuxguitar.song.models.TGColor;
  import org.herac.tuxguitar.song.models.TGDivisionType;
  import org.herac.tuxguitar.song.models.TGDuration;
  import org.herac.tuxguitar.song.models.TGLyric;
  import org.herac.tuxguitar.song.models.TGMarker;
  import org.herac.tuxguitar.song.models.TGMeasure;
  import org.herac.tuxguitar.song.models.TGMeasureHeader;
  import org.herac.tuxguitar.song.models.TGNote;
  import org.herac.tuxguitar.song.models.TGNoteEffect;
  import org.herac.tuxguitar.song.models.TGSong;
  import org.herac.tuxguitar.song.models.TGString;
  import org.herac.tuxguitar.song.models.TGStroke;
  import org.herac.tuxguitar.song.models.TGTempo;
  import org.herac.tuxguitar.song.models.TGText;
  import org.herac.tuxguitar.song.models.TGTimeSignature;
  import org.herac.tuxguitar.song.models.TGTrack;
  import org.herac.tuxguitar.song.models.TGVoice;
  import org.herac.tuxguitar.song.models.effects.TGEffectBend;
  import org.herac.tuxguitar.song.models.effects.TGEffectGrace;
  import org.herac.tuxguitar.song.models.effects.TGEffectHarmonic;
  import org.herac.tuxguitar.song.models.effects.TGEffectTremoloBar;
  import org.herac.tuxguitar.song.models.effects.TGEffectTremoloPicking;
  import org.herac.tuxguitar.song.models.effects.TGEffectTrill;
  /**
   * @author julian
   *
   * TODO To change the template for this generated type comment go to
   * Window - Preferences - Java - Code Style - Code Templates
   */
  public class TGOutputStream extends TGStream implements TGLocalFileExporter{
  	
  	private TGFactory factory;
  	private GMChannelRouter channelRouter;
  	private DataOutputStream dataOutputStream;
  	
  	public boolean isSupportedExtension(String extension) {
  		return (extension.toLowerCase().equals(TG_FORMAT_EXTENSION));
  	}
  	
  	public String getExportName(){
  		return "TuxGuitar 1.1";
  	}
  	
  	public TGFileFormat getFileFormat(){
  		return new TGFileFormat("TuxGuitar 1.1", new String[]{"tg"});
  	}
  	
  	public boolean configure(TGSong song, boolean setDefaults){
  		return true;
  	}
  	
  	public void init(TGFactory factory,OutputStream stream){
  		this.factory = factory;
  		this.dataOutputStream = new DataOutputStream(stream);
  	}
  	
  	public void exportSong(TGSong song) throws TGFileFormatException {
  		try{
  			this.configureChannelRouter(song);
  			this.writeVersion();
  			this.write(song);
  			this.dataOutputStream.flush();
  			this.dataOutputStream.close();
  		}catch( Throwable throwable){
  			throw new TGFileFormatException(throwable);
  		}
  	}
  	
  	private void writeVersion(){
  		writeUnsignedByteString(TG_FORMAT_VERSION);
  	}
  	
  	private void write(TGSong song){
  		//escribo el nombre
  		writeUnsignedByteString(song.getName());
  		
  		//escribo el artista
  		writeUnsignedByteString(song.getArtist());
  		
  		//escribo el album
  		writeUnsignedByteString(song.getAlbum());
  		
  		//escribo el autor
  		writeUnsignedByteString(song.getAuthor());
  		
  		//escribo la cantidad de measure headers 
  		writeShort((short)song.countMeasureHeaders());
  		
  		//escribo las pistas
  		TGMeasureHeader lastHeader = null;
  		Iterator headers = song.getMeasureHeaders();
  		while(headers.hasNext()){
  			TGMeasureHeader header = (TGMeasureHeader)headers.next();
  			writeMeasureHeader(header,lastHeader);
  			lastHeader = header;
  		}
  		
  		//escribo la cantidad de pistas
  		writeByte(song.countTracks());
  		
  		//escribo las pistas
  		for(int i = 0;i < song.countTracks();i++){
  			TGTrack track = song.getTrack(i);
  			writeTrack(track);
  		}
  	}
  	
  	private void writeTrack(TGTrack track){
  		//header
  		int header = 0;
  		if (track.isSolo()) {
  			header |= TRACK_SOLO;
  		}
  		if (track.isMute()) {
  			header |= TRACK_MUTE;
  		}
  		if(!track.getLyrics().isEmpty()){
  			header |= TRACK_LYRICS;
  		}
  		writeHeader(header);
  		
  		//escribo el nombre
  		writeUnsignedByteString(track.getName());
  		
  		//escribo el canal
  		writeChannel(getChannel(track.getSong(), track));
  		
  		//escribo los compases
  		TGMeasure lastMeasure = null;
  		Iterator measures  = track.getMeasures();
  		while(measures.hasNext()){
  			TGMeasure measure = (TGMeasure)measures.next();
  			writeMeasure(measure,lastMeasure);
  			lastMeasure = measure;
  		}
  		
  		//escribo la cantidad de cuerdas 
  		writeByte(track.getStrings().size());
  		
  		//escribo las cuerdas
  		Iterator stringIt  = track.getStrings().iterator();
  		while(stringIt.hasNext()){
  			TGString string = (TGString)stringIt.next();
  			writeInstrumentString(string);
  		}
  		
  		//escribo el offset
  		writeByte(track.getOffset() - TGTrack.MIN_OFFSET);
  		
  		//escribo el color
  		writeRGBColor(track.getColor());
  		
  		//escribo el lyrics
  		if(((header & TRACK_LYRICS) != 0)){
  			writeLyrics(track.getLyrics());
  		}
  	}
  	
  	private void writeMeasureHeader(TGMeasureHeader measureheader,TGMeasureHeader lastMeasureHeader){
  		int header = 0;
  		if(lastMeasureHeader == null){
  			header |= MEASURE_HEADER_TIMESIGNATURE;
  			header |= MEASURE_HEADER_TEMPO;
  			if(measureheader.getTripletFeel() != TGMeasureHeader.TRIPLET_FEEL_NONE){
  				header |= MEASURE_HEADER_TRIPLET_FEEL;
  			}
  		}else{
  			//Time Signature
  			int numerator = measureheader.getTimeSignature().getNumerator();
  			int value = measureheader.getTimeSignature().getDenominator().getValue();
  			int prevNumerator = lastMeasureHeader.getTimeSignature().getNumerator();
  			int prevValue = lastMeasureHeader.getTimeSignature().getDenominator().getValue();
  			if(numerator != prevNumerator || value != prevValue){
  				header |= MEASURE_HEADER_TIMESIGNATURE;
  			}
  			//Tempo
  			if(measureheader.getTempo().getValue() != lastMeasureHeader.getTempo().getValue()){
  				header |= MEASURE_HEADER_TEMPO;
  			}
  			//Triplet Feel
  			if(measureheader.getTripletFeel() != lastMeasureHeader.getTripletFeel()){
  				header |= MEASURE_HEADER_TRIPLET_FEEL;
  			}
  		}
  		header = (measureheader.isRepeatOpen())?header |= MEASURE_HEADER_REPEAT_OPEN:header;
  		header = (measureheader.getRepeatClose() > 0)?header |= MEASURE_HEADER_REPEAT_CLOSE:header;
  		header = (measureheader.getRepeatAlternative() > 0)?header |= MEASURE_HEADER_REPEAT_ALTERNATIVE:header;
  		header = (measureheader.hasMarker())?header |= MEASURE_HEADER_MARKER:header;
  		
  		writeHeader(header);
  		
  		//escribo el timeSignature
  		if(((header & MEASURE_HEADER_TIMESIGNATURE) != 0)){
  			writeTimeSignature(measureheader.getTimeSignature());
  		}
  		
  		//escribo el tempo
  		if(((header & MEASURE_HEADER_TEMPO) != 0)){
  			writeTempo(measureheader.getTempo());
  		}
  		
  		//escribo el numero de repeticiones
  		if(((header & MEASURE_HEADER_REPEAT_CLOSE) != 0)){
  			writeShort((short)measureheader.getRepeatClose());
  		}
  		
  		//escribo los finales alternativos
  		if(((header & MEASURE_HEADER_REPEAT_ALTERNATIVE) != 0)){
  			writeByte(measureheader.getRepeatAlternative());
  		}
  		
  		//escribo el marker
  		if(((header & MEASURE_HEADER_MARKER) != 0)){
  			writeMarker(measureheader.getMarker());
  		}
  		
  		//escribo el triplet feel
  		if(((header & MEASURE_HEADER_TRIPLET_FEEL) != 0)){
  			writeByte(measureheader.getTripletFeel());
  		}
  	}
  	
  	private void writeMeasure(TGMeasure measure,TGMeasure lastMeasure){
  		int header = 0;
  		if(lastMeasure == null){
  			header |= MEASURE_CLEF;
  