Package entagged.audioformats.flac.util

Source Code of entagged.audioformats.flac.util.FlacTagWriter

/*
* Entagged Audio Tag library
* Copyright (c) 2003-2005 Rapha�l Slinckx <raphael@slinckx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
package entagged.audioformats.flac.util;

import entagged.audioformats.*;
import entagged.audioformats.exceptions.*;
import entagged.audioformats.ogg.OggTag;

import java.io.*;
import java.nio.channels.*;
import java.util.*;


public class FlacTagWriter {
 
  private Vector metadataBlockPadding = new Vector(1);
  private Vector metadataBlockApplication = new Vector(1);
  private Vector metadataBlockSeekTable = new Vector(1);
  private Vector metadataBlockCueSheet = new Vector(1);

  private FlacTagCreator tc = new FlacTagCreator();
  private FlacTagReader reader = new FlacTagReader();
 
  public void delete(RandomAccessFile raf,  RandomAccessFile tempRaf) throws IOException, CannotWriteException {
    OggTag tag = null;
    try {
      tag = reader.read(raf);
    } catch(CannotReadException e) {
      write(new OggTag(), raf, tempRaf);
      return;
    }
   
    OggTag emptyTag = new OggTag();
    emptyTag.setVendor(tag.getVendor());
   
    raf.seek(0);
    tempRaf.seek(0);
   
    write(emptyTag, raf, tempRaf);
  }
 
  public void write( Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp ) throws CannotWriteException, IOException {
    //Clean up old datas
    metadataBlockPadding.removeAllElements();
    metadataBlockApplication.removeAllElements();
    metadataBlockSeekTable.removeAllElements();
    metadataBlockCueSheet.removeAllElements();
   
    byte[] b = new byte[4];
    raf.readFully(b);
   
    String flac = new String(b);
    if(!flac.equals("fLaC"))
      throw new CannotWriteException("This is not a FLAC file");
   
    boolean isLastBlock = false;
    while(!isLastBlock) {
      b = new byte[4];
      raf.readFully(b);
      MetadataBlockHeader mbh = new MetadataBlockHeader(b);
   
      //System.err.println("BlockType: "+mbh.getBlockTypeString());
      switch(mbh.getBlockType()) {
        case MetadataBlockHeader.VORBIS_COMMENT : handlePadding(mbh, raf); break;
        case MetadataBlockHeader.PADDING : handlePadding(mbh, raf); break;
        case MetadataBlockHeader.APPLICATION : handleApplication(mbh, raf); break;
        case MetadataBlockHeader.SEEKTABLE : handleSeekTable(mbh, raf); break;
        case MetadataBlockHeader.CUESHEET : handleCueSheet(mbh, raf); break;
        default : skipBlock(mbh, raf); break;
      }

      isLastBlock = mbh.isLastBlock();
    }
   
    int availableRoom =  computeAvailableRoom();
    int newTagSize = tc.getTagLength(tag);
    int neededRoom = newTagSize + computeNeededRoom();
    //System.err.println("Av.:"+availableRoom+"|Needed:"+neededRoom);
    raf.seek(0);
   
    if(availableRoom>=neededRoom) {
      //OVERWRITE EXISTING TAG
      raf.seek(42);
   
      for(int i = 0; i<metadataBlockApplication.size(); i++) {
        raf.write( ((MetadataBlock) metadataBlockApplication.elementAt(i)).getHeader().getBytes());
        raf.write( ((MetadataBlock) metadataBlockApplication.elementAt(i)).getData().getBytes());
      }

      for(int i = 0; i<metadataBlockSeekTable.size(); i++) {
        raf.write( ((MetadataBlock) metadataBlockSeekTable.elementAt(i)).getHeader().getBytes());
        raf.write( ((MetadataBlock) metadataBlockSeekTable.elementAt(i)).getData().getBytes());
      }
   
      for(int i = 0; i<metadataBlockCueSheet.size(); i++) {
        raf.write( ((MetadataBlock) metadataBlockCueSheet.elementAt(i)).getHeader().getBytes());
        raf.write( ((MetadataBlock) metadataBlockCueSheet.elementAt(i)).getData().getBytes());
      }
   
      raf.getChannel().write( tc.convert(tag, availableRoom-neededRoom ) );
   
    } else {
      //create new tag with padding (we remove the header and keep the audio data)
     
      FileChannel fc = raf.getChannel();
      b = new byte[42];
      raf.readFully(b);
      raf.seek(availableRoom+42);

      FileChannel tempFC = rafTemp.getChannel();
     
      rafTemp.write( b );
     
      for(int i = 0; i<metadataBlockApplication.size(); i++) {
        rafTemp.write( ((MetadataBlock) metadataBlockApplication.elementAt(i)).getHeader().getBytes());
        rafTemp.write( ((MetadataBlock) metadataBlockApplication.elementAt(i)).getData().getBytes());
      }

      for(int i = 0; i<metadataBlockSeekTable.size(); i++) {
        rafTemp.write( ((MetadataBlock) metadataBlockSeekTable.elementAt(i)).getHeader().getBytes());
        rafTemp.write( ((MetadataBlock) metadataBlockSeekTable.elementAt(i)).getData().getBytes());
      }
   
      for(int i = 0; i<metadataBlockCueSheet.size(); i++) {
        rafTemp.write( ((MetadataBlock) metadataBlockCueSheet.elementAt(i)).getHeader().getBytes());
        rafTemp.write( ((MetadataBlock) metadataBlockCueSheet.elementAt(i)).getData().getBytes());
      }
     
      rafTemp.write( tc.convert(tag, FlacTagCreator.DEFAULT_PADDING ).array());
     
      tempFC.transferFrom( fc, tempFC.position(), fc.size() );
    }
  }
 
  private int computeAvailableRoom() {
    int length = 0;
   
    for(int i = 0; i<metadataBlockApplication.size(); i++)
      length += ((MetadataBlock) metadataBlockApplication.elementAt(i)).getLength();
   
    for(int i = 0; i<metadataBlockSeekTable.size(); i++)
      length += ((MetadataBlock) metadataBlockSeekTable.elementAt(i)).getLength();
   
    for(int i = 0; i<metadataBlockCueSheet.size(); i++)
      length += ((MetadataBlock) metadataBlockCueSheet.elementAt(i)).getLength();
   
    for(int i = 0; i<metadataBlockPadding.size(); i++)
      length += ((MetadataBlock) metadataBlockPadding.elementAt(i)).getLength();
   
    return length;
  }
 
  private int computeNeededRoom() {
    int length = 0;
   
    for(int i = 0; i<metadataBlockApplication.size(); i++)
      length += ((MetadataBlock) metadataBlockApplication.elementAt(i)).getLength();
   
    for(int i = 0; i<metadataBlockSeekTable.size(); i++)
      length += ((MetadataBlock) metadataBlockSeekTable.elementAt(i)).getLength();
   
    for(int i = 0; i<metadataBlockCueSheet.size(); i++)
      length += ((MetadataBlock) metadataBlockCueSheet.elementAt(i)).getLength();
   
    return length;
  }
   
 
  private void skipBlock(MetadataBlockHeader mbh, RandomAccessFile raf) throws IOException {
    raf.seek(raf.getFilePointer()+mbh.getDataLength());
  }
 
 
  private void handlePadding(MetadataBlockHeader mbh, RandomAccessFile raf) throws IOException {
    raf.seek(raf.getFilePointer()+mbh.getDataLength());
   
    MetadataBlockData mbd = new MetadataBlockDataPadding( mbh.getDataLength() );
    metadataBlockPadding.add(new MetadataBlock(mbh, mbd));
  }
 
  private void handleApplication(MetadataBlockHeader mbh, RandomAccessFile raf) throws IOException {
    byte[] b = new byte[mbh.getDataLength()];
    raf.readFully(b);
     
    MetadataBlockData mbd = new MetadataBlockDataApplication(b);
    metadataBlockApplication.add(new MetadataBlock(mbh, mbd));
  }
 
  private void handleSeekTable(MetadataBlockHeader mbh, RandomAccessFile raf) throws IOException {
    byte[] b = new byte[mbh.getDataLength()];
    raf.readFully(b);
     
    MetadataBlockData mbd = new MetadataBlockDataSeekTable(b);
    metadataBlockSeekTable.add(new MetadataBlock(mbh, mbd));
  }
 
  private void handleCueSheet(MetadataBlockHeader mbh, RandomAccessFile raf) throws IOException {
    byte[] b = new byte[mbh.getDataLength()];
    raf.readFully(b);
     
    MetadataBlockData mbd = new MetadataBlockDataCueSheet(b);
    metadataBlockCueSheet.add(new MetadataBlock(mbh, mbd));
  }

}

TOP

Related Classes of entagged.audioformats.flac.util.FlacTagWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.