EMMA Coverage Report (generated Tue Mar 14 21:50:42 EST 2006)
[all classes][org.farng.mp3.id3]

COVERAGE SUMMARY FOR SOURCE FILE [ID3v2_3.java]

nameclass, %method, %block, %line, %
ID3v2_3.java100% (1/1)88%  (28/32)67%  (906/1350)67%  (200.7/300)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ID3v2_3100% (1/1)88%  (28/32)67%  (906/1350)67%  (200.7/300)
ID3v2_3 (AbstractMP3Tag): void 0%   (0/1)0%   (0/93)0%   (0/26)
overwrite (AbstractMP3Tag): void 0%   (0/1)0%   (0/32)0%   (0/8)
write (AbstractMP3Tag): void 0%   (0/1)0%   (0/32)0%   (0/8)
write (RandomAccessFile): void 0%   (0/1)0%   (0/147)0%   (0/34)
read (RandomAccessFile): void 100% (1/1)56%  (130/232)66%  (27.7/42)
equals (Object): boolean 100% (1/1)74%  (35/47)57%  (8/14)
getSize (): int 100% (1/1)79%  (23/29)70%  (7/10)
setSongComment (String): void 100% (1/1)79%  (23/29)83%  (5/6)
setSongLyric (String): void 100% (1/1)79%  (23/29)83%  (5/6)
getSongLyric (): String 100% (1/1)79%  (27/34)82%  (9/11)
seek (RandomAccessFile): boolean 100% (1/1)98%  (49/50)100% (9/9)
ID3v2_3 (): void 100% (1/1)100% (24/24)100% (9/9)
ID3v2_3 (ID3v2_3): void 100% (1/1)100% (39/39)100% (12/12)
ID3v2_3 (RandomAccessFile): void 100% (1/1)100% (21/21)100% (8/8)
append (AbstractMP3Tag): void 100% (1/1)100% (32/32)100% (8/8)
getAlbumTitle (): String 100% (1/1)100% (18/18)100% (6/6)
getAuthorComposer (): String 100% (1/1)100% (18/18)100% (6/6)
getIdentifier (): String 100% (1/1)100% (2/2)100% (1/1)
getLeadArtist (): String 100% (1/1)100% (18/18)100% (6/6)
getSongComment (): String 100% (1/1)100% (18/18)100% (6/6)
getSongGenre (): String 100% (1/1)100% (18/18)100% (6/6)
getSongTitle (): String 100% (1/1)100% (18/18)100% (6/6)
getTrackNumberOnAlbum (): String 100% (1/1)100% (18/18)100% (6/6)
getYearReleased (): String 100% (1/1)100% (18/18)100% (6/6)
setAlbumTitle (String): void 100% (1/1)100% (27/27)100% (6/6)
setAuthorComposer (String): void 100% (1/1)100% (27/27)100% (6/6)
setLeadArtist (String): void 100% (1/1)100% (27/27)100% (6/6)
setSongGenre (String): void 100% (1/1)100% (27/27)100% (6/6)
setSongTitle (String): void 100% (1/1)100% (27/27)100% (6/6)
setTrackNumberOnAlbum (String): void 100% (1/1)100% (27/27)100% (6/6)
setYearReleased (String): void 100% (1/1)100% (27/27)100% (6/6)
toString (): String 100% (1/1)100% (145/145)100% (13/13)

1package org.farng.mp3.id3;
2 
3import org.farng.mp3.AbstractMP3Tag;
4import org.farng.mp3.InvalidTagException;
5import org.farng.mp3.MP3File;
6import org.farng.mp3.TagConstant;
7import org.farng.mp3.TagException;
8import org.farng.mp3.TagNotFoundException;
9 
10import java.io.IOException;
11import java.io.RandomAccessFile;
12import java.util.Iterator;
13 
14/**
15 * <p class=t> The two biggest design goals were to be able to implement ID3v2 without disturbing old software too much
16 * and that ID3v2 should be as flexible and expandable as possible. </p>
17 * <p/>
18 * <p class=t> The first criterion is met by the simple fact that the <a href="#MPEG">MPEG</a> decoding software uses a
19 * syncsignal, embedded in the audiostream, to 'lock on to' the audio. Since the ID3v2 tag doesn't contain a valid
20 * syncsignal, no software will attempt to play the tag. If, for any reason, coincidence make a syncsignal appear within
21 * the tag it will be taken care of by the 'unsynchronisation scheme' described in <a href="#sec5">section 5</a>. </p>
22 * <p/>
23 * <p class=t> The second criterion has made a more noticeable impact on the design of the ID3v2 tag. It is constructed
24 * as a container for several information blocks, called frames, whose format need not be known to the software that
25 * encounters them. At the start of every frame there is an identifier that explains the frames' format and content, and
26 * a size descriptor that allows software to skip unknown frames. </p>
27 * <p/>
28 * <p class=t> If a total revision of the ID3v2 tag should be needed, there is a version number and a size descriptor in
29 * the ID3v2 header. </p>
30 * <p/>
31 * <p class=t> The ID3 tag described in this document is mainly targeted at files encoded with <a
32 * href="#MPEG">MPEG</a>-1/2 layer I, <a href="#MPEG">MPEG</a>-1/2 layer II, <a href="#MPEG">MPEG</a>-1/2 layer III and
33 * MPEG-2.5, but may work with other types of encoded audio. </p>
34 * <p/>
35 * <p class=t> The bitorder in ID3v2 is most significant bit first (MSB). The byteorder in multibyte numbers is most
36 * significant byte first (e.g. $12345678 would be encoded $12 34 56 78). </p>
37 * <p/>
38 * <p class=t> It is permitted to include padding after all the final frame (at the end of the ID3 tag), making the size
39 * of all the frames together smaller than the size given in the head of the tag. A possible purpose of this padding is
40 * to allow for adding a few additional frames or enlarge existing frames within the tag without having to rewrite the
41 * entire file. The value of the padding bytes must be $00. </p> <p class=t> The ID3v2 tag header, which should be the
42 * first information in the file, is 10 bytes as follows: </p>
43 * <p/>
44 * <p><center> <table border=0> <tr><td nowrap>ID3v2/file identifier</td><td rowspan=4>&nbsp;</td><td
45 * width="100%">"ID3"</td></tr> <tr><td>ID3v2 version</td><td>$03 00</td></tr> <tr><td>ID3v2
46 * flags</td><td>%abc00000</td></tr> <tr><td>ID3v2 size</td><td>4 * %0xxxxxxx</td></tr> </table> </center>
47 * <p/>
48 * <p class=t> The first three bytes of the tag are always "ID3" to indicate that this is an ID3v2 tag, directly
49 * followed by the two version bytes. The first byte of ID3v2 version is it's major version, while the second byte is
50 * its revision number. In this case this is ID3v2.3.0. All revisions are backwards compatible while major versions are
51 * not. If software with ID3v2.2.0 and below support should encounter version three or higher it should simply ignore
52 * the whole tag. Version and revision will never be $FF. </p>
53 * <p/>
54 * <p class=t> The version is followed by one the ID3v2 flags field, of which currently only three flags are used. </p>
55 * <p/>
56 * <p class=t> a - Unsynchronisation </p>
57 * <p/>
58 * <p class=ind> Bit 7 in the 'ID3v2 flags' indicates whether or not unsynchronisation is used (see <a
59 * href="#sec5">section 5</a> for details); a set bit indicates usage.</p>
60 * <p/>
61 * <p class=t> b - Extended header </p>
62 * <p/>
63 * <p class=ind> The second bit (bit 6) indicates whether or not the header is followed by an extended header. The
64 * extended header is described in <a href="#sec3.2">section 3.2</a>. </p>
65 * <p/>
66 * <p class=t> c - Experimental indicator </p>
67 * <p/>
68 * <p class=ind> The third bit (bit 5) should be used as an 'experimental indicator'. This flag should always be set
69 * when the tag is in an experimental stage. </p>
70 * <p/>
71 * <p class=t> All the other flags should be cleared. If one of these undefined flags are set that might mean that the
72 * tag is not readable for a parser that does not know the flags function. </p>
73 * <p/>
74 * <p class=t> The ID3v2 tag size is encoded with four bytes where the most significant bit (bit 7) is set to zero in
75 * every byte, making a total of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is represented as $00 00
76 * 02 01. </p>
77 * <p/>
78 * <p class=t> The ID3v2 tag size is the size of the complete tag after unsychronisation, including padding, excluding
79 * the header but not excluding the extended header (total tag size - 10). Only 28 bits (representing up to 256MB) are
80 * used in the size description to avoid the introducuction of 'false syncsignals'. </p>
81 * <p/>
82 * <p class=t> An ID3v2 tag can be detected with the following pattern:<br> $49 44 33 yy yy xx zz zz zz zz<br> Where yy
83 * is less than $FF, xx is the 'flags' byte and zz is less than $80. </p>
84 *
85 * @author Eric Farng
86 * @version $Revision: 1.5 $
87 */
88public class ID3v2_3 extends ID3v2_2 {
89 
90    protected boolean crcDataFlag = false;
91    protected boolean experimental = false;
92    protected boolean extended = false;
93    protected int crcData = 0;
94    protected int paddingSize = 0;
95 
96    /**
97     * Creates a new ID3v2_3 object.
98     */
99    public ID3v2_3() {
100        setMajorVersion((byte) 2);
101        setRevision((byte) 3);
102    }
103 
104    /**
105     * Creates a new ID3v2_3 object.
106     */
107    public ID3v2_3(final ID3v2_3 copyObject) {
108        super(copyObject);
109        this.crcDataFlag = copyObject.crcDataFlag;
110        this.experimental = copyObject.experimental;
111        this.extended = copyObject.extended;
112        this.crcData = copyObject.crcData;
113        this.paddingSize = copyObject.paddingSize;
114    }
115 
116    /**
117     * Creates a new ID3v2_3 object.
118     */
119    public ID3v2_3(final AbstractMP3Tag mp3tag) {
120        if (mp3tag != null) {
121            final ID3v2_4 convertedTag;
122            if ((mp3tag instanceof ID3v2_4 == false) && (mp3tag instanceof ID3v2_3 == true)) {
123                throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument");
124            }
125            if (mp3tag instanceof ID3v2_4) {
126                convertedTag = (ID3v2_4) mp3tag;
127            } else {
128                convertedTag = new ID3v2_4(mp3tag);
129            }
130            this.extended = convertedTag.extended;
131            this.experimental = convertedTag.experimental;
132            this.crcDataFlag = convertedTag.crcDataFlag;
133            this.crcData = convertedTag.crcData;
134            this.paddingSize = convertedTag.paddingSize;
135            this.compression = convertedTag.compression;
136            this.unsynchronization = convertedTag.unsynchronization;
137            final AbstractID3v2 id3tag = convertedTag;
138            final Iterator iterator = id3tag.getFrameIterator();
139            AbstractID3v2Frame frame;
140            ID3v2_3Frame newFrame;
141            while (iterator.hasNext()) {
142                frame = (AbstractID3v2Frame) iterator.next();
143                newFrame = new ID3v2_3Frame(frame);
144                this.setFrame(newFrame);
145            }
146        }
147    }
148 
149    /**
150     * Creates a new ID3v2_3 object.
151     */
152    public ID3v2_3(final RandomAccessFile file) throws TagException, IOException {
153        this.read(file);
154    }
155 
156    public String getIdentifier() {
157        return "ID3v2.30";
158    }
159 
160    public int getSize() {
161        int size = 3 + 2 + 1 + 4;
162        if (this.extended) {
163            if (this.crcDataFlag) {
164                size += (4 + 2 + 4 + 4);
165            } else {
166                size += (4 + 2 + 4);
167            }
168        }
169        final Iterator iterator = this.getFrameIterator();
170        AbstractID3v2Frame frame;
171        while (iterator.hasNext()) {
172            frame = (AbstractID3v2Frame) iterator.next();
173            size += frame.getSize();
174        }
175        return size;
176    }
177 
178    public void append(final AbstractMP3Tag tag) {
179        if (tag instanceof ID3v2_3) {
180            this.experimental = ((ID3v2_3) tag).experimental;
181            this.extended = ((ID3v2_3) tag).extended;
182            this.crcDataFlag = ((ID3v2_3) tag).crcDataFlag;
183            this.paddingSize = ((ID3v2_3) tag).paddingSize;
184            this.crcData = ((ID3v2_3) tag).crcData;
185        }
186        super.append(tag);
187    }
188 
189    public boolean equals(final Object obj) {
190        if ((obj instanceof ID3v2_3) == false) {
191            return false;
192        }
193        final ID3v2_3 id3v2_3 = (ID3v2_3) obj;
194        if (this.crcData != id3v2_3.crcData) {
195            return false;
196        }
197        if (this.crcDataFlag != id3v2_3.crcDataFlag) {
198            return false;
199        }
200        if (this.experimental != id3v2_3.experimental) {
201            return false;
202        }
203        if (this.extended != id3v2_3.extended) {
204            return false;
205        }
206        if (this.paddingSize != id3v2_3.paddingSize) {
207            return false;
208        }
209        return super.equals(obj);
210    }
211 
212    public void overwrite(final AbstractMP3Tag tag) {
213        if (tag instanceof ID3v2_3) {
214            this.experimental = ((ID3v2_3) tag).experimental;
215            this.extended = ((ID3v2_3) tag).extended;
216            this.crcDataFlag = ((ID3v2_3) tag).crcDataFlag;
217            this.paddingSize = ((ID3v2_3) tag).paddingSize;
218            this.crcData = ((ID3v2_3) tag).crcData;
219        }
220        super.overwrite(tag);
221    }
222 
223    public void read(final RandomAccessFile file) throws TagException, IOException {
224        final int size;
225        final byte[] buffer = new byte[4];
226        if (seek(file) == false) {
227            throw new TagNotFoundException(getIdentifier() + " tag not found");
228        }
229 
230        // read the major and minor @version number & flags byte
231        file.read(buffer, 0, 3);
232        if ((buffer[0] != 3) || (buffer[1] != 0)) {
233            throw new TagNotFoundException(getIdentifier() + " tag not found");
234        }
235        setMajorVersion(buffer[0]);
236        setRevision(buffer[1]);
237        this.unsynchronization = (buffer[2] & TagConstant.MASK_V23_UNSYNCHRONIZATION) != 0;
238        this.extended = (buffer[2] & TagConstant.MASK_V23_EXTENDED_HEADER) != 0;
239        this.experimental = (buffer[2] & TagConstant.MASK_V23_EXPERIMENTAL) != 0;
240 
241        // read the size
242        file.read(buffer, 0, 4);
243        size = byteArrayToSize(buffer);
244        final long filePointer = file.getFilePointer();
245        if (this.extended) {
246            // int is 4 bytes.
247            final int extendedHeaderSize = file.readInt();
248 
249            // the extended header is only 6 or 10 bytes.
250            if (extendedHeaderSize != 6 && extendedHeaderSize != 10) {
251                throw new InvalidTagException("Invalid Extended Header Size.");
252            }
253            file.read(buffer, 0, 2);
254            this.crcDataFlag = (buffer[0] & TagConstant.MASK_V23_CRC_DATA_PRESENT) != 0;
255 
256            // if it's 10 bytes, the CRC flag must be set
257            // and if it's 6 bytes, it must not be set
258            if (((extendedHeaderSize == 10) && (this.crcDataFlag == false)) ||
259                ((extendedHeaderSize == 6) && (this.crcDataFlag == true))) {
260                throw new InvalidTagException("CRC Data flag not set correctly.");
261            }
262            this.paddingSize = file.readInt();
263            if ((extendedHeaderSize == 10) && this.crcDataFlag) {
264                this.crcData = file.readInt();
265            }
266        }
267        ID3v2_3Frame next;
268        this.clearFrameMap();
269 
270        // read all the frames.
271        this.setFileReadBytes(size);
272        AbstractID3v2.resetPaddingCounter();
273        while ((file.getFilePointer() - filePointer) <= size) {
274            try {
275                next = new ID3v2_3Frame(file);
276                final String id = next.getIdentifier();
277                if (this.hasFrame(id)) {
278                    this.appendDuplicateFrameId(id + "; ");
279                    this.incrementDuplicateBytes(this.getFrame(id).getSize());
280                }
281                this.setFrame(next);
282            } catch (InvalidTagException ex) {
283                if (ex.getMessage().equals("Found empty frame")) {
284                    this.incrementEmptyFrameBytes(10);
285                } else {
286                    this.incrementInvalidFrameBytes();
287                }
288            }
289        }
290        this.setPaddingSize(getPaddingCounter());
291    }
292 
293    public boolean seek(final RandomAccessFile file) throws IOException {
294        final byte[] buffer = new byte[3];
295        file.seek(0);
296 
297        // read the tag if it exists
298        file.read(buffer, 0, 3);
299        final String tag = new String(buffer, 0, 3);
300        if (tag.equals("ID3") == false) {
301            return false;
302        }
303 
304        // read the major and minor @version number
305        file.read(buffer, 0, 2);
306 
307        // read back the @version bytes so we can read and save them later
308        file.seek(file.getFilePointer() - 2);
309        return ((buffer[0] == 3) && (buffer[1] == 0));
310    }
311 
312    public String toString() {
313        final Iterator iterator = this.getFrameIterator();
314        AbstractID3v2Frame frame;
315        String str = getIdentifier() + " " + this.getSize() + "\n";
316        str += ("compression        = " + this.compression + "\n");
317        str += ("unsynchronization  = " + this.unsynchronization + "\n");
318        str += ("crcData            = " + this.crcData + "\n");
319        str += ("crcDataFlag        = " + this.crcDataFlag + "\n");
320        str += ("experimental       = " + this.experimental + "\n");
321        str += ("extended           = " + this.extended + "\n");
322        str += ("paddingSize        = " + this.paddingSize + "\n");
323        while (iterator.hasNext()) {
324            frame = (ID3v2_3Frame) iterator.next();
325            str += (frame.toString() + "\n");
326        }
327        return str + "\n";
328    }
329 
330    public void write(final AbstractMP3Tag tag) {
331        if (tag instanceof ID3v2_3) {
332            this.experimental = ((ID3v2_3) tag).experimental;
333            this.extended = ((ID3v2_3) tag).extended;
334            this.crcDataFlag = ((ID3v2_3) tag).crcDataFlag;
335            this.paddingSize = ((ID3v2_3) tag).paddingSize;
336            this.crcData = ((ID3v2_3) tag).crcData;
337        }
338        super.write(tag);
339    }
340 
341    public void write(final RandomAccessFile file) throws IOException {
342        final String str;
343        final Iterator iterator;
344        final byte[] buffer = new byte[6];
345        final MP3File mp3 = new MP3File();
346        mp3.seekMP3Frame(file);
347        final long mp3start = file.getFilePointer();
348        file.seek(0);
349        ID3v2_3Frame frame;
350        str = "ID3";
351        for (int i = 0; i < str.length(); i++) {
352            buffer[i] = (byte) str.charAt(i);
353        }
354        buffer[3] = 3;
355        buffer[4] = 0;
356        if (this.unsynchronization) {
357            buffer[5] |= TagConstant.MASK_V23_UNSYNCHRONIZATION;
358        }
359        if (this.extended) {
360            buffer[5] |= TagConstant.MASK_V23_EXTENDED_HEADER;
361        }
362        if (this.experimental) {
363            buffer[5] |= TagConstant.MASK_V23_EXPERIMENTAL;
364        }
365        file.write(buffer);
366 
367        // write size
368        file.write(sizeToByteArray((int) mp3start - 10));
369        if (this.extended) {
370            if (this.crcDataFlag) {
371                file.writeInt(10);
372                buffer[0] = 0;
373                buffer[0] |= TagConstant.MASK_V23_CRC_DATA_PRESENT;
374                file.write(buffer, 0, 2);
375                file.writeInt(this.paddingSize);
376                file.writeInt(this.crcData);
377            } else {
378                file.writeInt(6);
379                file.write(buffer, 0, 2);
380                file.writeInt(this.paddingSize);
381            }
382        }
383 
384        // write all frames
385        iterator = this.getFrameIterator();
386        while (iterator.hasNext()) {
387            frame = (ID3v2_3Frame) iterator.next();
388            frame.write(file);
389        }
390    }
391 
392    public String getSongTitle() {
393        String text = "";
394        AbstractID3v2Frame frame = getFrame("TIT2");
395        if (frame != null) {
396            FrameBodyTIT2 body = (FrameBodyTIT2) frame.getBody();
397            text = body.getText();
398        }
399        return text.trim();
400    }
401 
402    public String getLeadArtist() {
403        String text = "";
404        AbstractID3v2Frame frame = getFrame("TPE1");
405        if (frame != null) {
406            FrameBodyTPE1 body = (FrameBodyTPE1) frame.getBody();
407            text = body.getText();
408        }
409        return text.trim();
410    }
411 
412    public String getAlbumTitle() {
413        String text = "";
414        AbstractID3v2Frame frame = getFrame("TALB");
415        if (frame != null) {
416            FrameBodyTALB body = (FrameBodyTALB) frame.getBody();
417            text = body.getText();
418        }
419        return text.trim();
420    }
421 
422    public String getYearReleased() {
423        String text = "";
424        AbstractID3v2Frame frame = getFrame("TYER");
425        if (frame != null) {
426            FrameBodyTYER body = (FrameBodyTYER) frame.getBody();
427            text = body.getText();
428        }
429        return text.trim();
430    }
431 
432    public String getSongComment() {
433        String text = "";
434        AbstractID3v2Frame frame = getFrame("COMM" + ((char) 0) + "eng" + ((char) 0) + "");
435        if (frame != null) {
436            FrameBodyCOMM body = (FrameBodyCOMM) frame.getBody();
437            text = body.getText();
438        }
439        return text.trim();
440    }
441 
442    public String getSongGenre() {
443        String text = "";
444        AbstractID3v2Frame frame = getFrame("TCON");
445        if (frame != null) {
446            FrameBodyTCON body = (FrameBodyTCON) frame.getBody();
447            text = body.getText();
448        }
449        return text.trim();
450    }
451 
452    public String getTrackNumberOnAlbum() {
453        String text = "";
454        AbstractID3v2Frame frame = getFrame("TRCK");
455        if (frame != null) {
456            FrameBodyTRCK body = (FrameBodyTRCK) frame.getBody();
457            text = body.getText();
458        }
459        return text.trim();
460    }
461 
462    public String getSongLyric() {
463        String text = "";
464        AbstractID3v2Frame frame = getFrame("SYLT");
465        if (frame != null) {
466            FrameBodySYLT body = (FrameBodySYLT) frame.getBody();
467            text = body.getLyric();
468        }
469        if (text == "") {
470            frame = getFrame("USLT" + ((char) 0) + "eng" + ((char) 0) + "");
471            if (frame != null) {
472                FrameBodyUSLT body = (FrameBodyUSLT) frame.getBody();
473                text = body.getLyric();
474            }
475        }
476        return text.trim();
477    }
478 
479    public String getAuthorComposer() {
480        String text = "";
481        AbstractID3v2Frame frame = getFrame("TCOM");
482        if (frame != null) {
483            FrameBodyTCOM body = (FrameBodyTCOM) frame.getBody();
484            text = body.getText();
485        }
486        return text.trim();
487    }
488 
489    public void setSongTitle(String songTitle) {
490        AbstractID3v2Frame field = getFrame("TIT2");
491        if (field == null) {
492            field = new ID3v2_3Frame(new FrameBodyTIT2((byte) 0, songTitle.trim()));
493            setFrame(field);
494        } else {
495            ((FrameBodyTIT2) field.getBody()).setText(songTitle.trim());
496        }
497    }
498 
499    public void setLeadArtist(String leadArtist) {
500        AbstractID3v2Frame field = getFrame("TPE1");
501        if (field == null) {
502            field = new ID3v2_3Frame(new FrameBodyTPE1((byte) 0, leadArtist.trim()));
503            setFrame(field);
504        } else {
505            ((FrameBodyTPE1) field.getBody()).setText(leadArtist.trim());
506        }
507    }
508 
509    public void setAlbumTitle(String albumTitle) {
510        AbstractID3v2Frame field = getFrame("TALB");
511        if (field == null) {
512            field = new ID3v2_3Frame(new FrameBodyTALB((byte) 0, albumTitle.trim()));
513            setFrame(field);
514        } else {
515            ((FrameBodyTALB) field.getBody()).setText(albumTitle.trim());
516        }
517    }
518 
519    public void setYearReleased(String yearReleased) {
520        AbstractID3v2Frame field = getFrame("TYER");
521        if (field == null) {
522            field = new ID3v2_3Frame(new FrameBodyTYER((byte) 0, yearReleased.trim()));
523            setFrame(field);
524        } else {
525            ((FrameBodyTYER) field.getBody()).setText(yearReleased.trim());
526        }
527    }
528 
529    public void setSongComment(String songComment) {
530        AbstractID3v2Frame field = getFrame("COMM");
531        if (field == null) {
532            field = new ID3v2_3Frame(new FrameBodyCOMM((byte) 0, "ENG", "", songComment.trim()));
533            setFrame(field);
534        } else {
535            ((FrameBodyCOMM) field.getBody()).setText(songComment.trim());
536        }
537    }
538 
539    public void setSongGenre(String songGenre) {
540        AbstractID3v2Frame field = getFrame("TCON");
541        if (field == null) {
542            field = new ID3v2_3Frame(new FrameBodyTCON((byte) 0, songGenre.trim()));
543            setFrame(field);
544        } else {
545            ((FrameBodyTCON) field.getBody()).setText(songGenre.trim());
546        }
547    }
548 
549    public void setTrackNumberOnAlbum(String trackNumberOnAlbum) {
550        AbstractID3v2Frame field = getFrame("TRCK");
551        if (field == null) {
552            field = new ID3v2_3Frame(new FrameBodyTRCK((byte) 0, trackNumberOnAlbum.trim()));
553            setFrame(field);
554        } else {
555            ((FrameBodyTRCK) field.getBody()).setText(trackNumberOnAlbum.trim());
556        }
557    }
558 
559    public void setSongLyric(String songLyrics) {
560        AbstractID3v2Frame field = getFrame("SYLT");
561        if (field == null) {
562            field = new ID3v2_3Frame(new FrameBodyUSLT((byte) 0, "ENG", "", songLyrics.trim()));
563            setFrame(field);
564        } else {
565            ((FrameBodyUSLT) field.getBody()).setLyric(songLyrics.trim());
566        }
567    }
568 
569    public void setAuthorComposer(String authorComposer) {
570        AbstractID3v2Frame field = getFrame("TCOM");
571        if (field == null) {
572            field = new ID3v2_3Frame(new FrameBodyTCOM((byte) 0, authorComposer.trim()));
573            setFrame(field);
574        } else {
575            ((FrameBodyTCOM) field.getBody()).setText(authorComposer.trim());
576        }
577    }
578}

[all classes][org.farng.mp3.id3]
EMMA 2.0.5312 (C) Vladimir Roubtsov