package org.farng.mp3; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Iterator; import org.farng.mp3.id3.AbstractID3v2; import org.farng.mp3.id3.AbstractID3v2Frame; import org.farng.mp3.id3.ID3v2_4; /** * <h2>Introduction to tags</h2> There are three types of tags found in an MP3 file found in this order: <ol> * <li>ID3v2</li> <li><i><MP3 Data></i><mp3 data=""></mp3></li> <li>Lyrics3</li> <li>ID3v1</li> </ol> In addition, * there are different versions for each tag: <ol> <li>ID3v2 <ul> <li>ID3v2.2 </li> <li>ID3v2.3 </li> <li>ID3v2.4 </li> * </ul> </li> <li>Lyrics3 <ul> <li>Lyrics3v1 </li> <li>Lyrics3v2 </li> </ul> </li> <li>ID3v1 <ul> <li>ID3v1.0 </li> * <li>ID3v1.1 </li> </ul> </li> </ol> * <p/> * <h2>Compiling:</h2> If you have ant, there is a build.xml. Type "ant help" for build options.<BR> If you get from * CVS, you can use IntelliJ and read jid3lib.ipr<br> * <p/> * <h2>Reading:<br> </h2> * <pre> * File sourceFile; * MP3File mp3file = new MP3File(sourceFile); * </pre> * You can also read specific tags: * <pre> * ID3v1_1 tag = new ID3v1_1(sourceFile); * ID3v1 tag = new ID3v1(sourceFile); * ID3v2_4 tag = new ID3v2_4(sourceFile); * ID3v2_3 tag = new ID3v2_3(sourceFile); * ID3v2_2 tag = new ID3v2_2(sourceFile); * Lyrics3v2 tag = new Lyrics3v2(sourceFile); * Lyrics3v1 tag = new Lyrics3v1(sourceFile); * </pre> * <p/> * <h2>Creating:</h2> * <pre> * MP3File mp3file = new MP3File(); * TagOptionSingleton.getInstance().setDefaultSaveMode(TagConstant.MP3_FILE_SAVE_OVERWRITE); * <p/> * // setup id3v1 * id3v1.setAlbum("albumTitle"); * <p/> * // setup id3v2 * AbstractID3v2Frame frame; * AbstractID3v2FrameBody frameBody; * frameBody = new FrameBodyTALB((byte) 0, "albumTitle"); * frame = new ID3v2_4Frame(frameBody); * id3v2.setFrame(frame); * <p/> * // setup lyrics3v2 * Lyrics3v2Field field; * AbstractLyrics3v2FieldBody fieldBody; * fieldBody = new FieldBodyEAL("albumTitle"); * field = new Lyrics3v2Field(fieldBody); * lyrics3.setField(field); * <p/> * // setup filename tag * frameBody = new FrameBodyTALB((byte) 0, "albumTitle"); * frame = new ID3v2_4Frame(frameBody); * filenameId3.setFrame(frame); * TagOptionSingleton.getInstance().setFilenameTagSave(true); * </pre> * Things to note: <ul> <li>The default save mode is "write but do not delete." This means each field in the object will * be saved, but existing fields in the file on disk will not be deleted. The other two are "only append" or "delete and * write from scratch."</li> </ul> * <p/> * <h2>Editing Part 1:</h2> * <p/> * There are convience methods defined in AbstractMP3Tag to edit common data fields. Not all tags have all fields listed * here. * <p/> * <pre> * public abstract String getSongTitle(); * public abstract String getLeadArtist(); * public abstract String getAlbumTitle(); * public abstract String getYearReleased(); * public abstract String getSongComment(); * public abstract String getSongGenre(); * public abstract String getTrackNumberOnAlbum(); * public abstract String getSongLyric(); * public abstract String getAuthorComposer(); * public abstract void setSongTitle(String songTitle); * public abstract void setLeadArtist(String leadArtist); * public abstract void setAlbumTitle(String albumTitle); * public abstract void setYearReleased(String yearReleased); * public abstract void setSongComment(String songComment); * public abstract void setSongGenre(String songGenre); * public abstract void setTrackNumberOnAlbum(String trackNumberOnAlbum); * public abstract void setSongLyric(String songLyrics); * public abstract void setAuthorComposer(String authorComposer); * </pre> * <p/> * <h2>Editing Part 2:</h2> If the field you want is not listed above, you can use these methods. * <pre> * id3v1 = mp3file.getID3v1Tag(); * id3v2 = mp3file.getID3v2Tag(); * lyrics3 = mp3file.getLyrics3Tag(); * </pre> * ID3v1 tags have fixed fields and use accessor methods to change it's properties. <p>ID3v2 tags have multiple * <i>frames</i>. Use this to set the title of the tag.</p> * <pre> * frame = id3v2.getFrame("TIT2"); * ((FrameBodyTIT2) frame.getBody()).setText("New Title"); * </pre> * <p/> * <p>Lyrics3 tags have multiple <i>fields</i>. Use this to set the title of the tag.</p> * <pre> * field = lyrics3.getField("ETT"); * ((FieldBodyETT) field.getBody()).setTitle("New Title"); * </pre> * <p/> * <h2>Writing: </h2> * <pre> * mp3file.save(); * </pre> * You can also save each individual tag through each tags' save() method.<br> <br> * * @author Eric Farng * @version $Revision: 2374 $ */ public abstract class AbstractMP3Tag extends AbstractMP3FileItem { /** * Creates a new AbstractMP3Tag object. */ protected AbstractMP3Tag() { super(); } /** * Creates a new AbstractMP3Tag object. */ protected AbstractMP3Tag(final AbstractMP3Tag copyObject) { super(copyObject); } /** * Appends this tag to the given file. Append means any information this tag contains will be added to the file's * corresponding tag, but it will not replace any fields that the file already has. If the file does not have this * specific tag, a new one will be created. * * @param file MP3 file to append to. * * @throws IOException on any I/O error * @throws TagException on any exception generated by this library. */ public abstract void append(RandomAccessFile file) throws IOException, TagException; /** * removes the specific tag the easiest way. <BR> ID3v1 - cuts the length of the tag <BR> lyrics3 -cuts the length * of the tag, then writes the id3v1 tag if it existed <BR> id3v2 - just overwrites the ID3 tag indicator at the * start of the tag <BR> * * @param file MP3 file to append to. * * @throws IOException on any I/O error */ public abstract void delete(RandomAccessFile file) throws IOException; /** * Overwrites this tag to the given file. Overwrite means any information this tag contains will replace any * existing fields in the file's corresponding tag. If the file does not have this specific tag, a new one will be * created. * * @param file MP3 file to overwrite * * @throws IOException on any I/O error * @throws TagException on any exception generated by this library. */ public abstract void overwrite(RandomAccessFile file) throws IOException, TagException; /** * Looks for this tag. returns true if found. If found, the file pointer is right after the tag start indicator i.e. * "TAG" "LYRICSBEGIN" "ID3" + 2 * * @param file MP3 file to overwrite * * @return returns true if found, false otherwise. * * @throws IOException on any I/O error */ public abstract boolean seek(RandomAccessFile file) throws IOException; /** * Returns true if this tag is a subset of the argument. Both tags are converted into ID3v2_4 tags, and then * compared frame by frame. * * @param abstractMP3Tag superset tag * * @return true if this tag is a subset of the argument */ public boolean isSubsetOf(final AbstractMP3Tag abstractMP3Tag) { final AbstractID3v2 subset = new ID3v2_4(this); final AbstractID3v2 superset = new ID3v2_4(abstractMP3Tag); final Iterator iterator = subset.iterator(); while (iterator.hasNext()) { final AbstractID3v2Frame subsetFrame = (AbstractID3v2Frame) iterator.next(); final String identifier = subsetFrame.getIdentifier(); final AbstractID3v2Frame supersetFrame = superset.getFrame(identifier); if (supersetFrame == null) { return false; } if (!subsetFrame.isSubsetOf(supersetFrame)) { return false; } } return true; } /** * This method does nothing, but is called by subclasses for completeness * * @param abstractMP3Tag tag to overwrite */ public abstract void append(AbstractMP3Tag abstractMP3Tag); /** * Determines whether another object is equal to this tag. It just compares if they are the same class, then calls * <code>super.equals(object)</code>. */ public boolean equals(final Object obj) { return obj instanceof AbstractMP3Tag && super.equals(obj); } public abstract Iterator iterator(); /** * This method does nothing, but is called by subclasses for completeness * * @param abstractMP3Tag tag to overwrite */ public abstract void overwrite(AbstractMP3Tag abstractMP3Tag); /** * This method does nothing, but is called by subclasses for completeness * * @param abstractMP3Tag tag to write to */ public abstract void write(AbstractMP3Tag abstractMP3Tag); public abstract String getSongTitle(); public abstract String getLeadArtist(); public abstract String getAlbumTitle(); public abstract String getYearReleased(); public abstract String getSongComment(); public abstract String getSongGenre(); public abstract String getTrackNumberOnAlbum(); public abstract String getSongLyric(); public abstract String getAuthorComposer(); public abstract void setSongTitle(String songTitle); public abstract void setLeadArtist(String leadArtist); public abstract void setAlbumTitle(String albumTitle); public abstract void setYearReleased(String yearReleased); public abstract void setSongComment(String songComment); public abstract void setSongGenre(String songGenre); public abstract void setTrackNumberOnAlbum(String trackNumberOnAlbum); public abstract void setSongLyric(String songLyrics); public abstract void setAuthorComposer(String authorComposer); }