package com.limegroup.gnutella.hashing; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import org.jaudiotagger.audio.exceptions.CannotReadException; import org.jaudiotagger.audio.flac.FlacStreamReader; import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; import org.limewire.io.IOUtils; /** * Locates the beginning and end of the audio portion of a FLAC file. This * checks for ID3v2.x tags, and FLAC Headers at the begining of the file. * Per FLAC spec, no tags are ever located at the end of the file so we * assume EOF is end-of-audio. */ class FLACNonMetaDataHasher extends NonMetaDataHasher { private final File file; FLACNonMetaDataHasher(File file) { this.file = file; } /** * Returns the start frame of this FLAC file. The FLAC audio * stream may be preceded by an ID3 tag and a series of MetaData * Block Headers including an OGG_Comment header. This returns the * position of the first frame within the FLAC_Audio stream. */ @Override public long getStartPosition() throws IOException { RandomAccessFile raf = null; try { raf = new RandomAccessFile(file, "r"); FlacStreamReader flacStream = new FlacStreamReader(raf); try { // attempt to locate the start of the FLAC file. ID3 tags // or other tags may be added before the FLAC Headers flacStream.findStream(); } catch(CannotReadException e) { throw new IOException(e); } boolean isEndOfHeader = false; while(!isEndOfHeader) { MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf); raf.seek(raf.getFilePointer() + mbh.getDataLength()); isEndOfHeader = mbh.isLastBlock(); } return raf.getFilePointer(); } finally { IOUtils.close(raf); } } /** * Returns the position of the end of the last frame of audio in this file. For * FLAC files this is equal to EOF. */ @Override public long getEndPosition() throws IOException { return file.length(); } }