Coverage Report - org.jaudiotagger.audio.asf.AsfFileReader
 
Classes in this File Line Coverage Branch Coverage Complexity
AsfFileReader
52%
42/80
37%
14/38
0
 
 1  
 /*
 2  
  * Entagged Audio Tag library
 3  
  * Copyright (c) 2004-2005 Christian Laireiter <liree@web.de>
 4  
  * 
 5  
  * This library is free software; you can redistribute it and/or
 6  
  * modify it under the terms of the GNU Lesser General Public
 7  
  * License as published by the Free Software Foundation; either
 8  
  * version 2.1 of the License, or (at your option) any later version.
 9  
  *  
 10  
  * This library is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
  * Lesser General Public License for more details.
 14  
  * 
 15  
  * You should have received a copy of the GNU Lesser General Public
 16  
  * License along with this library; if not, write to the Free Software
 17  
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18  
  */
 19  
 package org.jaudiotagger.audio.asf;
 20  
 
 21  
 import org.jaudiotagger.audio.AudioFile;
 22  
 import org.jaudiotagger.audio.asf.data.AsfHeader;
 23  
 import org.jaudiotagger.audio.asf.data.AudioStreamChunk;
 24  
 import org.jaudiotagger.audio.asf.data.ContentDescriptor;
 25  
 import org.jaudiotagger.audio.asf.data.ExtendedContentDescription;
 26  
 import org.jaudiotagger.audio.asf.io.*;
 27  
 import org.jaudiotagger.audio.asf.tag.AsfTag;
 28  
 import org.jaudiotagger.audio.asf.util.TagConverter;
 29  
 import org.jaudiotagger.audio.asf.util.Utils;
 30  
 import org.jaudiotagger.audio.exceptions.CannotReadException;
 31  
 import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
 32  
 import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
 33  
 import org.jaudiotagger.audio.generic.AudioFileReader;
 34  
 import org.jaudiotagger.audio.generic.GenericAudioHeader;
 35  
 import org.jaudiotagger.logging.ErrorMessage;
 36  
 import org.jaudiotagger.tag.TagException;
 37  
 
 38  
 import java.io.*;
 39  
 import java.util.ArrayList;
 40  
 import java.util.List;
 41  
 
 42  
 /**
 43  
  * This reader can read ASF files containing any content (stream type). <br>
 44  
  *
 45  
  * @author Christian Laireiter
 46  
  */
 47  84
 public class AsfFileReader extends AudioFileReader
 48  
 {
 49  
 
 50  
     /**
 51  
      * This reader will be configured to read tag and audio header information.<br>
 52  
      */
 53  
     private final static AsfHeaderReader HEADER_READER;
 54  
 
 55  
     static
 56  
     {
 57  42
         List<Class<? extends ChunkReader>> readers = new ArrayList<Class<? extends ChunkReader>>();
 58  42
         readers.add(ContentDescriptionReader.class);
 59  42
         readers.add(ExtContentDescReader.class);
 60  
 
 61  
         // Create the header extension object reader with just content description reader as well
 62  
         // as extended content description reader.
 63  42
         AsfExtHeaderReader extReader = new AsfExtHeaderReader(readers, true);
 64  42
         readers.add(FileHeaderReader.class);
 65  42
         readers.add(StreamChunkReader.class);
 66  42
         HEADER_READER = new AsfHeaderReader(readers, true);
 67  42
         HEADER_READER.setExtendedHeaderReader(extReader);
 68  42
     }
 69  
 
 70  
     /**
 71  
      * Determines if the &quot;isVbr&quot; field is set in the extended content description.<br>
 72  
      *
 73  
      * @param header the header to look up.
 74  
      * @return <code>true</code> if &quot;isVbr&quot; is present with a <code>true</code> value.
 75  
      */
 76  
     private boolean determineVariableBitrate(AsfHeader header)
 77  
     {
 78  39
         assert header != null;
 79  39
         boolean result = false;
 80  39
         ExtendedContentDescription extDesc = header.findExtendedContentDescription();
 81  39
         if (extDesc != null)
 82  
         {
 83  30
             List<ContentDescriptor> descriptors = extDesc.getDescriptors("IsVBR");
 84  30
             if (descriptors != null && !descriptors.isEmpty())
 85  
             {
 86  30
                 result = Boolean.TRUE.toString().equals(descriptors.get(0).getString());
 87  
             }
 88  
         }
 89  39
         return result;
 90  
     }
 91  
 
 92  
     /**
 93  
      * Creates a generic audio header instance with provided data from header.
 94  
      *
 95  
      * @param header ASF header which contains the information.
 96  
      * @return generic audio header representation.
 97  
      * @throws CannotReadException If header does not contain mandatory information.
 98  
      *                             (Audio stream chunk and file header chunk)
 99  
      */
 100  
     private GenericAudioHeader getAudioHeader(final AsfHeader header) throws CannotReadException
 101  
     {
 102  39
         final GenericAudioHeader info = new GenericAudioHeader();
 103  39
         if (header.getFileHeader() == null)
 104  
         {
 105  0
             throw new CannotReadException("Invalid ASF/WMA file. File header object not available.");
 106  
         }
 107  39
         if (header.getAudioStreamChunk() == null)
 108  
         {
 109  0
             throw new CannotReadException("Invalid ASF/WMA file. No audio stream contained.");
 110  
         }
 111  39
         info.setBitrate(header.getAudioStreamChunk().getKbps());
 112  39
         info.setChannelNumber((int) header.getAudioStreamChunk().getChannelCount());
 113  39
         info.setEncodingType("ASF (audio): " + header.getAudioStreamChunk().getCodecDescription());
 114  39
         info.setLossless(header.getAudioStreamChunk().getCompressionFormat() == AudioStreamChunk.WMA_LOSSLESS);
 115  39
         info.setPreciseLength(header.getFileHeader().getPreciseDuration());
 116  39
         info.setSamplingRate((int) header.getAudioStreamChunk().getSamplingRate());
 117  39
         info.setVariableBitRate(determineVariableBitrate(header));
 118  39
         return info;
 119  
     }
 120  
 
 121  
     /**
 122  
      * (overridden)
 123  
      *
 124  
      * @see org.jaudiotagger.audio.generic.AudioFileReader#getEncodingInfo(java.io.RandomAccessFile)
 125  
      */
 126  
     protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException
 127  
     {
 128  0
         raf.seek(0);
 129  0
         GenericAudioHeader info = null;
 130  
         try
 131  
         {
 132  0
             AsfHeader header = AsfHeaderReader.readInfoHeader(raf);
 133  0
             if (header == null)
 134  
             {
 135  0
                 throw new CannotReadException("Some values must have been " + "incorrect for interpretation as asf with wma content.");
 136  
             }
 137  0
             info = getAudioHeader(header);
 138  
         }
 139  0
         catch (Exception e)
 140  
         {
 141  0
             if (e instanceof IOException)
 142  
             {
 143  0
                 throw (IOException) e;
 144  
             }
 145  0
             else if (e instanceof CannotReadException)
 146  
             {
 147  0
                 throw (CannotReadException) e;
 148  
             }
 149  
             else
 150  
             {
 151  0
                 throw new CannotReadException("Failed to read. Cause: " + e.getMessage(), e);
 152  
             }
 153  0
         }
 154  0
         return info;
 155  
     }
 156  
 
 157  
     /**
 158  
      * Creates a tag instance with provided data from header.
 159  
      *
 160  
      * @param header ASF header which contains the information.
 161  
      * @return generic audio header representation.
 162  
      */
 163  
     private AsfTag getTag(AsfHeader header)
 164  
     {
 165  39
         return TagConverter.createTagOf(header);
 166  
     }
 167  
 
 168  
     /**
 169  
      * (overridden)
 170  
      *
 171  
      * @see org.jaudiotagger.audio.generic.AudioFileReader#getTag(java.io.RandomAccessFile)
 172  
      */
 173  
     protected AsfTag getTag(RandomAccessFile raf) throws CannotReadException, IOException
 174  
     {
 175  0
         raf.seek(0);
 176  
         AsfTag tag;
 177  
         try
 178  
         {
 179  0
             AsfHeader header = AsfHeaderReader.readTagHeader(raf);
 180  0
             if (header == null)
 181  
             {
 182  0
                 throw new CannotReadException("Some values must have been " + "incorrect for interpretation as asf with wma content.");
 183  
             }
 184  
 
 185  0
             tag = TagConverter.createTagOf(header);
 186  
 
 187  
         }
 188  0
         catch (Exception e)
 189  
         {
 190  0
             e.printStackTrace();
 191  0
             if (e instanceof IOException)
 192  
             {
 193  0
                 throw (IOException) e;
 194  
             }
 195  0
             else if (e instanceof CannotReadException)
 196  
             {
 197  0
                 throw (CannotReadException) e;
 198  
             }
 199  
             else
 200  
             {
 201  0
                 throw new CannotReadException("Failed to read. Cause: " + e.getMessage());
 202  
             }
 203  0
         }
 204  0
         return tag;
 205  
     }
 206  
 
 207  
     /**
 208  
      * {@inheritDoc}
 209  
      */
 210  
     public AudioFile read(File f) throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException
 211  
     {
 212  39
         if (!f.canRead())
 213  
         {
 214  0
             throw new CannotReadException(ErrorMessage.GENERAL_READ_FAILED_DO_NOT_HAVE_PERMISSION_TO_READ_FILE.getMsg(f.getAbsolutePath()));
 215  
         }
 216  39
         InputStream stream = null;
 217  
         try
 218  
         {
 219  39
             stream = new FullRequestInputStream(new BufferedInputStream(new FileInputStream(f)));
 220  39
             final AsfHeader header = HEADER_READER.read(Utils.readGUID(stream), stream, 0);
 221  39
             if (header == null)
 222  
             {
 223  0
                 throw new CannotReadException(ErrorMessage.ASF_HEADER_MISSING.getMsg(f.getAbsolutePath()));
 224  
             }
 225  39
             if (header.getFileHeader() == null)
 226  
             {
 227  0
                 throw new CannotReadException(ErrorMessage.ASF_FILE_HEADER_MISSING.getMsg(f.getAbsolutePath()));
 228  
             }
 229  
 
 230  
             //Just log a warning because file seems to play okay
 231  39
             if (header.getFileHeader().getFileSize().longValue() != f.length())
 232  
             {
 233  1
                 logger.warning(ErrorMessage.ASF_FILE_HEADER_SIZE_DOES_NOT_MATCH_FILE_SIZE.getMsg(f.getAbsolutePath(), header.getFileHeader().getFileSize().longValue(), f.length()));
 234  
             }
 235  
 
 236  39
             return new AudioFile(f, getAudioHeader(header), getTag(header));
 237  
 
 238  
         }
 239  0
         catch (Exception e)
 240  
         {
 241  0
             throw new CannotReadException("\"" + f + "\" :" + e, e);
 242  
         }
 243  
         finally
 244  
         {
 245  0
             try
 246  
             {
 247  39
                 if (stream != null)
 248  
                 {
 249  39
                     stream.close();
 250  
                 }
 251  
             }
 252  0
             catch (Exception ex)
 253  
             {
 254  0
                 System.err.println("\"" + f + "\" :" + ex);
 255  78
             }
 256  
         }
 257  
     }
 258  
 
 259  
 }