summaryrefslogtreecommitdiff
path: root/songdbj/net/shredzone/ifish
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2007-01-08 23:53:00 +0000
committerBjörn Stenberg <bjorn@haxx.se>2007-01-08 23:53:00 +0000
commit7039a05147b8bbfc829babea1c65bd436450b505 (patch)
tree4ba555eb84ed97b72b0575034d5b0530a393713e /songdbj/net/shredzone/ifish
parent6d4c19707ef95942e323cbdc89fbbfdbe45e7cc5 (diff)
downloadrockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.gz
rockbox-7039a05147b8bbfc829babea1c65bd436450b505.zip
Splitting out songdbj
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11953 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/net/shredzone/ifish')
-rw-r--r--songdbj/net/shredzone/ifish/ltr/FormatDecodeException.java66
-rw-r--r--songdbj/net/shredzone/ifish/ltr/LTR.java251
-rw-r--r--songdbj/net/shredzone/ifish/ltr/LTRmp3.java165
-rw-r--r--songdbj/net/shredzone/ifish/ltr/OggFastFileStream.java249
-rw-r--r--songdbj/net/shredzone/ifish/ltr/TagAsf.java170
-rw-r--r--songdbj/net/shredzone/ifish/ltr/TagMp3v1.java184
-rw-r--r--songdbj/net/shredzone/ifish/ltr/TagMp3v2.java441
-rw-r--r--songdbj/net/shredzone/ifish/ltr/TagMp3v200.java373
-rw-r--r--songdbj/net/shredzone/ifish/ltr/TagOggVorbis.java207
9 files changed, 0 insertions, 2106 deletions
diff --git a/songdbj/net/shredzone/ifish/ltr/FormatDecodeException.java b/songdbj/net/shredzone/ifish/ltr/FormatDecodeException.java
deleted file mode 100644
index 72522eaa4d..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/FormatDecodeException.java
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47/**
48 * This exception signals that the Tag could not be decoded for various
49 * reasons.
50 *
51 * @author Richard Körber &lt;dev@shredzone.de&gt;
52 * @version $Id$
53 */
54public class FormatDecodeException extends Exception {
55 private static final long serialVersionUID = 3690758397339187507L;
56
57 /**
58 * Constructor for the FormatDecodeException object
59 *
60 * @param msg A message
61 */
62 public FormatDecodeException( String msg ) {
63 super( msg );
64 }
65
66}
diff --git a/songdbj/net/shredzone/ifish/ltr/LTR.java b/songdbj/net/shredzone/ifish/ltr/LTR.java
deleted file mode 100644
index 8a38676583..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/LTR.java
+++ /dev/null
@@ -1,251 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48
49/**
50 * The Base Class for the Lightweight Tag Reader. LTR was made to read
51 * the basic tag information of MP3 (IDv1, IDv2), Ogg Vorbis and ASF/WMA
52 * files. It is lightweight because it is optimized for speed, and is
53 * only able to read the tag information, but unable to edit them.
54 *
55 * @author Richard Körber &lt;dev@shredzone.de&gt;
56 * @version $Id$
57 */
58public abstract class LTR {
59 protected RandomAccessFile in; // The file to be checked
60
61 /**
62 * Create a new LTR object. It is connected to the file to be decoded,
63 * by a RandomAccessFile. The cursor position will be changed during
64 * recognizing and decoding.
65 *
66 * @param in RandomAccessFile to be used
67 * @throws FormatDecodeException Description of the Exception
68 */
69 public LTR( RandomAccessFile in )
70 throws FormatDecodeException {
71 this.in = in;
72 try {
73 in.seek( 0 ); // To the beginning of file
74 } catch( IOException e ) {
75 throw new FormatDecodeException( "couldn't seek: " + e.toString() );
76 }
77 }
78
79 /**
80 * Create an LTR object for a file. If the file given, was not
81 * recognized or did not contain any tags, null will be returned.
82 *
83 * @param file File to open
84 * @return LTR to this file, or null
85 * @exception IOException Description of the Exception
86 */
87 public static LTR create( File file ) {
88 RandomAccessFile in = null;
89 LTR result = null;
90
91 try {
92 in = new RandomAccessFile( file, "r" );
93
94 try {
95 result = new TagOggVorbis( in );
96 return result;
97 } catch( FormatDecodeException e ) {}
98
99 try {
100 result = new TagMp3v2( in );
101 return result;
102 } catch( FormatDecodeException e ) {}
103
104 try {
105 result = new TagMp3v200( in );
106 return result;
107 } catch( FormatDecodeException e ) {}
108
109 try {
110 result = new TagAsf( in, file );
111 return result;
112 }catch( FormatDecodeException e ) {}
113
114 try {
115 // Always check ID3v1 *after* ID3v2, because a lot of ID3v2
116 // files also contain ID3v1 tags with limited content.
117 result = new TagMp3v1( in );
118 return result;
119 } catch( FormatDecodeException e ) {}
120 }catch(IOException e) {
121 return null;
122 } finally {
123 try {
124 if( in!=null ) in.close();
125 } catch(IOException e) {
126 System.out.println("Failed to close file.");
127 }
128 }
129
130 return null;
131 }
132
133 /**
134 * Get the type of this file. This is usually the compression format
135 * itself (e.g. "OGG" or "MP3"). If there are different taggings for
136 * this format, the used tag format is appended after a slash (e.g.
137 * "MP3/id3v2").
138 *
139 * @return The type
140 */
141 public abstract String getType();
142
143 /**
144 * Get the artist.
145 *
146 * @return The artist (never null)
147 */
148 public abstract String getArtist();
149
150 /**
151 * Get the album.
152 *
153 * @return The album (never null)
154 */
155 public abstract String getAlbum();
156
157 /**
158 * Get the title.
159 *
160 * @return The title (never null)
161 */
162 public abstract String getTitle();
163
164 /**
165 * Get the genre.
166 *
167 * @return The genre (never null)
168 */
169 public abstract String getGenre();
170
171 /**
172 * Get the year.
173 *
174 * @return The year (never null)
175 */
176 public abstract String getYear();
177
178 /**
179 * Get the comment.
180 *
181 * @return The comment (never null)
182 */
183 public abstract String getComment();
184
185 /**
186 * Get the track.
187 *
188 * @return The track (never null)
189 */
190 public abstract String getTrack();
191
192 /**
193 * Read a String of a certain length from the file. It will always use
194 * "ISO-8859-1" encoding!
195 *
196 * @param length Maximum number of bytes to read
197 * @return String that was read
198 * @throws IOException If EOF was already reached
199 */
200 protected String readStringLen( int length )
201 throws IOException {
202 return readStringLen( length, "ISO-8859-1" );
203 }
204
205 /**
206 * Read a String of a certain length from the file. The length will
207 * not be exceeded. No null termination is required. Anyhow an
208 * IOException will be thrown if the EOF was reached before invocation.
209 *
210 * @param length Maximum number of bytes to read
211 * @param charset Charset to be used
212 * @return String that was read
213 * @throws IOException If EOF was already reached
214 */
215 protected String readStringLen( int length, String charset )
216 throws IOException {
217 byte[] buf = new byte[length];
218 int readlength = in.read( buf );
219 if( readlength < 0 ) {
220 throw new IOException( "Unexpected EOF" );
221 }
222 return new String( buf, 0, readlength, charset );
223 }
224
225 /**
226 * Return a string representation of the LTR content.
227 *
228 * @return String representation
229 */
230 public String toString() {
231 StringBuffer buff = new StringBuffer();
232 buff.append( getType() );
233 buff.append( "[ART='" );
234 buff.append( getArtist() );
235 buff.append( "' ALB='" );
236 buff.append( getAlbum() );
237 buff.append( "' TIT='" );
238 buff.append( getTitle() );
239 buff.append( "' TRK='" );
240 buff.append( getTrack() );
241 buff.append( "' GEN='" );
242 buff.append( getGenre() );
243 buff.append( "' YR='" );
244 buff.append( getYear() );
245 buff.append( "' CMT='" );
246 buff.append( getComment() );
247 buff.append( "']" );
248 return buff.toString();
249 }
250
251}
diff --git a/songdbj/net/shredzone/ifish/ltr/LTRmp3.java b/songdbj/net/shredzone/ifish/ltr/LTRmp3.java
deleted file mode 100644
index 1b31c405ba..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/LTRmp3.java
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48
49/**
50 * The Base Class for mp3 decoding of the Lightweight Tag Reader.
51 *
52 * @author Richard Körber &lt;dev@shredzone.de&gt;
53 * @version $Id$
54 */
55public abstract class LTRmp3 extends LTR {
56
57 private final static String[] genres = {
58 //--- Genres as specified in ID3v1 ---
59 "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
60 "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other",
61 "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial",
62 "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack",
63 "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
64 "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
65 "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
66 "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
67 "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
68 "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
69 "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40",
70 "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
71 "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
72 "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
73 "Rock & Roll", "Hard Rock",
74
75 //--- This are WinAmp extensions ---
76 "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebop",
77 "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
78 "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
79 "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
80 "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
81 "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
82 "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
83 "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
84 };
85
86 protected final String charsetV1 = "ISO-8859-1";
87 protected final String charsetV2 = "ISO-8859-1";
88
89 /**
90 * Constructor for the LTRmp3 object
91 *
92 * @param in File to be used
93 * @throws FormatDecodeException Could not decode file
94 */
95 public LTRmp3( RandomAccessFile in )
96 throws FormatDecodeException {
97 super( in );
98 }
99
100 /**
101 * Decode the mp3 numerical Genre code and convert it to a human
102 * readable string. The genre is decoded according to the
103 * specifications found at <a href="http://www.id3.org">www.id3.org</a>,
104 * as well as the WinAmp extensions.
105 *
106 * @param id Genre ID
107 * @return ID String, null if the genre ID was unknown
108 */
109 protected String decodeGenre( int id ) {
110 if( id>=genres.length ) return null;
111 return genres[id];
112 }
113
114 /**
115 * Read an ID3v2 integer. This is a 4 byte big endian value, which is
116 * always not syncsafe.
117 *
118 * @return The integer read.
119 * @throws IOException If there were not enough bytes in the file.
120 */
121 protected int readInt()
122 throws IOException {
123 int val = 0;
124 for( int cnt = 4; cnt > 0; cnt-- ) {
125 val <<= 8;
126 val |= ( in.readByte() & 0xFF );
127 }
128 return val;
129 }
130
131 /**
132 * Read an ID3v2 syncsafe integer. This is a 4 byte big endian value
133 * with the bit 7 of each byte always being 0.
134 *
135 * @return The syncsafe integer read.
136 * @throws IOException If there were not enough bytes in the file.
137 */
138 protected int readSyncsafeInt()
139 throws IOException {
140 int val = 0;
141 for( int cnt = 4; cnt > 0; cnt-- ) {
142 val <<= 7;
143 val |= ( readSyncsafe() & 0x7F );
144 }
145 return val;
146 }
147
148 /**
149 * Read a syncsafe byte. It is made sure that a byte is available in
150 * the file, and that bit 7 is 0. An IOException is thrown otherwise.
151 *
152 * @return The byte read.
153 * @throws IOException If premature EOF was reached or byte was not
154 * syncsafe.
155 */
156 protected byte readSyncsafe()
157 throws IOException {
158 byte read = in.readByte();
159 if(( read & 0x80 ) != 0 ) {
160 throw new IOException( "not syncsafe" );
161 }
162 return read;
163 }
164
165}
diff --git a/songdbj/net/shredzone/ifish/ltr/OggFastFileStream.java b/songdbj/net/shredzone/ifish/ltr/OggFastFileStream.java
deleted file mode 100644
index f86699b0f1..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/OggFastFileStream.java
+++ /dev/null
@@ -1,249 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48import java.util.*;
49
50import de.jarnbjo.ogg.*;
51
52/**
53 * Replacement file reader class. The original J-Ogg FileStream has the
54 * major disadvantage that it reads the entire file, even though we just
55 * need a few byte from it. This FastFileStream will only read as little
56 * information as possible.
57 *
58 * @author Richard Körber &lt;dev@shredzone.de&gt;
59 * @version $Id$
60 */
61public class OggFastFileStream implements PhysicalOggStream {
62 private InputStream sourceStream;
63 private boolean closed = false;
64 private int contentLength = 0;
65 private int position = 0;
66 private HashMap logicalStreams = new HashMap();
67 private OggPage firstPage;
68
69 /**
70 * Constructor for the OggFastFileStream object
71 *
72 * @param in RandomAccessFile to be read
73 * @throws OggFormatException Bad format
74 * @throws IOException IO error
75 */
76 public OggFastFileStream( RandomAccessFile in )
77 throws OggFormatException, IOException {
78 this.sourceStream = new RandomAdapterInputStream( in );
79 contentLength = (int) in.length();
80 firstPage = OggPage.create( sourceStream );
81 position += firstPage.getTotalLength();
82 LogicalOggStreamImpl los = new LogicalOggStreamImpl( this, firstPage.getStreamSerialNumber() );
83 logicalStreams.put( new Integer( firstPage.getStreamSerialNumber() ), los );
84 los.checkFormat( firstPage );
85 }
86
87 /**
88 * Get a collection of the logical streams.
89 *
90 * @return Collection
91 */
92 public Collection getLogicalStreams() {
93 return logicalStreams.values();
94 }
95
96 /**
97 * Checks if the file is open.
98 *
99 * @return true: open, false: closed
100 */
101 public boolean isOpen() {
102 return !closed;
103 }
104
105 /**
106 * Closes the stream
107 *
108 * @throws IOException IO error
109 */
110 public void close()
111 throws IOException {
112 closed = true;
113 sourceStream.close();
114 }
115
116 /**
117 * Get the content length
118 *
119 * @return The content length
120 */
121 public int getContentLength() {
122 return contentLength;
123 }
124
125 /**
126 * Get the current position
127 *
128 * @return Position
129 */
130 public int getPosition() {
131 return position;
132 }
133
134 /**
135 * Get an OggPage.
136 *
137 * @param index Index to be fetched
138 * @return The oggPage value
139 * @throws IOException IO Error
140 */
141 public OggPage getOggPage( int index )
142 throws IOException {
143 if( firstPage != null ) {
144 OggPage tmp = firstPage;
145 firstPage = null;
146 return tmp;
147 } else {
148 OggPage page = OggPage.create( sourceStream );
149 position += page.getTotalLength();
150 return page;
151 }
152 }
153
154 /**
155 * Move the stream to a certain time position.
156 *
157 * @param granulePosition The new position
158 * @throws IOException
159 */
160 public void setTime( long granulePosition )
161 throws IOException {
162 throw new UnsupportedOperationException( "not supported" );
163 }
164
165 /**
166 * Is this FileStream seekable? We pretend we are not, so J-Ogg
167 * will not get some stupid thoughts... ;)
168 *
169 * @return false
170 */
171 public boolean isSeekable() {
172 return false;
173 }
174
175/*--------------------------------------------------------------------*/
176
177 /**
178 * This class repairs a design flaw in JDK1.0. A RandomAccessFile
179 * is not derived from InputStream, though it provides the same API.
180 * This Adapter gives an InputStream view of a Random Access File.
181 * <p>
182 * For a detailed method description, see InputStream.
183 */
184 private static class RandomAdapterInputStream extends InputStream {
185 private RandomAccessFile rf;
186
187 /**
188 * Create a new Adapter.
189 *
190 * @param rf RandomAccessFile to be used
191 */
192 public RandomAdapterInputStream( RandomAccessFile rf ) {
193 this.rf = rf;
194 }
195
196 /**
197 * Read a byte.
198 *
199 * @return Read byte or -1.
200 */
201 public int read() throws IOException {
202 return rf.read();
203 }
204
205 /**
206 * Read a byte array.
207 *
208 * @param b Byte array to be read
209 * @return Number of bytes read or -1
210 */
211 public int read( byte[] b) throws IOException {
212 return rf.read(b);
213 }
214
215 /**
216 * Read into a byte array.
217 *
218 * @param b Byte array to be read
219 * @param off Starting offset
220 * @param len Length
221 * @return Number of bytes read or -1
222 */
223 public int read( byte[] b, int off, int len) throws IOException {
224 return rf.read( b, off, len );
225 }
226
227 /**
228 * Skip a number of bytes in forward direction.
229 *
230 * @param n Number of bytes to skip
231 * @return Number of bytes skipped, or -1
232 */
233 public long skip( long n ) throws IOException {
234 return rf.skipBytes( (int) n );
235 }
236
237 /**
238 * Return the number of available bytes. Here it is the number of
239 * bytes remaining until EOF.
240 *
241 * @return Number of bytes available.
242 */
243 public int available() throws IOException {
244 return (int) (rf.length() - rf.getFilePointer());
245 }
246
247 }
248
249}
diff --git a/songdbj/net/shredzone/ifish/ltr/TagAsf.java b/songdbj/net/shredzone/ifish/ltr/TagAsf.java
deleted file mode 100644
index fc68789345..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/TagAsf.java
+++ /dev/null
@@ -1,170 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48import java.util.List;
49
50import de.jarnbjo.ogg.*;
51import de.jarnbjo.vorbis.*;
52import entagged.audioformats.AudioFile;
53import entagged.audioformats.Tag;
54import entagged.audioformats.asf.AsfFileReader;
55import entagged.audioformats.exceptions.CannotReadException;
56
57/**
58 * Decodes an ASF/WMA stream. It uses parts of the
59 * <a href="http://entagged.sf.net/">Entagged</a> software, which is
60 * copyrighted by the Entagged Development Team, and published under
61 * GPL.
62 * <p>
63 * <em>NOTE</em> that due to the fact that Entagged is GPL, you <em>MUST</em>
64 * remove all entagged sources and this class file if you decide to use
65 * the LGPL or MPL part of the iFish licence!
66 *
67 * @author Richard Körber &lt;dev@shredzone.de&gt;
68 * @version $Id$
69 */
70public class TagAsf extends LTR {
71 private final Tag tag;
72
73 /**
74 * Create a new TagAsf object.
75 *
76 * @param in File to read
77 * @param file Reference to the file itself
78 * @throws FormatDecodeException Couldn't decode this file
79 */
80 public TagAsf( RandomAccessFile in, File file )
81 throws FormatDecodeException {
82 super( in );
83
84 try {
85 final AsfFileReader afr = new AsfFileReader();
86 final AudioFile af = afr.read( file, in );
87 tag = af.getTag();
88 }catch( CannotReadException e ) {
89 throw new FormatDecodeException( "could not decode file: " + e.toString() );
90 }catch( RuntimeException e ) {
91 throw new FormatDecodeException( "error decoding file: " + e.toString() );
92 }
93 }
94
95 /**
96 * Get the type of this file. This is usually the compression format
97 * itself (e.g. "OGG" or "MP3"). If there are different taggings for
98 * this format, the used tag format is appended after a slash (e.g.
99 * "MP3/id3v2").
100 *
101 * @return The type
102 */
103 public String getType() {
104 return "ASF";
105 }
106
107 /**
108 * Get the artist.
109 *
110 * @return The artist (never null)
111 */
112 public String getArtist() {
113 return tag.getFirstArtist().trim();
114 }
115
116 /**
117 * Get the album.
118 *
119 * @return The album (never null)
120 */
121 public String getAlbum() {
122 return tag.getFirstAlbum().trim();
123 }
124
125 /**
126 * Get the title.
127 *
128 * @return The title (never null)
129 */
130 public String getTitle() {
131 return tag.getFirstTitle().trim();
132 }
133
134 /**
135 * Get the genre.
136 *
137 * @return The genre (never null)
138 */
139 public String getGenre() {
140 return tag.getFirstGenre().trim();
141 }
142
143 /**
144 * Get the year.
145 *
146 * @return The year (never null)
147 */
148 public String getYear() {
149 return tag.getFirstYear().trim();
150 }
151
152 /**
153 * Get the comment.
154 *
155 * @return The comment (never null)
156 */
157 public String getComment() {
158 return tag.getFirstComment().trim();
159 }
160
161 /**
162 * Get the track.
163 *
164 * @return The track (never null)
165 */
166 public String getTrack() {
167 return tag.getFirstTrack().trim();
168 }
169
170}
diff --git a/songdbj/net/shredzone/ifish/ltr/TagMp3v1.java b/songdbj/net/shredzone/ifish/ltr/TagMp3v1.java
deleted file mode 100644
index 9d3182260a..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/TagMp3v1.java
+++ /dev/null
@@ -1,184 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48
49/**
50 * Decodes an MP3 file with ID3v1 tag. The file is compliant to the
51 * specifications found at <a href="http://www.id3.org">www.id3.org</a>.
52 *
53 * @author Richard Körber &lt;dev@shredzone.de&gt;
54 * @version $Id$
55 */
56public class TagMp3v1 extends LTRmp3 {
57 private String artist = "";
58 private String comment = "";
59 private String title = "";
60 private String album = "";
61 private String year = "";
62 private String track = "";
63 private String genre = "";
64
65 /**
66 * Create a new TagMp3v1 object.
67 *
68 * @param in File to be read
69 * @throws FormatDecodeException Description of the Exception
70 */
71 public TagMp3v1( RandomAccessFile in )
72 throws FormatDecodeException {
73 super( in );
74
75 try {
76 //--- Decode header ---
77 in.seek( in.length() - 128 ); // To the place where the tag lives
78 if( !readStringLen( 3 ).equals( "TAG" ) ) {
79 throw new FormatDecodeException( "not an id3v1 tag" );
80 }
81
82 title = readStringLen( 30, charsetV1 ).trim();
83 artist = readStringLen( 30, charsetV1 ).trim();
84 album = readStringLen( 30, charsetV1 ).trim();
85 year = readStringLen( 4, charsetV1 ).trim();
86 comment = readStringLen( 28, charsetV1 );
87
88 byte[] sto = new byte[2];
89 in.readFully( sto );
90 if( sto[0] == 0x00 ) {
91 // ID3v1.1
92 track = ( sto[1]>0 ? String.valueOf(sto[1]) : "" );
93 } else {
94 // ID3v1.0
95 comment += new String( sto, charsetV1 );
96 }
97 comment = comment.trim();
98
99 genre = decodeGenre( in.readUnsignedByte() );
100 if( genre==null ) genre="";
101
102 } catch( IOException e ) {
103 throw new FormatDecodeException( "could not decode file: " + e.toString() );
104 }catch( RuntimeException e ) {
105 throw new FormatDecodeException( "error decoding file: " + e.toString() );
106 }
107 }
108
109 /**
110 * Get the type of this file. This is usually the compression format
111 * itself (e.g. "OGG" or "MP3"). If there are different taggings for
112 * this format, the used tag format is appended after a slash (e.g.
113 * "MP3/id3v2").
114 *
115 * @return The type
116 */
117 public String getType() {
118 return "MP3/id3v1";
119 }
120
121 /**
122 * Get the artist.
123 *
124 * @return The artist (never null)
125 */
126 public String getArtist() {
127 return artist;
128 }
129
130 /**
131 * Get the album.
132 *
133 * @return The album (never null)
134 */
135 public String getAlbum() {
136 return album;
137 }
138
139 /**
140 * Get the title.
141 *
142 * @return The title (never null)
143 */
144 public String getTitle() {
145 return title;
146 }
147
148 /**
149 * Get the genre.
150 *
151 * @return The genre (never null)
152 */
153 public String getGenre() {
154 return genre;
155 }
156
157 /**
158 * Get the year.
159 *
160 * @return The year (never null)
161 */
162 public String getYear() {
163 return year;
164 }
165
166 /**
167 * Get the comment.
168 *
169 * @return The comment (never null)
170 */
171 public String getComment() {
172 return comment;
173 }
174
175 /**
176 * Get the track.
177 *
178 * @return The track (never null)
179 */
180 public String getTrack() {
181 return track;
182 }
183
184}
diff --git a/songdbj/net/shredzone/ifish/ltr/TagMp3v2.java b/songdbj/net/shredzone/ifish/ltr/TagMp3v2.java
deleted file mode 100644
index 689dd21618..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/TagMp3v2.java
+++ /dev/null
@@ -1,441 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48import java.util.regex.*;
49
50/**
51 * Decodes an MP3 file with ID3v2 tag. The file is compliant to the
52 * specifications found at <a href="http://www.id3.org">www.id3.org</a>,
53 * V2.4.0 and V2.3.0. ID3 V2.2.0 is handled in a separate tag handler.
54 * Anyhow it has certain limitations regarding tag frames which could
55 * not be used or entirely used to iFish, e.g. multiple genres.
56 *
57 * @author Richard Körber &lt;dev@shredzone.de&gt;
58 * @version $Id$
59 */
60public class TagMp3v2 extends LTRmp3 {
61 private int globalSize;
62 private Pattern patGenre;
63 private boolean v230 = false; // V2.3.0 detected
64
65 private String artist = "";
66 private String comment = "";
67 private String title = "";
68 private String album = "";
69 private String year = "";
70 private String track = "";
71 private String genre = "";
72
73 /**
74 * Create a new TagMp3v2 instance.
75 *
76 * @param in File to be read
77 * @throws FormatDecodeException Couldn't decode this file
78 */
79 public TagMp3v2( RandomAccessFile in )
80 throws FormatDecodeException {
81 super( in );
82
83 patGenre = Pattern.compile( "\\((\\d{1,3})\\).*" );
84
85 try {
86 //--- Decode header ---
87 if( !readStringLen( 3 ).equals( "ID3" ) ) {
88 throw new FormatDecodeException( "not an id3v2 tag" );
89 }
90
91 byte version = in.readByte();
92 byte revision = in.readByte();
93
94 if( version==0xFF || revision==0xFF ) {
95 throw new FormatDecodeException( "not an id3v2 tag" );
96 }
97
98 if( version<=0x02 || version>0x04 ) {
99 throw new FormatDecodeException( "unable to decode ID3v2."+version+"."+revision );
100 }
101
102 byte flags = in.readByte();
103 v230 = (version==0x03);
104 globalSize = readSyncsafeInt() + 10;
105
106 //--- Skip extended header ---
107 if( ( flags & 0x40 ) != 0 ) {
108 int ehsize = readAutoInt();
109 if( ehsize < 6 ) {
110 throw new FormatDecodeException( "extended header too small" );
111 }
112 in.skipBytes( ehsize - 4 );
113 }
114
115 //--- Read all frames ---
116 Frame frm;
117 while( ( frm = readFrame() ) != null ) {
118 String type = frm.getType();
119 String[] answer;
120
121 if( type.equals( "TOPE" ) || type.equals( "TPE1" ) ) {
122
123 answer = frm.getAsStringEnc();
124 artist = (answer.length>0 ? answer[0].trim() : "");
125
126 } else if( type.equals( "COMM" ) ) {
127
128 answer = frm.getAsStringEnc();
129 comment = (answer.length>1 ? answer[1].trim() : "");
130
131 } else if( type.equals( "TIT2" ) ) {
132
133 answer = frm.getAsStringEnc();
134 title =(answer.length>0 ? answer[0].trim() : "");
135
136 } else if( type.equals( "TALB" ) ) {
137
138 answer = frm.getAsStringEnc();
139 album = (answer.length>0 ? answer[0].trim() : "");
140
141 } else if( type.equals( "TYER" ) ) {
142
143 answer = frm.getAsStringEnc();
144 year = (answer.length>0 ? answer[0].trim() : "");
145
146 } else if( type.equals( "TRCK" ) ) {
147
148 answer = frm.getAsStringEnc();
149 track = (answer.length>0 ? answer[0].trim() : "");
150
151 } else if( type.equals( "TCON" ) ) {
152
153 answer = frm.getAsStringEnc();
154 if( answer.length>0 ) {
155 genre = answer[0].trim();
156 Matcher mat = patGenre.matcher( genre );
157 if( mat.matches() ) {
158 genre = decodeGenre( Integer.parseInt( mat.group( 1 ) ) );
159 if( genre==null ) genre="";
160 }
161 }
162 }
163 }
164
165 //--- Footer frame? ---
166 if( ( flags & 0x10 ) != 0 ) {
167 in.skipBytes( 10 ); // Then skip it
168 }
169 // Position is now the start of the MP3 data
170
171 } catch( IOException e ) {
172 throw new FormatDecodeException( "could not decode file: " + e.toString() );
173 }catch( RuntimeException e ) {
174 throw new FormatDecodeException( "error decoding file: " + e.toString() );
175 }
176 }
177
178 /**
179 * Get the type of this file. This is usually the compression format
180 * itself (e.g. "OGG" or "MP3"). If there are different taggings for
181 * this format, the used tag format is appended after a slash (e.g.
182 * "MP3/id3v2").
183 *
184 * @return The type
185 */
186 public String getType() {
187 return ( v230 ? "MP3/id3v2.3.0" : "MP3/id3v2.4.0" );
188 }
189
190 /**
191 * Get the artist.
192 *
193 * @return The artist (never null)
194 */
195 public String getArtist() {
196 return artist;
197 }
198
199 /**
200 * Get the album.
201 *
202 * @return The album (never null)
203 */
204 public String getAlbum() {
205 return album;
206 }
207
208 /**
209 * Get the title.
210 *
211 * @return The title (never null)
212 */
213 public String getTitle() {
214 return title;
215 }
216
217 /**
218 * Get the genre.
219 *
220 * @return The genre (never null)
221 */
222 public String getGenre() {
223 return genre;
224 }
225
226 /**
227 * Get the year.
228 *
229 * @return The year (never null)
230 */
231 public String getYear() {
232 return year;
233 }
234
235 /**
236 * Get the comment.
237 *
238 * @return The comment (never null)
239 */
240 public String getComment() {
241 return comment;
242 }
243
244 /**
245 * Get the track.
246 *
247 * @return The track (never null)
248 */
249 public String getTrack() {
250 return track;
251 }
252
253 /**
254 * Read an ID3v2 integer. This is a 4 byte big endian value, which is
255 * only syncsafe for ID3v2.4 or higher, but not for ID3v2.3.
256 *
257 * @return The integer read.
258 * @throws IOException If there were not enough bytes in the file.
259 */
260 protected int readAutoInt()
261 throws IOException {
262 return( v230 ? readInt() : readSyncsafeInt() );
263 }
264
265 /**
266 * Read a tag frame. A Frame object will be returned, or null if no
267 * more frames were available.
268 *
269 * @return The next frame, or null
270 * @throws IOException If premature EOF was reached.
271 */
272 protected Frame readFrame()
273 throws IOException {
274 if( in.getFilePointer() >= globalSize ) {
275 return null;
276 }
277
278 //--- Get the type ---
279 String type = readStringLen( 4 );
280 if( type.charAt(0)==0 ) { // Optional padding frame
281 in.skipBytes( (int) ( globalSize - in.getFilePointer() ) );// Skip it...
282 return null; // Return null
283 }
284
285 //--- Read the frame ---
286 int size = readAutoInt();
287 byte flag1 = in.readByte();
288 byte flag2 = in.readByte();
289
290 //--- Read the content ---
291 // Stay within reasonable boundaries. If the data part is bigger than
292 // 16K, it's not really useful for us, so we will keep the frame empty.
293 byte[] data = null;
294 if( size<=16384 ) {
295 data = new byte[size];
296 int rlen = in.read( data );
297 if( rlen != size ) {
298 throw new IOException( "unexpected EOF" );
299 }
300 }else {
301 in.skipBytes( size );
302 }
303
304 //--- Return the frame ---
305 return new Frame( type, size, flag1, flag2, data );
306 }
307
308/*--------------------------------------------------------------------*/
309
310 /**
311 * This class contains a ID3v2 frame.
312 */
313 private static class Frame {
314 private final String charset;
315 private final String type;
316// private final int size;
317// private final byte flag1;
318 private final byte flag2;
319 private byte[] data;
320 private boolean decoded = false;
321
322 /**
323 * Constructor for the Frame object
324 *
325 * @param type Frame type
326 * @param size Frame size
327 * @param flag1 Flag 1
328 * @param flag2 Flag 2
329 * @param data Frame content, may be null
330 */
331 public Frame( String type, int size, byte flag1, byte flag2, byte[] data ) {
332 charset = "ISO-8859-1";
333 this.type = type;
334// Currently unused...
335// this.size = size;
336// this.flag1 = flag1;
337 this.flag2 = flag2;
338 this.data = data;
339 }
340
341 /**
342 * Get the type.
343 *
344 * @return The type of this Frame
345 */
346 public String getType() {
347 return type;
348 }
349
350 /**
351 * Return the Frame content as String. This method is to be used for
352 * strings without a leading encoding byte. This machine's default
353 * encoding will be used instead.
354 *
355 * @return Encoded string
356 * @throws FormatDecodeException Could not read or decode frame
357 */
358 public String getAsString()
359 throws FormatDecodeException {
360 if(data==null) return null;
361 decode();
362 return new String( data );
363 }
364
365 /**
366 * Return the Frame content as encoded String. The first byte will
367 * contain the encoding type, following the string itself. Multiple
368 * strings are null-terminated. An array of all strings found, will
369 * be returned.
370 *
371 * @return Array of all strings. Might be an empty array!
372 * @throws FormatDecodeException Could not read or decode frame
373 */
374 public String[] getAsStringEnc()
375 throws FormatDecodeException {
376 if( data==null ) return new String[0];
377 decode();
378 if( data.length==0 ) return new String[0];
379 int len = data.length - 1;
380 String result = "";
381 try {
382 switch ( data[0] ) {
383 case 0x00:
384 result = new String( data, 1, len, charset );
385 break;
386 case 0x01:
387 result = new String( data, 1, len, "UTF-16" );
388 break;
389 case 0x02:
390 result = new String( data, 1, len, "UTF-16BE" );
391 break;
392 case 0x03:
393 result = new String( data, 1, len, "UTF-8" );
394 break;
395 default:
396 throw new FormatDecodeException( "unknown encoding of frame " + type );
397 }
398 }catch( UnsupportedEncodingException e ) {
399 throw new FormatDecodeException( "Java misses a basic encoding!?" );
400 }
401 return result.split( "\0" );
402 }
403
404 /**
405 * Decode a frame, unless already decoded. If the frame was
406 * unsynchronized, it will be synchronized here. Compression and
407 * encryption is not supported yet. You can invoke this method
408 * several times without any effect.
409 *
410 * @throws FormatDecodeException Description of the Exception
411 */
412 private void decode()
413 throws FormatDecodeException {
414 if( decoded ) return;
415 decoded = true;
416
417 if( ( flag2 & 0x02 ) != 0 ) { // Unsynchronize
418 byte decoded[] = new byte[data.length];
419 int pos = 0;
420 for( int ix = 0; ix < data.length - 1; ix++ ) {
421 decoded[pos++] = data[ix];
422 if( data[ix] == 0xFF && data[ix + 1] == 0x00 ) {
423 ix++;
424 }
425 }
426 data = new byte[pos];
427 System.arraycopy( decoded, 0, data, 0, pos );
428 }
429
430 if( ( flag2 & 0x08 ) != 0 ) { // Compression
431 throw new FormatDecodeException( "sorry, compression is not yet supported" );
432 }
433
434 if( ( flag2 & 0x04 ) != 0 ) { // Encryption
435 throw new FormatDecodeException( "sorry, encryption is not yet supported" );
436 }
437 }
438
439 }
440
441}
diff --git a/songdbj/net/shredzone/ifish/ltr/TagMp3v200.java b/songdbj/net/shredzone/ifish/ltr/TagMp3v200.java
deleted file mode 100644
index 28e623f962..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/TagMp3v200.java
+++ /dev/null
@@ -1,373 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48import java.util.regex.*;
49
50/**
51 * Decodes an MP3 file with old ID3v2.00 tag. The file is compliant to the
52 * specifications found at <a href="http://www.id3.org/id3v2-00.txt">www.id3.org</a>.
53 * Only ID3 V2.00 up to v2.2.0 is handled here. Newer versions are separately
54 * handled in TagMp3v2.
55 *
56 * @author Richard Körber &lt;dev@shredzone.de&gt;
57 * @version $Id$
58 */
59public class TagMp3v200 extends LTRmp3 {
60 private int globalSize;
61 private Pattern patGenre;
62
63 private String artist = "";
64 private String comment = "";
65 private String title = "";
66 private String album = "";
67 private String year = "";
68 private String track = "";
69 private String genre = "";
70
71 /**
72 * Create a new TagMp3v200 instance.
73 *
74 * @param in File to be read
75 * @throws FormatDecodeException Couldn't decode this file
76 */
77 public TagMp3v200( RandomAccessFile in )
78 throws FormatDecodeException {
79 super( in );
80
81 patGenre = Pattern.compile( "\\((\\d{1,3})\\).*" );
82
83 try {
84 //--- Decode header ---
85 if( !readStringLen( 3 ).equals( "ID3" ) ) {
86 throw new FormatDecodeException( "not an id3v2 tag" );
87 }
88
89 byte version = in.readByte();
90 byte revision = in.readByte();
91
92 if( version!=0x02 || revision==0xFF ) {
93 throw new FormatDecodeException( "not an id3v2.2.0 tag" );
94 }
95
96 byte flags = in.readByte();
97 globalSize = readSyncsafeInt() + 10;
98
99 //--- Read all frames ---
100 Frame frm;
101 while( ( frm = readFrame() ) != null ) {
102 String type = frm.getType();
103 String[] answer;
104
105 if( type.equals( "TOA" ) || type.equals( "TP1" ) ) {
106
107 answer = frm.getAsStringEnc();
108 artist = (answer.length>0 ? answer[0].trim() : "");
109
110 } else if( type.equals( "COM" ) ) {
111
112 answer = frm.getAsStringEnc();
113 comment = (answer.length>1 ? answer[1].trim() : "");
114
115 } else if( type.equals( "TT2" ) ) {
116
117 answer = frm.getAsStringEnc();
118 title =(answer.length>0 ? answer[0].trim() : "");
119
120 } else if( type.equals( "TAL" ) ) {
121
122 answer = frm.getAsStringEnc();
123 album = (answer.length>0 ? answer[0].trim() : "");
124
125 } else if( type.equals( "TYE" ) ) {
126
127 answer = frm.getAsStringEnc();
128 year = (answer.length>0 ? answer[0].trim() : "");
129
130 } else if( type.equals( "TRK" ) ) {
131
132 answer = frm.getAsStringEnc();
133 track = (answer.length>0 ? answer[0].trim() : "");
134
135 } else if( type.equals( "TCO" ) ) {
136
137 answer = frm.getAsStringEnc();
138 if( answer.length>0 ) {
139 genre = answer[0].trim();
140 Matcher mat = patGenre.matcher( genre );
141 if( mat.matches() ) {
142 genre = decodeGenre( Integer.parseInt( mat.group( 1 ) ) );
143 if( genre==null ) genre="";
144 }
145 }
146 }
147 }
148
149 // Position is now the start of the MP3 data
150
151 } catch( IOException e ) {
152 throw new FormatDecodeException( "could not decode file: " + e.toString() );
153 }catch( RuntimeException e ) {
154 throw new FormatDecodeException( "error decoding file: " + e.toString() );
155 }
156 }
157
158 /**
159 * Get the type of this file. This is usually the compression format
160 * itself (e.g. "OGG" or "MP3"). If there are different taggings for
161 * this format, the used tag format is appended after a slash (e.g.
162 * "MP3/id3v2").
163 *
164 * @return The type
165 */
166 public String getType() {
167 return "MP3/id3v2.2.0";
168 }
169
170 /**
171 * Get the artist.
172 *
173 * @return The artist (never null)
174 */
175 public String getArtist() {
176 return artist;
177 }
178
179 /**
180 * Get the album.
181 *
182 * @return The album (never null)
183 */
184 public String getAlbum() {
185 return album;
186 }
187
188 /**
189 * Get the title.
190 *
191 * @return The title (never null)
192 */
193 public String getTitle() {
194 return title;
195 }
196
197 /**
198 * Get the genre.
199 *
200 * @return The genre (never null)
201 */
202 public String getGenre() {
203 return genre;
204 }
205
206 /**
207 * Get the year.
208 *
209 * @return The year (never null)
210 */
211 public String getYear() {
212 return year;
213 }
214
215 /**
216 * Get the comment.
217 *
218 * @return The comment (never null)
219 */
220 public String getComment() {
221 return comment;
222 }
223
224 /**
225 * Get the track.
226 *
227 * @return The track (never null)
228 */
229 public String getTrack() {
230 return track;
231 }
232
233 /**
234 * Read a tag frame. A Frame object will be returned, or null if no
235 * more frames were available.
236 *
237 * @return The next frame, or null
238 * @throws IOException If premature EOF was reached.
239 */
240 protected Frame readFrame()
241 throws IOException {
242 if( in.getFilePointer() >= globalSize ) {
243 return null;
244 }
245
246 //--- Get the type ---
247 String type = readStringLen( 3 );
248 if( type.charAt(0)==0 ) { // Optional padding frame
249 in.skipBytes( (int) ( globalSize - in.getFilePointer() ) );// Skip it...
250 return null; // Return null
251 }
252
253 //--- Read the frame ---
254 int size = read3Int();
255
256 //--- Read the content ---
257 // Stay within reasonable boundaries. If the data part is bigger than
258 // 16K, it's not really useful for us, so we will keep the frame empty.
259 byte[] data = null;
260 if( size<=16384 ) {
261 data = new byte[size];
262 int rlen = in.read( data );
263 if( rlen != size ) {
264 throw new IOException( "unexpected EOF" );
265 }
266 }else {
267 in.skipBytes( size );
268 }
269
270 //--- Return the frame ---
271 return new Frame( type, size, data );
272 }
273
274 /**
275 * Read an ID3v2 3 byte integer. This is a 3 byte big endian value, which is
276 * always not syncsafe.
277 *
278 * @return The integer read.
279 * @throws IOException If there were not enough bytes in the file.
280 */
281 protected int read3Int()
282 throws IOException {
283 int val = 0;
284 for( int cnt = 3; cnt > 0; cnt-- ) {
285 val <<= 8;
286 val |= ( in.readByte() & 0xFF );
287 }
288 return val;
289 }
290
291/*--------------------------------------------------------------------*/
292
293 /**
294 * This class contains a ID3v2.2.0 frame.
295 */
296 private static class Frame {
297 private final String charset;
298 private final String type;
299// private final int size;
300 private byte[] data;
301
302 /**
303 * Constructor for the Frame object
304 *
305 * @param type Frame type
306 * @param size Frame size
307 * @param data Frame content, may be null
308 */
309 public Frame( String type, int size, byte[] data ) {
310 this.charset = "ISO-8859-1";
311 this.type = type;
312// Currently unused...
313// this.size = size;
314 this.data = data;
315 }
316
317 /**
318 * Get the type.
319 *
320 * @return The type of this Frame
321 */
322 public String getType() {
323 return type;
324 }
325
326 /**
327 * Return the Frame content as String. This method is to be used for
328 * strings without a leading encoding byte. This machine's default
329 * encoding will be used instead.
330 *
331 * @return Encoded string
332 * @throws FormatDecodeException Could not read or decode frame
333 */
334 public String getAsString()
335 throws FormatDecodeException {
336 if(data==null) return null;
337 return new String( data );
338 }
339
340 /**
341 * Return the Frame content as encoded String. The first byte will
342 * contain the encoding type, following the string itself. Multiple
343 * strings are null-terminated. An array of all strings found, will
344 * be returned.
345 *
346 * @return Array of all strings. Might be an empty array!
347 * @throws FormatDecodeException Could not read or decode frame
348 */
349 public String[] getAsStringEnc()
350 throws FormatDecodeException {
351 if(data==null) return new String[0];
352 int len = data.length - 1;
353 String result = "";
354 try {
355 switch ( data[0] ) {
356 case 0x00:
357 result = new String( data, 1, len, charset );
358 break;
359 case 0x01:
360 result = new String( data, 1, len, "UTF-16" );
361 break;
362 default:
363 throw new FormatDecodeException( "unknown encoding of frame " + type );
364 }
365 }catch( UnsupportedEncodingException e ) {
366 throw new FormatDecodeException( "Java misses a basic encoding!?" );
367 }
368 return result.split( "\0" );
369 }
370
371 }
372
373}
diff --git a/songdbj/net/shredzone/ifish/ltr/TagOggVorbis.java b/songdbj/net/shredzone/ifish/ltr/TagOggVorbis.java
deleted file mode 100644
index 45b7401437..0000000000
--- a/songdbj/net/shredzone/ifish/ltr/TagOggVorbis.java
+++ /dev/null
@@ -1,207 +0,0 @@
1/*
2 * iFish -- An iRiver iHP jukebox database creation tool
3 *
4 * Copyright (c) 2004 Richard "Shred" Körber
5 * http://www.shredzone.net/go/ifish
6 *
7 *-----------------------------------------------------------------------
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
10 *
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
20 *
21 * The Original Code is IFISH.
22 *
23 * The Initial Developer of the Original Code is
24 * Richard "Shred" Körber.
25 * Portions created by the Initial Developer are Copyright (C) 2004
26 * the Initial Developer. All Rights Reserved.
27 *
28 * Contributor(s):
29 *
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
41 *
42 * ***** END LICENSE BLOCK *****
43 */
44
45package net.shredzone.ifish.ltr;
46
47import java.io.*;
48import de.jarnbjo.ogg.*;
49import de.jarnbjo.vorbis.*;
50
51/**
52 * Decodes an Ogg Vorbis stream. It uses the
53 * <a href="http://www.j-ogg.de/">J-Ogg</a> library, which is
54 * copyrighted by Tor-Einar Jarnbjo. His licence says that may use and
55 * modify it as will (even commercial), as long as a reference to his
56 * library is stated in the software.
57 * <p>
58 * <b>NOTE:</b> Due to a bug, there is a patch required in the J-Ogg
59 * library. In class de.jarnbjo.vorbis.CommentHeader, private method
60 * <tt>addComment()</tt>, add a line
61 * <pre>
62 * key = key.toUpperCase();
63 * </pre>
64 * after the method declaration header.
65 *
66 * @author Richard Körber &lt;dev@shredzone.de&gt;
67 * @version $Id$
68 */
69public class TagOggVorbis extends LTR {
70 private CommentHeader cmt;
71
72 /**
73 * Create a new TagOggVorbis object.
74 *
75 * @param in File to read
76 * @throws FormatDecodeException Couldn't decode this file
77 */
78 public TagOggVorbis( RandomAccessFile in )
79 throws FormatDecodeException {
80 super( in );
81
82 try {
83 //--- Check for Ogg Signature ---
84 // I expected J-Ogg to do this check, but it has been commented
85 // out because very old ogg files do not seem to have this header.
86 // We will ignore those files.
87 if( !readStringLen(4).equals("OggS") )
88 throw new FormatDecodeException( "not an Ogg file" );
89 in.seek(0);
90
91 //--- Get the Comment Header ---
92 OggFastFileStream fs = new OggFastFileStream(in);
93 LogicalOggStream los = (LogicalOggStream) fs.getLogicalStreams().iterator().next();
94 if( los.getFormat() != LogicalOggStream.FORMAT_VORBIS )
95 throw new FormatDecodeException( "not a plain Ogg Vorbis file" );
96 VorbisStream vos = new VorbisStream( los );
97 cmt = vos.getCommentHeader();
98
99 }catch( OggFormatException e ) {
100 throw new FormatDecodeException( "not an Ogg file" );
101 }catch( VorbisFormatException e ) {
102 throw new FormatDecodeException( "not an Ogg Vorbis file" );
103 }catch( IOException e ) {
104 throw new FormatDecodeException( "could not decode file: " + e.toString() );
105 }catch( RuntimeException e ) {
106 throw new FormatDecodeException( "error decoding file: " + e.toString() );
107 }
108 }
109
110 /**
111 * Get the type of this file. This is usually the compression format
112 * itself (e.g. "OGG" or "MP3"). If there are different taggings for
113 * this format, the used tag format is appended after a slash (e.g.
114 * "MP3/id3v2").
115 *
116 * @return The type
117 */
118 public String getType() {
119 return "OGG";
120 }
121
122 /**
123 * Get the artist.
124 *
125 * @return The artist (never null)
126 */
127 public String getArtist() {
128 String val = cmt.getArtist();
129 if( val==null ) val="";
130 return val.trim();
131 }
132
133 /**
134 * Get the album.
135 *
136 * @return The album (never null)
137 */
138 public String getAlbum() {
139 String val = cmt.getAlbum();
140 if( val==null ) val="";
141 return val.trim();
142 }
143
144 /**
145 * Get the title.
146 *
147 * @return The title (never null)
148 */
149 public String getTitle() {
150 String val = cmt.getTitle();
151 if( val==null ) val="";
152 return val.trim();
153 }
154
155 /**
156 * Get the genre.
157 *
158 * @return The genre (never null)
159 */
160 public String getGenre() {
161 String val = cmt.getGenre();
162 if( val==null ) val="";
163 return val.trim();
164 }
165
166 /**
167 * Get the year.
168 *
169 * @return The year (never null)
170 */
171 public String getYear() {
172 String val = cmt.getDate();
173 if( val==null ) val="";
174 return val.trim();
175 }
176
177 /**
178 * Get the comment.
179 *
180 * @return The comment (never null)
181 */
182 public String getComment() {
183 String val = cmt.getDescription();
184 if( val==null ) {
185 // *sigh* The Ogg Vorbis documentation does not explicitely
186 // state the comment types. So there are some ogg writers
187 // around that use COMMENT instead of DESCRIPTION. We will
188 // use COMMENT if DESCRIPTION was empty.
189 val = cmt.getComment("COMMENT");
190 }
191 if( val==null )
192 val="";
193 return val.trim();
194 }
195
196 /**
197 * Get the track.
198 *
199 * @return The track (never null)
200 */
201 public String getTrack() {
202 String val = cmt.getTrackNumber();
203 if( val==null ) val="";
204 return val.trim();
205 }
206
207}