View Javadoc

1   /*
2    * Entagged Audio Tag library
3    * Copyright (c) 2003-2005 Raphaël Slinckx <raphael@slinckx.net>
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 entagged.audioformats.ape.util;
20  
21  import java.io.IOException;
22  import java.io.RandomAccessFile;
23  import entagged.audioformats.Tag;
24  import entagged.audioformats.ape.ApeTag;
25  import entagged.audioformats.exceptions.CannotReadException;
26  import entagged.audioformats.generic.Utils;
27  
28  public class ApeTagReader {
29  
30  	public Tag read(RandomAccessFile raf) throws CannotReadException, IOException {
31  		ApeTag tag = new ApeTag();
32  		
33  		//Check wether the file contains an APE tag--------------------------------
34  		raf.seek( raf.length() - 32 );
35  		
36  		byte[] b = new byte[8];
37  		raf.read(b);
38  		
39  		String tagS = new String( b );
40  		if(!tagS.equals( "APETAGEX" )){
41  			throw new CannotReadException("There is no APE Tag in this file");
42  		}
43  		//Parse the tag -)------------------------------------------------
44  		//Version
45  		b = new byte[4];
46  		raf.read( b );
47  		int version = Utils.getNumber(b, 0,3);
48  		if(version != 2000) {
49  			throw new CannotReadException("APE Tag other than version 2.0 are not supported");
50  		}
51  		
52  		//Size
53  		b = new byte[4];
54  		raf.read( b );
55  		long tagSize = Utils.getLongNumber(b, 0,3);
56  
57  		//Number of items
58  		b = new byte[4];
59  		raf.read( b );
60  		int itemNumber = Utils.getNumber(b, 0,3);
61  		
62  		//Tag Flags
63  		b = new byte[4];
64  		raf.read( b );
65  		//TODO handle these
66  		
67  		raf.seek(raf.length() - tagSize);
68  		
69  		for(int i = 0; i<itemNumber; i++) {
70  			//Content length
71  			b = new byte[4];
72  			raf.read( b );
73  			int contentLength = Utils.getNumber(b, 0,3);
74  			if(contentLength > 500000)
75  				throw new CannotReadException("Item size is much too large: "+contentLength+" bytes");
76  			
77  			//Item flags
78  			b = new byte[4];
79  			raf.read( b );
80  			//TODO handle these
81  			boolean binary = ((b[0]&0x06) >> 1) == 1;
82  			
83  			int j = 0;
84  			while(raf.readByte() != 0)
85  				j++;
86  			raf.seek(raf.getFilePointer() - j -1);
87  			int fieldSize = j;
88  			
89  			//Read Item key
90  			b = new byte[fieldSize];
91  			raf.read( b );
92  			raf.skipBytes(1);
93  			String field = new String(b);
94  			
95  			//Read Item content
96  			b = new byte[contentLength];
97  			raf.read( b );
98  			if(!binary)
99  			    tag.add(new ApeTagTextField(field, new String(b, "UTF-8")));
100 			else
101 			    tag.add(new ApeTagBinaryField(field, b));
102 		}
103 		
104 		return tag;
105 	} 
106 }