1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package entagged.audioformats.ogg.util;
20
21 import java.io.UnsupportedEncodingException;
22
23 import entagged.audioformats.generic.TagField;
24 import entagged.audioformats.generic.TagTextField;
25
26 /***
27 * This class encapsulates the name and content of a tag entry in ogg-files.
28 * <br>
29 *
30 * @author @author Raphael Slinckx (KiKiDonK)
31 * @author Christian Laireiter (liree)
32 */
33 public class OggTagField implements TagTextField {
34
35 /***
36 * If <code>true</code>, the id of the current encapsulated tag field is
37 * specified as a common field. <br>
38 * Example is "ARTIST" which should be interpreted by any application as the
39 * artist of the media content. <br>
40 * Will be set during construction with {@link #checkCommon()}.
41 */
42 private boolean common;
43
44 /***
45 * Stores the content of the tag field. <br>
46 */
47 private String content;
48
49 /***
50 * Stores the id (name) of the tag field. <br>
51 */
52 private String id;
53
54 /***
55 * Creates an instance.
56 *
57 * @param raw
58 * Raw byte data of the tagfield.
59 * @throws UnsupportedEncodingException
60 * If the data doesn't conform "UTF-8" specification.
61 */
62 public OggTagField(byte[] raw) throws UnsupportedEncodingException {
63 String field = new String(raw, "UTF-8");
64
65 String[] splitField = field.split("=");
66 if (splitField.length > 1) {
67 this.id = splitField[0].toUpperCase();
68 this.content = splitField[1];
69 } else {
70
71
72 int i = field.indexOf("=");
73 if(i != -1) {
74 this.id = field.substring(0, i+1);
75 this.content = "";
76 }
77 else {
78
79 this.id = "ERRONEOUS";
80 this.content = field;
81 }
82 }
83
84 checkCommon();
85 }
86
87 /***
88 * Creates an instance.
89 *
90 * @param fieldId
91 * ID (name) of the field.
92 * @param fieldContent
93 * Content of the field.
94 */
95 public OggTagField(String fieldId, String fieldContent) {
96 this.id = fieldId.toUpperCase();
97 this.content = fieldContent;
98 checkCommon();
99 }
100
101 /***
102 * This method examines the ID of the current field and modifies
103 * {@link #common}in order to reflect if the tag id is a commonly used one.
104 * <br>
105 */
106 private void checkCommon() {
107 this.common = id.equals("TITLE") || id.equals("ALBUM")
108 || id.equals("ARTIST") || id.equals("GENRE")
109 || id.equals("TRACKNUMBER") || id.equals("DATE")
110 || id.equals("DESCRIPTION") || id.equals("COMMENT")
111 || id.equals("TRACK");
112 }
113
114 /***
115 * This method will copy all bytes of <code>src</code> to <code>dst</code>
116 * at the specified location.
117 *
118 * @param src
119 * bytes to copy.
120 * @param dst
121 * where to copy to.
122 * @param dstOffset
123 * at which position of <code>dst</code> the data should be
124 * copied.
125 */
126 protected void copy(byte[] src, byte[] dst, int dstOffset) {
127
128
129
130
131
132
133 System.arraycopy(src, 0, dst, dstOffset, src.length);
134 }
135
136 /***
137 * (overridden)
138 *
139 * @see entagged.audioformats.generic.TagField#copyContent(entagged.audioformats.generic.TagField)
140 */
141 public void copyContent(TagField field) {
142 if (field instanceof TagTextField)
143 this.content = ((TagTextField) field).getContent();
144 }
145
146 /***
147 * This method will try to return the byte representation of the given
148 * string after it has been converted to the given encoding. <br>
149 *
150 * @param s
151 * The string whose converted bytes should be returned.
152 * @param encoding
153 * The encoding type to which the string should be converted.
154 * @return If <code>encoding</code> is supported the byte data of the
155 * given string is returned in that encoding.
156 * @throws UnsupportedEncodingException
157 * If the requested encoding is not available.
158 */
159 protected byte[] getBytes(String s, String encoding)
160 throws UnsupportedEncodingException {
161 return s.getBytes(encoding);
162 }
163
164 /***
165 * (overridden)
166 *
167 * @see entagged.audioformats.generic.TagTextField#getContent()
168 */
169 public String getContent() {
170 return content;
171 }
172
173 /***
174 * (overridden)
175 *
176 * @see entagged.audioformats.generic.TagTextField#getEncoding()
177 */
178 public String getEncoding() {
179 return "UTF-8";
180 }
181
182 /***
183 * (overridden)
184 *
185 * @see entagged.audioformats.generic.TagField#getId()
186 */
187 public String getId() {
188 return this.id;
189 }
190
191 /***
192 * (overridden)
193 *
194 * @see entagged.audioformats.generic.TagField#getRawContent()
195 */
196 public byte[] getRawContent() throws UnsupportedEncodingException {
197 byte[] size = new byte[4];
198 byte[] idBytes = this.id.getBytes();
199 byte[] contentBytes = getBytes(this.content, "UTF-8");
200 byte[] b = new byte[4 + idBytes.length + 1 + contentBytes.length];
201
202 int length = idBytes.length + 1 + contentBytes.length;
203 size[3] = (byte) ((length & 0xFF000000) >> 24);
204 size[2] = (byte) ((length & 0x00FF0000) >> 16);
205 size[1] = (byte) ((length & 0x0000FF00) >> 8);
206 size[0] = (byte) (length & 0x000000FF);
207
208 int offset = 0;
209 copy(size, b, offset);
210 offset += 4;
211 copy(idBytes, b, offset);
212 offset += idBytes.length;
213 b[offset] = (byte) 0x3D;
214 offset++;
215 copy(contentBytes, b, offset);
216
217 return b;
218 }
219
220 /***
221 * (overridden)
222 *
223 * @see entagged.audioformats.generic.TagField#isBinary()
224 */
225 public boolean isBinary() {
226 return false;
227 }
228
229 /***
230 * (overridden)
231 *
232 * @see entagged.audioformats.generic.TagField#isBinary(boolean)
233 */
234 public void isBinary(boolean b) {
235 if (b) {
236
237 throw new UnsupportedOperationException(
238 "OggTagFields cannot be changed to binary.\n"
239 + "binary data should be stored elsewhere"
240 + " according to Vorbis_I_spec.");
241 }
242 }
243
244 /***
245 * (overridden)
246 *
247 * @see entagged.audioformats.generic.TagField#isCommon()
248 */
249 public boolean isCommon() {
250 return common;
251 }
252
253 /***
254 * (overridden)
255 *
256 * @see entagged.audioformats.generic.TagField#isEmpty()
257 */
258 public boolean isEmpty() {
259 return this.content.equals("");
260 }
261
262 /***
263 * (overridden)
264 *
265 * @see entagged.audioformats.generic.TagTextField#setContent(java.lang.String)
266 */
267 public void setContent(String s) {
268 this.content = s;
269 }
270
271 /***
272 * (overridden)
273 *
274 * @see entagged.audioformats.generic.TagTextField#setEncoding(java.lang.String)
275 */
276 public void setEncoding(String s) {
277 if (s == null || !s.equalsIgnoreCase("UTF-8"))
278 throw new UnsupportedOperationException(
279 "The encoding of OggTagFields cannot be "
280 + "changed.(specified to be UTF-8)");
281 }
282
283 public String toString() {
284 return getContent();
285 }
286 }