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