Coverage Report - org.jaudiotagger.audio.flac.FlacStreamReader
 
Classes in this File Line Coverage Branch Coverage Complexity
FlacStreamReader
75%
41/54
54%
12/22
3.857
 
 1  
 package org.jaudiotagger.audio.flac;
 2  
 
 3  
 import org.jaudiotagger.audio.exceptions.CannotReadException;
 4  
 import org.jaudiotagger.logging.ErrorMessage;
 5  
 import org.jaudiotagger.tag.id3.AbstractID3v2Tag;
 6  
 import org.jaudiotagger.tag.id3.ID3v22Tag;
 7  
 import org.jaudiotagger.tag.id3.ID3v23Tag;
 8  
 import org.jaudiotagger.tag.id3.ID3v24Tag;
 9  
 
 10  
 import java.io.IOException;
 11  
 import java.io.RandomAccessFile;
 12  
 import java.nio.ByteBuffer;
 13  
 
 14  
 /**
 15  
  * Flac Stream
 16  
  * <p/>
 17  
  * Reader files and identifies if this is in fact a flac stream
 18  
  */
 19  
 public class FlacStreamReader
 20  
 {
 21  
     public static final int FLAC_STREAM_IDENTIFIER_LENGTH = 4;
 22  
     public static final String FLAC_STREAM_IDENTIFIER = "fLaC";
 23  
 
 24  
     private RandomAccessFile raf;
 25  
     private int startOfFlacInFile;
 26  
 
 27  
     /**
 28  
      * Create instance for holding stream info
 29  
      * @param raf
 30  
      */
 31  
     public FlacStreamReader(RandomAccessFile raf)
 32  247
     {
 33  247
         this.raf = raf;
 34  
 
 35  247
     }
 36  
 
 37  
     /**
 38  
      * Reads the stream block to ensure it is a flac file
 39  
      *
 40  
      * @throws IOException
 41  
      * @throws CannotReadException
 42  
      */
 43  
     public void findStream() throws IOException, CannotReadException
 44  
     {
 45  
         //Begins tag parsing
 46  247
         if (raf.length() == 0)
 47  
         {
 48  
             //Empty File
 49  0
             throw new CannotReadException("Error: File empty");
 50  
         }
 51  247
         raf.seek(0);
 52  
 
 53  
         //FLAC Stream at start
 54  247
         if (isFlacHeader())
 55  
         {
 56  226
             startOfFlacInFile = 0;
 57  226
             return;
 58  
         }
 59  
 
 60  
         //Ok maybe there is an ID3v24tag first
 61  21
         if (isId3v24Tag())
 62  
         {
 63  0
             startOfFlacInFile = (int) (raf.getFilePointer() - FLAC_STREAM_IDENTIFIER_LENGTH);
 64  0
             return;
 65  
         }
 66  
 
 67  
         //Ok maybe there is an ID3v23tag first
 68  21
         if (isId3v23Tag())
 69  
         {
 70  17
             startOfFlacInFile = (int) (raf.getFilePointer() - FLAC_STREAM_IDENTIFIER_LENGTH);
 71  17
             return;
 72  
         }
 73  
 
 74  
         //Ok maybe there is an ID3v22tag first
 75  4
         if (isId3v22Tag())
 76  
         {
 77  0
             startOfFlacInFile = (int) (raf.getFilePointer() - FLAC_STREAM_IDENTIFIER_LENGTH);
 78  0
             return;
 79  
         }
 80  4
         throw new CannotReadException(ErrorMessage.FLAC_NO_FLAC_HEADER_FOUND.getMsg());
 81  
     }
 82  
 
 83  
     private boolean isId3v24Tag() throws IOException
 84  
     {
 85  
         int id3tagsize;
 86  21
         ID3v24Tag id3tag = new ID3v24Tag();
 87  21
         ByteBuffer bb = ByteBuffer.allocate(AbstractID3v2Tag.TAG_HEADER_LENGTH);
 88  21
         raf.seek(0);
 89  21
         raf.getChannel().read(bb);
 90  21
         if (id3tag.seek(bb))
 91  
         {
 92  0
             id3tagsize = id3tag.readSize(bb);
 93  0
             raf.seek(id3tagsize);
 94  
             //FLAC Stream immediately after end of id3 tag
 95  0
             if (isFlacHeader())
 96  
             {
 97  0
                 return true;
 98  
             }
 99  
         }
 100  21
         return false;
 101  
     }
 102  
 
 103  
     private boolean isId3v23Tag() throws IOException
 104  
     {
 105  
         int id3tagsize;
 106  21
         ID3v23Tag id3tag = new ID3v23Tag();
 107  21
         ByteBuffer bb = ByteBuffer.allocate(AbstractID3v2Tag.TAG_HEADER_LENGTH);
 108  21
         raf.seek(0);
 109  21
         raf.getChannel().read(bb);
 110  21
         if (id3tag.seek(bb))
 111  
         {
 112  17
             id3tagsize = id3tag.readSize(bb);
 113  17
             raf.seek(id3tagsize);
 114  
             //FLAC Stream immediately after end of id3 tag
 115  17
             if (isFlacHeader())
 116  
             {
 117  17
                 return true;
 118  
             }
 119  
         }
 120  4
         return false;
 121  
     }
 122  
 
 123  
     private boolean isId3v22Tag() throws IOException
 124  
     {
 125  
         int id3tagsize;
 126  4
         ID3v22Tag id3tag = new ID3v22Tag();
 127  4
         ByteBuffer bb = ByteBuffer.allocate(AbstractID3v2Tag.TAG_HEADER_LENGTH);
 128  4
         raf.seek(0);
 129  4
         raf.getChannel().read(bb);
 130  4
         if (id3tag.seek(bb))
 131  
         {
 132  0
             id3tagsize = id3tag.readSize(bb);
 133  0
             raf.seek(id3tagsize);
 134  
             //FLAC Stream immediately after end of id3 tag
 135  0
             if (isFlacHeader())
 136  
             {
 137  0
                 return true;
 138  
             }
 139  
         }
 140  4
         return false;
 141  
     }
 142  
 
 143  
     private boolean isFlacHeader() throws IOException
 144  
     {
 145  
         //FLAC Stream at start
 146  264
         byte[] b = new byte[FLAC_STREAM_IDENTIFIER_LENGTH];
 147  264
         raf.read(b);
 148  264
         String flac = new String(b);
 149  264
         return flac.equals(FLAC_STREAM_IDENTIFIER);
 150  
     }
 151  
 
 152  
     /**
 153  
      * Usually flac header is at start of file, but unofficially and ID3 tag is allowed at the start of the file.
 154  
      *
 155  
      * @return the start of the Flac within file
 156  
      */
 157  
     public int getStartOfFlacInFile()
 158  
     {
 159  76
         return startOfFlacInFile;
 160  
     }
 161  
 }