diff --git a/pom.xml b/pom.xml index 59f1b8e..d3706b6 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,14 @@ maven-eclipse-repo http://maven-eclipse.github.io/maven + + + + jaudiotagger-repository + https://dl.bintray.com/ijabz/maven + + + @@ -216,6 +224,12 @@ test + + net.jthink + jaudiotagger + 2.2.3 + + com.opencsv opencsv diff --git a/src/main/help/index.html b/src/main/help/index.html index c4429e3..1d84dc5 100644 --- a/src/main/help/index.html +++ b/src/main/help/index.html @@ -62,9 +62,9 @@ -

Help

-

This may stop working at any time, due to changes in Audible systems or web site. If this happens, check for an update.

-

No technical support is provided. Use at your own risk. Open Source additions are welcome.

-

Suggestions welcome by sending issue or pull request.

+

Additional Help

+

This may stop working at any time, due to changes in Audible systems or web site. If this happens, check for an update or open issues.

+

No technical support is provided. Open Source additions are welcome.

+

Suggestions welcome by creating an issue or submitting a pull request.

diff --git a/src/main/java/org/jaudiotagger/FileConstants.java b/src/main/java/org/jaudiotagger/FileConstants.java deleted file mode 100644 index 5f6763d..0000000 --- a/src/main/java/org/jaudiotagger/FileConstants.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @author : Paul Taylor - *

- * Version @version:$Id: FileConstants.java 520 2008-01-01 15:16:38Z paultaylor $ - *

- * Jaudiotagger Copyright (C)2004,2005 - *

- * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

- * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

- * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

- * Description: - */ -package org.jaudiotagger; - -/** - * Definitions of the bit used when reading file format from file - */ -public interface FileConstants { - /** - * defined for convenience - */ - int BIT7 = 0x80; - /** - * defined for convenience - */ - int BIT6 = 0x40; - /** - * defined for convenience - */ - int BIT5 = 0x20; - /** - * defined for convenience - */ - int BIT4 = 0x10; - /** - * defined for convenience - */ - int BIT3 = 0x08; - /** - * defined for convenience - */ - int BIT2 = 0x04; - /** - * defined for convenience - */ - int BIT1 = 0x02; - /** - * defined for convenience - */ - int BIT0 = 0x01; -} diff --git a/src/main/java/org/jaudiotagger/audio/AudioFile.java b/src/main/java/org/jaudiotagger/audio/AudioFile.java deleted file mode 100644 index 3ce4930..0000000 --- a/src/main/java/org/jaudiotagger/audio/AudioFile.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio; - -import org.jaudiotagger.audio.aiff.AiffTag; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.audio.real.RealTag; -import org.jaudiotagger.audio.wav.WavTag; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.asf.AsfTag; -import org.jaudiotagger.tag.flac.FlacTag; -import org.jaudiotagger.tag.mp4.Mp4Tag; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.logging.Logger; - -/** - *

This is the main object manipulated by the user representing an audiofile, its properties and its tag.

- *

The prefered way to obtain an AudioFile is to use the AudioFileIO.read(File) method.

- *

The AudioFile contains every properties associated with the file itself (no meta-data), like the bitrate, the sampling rate, the encoding audioHeaders, etc.

- *

To get the meta-data contained in this file you have to get the Tag of this AudioFile

- * - * @author Raphael Slinckx - * @version $Id: AudioFile.java 1067 2012-10-17 18:01:32Z garymcgath $ - * @see AudioFileIO - * @see Tag - * @since v0.01 - */ -public class AudioFile { - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio"); - - /** - * The physical file that this instance represents. - */ - protected File file; - - /** - * The Audio header info - */ - protected AudioHeader audioHeader; - - /** - * The tag - */ - protected Tag tag; - - public AudioFile() { - - } - - /** - *

These constructors are used by the different readers, users should not use them, but use the AudioFileIO.read(File) method instead !.

- *

Create the AudioFile representing file f, the encoding audio headers and containing the tag

- * - * @param f The file of the audio file - * @param audioHeader the encoding audioHeaders over this file - * @param tag the tag contained in this file or null if no tag exists - */ - public AudioFile(File f, AudioHeader audioHeader, Tag tag) { - this.file = f; - this.audioHeader = audioHeader; - this.tag = tag; - } - - - /** - *

These constructors are used by the different readers, users should not use them, but use the AudioFileIO.read(File) method instead !.

- *

Create the AudioFile representing file denoted by pathnames, the encoding audio Headers and containing the tag

- * - * @param s The pathname of the audio file - * @param audioHeader the encoding audioHeaders over this file - * @param tag the tag contained in this file - */ - public AudioFile(String s, AudioHeader audioHeader, Tag tag) { - this.file = new File(s); - this.audioHeader = audioHeader; - this.tag = tag; - } - - /** - * @param file - * @return filename with audioFormat separator stripped off. - */ - public static String getBaseFilename(File file) { - int index = file.getName().toLowerCase().lastIndexOf("."); - if (index > 0) { - return file.getName().substring(0, index); - } - return file.getName(); - } - - /** - *

Write the tag contained in this AudioFile in the actual file on the disk, this is the same as calling the AudioFileIO.write(this) method.

- * - * @throws CannotWriteException If the file could not be written/accessed, the extension wasn't recognized, or other IO error occured. - * @see AudioFileIO - */ - public void commit() throws CannotWriteException { - AudioFileIO.write(this); - } - - /** - * Retrieve the physical file - * - * @return - */ - public File getFile() { - return file; - } - - /** - * Set the file to store the info in - * - * @param file - */ - public void setFile(File file) { - this.file = file; - } - - /** - * Return audio header information - * - * @return - */ - public AudioHeader getAudioHeader() { - return audioHeader; - } - - /** - *

Returns the tag contained in this AudioFile, the Tag contains any useful meta-data, like - * artist, album, title, etc. If the file does not contain any tag the null is returned. Some audio formats do - * not allow there to be no tag so in this case the reader would return an empty tag whereas for others such - * as mp3 it is purely optional. - * - * @return Returns the tag contained in this AudioFile, or null if no tag exists. - */ - public Tag getTag() { - return tag; - } - - /** - * Assign a tag to this audio file - * - * @param tag Tag to be assigned - */ - public void setTag(Tag tag) { - this.tag = tag; - } - - /** - *

Returns a multi-line string with the file path, the encoding audioHeader, and the tag contents.

- * - * @return A multi-line string with the file path, the encoding audioHeader, and the tag contents. - * TODO Maybe this can be changed ? - */ - public String toString() { - return "AudioFile " + getFile().getAbsolutePath() - + " --------\n" + audioHeader.toString() + "\n" + ((tag == null) ? "" : tag.toString()) + "\n-------------------"; - } - - /** - * Check does file exist - * - * @param file - * @throws FileNotFoundException if file not found - */ - public void checkFileExists(File file) throws FileNotFoundException { - logger.config("Reading file:" + "path" + file.getPath() + ":abs:" + file.getAbsolutePath()); - if (!file.exists()) { - logger.severe("Unable to find:" + file.getPath()); - throw new FileNotFoundException(ErrorMessage.UNABLE_TO_FIND_FILE.getMsg(file.getPath())); - } - } - - /** - * Checks the file is accessible with the correct permissions, otherwise exception occurs - * - * @param file - * @param readOnly - * @return - * @throws ReadOnlyFileException - * @throws FileNotFoundException - */ - protected RandomAccessFile checkFilePermissions(File file, boolean readOnly) throws ReadOnlyFileException, FileNotFoundException { - RandomAccessFile newFile; - - checkFileExists(file); - - // Unless opened as readonly the file must be writable - if (readOnly) { - newFile = new RandomAccessFile(file, "r"); - } else { - if (!file.canWrite()) { - logger.severe("Unable to write:" + file.getPath()); - throw new ReadOnlyFileException(ErrorMessage.NO_PERMISSIONS_TO_WRITE_TO_FILE.getMsg(file.getPath())); - } - newFile = new RandomAccessFile(file, "rws"); - } - return newFile; - } - - /** - * Optional debugging method. Must override to do anything interesting. - * - * @return Empty string. - */ - public String displayStructureAsXML() { - return ""; - } - - /** - * Optional debugging method. Must override to do anything interesting. - * - * @return - */ - public String displayStructureAsPlainText() { - return ""; - } - - /** - * Create Default Tag - * - * @return - */ - public Tag createDefaultTag() { - if (SupportedFileFormat.FLAC.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new FlacTag(VorbisCommentTag.createNewTag(), new ArrayList()); - } else if (SupportedFileFormat.OGG.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return VorbisCommentTag.createNewTag(); - } else if (SupportedFileFormat.MP4.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new Mp4Tag(); - } else if (SupportedFileFormat.M4A.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new Mp4Tag(); - } else if (SupportedFileFormat.M4P.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new Mp4Tag(); - } else if (SupportedFileFormat.WMA.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new AsfTag(); - } else if (SupportedFileFormat.WAV.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new WavTag(); - } else if (SupportedFileFormat.RA.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new RealTag(); - } else if (SupportedFileFormat.RM.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new RealTag(); - } else if (SupportedFileFormat.AIF.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) { - return new AiffTag(); - } else { - throw new RuntimeException("Unable to create default tag for this file format"); - } - - } - - /** - * Get the tag or if the file doesn't have one at all, create a default tag and return - * - * @return - */ - public Tag getTagOrCreateDefault() { - Tag tag = getTag(); - if (tag == null) { - return createDefaultTag(); - } - return tag; - } - - /** - * Get the tag or if the file doesn't have one at all, create a default tag and set it - * - * @return - */ - public Tag getTagOrCreateAndSetDefault() { - Tag tag = getTagOrCreateDefault(); - setTag(tag); - return tag; - } - - public Tag getTagAndConvertOrCreateAndSetDefault() { - return getTagOrCreateAndSetDefault(); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/AudioFileFilter.java b/src/main/java/org/jaudiotagger/audio/AudioFileFilter.java deleted file mode 100644 index 7d830dc..0000000 --- a/src/main/java/org/jaudiotagger/audio/AudioFileFilter.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio; - -import org.jaudiotagger.audio.generic.Utils; - -import java.io.File; -import java.io.FileFilter; - -/** - *

This is a simple FileFilter that will only allow the file supported by this library.

- *

It will also accept directories. An additional condition is that file must be readable (read permission) and - * are not hidden (dot files, or hidden files)

- * - * @author Raphael Slinckx - * @version $Id: AudioFileFilter.java 836 2009-11-12 15:44:07Z paultaylor $ - * @since v0.01 - */ -public class AudioFileFilter implements FileFilter { - /** - * allows Directories - */ - private final boolean allowDirectories; - - public AudioFileFilter(boolean allowDirectories) { - this.allowDirectories = allowDirectories; - } - - public AudioFileFilter() { - this(true); - } - - /** - *

Check whether the given file meet the required conditions (supported by the library OR directory). - * The File must also be readable and not hidden.

- * - * @param f The file to test - * @return a boolean indicating if the file is accepted or not - */ - public boolean accept(File f) { - if (f.isHidden() || !f.canRead()) { - return false; - } - - if (f.isDirectory()) { - return allowDirectories; - } - - String ext = Utils.getExtension(f); - - try { - if (SupportedFileFormat.valueOf(ext.toUpperCase()) != null) { - return true; - } - } catch (IllegalArgumentException iae) { - //Not known enum value - return false; - } - return false; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/AudioFileIO.java b/src/main/java/org/jaudiotagger/audio/AudioFileIO.java deleted file mode 100644 index 112bcb5..0000000 --- a/src/main/java/org/jaudiotagger/audio/AudioFileIO.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio; - -import org.jaudiotagger.audio.aiff.AiffFileReader; -import org.jaudiotagger.audio.asf.AsfFileReader; -import org.jaudiotagger.audio.asf.AsfFileWriter; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.audio.flac.FlacFileReader; -import org.jaudiotagger.audio.flac.FlacFileWriter; -import org.jaudiotagger.audio.generic.*; -import org.jaudiotagger.audio.mp3.MP3FileReader; -import org.jaudiotagger.audio.mp3.MP3FileWriter; -import org.jaudiotagger.audio.mp4.Mp4FileReader; -import org.jaudiotagger.audio.mp4.Mp4FileWriter; -import org.jaudiotagger.audio.ogg.OggFileReader; -import org.jaudiotagger.audio.ogg.OggFileWriter; -import org.jaudiotagger.audio.real.RealFileReader; -import org.jaudiotagger.audio.wav.WavFileReader; -import org.jaudiotagger.audio.wav.WavFileWriter; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.TagException; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.logging.Logger; - -/** - *

- * The main entry point for the Tag Reading/Writing operations, this class will - * select the appropriate reader/writer for the given file. - *

- *

- * It selects the appropriate reader/writer based on the file extension (case - * ignored). - *

- *

- * Here is an simple example of use: - *

- *

- * - * AudioFile audioFile = AudioFileIO.read(new File("audiofile.mp3")); //Reads the given file.
- * int bitrate = audioFile.getBitrate(); //Retreives the bitrate of the file.
- * String artist = audioFile.getTag().getFirst(TagFieldKey.ARTIST); //Retreive the artist name.
- * audioFile.getTag().setGenre("Progressive Rock"); //Sets the genre to Prog. Rock, note the file on disk is still unmodified.
- * AudioFileIO.write(audioFile); //Write the modifications in the file on disk. - *
- *

- *

- * You can also use the commit() method defined for - * AudioFiles to achieve the same goal as - * AudioFileIO.write(File), like this: - *

- *

- * - * AudioFile audioFile = AudioFileIO.read(new File("audiofile.mp3"));
- * audioFile.getTag().setGenre("Progressive Rock");
- * audioFile.commit(); //Write the modifications in the file on disk.
- *
- *

- * - * @author Raphael Slinckx - * @version $Id: AudioFileIO.java 1067 2012-10-17 18:01:32Z garymcgath $ - * @see AudioFile - * @see org.jaudiotagger.tag.Tag - * @since v0.01 - */ -public class AudioFileIO { - - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio"); - - // !! Do not forget to also add new supported extensions to AudioFileFilter - // !! - - /** - * This field contains the default instance for static use. - */ - private static AudioFileIO defaultInstance; - /** - * This member is used to broadcast modification events to registered - */ - private final ModificationHandler modificationHandler; - // These tables contains all the readers/writers associated with extension - // as a key - private Map readers = new HashMap(); - private Map writers = new HashMap(); - - /** - * Creates an instance. - */ - public AudioFileIO() { - this.modificationHandler = new ModificationHandler(); - prepareReadersAndWriters(); - } - - /** - *

- * Delete the tag, if any, contained in the given file. - *

- * - * @param f The file where the tag will be deleted - * @throws org.jaudiotagger.audio.exceptions.CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - */ - public static void delete(AudioFile f) throws CannotReadException, CannotWriteException { - getDefaultAudioFileIO().deleteTag(f); - } - - /** - * This method returns the default instance for static use.
- * - * @return The default instance. - */ - public static AudioFileIO getDefaultAudioFileIO() { - if (defaultInstance == null) { - defaultInstance = new AudioFileIO(); - } - return defaultInstance; - } - - /** - *

- * Read the tag contained in the given file. - *

- * - * @param f The file to read. - * @return The AudioFile with the file tag and the file encoding info. - * @throws org.jaudiotagger.audio.exceptions.CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws org.jaudiotagger.tag.TagException - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws java.io.IOException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public static AudioFile read(File f) - throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - return getDefaultAudioFileIO().readFile(f); - } - - /** - *

- * Write the tag contained in the audioFile in the actual file on the disk. - *

- * - * @param f The AudioFile to be written - * @throws CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - */ - public static void write(AudioFile f) throws CannotWriteException { - getDefaultAudioFileIO().writeFile(f); - } - - /** - * Adds an listener for all file formats. - * - * @param listener listener - */ - public void addAudioFileModificationListener( - AudioFileModificationListener listener) { - this.modificationHandler.addAudioFileModificationListener(listener); - } - - /** - *

- * Delete the tag, if any, contained in the given file. - *

- * - * @param f The file where the tag will be deleted - * @throws org.jaudiotagger.audio.exceptions.CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - */ - public void deleteTag(AudioFile f) throws CannotReadException, CannotWriteException { - String ext = Utils.getExtension(f.getFile()); - - Object afw = writers.get(ext); - if (afw == null) { - throw new CannotWriteException(ErrorMessage.NO_DELETER_FOR_THIS_FORMAT.getMsg(ext)); - } - - ((AudioFileWriter) afw).delete(f); - } - - /** - * Creates the readers and writers. - */ - private void prepareReadersAndWriters() { - - // Tag Readers - readers.put(SupportedFileFormat.OGG.getFilesuffix(), new OggFileReader()); - readers.put(SupportedFileFormat.FLAC.getFilesuffix(), new FlacFileReader()); - readers.put(SupportedFileFormat.MP3.getFilesuffix(), new MP3FileReader()); - readers.put(SupportedFileFormat.MP4.getFilesuffix(), new Mp4FileReader()); - readers.put(SupportedFileFormat.M4A.getFilesuffix(), new Mp4FileReader()); - readers.put(SupportedFileFormat.M4P.getFilesuffix(), new Mp4FileReader()); - readers.put(SupportedFileFormat.M4B.getFilesuffix(), new Mp4FileReader()); - readers.put(SupportedFileFormat.WAV.getFilesuffix(), new WavFileReader()); - readers.put(SupportedFileFormat.WMA.getFilesuffix(), new AsfFileReader()); - readers.put(SupportedFileFormat.AIF.getFilesuffix(), new AiffFileReader()); - final RealFileReader realReader = new RealFileReader(); - readers.put(SupportedFileFormat.RA.getFilesuffix(), realReader); - readers.put(SupportedFileFormat.RM.getFilesuffix(), realReader); - - // Tag Writers - writers.put(SupportedFileFormat.OGG.getFilesuffix(), new OggFileWriter()); - writers.put(SupportedFileFormat.FLAC.getFilesuffix(), new FlacFileWriter()); - writers.put(SupportedFileFormat.MP3.getFilesuffix(), new MP3FileWriter()); - writers.put(SupportedFileFormat.MP4.getFilesuffix(), new Mp4FileWriter()); - writers.put(SupportedFileFormat.M4A.getFilesuffix(), new Mp4FileWriter()); - writers.put(SupportedFileFormat.M4P.getFilesuffix(), new Mp4FileWriter()); - writers.put(SupportedFileFormat.M4B.getFilesuffix(), new Mp4FileWriter()); - writers.put(SupportedFileFormat.WAV.getFilesuffix(), new WavFileWriter()); - writers.put(SupportedFileFormat.WMA.getFilesuffix(), new AsfFileWriter()); - - // Register modificationHandler - Iterator it = writers.values().iterator(); - for (AudioFileWriter curr : writers.values()) { - curr.setAudioFileModificationListener(this.modificationHandler); - } - } - - /** - *

- * Read the tag contained in the given file. - *

- * - * @param f The file to read. - * @return The AudioFile with the file tag and the file encoding info. - * @throws org.jaudiotagger.audio.exceptions.CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws org.jaudiotagger.tag.TagException - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws java.io.IOException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public AudioFile readFile(File f) - throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - checkFileExists(f); - String ext = Utils.getExtension(f); - - AudioFileReader afr = readers.get(ext); - if (afr == null) { - throw new CannotReadException(ErrorMessage.NO_READER_FOR_THIS_FORMAT.getMsg(ext)); - } - - return afr.read(f); - } - - /** - * Check does file exist - * - * @param file - * @throws java.io.FileNotFoundException - */ - public void checkFileExists(File file) throws FileNotFoundException { - logger.config("Reading file:" + "path" + file.getPath() + ":abs:" + file.getAbsolutePath()); - if (!file.exists()) { - logger.severe("Unable to find:" + file.getPath()); - throw new FileNotFoundException(ErrorMessage.UNABLE_TO_FIND_FILE.getMsg(file.getPath())); - } - } - - /** - * Removes a listener for all file formats. - * - * @param listener listener - */ - public void removeAudioFileModificationListener( - AudioFileModificationListener listener) { - this.modificationHandler.removeAudioFileModificationListener(listener); - } - - /** - *

- * Write the tag contained in the audioFile in the actual file on the disk. - *

- * - * @param f The AudioFile to be written - * @throws CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - */ - public void writeFile(AudioFile f) throws CannotWriteException { - String ext = Utils.getExtension(f.getFile()); - - AudioFileWriter afw = writers.get(ext); - if (afw == null) { - throw new CannotWriteException(ErrorMessage.NO_WRITER_FOR_THIS_FORMAT.getMsg(ext)); - } - - afw.write(f); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/AudioHeader.java b/src/main/java/org/jaudiotagger/audio/AudioHeader.java deleted file mode 100644 index ac66eeb..0000000 --- a/src/main/java/org/jaudiotagger/audio/AudioHeader.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.jaudiotagger.audio; - -/** - * Representation of AudioHeader - *

- *

Contains info about the Audio Header - */ -public interface AudioHeader { - /** - * @return the audio file type - */ - String getEncodingType(); - - /** - * @return the BitRate of the Audio - */ - String getBitRate(); - - /** - * @return birate as a number - */ - long getBitRateAsNumber(); - - - /** - * @return the Sampling rate - */ - String getSampleRate(); - - /** - * @return - */ - int getSampleRateAsNumber(); - - /** - * @return the format - */ - String getFormat(); - - /** - * @return the Channel Mode such as Stereo or Mono - */ - String getChannels(); - - /** - * @return if the bitRate is variable - */ - boolean isVariableBitRate(); - - /** - * @return track length - */ - int getTrackLength(); - - /** - * @return the number of bits per sample - */ - int getBitsPerSample(); - - /** - * @return - */ - boolean isLossless(); -} diff --git a/src/main/java/org/jaudiotagger/audio/SupportedFileFormat.java b/src/main/java/org/jaudiotagger/audio/SupportedFileFormat.java deleted file mode 100644 index 6bff058..0000000 --- a/src/main/java/org/jaudiotagger/audio/SupportedFileFormat.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.jaudiotagger.audio; - -/** - * Files formats currently supported by Library. - * Each enum value is associated with a file suffix (extension). - */ -public enum SupportedFileFormat { - OGG("ogg"), - MP3("mp3"), - FLAC("flac"), - MP4("mp4"), - M4A("m4a"), - M4P("m4p"), - WMA("wma"), - WAV("wav"), - RA("ra"), - RM("rm"), - M4B("m4b"), - AIF("aif"); - - private String filesuffix; - - /** - * Constructor for internal use by this enum. - */ - SupportedFileFormat(String filesuffix) { - this.filesuffix = filesuffix; - } - - /** - * Returns the file suffix (lower case without initial .) associated with the format. - */ - public String getFilesuffix() { - return filesuffix; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffAudioHeader.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffAudioHeader.java deleted file mode 100644 index c598e31..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffAudioHeader.java +++ /dev/null @@ -1,179 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.generic.GenericAudioHeader; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Non-"tag" metadata from the AIFF file. In general, read-only. - */ -public class AiffAudioHeader extends GenericAudioHeader { - - private FileType fileType; - private Date timestamp; - private Endian endian; - private String audioEncoding; - private String name; - private String author; - private String copyright; - private List applicationIdentifiers; - private List comments; - - public AiffAudioHeader() { - applicationIdentifiers = new ArrayList(); - comments = new ArrayList(); - endian = Endian.BIG_ENDIAN; - } - - /** - * Return the timestamp of the file. - */ - public Date getTimestamp() { - return timestamp; - } - - /** - * Set the timestamp. - */ - public void setTimestamp(Date d) { - timestamp = d; - } - - /** - * Return the file type (AIFF or AIFC) - */ - public FileType getFileType() { - return fileType; - } - - /** - * Set the file type (AIFF or AIFC) - */ - public void setFileType(FileType typ) { - fileType = typ; - } - - /** - * Return the author - */ - public String getAuthor() { - return author; - } - - /** - * Set the author - */ - public void setAuthor(String a) { - author = a; - } - - /** - * Return the name. May be null. - */ - public String getName() { - return name; - } - - /** - * Set the name - */ - public void setName(String n) { - name = n; - } - - /** - * Return the copyright. May be null. - */ - public String getCopyright() { - return copyright; - } - - /** - * Set the copyright - */ - public void setCopyright(String c) { - copyright = c; - } - - /** - * Return endian status (big or little) - */ - public Endian getEndian() { - return endian; - } - - /** - * Set endian status (big or little) - */ - public void setEndian(Endian e) { - endian = e; - } - - /** - * Return list of all application identifiers - */ - public List getApplicationIdentifiers() { - return applicationIdentifiers; - } - - /** - * Add an application identifier. There can be any number of these. - */ - public void addApplicationIdentifier(String id) { - applicationIdentifiers.add(id); - } - - /** - * Return list of all annotations - */ - public List getAnnotations() { - return applicationIdentifiers; - } - - /** - * Add an annotation. There can be any number of these. - */ - public void addAnnotation(String a) { - applicationIdentifiers.add(a); - } - - /** - * Return list of all comments - */ - public List getComments() { - return comments; - } - - /** - * Add a comment. There can be any number of these. - */ - public void addComment(String c) { - comments.add(c); - } - - /** - * Return the audio encoding as a descriptive string - */ - public String getAudioEncoding() { - return audioEncoding; - } - - /** - * Set the audio encoding as a descriptive string - */ - public void setAudioEncoding(String s) { - audioEncoding = s; - } - - public enum FileType { - AIFFTYPE, - AIFCTYPE - } - - public enum Endian { - BIG_ENDIAN, - LITTLE_ENDIAN - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffFile.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffFile.java deleted file mode 100644 index 0eae3cc..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffFile.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.tag.TagException; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.text.SimpleDateFormat; -import java.util.logging.Level; - -public class AiffFile extends AudioFile { - - /** - * A static DateFormat object for generating ISO date strings - */ - public final static SimpleDateFormat ISO_DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - - /** - * Creates a new empty AiffFile that is not associated with a - * specific file. - */ - public AiffFile() { - - } - - - /** - * Creates a new MP3File datatype and parse the tag from the given filename. - * - * @param filename AIFF file - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public AiffFile(String filename) throws - IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - this(new File(filename)); - } - - /** - * Creates a new MP3File datatype and parse the tag from the given file - * Object. - * - * @param file MP3 file - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public AiffFile(File file) - throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - this(file, true); - } - - public AiffFile(File file, boolean readOnly) - throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - RandomAccessFile newFile = null; - try { - logger.setLevel(Level.FINEST); - logger.fine("Called AiffFile constructor on " + file.getAbsolutePath()); - this.file = file; - - //Check File accessibility - newFile = checkFilePermissions(file, readOnly); - audioHeader = new AiffAudioHeader(); - //readTag(); - - } finally { - if (newFile != null) { - newFile.close(); - } - } - } - - public AiffAudioHeader getAiffAudioHeader() { - return (AiffAudioHeader) audioHeader; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffFileReader.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffFileReader.java deleted file mode 100644 index 3a4396b..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffFileReader.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.aiff.AiffTag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class AiffFileReader extends AudioFileReader { - - /* Fixed value for first 4 bytes */ - private static final int[] sigByte = - {0X46, 0X4F, 0X52, 0X4D}; - - /* AIFF-specific information which isn't "tag" information */ - private AiffAudioHeader aiffHeader; - - /* "Tag" information */ - private AiffTag aiffTag; - - /* InputStream that reads the file sequentially */ -// private DataInputStream inStream; - - public AiffFileReader() { - aiffHeader = new AiffAudioHeader(); - aiffTag = new AiffTag(); - } - - - public AiffFileReader(RandomAccessFile raf) { - aiffHeader = new AiffAudioHeader(); - aiffTag = new AiffTag(); - } - - - /** - * Reads the file and fills in the audio header and tag information. - * Holds the tag information for later and returns the audio header. - */ - @Override - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) - throws CannotReadException, IOException { - logger.finest("Reading AIFF file "); - byte sigBuf[] = new byte[4]; - raf.read(sigBuf); - for (int i = 0; i < 4; i++) { - if (sigBuf[i] != sigByte[i]) { - logger.finest("AIFF file has incorrect signature"); - throw new CannotReadException("Not an AIFF file: incorrect signature"); - } - } - long bytesRemaining = AiffUtil.readUINT32(raf); - - // Read the file type. - if (!readFileType(raf)) { - throw new CannotReadException("Invalid AIFF file: Incorrect file type info"); - } - bytesRemaining -= 4; - while (bytesRemaining > 0) { - if (!readChunk(raf, bytesRemaining)) { - break; - } - } - return aiffHeader; - } - - @Override - protected Tag getTag(RandomAccessFile raf) throws CannotReadException, - IOException { - logger.info("getTag called"); - - // TODO fill out stub code - return aiffTag; - - } - - /* Reads the file type. - * Broken out from parse(). - * If it is not a valid file type, returns false. - */ - private boolean readFileType(RandomAccessFile raf) throws IOException { - String typ = AiffUtil.read4Chars(raf); - if ("AIFF".equals(typ)) { - aiffHeader.setFileType(AiffAudioHeader.FileType.AIFFTYPE); - return true; - } else if ("AIFC".equals(typ)) { - aiffHeader.setFileType(AiffAudioHeader.FileType.AIFCTYPE); - return true; - } else { - return false; - } - } - - /** - * Reads an AIFF Chunk. - */ - protected boolean readChunk - (RandomAccessFile raf, long bytesRemaining) - throws IOException { - Chunk chunk = null; - ChunkHeader chunkh = new ChunkHeader(); - if (!chunkh.readHeader(raf)) { - return false; - } - int chunkSize = (int) chunkh.getSize(); - bytesRemaining -= chunkSize + 8; - - String id = chunkh.getID(); - if ("FVER".equals(id)) { - chunk = new FormatVersionChunk(chunkh, raf, aiffHeader); - } else if ("APPL".equals(id)) { - chunk = new ApplicationChunk(chunkh, raf, aiffHeader); - // Any number of application chunks is ok - } else if ("COMM".equals(id)) { - // There should be no more than one of these - chunk = new CommonChunk(chunkh, raf, aiffHeader); - } else if ("COMT".equals(id)) { - chunk = new CommentsChunk(chunkh, raf, aiffHeader); - } else if ("NAME".equals(id)) { - chunk = new NameChunk(chunkh, raf, aiffHeader); - } else if ("AUTH".equals(id)) { - chunk = new AuthorChunk(chunkh, raf, aiffHeader); - } else if ("(c) ".equals(id)) { - chunk = new CopyrightChunk(chunkh, raf, aiffHeader); - } else if ("ANNO".equals(id)) { - chunk = new AnnotationChunk(chunkh, raf, aiffHeader); - } else if ("ID3 ".equals(id)) { - chunk = new ID3Chunk(chunkh, raf, aiffTag); - } - - if (chunk != null) { - if (!chunk.readChunk()) { - return false; - } - } else { - // Other chunk types are legal, just skip over them - raf.skipBytes(chunkSize); - } - if ((chunkSize & 1) != 0) { - // Must come out to an even byte boundary - raf.skipBytes(1); - --bytesRemaining; - } - return true; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffInfoReader.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffInfoReader.java deleted file mode 100644 index 98cee18..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffInfoReader.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.exceptions.CannotReadException; - -import java.io.IOException; -import java.io.RandomAccessFile; - - -/** - * Functions for reading an AIFF file - */ -public class AiffInfoReader { - - public AiffAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException { - if (raf.length() < 4) { - //Empty File - throw new CannotReadException("Not an AIFF file; too short"); - } - return null; // TODO stub - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffInputStream.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffInputStream.java deleted file mode 100644 index eded35d..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffInputStream.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; - -/** - * This class implements an InputStream over a RandomAccessFile for the - * sake of efficiency. The AIFF reader uses a RandomAccessFile for - * consistency with the other modules, but really just reads the file - * sequentially. This class permits reasonable buffering. - */ -public class AiffInputStream extends InputStream { - - private final static int BUFSIZE = 2048; - /** - * The underlying file - */ - private RandomAccessFile raf; - - /** - * The input buffer - */ - private byte[] fileBuf; - - /** - * Number of valid bytes in the input buffer - */ - private int fileBufSize; - - /** - * Current position in the input buffer - */ - private int fileBufOffset; - - /** - * End of file flag - */ - private boolean eof; - - public AiffInputStream(RandomAccessFile raf) { - this.raf = raf; - eof = false; - fileBuf = new byte[BUFSIZE]; - fileBufSize = 0; - fileBufOffset = 0; - } - - - @Override - public int read() throws IOException { - for (; ; ) { - if (eof) { - return -1; - } - if (fileBufOffset < fileBufSize) { - return ((int) fileBuf[fileBufOffset++]) & 0XFF; - } else { - fillBuf(); - } - } - } - - - /* Refill the buffer */ - private void fillBuf() throws IOException { - int bytesRead = raf.read(fileBuf, 0, BUFSIZE); - fileBufOffset = 0; - fileBufSize = bytesRead; - if (fileBufSize == 0) { - eof = true; - } - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffTag.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffTag.java deleted file mode 100644 index f7c3331..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffTag.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.generic.GenericTag; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.FieldDataInvalidException; -import org.jaudiotagger.tag.KeyNotFoundException; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.TagTextField; - -public class AiffTag extends GenericTag { - - public boolean hasField(AiffTagFieldKey fieldKey) { - return hasField(fieldKey.name()); - } - - /** - * Create new AIFF-specific field and set it in the tag - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void setField(AiffTagFieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - public TagField createField(AiffTagFieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - return new AiffTagTextField(genericKey.name(), value); - } - - private class AiffTagTextField implements TagTextField { - - /** - * Stores the identifier. - */ - private final String id; - /** - * Stores the string. - */ - private String content; - - /** - * Creates an instance. - * - * @param fieldId The identifier. - * @param initialContent The string. - */ - public AiffTagTextField(String fieldId, String initialContent) { - this.id = fieldId; - this.content = initialContent; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#copyContent(org.jaudiotagger.tag.TagField) - */ - public void copyContent(TagField field) { - if (field instanceof TagTextField) { - this.content = ((TagTextField) field).getContent(); - } - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#getContent() - */ - public String getContent() { - return this.content; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#setContent(java.lang.String) - */ - public void setContent(String s) { - this.content = s; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#getEncoding() - */ - public String getEncoding() { - return "ISO-8859-1"; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#setEncoding(java.lang.String) - */ - public void setEncoding(String s) { - /* Not allowed */ - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#getId() - */ - public String getId() { - return id; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#getRawContent() - */ - public byte[] getRawContent() { - return this.content == null ? new byte[]{} : Utils.getDefaultBytes(this.content, getEncoding()); - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isBinary() - */ - public boolean isBinary() { - return false; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isBinary(boolean) - */ - public void isBinary(boolean b) { - /* not supported */ - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isCommon() - */ - public boolean isCommon() { - return true; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isEmpty() - */ - public boolean isEmpty() { - return this.content.equals(""); - } - - /** - * (overridden) - * - * @see java.lang.Object#toString() - */ - public String toString() { - return getContent(); - } - } // End of AiffTagTextField - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffTagFieldKey.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffTagFieldKey.java deleted file mode 100644 index c3dee41..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffTagFieldKey.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -/** - * Enum for AIFF fields that don't have obvious matches in FieldKey - */ -public enum AiffTagFieldKey { - TIMESTAMP("TIMESTAMP"); - - private String fieldName; - - AiffTagFieldKey(String fieldName) { - this.fieldName = fieldName; - } - - public String getFieldName() { - return fieldName; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AiffUtil.java b/src/main/java/org/jaudiotagger/audio/aiff/AiffUtil.java deleted file mode 100644 index 7b45083..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AiffUtil.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -//import java.io.EOFException; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - -//import java.io.InputStream; - -public class AiffUtil { - - private final static SimpleDateFormat dateFmt = - new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - - private final static Charset LATIN1 = Charset.availableCharsets().get("ISO-8859-1"); - - /** - * Reads 4 bytes from file and interprets them as UINT32.
- * - * @param raf file to read from. - * @return UINT32 value - * @throws IOException on I/O Errors. - */ - public static long readUINT32(RandomAccessFile raf) throws IOException { - long result = 0; - for (int i = 0; i < 4; i++) { - // Warning, always cast to long here. Otherwise it will be - // shifted as int, which may produce a negative value, which will - // then be extended to long and assign the long variable a negative - // value. - result <<= 8; - result |= (long) raf.read(); - } - return result; - } - - /** - * Reads 4 bytes and concatenates them into a String. - * This pattern is used for ID's of various kinds. - */ - public static String read4Chars(RandomAccessFile raf) throws IOException { - StringBuffer sbuf = new StringBuffer(4); - for (int i = 0; i < 4; i++) { - char ch = (char) raf.read(); - sbuf.append(ch); - } - return sbuf.toString(); - } - - public static double read80BitDouble(RandomAccessFile raf) - throws IOException { - byte[] buf = new byte[10]; - raf.readFully(buf); - ExtDouble xd = new ExtDouble(buf); - return xd.toDouble(); - } - - /** - * Converts a Macintosh-style timestamp (seconds since - * January 1, 1904) into a Java date. The timestamp is - * treated as a time in the default localization. - * Depending on that localization, - * there may be some variation in the exact hour of the date - * returned, e.g., due to daylight savings time. - */ - public static Date timestampToDate(long timestamp) { - Calendar cal = Calendar.getInstance(); - cal.set(1904, 0, 1, 0, 0, 0); - - // If we add the seconds directly, we'll truncate the long - // value when converting to int. So convert to hours plus - // residual seconds. - int hours = (int) (timestamp / 3600); - int seconds = (int) (timestamp - (long) hours * 3600L); - cal.add(Calendar.HOUR_OF_DAY, hours); - cal.add(Calendar.SECOND, seconds); - Date dat = cal.getTime(); - return dat; - } - - /** - * Format a date as text - */ - public static String formatDate(Date dat) { - return dateFmt.format(dat); - } - - /** - * Convert a byte array to a Pascal string. The first byte is the byte count, - * followed by that many active characters. - */ - public static String bytesToPascalString(byte[] data) { - int len = (int) data[0]; - return new String(data, 0, len, LATIN1); - } - - /** - * Read a Pascal string from the file. - */ - public static String readPascalString(RandomAccessFile raf) throws IOException { - int len = raf.read(); - byte[] buf = new byte[len + 1]; - raf.read(buf, 1, len); - buf[0] = (byte) len; - return bytesToPascalString(buf); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AnnotationChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/AnnotationChunk.java deleted file mode 100644 index 801c822..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AnnotationChunk.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class AnnotationChunk extends TextChunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param aHdr The AiffAudioHeader into which information is stored - */ - public AnnotationChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(hdr, raf); - aiffHeader = aHdr; - } - - @Override - public boolean readChunk() throws IOException { - if (!super.readChunk()) { - return false; - } - aiffHeader.addAnnotation(chunkText); - return true; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/ApplicationChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/ApplicationChunk.java deleted file mode 100644 index 9c16d55..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/ApplicationChunk.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class ApplicationChunk extends Chunk { - - // private AiffTag aiffTag; - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param tag The AiffTag into which information is stored - */ - public ApplicationChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(raf, hdr); - aiffHeader = aHdr; - } - - /** - * Reads a chunk and puts an Application property into - * the RepInfo object. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public boolean readChunk() throws IOException { - String applicationSignature = Utils.readString(raf, 4); - String applicationName = null; - byte[] data = new byte[(int) (bytesLeft - 4)]; - raf.readFully(data); - // If the application signature is 'pdos' or 'stoc', - // then the beginning of the data area is a Pascal - // string naming the application. Otherwise, we - // ignore the data. ('pdos' is for Apple II - // applications, 'stoc' for the entire non-Apple world.) - if ("stoc".equals(applicationSignature) || - "pdos".equals(applicationSignature)) { - applicationName = AiffUtil.bytesToPascalString(data); - } - aiffHeader.addApplicationIdentifier - (applicationSignature + ": " + applicationName); - - return true; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/AuthorChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/AuthorChunk.java deleted file mode 100644 index ac2fc07..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/AuthorChunk.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class AuthorChunk extends TextChunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param aHdr The AiffAudioHeader into which information is stored - */ - public AuthorChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(hdr, raf); - aiffHeader = aHdr; - } - - @Override - public boolean readChunk() throws IOException { - if (!super.readChunk()) { - return false; - } - aiffHeader.setAuthor(chunkText); - return true; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/Chunk.java b/src/main/java/org/jaudiotagger/audio/aiff/Chunk.java deleted file mode 100644 index d56fe90..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/Chunk.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - - -/** - * Abstract superclass for IFF/AIFF chunks. - * - * @author Gary McGath - */ -public abstract class Chunk { - - protected long bytesLeft; - protected RandomAccessFile raf; - - /** - * Constructor. - * - * @param module The Module under which this was called - * @param hdr The header for this chunk - * @param dstrm The stream from which the data are being read - */ - public Chunk(RandomAccessFile raf, ChunkHeader hdr) { - this.raf = raf; - bytesLeft = hdr.getSize(); - } - - - /** - * Reads a chunk and puts appropriate information into - * the RepInfo object. - * - * @param info RepInfo object to receive information - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public abstract boolean readChunk() throws IOException; - - /** - * Convert a byte buffer cleanly to an ASCII string. - * This is used for fixed-allocation strings in Broadcast - * WAVE chunks, and might have uses elsewhere. - * If a string is shorter than its fixed allocation, we're - * guaranteed only that there is a null terminating the string, - * and noise could follow it. So we can't use the byte buffer - * constructor for a string. - */ - protected String byteBufString(byte[] b) { - StringBuffer sb = new StringBuffer(b.length); - for (int i = 0; i < b.length; i++) { - byte c = b[i]; - if (c == 0) { - // Terminate when we see a null - break; - } - sb.append((char) c); - } - return sb.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/ChunkHeader.java b/src/main/java/org/jaudiotagger/audio/aiff/ChunkHeader.java deleted file mode 100644 index 1436319..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/ChunkHeader.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class ChunkHeader { - - private long _size; // This does not include the 8 bytes of header - private String _chunkID; // 4-character ID of the chunk - - /** - * Constructor. - * - * @param module The module under which the chunk is being read - * @param info The RepInfo object being used by the module - */ - public ChunkHeader() { - } - - - /** - * Reads the header of a chunk. If _chunkID is non-null, - * it's assumed to have already been read. - */ - public boolean readHeader(RandomAccessFile raf) throws IOException { - StringBuffer id = new StringBuffer(4); - for (int i = 0; i < 4; i++) { - int ch = raf.read(); - if (ch < 32) { - String hx = Integer.toHexString(ch); - if (hx.length() < 2) { - hx = "0" + hx; - } - return false; - } - id.append((char) ch); - } - _chunkID = id.toString(); - _size = AiffUtil.readUINT32(raf); - return true; - } - - /** - * Returns the chunk type, which is a 4-character code - */ - public String getID() { - return _chunkID; - } - - /** - * Sets the chunk type, which is a 4-character code, directly. - */ - public void setID(String id) { - _chunkID = id; - } - - /** - * Returns the chunk size (excluding the first 8 bytes) - */ - public long getSize() { - return _size; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/CommentsChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/CommentsChunk.java deleted file mode 100644 index c3e3286..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/CommentsChunk.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Date; - -public class CommentsChunk extends Chunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param tag The AiffTag into which information is stored - */ - public CommentsChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(raf, hdr); - aiffHeader = aHdr; - } - - /** - * Reads a chunk and extracts information. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public boolean readChunk() throws IOException { - int numComments = Utils.readUint16(raf); - // Create a List of comments - for (int i = 0; i < numComments; i++) { - long timestamp = Utils.readUint32(raf); - Date jTimestamp = AiffUtil.timestampToDate(timestamp); - int marker = Utils.readInt16(raf); - int count = Utils.readUint16(raf); - bytesLeft -= 8; - byte[] buf = new byte[count]; - raf.read(buf); - bytesLeft -= count; - String cmt = new String(buf); - - // Append a timestamp to the comment - cmt += " " + AiffUtil.formatDate(jTimestamp); - aiffHeader.addComment(cmt); - } - return true; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/CommonChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/CommonChunk.java deleted file mode 100644 index e20e47f..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/CommonChunk.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class CommonChunk extends Chunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param tag The AiffTag into which information is stored - */ - public CommonChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(raf, hdr); - aiffHeader = aHdr; - } - - - @Override - public boolean readChunk() throws IOException { - int numChannels = Utils.readUint16(raf); - long numSampleFrames = Utils.readUint32(raf); - int sampleSize = Utils.readUint16(raf); - bytesLeft -= 8; - - String compressionType = null; - String compressionName = null; - - double sampleRate = AiffUtil.read80BitDouble(raf); - bytesLeft -= 10; - - if (aiffHeader.getFileType() == AiffAudioHeader.FileType.AIFCTYPE) { - if (bytesLeft == 0) { - // This is a rather special case, but testing did turn up - // a file that misbehaved in this way. - return false; - } - compressionType = AiffUtil.read4Chars(raf); - // According to David Ackerman, the compression type can - // change the endianness of the document. - if (compressionType.equals("sowt")) { - aiffHeader.setEndian(AiffAudioHeader.Endian.LITTLE_ENDIAN); - } - bytesLeft -= 4; - compressionName = AiffUtil.readPascalString(raf); - bytesLeft -= compressionName.length() + 1; - } - - aiffHeader.setBitsPerSample(sampleSize); - aiffHeader.setSamplingRate((int) sampleRate); - aiffHeader.setChannelNumber(numChannels); - aiffHeader.setLength((int) (numSampleFrames / sampleRate)); - aiffHeader.setPreciseLength((float) (numSampleFrames / sampleRate)); - aiffHeader.setLossless(true); // for all known compression types - // Proper handling of compression type should depend - // on whether raw output is set - if (compressionType != null) { - if (compressionType.equals("NONE")) { - } else if (compressionType.equals("raw ")) { - compressionName = "PCM 8-bit offset-binary"; - } else if (compressionType.equals("twos")) { - compressionName = "PCM 16-bit twos-complement big-endian"; - } else if (compressionType.equals("sowt")) { - compressionName = "PCM 16-bit twos-complement little-endian"; - } else if (compressionType.equals("fl32")) { - compressionName = "PCM 32-bit integer"; - } else if (compressionType.equals("fl64")) { - compressionName = "PCM 64-bit floating point"; - } else if (compressionType.equals("in24")) { - compressionName = "PCM 24-bit integer"; - } else if (compressionType.equals("in32")) { - compressionName = "PCM 32-bit integer"; - } else { - aiffHeader.setLossless(false); // We don't know, so we have to assume lossy - } - aiffHeader.setAudioEncoding(compressionName); - - // The size of the data after compression isn't available - // from the Common chunk, so we mark it as "unknown." - // With a bit more sophistication, we could combine the - // information from here and the Sound Data chunk to get - // the effective byte rate, but we're about to release. - String name = compressionName; - if (name == null || name.length() == 0) { - name = compressionType; - } - } - return true; - - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/CopyrightChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/CopyrightChunk.java deleted file mode 100644 index 68eec08..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/CopyrightChunk.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class CopyrightChunk extends TextChunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param aHdr The AiffAudioHeader into which information is stored - */ - public CopyrightChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(hdr, raf); - aiffHeader = aHdr; - } - - @Override - public boolean readChunk() throws IOException { - if (!super.readChunk()) { - return false; - } - aiffHeader.setCopyright(chunkText); - return true; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/ExtDouble.java b/src/main/java/org/jaudiotagger/audio/aiff/ExtDouble.java deleted file mode 100644 index 1e42063..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/ExtDouble.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -/** - * Code to deal with the 80-bit floating point (extended double) - * numbers which occur in AIFF files. Should also be applicable - * in general. - *

- * Java has no built-in support for IEEE 754 extended double numbers. - * Thus, we have to unpack the number and convert it to a double by - * hand. There is, of course, loss of precision. - *

- * This isn't designed for high-precision work; as the standard - * disclaimer says, don't use it for life support systems or nuclear - * power plants. - *

- * Lifted bodily from JHOVE. - * - * @author Gary McGath - */ -public class ExtDouble { - - byte[] _rawData; - - /** - * Constructor. - * - * @param rawData A 10-byte array representing the number - * in the sequence in which it was stored. - */ - public ExtDouble(byte[] rawData) { - _rawData = rawData; - } - - - /** - * Convert the value to a Java double. This results in - * loss of precision. If the number is out of range, - * results aren't guaranteed. - */ - public double toDouble() { - int sign; - int exponent; - long mantissa = 0; - - // Extract the sign bit. - sign = _rawData[0] >> 7; - - // Extract the exponent. It's stored with a - // bias of 16383, so subtract that off. - // Also, the mantissa is between 1 and 2 (i.e., - // all but 1 digits are to the right of the binary point, so - // we take 62 (not 63: see below) off the exponent for that. - exponent = (_rawData[0] << 8) | _rawData[1]; - exponent &= 0X7FFF; // strip off sign bit - exponent -= (16383 + 62); // 1 is added to the "real" exponent - - // Extract the mantissa. It's 64 bits of unsigned - // data, but a long is a signed number, so we have to - // discard the LSB. We'll lose more than that converting - // to double anyway. This division by 2 is the reason for - // adding an extra 1 to the exponent above. - int shifter = 55; - for (int i = 2; i < 9; i++) { - mantissa |= ((long) _rawData[i] & 0XFFL) << shifter; - shifter -= 8; - } - mantissa |= _rawData[9] >>> 1; - - // Now put it together in a floating point number. - double val = Math.pow(2, exponent); - val *= mantissa; - if (sign != 0) { - val = -val; - } - return val; - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/aiff/FormatVersionChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/FormatVersionChunk.java deleted file mode 100644 index 6b58a7b..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/FormatVersionChunk.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Date; - -public class FormatVersionChunk extends Chunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param tag The AiffTag into which information is stored - */ - public FormatVersionChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(raf, hdr); - aiffHeader = aHdr; - } - - /** - * Reads a chunk and extracts information. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public boolean readChunk() throws IOException { - long rawTimestamp = Utils.readUint32(raf); - // The timestamp is in seconds since January 1, 1904. - // We must convert to Java time. - Date timestamp = AiffUtil.timestampToDate(rawTimestamp); - aiffHeader.setTimestamp(timestamp); - return true; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/ID3Chunk.java b/src/main/java/org/jaudiotagger/audio/aiff/ID3Chunk.java deleted file mode 100644 index 67ae25b..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/ID3Chunk.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.tag.TagException; -import org.jaudiotagger.tag.aiff.AiffTag; -import org.jaudiotagger.tag.id3.AbstractID3v2Tag; -import org.jaudiotagger.tag.id3.ID3v22Tag; -import org.jaudiotagger.tag.id3.ID3v23Tag; -import org.jaudiotagger.tag.id3.ID3v24Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - -public class ID3Chunk extends Chunk { - - private AiffTag aiffTag; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param tag The AiffTag into which information is stored - */ - public ID3Chunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffTag tag) { - super(raf, hdr); - aiffTag = tag; - } - - @Override - public boolean readChunk() throws IOException { - // TODO Auto-generated method stub - if (!isId3v2Tag()) { - return false; // Bad ID3V2 tag - } - int version = raf.read(); - AbstractID3v2Tag id3Tag; - switch (version) { - case 2: - id3Tag = new ID3v22Tag(); - AudioFile.logger.finest("Reading ID3V2.2 tag"); - break; - case 3: - id3Tag = new ID3v23Tag(); - AudioFile.logger.finest("Reading ID3V2.3 tag"); - break; - case 4: - id3Tag = new ID3v24Tag(); - AudioFile.logger.finest("Reading ID3V2.4 tag"); - break; - default: - return false; // bad or unknown version - } - aiffTag.setID3Tag(id3Tag); - raf.seek(raf.getFilePointer() - 4); // back up to start of tag - byte[] buf = new byte[(int) bytesLeft]; - raf.read(buf); - ByteBuffer bb = ByteBuffer.allocate((int) bytesLeft); - bb.put(buf); - try { - id3Tag.read(bb); - } catch (TagException e) { - AudioFile.logger.info("Exception reading ID3 tag: " + e.getClass().getName() - + ": " + e.getMessage()); - return false; - } - return true; - } - - - /** - * @param rawdata - * @param isFramingBit - * @return logical representation of VorbisCommentTag - * @throws IOException - * @throws CannotReadException - */ - public void parse(byte[] rawdata, AiffTag aiffTag) throws IOException, CannotReadException { - - - } - - /** - * Reads 3 bytes to determine if the tag really looks like ID3 data. - */ - private boolean isId3v2Tag() throws IOException { - byte buf[] = new byte[3]; - raf.read(buf); - String id = new String(buf, "ASCII"); - return "ID3".equals(id); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/NameChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/NameChunk.java deleted file mode 100644 index be60727..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/NameChunk.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class NameChunk extends TextChunk { - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - * @param aHdr The AiffAudioHeader into which information is stored - */ - public NameChunk( - ChunkHeader hdr, - RandomAccessFile raf, - AiffAudioHeader aHdr) { - super(hdr, raf); - aiffHeader = aHdr; - } - - @Override - public boolean readChunk() throws IOException { - if (!super.readChunk()) { - return false; - } - aiffHeader.setName(chunkText); - return true; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/TextChunk.java b/src/main/java/org/jaudiotagger/audio/aiff/TextChunk.java deleted file mode 100644 index 0615880..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/TextChunk.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * This class provides common functionality for NameChunk, AuthorChunk, - * and CopyrightChunk - */ -public abstract class TextChunk extends Chunk { - - protected String chunkText; - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param hdr The header for this chunk - * @param raf The file from which the AIFF data are being read - */ - public TextChunk( - ChunkHeader hdr, - RandomAccessFile raf) { - super(raf, hdr); - } - - /** - * Read the chunk. The subclasses need to take the value of - * chunkText and use it appropriately. - */ - @Override - public boolean readChunk() throws IOException { - - byte[] buf = new byte[(int) bytesLeft]; - raf.read(buf); - chunkText = new String(buf, "ISO-8859-1"); - return true; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/aiff/package.html b/src/main/java/org/jaudiotagger/audio/aiff/package.html deleted file mode 100644 index 866d722..0000000 --- a/src/main/java/org/jaudiotagger/audio/aiff/package.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - -Very preliminary code for AIFF files. -Not even remotely working yet. Uploaded for review. - -
- - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/asf/AsfFileReader.java b/src/main/java/org/jaudiotagger/audio/asf/AsfFileReader.java deleted file mode 100644 index 3c2ff0c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/AsfFileReader.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.asf.data.AudioStreamChunk; -import org.jaudiotagger.audio.asf.data.MetadataContainer; -import org.jaudiotagger.audio.asf.data.MetadataDescriptor; -import org.jaudiotagger.audio.asf.io.*; -import org.jaudiotagger.audio.asf.util.TagConverter; -import org.jaudiotagger.audio.asf.util.Utils; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.TagException; -import org.jaudiotagger.tag.asf.AsfTag; - -import java.io.*; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * This reader can read ASF files containing any content (stream type).
- * - * @author Christian Laireiter - */ -public class AsfFileReader extends AudioFileReader { - - /** - * Logger instance - */ - private final static Logger LOGGER = Logger - .getLogger("org.jaudiotagger.audio.asf"); - - /** - * This reader will be configured to read tag and audio header information.
- */ - private final static AsfHeaderReader HEADER_READER; - - static { - final List> readers = new ArrayList>(); - readers.add(ContentDescriptionReader.class); - readers.add(ContentBrandingReader.class); - readers.add(MetadataReader.class); - readers.add(LanguageListReader.class); - - // Create the header extension object reader with just content - // description reader as well - // as extended content description reader. - final AsfExtHeaderReader extReader = new AsfExtHeaderReader(readers, - true); - readers.add(FileHeaderReader.class); - readers.add(StreamChunkReader.class); - HEADER_READER = new AsfHeaderReader(readers, true); - HEADER_READER.setExtendedHeaderReader(extReader); - } - - /** - * Determines if the "isVbr" field is set in the extended content - * description.
- * - * @param header the header to look up. - * @return true if "isVbr" is present with a - * true value. - */ - private boolean determineVariableBitrate(final AsfHeader header) { - assert header != null; - boolean result = false; - final MetadataContainer extDesc = header - .findExtendedContentDescription(); - if (extDesc != null) { - final List descriptors = extDesc - .getDescriptorsByName("IsVBR"); - if (descriptors != null && !descriptors.isEmpty()) { - result = Boolean.TRUE.toString().equals( - descriptors.get(0).getString()); - } - } - return result; - } - - /** - * Creates a generic audio header instance with provided data from header. - * - * @param header ASF header which contains the information. - * @return generic audio header representation. - * @throws CannotReadException If header does not contain mandatory information. (Audio - * stream chunk and file header chunk) - */ - private GenericAudioHeader getAudioHeader(final AsfHeader header) - throws CannotReadException { - final GenericAudioHeader info = new GenericAudioHeader(); - if (header.getFileHeader() == null) { - throw new CannotReadException( - "Invalid ASF/WMA file. File header object not available."); - } - if (header.getAudioStreamChunk() == null) { - throw new CannotReadException( - "Invalid ASF/WMA file. No audio stream contained."); - } - info.setBitrate(header.getAudioStreamChunk().getKbps()); - info.setChannelNumber((int) header.getAudioStreamChunk() - .getChannelCount()); - info.setEncodingType("ASF (audio): " - + header.getAudioStreamChunk().getCodecDescription()); - info - .setLossless(header.getAudioStreamChunk() - .getCompressionFormat() == AudioStreamChunk.WMA_LOSSLESS); - info.setPreciseLength(header.getFileHeader().getPreciseDuration()); - info.setSamplingRate((int) header.getAudioStreamChunk() - .getSamplingRate()); - info.setVariableBitRate(determineVariableBitrate(header)); - info.setBitsPerSample(header.getAudioStreamChunk().getBitsPerSample()); - return info; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileReader#getEncodingInfo(java.io.RandomAccessFile) - */ - @Override - protected GenericAudioHeader getEncodingInfo(final RandomAccessFile raf) - throws CannotReadException, IOException { - raf.seek(0); - GenericAudioHeader info; - try { - final AsfHeader header = AsfHeaderReader.readInfoHeader(raf); - if (header == null) { - throw new CannotReadException( - "Some values must have been " - + "incorrect for interpretation as asf with wma content."); - } - info = getAudioHeader(header); - } catch (final Exception e) { - if (e instanceof IOException) { - throw (IOException) e; - } else if (e instanceof CannotReadException) { - throw (CannotReadException) e; - } else { - throw new CannotReadException("Failed to read. Cause: " - + e.getMessage(), e); - } - } - return info; - } - - /** - * Creates a tag instance with provided data from header. - * - * @param header ASF header which contains the information. - * @return generic audio header representation. - */ - private AsfTag getTag(final AsfHeader header) { - return TagConverter.createTagOf(header); - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileReader#getTag(java.io.RandomAccessFile) - */ - @Override - protected AsfTag getTag(final RandomAccessFile raf) - throws CannotReadException, IOException { - raf.seek(0); - AsfTag tag; - try { - final AsfHeader header = AsfHeaderReader.readTagHeader(raf); - if (header == null) { - throw new CannotReadException( - "Some values must have been " - + "incorrect for interpretation as asf with wma content."); - } - - tag = TagConverter.createTagOf(header); - - } catch (final Exception e) { - logger.severe(e.getMessage()); - if (e instanceof IOException) { - throw (IOException) e; - } else if (e instanceof CannotReadException) { - throw (CannotReadException) e; - } else { - throw new CannotReadException("Failed to read. Cause: " - + e.getMessage()); - } - } - return tag; - } - - /** - * {@inheritDoc} - */ - @Override - public AudioFile read(final File f) throws CannotReadException, - IOException, TagException, ReadOnlyFileException, - InvalidAudioFrameException { - if (!f.canRead()) { - throw new CannotReadException( - ErrorMessage.GENERAL_READ_FAILED_DO_NOT_HAVE_PERMISSION_TO_READ_FILE - .getMsg(f.getAbsolutePath())); - } - InputStream stream = null; - try { - stream = new FullRequestInputStream(new BufferedInputStream( - new FileInputStream(f))); - final AsfHeader header = HEADER_READER.read(Utils.readGUID(stream), - stream, 0); - if (header == null) { - throw new CannotReadException(ErrorMessage.ASF_HEADER_MISSING - .getMsg(f.getAbsolutePath())); - } - if (header.getFileHeader() == null) { - throw new CannotReadException( - ErrorMessage.ASF_FILE_HEADER_MISSING.getMsg(f - .getAbsolutePath())); - } - - // Just log a warning because file seems to play okay - if (header.getFileHeader().getFileSize().longValue() != f.length()) { - logger - .warning(ErrorMessage.ASF_FILE_HEADER_SIZE_DOES_NOT_MATCH_FILE_SIZE - .getMsg(f.getAbsolutePath(), header - .getFileHeader().getFileSize() - .longValue(), f.length())); - } - - return new AudioFile(f, getAudioHeader(header), getTag(header)); - - } catch (final CannotReadException e) { - throw e; - } catch (final Exception e) { - throw new CannotReadException("\"" + f + "\" :" + e, e); - } finally { - try { - if (stream != null) { - stream.close(); - } - } catch (final Exception ex) { - LOGGER.severe("\"" + f + "\" :" + ex); - } - } - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/AsfFileWriter.java b/src/main/java/org/jaudiotagger/audio/asf/AsfFileWriter.java deleted file mode 100644 index 09f20f1..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/AsfFileWriter.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf; - -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.asf.data.ChunkContainer; -import org.jaudiotagger.audio.asf.data.MetadataContainer; -import org.jaudiotagger.audio.asf.io.*; -import org.jaudiotagger.audio.asf.util.TagConverter; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.generic.AudioFileWriter; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.asf.AsfTag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; - -/** - * This class writes given tags to ASF files containing WMA content.
- *
- * - * @author Christian Laireiter - */ -public class AsfFileWriter extends AudioFileWriter { - - /** - * {@inheritDoc} - */ - @Override - protected void deleteTag(final RandomAccessFile raf, - final RandomAccessFile tempRaf) throws CannotWriteException, - IOException { - writeTag(new AsfTag(true), raf, tempRaf); - } - - private boolean[] searchExistence(final ChunkContainer container, - final MetadataContainer[] metaContainers) { - assert container != null; - assert metaContainers != null; - final boolean[] result = new boolean[metaContainers.length]; - for (int i = 0; i < result.length; i++) { - result[i] = container.hasChunkByGUID(metaContainers[i] - .getContainerType().getContainerGUID()); - } - return result; - } - - /** - * {@inheritDoc} - */ - @Override - protected void writeTag(final Tag tag, final RandomAccessFile raf, - final RandomAccessFile rafTemp) throws CannotWriteException, - IOException { - /* - * Since this implementation should not change the structure of the ASF - * file (locations of content description chunks), we need to read the - * content description chunk and the extended content description chunk - * from the source file. In the second step we need to determine which - * modifier (asf header or asf extended header) gets the appropriate - * modifiers. The following policies are applied: if the source does not - * contain any descriptor, the necessary descriptors are appended to the - * header object. - * - * if the source contains only one descriptor in the header extension - * object, and the other type is needed as well, the other one will be - * put into the header extension object. - * - * for each descriptor type, if an object is found, an updater will be - * configured. - */ - final AsfHeader sourceHeader = AsfHeaderReader.readTagHeader(raf); - raf.seek(0); // Reset for the streamer - /* - * Now createField modifiers for metadata descriptor and extended content - * descriptor as implied by the given Tag. - */ - // TODO not convinced that we need to copy fields here - final AsfTag copy = new AsfTag(tag, true); - final MetadataContainer[] distribution = TagConverter - .distributeMetadata(copy); - final boolean[] existHeader = searchExistence(sourceHeader, - distribution); - final boolean[] existExtHeader = searchExistence(sourceHeader - .getExtendedHeader(), distribution); - // Modifiers for the asf header object - final List headerModifier = new ArrayList(); - // Modifiers for the asf header extension object - final List extHeaderModifier = new ArrayList(); - for (int i = 0; i < distribution.length; i++) { - final WriteableChunkModifer modifier = new WriteableChunkModifer( - distribution[i]); - if (existHeader[i]) { - // Will remove or modify chunks in ASF header - headerModifier.add(modifier); - } else if (existExtHeader[i]) { - // Will remove or modify chunks in extended header - extHeaderModifier.add(modifier); - } else { - // Objects (chunks) will be added here. - if (i == 0 || i == 2 || i == 1) { - // Add content description and extended content description - // at header for maximum compatibility - headerModifier.add(modifier); - } else { - // For now, the rest should be created at extended header - // since other positions aren't known. - extHeaderModifier.add(modifier); - } - } - } - // only addField an AsfExtHeaderModifier, if there is actually something to - // change (performance) - if (!extHeaderModifier.isEmpty()) { - headerModifier.add(new AsfExtHeaderModifier(extHeaderModifier)); - } - new AsfStreamer() - .createModifiedCopy(new RandomAccessFileInputstream(raf), - new RandomAccessFileOutputStream(rafTemp), - headerModifier); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/AsfExtendedHeader.java b/src/main/java/org/jaudiotagger/audio/asf/data/AsfExtendedHeader.java deleted file mode 100644 index d780c0f..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/AsfExtendedHeader.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import java.math.BigInteger; - -/** - * This class represents the ASF extended header object (chunk).
- * Like {@link AsfHeader} it contains multiple other ASF objects (chunks).
- * - * @author Christian Laireiter - */ -public final class AsfExtendedHeader extends ChunkContainer { - - /** - * Creates an instance.
- * - * @param pos Position within the stream.
- * @param length the length of the extended header object. - */ - public AsfExtendedHeader(final long pos, final BigInteger length) { - super(GUID.GUID_HEADER_EXTENSION, pos, length); - } - - /** - * @return Returns the contentDescription. - */ - public ContentDescription getContentDescription() { - return (ContentDescription) getFirst(GUID.GUID_CONTENTDESCRIPTION, - ContentDescription.class); - } - - /** - * @return Returns the tagHeader. - */ - public MetadataContainer getExtendedContentDescription() { - return (MetadataContainer) getFirst( - GUID.GUID_EXTENDED_CONTENT_DESCRIPTION, MetadataContainer.class); - } - - /** - * Returns a language list object if present. - * - * @return a language list object. - */ - public LanguageList getLanguageList() { - return (LanguageList) getFirst(GUID.GUID_LANGUAGE_LIST, - LanguageList.class); - } - - /** - * Returns a metadata library object if present. - * - * @return metadata library objet - */ - public MetadataContainer getMetadataLibraryObject() { - return (MetadataContainer) getFirst(GUID.GUID_METADATA_LIBRARY, - MetadataContainer.class); - } - - /** - * Returns a metadata object if present. - * - * @return metadata object - */ - public MetadataContainer getMetadataObject() { - return (MetadataContainer) getFirst(GUID.GUID_METADATA, - MetadataContainer.class); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/AsfHeader.java b/src/main/java/org/jaudiotagger/audio/asf/data/AsfHeader.java deleted file mode 100644 index 893c9b4..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/AsfHeader.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Each ASF file starts with a so called header.
- * This header contains other chunks. Each chunk starts with a 16 byte GUID - * followed by the length (in bytes) of the chunk (including GUID). The length - * number takes 8 bytes and is unsigned. Finally the chunk's data appears.
- * - * @author Christian Laireiter - */ -public final class AsfHeader extends ChunkContainer { - /** - * The charset "UTF-16LE" is mandatory for ASF handling. - */ - public final static Charset ASF_CHARSET = Charset.forName("UTF-16LE"); //$NON-NLS-1$ - - /** - * Byte sequence representing the zero term character. - */ - public final static byte[] ZERO_TERM = {0, 0}; - - static { - Set MULTI_CHUNKS = new HashSet(); - MULTI_CHUNKS.add(GUID.GUID_STREAM); - } - - /** - * An ASF header contains multiple chunks.
- * The count of those is stored here. - */ - private final long chunkCount; - - /** - * Creates an instance. - * - * @param pos see {@link Chunk#position} - * @param chunkLen see {@link Chunk#chunkLength} - * @param chunkCnt - */ - public AsfHeader(final long pos, final BigInteger chunkLen, - final long chunkCnt) { - super(GUID.GUID_HEADER, pos, chunkLen); - this.chunkCount = chunkCnt; - } - - /** - * This method looks for an content description object in this header - * instance, if not found there, it tries to get one from a contained ASF - * header extension object. - * - * @return content description if found, null otherwise. - */ - public ContentDescription findContentDescription() { - ContentDescription result = getContentDescription(); - if (result == null && getExtendedHeader() != null) { - result = getExtendedHeader().getContentDescription(); - } - return result; - } - - /** - * This method looks for an extended content description object in this - * header instance, if not found there, it tries to get one from a contained - * ASF header extension object. - * - * @return extended content description if found, null - * otherwise. - */ - public MetadataContainer findExtendedContentDescription() { - MetadataContainer result = getExtendedContentDescription(); - if (result == null && getExtendedHeader() != null) { - result = getExtendedHeader().getExtendedContentDescription(); - } - return result; - } - - /** - * This method searches for a metadata container of the given type.
- * - * @param type the type of the container to look up. - * @return a container of specified type, of null if not - * contained. - */ - public MetadataContainer findMetadataContainer(final ContainerType type) { - MetadataContainer result = (MetadataContainer) getFirst(type - .getContainerGUID(), MetadataContainer.class); - if (result == null) { - result = (MetadataContainer) getExtendedHeader().getFirst( - type.getContainerGUID(), MetadataContainer.class); - } - return result; - } - - /** - * This method returns the first audio stream chunk found in the asf file or - * stream. - * - * @return Returns the audioStreamChunk. - */ - public AudioStreamChunk getAudioStreamChunk() { - AudioStreamChunk result = null; - final List streamChunks = assertChunkList(GUID.GUID_STREAM); - for (int i = 0; i < streamChunks.size() && result == null; i++) { - if (streamChunks.get(i) instanceof AudioStreamChunk) { - result = (AudioStreamChunk) streamChunks.get(i); - } - } - return result; - } - - /** - * Returns the amount of chunks, when this instance was created.
- * If chunks have been added, this won't be reflected with this call.
- * For that use {@link #getChunks()}. - * - * @return Chunkcount at instance creation. - */ - public long getChunkCount() { - return this.chunkCount; - } - - /** - * @return Returns the contentDescription. - */ - public ContentDescription getContentDescription() { - return (ContentDescription) getFirst(GUID.GUID_CONTENTDESCRIPTION, - ContentDescription.class); - } - - /** - * @return Returns the encodingChunk. - */ - public EncodingChunk getEncodingChunk() { - return (EncodingChunk) getFirst(GUID.GUID_ENCODING, EncodingChunk.class); - } - - /** - * @return Returns the encodingChunk. - */ - public EncryptionChunk getEncryptionChunk() { - return (EncryptionChunk) getFirst(GUID.GUID_CONTENT_ENCRYPTION, - EncryptionChunk.class); - } - - /** - * @return Returns the tagHeader. - */ - public MetadataContainer getExtendedContentDescription() { - return (MetadataContainer) getFirst( - GUID.GUID_EXTENDED_CONTENT_DESCRIPTION, MetadataContainer.class); - } - - /** - * @return Returns the extended header. - */ - public AsfExtendedHeader getExtendedHeader() { - return (AsfExtendedHeader) getFirst(GUID.GUID_HEADER_EXTENSION, - AsfExtendedHeader.class); - } - - /** - * @return Returns the fileHeader. - */ - public FileHeader getFileHeader() { - return (FileHeader) getFirst(GUID.GUID_FILE, FileHeader.class); - } - - /** - * @return Returns the streamBitratePropertiesChunk. - */ - public StreamBitratePropertiesChunk getStreamBitratePropertiesChunk() { - return (StreamBitratePropertiesChunk) getFirst( - GUID.GUID_STREAM_BITRATE_PROPERTIES, - StreamBitratePropertiesChunk.class); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix, - prefix + " | : Contains: \"" + getChunkCount() + "\" chunks" - + Utils.LINE_SEPARATOR)); - return result.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/AudioStreamChunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/AudioStreamChunk.java deleted file mode 100644 index 783ffd2..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/AudioStreamChunk.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; - -/** - * This class represents the stream chunk describing an audio stream.
- * - * @author Christian Laireiter - */ -public final class AudioStreamChunk extends StreamChunk { - /** - * Stores the hex values of codec identifiers to their descriptions.
- */ - public final static String[][] CODEC_DESCRIPTIONS = { - {"161", " (Windows Media Audio (ver 7,8,9))"}, - {"162", " (Windows Media Audio 9 series (Professional))"}, - {"163", "(Windows Media Audio 9 series (Lossless))"}, - {"7A21", " (GSM-AMR (CBR))"}, {"7A22", " (GSM-AMR (VBR))"}}; - /** - * Stores the audio codec number for WMA - */ - public final static long WMA = 0x161; - /** - * Stores the audio codec number for WMA (CBR) - */ - public final static long WMA_CBR = 0x7A21; - /** - * Stores the audio codec number for WMA_LOSSLESS - */ - public final static long WMA_LOSSLESS = 0x163; - /** - * Stores the audio codec number for WMA_PRO - */ - public final static long WMA_PRO = 0x162; - - /** - * Stores the audio codec number for WMA (VBR) - */ - public final static long WMA_VBR = 0x7A22; - - /** - * Stores the average amount of bytes used by audio stream.
- * This value is a field within type specific data of audio stream. Maybe it - * could be used to calculate the KBPs. - */ - private long averageBytesPerSec; - - /** - * Amount of bits used per sample.
- */ - private int bitsPerSample; - - /** - * The block alignment of the audio data. - */ - private long blockAlignment; - - /** - * Number of channels. - */ - private long channelCount; - - /** - * Some data which needs to be interpreted if the codec is handled. - */ - private byte[] codecData = new byte[0]; - - /** - * The audio compression format code. - */ - private long compressionFormat; - - /** - * this field stores the error concealment type. - */ - private GUID errorConcealment; - - /** - * Sampling rate of audio stream. - */ - private long samplingRate; - - /** - * Creates an instance. - * - * @param chunkLen Length of the entire chunk (including guid and size) - */ - public AudioStreamChunk(final BigInteger chunkLen) { - super(GUID.GUID_AUDIOSTREAM, chunkLen); - } - - /** - * @return Returns the averageBytesPerSec. - */ - public long getAverageBytesPerSec() { - return this.averageBytesPerSec; - } - - /** - * @param avgeBytesPerSec The averageBytesPerSec to set. - */ - public void setAverageBytesPerSec(final long avgeBytesPerSec) { - this.averageBytesPerSec = avgeBytesPerSec; - } - - /** - * @return Returns the bitsPerSample. - */ - public int getBitsPerSample() { - return this.bitsPerSample; - } - - /** - * Sets the bitsPerSample - * - * @param bps - */ - public void setBitsPerSample(final int bps) { - this.bitsPerSample = bps; - } - - /** - * @return Returns the blockAlignment. - */ - public long getBlockAlignment() { - return this.blockAlignment; - } - - /** - * Sets the blockAlignment. - * - * @param align - */ - public void setBlockAlignment(final long align) { - this.blockAlignment = align; - } - - /** - * @return Returns the channelCount. - */ - public long getChannelCount() { - return this.channelCount; - } - - /** - * @param channels The channelCount to set. - */ - public void setChannelCount(final long channels) { - this.channelCount = channels; - } - - /** - * @return Returns the codecData. - */ - public byte[] getCodecData() { - return this.codecData.clone(); - } - - /** - * Sets the codecData - * - * @param codecSpecificData - */ - public void setCodecData(final byte[] codecSpecificData) { - if (codecSpecificData == null) { - throw new IllegalArgumentException(); - } - this.codecData = codecSpecificData.clone(); - } - - /** - * This method will take a look at {@link #compressionFormat}and returns a - * String with its hex value and if known a textual note on what coded it - * represents.
- * - * @return A description for the used codec. - */ - public String getCodecDescription() { - final StringBuilder result = new StringBuilder(Long - .toHexString(getCompressionFormat())); - String furtherDesc = " (Unknown)"; - for (final String[] aCODEC_DESCRIPTIONS : CODEC_DESCRIPTIONS) { - if (aCODEC_DESCRIPTIONS[0].equalsIgnoreCase(result.toString())) { - furtherDesc = aCODEC_DESCRIPTIONS[1]; - break; - } - } - if (result.length() % 2 == 0) { - result.insert(0, "0x"); - } else { - result.insert(0, "0x0"); - } - result.append(furtherDesc); - return result.toString(); - } - - /** - * @return Returns the compressionFormat. - */ - public long getCompressionFormat() { - return this.compressionFormat; - } - - /** - * @param cFormatCode The compressionFormat to set. - */ - public void setCompressionFormat(final long cFormatCode) { - this.compressionFormat = cFormatCode; - } - - /** - * @return Returns the errorConcealment. - */ - public GUID getErrorConcealment() { - return this.errorConcealment; - } - - /** - * This method sets the error concealment type which is given by two GUIDs.
- * - * @param errConc the type of error concealment the audio stream is stored as. - */ - public void setErrorConcealment(final GUID errConc) { - this.errorConcealment = errConc; - } - - /** - * This method takes the value of {@link #getAverageBytesPerSec()}and - * calculates the kbps out of it, by simply multiplying by 8 and dividing by - * 1000.
- * - * @return amount of bits per second in kilo bits. - */ - public int getKbps() { - return (int) getAverageBytesPerSec() * 8 / 1000; - } - - /** - * @return Returns the samplingRate. - */ - public long getSamplingRate() { - return this.samplingRate; - } - - /** - * @param sampRate The samplingRate to set. - */ - public void setSamplingRate(final long sampRate) { - this.samplingRate = sampRate; - } - - /** - * This mehtod returns whether the audio stream data is error concealed.
- * For now only interleaved concealment is known.
- * - * @return true if error concealment is used. - */ - public boolean isErrorConcealed() { - return getErrorConcealment().equals( - GUID.GUID_AUDIO_ERROR_CONCEALEMENT_INTERLEAVED); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.append(prefix).append(" |-> Audio info:").append( - Utils.LINE_SEPARATOR); - result.append(prefix).append(" | : Bitrate : ").append(getKbps()) - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" | : Channels : ").append( - getChannelCount()).append(" at ").append(getSamplingRate()) - .append(" Hz").append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" | : Bits per Sample: ").append( - getBitsPerSample()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" | : Formatcode: ").append( - getCodecDescription()).append(Utils.LINE_SEPARATOR); - return result.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/Chunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/Chunk.java deleted file mode 100644 index 5553a0d..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/Chunk.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; - -/** - * This class represents a chunk within ASF streams.
- * Each chunk starts with a 16byte {@linkplain GUID GUID} identifying the type. - * After that a number (represented by 8 bytes) follows which shows the size in - * bytes of the chunk. Finally there is the data of the chunk. - * - * @author Christian Laireiter - */ -public class Chunk { - - /** - * The length of current chunk.
- */ - protected final BigInteger chunkLength; - - /** - * The GUID of represented chunk header. - */ - protected final GUID guid; - - /** - * The position of current header object within file or stream. - */ - protected long position; - - /** - * Creates an instance - * - * @param headerGuid The GUID of header object. - * @param chunkLen Length of current chunk. - */ - public Chunk(final GUID headerGuid, final BigInteger chunkLen) { - if (headerGuid == null) { - throw new IllegalArgumentException("GUID must not be null."); - } - if (chunkLen == null || chunkLen.compareTo(BigInteger.ZERO) < 0) { - throw new IllegalArgumentException( - "chunkLen must not be null nor negative."); - } - this.guid = headerGuid; - this.chunkLength = chunkLen; - } - - /** - * Creates an instance - * - * @param headerGuid The GUID of header object. - * @param pos Position of header object within stream or file. - * @param chunkLen Length of current chunk. - */ - public Chunk(final GUID headerGuid, final long pos, - final BigInteger chunkLen) { - if (headerGuid == null) { - throw new IllegalArgumentException("GUID must not be null"); - } - if (pos < 0) { - throw new IllegalArgumentException( - "Position of header can't be negative."); - } - if (chunkLen == null || chunkLen.compareTo(BigInteger.ZERO) < 0) { - throw new IllegalArgumentException( - "chunkLen must not be null nor negative."); - } - this.guid = headerGuid; - this.position = pos; - this.chunkLength = chunkLen; - } - - /** - * This method returns the End of the current chunk introduced by current - * header object. - * - * @return Position after current chunk. - * @deprecated typo, use {@link #getChunkEnd()} instead. - */ - @Deprecated - public long getChunckEnd() { - return this.position + this.chunkLength.longValue(); - } - - /** - * This method returns the End of the current chunk introduced by current - * header object. - * - * @return Position after current chunk. - */ - public long getChunkEnd() { - return this.position + this.chunkLength.longValue(); - } - - /** - * @return Returns the chunkLength. - */ - public BigInteger getChunkLength() { - return this.chunkLength; - } - - /** - * @return Returns the guid. - */ - public GUID getGuid() { - return this.guid; - } - - /** - * @return Returns the position. - */ - public long getPosition() { - return this.position; - } - - /** - * Sets the position. - * - * @param pos position to set. - */ - public void setPosition(final long pos) { - this.position = pos; - } - - /** - * This method creates a String containing useful information prepared to be - * printed on STD-OUT.
- * This method is intended to be overwritten by inheriting classes. - * - * @param prefix each line gets this string prepended. - * @return Information of current Chunk Object. - */ - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(); - result.append(prefix).append("-> GUID: ").append( - GUID.getGuidDescription(this.guid)) - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" | : Starts at position: ").append( - getPosition()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" | : Last byte at: ").append( - getChunkEnd() - 1).append(Utils.LINE_SEPARATOR); - return result.toString(); - } - - /** - * (overridden) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return prettyPrint(""); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/ChunkContainer.java b/src/main/java/org/jaudiotagger/audio/asf/data/ChunkContainer.java deleted file mode 100644 index 0b0b63b..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/ChunkContainer.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.ChunkPositionComparator; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.util.*; - -/** - * Stores multiple ASF objects (chunks) in form of {@link Chunk} objects, and is - * itself an ASF object (chunk).
- *
- * Because current implementation is solely used for ASF metadata, all chunks - * (except for {@link StreamChunk}) may only be {@linkplain #addChunk(Chunk) - * inserted} once. - * - * @author Christian Laireiter - */ -public class ChunkContainer extends Chunk { - - /** - * Stores the {@link GUID} instances, which are allowed multiple times - * within an ASF header. - */ - private final static Set MULTI_CHUNKS; - - static { - MULTI_CHUNKS = new HashSet(); - MULTI_CHUNKS.add(GUID.GUID_STREAM); - } - - /** - * Stores the {@link Chunk} objects to their {@link GUID}. - */ - private final Map> chunkTable; - - /** - * Creates an instance. - * - * @param chunkGUID the GUID which identifies the chunk. - * @param pos the position of the chunk within the stream. - * @param length the length of the chunk. - */ - public ChunkContainer(final GUID chunkGUID, final long pos, - final BigInteger length) { - super(chunkGUID, pos, length); - this.chunkTable = new Hashtable>(); - } - - /** - * Tests whether all stored chunks have a unique starting position among - * their brothers. - * - * @param container the container to test. - * @return true if all chunks are located at an unique - * position. However, no intersection is tested. - */ - protected static boolean chunkstartsUnique(final ChunkContainer container) { - boolean result = true; - final Set chunkStarts = new HashSet(); - final Collection chunks = container.getChunks(); - for (final Chunk curr : chunks) { - result &= chunkStarts.add(curr.getPosition()); - } - return result; - } - - /** - * Adds a chunk to the container.
- * - * @param toAdd The chunk which is to be added. - * @throws IllegalArgumentException If a chunk of same type is already added, except for - * {@link StreamChunk}. - */ - public void addChunk(final Chunk toAdd) { - final List list = assertChunkList(toAdd.getGuid()); - if (!list.isEmpty() && !MULTI_CHUNKS.contains(toAdd.getGuid())) { - throw new IllegalArgumentException( - "The GUID of the given chunk indicates, that there is no more instance allowed."); //$NON-NLS-1$ - } - list.add(toAdd); - assert chunkstartsUnique(this) : "Chunk has equal start position like an already inserted one."; //$NON-NLS-1$ - } - - /** - * This method asserts that a {@link List} exists for the given {@link GUID} - * , in {@link #chunkTable}.
- * - * @param lookFor The GUID to get list for. - * @return an already existing, or newly created list. - */ - protected List assertChunkList(final GUID lookFor) { - List result = this.chunkTable.get(lookFor); - if (result == null) { - result = new ArrayList(); - this.chunkTable.put(lookFor, result); - } - return result; - } - - /** - * Returns a collection of all contained chunks.
- * - * @return all contained chunks - */ - public Collection getChunks() { - final List result = new ArrayList(); - for (final List curr : this.chunkTable.values()) { - result.addAll(curr); - } - return result; - } - - /** - * Looks for the first stored chunk which has the given GUID. - * - * @param lookFor GUID to look up. - * @param instanceOf The class which must additionally be matched. - * @return null if no chunk was found, or the stored instance - * doesn't match. - */ - protected Chunk getFirst(final GUID lookFor, - final Class instanceOf) { - Chunk result = null; - final List list = this.chunkTable.get(lookFor); - if (list != null && !list.isEmpty()) { - final Chunk chunk = list.get(0); - if (instanceOf.isAssignableFrom(chunk.getClass())) { - result = chunk; - } - } - return result; - } - - /** - * This method checks if a chunk has been {@linkplain #addChunk(Chunk) - * added} with specified {@linkplain Chunk#getGuid() GUID}.
- * - * @param lookFor GUID to look up. - * @return true if chunk with specified GUID has been added. - */ - public boolean hasChunkByGUID(final GUID lookFor) { - return this.chunkTable.containsKey(lookFor); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - return prettyPrint(prefix, ""); - } - - /** - * Nearly the same as {@link #prettyPrint(String)} however, additional - * information can be injected below the {@link Chunk#prettyPrint(String)} - * output and the listing of the contained chunks.
- * - * @param prefix The prefix to prepend. - * @param containerInfo Information to inject. - * @return Information of current Chunk Object. - */ - public String prettyPrint(final String prefix, final String containerInfo) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.append(containerInfo); - result.append(prefix).append(" |").append(Utils.LINE_SEPARATOR); - final ArrayList list = new ArrayList(getChunks()); - Collections.sort(list, new ChunkPositionComparator()); - - for (Chunk curr : list) { - result.append(curr.prettyPrint(prefix + " |")); - result.append(prefix).append(" |").append(Utils.LINE_SEPARATOR); - } - return result.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/ContainerType.java b/src/main/java/org/jaudiotagger/audio/asf/data/ContainerType.java deleted file mode 100644 index cac7a99..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/ContainerType.java +++ /dev/null @@ -1,283 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; -import org.jaudiotagger.logging.ErrorMessage; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.List; - -/** - * Enumerates capabilities, respectively uses, of metadata descriptors.
- *
- * The {@link #METADATA_LIBRARY_OBJECT} allows the most variations of data, as - * well as no size limitation (if it can be stored within a DWORD amount of - * bytes).
- * - * @author Christian Laireiter - */ -public enum ContainerType { - - /** - * The descriptor is used in the content branding object (chunk) - */ - CONTENT_BRANDING(GUID.GUID_CONTENT_BRANDING, 32, false, false, false, false), - - /** - * The descriptor is used in the content description object (chunk), so - * {@linkplain MetadataDescriptor#DWORD_MAXVALUE maximum data length} - * applies, no language index and stream number are allowed, as well as no - * multiple values. - */ - CONTENT_DESCRIPTION(GUID.GUID_CONTENTDESCRIPTION, 16, false, false, false, - false), - /** - * The descriptor is used in an extended content description object, so the - * {@linkplain MetadataDescriptor#DWORD_MAXVALUE maximum data size} applies, - * and no language index and stream number other than "0" is - * allowed. Additionally no multiple values are permitted. - */ - EXTENDED_CONTENT(GUID.GUID_EXTENDED_CONTENT_DESCRIPTION, 16, false, false, - false, false), - /** - * The descriptor is used in a metadata library object. No real size limit - * (except DWORD range) applies. Stream numbers and language indexes can be - * specified. - */ - METADATA_LIBRARY_OBJECT(GUID.GUID_METADATA_LIBRARY, 32, true, true, true, - true), - /** - * The descriptor is used in a metadata object. The - * {@linkplain MetadataDescriptor#DWORD_MAXVALUE maximum data size} applies. - * Stream numbers can be specified. But no language index (always - * "0"). - */ - METADATA_OBJECT(GUID.GUID_METADATA, 16, false, true, false, true); - - /** - * Stores the guid that identifies ASF chunks which store metadata of the - * current type. - */ - private final GUID containerGUID; - /** - * true if the descriptor field can store {@link GUID} values. - */ - private final boolean guidEnabled; - /** - * true if descriptor field can refer to a language. - */ - private final boolean languageEnabled; - /** - * The maximum amount of bytes the descriptor data may consume.
- */ - private final BigInteger maximumDataLength; - /** - * true if the container may store multiple values of the same - * metadata descriptor specification (equality on name, language, and - * stream).
- * WindowsMedia players advanced tag editor for example stores the - * WM/Picture attribute once in the extended content description, and all - * others in the metadata library object. - */ - private final boolean multiValued; - /** - * if -1 a size value has to be compared against - * {@link #maximumDataLength} because {@link Long#MAX_VALUE} is exceeded.
- * Otherwise this is the {@link BigInteger#longValue()} representation. - */ - private final long perfMaxDataLen; - /** - * true if descriptor field can refer to specific streams. - */ - private final boolean streamEnabled; - - /** - * Creates an instance - * - * @param guid see {@link #containerGUID} - * @param maxDataLenBits The amount of bits that is used to represent an unsigned value - * for the containers size descriptors. Will create a maximum - * value for {@link #maximumDataLength}. (2 ^ maxDataLenBits -1) - * @param guidAllowed see {@link #guidEnabled} - * @param stream see {@link #streamEnabled} - * @param language see {@link #languageEnabled} - * @param multiValue see {@link #multiValued} - */ - ContainerType(final GUID guid, final int maxDataLenBits, - final boolean guidAllowed, final boolean stream, - final boolean language, final boolean multiValue) { - this.containerGUID = guid; - this.maximumDataLength = BigInteger.valueOf(2).pow(maxDataLenBits) - .subtract(BigInteger.ONE); - if (this.maximumDataLength - .compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { - this.perfMaxDataLen = this.maximumDataLength.longValue(); - } else { - this.perfMaxDataLen = -1; - } - this.guidEnabled = guidAllowed; - this.streamEnabled = stream; - this.languageEnabled = language; - this.multiValued = multiValue; - } - - /** - * Determines if low has <= index as high, in respect to - * {@link #getOrdered()} - * - * @param low - * @param high - * @return true if in correct order. - */ - public static boolean areInCorrectOrder(final ContainerType low, - final ContainerType high) { - final List asList = Arrays.asList(getOrdered()); - return asList.indexOf(low) <= asList.indexOf(high); - } - - /** - * Returns the elements in an order, that indicates more capabilities - * (ascending).
- * - * @return capability ordered types - */ - public static ContainerType[] getOrdered() { - return new ContainerType[]{CONTENT_DESCRIPTION, CONTENT_BRANDING, EXTENDED_CONTENT, METADATA_OBJECT, METADATA_LIBRARY_OBJECT}; - } - - /** - * Calls {@link #checkConstraints(String, byte[], int, int, int)} and - * actually throws the exception if there is one. - * - * @param name name of the descriptor - * @param data content - * @param type data type - * @param stream stream number - * @param language language index - */ - public void assertConstraints(final String name, final byte[] data, - final int type, final int stream, final int language) { - final RuntimeException result = checkConstraints(name, data, type, - stream, language); - if (result != null) { - throw result; - } - } - - /** - * Checks if the values for a {@linkplain MetadataDescriptor content - * descriptor} match the contraints of the container type, and returns a - * {@link RuntimeException} if the requirements aren't met. - * - * @param name name of the descriptor - * @param data content - * @param type data type - * @param stream stream number - * @param language language index - * @return null if everything is fine. - */ - public RuntimeException checkConstraints(final String name, - final byte[] data, final int type, final int stream, - final int language) { - RuntimeException result = null; - // TODO generate tests - if (name == null || data == null) { - result = new IllegalArgumentException("Arguments must not be null."); - } else { - if (!Utils.isStringLengthValidNullSafe(name)) { - result = new IllegalArgumentException( - ErrorMessage.WMA_LENGTH_OF_STRING_IS_TOO_LARGE - .getMsg(name.length())); - } - } - if (result == null && !isWithinValueRange(data.length)) { - result = new IllegalArgumentException( - ErrorMessage.WMA_LENGTH_OF_DATA_IS_TOO_LARGE.getMsg( - data.length, getMaximumDataLength(), - getContainerGUID().getDescription())); - } - if (result == null - && (stream < 0 || stream > MetadataDescriptor.MAX_STREAM_NUMBER || (!isStreamNumberEnabled() && stream != 0))) { - final String streamAllowed = isStreamNumberEnabled() ? "0 to 127" - : "0"; - result = new IllegalArgumentException( - ErrorMessage.WMA_INVALID_STREAM_REFERNCE.getMsg(stream, - streamAllowed, getContainerGUID().getDescription())); - } - if (result == null && type == MetadataDescriptor.TYPE_GUID - && !isGuidEnabled()) { - result = new IllegalArgumentException( - ErrorMessage.WMA_INVALID_GUID_USE.getMsg(getContainerGUID() - .getDescription())); - } - if (result == null - && ((language != 0 && !isLanguageEnabled()) || (language < 0 || language >= MetadataDescriptor.MAX_LANG_INDEX))) { - final String langAllowed = isStreamNumberEnabled() ? "0 to 126" - : "0"; - result = new IllegalArgumentException( - ErrorMessage.WMA_INVALID_LANGUAGE_USE.getMsg(language, - getContainerGUID().getDescription(), langAllowed)); - } - if (result == null && this == CONTENT_DESCRIPTION - && type != MetadataDescriptor.TYPE_STRING) { - result = new IllegalArgumentException( - ErrorMessage.WMA_ONLY_STRING_IN_CD.getMsg()); - } - return result; - } - - /** - * @return the containerGUID - */ - public GUID getContainerGUID() { - return this.containerGUID; - } - - /** - * @return the maximumDataLength - */ - public BigInteger getMaximumDataLength() { - return this.maximumDataLength; - } - - /** - * @return the guidEnabled - */ - public boolean isGuidEnabled() { - return this.guidEnabled; - } - - /** - * @return the languageEnabled - */ - public boolean isLanguageEnabled() { - return this.languageEnabled; - } - - /** - * Tests if the given value is less than or equal to - * {@link #getMaximumDataLength()}, and greater or equal to zero.
- * - * @param value The value to test - * @return true if size restrictions for binary data are met - * with this container type. - */ - public boolean isWithinValueRange(final long value) { - return (this.perfMaxDataLen == -1 || this.perfMaxDataLen >= value) - && value >= 0; - } - - /** - * @return the multiValued - */ - public boolean isMultiValued() { - return this.multiValued; - } - - /** - * @return the streamEnabled - */ - public boolean isStreamNumberEnabled() { - return this.streamEnabled; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/ContentBranding.java b/src/main/java/org/jaudiotagger/audio/asf/data/ContentBranding.java deleted file mode 100644 index 3ef509c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/ContentBranding.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.OutputStream; -import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; - -/** - * This structure represents the value of the content branding object, which - * stores the banner image, the banner image URL and the copyright URL.
- * - * @author Christian Laireiter - */ -public final class ContentBranding extends MetadataContainer { - - /** - * Stores the allowed {@linkplain MetadataDescriptor#getName() descriptor - * keys}. - */ - public final static Set ALLOWED; - - /** - * Descriptor key representing the banner image. - */ - public final static String KEY_BANNER_IMAGE = "BANNER_IMAGE"; - - /** - * Descriptor key representing the banner image type.
- *
- * Known/valid values are: - *

    - *
  1. 0: there is no image present
  2. - *
  3. 1: there is a BMP image
  4. - *
  5. 2: there is a JPEG image
  6. - *
  7. 3: there is a GIF image
  8. - *
- */ - public final static String KEY_BANNER_TYPE = "BANNER_IMAGE_TYPE"; - - /** - * Descriptor key representing the banner image URL. - */ - public final static String KEY_BANNER_URL = "BANNER_IMAGE_URL"; - - /** - * Descriptor key representing the copyright URL. - */ - public final static String KEY_COPYRIGHT_URL = "COPYRIGHT_URL"; - - static { - ALLOWED = new HashSet(); - ALLOWED.add(KEY_BANNER_IMAGE); - ALLOWED.add(KEY_BANNER_TYPE); - ALLOWED.add(KEY_BANNER_URL); - ALLOWED.add(KEY_COPYRIGHT_URL); - } - - /** - * Creates an instance. - */ - public ContentBranding() { - this(0, BigInteger.ZERO); - } - - /** - * Creates an instance. - * - * @param pos Position of content description within file or stream - * @param size Length of content description. - */ - public ContentBranding(final long pos, final BigInteger size) { - super(ContainerType.CONTENT_BRANDING, pos, size); - } - - /** - * Returns the banner image URL. - * - * @return the banner image URL. - */ - public String getBannerImageURL() { - return getValueFor(KEY_BANNER_URL); - } - - /** - * This method sets the banner image URL, if imageURL is not - * blank.
- * - * @param imageURL image URL to set. - */ - public void setBannerImageURL(final String imageURL) { - if (Utils.isBlank(imageURL)) { - removeDescriptorsByName(KEY_BANNER_URL); - } else { - assertDescriptor(KEY_BANNER_URL).setStringValue(imageURL); - } - } - - /** - * Returns the copyright URL. - * - * @return the banner image URL. - */ - public String getCopyRightURL() { - return getValueFor(KEY_COPYRIGHT_URL); - } - - /** - * This method sets the copyright URL, if copyRight is not - * blank.
- * - * @param copyRight copyright URL to set. - */ - public void setCopyRightURL(final String copyRight) { - if (Utils.isBlank(copyRight)) { - removeDescriptorsByName(KEY_COPYRIGHT_URL); - } else { - assertDescriptor(KEY_COPYRIGHT_URL).setStringValue(copyRight); - } - } - - /** - * {@inheritDoc} - */ - @Override - public long getCurrentAsfChunkSize() { - // GUID, size, image type, image data size, image url data size, - // copyright data size - long result = 40; - result += assertDescriptor(KEY_BANNER_IMAGE, - MetadataDescriptor.TYPE_BINARY).getRawDataSize(); - result += getBannerImageURL().length(); - result += getCopyRightURL().length(); - return result; - } - - /** - * Returns the binary image data. - * - * @return binary image data. - */ - public byte[] getImageData() { - return assertDescriptor(KEY_BANNER_IMAGE, - MetadataDescriptor.TYPE_BINARY).getRawData(); - } - - /** - * Returns the image type.
- * - * @return image type - * @see #KEY_BANNER_TYPE for known/valid values. - */ - public long getImageType() { - if (!hasDescriptor(KEY_BANNER_TYPE)) { - final MetadataDescriptor descriptor = new MetadataDescriptor( - ContainerType.CONTENT_BRANDING, KEY_BANNER_TYPE, - MetadataDescriptor.TYPE_DWORD); - descriptor.setDWordValue(0); - addDescriptor(descriptor); - } - return assertDescriptor(KEY_BANNER_TYPE).getNumber(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAddSupported(final MetadataDescriptor descriptor) { - return ALLOWED.contains(descriptor.getName()) - && super.isAddSupported(descriptor); - } - - /** - * @param imageType - * @param imageData - */ - public void setImage(final long imageType, final byte[] imageData) { - assert imageType >= 0 && imageType <= 3; - assert imageType > 0 || imageData.length == 0; - assertDescriptor(KEY_BANNER_TYPE, MetadataDescriptor.TYPE_DWORD) - .setDWordValue(imageType); - assertDescriptor(KEY_BANNER_IMAGE, MetadataDescriptor.TYPE_BINARY) - .setBinaryValue(imageData); - } - - /** - * {@inheritDoc} - */ - @Override - public long writeInto(final OutputStream out) throws IOException { - final long chunkSize = getCurrentAsfChunkSize(); - out.write(getGuid().getBytes()); - Utils.writeUINT64(chunkSize, out); - Utils.writeUINT32(getImageType(), out); - assert getImageType() >= 0 && getImageType() <= 3; - final byte[] imageData = getImageData(); - assert getImageType() > 0 || imageData.length == 0; - Utils.writeUINT32(imageData.length, out); - out.write(imageData); - Utils.writeUINT32(getBannerImageURL().length(), out); - out.write(getBannerImageURL().getBytes("ASCII")); - Utils.writeUINT32(getCopyRightURL().length(), out); - out.write(getCopyRightURL().getBytes("ASCII")); - return chunkSize; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/ContentDescription.java b/src/main/java/org/jaudiotagger/audio/asf/data/ContentDescription.java deleted file mode 100644 index 8bd04d8..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/ContentDescription.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.OutputStream; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * This class represents the data of a chunk which contains title, author, - * copyright, description and the rating of the file.
- * It is optional within ASF files. But if, exists only once. - * - * @author Christian Laireiter - */ -public final class ContentDescription extends MetadataContainer { - /** - * Stores the only allowed keys of this metadata container. - */ - public final static Set ALLOWED; - - /** - * Field key for author. - */ - public final static String KEY_AUTHOR = "AUTHOR"; - - /** - * Field key for copyright. - */ - public final static String KEY_COPYRIGHT = "COPYRIGHT"; - - /** - * Field key for description. - */ - public final static String KEY_DESCRIPTION = "DESCRIPTION"; - - /** - * Field key for rating. - */ - public final static String KEY_RATING = "RATING"; - - /** - * Field key for title. - */ - public final static String KEY_TITLE = "TITLE"; - - static { - ALLOWED = new HashSet(Arrays.asList(KEY_AUTHOR, - KEY_COPYRIGHT, KEY_DESCRIPTION, KEY_RATING, KEY_TITLE)); - } - - /** - * Creates an instance.
- */ - public ContentDescription() { - this(0, BigInteger.ZERO); - } - - /** - * Creates an instance. - * - * @param pos Position of content description within file or stream - * @param chunkLen Length of content description. - */ - public ContentDescription(final long pos, final BigInteger chunkLen) { - super(ContainerType.CONTENT_DESCRIPTION, pos, chunkLen); - } - - /** - * @return Returns the author. - */ - public String getAuthor() { - return getValueFor(KEY_AUTHOR); - } - - /** - * @param fileAuthor The author to set. - * @throws IllegalArgumentException If "UTF-16LE"-byte-representation would take more than 65535 - * bytes. - */ - public void setAuthor(final String fileAuthor) throws IllegalArgumentException { - setStringValue(KEY_AUTHOR, fileAuthor); - } - - /** - * @return Returns the comment. - */ - public String getComment() { - return getValueFor(KEY_DESCRIPTION); - } - - /** - * @param tagComment The comment to set. - * @throws IllegalArgumentException If "UTF-16LE"-byte-representation would take more than 65535 - * bytes. - */ - public void setComment(final String tagComment) throws IllegalArgumentException { - setStringValue(KEY_DESCRIPTION, tagComment); - } - - /** - * @return Returns the copyRight. - */ - public String getCopyRight() { - return getValueFor(KEY_COPYRIGHT); - } - - /** - * {@inheritDoc} - */ - @Override - public long getCurrentAsfChunkSize() { - long result = 44; // GUID + UINT64 for size + 5 times string length - // (each - // 2 bytes) + 5 times zero term char (2 bytes each). - result += getAuthor().length() * 2; // UTF-16LE - result += getComment().length() * 2; - result += getRating().length() * 2; - result += getTitle().length() * 2; - result += getCopyRight().length() * 2; - return result; - } - - /** - * @return returns the rating. - */ - public String getRating() { - return getValueFor(KEY_RATING); - } - - /** - * @param ratingText The rating to be set. - * @throws IllegalArgumentException If "UTF-16LE"-byte-representation would take more than 65535 - * bytes. - */ - public void setRating(final String ratingText) throws IllegalArgumentException { - setStringValue(KEY_RATING, ratingText); - } - - /** - * @return Returns the title. - */ - public String getTitle() { - return getValueFor(KEY_TITLE); - } - - /** - * @param songTitle The title to set. - * @throws IllegalArgumentException If "UTF-16LE"-byte-representation would take more than 65535 - * bytes. - */ - public void setTitle(final String songTitle) throws IllegalArgumentException { - setStringValue(KEY_TITLE, songTitle); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAddSupported(final MetadataDescriptor descriptor) { - return ALLOWED.contains(descriptor.getName()) - && super.isAddSupported(descriptor); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.append(prefix).append(" |->Title : ").append(getTitle()) - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Author : ").append(getAuthor()) - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Copyright : ").append( - getCopyRight()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Description: ").append(getComment()) - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Rating :").append(getRating()) - .append(Utils.LINE_SEPARATOR); - return result.toString(); - } - - /** - * @param cpright The copyRight to set. - * @throws IllegalArgumentException If "UTF-16LE"-byte-representation would take more than 65535 - * bytes. - */ - public void setCopyright(final String cpright) throws IllegalArgumentException { - setStringValue(KEY_COPYRIGHT, cpright); - } - - /** - * {@inheritDoc} - */ - @Override - public long writeInto(final OutputStream out) throws IOException { - final long chunkSize = getCurrentAsfChunkSize(); - - out.write(this.getGuid().getBytes()); - Utils.writeUINT64(getCurrentAsfChunkSize(), out); - // write the sizes of the string representations plus 2 bytes zero term - // character - Utils.writeUINT16(getTitle().length() * 2 + 2, out); - Utils.writeUINT16(getAuthor().length() * 2 + 2, out); - Utils.writeUINT16(getCopyRight().length() * 2 + 2, out); - Utils.writeUINT16(getComment().length() * 2 + 2, out); - Utils.writeUINT16(getRating().length() * 2 + 2, out); - // write the Strings - out.write(Utils.getBytes(getTitle(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - out.write(Utils.getBytes(getAuthor(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - out.write(Utils.getBytes(getCopyRight(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - out.write(Utils.getBytes(getComment(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - out.write(Utils.getBytes(getRating(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - return chunkSize; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/EncodingChunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/EncodingChunk.java deleted file mode 100644 index a727135..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/EncodingChunk.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * This class was intended to store the data of a chunk which contained the - * encoding parameters in textual form.
- * Since the needed parameters were found in other chunks the implementation of - * this class was paused.
- * TODO complete analysis. - * - * @author Christian Laireiter - */ -public class EncodingChunk extends Chunk { - - /** - * The read strings. - */ - private final List strings; - - /** - * Creates an instance. - * - * @param chunkLen Length of current chunk. - */ - public EncodingChunk(final BigInteger chunkLen) { - super(GUID.GUID_ENCODING, chunkLen); - this.strings = new ArrayList(); - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void addString(final String toAdd) { - this.strings.add(toAdd); - } - - /** - * This method returns a collection of all {@linkplain String Strings} which - * were added due {@link #addString(String)}. - * - * @return Inserted Strings. - */ - public Collection getStrings() { - return new ArrayList(this.strings); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super - .prettyPrint(prefix)); - this.strings.iterator(); - for (final String string : this.strings) { - result.append(prefix).append(" | : ").append(string).append( - Utils.LINE_SEPARATOR); - } - return result.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/EncryptionChunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/EncryptionChunk.java deleted file mode 100644 index 3105224..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/EncryptionChunk.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collection; - -/** - * @author eric - */ -public class EncryptionChunk extends Chunk { - /** - * The read strings. - */ - private final ArrayList strings; - private String keyID; - private String licenseURL; - private String protectionType; - private String secretData; - - /** - * Creates an instance. - * - * @param chunkLen Length of current chunk. - */ - public EncryptionChunk(final BigInteger chunkLen) { - super(GUID.GUID_CONTENT_ENCRYPTION, chunkLen); - this.strings = new ArrayList(); - this.secretData = ""; - this.protectionType = ""; - this.keyID = ""; - this.licenseURL = ""; - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void addString(final String toAdd) { - this.strings.add(toAdd); - } - - /** - * This method gets the keyID. - * - * @return - */ - public String getKeyID() { - return this.keyID; - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void setKeyID(final String toAdd) { - this.keyID = toAdd; - } - - /** - * This method gets the license URL. - * - * @return - */ - public String getLicenseURL() { - return this.licenseURL; - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void setLicenseURL(final String toAdd) { - this.licenseURL = toAdd; - } - - /** - * This method gets the secret data. - * - * @return - */ - public String getProtectionType() { - return this.protectionType; - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void setProtectionType(final String toAdd) { - this.protectionType = toAdd; - } - - /** - * This method gets the secret data. - * - * @return - */ - public String getSecretData() { - return this.secretData; - } - - /** - * This method adds the secret data. - * - * @param toAdd String to add. - */ - public void setSecretData(final String toAdd) { - this.secretData = toAdd; - } - - /** - * This method returns a collection of all {@link String}s which were addid - * due {@link #addString(String)}. - * - * @return Inserted Strings. - */ - public Collection getStrings() { - return new ArrayList(this.strings); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.insert(0, Utils.LINE_SEPARATOR + prefix + " Encryption:" - + Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->keyID ").append(this.keyID).append( - Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->secretData ").append(this.secretData) - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->protectionType ").append( - this.protectionType).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->licenseURL ").append(this.licenseURL) - .append(Utils.LINE_SEPARATOR); - this.strings.iterator(); - for (final String string : this.strings) { - result.append(prefix).append(" |->").append(string).append(Utils.LINE_SEPARATOR); - } - return result.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/FileHeader.java b/src/main/java/org/jaudiotagger/audio/asf/data/FileHeader.java deleted file mode 100644 index 82e228d..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/FileHeader.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.util.Date; - -/** - * This class stores the information about the file, which is contained within a - * special chunk of ASF files.
- * - * @author Christian Laireiter - */ -public class FileHeader extends Chunk { - - /** - * Duration of the media content in 100ns steps. - */ - private final BigInteger duration; - - /** - * The time the file was created. - */ - private final Date fileCreationTime; - - /** - * Size of the file or stream. - */ - private final BigInteger fileSize; - - /** - * Usually contains value of 2. - */ - private final long flags; - - /** - * Maximum size of stream packages.
- * Warning: must be same size as {@link #minPackageSize}. Its not - * known how to handle deviating values. - */ - private final long maxPackageSize; - - /** - * Minimun size of stream packages.
- * Warning: must be same size as {@link #maxPackageSize}. Its not - * known how to handle deviating values. - */ - private final long minPackageSize; - - /** - * Number of stream packages within the File. - */ - private final BigInteger packageCount; - - /** - * No Idea of the Meaning, but stored anyway.
- * Source documentation says it is: "Timestamp of end position" - */ - private final BigInteger timeEndPos; - - /** - * Like {@link #timeEndPos}no Idea. - */ - private final BigInteger timeStartPos; - - /** - * Size of an uncompressed video frame. - */ - private final long uncompressedFrameSize; - - /** - * Creates an instance. - * - * @param chunckLen Length of the file header (chunk) - * @param size Size of file or stream - * @param fileTime Time file or stream was created. Time is calculated since 1st - * january of 1601 in 100ns steps. - * @param pkgCount Number of stream packages. - * @param dur Duration of media clip in 100ns steps - * @param timestampStart Timestamp of start {@link #timeStartPos} - * @param timestampEnd Timestamp of end {@link #timeEndPos} - * @param headerFlags some stream related flags. - * @param minPkgSize minimum size of packages - * @param maxPkgSize maximum size of packages - * @param uncmpVideoFrameSize Size of an uncompressed Video Frame. - */ - public FileHeader(final BigInteger chunckLen, final BigInteger size, - final BigInteger fileTime, final BigInteger pkgCount, - final BigInteger dur, final BigInteger timestampStart, - final BigInteger timestampEnd, final long headerFlags, - final long minPkgSize, final long maxPkgSize, - final long uncmpVideoFrameSize) { - super(GUID.GUID_FILE, chunckLen); - this.fileSize = size; - this.packageCount = pkgCount; - this.duration = dur; - this.timeStartPos = timestampStart; - this.timeEndPos = timestampEnd; - this.flags = headerFlags; - this.minPackageSize = minPkgSize; - this.maxPackageSize = maxPkgSize; - this.uncompressedFrameSize = uncmpVideoFrameSize; - this.fileCreationTime = Utils.getDateOf(fileTime).getTime(); - } - - /** - * @return Returns the duration. - */ - public BigInteger getDuration() { - return this.duration; - } - - /** - * This method converts {@link #getDuration()}from 100ns steps to normal - * seconds. - * - * @return Duration of the media in seconds. - */ - public int getDurationInSeconds() { - return this.duration.divide(new BigInteger("10000000")).intValue(); - } - - /** - * @return Returns the fileCreationTime. - */ - public Date getFileCreationTime() { - return new Date(this.fileCreationTime.getTime()); - } - - /** - * @return Returns the fileSize. - */ - public BigInteger getFileSize() { - return this.fileSize; - } - - /** - * @return Returns the flags. - */ - public long getFlags() { - return this.flags; - } - - /** - * @return Returns the maxPackageSize. - */ - public long getMaxPackageSize() { - return this.maxPackageSize; - } - - /** - * @return Returns the minPackageSize. - */ - public long getMinPackageSize() { - return this.minPackageSize; - } - - /** - * @return Returns the packageCount. - */ - public BigInteger getPackageCount() { - return this.packageCount; - } - - /** - * This method converts {@link #getDuration()} from 100ns steps to normal - * seconds with a fractional part taking milliseconds.
- * - * @return The duration of the media in seconds (with a precision of - * milliseconds) - */ - public float getPreciseDuration() { - return (float) (getDuration().doubleValue() / 10000000d); - } - - /** - * @return Returns the timeEndPos. - */ - public BigInteger getTimeEndPos() { - return this.timeEndPos; - } - - /** - * @return Returns the timeStartPos. - */ - public BigInteger getTimeStartPos() { - return this.timeStartPos; - } - - /** - * @return Returns the uncompressedFrameSize. - */ - public long getUncompressedFrameSize() { - return this.uncompressedFrameSize; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.asf.data.Chunk#prettyPrint(String) - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.append(prefix).append(" |-> Filesize = ").append( - getFileSize().toString()).append(" Bytes").append( - Utils.LINE_SEPARATOR); - result.append(prefix).append(" |-> Media duration= ").append( - getDuration().divide(new BigInteger("10000")).toString()) - .append(" ms").append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |-> Created at = ").append( - getFileCreationTime()).append(Utils.LINE_SEPARATOR); - return result.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/GUID.java b/src/main/java/org/jaudiotagger/audio/asf/data/GUID.java deleted file mode 100644 index aae250f..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/GUID.java +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * This class is used for representation of GUIDs and as a reference list of all - * Known GUIDs.
- * - * @author Christian Laireiter - */ -public final class GUID { - - /** - * This constant defines the GUID for stream chunks describing audio - * streams, indicating the the audio stream has no error concealment.
- */ - public final static GUID GUID_AUDIO_ERROR_CONCEALEMENT_ABSENT = new GUID( - new int[]{0x40, 0xA4, 0xF1, 0x49, 0xCE, 0x4E, 0xD0, 0x11, 0xA3, - 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6}, - "Audio error concealment absent."); - - /** - * This constant defines the GUID for stream chunks describing audio - * streams, indicating the the audio stream has interleaved error - * concealment.
- */ - public final static GUID GUID_AUDIO_ERROR_CONCEALEMENT_INTERLEAVED = new GUID( - new int[]{0x40, 0xA4, 0xF1, 0x49, 0xCE, 0x4E, 0xD0, 0x11, 0xA3, - 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6}, - "Interleaved audio error concealment."); - - /** - * This constant stores the GUID indicating that stream type is audio. - */ - public final static GUID GUID_AUDIOSTREAM = new GUID(new int[]{0x40, - 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, - 0x5F, 0x5C, 0x44, 0x2B}, " Audio stream"); - - /** - * This constant stores the GUID indicating a content branding object. - */ - public final static GUID GUID_CONTENT_BRANDING = new GUID(new int[]{0xFA, - 0xB3, 0x11, 0x22, 0x23, 0xBD, 0xD2, 0x11, 0xB4, 0xB7, 0x00, 0xA0, - 0xC9, 0x55, 0xFC, 0x6E}, "Content Branding"); - - /** - * This is for the Content Encryption Object - * 2211B3FB-BD23-11D2-B4B7-00A0C955FC6E, needs to be little-endian. - */ - public final static GUID GUID_CONTENT_ENCRYPTION = new GUID(new int[]{ - 0xfb, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, - 0xa0, 0xc9, 0x55, 0xfc, 0x6e}, "Content Encryption Object"); - - /** - * This constant represents the guidData for a chunk which contains Title, - * author, copyright, description and rating. - */ - public final static GUID GUID_CONTENTDESCRIPTION = new GUID(new int[]{ - 0x33, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, - 0xAA, 0x00, 0x62, 0xCE, 0x6C}, "Content Description"); - - /** - * This constant stores the GUID for Encoding-Info chunks. - */ - public final static GUID GUID_ENCODING = new GUID(new int[]{0x40, 0x52, - 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, - 0x03, 0x48, 0xF6}, "Encoding description"); - - /** - * This constant defines the GUID for a WMA "Extended Content Description" - * chunk.
- */ - public final static GUID GUID_EXTENDED_CONTENT_DESCRIPTION = new GUID( - new int[]{0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, - 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50}, - "Extended Content Description"); - - /** - * GUID of ASF file header. - */ - public final static GUID GUID_FILE = new GUID(new int[]{0xA1, 0xDC, 0xAB, - 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, - 0x53, 0x65}, "File header"); - - /** - * This constant defines the GUID of a asf header chunk. - */ - public final static GUID GUID_HEADER = new GUID(new int[]{0x30, 0x26, - 0xb2, 0x75, 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, - 0x62, 0xce, 0x6c}, "Asf header"); - - /** - * This constant stores a GUID whose functionality is unknown. - */ - public final static GUID GUID_HEADER_EXTENSION = new GUID(new int[]{0xB5, - 0x03, 0xBF, 0x5F, 0x2E, 0xA9, 0xCF, 0x11, 0x8E, 0xE3, 0x00, 0xC0, - 0x0C, 0x20, 0x53, 0x65}, "Header Extension"); - - /** - * This constant stores the GUID indicating the asf language list object.
- */ - public final static GUID GUID_LANGUAGE_LIST = new GUID(new int[]{0xa9, - 0x46, 0x43, 0x7c, 0xe0, 0xef, 0xfc, 0x4b, 0xb2, 0x29, 0x39, 0x3e, - 0xde, 0x41, 0x5c, 0x85}, "Language List"); - - /** - * This constant stores the length of GUIDs used with ASF streams.
- */ - public final static int GUID_LENGTH = 16; - - /** - * This constant stores the GUID indicating the asf metadata object.
- */ - public final static GUID GUID_METADATA = new GUID(new int[]{0xea, 0xcb, - 0xf8, 0xc5, 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, - 0xfa, 0x4c, 0xca}, "Metadata"); - - /** - * This constant stores the GUID indicating the asf metadata library object.
- */ - public final static GUID GUID_METADATA_LIBRARY = new GUID(new int[]{0x94, - 0x1c, 0x23, 0x44, 0x98, 0x94, 0xd1, 0x49, 0xa1, 0x41, 0x1d, 0x13, - 0x4e, 0x45, 0x70, 0x54}, "Metadata Library"); - /** - * This constant stores the GUID indicating a stream object. - */ - public final static GUID GUID_STREAM = new GUID(new int[]{0x91, 0x07, - 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, - 0x20, 0x53, 0x65}, "Stream"); - /** - * This constant stores a GUID indicating a "stream bitrate properties" - * chunk. - */ - public final static GUID GUID_STREAM_BITRATE_PROPERTIES = new GUID( - new int[]{0xCE, 0x75, 0xF8, 0x7B, 0x8D, 0x46, 0xD1, 0x11, 0x8D, - 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2}, - "Stream bitrate properties"); - /** - * This constant represents a GUID implementation which can be used for - * generic implementations, which have to provide a GUID, but do not really - * require a specific GUID to work. - */ - public final static GUID GUID_UNSPECIFIED = new GUID(new int[]{0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, "Unspecified"); - /** - * This constant stores the GUID indicating that stream type is video. - */ - public final static GUID GUID_VIDEOSTREAM = new GUID(new int[]{0xC0, - 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, - 0x5F, 0x5C, 0x44, 0x2B}, "Video stream"); - /** - * This field stores all known GUIDs. - */ - public final static GUID[] KNOWN_GUIDS; - /** - * This constant stores the GUID for a "script command object".
- */ - public final static GUID SCRIPT_COMMAND_OBJECT = new GUID(new int[]{0x30, - 0x1a, 0xfb, 0x1e, 0x62, 0x0b, 0xd0, 0x11, 0xa3, 0x9b, 0x00, 0xa0, - 0xc9, 0x03, 0x48, 0xf6}, "Script Command Object"); - /** - * The GUID String values format.
- */ - private final static Pattern GUID_PATTERN = Pattern - .compile( - "[a-f0-9]{8}\\-[a-f0-9]{4}\\-[a-f0-9]{4}\\-[a-f0-9]{4}\\-[a-f0-9]{12}", - Pattern.CASE_INSENSITIVE); - /** - * This map is used, to get the description of a GUID instance, which has - * been created by reading.
- * The map comparison is done against the {@link GUID#guidData} field. But - * only the {@link #KNOWN_GUIDS} have a description set. - */ - private final static Map GUID_TO_CONFIGURED; - - static { - KNOWN_GUIDS = new GUID[]{GUID_AUDIO_ERROR_CONCEALEMENT_ABSENT, - GUID_CONTENTDESCRIPTION, GUID_AUDIOSTREAM, GUID_ENCODING, - GUID_FILE, GUID_HEADER, GUID_STREAM, - GUID_EXTENDED_CONTENT_DESCRIPTION, GUID_VIDEOSTREAM, - GUID_HEADER_EXTENSION, GUID_STREAM_BITRATE_PROPERTIES, - SCRIPT_COMMAND_OBJECT, GUID_CONTENT_ENCRYPTION, - GUID_CONTENT_BRANDING, GUID_UNSPECIFIED, GUID_METADATA_LIBRARY, - GUID_METADATA, GUID_LANGUAGE_LIST}; - GUID_TO_CONFIGURED = new HashMap(KNOWN_GUIDS.length); - for (final GUID curr : KNOWN_GUIDS) { - assert !GUID_TO_CONFIGURED.containsKey(curr) : "Double definition: \"" - + GUID_TO_CONFIGURED.get(curr).getDescription() - + "\" <-> \"" + curr.getDescription() + "\""; - GUID_TO_CONFIGURED.put(curr, curr); - } - } - - /** - * Stores an optionally description of the GUID. - */ - private String description = ""; - /** - * An instance of this class stores the value of the wrapped GUID in this - * field.
- */ - private int[] guidData = null; - /** - * Stores the hash code of the object.
- * "-1" if not determined yet. - */ - private int hash; - - /** - * Creates an instance and assigns given value.
- * - * @param value GUID, which should be assigned. (will be converted to int[]) - */ - public GUID(final byte[] value) { - assert value != null; - final int[] tmp = new int[value.length]; - for (int i = 0; i < value.length; i++) { - tmp[i] = (0xFF & value[i]); - } - setGUID(tmp); - } - - /** - * Creates an instance and assigns given value.
- * - * @param value GUID, which should be assigned. - */ - public GUID(final int[] value) { - setGUID(value); - } - - /** - * Creates an instance like {@link #GUID(int[])}and sets the optional - * description.
- * - * @param value GUID, which should be assigned. - * @param desc Description for the GUID. - */ - public GUID(final int[] value, final String desc) { - this(value); - if (desc == null) { - throw new IllegalArgumentException("Argument must not be null."); - } - this.description = desc; - } - - /** - * Creates an instance like {@link #GUID(int[])} and sets the optional - * description. (the int[] is obtained by {@link GUID#parseGUID(String)})
- * - * @param guidString GUID, which should be assigned. - * @param desc Description for the GUID. - */ - public GUID(final String guidString, final String desc) { - this(parseGUID(guidString).getGUID()); - if (desc == null) { - throw new IllegalArgumentException("Argument must not be null."); - } - this.description = desc; - } - - /** - * This method checks if the given value is matching the GUID - * specification of ASF streams.
- * - * @param value possible GUID. - * @return true if value matches the specification - * of a GUID. - */ - public static boolean assertGUID(final int[] value) { - return value != null && value.length == GUID.GUID_LENGTH; - } - - /** - * This method looks up a GUID instance from {@link #KNOWN_GUIDS} which - * matches the value of the given GUID. - * - * @param orig GUID to look up. - * @return a GUID instance from {@link #KNOWN_GUIDS} if available. - * null else. - */ - public static GUID getConfigured(final GUID orig) { - // safe against null - return GUID_TO_CONFIGURED.get(orig); - } - - /** - * This method searches a GUID in {@link #KNOWN_GUIDS}which is equal to the - * given guidData and returns its description.
- * This method is useful if a GUID was read out of a file and no - * identification has been done yet. - * - * @param guid GUID, which description is needed. - * @return description of the GUID if found. Else null - */ - public static String getGuidDescription(final GUID guid) { - String result = null; - if (guid == null) { - throw new IllegalArgumentException("Argument must not be null."); - } - if (getConfigured(guid) != null) { - result = getConfigured(guid).getDescription(); - } - return result; - } - - /** - * This method parses a String as GUID.
- * The format is like the one in the ASF specification.
- * An Example: C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA
- * - * @param guid the string to parse. - * @return the GUID. - * @throws GUIDFormatException If the GUID has an invalid format. - */ - public static GUID parseGUID(final String guid) throws GUIDFormatException { - if (guid == null) { - throw new GUIDFormatException("null"); - } - if (!GUID_PATTERN.matcher(guid).matches()) { - throw new GUIDFormatException("Invalid guidData format."); - } - final int[] bytes = new int[GUID_LENGTH]; - /* - * Don't laugh, but did not really come up with a nicer solution today - */ - final int[] arrayIndices = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, - 13, 14, 15}; - int arrayPointer = 0; - for (int i = 0; i < guid.length(); i++) { - if (guid.charAt(i) == '-') { - continue; - } - bytes[arrayIndices[arrayPointer++]] = Integer.parseInt(guid - .substring(i, i + 2), 16); - i++; - } - return new GUID(bytes); - } - - /** - * This method compares two objects. If the given Object is a {@link GUID}, - * the stored GUID values are compared.
- * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(final Object obj) { - boolean result = false; - if (obj instanceof GUID) { - final GUID other = (GUID) obj; - result = Arrays.equals(this.getGUID(), other.getGUID()); - } - return result; - } - - /** - * This method returns the GUID as an array of bytes.
- * - * @return The GUID as a byte array. - * @see #getGUID() - */ - public byte[] getBytes() { - final byte[] result = new byte[this.guidData.length]; - for (int i = 0; i < result.length; i++) { - result[i] = (byte) (this.guidData[i] & 0xFF); - } - return result; - } - - /** - * @return Returns the description. - */ - public String getDescription() { - return this.description; - } - - /** - * This method returns the GUID of this object.
- * - * @return stored GUID. - */ - public int[] getGUID() { - final int[] copy = new int[this.guidData.length]; - System.arraycopy(this.guidData, 0, copy, 0, this.guidData.length); - return copy; - } - - /** - * This method saves a copy of the given value as the - * represented value of this object.
- * The given value is checked with {@link #assertGUID(int[])}.
- * - * @param value GUID to assign. - */ - private void setGUID(final int[] value) { - if (assertGUID(value)) { - this.guidData = new int[GUID_LENGTH]; - System.arraycopy(value, 0, this.guidData, 0, GUID_LENGTH); - } else { - throw new IllegalArgumentException( - "The given guidData doesn't match the GUID specification."); - } - } - - /** - * Convenience method to get 2digit hex values of each byte. - * - * @param bytes bytes to convert. - * @return each byte as 2 digit hex. - */ - private String[] getHex(final byte[] bytes) { - final String[] result = new String[bytes.length]; - final StringBuilder tmp = new StringBuilder(); - for (int i = 0; i < bytes.length; i++) { - tmp.delete(0, tmp.length()); - tmp.append(Integer.toHexString(0xFF & bytes[i])); - if (tmp.length() == 1) { - tmp.insert(0, "0"); - } - result[i] = tmp.toString(); - } - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - if (this.hash == -1) { - int tmp = 0; - for (final int curr : getGUID()) { - tmp = tmp * 31 + curr; - } - this.hash = tmp; - } - return this.hash; - } - - /** - * This method checks if the currently stored GUID ({@link #guidData}) is - * correctly filled.
- * - * @return true if it is. - */ - public boolean isValid() { - return assertGUID(getGUID()); - } - - /** - * This method gives a hex formatted representation of {@link #getGUID()} - * - * @return hex formatted representation. - */ - public String prettyPrint() { - final StringBuilder result = new StringBuilder(); - String descr = getDescription(); - if (Utils.isBlank(descr)) { - descr = getGuidDescription(this); - } - if (!Utils.isBlank(descr)) { - result.append("Description: ").append(descr).append( - Utils.LINE_SEPARATOR).append(" "); - } - result.append(this.toString()); - return result.toString(); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - // C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA - // 0xea, 0xcb,0xf8, 0xc5, 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, - // 0x8c, 0x44,0xfa, 0x4c, 0xca - final StringBuilder result = new StringBuilder(); - final String[] bytes = getHex(getBytes()); - result.append(bytes[3]); - result.append(bytes[2]); - result.append(bytes[1]); - result.append(bytes[0]); - result.append('-'); - result.append(bytes[5]); - result.append(bytes[4]); - result.append('-'); - result.append(bytes[7]); - result.append(bytes[6]); - result.append('-'); - result.append(bytes[8]); - result.append(bytes[9]); - result.append('-'); - result.append(bytes[10]); - result.append(bytes[11]); - result.append(bytes[12]); - result.append(bytes[13]); - result.append(bytes[14]); - result.append(bytes[15]); - return result.toString(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/GUIDFormatException.java b/src/main/java/org/jaudiotagger/audio/asf/data/GUIDFormatException.java deleted file mode 100644 index 9309d2c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/GUIDFormatException.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -/** - * This exception is used when a string was about to be interpreted as a GUID, - * but did not match the format.
- * - * @author Christian Laireiter - */ -public class GUIDFormatException extends IllegalArgumentException { - - /** - * - */ - private static final long serialVersionUID = 6035645678612384953L; - - /** - * Creates an instance. - * - * @param detail detail message. - */ - public GUIDFormatException(final String detail) { - super(detail); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/LanguageList.java b/src/main/java/org/jaudiotagger/audio/asf/data/LanguageList.java deleted file mode 100644 index febfd6c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/LanguageList.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; -import org.jaudiotagger.logging.ErrorMessage; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -/** - * This structure represents the data of the ASF language object.
- * The language list is simply a listing of language codes which should comply - * to RFC-1766.
- * Consider: the index of a language is used by other entries in the ASF - * metadata. - * - * @author Christian Laireiter - */ -public class LanguageList extends Chunk { - - /** - * List of language codes, complying RFC-1766 - */ - private final List languages = new ArrayList(); - - /** - * Creates a new instance.
- */ - public LanguageList() { - super(GUID.GUID_LANGUAGE_LIST, 0, BigInteger.ZERO); - } - - /** - * Creates an instance. - * - * @param pos position within the ASF file. - * @param size size of the chunk - */ - public LanguageList(final long pos, final BigInteger size) { - super(GUID.GUID_LANGUAGE_LIST, pos, size); - } - - /** - * This method adds a language.
- * - * @param language language code - */ - public void addLanguage(final String language) { - if (language.length() < MetadataDescriptor.MAX_LANG_INDEX) { - if (!this.languages.contains(language)) { - this.languages.add(language); - } - } else { - throw new IllegalArgumentException( - ErrorMessage.WMA_LENGTH_OF_LANGUAGE_IS_TOO_LARGE - .getMsg(language.length() * 2 + 2)); - } - } - - /** - * Returns the language code at the specified index. - * - * @param index the index of the language code to get. - * @return the language code at given index. - */ - public String getLanguage(final int index) { - return this.languages.get(index); - } - - /** - * Returns the amount of stored language codes. - * - * @return number of stored language codes. - */ - public int getLanguageCount() { - return this.languages.size(); - } - - /** - * Returns all language codes in list. - * - * @return list of language codes. - */ - public List getLanguages() { - return new ArrayList(this.languages); - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - for (int i = 0; i < getLanguageCount(); i++) { - result.append(prefix); - result.append(" |-> "); - result.append(i); - result.append(" : "); - result.append(getLanguage(i)); - result.append(Utils.LINE_SEPARATOR); - } - return result.toString(); - } - - /** - * Removes the language entry at specified index. - * - * @param index index of language to remove. - */ - public void removeLanguage(final int index) { - this.languages.remove(index); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/MetadataContainer.java b/src/main/java/org/jaudiotagger/audio/asf/data/MetadataContainer.java deleted file mode 100644 index 1cd533f..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/MetadataContainer.java +++ /dev/null @@ -1,443 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.io.WriteableChunk; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.OutputStream; -import java.math.BigInteger; -import java.util.*; - -/** - * This structure represents the "Metadata Object","Metadata - * Library Object" and "Extended Content Description".
- * - * @author Christian Laireiter - */ -public class MetadataContainer extends Chunk implements WriteableChunk { - - /** - * stores the represented container type.
- */ - private final ContainerType containerType; - /** - * Stores the descriptors. - */ - private final Map> descriptors = new Hashtable>(); - /** - * for performance reasons this instance is used to look up existing - * descriptors in {@link #descriptors}.
- */ - private final DescriptorPointer perfPoint = new DescriptorPointer( - new MetadataDescriptor("")); - - /** - * Creates an instance. - * - * @param type determines the type of the container - */ - public MetadataContainer(final ContainerType type) { - this(type, 0, BigInteger.ZERO); - } - - /** - * Creates an instance. - * - * @param type determines the type of the container - * @param pos location in the ASF file - * @param size size of the chunk. - */ - public MetadataContainer(final ContainerType type, final long pos, - final BigInteger size) { - super(type.getContainerGUID(), pos, size); - this.containerType = type; - } - - /** - * Creates an instance. - * - * @param containerGUID the containers GUID - * @param pos location in the ASF file - * @param size size of the chunk. - */ - public MetadataContainer(final GUID containerGUID, final long pos, - final BigInteger size) { - this(determineType(containerGUID), pos, size); - } - - /** - * Looks up all {@linkplain ContainerType#getContainerGUID() guids} and - * returns the matching type. - * - * @param guid GUID to look up - * @return matching container type. - * @throws IllegalArgumentException if no container type matches - */ - private static ContainerType determineType(final GUID guid) - throws IllegalArgumentException { - assert guid != null; - ContainerType result = null; - for (final ContainerType curr : ContainerType.values()) { - if (curr.getContainerGUID().equals(guid)) { - result = curr; - break; - } - } - if (result == null) { - throw new IllegalArgumentException( - "Unknown metadata container specified by GUID (" - + guid.toString() + ")"); - } - return result; - } - - /** - * Adds a metadata descriptor. - * - * @param toAdd the descriptor to add. - * @throws IllegalArgumentException if descriptor does not meet container requirements, or - * already exist. - */ - public final void addDescriptor(final MetadataDescriptor toAdd) - throws IllegalArgumentException { - // check with throwing exceptions - this.containerType.assertConstraints(toAdd.getName(), toAdd - .getRawData(), toAdd.getType(), toAdd.getStreamNumber(), toAdd - .getLanguageIndex()); - // validate containers capabilities - if (!isAddSupported(toAdd)) { - throw new IllegalArgumentException( - "Descriptor cannot be added, see isAddSupported(...)"); - } - /* - * Check for containers types capabilities. - */ - // Search for descriptor list by name, language and stream. - List list; - synchronized (this.perfPoint) { - list = this.descriptors.get(this.perfPoint.setDescriptor(toAdd)); - } - if (list == null) { - list = new ArrayList(); - this.descriptors.put(new DescriptorPointer(toAdd), list); - } else { - if (!list.isEmpty() && !this.containerType.isMultiValued()) { - throw new IllegalArgumentException( - "Container does not allow multiple values of descriptors with same name, language index and stream number"); - } - } - list.add(toAdd); - } - - /** - * This method asserts that this container has a descriptor with the - * specified key, means returns an existing or creates a new descriptor. - * - * @param key the descriptor name to look up (or create) - * @return the/a descriptor with the specified name (and initial type of - * {@link MetadataDescriptor#TYPE_STRING}. - */ - protected final MetadataDescriptor assertDescriptor(final String key) { - return assertDescriptor(key, MetadataDescriptor.TYPE_STRING); - } - - /** - * This method asserts that this container has a descriptor with the - * specified key, means returns an existing or creates a new descriptor. - * - * @param key the descriptor name to look up (or create) - * @param type if the descriptor is created, this data type is applied. - * @return the/a descriptor with the specified name. - */ - protected final MetadataDescriptor assertDescriptor(final String key, - final int type) { - MetadataDescriptor desc; - final List descriptorsByName = getDescriptorsByName(key); - if (descriptorsByName == null || descriptorsByName.isEmpty()) { - desc = new MetadataDescriptor(getContainerType(), key, type); - addDescriptor(desc); - } else { - desc = descriptorsByName.get(0); - } - return desc; - } - - /** - * Checks whether a descriptor already exists.
- * Name, stream number and language index are compared. Data and data type - * are ignored. - * - * @param lookup descriptor to look up. - * @return true if such a descriptor already exists. - */ - public final boolean containsDescriptor(final MetadataDescriptor lookup) { - assert lookup != null; - return this.descriptors.containsKey(this.perfPoint - .setDescriptor(lookup)); - } - - /** - * Returns the type of container this instance represents.
- * - * @return represented container type. - */ - public final ContainerType getContainerType() { - return this.containerType; - } - - /** - * {@inheritDoc} - */ - public long getCurrentAsfChunkSize() { - /* - * 16 bytes GUID, 8 bytes chunk size, 2 bytes descriptor count - */ - long result = 26; - for (final MetadataDescriptor curr : getDescriptors()) { - result += curr.getCurrentAsfSize(this.containerType); - } - return result; - } - - /** - * Returns the number of contained descriptors. - * - * @return number of descriptors. - */ - public final int getDescriptorCount() { - return this.getDescriptors().size(); - } - - /** - * Returns all stored descriptors. - * - * @return stored descriptors. - */ - public final List getDescriptors() { - final List result = new ArrayList(); - for (final List curr : this.descriptors.values()) { - result.addAll(curr); - } - return result; - } - - /** - * Returns a list of descriptors with the given - * {@linkplain MetadataDescriptor#getName() name}.
- * - * @param name name of the descriptors to return - * @return list of descriptors with given name. - */ - public final List getDescriptorsByName(final String name) { - assert name != null; - final List result = new ArrayList(); - final Collection> values = this.descriptors - .values(); - for (final List currList : values) { - if (!currList.isEmpty() && currList.get(0).getName().equals(name)) { - result.addAll(currList); - } - } - return result; - } - - /** - * This method looks up a descriptor with given name and returns its value - * as string.
- * - * @param name the name of the descriptor to look up. - * @return the string representation of a found descriptors value. Even an - * empty string if no descriptor has been found. - */ - protected final String getValueFor(final String name) { - String result = ""; - final List descs = getDescriptorsByName(name); - if (descs != null) { - assert descs.size() <= 1; - if (!descs.isEmpty()) { - result = descs.get(0).getString(); - } - } - return result; - } - - /** - * Determines if this container contains a descriptor with given - * {@linkplain MetadataDescriptor#getName() name}.
- * - * @param name Name of the descriptor to look for. - * @return true if descriptor has been found. - */ - public final boolean hasDescriptor(final String name) { - return !getDescriptorsByName(name).isEmpty(); - } - - /** - * Determines/checks if the given descriptor may be added to the container.
- * This implies a check for the capabilities of the container specified by - * its {@linkplain #getContainerType() container type}.
- * - * @param descriptor the descriptor to test. - * @return true if {@link #addDescriptor(MetadataDescriptor)} - * can be called with given descriptor. - */ - public boolean isAddSupported(final MetadataDescriptor descriptor) { - boolean result = getContainerType().checkConstraints( - descriptor.getName(), descriptor.getRawData(), - descriptor.getType(), descriptor.getStreamNumber(), - descriptor.getLanguageIndex()) == null; - // Now check if there is already a value contained. - if (result && !getContainerType().isMultiValued()) { - synchronized (this.perfPoint) { - final List list = this.descriptors - .get(this.perfPoint.setDescriptor(descriptor)); - if (list != null) { - result = list.isEmpty(); - } - } - } - return result; - } - - /** - * {@inheritDoc} - */ - public final boolean isEmpty() { - boolean result = true; - if (getDescriptorCount() != 0) { - final Iterator iterator = getDescriptors() - .iterator(); - while (result && iterator.hasNext()) { - result &= iterator.next().isEmpty(); - } - } - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - for (final MetadataDescriptor curr : getDescriptors()) { - result.append(prefix).append(" |-> "); - result.append(curr); - result.append(Utils.LINE_SEPARATOR); - } - return result.toString(); - } - - /** - * Removes all stored descriptors with the given - * {@linkplain MetadataDescriptor#getName() name}.
- * - * @param name the name to remove. - */ - public final void removeDescriptorsByName(final String name) { - assert name != null; - final Iterator> iterator = this.descriptors - .values().iterator(); - while (iterator.hasNext()) { - final List curr = iterator.next(); - if (!curr.isEmpty() && curr.get(0).getName().equals(name)) { - iterator.remove(); - } - } - } - - /** - * {@linkplain #assertDescriptor(String) asserts} the existence of a - * descriptor with given name and - * {@linkplain MetadataDescriptor#setStringValue(String) assings} the string - * value. - * - * @param name the name of the descriptor to set the value for. - * @param value the string value. - */ - protected final void setStringValue(final String name, final String value) { - assertDescriptor(name).setStringValue(value); - } - - /** - * {@inheritDoc} - */ - public long writeInto(final OutputStream out) throws IOException { - final long chunkSize = getCurrentAsfChunkSize(); - final List descriptorList = getDescriptors(); - out.write(getGuid().getBytes()); - Utils.writeUINT64(chunkSize, out); - Utils.writeUINT16(descriptorList.size(), out); - for (final MetadataDescriptor curr : descriptorList) { - curr.writeInto(out, this.containerType); - } - return chunkSize; - } - - /** - * This class is used to uniquely identify an enclosed descriptor by its - * name, language index and stream number.
- * The type of the descriptor is ignored, since it just specifies the data - * content. - * - * @author Christian Laireiter - */ - private final static class DescriptorPointer { - - /** - * The represented descriptor. - */ - private MetadataDescriptor desc; - - /** - * Creates an instance. - * - * @param descriptor the metadata descriptor to identify. - */ - public DescriptorPointer(final MetadataDescriptor descriptor) { - setDescriptor(descriptor); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(final Object obj) { - boolean result = obj == this; - if (obj instanceof DescriptorPointer && !result) { - final MetadataDescriptor other = ((DescriptorPointer) obj).desc; - result = this.desc.getName().equals(other.getName()); - result &= this.desc.getLanguageIndex() == other - .getLanguageIndex(); - result &= this.desc.getStreamNumber() == other - .getStreamNumber(); - } - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - int hashCode; - hashCode = this.desc.getName().hashCode(); - hashCode = hashCode * 31 + this.desc.getLanguageIndex(); - hashCode = hashCode * 31 + this.desc.getStreamNumber(); - return hashCode; - } - - /** - * Sets the descriptor to identify. - * - * @param descriptor the descriptor to identify. - * @return this instance. - */ - protected DescriptorPointer setDescriptor( - final MetadataDescriptor descriptor) { - assert descriptor != null; - this.desc = descriptor; - return this; - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/MetadataContainerFactory.java b/src/main/java/org/jaudiotagger/audio/asf/data/MetadataContainerFactory.java deleted file mode 100644 index 0142405..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/MetadataContainerFactory.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.jaudiotagger.audio.asf.data; - -import java.math.BigInteger; - -/** - * A factory for creating appropriate {@link MetadataContainer} objects upon - * specified {@linkplain ContainerType container types}.
- * - * @author Christian Laireiter - */ -public final class MetadataContainerFactory { - - /** - * Factory instance. - */ - private final static MetadataContainerFactory INSTANCE = new MetadataContainerFactory(); - - /** - * Hidden utility class constructor. - */ - private MetadataContainerFactory() { - // Hidden - } - - /** - * Returns an instance. - * - * @return an instance. - */ - public static MetadataContainerFactory getInstance() { - return INSTANCE; - } - - /** - * Creates an appropriate {@linkplain MetadataContainer container - * implementation} for the given container type. - * - * @param type the type of container to get a container instance for. - * @return appropriate container implementation. - */ - public MetadataContainer createContainer(final ContainerType type) { - return createContainer(type, 0, BigInteger.ZERO); - } - - /** - * Convenience Method for I/O. Same as - * {@link #createContainer(ContainerType)}, but additionally assigns - * position and size. (since a {@link MetadataContainer} is actually a - * {@link Chunk}). - * - * @param type The containers type. - * @param pos the position within the stream. - * @param chunkSize the size of the container. - * @return an appropriate container implementation with assigned size and - * position. - */ - public MetadataContainer createContainer(final ContainerType type, - final long pos, final BigInteger chunkSize) { - MetadataContainer result; - if (type == ContainerType.CONTENT_DESCRIPTION) { - result = new ContentDescription(pos, chunkSize); - } else if (type == ContainerType.CONTENT_BRANDING) { - result = new ContentBranding(pos, chunkSize); - } else { - result = new MetadataContainer(type, pos, chunkSize); - } - return result; - } - - /** - * Convenience method which calls {@link #createContainer(ContainerType)} - * for each given container type. - * - * @param types types of the container which are to be created. - * @return appropriate container implementations. - */ - public MetadataContainer[] createContainers(final ContainerType[] types) { - assert types != null; - final MetadataContainer[] result = new MetadataContainer[types.length]; - for (int i = 0; i < result.length; i++) { - result[i] = createContainer(types[i]); - } - return result; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/MetadataDescriptor.java b/src/main/java/org/jaudiotagger/audio/asf/data/MetadataDescriptor.java deleted file mode 100644 index 5851de3..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/MetadataDescriptor.java +++ /dev/null @@ -1,877 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.TagOptionSingleton; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.logging.Logger; - -/** - * This structure represents metadata objects in ASF {@link MetadataContainer}.
- * The values are - * {@linkplain ContainerType#assertConstraints(String, byte[], int, int, int) - * checked} against the capability introduced by the given - * {@link ContainerType} at construction.
- *
- * Limitation: Even though some container types do not restrict the data - * size to {@link Integer#MAX_VALUE}, this implementation does it (due to java - * nature).
- * 2 GiB of data should suffice, and even be to large for normal java heap. - * - * @author Christian Laireiter - */ -public class MetadataDescriptor implements Comparable, - Cloneable { - - /** - * Maximum value for WORD. - */ - public static final long DWORD_MAXVALUE = new BigInteger("FFFFFFFF", 16) - .longValue(); - /** - * The maximum language index allowed. (exclusive) - */ - public static final int MAX_LANG_INDEX = 127; - /** - * Maximum stream number. (inclusive) - */ - public static final int MAX_STREAM_NUMBER = 127; - /** - * Maximum value for a QWORD value (64 bit unsigned).
- */ - public static final BigInteger QWORD_MAXVALUE = new BigInteger( - "FFFFFFFFFFFFFFFF", 16); - /** - * Constant for the metadata descriptor-type for binary data. - */ - public final static int TYPE_BINARY = 1; - /** - * Constant for the metadata descriptor-type for booleans. - */ - public final static int TYPE_BOOLEAN = 2; - /** - * Constant for the metadata descriptor-type for DWORD (32-bit unsigned).
- */ - public final static int TYPE_DWORD = 3; - /** - * Constant for the metadata descriptor-type for GUIDs (128-bit).
- */ - public final static int TYPE_GUID = 6; - /** - * Constant for the metadata descriptor-type for QWORD (64-bit unsinged).
- */ - public final static int TYPE_QWORD = 4; - /** - * Constant for the metadata descriptor-type for Strings. - */ - public final static int TYPE_STRING = 0; - /** - * Constant for the metadata descriptor-type for WORD (16-bit unsigned).
- */ - public final static int TYPE_WORD = 5; - /** - * Maximum value for WORD. - */ - public static final int WORD_MAXVALUE = 65535; - /** - * Logger instance. - */ - private static final Logger LOGGER = Logger - .getLogger("org.jaudiotagger.audio.asf.data"); - /** - * Stores the containerType of the descriptor. - */ - private final ContainerType containerType; - /** - * The name of the metadata descriptor. - */ - private final String name; - /** - * The binary representation of the value. - */ - /* - * Note: The maximum data length could be up to a 64-Bit number (unsigned), - * but java for now handles just int sized byte[]. Since this class stores - * all data in primitive byte[] this size restriction is cascaded to all - * dependent implementations. - */ - private byte[] content = new byte[0]; - /** - * This field shows the type of the metadata descriptor.
- * - * @see #TYPE_BINARY - * @see #TYPE_BOOLEAN - * @see #TYPE_DWORD - * @see #TYPE_GUID - * @see #TYPE_QWORD - * @see #TYPE_STRING - * @see #TYPE_WORD - */ - private int descriptorType; - /** - * the index of the language in the {@linkplain LanguageList language list} - * this descriptor applies to.
- */ - private int languageIndex = 0; - /** - * The number of the stream, this descriptor applies to.
- */ - private int streamNumber = 0; - - /** - * Creates an Instance.
- * - * @param type the container type, this descriptor is resctricted to. - * @param propName Name of the MetadataDescriptor. - * @param propType Type of the metadata descriptor. See {@link #descriptorType} - */ - public MetadataDescriptor(final ContainerType type, final String propName, - final int propType) { - this(type, propName, propType, 0, 0); - } - - /** - * Creates an Instance. - * - * @param type The container type the values (the whole descriptor) is - * restricted to. - * @param propName Name of the MetadataDescriptor. - * @param propType Type of the metadata descriptor. See {@link #descriptorType} - * @param stream the number of the stream the descriptor refers to. - * @param language the index of the language entry in a {@link LanguageList} this - * descriptor refers to.
- * Consider: No checks performed if language entry exists. - */ - public MetadataDescriptor(final ContainerType type, final String propName, - final int propType, final int stream, final int language) { - assert type != null; - type.assertConstraints(propName, new byte[0], propType, stream, - language); - this.containerType = type; - this.name = propName; - this.descriptorType = propType; - this.streamNumber = stream; - this.languageIndex = language; - } - - /** - * Creates an instance.
- * Capabilities are set to {@link ContainerType#METADATA_LIBRARY_OBJECT}.
- * - * @param propName name of the metadata descriptor. - */ - public MetadataDescriptor(final String propName) { - this(propName, TYPE_STRING); - } - - /** - * Creates an Instance.
- * Capabilities are set to {@link ContainerType#METADATA_LIBRARY_OBJECT}.
- * - * @param propName Name of the MetadataDescriptor. - * @param propType Type of the metadata descriptor. See {@link #descriptorType} - */ - public MetadataDescriptor(final String propName, final int propType) { - this(ContainerType.METADATA_LIBRARY_OBJECT, propName, propType, 0, 0); - } - - /** - * Converts the descriptors value into a number if possible.
- * A boolean will be converted to "1" if true, - * otherwise "0".
- * String will be interpreted as number with radix "10".
- * Binary data will be interpreted as the default WORD,DWORD or QWORD binary - * representation, but only if the data does not exceed 8 bytes. This - * precaution is done to prevent creating a number of a multi kilobyte - * image.
- * A GUID cannot be converted in any case. - * - * @return number representation. - * @throws NumberFormatException If no conversion is supported. - */ - public BigInteger asNumber() { - BigInteger result = null; - switch (this.descriptorType) { - case TYPE_BOOLEAN: - case TYPE_WORD: - case TYPE_DWORD: - case TYPE_QWORD: - case TYPE_BINARY: - if (this.content.length > 8) { - throw new NumberFormatException( - "Binary data would exceed QWORD"); - } - break; - case TYPE_GUID: - throw new NumberFormatException( - "GUID cannot be converted to a number."); - case TYPE_STRING: - result = new BigInteger(getString(), 10); - break; - default: - throw new IllegalStateException(); - } - if (result == null) { - final byte[] copy = new byte[this.content.length]; - for (int i = 0; i < copy.length; i++) { - copy[i] = this.content[this.content.length - (i + 1)]; - } - result = new BigInteger(1, copy); - } - return result; - } - - /** - * (overridden) - * - * @see java.lang.Object#clone() - */ - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - /** - * {@inheritDoc} - */ - public int compareTo(final MetadataDescriptor other) { - return getName().compareTo(other.getName()); - } - - /** - * This method creates a copy of the current object.
- * All data will be copied, too.
- * - * @return A new metadata descriptor containing the same values as the - * current one. - */ - public MetadataDescriptor createCopy() { - final MetadataDescriptor result = new MetadataDescriptor( - this.containerType, this.name, this.descriptorType, - this.streamNumber, this.languageIndex); - result.content = getRawData(); - return result; - } - - /** - * (overridden) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(final Object obj) { - boolean result = false; - if (obj instanceof MetadataDescriptor) { - if (obj == this) { - result = true; - } else { - final MetadataDescriptor other = (MetadataDescriptor) obj; - result = other.getName().equals(getName()) - && other.descriptorType == this.descriptorType - && other.languageIndex == this.languageIndex - && other.streamNumber == this.streamNumber - && Arrays.equals(this.content, other.content); - } - } - return result; - } - - /** - * Returns the value of the MetadataDescriptor as a Boolean.
- * If no Conversion is Possible false is returned.
- * true if first byte of {@link #content}is not zero. - * - * @return boolean representation of the current value. - */ - public boolean getBoolean() { - return this.content.length > 0 && this.content[0] != 0; - } - - /** - * This method will return a byte array, which can directly be written into - * an "Extended Content Description"-chunk.
- * - * @return byte[] with the data, that occurs in ASF files. - * @deprecated {@link #writeInto(OutputStream, ContainerType)} is used - */ - @Deprecated - public byte[] getBytes() { - final ByteArrayOutputStream result = new ByteArrayOutputStream(); - try { - writeInto(result, this.containerType); - } catch (final IOException e) { - LOGGER.warning(e.getMessage()); - } - return result.toByteArray(); - } - - /** - * Returns the container type this descriptor ist restricted to. - * - * @return the container type - */ - public ContainerType getContainerType() { - return this.containerType; - } - - /** - * Returns the size (in bytes) this descriptor will take when written to an - * ASF file.
- * - * @param type the container type for which the size is calculated. - * @return size of the descriptor in an ASF file. - */ - public int getCurrentAsfSize(final ContainerType type) { - /* - * 2 bytes name length, 2 bytes name zero term, 2 bytes type, 2 bytes - * content length - */ - int result = 8; - - if (type != ContainerType.EXTENDED_CONTENT) { - // Stream number and language index (respectively reserved field). - // And +2 bytes, because data type is 32 bit, not 16 - result += 6; - } - result += getName().length() * 2; - - if (this.getType() == TYPE_BOOLEAN) { - result += 2; - if (type == ContainerType.EXTENDED_CONTENT) { - // Extended content description boolean values are stored with - // 32-bit - result += 2; - } - } else { - - result += this.content.length; - if (TYPE_STRING == this.getType()) { - result += 2; // zero term of content string. - } - } - return result; - } - - /** - * Returns the GUID value, if content could represent one. - * - * @return GUID value - */ - public GUID getGuid() { - GUID result = null; - if (getType() == TYPE_GUID && this.content.length == GUID.GUID_LENGTH) { - result = new GUID(this.content); - } - return result; - } - - /** - * Returns the index of the language that is referred (see - * {@link LanguageList}): - * - * @return the language index - */ - public int getLanguageIndex() { - return this.languageIndex; - } - - /** - * Sets the index of the referred language (see {@link LanguageList}).
- * Consider: The {@linkplain #containerType requirements} must be - * held. - * - * @param language the language index to set - */ - public void setLanguageIndex(final int language) { - this.containerType.assertConstraints(this.name, this.content, - this.descriptorType, this.streamNumber, language); - this.languageIndex = language; - } - - /** - * This method returns the name of the metadata descriptor. - * - * @return Name. - */ - public String getName() { - return this.name; - } - - /** - * This method returns the value of the metadata descriptor as a long.
- * Converts the needed amount of byte out of {@link #content}to a number.
- * Only possible if {@link #getType()}equals on of the following:
- *
  • - * - * @return integer value. - * @see #TYPE_BOOLEAN
  • - * @see #TYPE_DWORD
  • - * @see #TYPE_QWORD
  • - * @see #TYPE_WORD
  • - */ - public long getNumber() { - int bytesNeeded; - switch (getType()) { - case TYPE_BOOLEAN: - bytesNeeded = 1; - break; - case TYPE_DWORD: - bytesNeeded = 4; - break; - case TYPE_QWORD: - bytesNeeded = 8; - break; - case TYPE_WORD: - bytesNeeded = 2; - break; - default: - throw new UnsupportedOperationException( - "The current type doesn't allow an interpretation as a number. (" - + getType() + ")"); - } - if (bytesNeeded > this.content.length) { - throw new IllegalStateException( - "The stored data cannot represent the type of current object."); - } - long result = 0; - for (int i = 0; i < bytesNeeded; i++) { - result |= (((long) this.content[i] & 0xFF) << (i * 8)); - } - return result; - } - - /** - * This method returns a copy of the content of the descriptor.
    - * - * @return The content in binary representation, as it would be written to - * asf file.
    - */ - public byte[] getRawData() { - final byte[] copy = new byte[this.content.length]; - System.arraycopy(this.content, 0, copy, 0, this.content.length); - return copy; - } - - /** - * Returns the size (in bytes) the binary representation of the content - * uses. (length of {@link #getRawData()})
    - * - * @return size of binary representation of the content. - */ - public int getRawDataSize() { - return this.content.length; - } - - /** - * Returns the stream number this descriptor applies to.
    - * - * @return the stream number. - */ - public int getStreamNumber() { - return this.streamNumber; - } - - /** - * Sets the stream number the descriptor applies to.
    - * Consider: The {@linkplain #containerType requirements} must be - * held. - * - * @param stream the stream number to set - */ - public void setStreamNumber(final int stream) { - this.containerType.assertConstraints(this.name, this.content, - this.descriptorType, stream, this.languageIndex); - this.streamNumber = stream; - } - - /** - * Returns the value of the MetadataDescriptor as a String.
    - * - * @return String - Representation Value - */ - public String getString() { - String result = null; - switch (getType()) { - case TYPE_BINARY: - result = "binary data"; - break; - case TYPE_BOOLEAN: - result = String.valueOf(getBoolean()); - break; - case TYPE_GUID: - result = getGuid() == null ? "Invalid GUID" : getGuid().toString(); - break; - case TYPE_QWORD: - case TYPE_DWORD: - case TYPE_WORD: - result = String.valueOf(getNumber()); - break; - case TYPE_STRING: - try { - result = new String(this.content, "UTF-16LE"); - } catch (final UnsupportedEncodingException e) { - LOGGER.warning(e.getMessage()); - } - break; - default: - throw new IllegalStateException("Current type is not known."); - } - return result; - } - - /** - * This method converts the given string value into the current - * {@linkplain #getType() data type}. - * - * @param value value to set. - * @throws IllegalArgumentException If conversion was impossible. - */ - public void setString(final String value) - throws IllegalArgumentException { - try { - switch (getType()) { - case TYPE_BINARY: - throw new IllegalArgumentException( - "Cannot interpret binary as string."); - case TYPE_BOOLEAN: - setBooleanValue(Boolean.parseBoolean(value)); - break; - case TYPE_DWORD: - setDWordValue(Long.parseLong(value)); - break; - case TYPE_QWORD: - setQWordValue(new BigInteger(value, 10)); - break; - case TYPE_WORD: - setWordValue(Integer.parseInt(value)); - break; - case TYPE_GUID: - setGUIDValue(GUID.parseGUID(value)); - break; - case TYPE_STRING: - setStringValue(value); - break; - default: - // new Type added but not handled. - throw new IllegalStateException(); - } - } catch (final NumberFormatException nfe) { - throw new IllegalArgumentException( - "Value cannot be parsed as Number or is out of range (\"" - + value + "\")", nfe); - } - } - - /** - * Returns the type of the metadata descriptor.
    - * - * @return the value of {@link #descriptorType} - * @see #TYPE_BINARY - * @see #TYPE_BOOLEAN - * @see #TYPE_DWORD - * @see #TYPE_GUID - * @see #TYPE_QWORD - * @see #TYPE_STRING - * @see #TYPE_WORD - */ - public int getType() { - return this.descriptorType; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - return this.name.hashCode(); - } - - /** - * This method checks if the binary data is empty.
    - * Disregarding the type of the descriptor its content is stored as a byte - * array. - * - * @return true if no value is set. - */ - public boolean isEmpty() { - return this.content.length == 0; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_BINARY}.
    - * - * @param data Value to set. - * @throws IllegalArgumentException if data is invalid for {@linkplain #getContainerType() - * container}. - */ - public void setBinaryValue(final byte[] data) - throws IllegalArgumentException { - this.containerType.assertConstraints(this.name, data, - this.descriptorType, this.streamNumber, this.languageIndex); - this.content = data.clone(); - this.descriptorType = TYPE_BINARY; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_BOOLEAN}.
    - * - * @param value Value to set. - */ - public void setBooleanValue(final boolean value) { - this.content = new byte[]{value ? (byte) 1 : 0}; - this.descriptorType = TYPE_BOOLEAN; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_DWORD}. - * - * @param value Value to set. - */ - public void setDWordValue(final long value) { - if (value < 0 || value > DWORD_MAXVALUE) { - throw new IllegalArgumentException("value out of range (0-" - + DWORD_MAXVALUE + ")"); - } - this.content = Utils.getBytes(value, 4); - this.descriptorType = TYPE_DWORD; - } - - /** - * Sets the value of the metadata descriptor.
    - * Using this method will change {@link #descriptorType} to - * {@link #TYPE_GUID} - * - * @param value value to set. - */ - public void setGUIDValue(final GUID value) { - this.containerType.assertConstraints(this.name, value.getBytes(), - TYPE_GUID, this.streamNumber, this.languageIndex); - this.content = value.getBytes(); - this.descriptorType = TYPE_GUID; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_QWORD} - * - * @param value Value to set. - * @throws NumberFormatException on null values. - * @throws IllegalArgumentException on illegal values or values exceeding range. - */ - public void setQWordValue(final BigInteger value) - throws IllegalArgumentException { - if (value == null) { - throw new NumberFormatException("null"); - } - if (BigInteger.ZERO.compareTo(value) > 0) { - throw new IllegalArgumentException( - "Only unsigned values allowed (no negative)"); - } - if (MetadataDescriptor.QWORD_MAXVALUE.compareTo(value) < 0) { - throw new IllegalArgumentException( - "Value exceeds QWORD (64 bit unsigned)"); - } - this.content = new byte[8]; - final byte[] valuesBytes = value.toByteArray(); - if (valuesBytes.length <= 8) { - for (int i = valuesBytes.length - 1; i >= 0; i--) { - this.content[valuesBytes.length - (i + 1)] = valuesBytes[i]; - } - } else { - /* - * In case of 64-Bit set - */ - Arrays.fill(this.content, (byte) 0xFF); - } - this.descriptorType = TYPE_QWORD; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_QWORD} - * - * @param value Value to set. - */ - public void setQWordValue(final long value) { - if (value < 0) { - throw new IllegalArgumentException("value out of range (0-" - + MetadataDescriptor.QWORD_MAXVALUE.toString() + ")"); - } - this.content = Utils.getBytes(value, 8); - this.descriptorType = TYPE_QWORD; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_STRING}. - * - * @param value Value to set. - * @throws IllegalArgumentException If byte representation would take more than 65535 Bytes. - */ - // TODO Test - public void setStringValue(final String value) - throws IllegalArgumentException { - if (value == null) { - this.content = new byte[0]; - } else { - final byte[] tmp = Utils.getBytes(value, AsfHeader.ASF_CHARSET); - if (getContainerType().isWithinValueRange(tmp.length)) { - // Everything is fine here, data can be stored. - this.content = tmp; - } else { - // Normally a size violation, check if JAudiotagger my truncate - // the string - if (TagOptionSingleton.getInstance() - .isTruncateTextWithoutErrors()) { - // truncate the string - final int copyBytes = (int) getContainerType() - .getMaximumDataLength().longValue(); - this.content = new byte[copyBytes % 2 == 0 ? copyBytes - : copyBytes - 1]; - System.arraycopy(tmp, 0, this.content, 0, - this.content.length); - } else { - // We may not truncate, so its an error - throw new IllegalArgumentException( - ErrorMessage.WMA_LENGTH_OF_DATA_IS_TOO_LARGE - .getMsg(tmp.length, getContainerType() - .getMaximumDataLength(), - getContainerType() - .getContainerGUID() - .getDescription())); - } - } - } - this.descriptorType = TYPE_STRING; - } - - /** - * Sets the Value of the current metadata descriptor.
    - * Using this method will change {@link #descriptorType}to - * {@link #TYPE_WORD} - * - * @param value Value to set. - * @throws IllegalArgumentException on negative values. ASF just supports unsigned values. - */ - public void setWordValue(final int value) - throws IllegalArgumentException { - if (value < 0 || value > WORD_MAXVALUE) { - throw new IllegalArgumentException("value out of range (0-" - + WORD_MAXVALUE + ")"); - } - this.content = Utils.getBytes(value, 2); - this.descriptorType = TYPE_WORD; - } - - /** - * (overridden) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return getName() - + " : " - + new String[]{"String: ", "Binary: ", "Boolean: ", - "DWORD: ", "QWORD:", "WORD:", "GUID:"}[this.descriptorType] - + getString() + " (language: " + this.languageIndex - + " / stream: " + this.streamNumber + ")"; - } - - /** - * Writes this descriptor into the specified output stream.
    - * - * @param out stream to write into. - * @param contType the container type this descriptor is written to. - * @return amount of bytes written. - * @throws IOException on I/O Errors - */ - public int writeInto(final OutputStream out, - final ContainerType contType) throws IOException { - final int size = getCurrentAsfSize(contType); - /* - * Booleans are stored as one byte, if a boolean is written, the data - * must be converted according to the container type. - */ - byte[] binaryData; - if (this.descriptorType == TYPE_BOOLEAN) { - binaryData = new byte[contType == ContainerType.EXTENDED_CONTENT ? 4 - : 2]; - binaryData[0] = (byte) (getBoolean() ? 1 : 0); - } else { - binaryData = this.content; - } - // for Metadata objects the stream number and language index - if (contType != ContainerType.EXTENDED_CONTENT) { - Utils.writeUINT16(getLanguageIndex(), out); - Utils.writeUINT16(getStreamNumber(), out); - } - Utils.writeUINT16(getName().length() * 2 + 2, out); - - // The name for the metadata objects come later - if (contType == ContainerType.EXTENDED_CONTENT) { - out.write(Utils.getBytes(getName(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - } - - // type and content len follow up are identical - final int type = getType(); - Utils.writeUINT16(type, out); - int contentLen = binaryData.length; - if (TYPE_STRING == type) { - contentLen += 2; // Zero Term - } - - if (contType == ContainerType.EXTENDED_CONTENT) { - Utils.writeUINT16(contentLen, out); - } else { - Utils.writeUINT32(contentLen, out); - } - - // Metadata objects now write their descriptor name - if (contType != ContainerType.EXTENDED_CONTENT) { - out.write(Utils.getBytes(getName(), AsfHeader.ASF_CHARSET)); - out.write(AsfHeader.ZERO_TERM); - } - - // The content. - out.write(binaryData); - if (TYPE_STRING == type) { - out.write(AsfHeader.ZERO_TERM); - } - return size; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java deleted file mode 100644 index 7da6b52..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -/** - * This class represents the "Stream Bitrate Properties" chunk of an ASF media - * file.
    - * It is optional, but contains useful information about the streams bitrate.
    - * - * @author Christian Laireiter - */ -public class StreamBitratePropertiesChunk extends Chunk { - - /** - * For each call of {@link #addBitrateRecord(int, long)} an {@link Long} - * object is appended, which represents the average bitrate. - */ - private final List bitRates; - - /** - * For each call of {@link #addBitrateRecord(int, long)} an {@link Integer} - * object is appended, which represents the stream-number. - */ - private final List streamNumbers; - - /** - * Creates an instance. - * - * @param chunkLen Length of current chunk. - */ - public StreamBitratePropertiesChunk(final BigInteger chunkLen) { - super(GUID.GUID_STREAM_BITRATE_PROPERTIES, chunkLen); - this.bitRates = new ArrayList(); - this.streamNumbers = new ArrayList(); - } - - /** - * Adds the public values of a stream-record. - * - * @param streamNum The number of the referred stream. - * @param averageBitrate Its average bitrate. - */ - public void addBitrateRecord(final int streamNum, final long averageBitrate) { - this.streamNumbers.add(streamNum); - this.bitRates.add(averageBitrate); - } - - /** - * Returns the average bitrate of the given stream.
    - * - * @param streamNumber Number of the stream whose bitrate to determine. - * @return The average bitrate of the numbered stream. -1 if no - * information was given. - */ - public long getAvgBitrate(final int streamNumber) { - final Integer seach = streamNumber; - final int index = this.streamNumbers.indexOf(seach); - long result; - if (index == -1) { - result = -1; - } else { - result = this.bitRates.get(index); - } - return result; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.asf.data.Chunk#prettyPrint(String) - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - for (int i = 0; i < this.bitRates.size(); i++) { - result.append(prefix).append(" |-> Stream no. \"").append( - this.streamNumbers.get(i)).append( - "\" has an average bitrate of \"").append( - this.bitRates.get(i)).append('"').append( - Utils.LINE_SEPARATOR); - } - return result.toString(); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/StreamChunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/StreamChunk.java deleted file mode 100644 index 79bd90a..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/StreamChunk.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; - -/** - * This class is the base for all handled stream contents.
    - * A Stream chunk delivers information about a audio or video stream. Because of - * this the stream chunk identifies in one field what type of stream it is - * describing and so other data is provided. However some information is common - * to all stream chunks which are stored in this hierarchy of the class tree. - * - * @author Christian Laireiter - */ -public abstract class StreamChunk extends Chunk { - - /** - * Stores the stream type.
    - * - * @see GUID#GUID_AUDIOSTREAM - * @see GUID#GUID_VIDEOSTREAM - */ - private final GUID type; - /** - * If true, the stream data is encrypted. - */ - private boolean contentEncrypted; - /** - * This field stores the number of the current stream.
    - */ - private int streamNumber; - /** - * @see #typeSpecificDataSize - */ - private long streamSpecificDataSize; - /** - * Something technical.
    - * Format time in 100-ns steps. - */ - private long timeOffset; - /** - * Stores the size of type specific data structure within chunk. - */ - private long typeSpecificDataSize; - - /** - * Creates an instance - * - * @param streamType The GUID which tells the stream type represented ( - * {@link GUID#GUID_AUDIOSTREAM} or {@link GUID#GUID_VIDEOSTREAM} - * ): - * @param chunkLen length of chunk - */ - public StreamChunk(final GUID streamType, final BigInteger chunkLen) { - super(GUID.GUID_STREAM, chunkLen); - assert GUID.GUID_AUDIOSTREAM.equals(streamType) - || GUID.GUID_VIDEOSTREAM.equals(streamType); - this.type = streamType; - } - - /** - * @return Returns the streamNumber. - */ - public int getStreamNumber() { - return this.streamNumber; - } - - /** - * @param streamNum The streamNumber to set. - */ - public void setStreamNumber(final int streamNum) { - this.streamNumber = streamNum; - } - - /** - * @return Returns the streamSpecificDataSize. - */ - public long getStreamSpecificDataSize() { - return this.streamSpecificDataSize; - } - - /** - * @param strSpecDataSize The streamSpecificDataSize to set. - */ - public void setStreamSpecificDataSize(final long strSpecDataSize) { - this.streamSpecificDataSize = strSpecDataSize; - } - - /** - * Returns the stream type of the stream chunk.
    - * - * @return {@link GUID#GUID_AUDIOSTREAM} or {@link GUID#GUID_VIDEOSTREAM}. - */ - public GUID getStreamType() { - return this.type; - } - - /** - * @return Returns the timeOffset. - */ - public long getTimeOffset() { - return this.timeOffset; - } - - /** - * @param timeOffs sets the time offset - */ - public void setTimeOffset(final long timeOffs) { - this.timeOffset = timeOffs; - } - - /** - * @return Returns the typeSpecificDataSize. - */ - public long getTypeSpecificDataSize() { - return this.typeSpecificDataSize; - } - - /** - * @param typeSpecDataSize The typeSpecificDataSize to set. - */ - public void setTypeSpecificDataSize(final long typeSpecDataSize) { - this.typeSpecificDataSize = typeSpecDataSize; - } - - /** - * @return Returns the contentEncrypted. - */ - public boolean isContentEncrypted() { - return this.contentEncrypted; - } - - /** - * @param cntEnc The contentEncrypted to set. - */ - public void setContentEncrypted(final boolean cntEnc) { - this.contentEncrypted = cntEnc; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.asf.data.Chunk#prettyPrint(String) - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.append(prefix).append(" |-> Stream number: ").append( - getStreamNumber()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |-> Type specific data size : ") - .append(getTypeSpecificDataSize()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |-> Stream specific data size: ") - .append(getStreamSpecificDataSize()).append( - Utils.LINE_SEPARATOR); - result.append(prefix).append(" |-> Time Offset : ") - .append(getTimeOffset()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |-> Content Encryption : ") - .append(isContentEncrypted()).append(Utils.LINE_SEPARATOR); - return result.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/VideoStreamChunk.java b/src/main/java/org/jaudiotagger/audio/asf/data/VideoStreamChunk.java deleted file mode 100644 index 81cd2f2..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/VideoStreamChunk.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.data; - -import org.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; - -/** - * @author Christian Laireiter - */ -public class VideoStreamChunk extends StreamChunk { - - /** - * Stores the codecs id. Normally the Four-CC (4-Bytes). - */ - private byte[] codecId = new byte[0]; - - /** - * This field stores the height of the video stream. - */ - private long pictureHeight; - - /** - * This field stores the width of the video stream. - */ - private long pictureWidth; - - /** - * Creates an instance. - * - * @param chunkLen Length of the entire chunk (including guid and size) - */ - public VideoStreamChunk(final BigInteger chunkLen) { - super(GUID.GUID_VIDEOSTREAM, chunkLen); - } - - /** - * @return Returns the codecId. - */ - public byte[] getCodecId() { - return this.codecId.clone(); - } - - /** - * @param codecIdentifier The codecId to set. - */ - public void setCodecId(final byte[] codecIdentifier) { - this.codecId = codecIdentifier.clone(); - } - - /** - * Returns the {@link #getCodecId()}, as a String, where each byte has been - * converted to a char. - * - * @return Codec Id as String. - */ - public String getCodecIdAsString() { - String result; - if (this.codecId == null) { - result = "Unknown"; - } else { - result = new String(getCodecId()); - } - return result; - } - - /** - * @return Returns the pictureHeight. - */ - public long getPictureHeight() { - return this.pictureHeight; - } - - /** - * @param picHeight - */ - public void setPictureHeight(final long picHeight) { - this.pictureHeight = picHeight; - } - - /** - * @return Returns the pictureWidth. - */ - public long getPictureWidth() { - return this.pictureWidth; - } - - /** - * @param picWidth - */ - public void setPictureWidth(final long picWidth) { - this.pictureWidth = picWidth; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.asf.data.StreamChunk#prettyPrint(String) - */ - @Override - public String prettyPrint(final String prefix) { - final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); - result.insert(0, Utils.LINE_SEPARATOR + prefix + "|->VideoStream"); - result.append(prefix).append("Video info:") - .append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Width : ").append( - getPictureWidth()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Heigth : ").append( - getPictureHeight()).append(Utils.LINE_SEPARATOR); - result.append(prefix).append(" |->Codec : ").append( - getCodecIdAsString()).append(Utils.LINE_SEPARATOR); - return result.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/data/package.html b/src/main/java/org/jaudiotagger/audio/asf/data/package.html deleted file mode 100644 index 617557a..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/data/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for data components of the Microsoft Advanced Systems Format header. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java b/src/main/java/org/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java deleted file mode 100644 index a6f155c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * This modifier manipulates an ASF header extension object. - * - * @author Christian Laireiter - */ -public class AsfExtHeaderModifier implements ChunkModifier { - - /** - * List of modifiers which are to be applied to contained chunks. - */ - private final List modifierList; - - /** - * Creates an instance.
    - * - * @param modifiers modifiers to apply. - */ - public AsfExtHeaderModifier(final List modifiers) { - assert modifiers != null; - this.modifierList = new ArrayList(modifiers); - } - - /** - * Simply copies a chunk from source to - * destination.
    - * The method assumes, that the GUID has already been read and will write - * the provided one to the destination.
    - * The chunk length however will be read and used to determine the amount of - * bytes to copy. - * - * @param guid GUID of the current CHUNK. - * @param source source of an ASF chunk, which is to be located at the chunk - * length field. - * @param destination the destination to copy the chunk to. - * @throws IOException on I/O errors. - */ - private void copyChunk(final GUID guid, final InputStream source, - final OutputStream destination) throws IOException { - final long chunkSize = Utils.readUINT64(source); - destination.write(guid.getBytes()); - Utils.writeUINT64(chunkSize, destination); - Utils.copy(source, destination, chunkSize - 24); - } - - /** - * {@inheritDoc} - */ - public boolean isApplicable(final GUID guid) { - return GUID.GUID_HEADER_EXTENSION.equals(guid); - } - - /** - * {@inheritDoc} - */ - public ModificationResult modify(final GUID guid, final InputStream source, - final OutputStream destination) throws IOException { - assert GUID.GUID_HEADER_EXTENSION.equals(guid); - - long difference = 0; - final List modders = new ArrayList( - this.modifierList); - final Set occuredGuids = new HashSet(); - occuredGuids.add(guid); - - final BigInteger chunkLen = Utils.readBig64(source); - final GUID reserved1 = Utils.readGUID(source); - final int reserved2 = Utils.readUINT16(source); - final long dataSize = Utils.readUINT32(source); - - assert dataSize == 0 || dataSize >= 24; - assert chunkLen.subtract(BigInteger.valueOf(46)).longValue() == dataSize; - - /* - * Stream buffer for the chunk list - */ - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - /* - * Stream which counts read bytes. Dirty but quick way of implementing - * this. - */ - final CountingInputStream cis = new CountingInputStream(source); - - while (cis.getReadCount() < dataSize) { - // read GUID - final GUID curr = Utils.readGUID(cis); - boolean handled = false; - for (int i = 0; i < modders.size() && !handled; i++) { - if (modders.get(i).isApplicable(curr)) { - final ModificationResult modRes = modders.get(i).modify( - curr, cis, bos); - difference += modRes.getByteDifference(); - occuredGuids.addAll(modRes.getOccuredGUIDs()); - modders.remove(i); - handled = true; - } - } - if (!handled) { - occuredGuids.add(curr); - copyChunk(curr, cis, bos); - } - } - // Now apply the left modifiers. - for (final ChunkModifier curr : modders) { - // chunks, which were not in the source file, will be added to the - // destination - final ModificationResult result = curr.modify(null, null, bos); - difference += result.getByteDifference(); - occuredGuids.addAll(result.getOccuredGUIDs()); - } - destination.write(GUID.GUID_HEADER_EXTENSION.getBytes()); - Utils.writeUINT64(chunkLen.add(BigInteger.valueOf(difference)) - .longValue(), destination); - destination.write(reserved1.getBytes()); - Utils.writeUINT16(reserved2, destination); - Utils.writeUINT32(dataSize + difference, destination); - destination.write(bos.toByteArray()); - return new ModificationResult(0, difference, occuredGuids); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java deleted file mode 100644 index c18ea34..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.AsfExtendedHeader; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.util.List; - -/** - * This reader reads an ASF header extension object from an {@link InputStream} - * and creates an {@link AsfExtendedHeader} object.
    - * - * @author Christian Laireiter - */ -public class AsfExtHeaderReader extends ChunkContainerReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_HEADER_EXTENSION}; - - /** - * Creates a reader instance, which only utilizes the given list of chunk - * readers.
    - * - * @param toRegister List of {@link ChunkReader} class instances, which are to be - * utilized by the instance. - * @param readChunkOnce if true, each chunk type (identified by chunk - * GUID) will handled only once, if a reader is available, other - * chunks will be discarded. - */ - public AsfExtHeaderReader( - final List> toRegister, - final boolean readChunkOnce) { - super(toRegister, readChunkOnce); - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - protected AsfExtendedHeader createContainer(final long streamPosition, - final BigInteger chunkLength, final InputStream stream) - throws IOException { - Utils.readGUID(stream); // First reserved field (should be a specific - // GUID. - Utils.readUINT16(stream); // Second reserved field (should always be 6) - final long extensionSize = Utils.readUINT32(stream); - assert extensionSize == 0 || extensionSize >= 24; - assert chunkLength.subtract(BigInteger.valueOf(46)).longValue() == extensionSize; - return new AsfExtendedHeader(streamPosition, chunkLength); - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/AsfHeaderReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/AsfHeaderReader.java deleted file mode 100644 index d76fedf..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/AsfHeaderReader.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.*; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -/** - * This class reads an ASF header out of an input stream an creates an - * {@link org.jaudiotagger.audio.asf.data.AsfHeader} object if successful.
    - * For now only ASF ver 1.0 is supported, because ver 2.0 seems not to be used - * anywhere.
    - * ASF headers contains other chunks. As of this other readers of current - * package are called from within. - * - * @author Christian Laireiter - */ -public class AsfHeaderReader extends ChunkContainerReader { - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_HEADER}; - - /** - * ASF reader configured to extract all information. - */ - private final static AsfHeaderReader FULL_READER; - /** - * ASF reader configured to just extract information about audio streams.
    - * If the ASF file only contains one audio stream it works fine.
    - */ - private final static AsfHeaderReader INFO_READER; - - /** - * ASF reader configured to just extract metadata information.
    - */ - private final static AsfHeaderReader TAG_READER; - - static { - final List> readers = new ArrayList>(); - readers.add(FileHeaderReader.class); - readers.add(StreamChunkReader.class); - INFO_READER = new AsfHeaderReader(readers, true); - readers.clear(); - readers.add(ContentDescriptionReader.class); - readers.add(ContentBrandingReader.class); - readers.add(LanguageListReader.class); - readers.add(MetadataReader.class); - /* - * Create the header extension object readers with just content - * description reader, extended content description reader, language - * list reader and both metadata object readers. - */ - final AsfExtHeaderReader extReader = new AsfExtHeaderReader(readers, - true); - final AsfExtHeaderReader extReader2 = new AsfExtHeaderReader(readers, - true); - TAG_READER = new AsfHeaderReader(readers, true); - TAG_READER.setExtendedHeaderReader(extReader); - readers.add(FileHeaderReader.class); - readers.add(StreamChunkReader.class); - readers.add(EncodingChunkReader.class); - readers.add(EncryptionChunkReader.class); - readers.add(StreamBitratePropertiesReader.class); - FULL_READER = new AsfHeaderReader(readers, false); - FULL_READER.setExtendedHeaderReader(extReader2); - } - - /** - * Creates an instance of this reader. - * - * @param toRegister The chunk readers to utilize. - * @param readChunkOnce if true, each chunk type (identified by chunk - * GUID) will handled only once, if a reader is available, other - * chunks will be discarded. - */ - public AsfHeaderReader(final List> toRegister, - final boolean readChunkOnce) { - super(toRegister, readChunkOnce); - } - - /** - * Creates a Stream that will read from the specified - * {@link RandomAccessFile};
    - * - * @param raf data source to read from. - * @return a stream which accesses the source. - */ - private static InputStream createStream(final RandomAccessFile raf) { - return new FullRequestInputStream(new BufferedInputStream( - new RandomAccessFileInputstream(raf))); - } - - /** - * This method extracts the full ASF-Header from the given file.
    - * If no header could be extracted null is returned.
    - * - * @param file the ASF file to read.
    - * @return AsfHeader-Wrapper, or null if no supported ASF - * header was found. - * @throws IOException on I/O Errors. - */ - public static AsfHeader readHeader(final File file) throws IOException { - final InputStream stream = new FileInputStream(file); - final AsfHeader result = FULL_READER.read(Utils.readGUID(stream), - stream, 0); - stream.close(); - return result; - } - - /** - * This method tries to extract a full ASF-header out of the given stream.
    - * If no header could be extracted null is returned.
    - * - * @param file File which contains the ASF header. - * @return AsfHeader-Wrapper, or null if no supported ASF - * header was found. - * @throws IOException Read errors - */ - public static AsfHeader readHeader(final RandomAccessFile file) - throws IOException { - final InputStream stream = createStream(file); - return FULL_READER.read(Utils.readGUID(stream), stream, 0); - } - - /** - * This method tries to extract an ASF-header out of the given stream, which - * only contains information about the audio stream.
    - * If no header could be extracted null is returned.
    - * - * @param file File which contains the ASF header. - * @return AsfHeader-Wrapper, or null if no supported ASF - * header was found. - * @throws IOException Read errors - */ - public static AsfHeader readInfoHeader(final RandomAccessFile file) - throws IOException { - final InputStream stream = createStream(file); - return INFO_READER.read(Utils.readGUID(stream), stream, 0); - } - - /** - * This method tries to extract an ASF-header out of the given stream, which - * only contains metadata.
    - * If no header could be extracted null is returned.
    - * - * @param file File which contains the ASF header. - * @return AsfHeader-Wrapper, or null if no supported ASF - * header was found. - * @throws IOException Read errors - */ - public static AsfHeader readTagHeader(final RandomAccessFile file) - throws IOException { - final InputStream stream = createStream(file); - return TAG_READER.read(Utils.readGUID(stream), stream, 0); - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - protected AsfHeader createContainer(final long streamPosition, - final BigInteger chunkLength, final InputStream stream) - throws IOException { - final long chunkCount = Utils.readUINT32(stream); - /* - * 2 reserved bytes. first should be equal to 0x01 and second 0x02. ASF - * specification suggests to not read the content if second byte is not - * 0x02. - */ - if (stream.read() != 1) { - throw new IOException("No ASF"); //$NON-NLS-1$ - } - if (stream.read() != 2) { - throw new IOException("No ASF"); //$NON-NLS-1$ - } - /* - * Creating the resulting object - */ - return new AsfHeader(streamPosition, chunkLength, chunkCount); - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * Sets the {@link AsfExtHeaderReader}, which is to be used, when an header - * extension object is found. - * - * @param extReader header extension object reader. - */ - public void setExtendedHeaderReader(final AsfExtHeaderReader extReader) { - for (final GUID curr : extReader.getApplyingIds()) { - this.readerMap.put(curr, extReader); - } - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/AsfStreamer.java b/src/main/java/org/jaudiotagger/audio/asf/io/AsfStreamer.java deleted file mode 100644 index 90758b6..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/AsfStreamer.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.*; -import java.util.ArrayList; -import java.util.List; - -/** - * This class creates a modified copy of an ASF file.
    - * - * @author Christian Laireiter - */ -public class AsfStreamer { - - /** - * Simply copies a chunk from source to - * destination.
    - * The method assumes, that the GUID has already been read and will write - * the provided one to the destination.
    - * The chunk length however will be read and used to determine the amount of - * bytes to copy. - * - * @param guid GUID of the current chunk. - * @param source source of an ASF chunk, which is to be located at the chunk - * length field. - * @param destination the destination to copy the chunk to. - * @throws IOException on I/O errors. - */ - private void copyChunk(final GUID guid, final InputStream source, - final OutputStream destination) throws IOException { - final long chunkSize = Utils.readUINT64(source); - destination.write(guid.getBytes()); - Utils.writeUINT64(chunkSize, destination); - Utils.copy(source, destination, chunkSize - 24); - } - - /** - * Reads the source and applies the modifications provided by - * the given modifiers, and puts it to dest.
    - * Each {@linkplain ChunkModifier modifier} is used only once, so if one - * should be used multiple times, it should be added multiple times into the - * list.
    - * - * @param source the source ASF file - * @param dest the destination to write the modified version to. - * @param modifiers list of chunk modifiers to apply. - * @throws IOException on I/O errors. - */ - public void createModifiedCopy(final InputStream source, - final OutputStream dest, final List modifiers) - throws IOException { - final List modders = new ArrayList(); - if (modifiers != null) { - modders.addAll(modifiers); - } - // Read and check ASF GUID - final GUID readGUID = Utils.readGUID(source); - if (GUID.GUID_HEADER.equals(readGUID)) { - // used to calculate differences - long totalDiff = 0; - long chunkDiff = 0; - - // read header information - final long headerSize = Utils.readUINT64(source); - final long chunkCount = Utils.readUINT32(source); - final byte[] reserved = new byte[2]; - reserved[0] = (byte) (source.read() & 0xFF); - reserved[1] = (byte) (source.read() & 0xFF); - - /* - * bos will get all unmodified and modified header chunks. This is - * necessary, because the header chunk (and file properties chunk) - * need to be adjusted but are written in front of the others. - */ - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - // fileHeader will get the binary representation of the file - // properties chunk, without GUID - byte[] fileHeader = null; - - // Iterate through all chunks - for (long i = 0; i < chunkCount; i++) { - // Read GUID - final GUID curr = Utils.readGUID(source); - // special case for file properties chunk - if (GUID.GUID_FILE.equals(curr)) { - final ByteArrayOutputStream tmp = new ByteArrayOutputStream(); - final long size = Utils.readUINT64(source); - Utils.writeUINT64(size, tmp); - Utils.copy(source, tmp, size - 24); - fileHeader = tmp.toByteArray(); - } else { - /* - * Now look for ChunkModifier objects which modify the - * current chunk - */ - boolean handled = false; - for (int j = 0; j < modders.size() && !handled; j++) { - if (modders.get(j).isApplicable(curr)) { - // alter current chunk - final ModificationResult result = modders.get(j) - .modify(curr, source, bos); - // remember size differences. - chunkDiff += result.getChunkCountDifference(); - totalDiff += result.getByteDifference(); - // remove current modifier from index. - modders.remove(j); - handled = true; - } - } - if (!handled) { - // copy chunks which are not modified. - copyChunk(curr, source, bos); - } - } - } - // Now apply the left modifiers. - for (final ChunkModifier curr : modders) { - // chunks, which were not in the source file, will be added to - // the destination - final ModificationResult result = curr.modify(null, null, bos); - chunkDiff += result.getChunkCountDifference(); - totalDiff += result.getByteDifference(); - } - /* - * Now all header objects have been read or manipulated and stored - * in the internal buffer (bos). - */ - // write ASF GUID - dest.write(readGUID.getBytes()); - // write altered header object size - Utils.writeUINT64(headerSize + totalDiff, dest); - // write altered number of chunks - Utils.writeUINT32(chunkCount + chunkDiff, dest); - // write the reserved 2 bytes (0x01,0x02). - dest.write(reserved); - // write the new file header - modifyFileHeader(new ByteArrayInputStream(fileHeader), dest, - totalDiff); - // write the header objects (chunks) - dest.write(bos.toByteArray()); - // copy the rest of the file (data and index) - Utils.flush(source, dest); - } else { - throw new IllegalArgumentException("No ASF header object."); - } - } - - /** - * This is a slight variation of - * {@link #copyChunk(GUID, InputStream, OutputStream)}, it only handles file - * property chunks correctly.
    - * The copied chunk will have the file size field modified by the given - * fileSizeDiff value. - * - * @param source source of file properties chunk, located at its chunk length - * field. - * @param destination the destination to copy the chunk to. - * @param fileSizeDiff the difference which should be applied. (negative values would - * subtract the stored file size) - * @throws IOException on I/O errors. - */ - private void modifyFileHeader(final InputStream source, - final OutputStream destination, final long fileSizeDiff) - throws IOException { - destination.write(GUID.GUID_FILE.getBytes()); - final long chunkSize = Utils.readUINT64(source); - Utils.writeUINT64(chunkSize, destination); - destination.write(Utils.readGUID(source).getBytes()); - final long fileSize = Utils.readUINT64(source); - Utils.writeUINT64(fileSize + fileSizeDiff, destination); - Utils.copy(source, destination, chunkSize - 48); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkContainerReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/ChunkContainerReader.java deleted file mode 100644 index 46ecbd7..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkContainerReader.java +++ /dev/null @@ -1,215 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.ChunkContainer; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.util.*; -import java.util.logging.Logger; - -/** - * This class represents a reader implementation, which is able to read ASF - * objects (chunks) which store other objects (chunks) within them.
    - * - * @param The {@link ChunkContainer} instance, the implementation will - * create. - * @author Christian Laireiter - */ -abstract class ChunkContainerReader - implements ChunkReader { - - /** - * Within this range, a {@link ChunkReader} should be aware if it fails. - */ - public final static int READ_LIMIT = 8192; - /** - * Logger - */ - protected static final Logger LOGGER = Logger - .getLogger("org.jaudiotabgger.audio"); //$NON-NLS-1$ - /** - * If true each chunk type will only be read once.
    - */ - protected final boolean eachChunkOnce; - /** - * Registers GUIDs to their reader classes.
    - */ - protected final Map readerMap = new HashMap(); - /** - * If true due to a {@linkplain #register(Class) registered} - * chunk reader, all {@link InputStream} objects passed to - * {@link #read(GUID, InputStream, long)} must support mark/reset. - */ - protected boolean hasFailingReaders = false; - - /** - * Creates a reader instance, which only utilizes the given list of chunk - * readers.
    - * - * @param toRegister List of {@link ChunkReader} class instances, which are to be - * utilized by the instance. - * @param readChunkOnce if true, each chunk type (identified by chunk - * GUID) will handled only once, if a reader is available, other - * chunks will be discarded. - */ - protected ChunkContainerReader( - final List> toRegister, - final boolean readChunkOnce) { - this.eachChunkOnce = readChunkOnce; - for (final Class curr : toRegister) { - register(curr); - } - } - - /** - * Checks for the constraints of this class. - * - * @param stream stream to test. - * @throws IllegalArgumentException If stream does not meet the requirements. - */ - protected void checkStream(final InputStream stream) - throws IllegalArgumentException { - if (this.hasFailingReaders && !stream.markSupported()) { - throw new IllegalArgumentException( - "Stream has to support mark/reset."); - } - } - - /** - * This method is called by {@link #read(GUID, InputStream, long)} in order - * to create the resulting object. Implementations of this class should now - * return a new instance of their implementation specific result AND - * all data should be read, until the list of chunks starts. (The - * {@link ChunkContainer#getChunkEnd()} must return a sane result, too)
    - * - * @param streamPosition position of the stream, the chunk starts. - * @param chunkLength the length of the chunk (from chunk header) - * @param stream to read the implementation specific information. - * @return instance of the implementations result. - * @throws IOException On I/O Errors and Invalid data. - */ - abstract protected ChunkType createContainer(long streamPosition, - BigInteger chunkLength, InputStream stream) throws IOException; - - /** - * Gets a configured {@linkplain ChunkReader reader} instance for ASF - * objects (chunks) with the specified guid. - * - * @param guid GUID which identifies the chunk to be read. - * @return an appropriate reader implementation, null if not - * {@linkplain #register(Class) registered}. - */ - protected ChunkReader getReader(final GUID guid) { - return this.readerMap.get(guid); - } - - /** - * Tests whether {@link #getReader(GUID)} won't return null.
    - * - * @param guid GUID which identifies the chunk to be read. - * @return true if a reader is available. - */ - protected boolean isReaderAvailable(final GUID guid) { - return this.readerMap.containsKey(guid); - } - - /** - * This Method implements the reading of a chunk container.
    - * - * @param guid GUID of the currently read container. - * @param stream Stream which contains the chunk container. - * @param chunkStart The start of the chunk container from stream start.
    - * For direct file streams one can assume 0 here. - * @return null if no valid data found, else a Wrapper - * containing all supported data. - * @throws IOException Read errors. - * @throws IllegalArgumentException If one used {@link ChunkReader} could - * {@linkplain ChunkReader#canFail() fail} and the stream source - * doesn't support mark/reset. - */ - public ChunkType read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException, IllegalArgumentException { - checkStream(stream); - final CountingInputStream cis = new CountingInputStream(stream); - if (!Arrays.asList(getApplyingIds()).contains(guid)) { - throw new IllegalArgumentException( - "provided GUID is not supported by this reader."); - } - // For Know the file pointer pointed to an ASF header chunk. - final BigInteger chunkLen = Utils.readBig64(cis); - /* - * now read implementation specific information until the chunk - * collection starts and create the resulting object. - */ - final ChunkType result = createContainer(chunkStart, chunkLen, cis); - // 16 bytes have already been for providing the GUID - long currentPosition = chunkStart + cis.getReadCount() + 16; - - final HashSet alreadyRead = new HashSet(); - /* - * Now reading header of chuncks. - */ - while (currentPosition < result.getChunkEnd()) { - final GUID currentGUID = Utils.readGUID(cis); - final boolean skip = this.eachChunkOnce - && (!isReaderAvailable(currentGUID) || !alreadyRead - .add(currentGUID)); - Chunk chunk; - /* - * If one reader tells it could fail (new method), then check the - * input stream for mark/reset. And use it if failed. - */ - if (!skip && isReaderAvailable(currentGUID)) { - final ChunkReader reader = getReader(currentGUID); - if (reader.canFail()) { - cis.mark(READ_LIMIT); - } - chunk = getReader(currentGUID).read(currentGUID, cis, - currentPosition); - } else { - chunk = ChunkHeaderReader.getInstance().read(currentGUID, cis, - currentPosition); - } - if (chunk == null) { - /* - * Reader failed - */ - cis.reset(); - } else { - if (!skip) { - result.addChunk(chunk); - } - currentPosition = chunk.getChunkEnd(); - // Always take into account, that 16 bytes have been read prior - // to calling this method - assert cis.getReadCount() + chunkStart + 16 == currentPosition; - } - } - - return result; - } - - /** - * Registers the given reader.
    - * - * @param The actual reader implementation. - * @param toRegister chunk reader which is to be registered. - */ - private void register(final Class toRegister) { - try { - final T reader = toRegister.newInstance(); - for (final GUID curr : reader.getApplyingIds()) { - this.readerMap.put(curr, reader); - } - } catch (InstantiationException e) { - LOGGER.severe(e.getMessage()); - } catch (IllegalAccessException e) { - LOGGER.severe(e.getMessage()); - } - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkHeaderReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/ChunkHeaderReader.java deleted file mode 100644 index e058e0a..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkHeaderReader.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * Default reader, Reads GUID and size out of an input stream and creates a - * {@link org.jaudiotagger.audio.asf.data.Chunk}object, finally skips the - * remaining chunk bytes. - * - * @author Christian Laireiter - */ -final class ChunkHeaderReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_UNSPECIFIED}; - - /** - * Default instance. - */ - private static final ChunkHeaderReader INSTANCE = new ChunkHeaderReader(); - - /** - * Hidden Utility class constructor. - */ - private ChunkHeaderReader() { - // Hidden - } - - /** - * Returns an instance of the reader. - * - * @return instance. - */ - public static ChunkHeaderReader getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - final BigInteger chunkLen = Utils.readBig64(stream); - stream.skip(chunkLen.longValue() - 24); - return new Chunk(guid, chunkStart, chunkLen); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkModifier.java b/src/main/java/org/jaudiotagger/audio/asf/io/ChunkModifier.java deleted file mode 100644 index 00dba1a..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkModifier.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Reads an ASF chunk and writes a modified copy.
    - * - * @author Christian Laireiter - */ -public interface ChunkModifier { - - /** - * Determines, whether the modifier handles chunks identified by given - * guid. - * - * @param guid GUID to test. - * @return true, if this modifier can be used to modify the - * chunk. - */ - boolean isApplicable(GUID guid); - - /** - * Writes a modified copy of the chunk into the destination..
    - * - * @param guid GUID of the chunk to modify. - * @param source a stream providing the chunk, starting at the chunks length - * field. - * @param destination destination for the modified chunk. - * @return the differences between source and destination. - * @throws IOException on I/O errors. - */ - ModificationResult modify(GUID guid, InputStream source, - OutputStream destination) throws IOException; - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/ChunkReader.java deleted file mode 100644 index 63ab3c6..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkReader.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.GUID; - -import java.io.IOException; -import java.io.InputStream; - -/** - * A ChunkReader provides methods for reading an ASF chunk.
    - * - * @author Christian Laireiter - */ -public interface ChunkReader { - - /** - * Tells whether the reader can fail to return a valid chunk.
    - * The current Use would be a modified version of {@link StreamChunkReader}, - * which is configured to only manage audio streams. However, the primary - * GUID for audio and video streams is the same. So if a stream shows itself - * to be a video stream, the reader would return null.
    - * - * @return true, if further analysis of the chunk can show, - * that the reader is not applicable, despite the header GUID - * {@linkplain #getApplyingIds() identification} told it can handle - * the chunk. - */ - boolean canFail(); - - /** - * Returns the GUIDs identifying the types of chunk, this reader will parse.
    - * - * @return the GUIDs identifying the types of chunk, this reader will parse.
    - */ - GUID[] getApplyingIds(); - - /** - * Parses the chunk. - * - * @param guid the GUID of the chunks header, which is about to be read. - * @param stream source to read chunk from.
    - * No {@link GUID} is expected at the currents stream position. - * The length of the chunk is about to follow. - * @param streamPosition the position in stream, the chunk starts.
    - * @return the read chunk. (Mostly a subclass of {@link Chunk}).
    - * @throws IOException On I/O Errors. - */ - Chunk read(GUID guid, InputStream stream, long streamPosition) - throws IOException; -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkRemover.java b/src/main/java/org/jaudiotagger/audio/asf/io/ChunkRemover.java deleted file mode 100644 index 98e572a..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ChunkRemover.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.HashSet; -import java.util.Set; - -/** - * This {@link ChunkModifier} implementation is meant to remove selected chunks.
    - * - * @author Christian Laireiter - */ -@SuppressWarnings({"ManualArrayToCollectionCopy"}) -public class ChunkRemover implements ChunkModifier { - - /** - * Stores the GUIDs, which are about to be removed by this modifier.
    - */ - private final Set toRemove; - - /** - * Creates an instance, for removing selected chunks.
    - * - * @param guids the GUIDs which are about to be removed by this modifier. - */ - public ChunkRemover(final GUID... guids) { - this.toRemove = new HashSet(); - for (final GUID current : guids) { - this.toRemove.add(current); - } - } - - /** - * {@inheritDoc} - */ - public boolean isApplicable(final GUID guid) { - return this.toRemove.contains(guid); - } - - /** - * {@inheritDoc} - */ - public ModificationResult modify(final GUID guid, final InputStream source, - final OutputStream destination) throws IOException { - ModificationResult result; - if (guid == null) { - // Now a chunk should be added, however, this implementation is for - // removal. - result = new ModificationResult(0, 0); - } else { - assert isApplicable(guid); - // skip the chunk length minus 24 bytes for the already read length - // and the guid. - final long chunkLen = Utils.readUINT64(source); - source.skip(chunkLen - 24); - result = new ModificationResult(-1, -1 * chunkLen, guid); - } - return result; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ContentBrandingReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/ContentBrandingReader.java deleted file mode 100644 index b409d97..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ContentBrandingReader.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.ContentBranding; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * This reader is used to read the content branding object of ASF streams.
    - * - * @author Christian Laireiter - * @see org.jaudiotagger.audio.asf.data.ContainerType#CONTENT_BRANDING - * @see ContentBranding - */ -public class ContentBrandingReader implements ChunkReader { - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_CONTENT_BRANDING}; - - /** - * Should not be used for now. - */ - protected ContentBrandingReader() { - // NOTHING toDo - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long streamPosition) throws IOException { - assert GUID.GUID_CONTENT_BRANDING.equals(guid); - final BigInteger chunkSize = Utils.readBig64(stream); - final long imageType = Utils.readUINT32(stream); - assert imageType >= 0 && imageType <= 3 : imageType; - final long imageDataSize = Utils.readUINT32(stream); - assert imageType > 0 || imageDataSize == 0 : imageDataSize; - assert imageDataSize < Integer.MAX_VALUE; - final byte[] imageData = Utils.readBinary(stream, imageDataSize); - final long copyRightUrlLen = Utils.readUINT32(stream); - final String copyRight = new String(Utils.readBinary(stream, - copyRightUrlLen)); - final long imageUrlLen = Utils.readUINT32(stream); - final String imageUrl = new String(Utils - .readBinary(stream, imageUrlLen)); - final ContentBranding result = new ContentBranding(streamPosition, - chunkSize); - result.setImage(imageType, imageData); - result.setCopyRightURL(copyRight); - result.setBannerImageURL(imageUrl); - return result; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ContentDescriptionReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/ContentDescriptionReader.java deleted file mode 100644 index f03cf2c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ContentDescriptionReader.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.ContentDescription; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * Reads and interprets the data of a ASF chunk containing title, author...
    - * - * @author Christian Laireiter - * @see org.jaudiotagger.audio.asf.data.ContentDescription - */ -public class ContentDescriptionReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_CONTENTDESCRIPTION}; - - /** - * Should not be used for now. - */ - protected ContentDescriptionReader() { - // NOTHING toDo - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * Returns the next 5 UINT16 values as an array.
    - * - * @param stream stream to read from - * @return 5 int values read from stream. - * @throws IOException on I/O Errors. - */ - private int[] getStringSizes(final InputStream stream) throws IOException { - final int[] result = new int[5]; - for (int i = 0; i < result.length; i++) { - result[i] = Utils.readUINT16(stream); - } - return result; - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - final BigInteger chunkSize = Utils.readBig64(stream); - /* - * Now comes 16-Bit values representing the length of the Strings which - * follows. - */ - final int[] stringSizes = getStringSizes(stream); - - /* - * Now we know the String length of each occuring String. - */ - final String[] strings = new String[stringSizes.length]; - for (int i = 0; i < strings.length; i++) { - if (stringSizes[i] > 0) { - strings[i] = Utils - .readFixedSizeUTF16Str(stream, stringSizes[i]); - } - } - /* - * Now create the result - */ - final ContentDescription result = new ContentDescription(chunkStart, - chunkSize); - if (stringSizes[0] > 0) { - result.setTitle(strings[0]); - } - if (stringSizes[1] > 0) { - result.setAuthor(strings[1]); - } - if (stringSizes[2] > 0) { - result.setCopyright(strings[2]); - } - if (stringSizes[3] > 0) { - result.setComment(strings[3]); - } - if (stringSizes[4] > 0) { - result.setRating(strings[4]); - } - return result; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/CountingInputStream.java b/src/main/java/org/jaudiotagger/audio/asf/io/CountingInputStream.java deleted file mode 100644 index 0bf8dcd..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/CountingInputStream.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * This implementation of {@link FilterInputStream} counts each read byte.
    - * So at each time, with {@link #getReadCount()} one can determine how many - * bytes have been read, by this classes read and skip methods (mark and reset - * are also taken into account).
    - * - * @author Christian Laireiter - */ -class CountingInputStream extends FilterInputStream { - - /** - * If {@link #mark(int)} has been called, the current value of - * {@link #readCount} is stored, in order to reset it upon {@link #reset()}. - */ - private long markPos; - - /** - * The amount of read or skipped bytes. - */ - private long readCount; - - /** - * Creates an instance, which delegates the commands to the given stream. - * - * @param stream stream to actually work with. - */ - public CountingInputStream(final InputStream stream) { - super(stream); - this.markPos = 0; - this.readCount = 0; - } - - /** - * Counts the given amount of bytes. - * - * @param amountRead number of bytes to increase. - */ - private synchronized void bytesRead(final long amountRead) { - if (amountRead >= 0) { - this.readCount += amountRead; - } - } - - /** - * @return the readCount - */ - public synchronized long getReadCount() { - return this.readCount; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void mark(final int readlimit) { - super.mark(readlimit); - this.markPos = this.readCount; - } - - /** - * {@inheritDoc} - */ - @Override - public int read() throws IOException { - final int result = super.read(); - bytesRead(1); - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public int read(final byte[] destination, final int off, final int len) - throws IOException { - final int result = super.read(destination, off, len); - bytesRead(result); - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void reset() throws IOException { - super.reset(); - synchronized (this) { - this.readCount = this.markPos; - } - } - - /** - * {@inheritDoc} - */ - @Override - public long skip(final long amount) throws IOException { - final long skipped = super.skip(amount); - bytesRead(skipped); - return skipped; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/CountingOutputstream.java b/src/main/java/org/jaudiotagger/audio/asf/io/CountingOutputstream.java deleted file mode 100644 index 263c0d9..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/CountingOutputstream.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * This output stream wraps around another {@link OutputStream} and delegates - * the write calls.
    - * Additionally all written bytes are counted and available by - * {@link #getCount()}. - * - * @author Christian Laireiter - */ -public class CountingOutputstream extends OutputStream { - - /** - * The stream to forward the write calls. - */ - private final OutputStream wrapped; - /** - * Stores the amount of bytes written. - */ - private long count = 0; - - /** - * Creates an instance which will delegate the write calls to the given - * output stream. - * - * @param outputStream stream to wrap. - */ - public CountingOutputstream(final OutputStream outputStream) { - super(); - assert outputStream != null; - this.wrapped = outputStream; - } - - /** - * {@inheritDoc} - */ - @Override - public void close() throws IOException { - this.wrapped.close(); - } - - /** - * {@inheritDoc} - */ - @Override - public void flush() throws IOException { - this.wrapped.flush(); - } - - /** - * @return the count - */ - public long getCount() { - return this.count; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(final byte[] bytes) throws IOException { - this.wrapped.write(bytes); - this.count += bytes.length; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(final byte[] bytes, final int off, final int len) - throws IOException { - this.wrapped.write(bytes, off, len); - this.count += len; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(final int toWrite) throws IOException { - this.wrapped.write(toWrite); - this.count++; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/EncodingChunkReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/EncodingChunkReader.java deleted file mode 100644 index 76cc54e..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/EncodingChunkReader.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.EncodingChunk; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * This class reads the chunk containing encoding data
    - * Warning:
    - * Implementation is not completed. More analysis of this chunk is needed. - * - * @author Christian Laireiter - */ -class EncodingChunkReader implements ChunkReader { - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_ENCODING}; - - /** - * Should not be used for now. - */ - protected EncodingChunkReader() { - // NOTHING toDo - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - final BigInteger chunkLen = Utils.readBig64(stream); - final EncodingChunk result = new EncodingChunk(chunkLen); - int readBytes = 24; - // Can't be interpreted - /* - * What do I think of this data, well it seems to be another GUID. Then - * followed by a UINT16 indicating a length of data following (by half). - * My test files just had the length of one and a two bytes zero. - */ - stream.skip(20); - readBytes += 20; - - /* - * Read the number of strings which will follow - */ - final int stringCount = Utils.readUINT16(stream); - readBytes += 2; - - /* - * Now reading the specified amount of strings. - */ - for (int i = 0; i < stringCount; i++) { - final String curr = Utils.readCharacterSizedString(stream); - result.addString(curr); - readBytes += 4 + 2 * curr.length(); - } - stream.skip(chunkLen.longValue() - readBytes); - result.setPosition(chunkStart); - return result; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/EncryptionChunkReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/EncryptionChunkReader.java deleted file mode 100644 index cd50671..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/EncryptionChunkReader.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.EncryptionChunk; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * This class reads the chunk containing encoding data
    - * Warning:
    - * Implementation is not completed. More analysis of this chunk is needed. - * - * @author Christian Laireiter - */ -class EncryptionChunkReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_CONTENT_ENCRYPTION}; - - /** - * Should not be used for now. - */ - protected EncryptionChunkReader() { - // NOTHING toDo - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - EncryptionChunk result; - final BigInteger chunkLen = Utils.readBig64(stream); - result = new EncryptionChunk(chunkLen); - - // Can't be interpreted - /* - * Object ID GUID 128 Object Size QWORD 64 Secret Data Length DWORD 32 - * Secret Data INTEGER varies Protection Type Length DWORD 32 Protection - * Type char varies Key ID Length DWORD 32 Key ID char varies License - * URL Length DWORD 32 License URL char varies * Read the - */ - byte[] secretData; - byte[] protectionType; - byte[] keyID; - byte[] licenseURL; - - // Secret Data length - int fieldLength; - fieldLength = (int) Utils.readUINT32(stream); - // Secret Data - secretData = new byte[fieldLength + 1]; - stream.read(secretData, 0, fieldLength); - secretData[fieldLength] = 0; - - // Protection type Length - fieldLength = 0; - fieldLength = (int) Utils.readUINT32(stream); - // Protection Data Length - protectionType = new byte[fieldLength + 1]; - stream.read(protectionType, 0, fieldLength); - protectionType[fieldLength] = 0; - - // Key ID length - fieldLength = 0; - fieldLength = (int) Utils.readUINT32(stream); - // Key ID - keyID = new byte[fieldLength + 1]; - stream.read(keyID, 0, fieldLength); - keyID[fieldLength] = 0; - - // License URL length - fieldLength = 0; - fieldLength = (int) Utils.readUINT32(stream); - // License URL - licenseURL = new byte[fieldLength + 1]; - stream.read(licenseURL, 0, fieldLength); - licenseURL[fieldLength] = 0; - - result.setSecretData(new String(secretData)); - result.setProtectionType(new String(protectionType)); - result.setKeyID(new String(keyID)); - result.setLicenseURL(new String(licenseURL)); - - result.setPosition(chunkStart); - - return result; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/FileHeaderReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/FileHeaderReader.java deleted file mode 100644 index a33be46..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/FileHeaderReader.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.FileHeader; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * Reads and interprets the data of the file header.
    - * - * @author Christian Laireiter - */ -public class FileHeaderReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_FILE}; - - /** - * Should not be used for now. - */ - protected FileHeaderReader() { - // NOTHING toDo - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - final BigInteger chunkLen = Utils.readBig64(stream); - // Skip client GUID. - stream.skip(16); - final BigInteger fileSize = Utils.readBig64(stream); - // fileTime in 100 ns since midnight of 1st january 1601 GMT - final BigInteger fileTime = Utils.readBig64(stream); - - final BigInteger packageCount = Utils.readBig64(stream); - - final BigInteger timeEndPos = Utils.readBig64(stream); - final BigInteger duration = Utils.readBig64(stream); - final BigInteger timeStartPos = Utils.readBig64(stream); - - final long flags = Utils.readUINT32(stream); - - final long minPkgSize = Utils.readUINT32(stream); - final long maxPkgSize = Utils.readUINT32(stream); - final long uncompressedFrameSize = Utils.readUINT32(stream); - - final FileHeader result = new FileHeader(chunkLen, fileSize, fileTime, - packageCount, duration, timeStartPos, timeEndPos, flags, - minPkgSize, maxPkgSize, uncompressedFrameSize); - result.setPosition(chunkStart); - return result; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/FullRequestInputStream.java b/src/main/java/org/jaudiotagger/audio/asf/io/FullRequestInputStream.java deleted file mode 100644 index 7b01947..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/FullRequestInputStream.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * This implementation repeatedly reads from the wrapped input stream until the - * requested amount of bytes are read.
    - * - * @author Christian Laireiter - */ -public class FullRequestInputStream extends FilterInputStream { - - /** - * Creates an instance. - * - * @param source stream to read from. - */ - public FullRequestInputStream(final InputStream source) { - super(source); - } - - /** - * {@inheritDoc} - */ - @Override - public int read(final byte[] buffer) throws IOException { - return read(buffer, 0, buffer.length); - } - - /** - * {@inheritDoc} - */ - @Override - public int read(final byte[] buffer, final int off, final int len) - throws IOException { - int totalRead = 0; - int read; - while (totalRead < len) { - read = super.read(buffer, off + totalRead, len - totalRead); - if (read >= 0) { - totalRead += read; - } - if (read == -1) { - throw new IOException((len - totalRead) - + " more bytes expected."); - } - } - return totalRead; - } - - /** - * {@inheritDoc} - */ - @Override - public long skip(final long amount) throws IOException { - long skipped = 0; - int zeroSkipCnt = 0; - long currSkipped; - while (skipped < amount) { - currSkipped = super.skip(amount - skipped); - if (currSkipped == 0) { - zeroSkipCnt++; - if (zeroSkipCnt == 2) { - // If the skip value exceeds streams size, this and the - // number is extremely large, this can lead to a very long - // running loop. - break; - } - } - skipped += currSkipped; - } - return skipped; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/LanguageListReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/LanguageListReader.java deleted file mode 100644 index 89cbb0c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/LanguageListReader.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.data.LanguageList; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * Reads and interprets the "Language List Object" of ASF files.
    - * - * @author Christian Laireiter - */ -public class LanguageListReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_LANGUAGE_LIST}; - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long streamPosition) throws IOException { - assert GUID.GUID_LANGUAGE_LIST.equals(guid); - final BigInteger chunkLen = Utils.readBig64(stream); - - final int readUINT16 = Utils.readUINT16(stream); - - final LanguageList result = new LanguageList(streamPosition, chunkLen); - for (int i = 0; i < readUINT16; i++) { - final int langIdLen = (stream.read() & 0xFF); - final String langId = Utils - .readFixedSizeUTF16Str(stream, langIdLen); - // langIdLen = 2 bytes for each char and optionally one zero - // termination character - assert langId.length() == langIdLen / 2 - 1 - || langId.length() == langIdLen / 2; - result.addLanguage(langId); - } - - return result; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/MetadataReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/MetadataReader.java deleted file mode 100644 index d5ef7de..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/MetadataReader.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.*; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * Reads an interprets "Metadata Object", "Metadata Library - * Object" and "Extended Content Description" of ASF files.
    - * - * @author Christian Laireiter - */ -public class MetadataReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = { - ContainerType.EXTENDED_CONTENT.getContainerGUID(), - ContainerType.METADATA_OBJECT.getContainerGUID(), - ContainerType.METADATA_LIBRARY_OBJECT.getContainerGUID()}; - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long streamPosition) throws IOException { - final BigInteger chunkLen = Utils.readBig64(stream); - - final MetadataContainer result = new MetadataContainer(guid, - streamPosition, chunkLen); - // isExtDesc will be set to true, if a extended content description - // chunk is read - // otherwise it is a metadata object, there are only slight differences - final boolean isExtDesc = result.getContainerType() == ContainerType.EXTENDED_CONTENT; - final int recordCount = Utils.readUINT16(stream); - for (int i = 0; i < recordCount; i++) { - int languageIndex = 0; - int streamNumber = 0; - if (!isExtDesc) { - /* - * Metadata objects have a language index and a stream number - */ - languageIndex = Utils.readUINT16(stream); - assert languageIndex >= 0 - && languageIndex < MetadataDescriptor.MAX_LANG_INDEX; - assert result.getContainerType() == ContainerType.METADATA_LIBRARY_OBJECT - || languageIndex == 0; - streamNumber = Utils.readUINT16(stream); - assert streamNumber >= 0 - && streamNumber <= MetadataDescriptor.MAX_STREAM_NUMBER; - } - final int nameLen = Utils.readUINT16(stream); - String recordName = null; - if (isExtDesc) { - recordName = Utils.readFixedSizeUTF16Str(stream, nameLen); - } - final int dataType = Utils.readUINT16(stream); - assert dataType >= 0 && dataType <= 6; - final long dataLen = isExtDesc ? Utils.readUINT16(stream) : Utils - .readUINT32(stream); - assert dataLen >= 0; - assert result.getContainerType() == ContainerType.METADATA_LIBRARY_OBJECT - || dataLen <= MetadataDescriptor.DWORD_MAXVALUE; - if (!isExtDesc) { - recordName = Utils.readFixedSizeUTF16Str(stream, nameLen); - } - final MetadataDescriptor descriptor = new MetadataDescriptor(result - .getContainerType(), recordName, dataType, streamNumber, - languageIndex); - switch (dataType) { - case MetadataDescriptor.TYPE_STRING: - descriptor.setStringValue(Utils.readFixedSizeUTF16Str(stream, - (int) dataLen)); - break; - case MetadataDescriptor.TYPE_BINARY: - descriptor.setBinaryValue(Utils.readBinary(stream, dataLen)); - break; - case MetadataDescriptor.TYPE_BOOLEAN: - assert isExtDesc && dataLen == 4 || !isExtDesc && dataLen == 2; - descriptor.setBooleanValue(readBoolean(stream, (int) dataLen)); - break; - case MetadataDescriptor.TYPE_DWORD: - assert dataLen == 4; - descriptor.setDWordValue(Utils.readUINT32(stream)); - break; - case MetadataDescriptor.TYPE_WORD: - assert dataLen == 2; - descriptor.setWordValue(Utils.readUINT16(stream)); - break; - case MetadataDescriptor.TYPE_QWORD: - assert dataLen == 8; - descriptor.setQWordValue(Utils.readUINT64(stream)); - break; - case MetadataDescriptor.TYPE_GUID: - assert dataLen == GUID.GUID_LENGTH; - descriptor.setGUIDValue(Utils.readGUID(stream)); - break; - default: - // Unknown, hopefully the convention for the size of the - // value - // is given, so we could read it binary - descriptor.setStringValue("Invalid datatype: " - + new String(Utils.readBinary(stream, dataLen))); - } - result.addDescriptor(descriptor); - } - return result; - } - - /** - * Reads the given amount of bytes and checks the last byte, if its equal to - * one or zero (true / false).
    - * All other bytes must be zero. (if assertions enabled). - * - * @param stream stream to read from. - * @param bytes amount of bytes - * @return true or false. - * @throws IOException on I/O Errors - */ - private boolean readBoolean(final InputStream stream, final int bytes) - throws IOException { - final byte[] tmp = new byte[bytes]; - stream.read(tmp); - boolean result = false; - for (int i = 0; i < bytes; i++) { - if (i == bytes - 1) { - result = tmp[i] == 1; - assert tmp[i] == 0 || tmp[i] == 1; - } else { - assert tmp[i] == 0; - } - } - return result; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/ModificationResult.java b/src/main/java/org/jaudiotagger/audio/asf/io/ModificationResult.java deleted file mode 100644 index fbfc41a..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/ModificationResult.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * Structure to tell the differences occurred by altering a chunk. - * - * @author Christian Laireiter - */ -final class ModificationResult { - - /** - * Stores the difference of bytes.
    - */ - private final long byteDifference; - - /** - * Stores the difference of the amount of chunks.
    - * "-1" if the chunk disappeared upon modification.
    - * "0" if the chunk was just modified.
    - * "1" if a chunk has been created.
    - */ - private final int chunkDifference; - - /** - * Stores all GUIDs, which have been read.
    - */ - private final Set occuredGUIDs = new HashSet(); - - /** - * Creates an instance.
    - * - * @param chunkCountDiff amount of chunks appeared, disappeared - * @param bytesDiffer amount of bytes added or removed. - * @param occurred all GUIDs which have been occurred, during processing - */ - public ModificationResult(final int chunkCountDiff, final long bytesDiffer, - final GUID... occurred) { - assert occurred != null && occurred.length > 0; - this.chunkDifference = chunkCountDiff; - this.byteDifference = bytesDiffer; - this.occuredGUIDs.addAll(Arrays.asList(occurred)); - } - - /** - * Creates an instance.
    - * - * @param chunkCountDiff amount of chunks appeared, disappeared - * @param bytesDiffer amount of bytes added or removed. - * @param occurred all GUIDs which have been occurred, during processing - */ - public ModificationResult(final int chunkCountDiff, final long bytesDiffer, - final Set occurred) { - this.chunkDifference = chunkCountDiff; - this.byteDifference = bytesDiffer; - this.occuredGUIDs.addAll(occurred); - } - - /** - * Returns the difference of bytes. - * - * @return the byte difference - */ - public long getByteDifference() { - return this.byteDifference; - } - - /** - * Returns the difference of the amount of chunks. - * - * @return the chunk count difference - */ - public int getChunkCountDifference() { - return this.chunkDifference; - } - - /** - * Returns all GUIDs which have been occurred during processing. - * - * @return see description.s - */ - public Set getOccuredGUIDs() { - return new HashSet(this.occuredGUIDs); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java b/src/main/java/org/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java deleted file mode 100644 index 7fc691d..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; - -/** - * Wraps a {@link RandomAccessFile} into an {@link InputStream}.
    - * - * @author Christian Laireiter - */ -public final class RandomAccessFileInputstream extends InputStream { - - /** - * The file access to read from.
    - */ - private final RandomAccessFile source; - - /** - * Creates an instance that will provide {@link InputStream} functionality - * on the given {@link RandomAccessFile} by delegating calls.
    - * - * @param file The file to read. - */ - public RandomAccessFileInputstream(final RandomAccessFile file) { - super(); - if (file == null) { - throw new IllegalArgumentException("null"); - } - this.source = file; - } - - /** - * {@inheritDoc} - */ - @Override - public int read() throws IOException { - return this.source.read(); - } - - /** - * {@inheritDoc} - */ - @Override - public int read(final byte[] buffer, final int off, final int len) - throws IOException { - return this.source.read(buffer, off, len); - } - - /** - * {@inheritDoc} - */ - @Override - public long skip(final long amount) throws IOException { - if (amount < 0) { - throw new IllegalArgumentException("invalid negative value"); - } - long left = amount; - while (left > Integer.MAX_VALUE) { - this.source.skipBytes(Integer.MAX_VALUE); - left -= Integer.MAX_VALUE; - } - return this.source.skipBytes((int) left); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java b/src/main/java/org/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java deleted file mode 100644 index 7daf74f..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.RandomAccessFile; - -/** - * Wraps a {@link RandomAccessFile} into an {@link OutputStream}.
    - * - * @author Christian Laireiter - */ -public final class RandomAccessFileOutputStream extends OutputStream { - - /** - * the file to write to. - */ - private final RandomAccessFile targetFile; - - /** - * Creates an instance.
    - * - * @param target file to write to. - */ - public RandomAccessFileOutputStream(final RandomAccessFile target) { - super(); - this.targetFile = target; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(final byte[] bytes, final int off, final int len) - throws IOException { - this.targetFile.write(bytes, off, len); - } - - /** - * {@inheritDoc} - */ - @Override - public void write(final int toWrite) throws IOException { - this.targetFile.write(toWrite); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java deleted file mode 100644 index fafdeb7..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.Chunk; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.data.StreamBitratePropertiesChunk; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * This class reads the chunk containing the stream bitrate properties.
    - * - * @author Christian Laireiter - */ -public class StreamBitratePropertiesReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_STREAM_BITRATE_PROPERTIES}; - - /** - * Should not be used for now. - */ - protected StreamBitratePropertiesReader() { - // NOTHING toDo - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return false; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - final BigInteger chunkLen = Utils.readBig64(stream); - final StreamBitratePropertiesChunk result = new StreamBitratePropertiesChunk( - chunkLen); - - /* - * Read the amount of bitrate records - */ - final long recordCount = Utils.readUINT16(stream); - for (int i = 0; i < recordCount; i++) { - final int flags = Utils.readUINT16(stream); - final long avgBitrate = Utils.readUINT32(stream); - result.addBitrateRecord(flags & 0x00FF, avgBitrate); - } - - result.setPosition(chunkStart); - - return result; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/StreamChunkReader.java b/src/main/java/org/jaudiotagger/audio/asf/io/StreamChunkReader.java deleted file mode 100644 index 1892611..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/StreamChunkReader.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.*; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; - -/** - * Reads and interprets the data of the audio or video stream information chunk.
    - * - * @author Christian Laireiter - */ -public class StreamChunkReader implements ChunkReader { - - /** - * The GUID this reader {@linkplain #getApplyingIds() applies to} - */ - private final static GUID[] APPLYING = {GUID.GUID_STREAM}; - - /** - * Shouldn't be used for now. - */ - protected StreamChunkReader() { - // Nothing to do - } - - /** - * {@inheritDoc} - */ - public boolean canFail() { - return true; - } - - /** - * {@inheritDoc} - */ - public GUID[] getApplyingIds() { - return APPLYING.clone(); - } - - /** - * {@inheritDoc} - */ - public Chunk read(final GUID guid, final InputStream stream, - final long chunkStart) throws IOException { - StreamChunk result = null; - final BigInteger chunkLength = Utils.readBig64(stream); - // Now comes GUID indicating whether stream content type is audio or - // video - final GUID streamTypeGUID = Utils.readGUID(stream); - if (GUID.GUID_AUDIOSTREAM.equals(streamTypeGUID) - || GUID.GUID_VIDEOSTREAM.equals(streamTypeGUID)) { - - // A GUID is indicating whether the stream is error - // concealed - final GUID errorConcealment = Utils.readGUID(stream); - /* - * Read the Time Offset - */ - final long timeOffset = Utils.readUINT64(stream); - - final long typeSpecificDataSize = Utils.readUINT32(stream); - final long streamSpecificDataSize = Utils.readUINT32(stream); - - /* - * Read a bit field. (Contains stream number, and whether the stream - * content is encrypted.) - */ - final int mask = Utils.readUINT16(stream); - final int streamNumber = mask & 127; - final boolean contentEncrypted = (mask & 0x8000) != 0; - - /* - * Skip a reserved field - */ - stream.skip(4); - - /* - * very important to set for every stream type. The size of bytes - * read by the specific stream type, in order to skip the remaining - * unread bytes of the stream chunk. - */ - long streamSpecificBytes; - - if (GUID.GUID_AUDIOSTREAM.equals(streamTypeGUID)) { - /* - * Reading audio specific information - */ - final AudioStreamChunk audioStreamChunk = new AudioStreamChunk( - chunkLength); - result = audioStreamChunk; - - /* - * read WAVEFORMATEX and format extension. - */ - final long compressionFormat = Utils.readUINT16(stream); - final long channelCount = Utils.readUINT16(stream); - final long samplingRate = Utils.readUINT32(stream); - final long avgBytesPerSec = Utils.readUINT32(stream); - final long blockAlignment = Utils.readUINT16(stream); - final int bitsPerSample = Utils.readUINT16(stream); - final int codecSpecificDataSize = Utils.readUINT16(stream); - final byte[] codecSpecificData = new byte[codecSpecificDataSize]; - stream.read(codecSpecificData); - - audioStreamChunk.setCompressionFormat(compressionFormat); - audioStreamChunk.setChannelCount(channelCount); - audioStreamChunk.setSamplingRate(samplingRate); - audioStreamChunk.setAverageBytesPerSec(avgBytesPerSec); - audioStreamChunk.setErrorConcealment(errorConcealment); - audioStreamChunk.setBlockAlignment(blockAlignment); - audioStreamChunk.setBitsPerSample(bitsPerSample); - audioStreamChunk.setCodecData(codecSpecificData); - - streamSpecificBytes = 18 + codecSpecificData.length; - } else { - /* - * Reading video specific information - */ - final VideoStreamChunk videoStreamChunk = new VideoStreamChunk( - chunkLength); - result = videoStreamChunk; - - final long pictureWidth = Utils.readUINT32(stream); - final long pictureHeight = Utils.readUINT32(stream); - - // Skip unknown field - stream.skip(1); - - /* - * Now read the format specific data - */ - // Size of the data section (formatDataSize) - stream.skip(2); - - stream.skip(16); - final byte[] fourCC = new byte[4]; - stream.read(fourCC); - - videoStreamChunk.setPictureWidth(pictureWidth); - videoStreamChunk.setPictureHeight(pictureHeight); - videoStreamChunk.setCodecId(fourCC); - - streamSpecificBytes = 31; - } - - /* - * Setting common values for audio and video - */ - result.setStreamNumber(streamNumber); - result.setStreamSpecificDataSize(streamSpecificDataSize); - result.setTypeSpecificDataSize(typeSpecificDataSize); - result.setTimeOffset(timeOffset); - result.setContentEncrypted(contentEncrypted); - result.setPosition(chunkStart); - /* - * Now skip remainder of chunks bytes. chunk-length - 24 (size of - * GUID and chunklen) - streamSpecificBytes(stream type specific - * data) - 54 (common data) - */ - stream - .skip(chunkLength.longValue() - 24 - streamSpecificBytes - - 54); - } - return result; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/WriteableChunk.java b/src/main/java/org/jaudiotagger/audio/asf/io/WriteableChunk.java deleted file mode 100644 index 9cda2e8..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/WriteableChunk.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * Implementors can write themselves directly to an output stream, and have the - * ability to tell the size they would need, as well as determine if they are - * empty.
    - * - * @author Christian Laireiter - */ -public interface WriteableChunk { - - /** - * This method calculates the total amount of bytes, the chunk would consume - * in an ASF file.
    - * - * @return amount of bytes the chunk would currently need in an ASF file. - */ - long getCurrentAsfChunkSize(); - - /** - * Returns the GUID of the chunk. - * - * @return GUID of the chunk. - */ - GUID getGuid(); - - /** - * true if it is not necessary to write the chunk into an ASF - * file, since it contains no information. - * - * @return true if no useful data will be preserved. - */ - boolean isEmpty(); - - /** - * Writes the chunk into the specified output stream, as ASF stream chunk.
    - * - * @param out stream to write into. - * @return amount of bytes written. - * @throws IOException on I/O errors - */ - long writeInto(OutputStream out) throws IOException; -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/WriteableChunkModifer.java b/src/main/java/org/jaudiotagger/audio/asf/io/WriteableChunkModifer.java deleted file mode 100644 index 2e99494..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/WriteableChunkModifer.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.jaudiotagger.audio.asf.io; - -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.audio.asf.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * A chunk modifier which works with information provided by - * {@link WriteableChunk} objects.
    - * - * @author Christian Laireiter - */ -public class WriteableChunkModifer implements ChunkModifier { - - /** - * The chunk to write. - */ - private final WriteableChunk writableChunk; - - /** - * Creates an instance.
    - * - * @param chunk chunk to write - */ - public WriteableChunkModifer(final WriteableChunk chunk) { - this.writableChunk = chunk; - } - - /** - * {@inheritDoc} - */ - public boolean isApplicable(final GUID guid) { - return guid.equals(this.writableChunk.getGuid()); - } - - /** - * {@inheritDoc} - */ - public ModificationResult modify(final GUID guid, final InputStream chunk, - OutputStream destination) throws IOException { // NOPMD by Christian Laireiter on 5/9/09 5:03 PM - int chunkDiff = 0; - long newSize = 0; - long oldSize = 0; - /* - * Replace the outputstream with the counting one, only if assert's are - * evaluated. - */ - assert (destination = new CountingOutputstream(destination)) != null; - if (!this.writableChunk.isEmpty()) { - newSize = this.writableChunk.writeInto(destination); - assert newSize == this.writableChunk.getCurrentAsfChunkSize(); - /* - * If assert's are evaluated, we have replaced destination by a - * CountingOutpustream and can now verify if - * getCurrentAsfChunkSize() really works correctly. - */ - assert ((CountingOutputstream) destination).getCount() == newSize; - if (guid == null) { - chunkDiff++; - } - - } - if (guid != null) { - assert isApplicable(guid); - if (this.writableChunk.isEmpty()) { - chunkDiff--; - } - oldSize = Utils.readUINT64(chunk); - chunk.skip(oldSize - 24); - } - return new ModificationResult(chunkDiff, (newSize - oldSize), guid); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/asf/io/package.html b/src/main/java/org/jaudiotagger/audio/asf/io/package.html deleted file mode 100644 index 452c397..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/io/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for reading and writing Microsoft Advanced Systems Format files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/asf/package.html b/src/main/java/org/jaudiotagger/audio/asf/package.html deleted file mode 100644 index 633b3c4..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for Microsoft Advanced Systems Format files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/asf/util/ChunkPositionComparator.java b/src/main/java/org/jaudiotagger/audio/asf/util/ChunkPositionComparator.java deleted file mode 100644 index cd1bb0c..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/util/ChunkPositionComparator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.util; - -import org.jaudiotagger.audio.asf.data.Chunk; - -import java.io.Serializable; -import java.util.Comparator; - -/** - * This class is needed for ordering all types of - * {@link org.jaudiotagger.audio.asf.data.Chunk}s ascending by their Position.
    - * - * @author Christian Laireiter - */ -public final class ChunkPositionComparator implements Comparator, - Serializable { - - /** - * - */ - private static final long serialVersionUID = -6337108235272376289L; - - /** - * {@inheritDoc} - */ - public int compare(final Chunk first, final Chunk second) { - return Long.valueOf(first.getPosition()) - .compareTo(second.getPosition()); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/util/TagConverter.java b/src/main/java/org/jaudiotagger/audio/asf/util/TagConverter.java deleted file mode 100644 index fb2a462..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/util/TagConverter.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.util; - -import org.jaudiotagger.audio.asf.data.*; -import org.jaudiotagger.tag.FieldKey; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.asf.*; -import org.jaudiotagger.tag.reference.GenreTypes; - -import java.util.Iterator; -import java.util.List; - -/** - * This class provides functionality to convert - * {@link org.jaudiotagger.audio.asf.data.AsfHeader}objects into - * {@link org.jaudiotagger.tag.Tag}objects.
    - * - * @author Christian Laireiter (liree) - */ -public final class TagConverter { - - /** - * Hidden utility class constructor. - */ - private TagConverter() { - // Nothing to do. - } - - /** - * This method assigns those tags of tag which are defined to - * be common by jaudiotagger.
    - * - * @param tag The tag from which the values are gathered.
    - * Assigned values are:
    - * @param description The extended content description which should receive the - * values.
    - * Warning: the common values will be replaced. - */ - public static void assignCommonTagValues(Tag tag, - MetadataContainer description) { - assert description.getContainerType() == ContainerType.EXTENDED_CONTENT; - MetadataDescriptor tmp; - if (!Utils.isBlank(tag.getFirst(FieldKey.ALBUM))) { - tmp = new MetadataDescriptor(description.getContainerType(), - AsfFieldKey.ALBUM.getFieldName(), - MetadataDescriptor.TYPE_STRING); - tmp.setStringValue(tag.getFirst(FieldKey.ALBUM)); - description.removeDescriptorsByName(tmp.getName()); - description.addDescriptor(tmp); - } else { - description.removeDescriptorsByName(AsfFieldKey.ALBUM - .getFieldName()); - } - if (!Utils.isBlank(tag.getFirst(FieldKey.TRACK))) { - tmp = new MetadataDescriptor(description.getContainerType(), - AsfFieldKey.TRACK.getFieldName(), - MetadataDescriptor.TYPE_STRING); - tmp.setStringValue(tag.getFirst(FieldKey.TRACK)); - description.removeDescriptorsByName(tmp.getName()); - description.addDescriptor(tmp); - } else { - description.removeDescriptorsByName(AsfFieldKey.TRACK - .getFieldName()); - } - if (!Utils.isBlank(tag.getFirst(FieldKey.YEAR))) { - tmp = new MetadataDescriptor(description.getContainerType(), - AsfFieldKey.YEAR.getFieldName(), - MetadataDescriptor.TYPE_STRING); - tmp.setStringValue(tag.getFirst(FieldKey.YEAR)); - description.removeDescriptorsByName(tmp.getName()); - description.addDescriptor(tmp); - } else { - description - .removeDescriptorsByName(AsfFieldKey.YEAR.getFieldName()); - } - if (!Utils.isBlank(tag.getFirst(FieldKey.GENRE))) { - // Write Genre String value - tmp = new MetadataDescriptor(description.getContainerType(), - AsfFieldKey.GENRE.getFieldName(), - MetadataDescriptor.TYPE_STRING); - tmp.setStringValue(tag.getFirst(FieldKey.GENRE)); - description.removeDescriptorsByName(tmp.getName()); - description.addDescriptor(tmp); - Integer genreNum = GenreTypes.getInstanceOf().getIdForName( - tag.getFirst(FieldKey.GENRE)); - // ..and if it is one of the standard genre types used the id as - // well - if (genreNum != null) { - tmp = new MetadataDescriptor(description.getContainerType(), - AsfFieldKey.GENRE_ID.getFieldName(), - MetadataDescriptor.TYPE_STRING); - tmp.setStringValue("(" + genreNum + ")"); - description.removeDescriptorsByName(tmp.getName()); - description.addDescriptor(tmp); - } else { - description.removeDescriptorsByName(AsfFieldKey.GENRE_ID - .getFieldName()); - } - } else { - description.removeDescriptorsByName(AsfFieldKey.GENRE - .getFieldName()); - description.removeDescriptorsByName(AsfFieldKey.GENRE_ID - .getFieldName()); - } - } - - /** - * This method creates a {@link Tag}and fills it with the contents of the - * given {@link AsfHeader}.
    - * - * @param source The ASF header which contains the information.
    - * @return A Tag with all its values. - */ - public static AsfTag createTagOf(AsfHeader source) { - // TODO do we need to copy here. - AsfTag result = new AsfTag(true); - for (int i = 0; i < ContainerType.values().length; i++) { - MetadataContainer current = source - .findMetadataContainer(ContainerType.values()[i]); - if (current != null) { - List descriptors = current.getDescriptors(); - for (MetadataDescriptor descriptor : descriptors) { - AsfTagField toAdd; - if (descriptor.getType() == MetadataDescriptor.TYPE_BINARY) { - if (descriptor.getName().equals( - AsfFieldKey.COVER_ART.getFieldName())) { - toAdd = new AsfTagCoverField(descriptor); - } else if (descriptor.getName().equals( - AsfFieldKey.BANNER_IMAGE.getFieldName())) { - toAdd = new AsfTagBannerField(descriptor); - } else { - toAdd = new AsfTagField(descriptor); - } - } else { - toAdd = new AsfTagTextField(descriptor); - } - result.addField(toAdd); - } - } - } - return result; - } - - /** - * This method distributes the tags fields among the - * {@linkplain ContainerType#getOrdered()} {@linkplain MetadataContainer - * containers}. - * - * @param tag the tag with the fields to distribute. - * @return distribution - */ - public static MetadataContainer[] distributeMetadata(final AsfTag tag) { - final Iterator asfFields = tag.getAsfFields(); - final MetadataContainer[] createContainers = MetadataContainerFactory - .getInstance().createContainers(ContainerType.getOrdered()); - boolean assigned; - AsfTagField current; - while (asfFields.hasNext()) { - current = asfFields.next(); - assigned = false; - for (int i = 0; !assigned && i < createContainers.length; i++) { - if (ContainerType.areInCorrectOrder(createContainers[i] - .getContainerType(), AsfFieldKey.getAsfFieldKey( - current.getId()).getHighestContainer())) { - if (createContainers[i].isAddSupported(current - .getDescriptor())) { - createContainers[i].addDescriptor(current - .getDescriptor()); - assigned = true; - } - } - } - assert assigned; - } - return createContainers; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/util/Utils.java b/src/main/java/org/jaudiotagger/audio/asf/util/Utils.java deleted file mode 100644 index 27a2bbc..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/util/Utils.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.asf.util; - -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.asf.data.GUID; -import org.jaudiotagger.logging.ErrorMessage; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.Date; -import java.util.GregorianCalendar; - -/** - * Some static Methods which are used in several Classes.
    - * - * @author Christian Laireiter - */ -public class Utils { - - public static final long DIFF_BETWEEN_ASF_DATE_AND_JAVA_DATE = 11644470000000l; - /** - * Stores the default line separator of the current underlying system. - */ - public final static String LINE_SEPARATOR = System - .getProperty("line.separator"); //$NON-NLS-1$ - /** - * - */ - private static final int MAXIMUM_STRING_LENGTH_ALLOWED = 32766; - - /** - * This method checks given string will not exceed limit in bytes[] when - * converted UTF-16LE encoding (2 bytes per character) and checks whether - * the length doesn't exceed 65535 bytes.
    - * - * @param value The string to check. - * @throws IllegalArgumentException If byte representation takes more than 65535 bytes. - */ - public static void checkStringLengthNullSafe(String value) - throws IllegalArgumentException { - if (value != null) { - if (value.length() > MAXIMUM_STRING_LENGTH_ALLOWED) { - throw new IllegalArgumentException( - ErrorMessage.WMA_LENGTH_OF_STRING_IS_TOO_LARGE - .getMsg((value.length() * 2))); - } - } - } - - /** - * @param value String to check for null - * @return true unless string is too long - */ - public static boolean isStringLengthValidNullSafe(String value) { - if (value != null) { - if (value.length() > MAXIMUM_STRING_LENGTH_ALLOWED) { - return false; - } - } - return true; - } - - /** - * effectively copies a specified amount of bytes from one stream to - * another. - * - * @param source stream to read from - * @param dest stream to write to - * @param amount amount of bytes to copy - * @throws IOException on I/O errors, and if the source stream depletes before all - * bytes have been copied. - */ - public static void copy(InputStream source, OutputStream dest, long amount) - throws IOException { - byte[] buf = new byte[8192]; - long copied = 0; - while (copied < amount) { - int toRead = 8192; - if ((amount - copied) < 8192) { - toRead = (int) (amount - copied); - } - int read = source.read(buf, 0, toRead); - if (read == -1) { - throw new IOException( - "Inputstream has to continue for another " - + (amount - copied) + " bytes."); - } - dest.write(buf, 0, read); - copied += read; - } - } - - /** - * Copies all of the source to the destination.
    - * - * @param source source to read from - * @param dest stream to write to - * @throws IOException on I/O errors. - */ - public static void flush(final InputStream source, final OutputStream dest) - throws IOException { - final byte[] buf = new byte[8192]; - int read; - while ((read = source.read(buf)) != -1) { - dest.write(buf, 0, read); - } - } - - /** - * This method will create a byte[] at the size of byteCount - * and insert the bytes of value (starting from lowset byte) - * into it.
    - * You can easily create a Word (16-bit), DWORD (32-bit), QWORD (64 bit) out - * of the value, ignoring the original type of value, since java - * automatically performs transformations.
    - * Warning: This method works with unsigned numbers only. - * - * @param value The value to be written into the result. - * @param byteCount The number of bytes the array has got. - * @return A byte[] with the size of byteCount containing the - * lower byte values of value. - */ - public static byte[] getBytes(final long value, final int byteCount) { - byte[] result = new byte[byteCount]; - for (int i = 0; i < result.length; i++) { - result[i] = (byte) ((value >>> (i * 8)) & 0xFF); - } - return result; - } - - /** - * Convenience method to convert the given string into a byte sequence which - * has the format of the charset given. - * - * @param source string to convert. - * @param charset charset to apply - * @return the source's binary representation according to the charset. - */ - public static byte[] getBytes(final String source, final Charset charset) { - assert charset != null; - assert source != null; - final ByteBuffer encoded = charset.encode(source); - final byte[] result = new byte[encoded.limit()]; - encoded.rewind(); - encoded.get(result); - return result; - } - - /** - * Since date values in ASF files are given in 100 ns steps since first - * january of 1601 a little conversion must be done.
    - * This method converts a date given in described manner to a calendar. - * - * @param fileTime - * Time in 100ns since 1 jan 1601 - * @return Calendar holding the date representation. - */ - /* Old method that ran very slowely and doesnt logical correct, how does dividing something - at 10-4 by 10,000 convert it to 10 -3 - public static GregorianCalendar getDateOf(final BigInteger fileTime) { - final GregorianCalendar result = new GregorianCalendar(1601, 0, 1); - // lose anything beyond milliseconds, because calendar can't handle - // less value - BigInteger time = fileTime.divide(new BigInteger("10000")); //$NON-NLS-1$ - final BigInteger maxInt = new BigInteger(String - .valueOf(Integer.MAX_VALUE)); - while (time.compareTo(maxInt) > 0) { - result.add(Calendar.MILLISECOND, Integer.MAX_VALUE); - time = time.subtract(maxInt); - } - result.add(Calendar.MILLISECOND, time.intValue()); - return result; - } - */ - - /** - * Date values in ASF files are given in 100 ns (10 exp -4) steps since first - * - * @param fileTime Time in 100ns since 1 jan 1601 - * @return Calendar holding the date representation. - */ - public static GregorianCalendar getDateOf(final BigInteger fileTime) { - final GregorianCalendar result = new GregorianCalendar(); - - // Divide by 10 to convert from -4 to -3 (millisecs) - BigInteger time = fileTime.divide(new BigInteger("10")); - // Construct Date taking into the diff between 1601 and 1970 - Date date = new Date(time.longValue() - DIFF_BETWEEN_ASF_DATE_AND_JAVA_DATE); - result.setTime(date); - return result; - } - - /** - * Tests if the given string is null or just contains - * whitespace characters. - * - * @param toTest String to test. - * @return see description. - */ - public static boolean isBlank(String toTest) { - if (toTest == null) { - return true; - } - - for (int i = 0; i < toTest.length(); i++) { - if (!Character.isWhitespace(toTest.charAt(i))) { - return false; - } - } - return true; - } - - /** - * Reads 8 bytes from stream and interprets them as a UINT64 which is - * returned as {@link BigInteger}.
    - * - * @param stream stream to readm from. - * @return a BigInteger which represents the read 8 bytes value. - * @throws IOException if problem reading bytes - */ - public static BigInteger readBig64(InputStream stream) throws IOException { - byte[] bytes = new byte[8]; - byte[] oa = new byte[8]; - int read = stream.read(bytes); - if (read != 8) { - // 8 bytes mandatory. - throw new EOFException(); - } - for (int i = 0; i < bytes.length; i++) { - oa[7 - i] = bytes[i]; - } - return new BigInteger(oa); - } - - /** - * Reads size bytes from the stream.
    - * - * @param stream stream to read from. - * @param size amount of bytes to read. - * @return the read bytes. - * @throws IOException on I/O errors. - */ - public static byte[] readBinary(InputStream stream, long size) - throws IOException { - byte[] result = new byte[(int) size]; - stream.read(result); - return result; - } - - /** - * This method reads a UTF-16 String, which length is given on the number of - * characters it consists of.
    - * The stream must be at the number of characters. This number contains the - * terminating zero character (UINT16). - * - * @param stream Input source - * @return String - * @throws IOException read errors - */ - public static String readCharacterSizedString(InputStream stream) - throws IOException { - StringBuilder result = new StringBuilder(); - int strLen = readUINT16(stream); - int character = stream.read(); - character |= stream.read() << 8; - do { - if (character != 0) { - result.append((char) character); - character = stream.read(); - character |= stream.read() << 8; - } - } while (character != 0 || (result.length() + 1) > strLen); - if (strLen != (result.length() + 1)) { - throw new IllegalStateException( - "Invalid Data for current interpretation"); //$NON-NLS-1$ - } - return result.toString(); - } - - /** - * This method reads a UTF-16 encoded String.
    - * For the use this method the number of bytes used by current string must - * be known.
    - * The ASF specification recommends that those strings end with a - * terminating zero. However it also says that it is not always the case. - * - * @param stream Input source - * @param strLen Number of bytes the String may take. - * @return read String. - * @throws IOException read errors. - */ - public static String readFixedSizeUTF16Str(InputStream stream, int strLen) - throws IOException { - byte[] strBytes = new byte[strLen]; - int read = stream.read(strBytes); - if (read == strBytes.length) { - if (strBytes.length >= 2) { - /* - * Zero termination is recommended but optional. So check and - * if, remove. - */ - if (strBytes[strBytes.length - 1] == 0 - && strBytes[strBytes.length - 2] == 0) { - byte[] copy = new byte[strBytes.length - 2]; - System.arraycopy(strBytes, 0, copy, 0, strBytes.length - 2); - strBytes = copy; - } - } - return new String(strBytes, "UTF-16LE"); - } - throw new IllegalStateException( - "Couldn't read the necessary amount of bytes."); - } - - /** - * This Method reads a GUID (which is a 16 byte long sequence) from the - * given raf and creates a wrapper.
    - * Warning :
    - * There is no way of telling if a byte sequence is a guid or not. The next - * 16 bytes will be interpreted as a guid, whether it is or not. - * - * @param stream Input source. - * @return A class wrapping the guid. - * @throws IOException happens when the file ends before guid could be extracted. - */ - public static GUID readGUID(InputStream stream) throws IOException { - if (stream == null) { - throw new IllegalArgumentException("Argument must not be null"); //$NON-NLS-1$ - } - int[] binaryGuid = new int[GUID.GUID_LENGTH]; - for (int i = 0; i < binaryGuid.length; i++) { - binaryGuid[i] = stream.read(); - } - return new GUID(binaryGuid); - } - - /** - * Reads 2 bytes from stream and interprets them as UINT16.
    - * - * @param stream stream to read from. - * @return UINT16 value - * @throws IOException on I/O Errors. - */ - public static int readUINT16(InputStream stream) throws IOException { - int result = stream.read(); - result |= stream.read() << 8; - return result; - } - - /** - * Reads 4 bytes from stream and interprets them as UINT32.
    - * - * @param stream stream to read from. - * @return UINT32 value - * @throws IOException on I/O Errors. - */ - public static long readUINT32(InputStream stream) throws IOException { - long result = 0; - for (int i = 0; i <= 24; i += 8) { - // Warning, always cast to long here. Otherwise it will be - // shifted as int, which may produce a negative value, which will - // then be extended to long and assign the long variable a negative - // value. - result |= (long) stream.read() << i; - } - return result; - } - - /** - * Reads long as little endian. - * - * @param stream Data source - * @return long value - * @throws IOException read error, or eof is reached before long is completed - */ - public static long readUINT64(InputStream stream) throws IOException { - long result = 0; - for (int i = 0; i <= 56; i += 8) { - // Warning, always cast to long here. Otherwise it will be - // shifted as int, which may produce a negative value, which will - // then be extended to long and assign the long variable a negative - // value. - result |= (long) stream.read() << i; - } - return result; - } - - /** - * This method reads a UTF-16 encoded String, beginning with a 16-bit value - * representing the number of bytes needed. The String is terminated with as - * 16-bit ZERO.
    - * - * @param stream Input source - * @return read String. - * @throws IOException read errors. - */ - public static String readUTF16LEStr(InputStream stream) throws IOException { - int strLen = readUINT16(stream); - byte[] buf = new byte[strLen]; - int read = stream.read(buf); - if (read == strLen || (strLen == 0 && read == -1)) { - /* - * Check on zero termination - */ - if (buf.length >= 2) { - if (buf[buf.length - 1] == 0 && buf[buf.length - 2] == 0) { - byte[] copy = new byte[buf.length - 2]; - System.arraycopy(buf, 0, copy, 0, buf.length - 2); - buf = copy; - } - } - return new String(buf, AsfHeader.ASF_CHARSET.name()); - } - throw new IllegalStateException( - "Invalid Data for current interpretation"); //$NON-NLS-1$ - } - - /** - * Writes the given value as UINT16 into the stream. - * - * @param number value to write. - * @param out stream to write into. - * @throws IOException On I/O errors - */ - public static void writeUINT16(int number, OutputStream out) - throws IOException { - if (number < 0) { - throw new IllegalArgumentException("positive value expected."); //$NON-NLS-1$ - } - byte[] toWrite = new byte[2]; - for (int i = 0; i <= 8; i += 8) { - toWrite[i / 8] = (byte) ((number >> i) & 0xFF); - } - out.write(toWrite); - } - - /** - * Writes the given value as UINT32 into the stream. - * - * @param number value to write. - * @param out stream to write into. - * @throws IOException On I/O errors - */ - public static void writeUINT32(long number, OutputStream out) - throws IOException { - if (number < 0) { - throw new IllegalArgumentException("positive value expected."); //$NON-NLS-1$ - } - byte[] toWrite = new byte[4]; - for (int i = 0; i <= 24; i += 8) { - toWrite[i / 8] = (byte) ((number >> i) & 0xFF); - } - out.write(toWrite); - } - - /** - * Writes the given value as UINT64 into the stream. - * - * @param number value to write. - * @param out stream to write into. - * @throws IOException On I/O errors - */ - public static void writeUINT64(long number, OutputStream out) - throws IOException { - if (number < 0) { - throw new IllegalArgumentException("positive value expected."); //$NON-NLS-1$ - } - byte[] toWrite = new byte[8]; - for (int i = 0; i <= 56; i += 8) { - toWrite[i / 8] = (byte) ((number >> i) & 0xFF); - } - out.write(toWrite); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/asf/util/package.html b/src/main/java/org/jaudiotagger/audio/asf/util/package.html deleted file mode 100644 index 3c19872..0000000 --- a/src/main/java/org/jaudiotagger/audio/asf/util/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Utility classes for data components of the Microsoft Advanced Systems Format header. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/CannotReadException.java b/src/main/java/org/jaudiotagger/audio/exceptions/CannotReadException.java deleted file mode 100644 index 0571c22..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/CannotReadException.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.exceptions; - -/** - * This exception is thrown if an audio file cannot be read.
    - * Causes may be invalid data or IO errors. - * - * @author Raphaël Slinckx - */ -public class CannotReadException extends Exception { - /** - * Creates an instance. - */ - public CannotReadException() { - super(); - } - - public CannotReadException(Throwable ex) { - super(ex); - } - - /** - * Creates an instance. - * - * @param message The message. - */ - public CannotReadException(String message) { - super(message); - } - - /** - * Creates an instance. - * - * @param message The error message. - * @param cause The throwable causing this exception. - */ - public CannotReadException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/CannotReadVideoException.java b/src/main/java/org/jaudiotagger/audio/exceptions/CannotReadVideoException.java deleted file mode 100644 index 3fb4422..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/CannotReadVideoException.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.jaudiotagger.audio.exceptions; - -/** - * This exception should be thrown idf it appears the file is a video file, jaudiotagger only supports audio - * files. - */ -public class CannotReadVideoException extends CannotReadException { - /** - * Creates an instance. - */ - public CannotReadVideoException() { - super(); - } - - public CannotReadVideoException(Throwable ex) { - super(ex); - } - - /** - * Creates an instance. - * - * @param message The message. - */ - public CannotReadVideoException(String message) { - super(message); - } - - /** - * Creates an instance. - * - * @param message The error message. - * @param cause The throwable causing this exception. - */ - public CannotReadVideoException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/CannotWriteException.java b/src/main/java/org/jaudiotagger/audio/exceptions/CannotWriteException.java deleted file mode 100644 index 304d2e9..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/CannotWriteException.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.exceptions; - -/** - * This exception is thrown if the writing process of an audio file failed. - * - * @author Rapha�l Slinckx - */ -public class CannotWriteException extends Exception { - /** - * (overridden) - * - * @see Exception#Exception() - */ - public CannotWriteException() { - super(); - } - - /** - * (overridden) - * - * @param message - * @see Exception#Exception(java.lang.String) - */ - public CannotWriteException(String message) { - super(message); - } - - /** - * (overridden) - * - * @param message - * @param cause - * @see Exception#Exception(java.lang.String, java.lang.Throwable) - */ - public CannotWriteException(String message, Throwable cause) { - super(message, cause); - } - - /** - * (overridden) - * - * @param cause - * @see Exception#Exception(java.lang.Throwable) - */ - public CannotWriteException(Throwable cause) { - super(cause); - - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java b/src/main/java/org/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java deleted file mode 100644 index 218ae37..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: InvalidAudioFrameException.java 345 2007-08-07 16:14:03Z paultaylor $ - * Date :${DATE} - *

    - * Jaikoz Copyright Copyright (C) 2003 -2005 JThink Ltd - */ -package org.jaudiotagger.audio.exceptions; - -/** - * Thrown if portion of file thought to be an AudioFrame is found to not be. - */ -public class InvalidAudioFrameException extends Exception { - public InvalidAudioFrameException(String message) { - super(message); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java b/src/main/java/org/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java deleted file mode 100644 index 8d1bd94..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.jaudiotagger.audio.exceptions; - -/** - * Thrown if when trying to read box id the length doesn't make any sense - */ -public class InvalidBoxHeaderException extends RuntimeException { - public InvalidBoxHeaderException(String message) { - super(message); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/ModifyVetoException.java b/src/main/java/org/jaudiotagger/audio/exceptions/ModifyVetoException.java deleted file mode 100644 index 71c7cff..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/ModifyVetoException.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.exceptions; - - -/** - * This exception is thrown if a - * {@link org.jaudiotagger.audio.generic.AudioFileModificationListener} wants to - * prevent the "e;entagged audio library"e; from actually finishing its - * operation.
    - * This exception can be used in all methods but - * {@link org.jaudiotagger.audio.generic.AudioFileModificationListener#fileOperationFinished(java.io.File)}. - * - * @author Christian Laireiter - */ -public class ModifyVetoException extends Exception { - - /** - * (overridden) - */ - public ModifyVetoException() { - super(); - } - - /** - * (overridden) - * - * @param message - * @see Exception#Exception(java.lang.String) - */ - public ModifyVetoException(String message) { - super(message); - } - - /** - * (overridden) - * - * @param message - * @param cause - * @see Exception#Exception(java.lang.String, java.lang.Throwable) - */ - public ModifyVetoException(String message, Throwable cause) { - super(message, cause); - } - - /** - * (overridden) - * - * @param cause - * @see Exception#Exception(java.lang.Throwable) - */ - public ModifyVetoException(Throwable cause) { - super(cause); - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/NullBoxIdException.java b/src/main/java/org/jaudiotagger/audio/exceptions/NullBoxIdException.java deleted file mode 100644 index a9790e8..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/NullBoxIdException.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.jaudiotagger.audio.exceptions; - -/** - * Thrown if when trying to read box id just finds nulls - * Normally an error, but if occurs at end of file we allow it - */ -public class NullBoxIdException extends RuntimeException { - public NullBoxIdException(String message) { - super(message); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/ReadOnlyFileException.java b/src/main/java/org/jaudiotagger/audio/exceptions/ReadOnlyFileException.java deleted file mode 100644 index 89784c8..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/ReadOnlyFileException.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: ReadOnlyFileException.java 345 2007-08-07 16:14:03Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.audio.exceptions; - -/** - * This is the exception when try and access a read only file - */ -public class ReadOnlyFileException extends Exception { - /** - * Creates a new ReadOnlyException datatype. - */ - public ReadOnlyFileException() { - } - - public ReadOnlyFileException(Throwable ex) { - super(ex); - } - - /** - * Creates a new ReadOnlyException datatype. - * - * @param msg the detail message. - */ - public ReadOnlyFileException(String msg) { - super(msg); - } - - public ReadOnlyFileException(String msg, Throwable ex) { - super(msg, ex); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/UnableToCreateFileException.java b/src/main/java/org/jaudiotagger/audio/exceptions/UnableToCreateFileException.java deleted file mode 100644 index 907a311..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/UnableToCreateFileException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jaudiotagger.audio.exceptions; - -import java.io.IOException; - -/** - * Should be thrown when unable to create a file when it is expected it should be creatable. For example because - * you dont have permission to write to the folder that it is in. - */ -public class UnableToCreateFileException extends IOException { - public UnableToCreateFileException(String message) { - super(message); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/UnableToModifyFileException.java b/src/main/java/org/jaudiotagger/audio/exceptions/UnableToModifyFileException.java deleted file mode 100644 index 00cbb20..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/UnableToModifyFileException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jaudiotagger.audio.exceptions; - -import java.io.IOException; - -/** - * Should be thrown when unable to modify a file when it is expected it should bemodifiable. For example because - * you dont have permission to modify files in the folder that it is in. - */ -public class UnableToModifyFileException extends IOException { - public UnableToModifyFileException(String message) { - super(message); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/UnableToRenameFileException.java b/src/main/java/org/jaudiotagger/audio/exceptions/UnableToRenameFileException.java deleted file mode 100644 index 3197e80..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/UnableToRenameFileException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jaudiotagger.audio.exceptions; - -import java.io.IOException; - -/** - * Should be thrown when unable to rename a file when it is expected it should rename. For example could occur on Vista - * because you do not have Special Permission 'Delete' set to Denied. - */ -public class UnableToRenameFileException extends IOException { - public UnableToRenameFileException(String message) { - super(message); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/exceptions/package.html b/src/main/java/org/jaudiotagger/audio/exceptions/package.html deleted file mode 100644 index c43807d..0000000 --- a/src/main/java/org/jaudiotagger/audio/exceptions/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Exceptions defined for Jaudiotagger. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacAudioHeader.java b/src/main/java/org/jaudiotagger/audio/flac/FlacAudioHeader.java deleted file mode 100644 index 78ae674..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacAudioHeader.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.generic.GenericAudioHeader; - -public class FlacAudioHeader extends GenericAudioHeader { - private String md5; - - public String getMd5() { - return md5; - } - - public void setMd5(String md5) { - this.md5 = md5; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacFileReader.java b/src/main/java/org/jaudiotagger/audio/flac/FlacFileReader.java deleted file mode 100644 index a746975..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacFileReader.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Read encoding and tag info for Flac file (open source lossless encoding) - */ -public class FlacFileReader extends AudioFileReader { - - private FlacInfoReader ir = new FlacInfoReader(); - private FlacTagReader tr = new FlacTagReader(); - - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException { - return ir.read(raf); - } - - protected Tag getTag(RandomAccessFile raf) throws CannotReadException, IOException { - return tr.read(raf); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacFileWriter.java b/src/main/java/org/jaudiotagger/audio/flac/FlacFileWriter.java deleted file mode 100644 index 5bcb22d..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacFileWriter.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.generic.AudioFileWriter; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - - -/** - * Write/delete tag info for Flac file (opensource lossless encoding) - */ -public class FlacFileWriter extends AudioFileWriter { - - private FlacTagWriter tw = new FlacTagWriter(); - - protected void writeTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException { - tw.write(tag, raf, rafTemp); - } - - protected void deleteTag(RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotWriteException, IOException { - tw.delete(raf, tempRaf); - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacInfoReader.java b/src/main/java/org/jaudiotagger/audio/flac/FlacInfoReader.java deleted file mode 100644 index a05d19d..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacInfoReader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.flac.metadatablock.BlockType; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataStreamInfo; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Logger; - -/** - * Read info from Flac file - */ -public class FlacInfoReader { - private static final int NO_OF_BITS_IN_BYTE = 8; - private static final int KILOBYTES_TO_BYTES_MULTIPLIER = 1000; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac"); - - public FlacAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException { - FlacStreamReader flacStream = new FlacStreamReader(raf); - flacStream.findStream(); - - MetadataBlockDataStreamInfo mbdsi = null; - boolean isLastBlock = false; - - //Search for StreamInfo Block, but even after we found it we still have to continue through all - //the metadata blocks so that we can find the start of the audio frames which we need to calculate - //the bitrate - while (!isLastBlock) { - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf); - if (mbh.getBlockType() == BlockType.STREAMINFO) { - mbdsi = new MetadataBlockDataStreamInfo(mbh, raf); - if (!mbdsi.isValid()) { - throw new CannotReadException("FLAC StreamInfo not valid"); - } - } else { - raf.seek(raf.getFilePointer() + mbh.getDataLength()); - } - - isLastBlock = mbh.isLastBlock(); - mbh = null; //Free memory - } - - if (mbdsi == null) { - throw new CannotReadException("Unable to find Flac StreamInfo"); - } - - FlacAudioHeader info = new FlacAudioHeader(); - info.setLength(mbdsi.getSongLength()); - info.setPreciseLength(mbdsi.getPreciseLength()); - info.setChannelNumber(mbdsi.getChannelNumber()); - info.setSamplingRate(mbdsi.getSamplingRate()); - info.setBitsPerSample(mbdsi.getBitsPerSample()); - info.setEncodingType(mbdsi.getEncodingType()); - info.setExtraEncodingInfos(""); - info.setBitrate(computeBitrate(mbdsi.getPreciseLength(), raf.length() - raf.getFilePointer())); - info.setLossless(true); - info.setMd5(mbdsi.getMD5Signature()); - return info; - } - - private int computeBitrate(float length, long size) { - return (int) ((size / KILOBYTES_TO_BYTES_MULTIPLIER) * NO_OF_BITS_IN_BYTE / length); - } - - /** - * Count the number of metadatablocks, useful for debugging - * - * @param f - * @return - * @throws CannotReadException - * @throws IOException - */ - public int countMetaBlocks(File f) throws CannotReadException, IOException { - RandomAccessFile raf = new RandomAccessFile(f, "r"); - FlacStreamReader flacStream = new FlacStreamReader(raf); - flacStream.findStream(); - - - boolean isLastBlock = false; - - int count = 0; - while (!isLastBlock) { - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf); - logger.config("Found block:" + mbh.getBlockType()); - raf.seek(raf.getFilePointer() + mbh.getDataLength()); - isLastBlock = mbh.isLastBlock(); - mbh = null; //Free memory - count++; - } - raf.close(); - return count; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacStreamReader.java b/src/main/java/org/jaudiotagger/audio/flac/FlacStreamReader.java deleted file mode 100644 index fc26b46..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacStreamReader.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.id3.AbstractID3v2Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Logger; - -/** - * Flac Stream - *

    - * Reader files and identifies if this is in fact a flac stream - */ -public class FlacStreamReader { - public static final int FLAC_STREAM_IDENTIFIER_LENGTH = 4; - public static final String FLAC_STREAM_IDENTIFIER = "fLaC"; - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac"); - private RandomAccessFile raf; - private int startOfFlacInFile; - - /** - * Create instance for holding stream info - * - * @param raf - */ - public FlacStreamReader(RandomAccessFile raf) { - this.raf = raf; - - } - - /** - * Reads the stream block to ensure it is a flac file - * - * @throws IOException - * @throws CannotReadException - */ - public void findStream() throws IOException, CannotReadException { - //Begins tag parsing - if (raf.length() == 0) { - //Empty File - throw new CannotReadException("Error: File empty"); - } - raf.seek(0); - - //FLAC Stream at start - if (isFlacHeader()) { - startOfFlacInFile = 0; - return; - } - - //Ok maybe there is an ID3v24tag first - if (isId3v2Tag()) { - startOfFlacInFile = (int) (raf.getFilePointer() - FLAC_STREAM_IDENTIFIER_LENGTH); - return; - } - throw new CannotReadException(ErrorMessage.FLAC_NO_FLAC_HEADER_FOUND.getMsg()); - } - - private boolean isId3v2Tag() throws IOException { - raf.seek(0); - if (AbstractID3v2Tag.isId3Tag(raf)) { - logger.warning(ErrorMessage.FLAC_CONTAINS_ID3TAG.getMsg(raf.getFilePointer())); - //FLAC Stream immediately after end of id3 tag - if (isFlacHeader()) { - return true; - } - } - return false; - } - - private boolean isFlacHeader() throws IOException { - //FLAC Stream at start - byte[] b = new byte[FLAC_STREAM_IDENTIFIER_LENGTH]; - raf.read(b); - String flac = new String(b); - return flac.equals(FLAC_STREAM_IDENTIFIER); - } - - /** - * Usually flac header is at start of file, but unofficially and ID3 tag is allowed at the start of the file. - * - * @return the start of the Flac within file - */ - public int getStartOfFlacInFile() { - return startOfFlacInFile; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacTagCreator.java b/src/main/java/org/jaudiotagger/audio/flac/FlacTagCreator.java deleted file mode 100644 index 608ff37..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacTagCreator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.flac.metadatablock.BlockType; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPadding; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; -import org.jaudiotagger.audio.generic.AbstractTagCreator; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.flac.FlacTag; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentCreator; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.ListIterator; -import java.util.logging.Logger; - -/** - * Create the tag data ready for writing to flac file - */ -public class FlacTagCreator extends AbstractTagCreator { - public static final int DEFAULT_PADDING = 4000; - private static final VorbisCommentCreator creator = new VorbisCommentCreator(); - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac"); - - /** - * @param tag - * @param paddingSize extra padding to be added - * @return - * @throws UnsupportedEncodingException - */ - public ByteBuffer convert(Tag tag, int paddingSize) throws UnsupportedEncodingException { - logger.config("Convert flac tag:padding:" + paddingSize); - FlacTag flacTag = (FlacTag) tag; - - int tagLength = 0; - ByteBuffer vorbiscomment = null; - if (flacTag.getVorbisCommentTag() != null) { - vorbiscomment = creator.convert(flacTag.getVorbisCommentTag()); - tagLength = vorbiscomment.capacity() + MetadataBlockHeader.HEADER_LENGTH; - } - for (MetadataBlockDataPicture image : flacTag.getImages()) { - tagLength += image.getBytes().length + MetadataBlockHeader.HEADER_LENGTH; - } - - logger.config("Convert flac tag:taglength:" + tagLength); - ByteBuffer buf = ByteBuffer.allocate(tagLength + paddingSize); - - MetadataBlockHeader vorbisHeader; - //If there are other metadata blocks - if (flacTag.getVorbisCommentTag() != null) { - if ((paddingSize > 0) || (flacTag.getImages().size() > 0)) { - vorbisHeader = new MetadataBlockHeader(false, BlockType.VORBIS_COMMENT, vorbiscomment.capacity()); - } else { - vorbisHeader = new MetadataBlockHeader(true, BlockType.VORBIS_COMMENT, vorbiscomment.capacity()); - } - buf.put(vorbisHeader.getBytes()); - buf.put(vorbiscomment); - } - - //Images - ListIterator li = flacTag.getImages().listIterator(); - while (li.hasNext()) { - MetadataBlockDataPicture imageField = li.next(); - MetadataBlockHeader imageHeader; - - if (paddingSize > 0 || li.hasNext()) { - imageHeader = new MetadataBlockHeader(false, BlockType.PICTURE, imageField.getLength()); - } else { - imageHeader = new MetadataBlockHeader(true, BlockType.PICTURE, imageField.getLength()); - } - buf.put(imageHeader.getBytes()); - buf.put(imageField.getBytes()); - } - - //Padding - logger.config("Convert flac tag at" + buf.position()); - if (paddingSize > 0) { - int paddingDataSize = paddingSize - MetadataBlockHeader.HEADER_LENGTH; - MetadataBlockHeader paddingHeader = new MetadataBlockHeader(true, BlockType.PADDING, paddingDataSize); - MetadataBlockDataPadding padding = new MetadataBlockDataPadding(paddingDataSize); - buf.put(paddingHeader.getBytes()); - buf.put(padding.getBytes()); - } - buf.rewind(); - return buf; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacTagReader.java b/src/main/java/org/jaudiotagger/audio/flac/FlacTagReader.java deleted file mode 100644 index 234fe08..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacTagReader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; -import org.jaudiotagger.tag.InvalidFrameException; -import org.jaudiotagger.tag.flac.FlacTag; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentReader; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Read Flac Tag - */ -public class FlacTagReader { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac"); - - private VorbisCommentReader vorbisCommentReader = new VorbisCommentReader(); - - - public FlacTag read(RandomAccessFile raf) throws CannotReadException, IOException { - FlacStreamReader flacStream = new FlacStreamReader(raf); - flacStream.findStream(); - - //Hold the metadata - VorbisCommentTag tag = null; - List images = new ArrayList(); - - //Seems like we have a valid stream - boolean isLastBlock = false; - while (!isLastBlock) { - if (logger.isLoggable(Level.CONFIG)) { - logger.config("Looking for MetaBlockHeader at:" + raf.getFilePointer()); - } - - //Read the header - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf); - if (mbh == null) { - break; - } - - if (logger.isLoggable(Level.CONFIG)) { - logger.config("Reading MetadataBlockHeader:" + mbh.toString() + " ending at " + raf.getFilePointer()); - } - - //Is it one containing some sort of metadata, therefore interested in it? - switch (mbh.getBlockType()) { - //We got a vorbiscomment comment block, parse it - case VORBIS_COMMENT: - byte[] commentHeaderRawPacket = new byte[mbh.getDataLength()]; - raf.read(commentHeaderRawPacket); - tag = vorbisCommentReader.read(commentHeaderRawPacket, false); - break; - - case PICTURE: - try { - MetadataBlockDataPicture mbdp = new MetadataBlockDataPicture(mbh, raf); - images.add(mbdp); - } catch (IOException ioe) { - logger.warning("Unable to read picture metablock, ignoring:" + ioe.getMessage()); - } catch (InvalidFrameException ive) { - logger.warning("Unable to read picture metablock, ignoring" + ive.getMessage()); - } - - break; - - //This is not a metadata block we are interested in so we skip to next block - default: - if (logger.isLoggable(Level.CONFIG)) { - logger.config("Ignoring MetadataBlock:" + mbh.getBlockType()); - } - raf.seek(raf.getFilePointer() + mbh.getDataLength()); - break; - } - - isLastBlock = mbh.isLastBlock(); - mbh = null; - } - - //Note there may not be either a tag or any images, no problem this is valid however to make it easier we - //just initialize Flac with an empty VorbisTag - if (tag == null) { - tag = VorbisCommentTag.createNewTag(); - } - FlacTag flacTag = new FlacTag(tag, images); - return flacTag; - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/flac/FlacTagWriter.java b/src/main/java/org/jaudiotagger/audio/flac/FlacTagWriter.java deleted file mode 100644 index 3297352..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/FlacTagWriter.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.flac.metadatablock.*; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.flac.FlacTag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - - -/** - * Write Flac Tag - */ -public class FlacTagWriter { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac"); - - private FlacTagCreator tc = new FlacTagCreator(); - - /** - * Delete Tag from file - * - * @param raf - * @param tempRaf - * @throws IOException - * @throws CannotWriteException - */ - public void delete(RandomAccessFile raf, RandomAccessFile tempRaf) throws IOException, CannotWriteException { - //This will save the file without any Comment or PictureData blocks - FlacTag emptyTag = new FlacTag(null, new ArrayList()); - raf.seek(0); - tempRaf.seek(0); - write(emptyTag, raf, tempRaf); - } - - /** - * Write tag to file - * - * @param tag - * @param raf - * @param rafTemp - * @throws CannotWriteException - * @throws IOException - */ - public void write(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException { - logger.config("Writing tag"); - - MetadataBlockInfo blockInfo = new MetadataBlockInfo(); - - //Read existing data - FlacStreamReader flacStream = new FlacStreamReader(raf); - try { - flacStream.findStream(); - } catch (CannotReadException cre) { - throw new CannotWriteException(cre.getMessage()); - } - - boolean isLastBlock = false; - while (!isLastBlock) { - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf); - switch (mbh.getBlockType()) { - case STREAMINFO: { - blockInfo.streamInfoBlock = new MetadataBlock(mbh, new MetadataBlockDataStreamInfo(mbh, raf)); - break; - } - - case VORBIS_COMMENT: - case PADDING: - case PICTURE: { - //All these will be replaced by the new metadata so we just treat as padding in order - //to determine how much space is already allocated in the file - raf.seek(raf.getFilePointer() + mbh.getDataLength()); - MetadataBlockData mbd = new MetadataBlockDataPadding(mbh.getDataLength()); - blockInfo.metadataBlockPadding.add(new MetadataBlock(mbh, mbd)); - break; - } - case APPLICATION: { - MetadataBlockData mbd = new MetadataBlockDataApplication(mbh, raf); - blockInfo.metadataBlockApplication.add(new MetadataBlock(mbh, mbd)); - break; - } - case SEEKTABLE: { - MetadataBlockData mbd = new MetadataBlockDataSeekTable(mbh, raf); - blockInfo.metadataBlockSeekTable.add(new MetadataBlock(mbh, mbd)); - break; - } - case CUESHEET: { - MetadataBlockData mbd = new MetadataBlockDataCueSheet(mbh, raf); - blockInfo.metadataBlockCueSheet.add(new MetadataBlock(mbh, mbd)); - break; - } - default: { - //What are the consequences of doing this - raf.seek(raf.getFilePointer() + mbh.getDataLength()); - break; - } - } - isLastBlock = mbh.isLastBlock(); - } - - //Number of bytes in the existing file available before audio data - int availableRoom = computeAvailableRoom(blockInfo); - - //Minimum Size of the New tag data without padding - int newTagSize = tc.convert(tag).limit(); - - //Number of bytes required for new tagdata and other metadata blocks - int neededRoom = newTagSize + computeNeededRoom(blockInfo); - - //Go to start of Flac within file - raf.seek(flacStream.getStartOfFlacInFile()); - - logger.config("Writing tag available bytes:" + availableRoom + ":needed bytes:" + neededRoom); - - //There is enough room to fit the tag without moving the audio just need to - //adjust padding accordingly need to allow space for padding header if padding required - if ((availableRoom == neededRoom) || (availableRoom > neededRoom + MetadataBlockHeader.HEADER_LENGTH)) { - //Jump over Id3 (if exists) Flac and StreamInfoBlock - raf.seek(flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH); - - //Write StreamInfo, we always write this first even if wasn't first in original spec - raf.write(blockInfo.streamInfoBlock.getHeader().getBytesWithoutIsLastBlockFlag()); - raf.write(blockInfo.streamInfoBlock.getData().getBytes()); - - //Write Application Blocks - for (MetadataBlock aMetadataBlockApplication : blockInfo.metadataBlockApplication) { - raf.write(aMetadataBlockApplication.getHeader().getBytesWithoutIsLastBlockFlag()); - raf.write(aMetadataBlockApplication.getData().getBytes()); - } - - //Write Seek Table Blocks - for (MetadataBlock aMetadataBlockSeekTable : blockInfo.metadataBlockSeekTable) { - raf.write(aMetadataBlockSeekTable.getHeader().getBytesWithoutIsLastBlockFlag()); - raf.write(aMetadataBlockSeekTable.getData().getBytes()); - } - - //Write Cue sheet Blocks - for (MetadataBlock aMetadataBlockCueSheet : blockInfo.metadataBlockCueSheet) { - raf.write(aMetadataBlockCueSheet.getHeader().getBytesWithoutIsLastBlockFlag()); - raf.write(aMetadataBlockCueSheet.getData().getBytes()); - } - - //Write tag (and padding) - raf.getChannel().write(tc.convert(tag, availableRoom - neededRoom)); - } - //Need to move audio - else { - //Skip to start of Audio - - //If Flac tag contains ID3header or something before start of official Flac header copy it over - if (flacStream.getStartOfFlacInFile() > 0) { - raf.seek(0); - rafTemp.getChannel().transferFrom(raf.getChannel(), 0, flacStream.getStartOfFlacInFile()); - rafTemp.seek(flacStream.getStartOfFlacInFile()); - } - rafTemp.writeBytes(FlacStreamReader.FLAC_STREAM_IDENTIFIER); - rafTemp.writeByte(0); //To ensure never set Last-metadata-block flag even if was before - - int uptoStreamHeaderSize = flacStream.getStartOfFlacInFile() - + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH - + MetadataBlockHeader.BLOCK_TYPE_LENGTH; - rafTemp.seek(uptoStreamHeaderSize); - raf.seek(uptoStreamHeaderSize); - - rafTemp.getChannel().transferFrom( - raf.getChannel(), - uptoStreamHeaderSize, - MetadataBlockHeader.BLOCK_LENGTH + MetadataBlockDataStreamInfo.STREAM_INFO_DATA_LENGTH); - - int dataStartSize = flacStream.getStartOfFlacInFile() - + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH - + MetadataBlockHeader.HEADER_LENGTH - + MetadataBlockDataStreamInfo.STREAM_INFO_DATA_LENGTH; - rafTemp.seek(dataStartSize); - - //Write all the metadatablocks - for (MetadataBlock aMetadataBlockApplication : blockInfo.metadataBlockApplication) { - rafTemp.write(aMetadataBlockApplication.getHeader().getBytesWithoutIsLastBlockFlag()); - rafTemp.write(aMetadataBlockApplication.getData().getBytes()); - } - - for (MetadataBlock aMetadataBlockSeekTable : blockInfo.metadataBlockSeekTable) { - rafTemp.write(aMetadataBlockSeekTable.getHeader().getBytesWithoutIsLastBlockFlag()); - rafTemp.write(aMetadataBlockSeekTable.getData().getBytes()); - } - - for (MetadataBlock aMetadataBlockCueSheet : blockInfo.metadataBlockCueSheet) { - rafTemp.write(aMetadataBlockCueSheet.getHeader().getBytesWithoutIsLastBlockFlag()); - rafTemp.write(aMetadataBlockCueSheet.getData().getBytes()); - } - - //Write tag data use default padding - rafTemp.write(tc.convert(tag, FlacTagCreator.DEFAULT_PADDING).array()); - //Write audio to new file - raf.seek(dataStartSize + availableRoom); - - //Issue #385 - //Transfer 'size' bytes from raf at its current position to rafTemp at position but do it in batches - //to prevent OutOfMemory exceptions - long amountToBeWritten = raf.getChannel().size() - raf.getChannel().position(); - long written = 0; - long chunksize = TagOptionSingleton.getInstance().getWriteChunkSize(); - long count = amountToBeWritten / chunksize; - long mod = amountToBeWritten % chunksize; - for (int i = 0; i < count; i++) { - written += rafTemp.getChannel().transferFrom(raf.getChannel(), rafTemp.getChannel().position(), chunksize); - rafTemp.getChannel().position(rafTemp.getChannel().position() + chunksize); - } - written += rafTemp.getChannel().transferFrom(raf.getChannel(), rafTemp.getChannel().position(), mod); - if (written != amountToBeWritten) { - throw new CannotWriteException("Was meant to write " + amountToBeWritten + " bytes but only written " + written + " bytes"); - } - } - } - - /** - * @param blockInfo - * @return space currently available for writing all Flac metadatablocks except for StreamInfo which is fixed size - */ - private int computeAvailableRoom(MetadataBlockInfo blockInfo) { - int length = 0; - - for (MetadataBlock aMetadataBlockApplication : blockInfo.metadataBlockApplication) { - length += aMetadataBlockApplication.getLength(); - } - - for (MetadataBlock aMetadataBlockSeekTable : blockInfo.metadataBlockSeekTable) { - length += aMetadataBlockSeekTable.getLength(); - } - - for (MetadataBlock aMetadataBlockCueSheet : blockInfo.metadataBlockCueSheet) { - length += aMetadataBlockCueSheet.getLength(); - } - - for (MetadataBlock aMetadataBlockPadding : blockInfo.metadataBlockPadding) { - length += aMetadataBlockPadding.getLength(); - } - - return length; - } - - /** - * @param blockInfo - * @return space required to write the metadata blocks that are part of Flac but are not part of tagdata - * in the normal sense. - */ - private int computeNeededRoom(MetadataBlockInfo blockInfo) { - int length = 0; - - for (MetadataBlock aMetadataBlockApplication : blockInfo.metadataBlockApplication) { - length += aMetadataBlockApplication.getLength(); - } - - for (MetadataBlock aMetadataBlockSeekTable : blockInfo.metadataBlockSeekTable) { - length += aMetadataBlockSeekTable.getLength(); - } - - for (MetadataBlock aMetadataBlockCueSheet : blockInfo.metadataBlockCueSheet) { - length += aMetadataBlockCueSheet.getLength(); - } - - return length; - } - - private static class MetadataBlockInfo { - private MetadataBlock streamInfoBlock; - private List metadataBlockPadding = new ArrayList(1); - private List metadataBlockApplication = new ArrayList(1); - private List metadataBlockSeekTable = new ArrayList(1); - private List metadataBlockCueSheet = new ArrayList(1); - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/BlockType.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/BlockType.java deleted file mode 100644 index abb6b90..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/BlockType.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.jaudiotagger.audio.flac.metadatablock; - -/** - * The different types of metadata block - *

    - * 7 - 126 are reserved for future use - * 127 is invalid - * User: Paul Taylor - * Date: 21-Nov-2007 - */ -public enum BlockType { - STREAMINFO(0), - PADDING(1), - APPLICATION(2), - SEEKTABLE(3), - VORBIS_COMMENT(4), - CUESHEET(5), - PICTURE(6); - - private int id; - - BlockType(int id) { - this.id = id; - } - - public int getId() { - return id; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java deleted file mode 100644 index ff286d4..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -/** - * Metadata Block - *

    - *

    A FLAC bitstream consists of the "fLaC" marker at the beginning of the stream, - * followed by a mandatory metadata block (called the STREAMINFO block), any number of other metadata blocks, - * then the audio frames. - */ -public class MetadataBlock { - private MetadataBlockHeader mbh; - private MetadataBlockData mbd; - - public MetadataBlock(MetadataBlockHeader mbh, MetadataBlockData mbd) { - this.mbh = mbh; - this.mbd = mbd; - } - - public MetadataBlockHeader getHeader() { - return mbh; - } - - public MetadataBlockData getData() { - return mbd; - } - - public int getLength() { - return MetadataBlockHeader.HEADER_LENGTH + mbh.getDataLength(); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java deleted file mode 100644 index bd2fb6a..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -/** - * This defines the interface required of the different metadata block types - */ -public interface MetadataBlockData { - /** - * @return the rawdata as it will be written to file - */ - byte[] getBytes(); - - /** - * @return the length in bytes that the data uses when written to file - */ - int getLength(); -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java deleted file mode 100644 index 1750246..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.io.RandomAccessFile; - - -/** - * Application Block - *

    - *

    This block is for use by third-party applications. The only mandatory field is a 32-bit identifier. - * This ID is granted upon request to an application by the FLAC maintainers. The remainder is of the block is defined - * by the registered application. - */ -public class MetadataBlockDataApplication implements MetadataBlockData { - - private byte[] data; - - public MetadataBlockDataApplication(MetadataBlockHeader header, RandomAccessFile raf) throws IOException { - data = new byte[header.getDataLength()]; - raf.readFully(data); - } - - public byte[] getBytes() { - return data; - } - - public int getLength() { - return data.length; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java deleted file mode 100644 index 1910b1e..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Cuesheet Block - *

    - *

    This block is for storing various information that can be used in a cue sheet. It supports track and index points, - * compatible with Red Book CD digital audio discs, as well as other CD-DA metadata such as media catalog number and - * track ISRCs. The CUESHEET block is especially useful for backing up CD-DA discs, but it can be used as a general - * purpose cueing mechanism for playback - */ -public class MetadataBlockDataCueSheet implements MetadataBlockData { - private byte[] data; - - public MetadataBlockDataCueSheet(MetadataBlockHeader header, RandomAccessFile raf) throws IOException { - data = new byte[header.getDataLength()]; - raf.readFully(data); - } - - public byte[] getBytes() { - return data; - } - - public int getLength() { - return data.length; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.java deleted file mode 100644 index 9f2c5a0..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -/** - * Padding Block - *

    - *

    This block allows for an arbitrary amount of padding. The contents of a PADDING block have no meaning. - * This block is useful when it is known that metadata will be edited after encoding; the user can instruct the encoder - * to reserve a PADDING block of sufficient size so that when metadata is added, it will simply overwrite the padding - * (which is relatively quick) instead of having to insert it into the right place in the existing file - * (which would normally require rewriting the entire file). - */ -public class MetadataBlockDataPadding implements MetadataBlockData { - private int length; - - public MetadataBlockDataPadding(int length) { - this.length = length; - } - - public byte[] getBytes() { - byte[] data = new byte[length]; - for (int i = 0; i < length; i++) { - data[i] = 0; - } - return data; - } - - public int getLength() { - return length; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java deleted file mode 100644 index 9d2eb60..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java +++ /dev/null @@ -1,328 +0,0 @@ -package org.jaudiotagger.audio.flac.metadatablock; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.FieldKey; -import org.jaudiotagger.tag.InvalidFrameException; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - - -/** - * Picture Block - *

    - *

    - *

    This block is for storing pictures associated with the file, most commonly cover art from CDs. - * There may be more than one PICTURE block in a file. The picture format is similar to the APIC frame in ID3v2. - * The PICTURE block has a type, MIME type, and UTF-8 description like ID3v2, and supports external linking via URL - * (though this is discouraged). The differences are that there is no uniqueness constraint on the description field, - * and the MIME type is mandatory. The FLAC PICTURE block also includes the resolution, color depth, and palette size - * so that the client can search for a suitable picture without having to scan them all - *

    - * Format: - * Info - * <32> The picture type according to the ID3v2 APIC frame: (There may only be one each of picture type 1 and 2 in a file) - * <32> The length of the MIME type string in bytes. - * The MIME type string, in printable ASCII characters 0x20-0x7e. The MIME type may also be --> to signify that the data part is a URL of the picture instead of the picture data itself. - * <32> The length of the description string in bytes. - * The description of the picture, in UTF-8. - * <32> The width of the picture in pixels. - * <32> The height of the picture in pixels. - * <32> The color depth of the picture in bits-per-pixel. - * <32> For indexed-color pictures (e.g. GIF), the number of colors used, or 0 for non-indexed pictures. - * <32> The length of the picture data in bytes. - * The binary picture data. - */ -public class MetadataBlockDataPicture implements MetadataBlockData, TagField { - public static final String IMAGE_IS_URL = "-->"; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac.MetadataBlockDataPicture"); - private int pictureType; - private String mimeType; - private String description; - private int width; - private int height; - private int colourDepth; - private int indexedColouredCount; - private byte[] imageData; - - /** - * Initialize MetaBlockDataPicture from byteBuffer - * - * @param rawdata - * @throws IOException - * @throws InvalidFrameException - */ - public MetadataBlockDataPicture(ByteBuffer rawdata) throws IOException, InvalidFrameException { - initFromByteBuffer(rawdata); - } - - /** - * Construct picture block by reading from file, the header informs us how many bytes we should be reading from - * - * @param header - * @param raf - * @throws java.io.IOException - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - //TODO check for buffer underflows see http://research.eeye.com/html/advisories/published/AD20071115.html - public MetadataBlockDataPicture(MetadataBlockHeader header, RandomAccessFile raf) throws IOException, InvalidFrameException { - ByteBuffer rawdata = ByteBuffer.allocate(header.getDataLength()); - int bytesRead = raf.getChannel().read(rawdata); - if (bytesRead < header.getDataLength()) { - throw new IOException("Unable to read required number of databytes read:" + bytesRead + ":required:" + header.getDataLength()); - } - rawdata.rewind(); - initFromByteBuffer(rawdata); - - - } - - /** - * Construct new MetadataPicture block - * - * @param imageData - * @param pictureType - * @param mimeType - * @param description - * @param width - * @param height - * @param colourDepth - * @param indexedColouredCount - */ - public MetadataBlockDataPicture(byte[] imageData, int pictureType, String mimeType, String description, int width, int height, int colourDepth, int indexedColouredCount) { - //Picture Type - this.pictureType = pictureType; - - //MimeType - this.mimeType = mimeType; - - //Description - this.description = description; - - this.width = width; - - this.height = height; - - this.colourDepth = colourDepth; - - this.indexedColouredCount = indexedColouredCount; - //ImageData - this.imageData = imageData; - } - - private void initFromByteBuffer(ByteBuffer rawdata) throws IOException, InvalidFrameException { - //Picture Type - pictureType = rawdata.getInt(); - if (pictureType >= PictureTypes.getInstanceOf().getSize()) { - throw new InvalidFrameException("PictureType was:" + pictureType + "but the maximum allowed is " + (PictureTypes.getInstanceOf().getSize() - 1)); - } - - //MimeType - int mimeTypeSize = rawdata.getInt(); - mimeType = getString(rawdata, mimeTypeSize, "ISO-8859-1"); - - //Description - int descriptionSize = rawdata.getInt(); - description = getString(rawdata, descriptionSize, "UTF-8"); - - //Image width - width = rawdata.getInt(); - - //Image height - height = rawdata.getInt(); - - //Colour Depth - colourDepth = rawdata.getInt(); - - //Indexed Colour Count - indexedColouredCount = rawdata.getInt(); - - //ImageData - int rawdataSize = rawdata.getInt(); - imageData = new byte[rawdataSize]; - rawdata.get(imageData); - - logger.config("Read image:" + this.toString()); - } - - private String getString(ByteBuffer rawdata, int length, String charset) throws IOException { - byte[] tempbuffer = new byte[length]; - rawdata.get(tempbuffer); - return new String(tempbuffer, charset); - } - - public byte[] getBytes() { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(Utils.getSizeBEInt32(pictureType)); - baos.write(Utils.getSizeBEInt32(mimeType.length())); - baos.write(mimeType.getBytes("ISO-8859-1")); - baos.write(Utils.getSizeBEInt32(description.length())); - baos.write(description.getBytes("UTF-8")); - baos.write(Utils.getSizeBEInt32(width)); - baos.write(Utils.getSizeBEInt32(height)); - baos.write(Utils.getSizeBEInt32(colourDepth)); - baos.write(Utils.getSizeBEInt32(indexedColouredCount)); - baos.write(Utils.getSizeBEInt32(imageData.length)); - baos.write(imageData); - return baos.toByteArray(); - - } catch (IOException ioe) { - throw new RuntimeException(ioe.getMessage()); - } - } - - public int getLength() { - return getBytes().length; - } - - public int getPictureType() { - return pictureType; - } - - public String getMimeType() { - return mimeType; - } - - public String getDescription() { - return description; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public int getColourDepth() { - return colourDepth; - } - - public int getIndexedColourCount() { - return indexedColouredCount; - } - - public byte[] getImageData() { - return imageData; - } - - /** - * @return true if imagedata is held as a url rather than actually being imagedata - */ - public boolean isImageUrl() { - return getMimeType().equals(IMAGE_IS_URL); - } - - /** - * @return the image url if there is otherwise return an empty String - */ - public String getImageUrl() { - if (isImageUrl()) { - return Utils.getString(getImageData(), 0, getImageData().length, TextEncoding.CHARSET_ISO_8859_1); - } else { - return ""; - } - } - - public String toString() { - return PictureTypes.getInstanceOf().getValueForId(pictureType) + ":" + mimeType + ":" + description + ":" + "width:" + width + ":height:" + height + ":colourdepth:" + colourDepth + ":indexedColourCount:" + indexedColouredCount + ":image size in bytes:" + imageData.length; - } - - /** - * This method copies the data of the given field to the current data.
    - * - * @param field The field containing the data to be taken. - */ - public void copyContent(TagField field) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the Id of the represented tag field.
    - * This value should uniquely identify a kind of tag data, like title. - * {@link org.jaudiotagger.audio.generic.AbstractTag} will use the "id" to summarize multiple - * fields. - * - * @return Unique identifier for the fields type. (title, artist...) - */ - public String getId() { - return FieldKey.COVER_ART.name(); - } - - /** - * This method delivers the binary representation of the fields data in - * order to be directly written to the file.
    - * - * @return Binary data representing the current tag field.
    - * @throws java.io.UnsupportedEncodingException Most tag data represents text. In some cases the underlying - * implementation will need to convert the text data in java to - * a specific charset encoding. In these cases an - * {@link java.io.UnsupportedEncodingException} may occur. - */ - public byte[] getRawContent() throws UnsupportedEncodingException { - return getBytes(); - } - - /** - * Determines whether the represented field contains (is made up of) binary - * data, instead of text data.
    - * Software can identify fields to be displayed because they are human - * readable if this method returns false. - * - * @return true if field represents binary data (not human - * readable). - */ - public boolean isBinary() { - return true; - } - - /** - * This method will set the field to represent binary data.
    - *

    - * Some implementations may support conversions.
    - * As of now (Octobre 2005) there is no implementation really using this - * method to perform useful operations. - * - * @param b true, if the field contains binary data. - * @deprecated As for now is of no use. Implementations should use another - * way of setting this property. - */ - public void isBinary(boolean b) { - //Do nothing, always true - } - - /** - * Identifies a field to be of common use.
    - *

    - * Some software may differ between common and not common fields. A common - * one is for sure the title field. A web link may not be of common use for - * tagging. However some file formats, or future development of users - * expectations will make more fields common than now can be known. - * - * @return true if the field is of common use. - */ - public boolean isCommon() { - return true; - } - - /** - * Determines whether the content of the field is empty.
    - * - * @return true if no data is stored (or empty String). - */ - public boolean isEmpty() { - return false; - } - - -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.java deleted file mode 100644 index a426388..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.io.RandomAccessFile; - - -/** - * SeekTable Block - *

    - *

    This is an optional block for storing seek points. It is possible to seek to any given sample in a FLAC stream - * without a seek table, but the delay can be unpredictable since the bitrate may vary widely within a stream. - * By adding seek points to a stream, this delay can be significantly reduced. Each seek point takes 18 bytes, so 1% - * resolution within a stream adds less than 2k. There can be only one SEEKTABLE in a stream, but the table can have - * any number of seek points. There is also a special 'placeholder' seekpoint which will be ignored by decoders but - * which can be used to reserve space for future seek point insertion. - */ -public class MetadataBlockDataSeekTable implements MetadataBlockData { - private byte[] data; - - public MetadataBlockDataSeekTable(MetadataBlockHeader header, RandomAccessFile raf) throws IOException { - data = new byte[header.getDataLength()]; - raf.readFully(data); - } - - public byte[] getBytes() { - return data; - } - - public int getLength() { - return data.length; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java deleted file mode 100644 index d32a65b..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Stream Info - *

    - *

    This block has information about the whole stream, like sample rate, number of channels, total number of samples, - * etc. It must be present as the first metadata block in the stream. Other metadata blocks may follow, and ones - * that the decoder doesn't understand, it will skip. - * Format: - * Info - * <16> The minimum block size (in samples) used in the stream. - * <16> The maximum block size (in samples) used in the stream. (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream. - * <24> The minimum frame size (in bytes) used in the stream. May be 0 to imply the value is not known. - * <24> The maximum frame size (in bytes) used in the stream. May be 0 to imply the value is not known. - * <20> Sample rate in Hz. Though 20 bits are available, the maximum sample rate is limited by the structure of frame headers to 655350Hz. Also, - * a value of 0 is invalid. - * <3> (number of channels)-1. FLAC supports from 1 to 8 channels - * <5> (bits per sample)-1. FLAC supports from 4 to 32 bits per sample. Currently the reference encoder and decoders only support up to 24 bits per sample. - * <36> Total samples in stream. 'Samples' means inter-channel sample, - * i.e. one second of 44.1Khz audio will have 44100 samples regardless of the number of channels. - * A value of zero here means the number of total samples is unknown. - * <128> MD5 signature of the unencoded audio data. This allows the decoder to determine if an error exists in the audio data - * even when the error does not result in an invalid bitstream. - * NOTES - * * FLAC specifies a minimum block size of 16 and a maximum block size of 65535, meaning the bit patterns corresponding to the numbers 0-15 in the minimum blocksize and maximum blocksize fields are invalid. - */ -public class MetadataBlockDataStreamInfo implements MetadataBlockData { - public static final int STREAM_INFO_DATA_LENGTH = 34; - - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac.MetadataBlockDataStreamInfo"); - - private int minBlockSize, maxBlockSize, minFrameSize, maxFrameSize, samplingRate, samplingRatePerChannel, bitsPerSample, channelNumber, totalNumberOfSamples; - private float songLength; - private String md5; - private boolean isValid = true; - - private ByteBuffer rawdata; - - public MetadataBlockDataStreamInfo(MetadataBlockHeader header, RandomAccessFile raf) throws IOException { - rawdata = ByteBuffer.allocate(header.getDataLength()); - int bytesRead = raf.getChannel().read(rawdata); - if (bytesRead < header.getDataLength()) { - throw new IOException("Unable to read required number of databytes read:" + bytesRead + ":required:" + header.getDataLength()); - } - rawdata.rewind(); - - minBlockSize = rawdata.getShort(); - maxBlockSize = rawdata.getShort(); - minFrameSize = readThreeByteInteger(rawdata.get(), rawdata.get(), rawdata.get()); - maxFrameSize = readThreeByteInteger(rawdata.get(), rawdata.get(), rawdata.get()); - - samplingRate = readSamplingRate(rawdata.get(), rawdata.get(), rawdata.get()); - channelNumber = ((u(rawdata.get(12)) & 0x0E) >>> 1) + 1; - samplingRatePerChannel = samplingRate / channelNumber; - bitsPerSample = ((u(rawdata.get(12)) & 0x01) << 4) + ((u(rawdata.get(13)) & 0xF0) >>> 4) + 1; - - totalNumberOfSamples = readTotalNumberOfSamples(rawdata.get(13), rawdata.get(14), rawdata.get(15), rawdata.get(16), rawdata.get(17)); - - StringBuilder sb = new StringBuilder(); - for (int i = 18; i < 34; i++) { - byte dataByte = rawdata.get(i); - sb.append(String.format("%x", dataByte)); - } - md5 = sb.toString(); - - songLength = (float) ((double) totalNumberOfSamples / samplingRate); - logger.config(this.toString()); - } - - /** - * @return the rawdata as it will be written to file - */ - public byte[] getBytes() { - return rawdata.array(); - } - - public int getLength() { - return getBytes().length; - } - - - public String toString() { - - return "MinBlockSize:" + minBlockSize + "MaxBlockSize:" + maxBlockSize + "MinFrameSize:" + minFrameSize + "MaxFrameSize:" + maxFrameSize + "SampleRateTotal:" + samplingRate + "SampleRatePerChannel:" + samplingRatePerChannel + ":Channel number:" + channelNumber + ":Bits per sample: " + bitsPerSample + ":TotalNumberOfSamples: " + totalNumberOfSamples + ":Length: " + songLength; - - } - - public int getSongLength() { - return (int) songLength; - } - - public float getPreciseLength() { - return songLength; - } - - public int getChannelNumber() { - return channelNumber; - } - - public int getSamplingRate() { - return samplingRate; - } - - public int getSamplingRatePerChannel() { - return samplingRatePerChannel; - } - - public String getEncodingType() { - return "FLAC " + bitsPerSample + " bits"; - } - - public int getBitsPerSample() { - return bitsPerSample; - } - - public String getMD5Signature() { - return md5; - } - - public boolean isValid() { - return isValid; - } - - private int readThreeByteInteger(byte b1, byte b2, byte b3) { - int rate = (u(b1) << 16) + (u(b2) << 8) + (u(b3)); - return rate; - } - - //TODO this code seems to be give a sampling rate over 21 bytes instead of 20 bytes but attempt to change - //to 21 bytes give wrong value - private int readSamplingRate(byte b1, byte b2, byte b3) { - int rate = (u(b1) << 12) + (u(b2) << 4) + ((u(b3) & 0xF0) >>> 4); - return rate; - - } - - private int readTotalNumberOfSamples(byte b1, byte b2, byte b3, byte b4, byte b5) { - int nb = u(b5); - nb += u(b4) << 8; - nb += u(b3) << 16; - nb += u(b2) << 24; - nb += (u(b1) & 0x0F) << 32; - return nb; - } - - private int u(int i) { - return i & 0xFF; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java deleted file mode 100644 index 560c02d..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - -/** - * Metadata Block Header - */ -public class MetadataBlockHeader { - public static final int BLOCK_TYPE_LENGTH = 1; - public static final int BLOCK_LENGTH = 3; - public static final int HEADER_LENGTH = BLOCK_TYPE_LENGTH + BLOCK_LENGTH; - - private boolean isLastBlock; - private int dataLength; - private byte[] bytes; - private BlockType blockType; - - /** - * Construct header by reading bytes - * - * @param rawdata - */ - public MetadataBlockHeader(ByteBuffer rawdata) { - isLastBlock = ((rawdata.get(0) & 0x80) >>> 7) == 1; - - int type = rawdata.get(0) & 0x7F; - if (type < BlockType.values().length) { - blockType = BlockType.values()[type]; - } - - - dataLength = (u(rawdata.get(1)) << 16) + (u(rawdata.get(2)) << 8) + (u(rawdata.get(3))); - - bytes = new byte[HEADER_LENGTH]; - for (int i = 0; i < HEADER_LENGTH; i++) { - bytes[i] = rawdata.get(i); - } - } - - /** - * Construct a new header in order to write metadatablock to file - * - * @param isLastBlock - * @param blockType - * @param dataLength - */ - public MetadataBlockHeader(boolean isLastBlock, BlockType blockType, int dataLength) { - ByteBuffer rawdata = ByteBuffer.allocate(HEADER_LENGTH); - this.blockType = blockType; - this.isLastBlock = isLastBlock; - this.dataLength = dataLength; - - byte type; - if (isLastBlock) { - type = (byte) (0x80 | blockType.getId()); - } else { - type = (byte) blockType.getId(); - } - rawdata.put(type); - - //Size is 3Byte BigEndian int - rawdata.put((byte) ((dataLength & 0xFF0000) >>> 16)); - rawdata.put((byte) ((dataLength & 0xFF00) >>> 8)); - rawdata.put((byte) (dataLength & 0xFF)); - - bytes = new byte[HEADER_LENGTH]; - for (int i = 0; i < HEADER_LENGTH; i++) { - bytes[i] = rawdata.get(i); - } - } - - /** - * Create header by reading from file - * - * @param raf - * @return - * @throws IOException - */ - public static MetadataBlockHeader readHeader(RandomAccessFile raf) throws IOException { - ByteBuffer rawdata = ByteBuffer.allocate(HEADER_LENGTH); - int bytesRead = raf.getChannel().read(rawdata); - if (bytesRead < HEADER_LENGTH) { - throw new IOException("Unable to read required number of databytes read:" + bytesRead + ":required:" + HEADER_LENGTH); - } - rawdata.rewind(); - return new MetadataBlockHeader(rawdata); - } - - public String toString() { - return "BlockType:" + blockType + " DataLength:" + dataLength + " isLastBlock:" + isLastBlock; - } - - private int u(int i) { - return i & 0xFF; - } - - public int getDataLength() { - return dataLength; - } - - public BlockType getBlockType() { - return blockType; - } - - public boolean isLastBlock() { - return isLastBlock; - } - - public byte[] getBytesWithoutIsLastBlockFlag() { - bytes[0] = (byte) (bytes[0] & 0x7F); - return bytes; - } - - public byte[] getBytes() { - return bytes; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/package.html b/src/main/java/org/jaudiotagger/audio/flac/metadatablock/package.html deleted file mode 100644 index de75c42..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/metadatablock/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for the FLAC metadata block. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/flac/package.html b/src/main/java/org/jaudiotagger/audio/flac/package.html deleted file mode 100644 index a71ad41..0000000 --- a/src/main/java/org/jaudiotagger/audio/flac/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for FLAC (Free Lossless Audio Codec) files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/generic/AbstractTag.java b/src/main/java/org/jaudiotagger/audio/generic/AbstractTag.java deleted file mode 100644 index 91499f4..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/AbstractTag.java +++ /dev/null @@ -1,408 +0,0 @@ -/* - * jaudiotagger library - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.images.Artwork; - -import java.util.*; - -/** - * This class is the default implementation for - * {@link org.jaudiotagger.tag.Tag} and introduces some more useful - * functionality to be implemented.
    - * - * @author Raphaël Slinckx - */ -public abstract class AbstractTag implements Tag { - /** - * Stores the amount of {@link TagField} with {@link TagField#isCommon()} - * true. - */ - protected int commonNumber = 0; - - /** - * This map stores the {@linkplain TagField#getId() ids} of the stored - * fields to the {@linkplain TagField fields} themselves. Because a linked hashMap is used the order - * that they are added in is preserved, the only exception to this rule is when two fields of the same id - * exist, both will be returned according to when the first item was added to the file.
    - */ - protected Map> fields = new LinkedHashMap>(); - - /** - * Add field - * - * @see org.jaudiotagger.tag.Tag#addField(org.jaudiotagger.tag.TagField) - *

    - * Changed so add empty fields - */ - public void addField(TagField field) { - if (field == null) { - return; - } - - List list = fields.get(field.getId()); - - // There was no previous item - if (list == null) { - list = new ArrayList(); - list.add(field); - fields.put(field.getId(), list); - if (field.isCommon()) { - commonNumber++; - } - } else { - // We append to existing list - list.add(field); - } - } - - - /** - * Get list of fields within this tag with the specified id - * - * @see org.jaudiotagger.tag.Tag#getFields(java.lang.String) - */ - public List getFields(String id) { - List list = fields.get(id); - - if (list == null) { - return new ArrayList(); - } - - return list; - } - - - public List getAll(String id) throws KeyNotFoundException { - List fields = new ArrayList(); - List tagFields = getFields(id); - for (TagField tagField : tagFields) { - fields.add(tagField.toString()); - } - return fields; - } - - /** - * @param id - * @param index - * @return - */ - public String getItem(String id, int index) { - List l = getFields(id); - return (l.size() > index) ? l.get(index).toString() : ""; - } - - /** - * Retrieve the first value that exists for this generic key - * - * @param genericKey - * @return - */ - public String getFirst(FieldKey genericKey) throws KeyNotFoundException { - return getValue(genericKey, 0); - } - - /** - * @param id - * @return - */ - public String getFirst(String id) { - List l = getFields(id); - return (l.size() != 0) ? l.get(0).toString() : ""; - } - - /** - * @param id audio specific key - * @return - */ - public TagField getFirstField(String id) { - List l = getFields(id); - return (l.size() != 0) ? l.get(0) : null; - } - - - /** - * @see org.jaudiotagger.tag.Tag#getFields() - */ - public Iterator getFields() { - final Iterator>> it = this.fields.entrySet().iterator(); - return new Iterator() { - private Iterator fieldsIt; - - private void changeIt() { - if (!it.hasNext()) { - return; - } - - Map.Entry> e = it.next(); - List l = e.getValue(); - fieldsIt = l.iterator(); - } - - public boolean hasNext() { - if (fieldsIt == null) { - changeIt(); - } - return it.hasNext() || (fieldsIt != null && fieldsIt.hasNext()); - } - - public TagField next() { - if (!fieldsIt.hasNext()) { - changeIt(); - } - - return fieldsIt.next(); - } - - public void remove() { - fieldsIt.remove(); - } - }; - } - - /** - * Return field count - *

    - * TODO:There must be a more efficient way to do this. - * - * @return field count - */ - public int getFieldCount() { - Iterator it = getFields(); - int count = 0; - while (it.hasNext()) { - count++; - it.next(); - } - return count; - } - - public int getFieldCountIncludingSubValues() { - return getFieldCount(); - } - - /** - * Does this tag contain any comon fields - * - * @see org.jaudiotagger.tag.Tag#hasCommonFields() - */ - public boolean hasCommonFields() { - return commonNumber != 0; - } - - /** - * Does this tag contain a field with the specified id - * - * @see org.jaudiotagger.tag.Tag#hasField(java.lang.String) - */ - public boolean hasField(String id) { - return getFields(id).size() != 0; - } - - public boolean hasField(FieldKey fieldKey) { - return hasField(fieldKey.name()); - } - - /** - * Determines whether the given charset encoding may be used for the - * represented tagging system. - * - * @param enc charset encoding. - * @return true if the given encoding can be used. - */ - protected abstract boolean isAllowedEncoding(String enc); - - /** - * Is this tag empty - * - * @see org.jaudiotagger.tag.Tag#isEmpty() - */ - public boolean isEmpty() { - return fields.size() == 0; - } - - /** - * Create new field and set it in the tag - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - - /** - * Create new field and add it to the tag - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - /** - * Set field - *

    - * Changed:Just because field is empty it doesn't mean it should be deleted. That should be the choice - * of the developer. (Or does this break things) - * - * @see org.jaudiotagger.tag.Tag#setField(org.jaudiotagger.tag.TagField) - */ - public void setField(TagField field) { - if (field == null) { - return; - } - - // If there is already an existing field with same id - // and both are TextFields, we replace the first element - List list = fields.get(field.getId()); - if (list != null) { - list.set(0, field); - return; - } - - // Else we put the new field in the fields. - list = new ArrayList(); - list.add(field); - fields.put(field.getId(), list); - if (field.isCommon()) { - commonNumber++; - } - } - - - /** - * Set or add encoding - * - * @see org.jaudiotagger.tag.Tag#setEncoding(java.lang.String) - */ - public boolean setEncoding(String enc) { - if (!isAllowedEncoding(enc)) { - return false; - } - - Iterator it = getFields(); - while (it.hasNext()) { - TagField field = (TagField) it.next(); - if (field instanceof TagTextField) { - ((TagTextField) field).setEncoding(enc); - } - } - - return true; - } - - /** - * (overridden) - * - * @see java.lang.Object#toString() - */ - public String toString() { - StringBuffer out = new StringBuffer(); - out.append("Tag content:\n"); - Iterator it = getFields(); - while (it.hasNext()) { - TagField field = (TagField) it.next(); - out.append("\t"); - out.append(field.getId()); - out.append(":"); - out.append(field.toString()); - out.append("\n"); - } - return out.toString().substring(0, out.length() - 1); - } - - /** - * @param genericKey - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public abstract TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException; - - /** - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public abstract TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException; - - /** - * @param fieldKey - * @throws KeyNotFoundException - */ - public abstract void deleteField(FieldKey fieldKey) throws KeyNotFoundException; - - - /** - * Delete all occurrences of field with this id. - * - * @param key - */ - public void deleteField(String key) { - fields.remove(key); - } - - public Artwork getFirstArtwork() { - List artwork = getArtworkList(); - if (artwork.size() > 0) { - return artwork.get(0); - } - return null; - } - - /** - * Create field and then set within tag itself - * - * @param artwork - * @throws FieldDataInvalidException - */ - public void setField(Artwork artwork) throws FieldDataInvalidException { - this.setField(createField(artwork)); - } - - /** - * Create field and then add within tag itself - * - * @param artwork - * @throws FieldDataInvalidException - */ - public void addField(Artwork artwork) throws FieldDataInvalidException { - this.addField(createField(artwork)); - } - - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException { - this.deleteField(FieldKey.COVER_ART); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/AbstractTagCreator.java b/src/main/java/org/jaudiotagger/audio/generic/AbstractTagCreator.java deleted file mode 100644 index 2703d96..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/AbstractTagCreator.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.tag.Tag; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Abstract class for creating the raw content that represents the tag so it can be written - * to file. - */ -public abstract class AbstractTagCreator { - /** - * Convert tagdata to rawdata ready for writing to file with no additional padding - * - * @param tag - * @return - * @throws UnsupportedEncodingException - */ - public ByteBuffer convert(Tag tag) throws UnsupportedEncodingException { - return convert(tag, 0); - } - - /** - * Convert tagdata to rawdata ready for writing to file - * - * @param tag - * @param padding TODO is this padding or additional padding - * @return - * @throws UnsupportedEncodingException - */ - public abstract ByteBuffer convert(Tag tag, int padding) throws UnsupportedEncodingException; -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/AudioFileModificationAdapter.java b/src/main/java/org/jaudiotagger/audio/generic/AudioFileModificationAdapter.java deleted file mode 100644 index f3a85ad..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/AudioFileModificationAdapter.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.ModifyVetoException; - -import java.io.File; - -/** - * Adapter for - * {@link org.jaudiotagger.audio.generic.AudioFileModificationListener}. - * - * @author Christian Laireiter - */ -public class AudioFileModificationAdapter implements AudioFileModificationListener { - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#fileModified(org.jaudiotagger.audio.AudioFile, - * File) - */ - public void fileModified(AudioFile original, File temporary) throws ModifyVetoException { - // Nothing to do - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#fileOperationFinished(File) - */ - public void fileOperationFinished(File result) { - // Nothing to do - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#fileWillBeModified(org.jaudiotagger.audio.AudioFile, - * boolean) - */ - public void fileWillBeModified(AudioFile file, boolean delete) throws ModifyVetoException { - // Nothing to do - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#vetoThrown(org.jaudiotagger.audio.generic.AudioFileModificationListener, - * org.jaudiotagger.audio.AudioFile, - * org.jaudiotagger.audio.exceptions.ModifyVetoException) - */ - public void vetoThrown(AudioFileModificationListener cause, AudioFile original, ModifyVetoException veto) { - // Nothing to do - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/AudioFileModificationListener.java b/src/main/java/org/jaudiotagger/audio/generic/AudioFileModificationListener.java deleted file mode 100644 index 783c4ec..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/AudioFileModificationListener.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.ModifyVetoException; - -import java.io.File; - -/** - * Classes implementing this interface will be notified on audio file's - * modifications.
    - *

    - *

    It will be notified on several occasions:
    - *

      - *
    • An audio file is about to be modified - * {@link #fileWillBeModified(AudioFile, boolean)}
      - * Here one can modify the tag data because of global settings.
    • - *
    • The write process has just finished. But if a copy was created the - * original has not been replaced yet. ({@link #fileModified(AudioFile, File)}).
    • - *
    • The operation has been finished. {@link #fileOperationFinished(File)}
    • - *
    - * - * @author Christian Laireiter - */ -public interface AudioFileModificationListener { - - /** - * Notifies that original has been processed.
    - * Because the audiolibrary allows format implementors to either change the - * original file or create a copy, it is possible that the real result is - * located in the original and temporary is of zero size - * or the original will be deleted and replaced by temporary.
    - * - * @param original The original file on which the operation was started. - * @param temporary The modified copy. (It may be of zero size if the original was - * modified) - * @throws ModifyVetoException If the Results doesn't fit the expectations of the listener, - * it can prevent the replacement of the original by temporary.
    - * If the original is already modified, this exception results - * in nothing. - */ - void fileModified(AudioFile original, File temporary) throws ModifyVetoException; - - /** - * Informs the listener that the process has been finished.
    - * The given file is either the original file or the modified copy.
    - * - * @param result The remaining file. It's not of {@link AudioFile} since it may - * be possible that a new file was created. In that case the - * audiolibs would need to parse the file again, which leads to - * long and unnecessary operation time, if the tag data is not - * needed any more. - */ - void fileOperationFinished(File result); - - /** - * Notifies that the file is about to be modified. - * - * @param file The file that will be modified. - * @param delete true if the deletion of tag data will be - * performed. - * @throws ModifyVetoException Thrown if the listener wants to prevent the process. - */ - void fileWillBeModified(AudioFile file, boolean delete) throws ModifyVetoException; - - /** - * This method notifies about a veto exception that has been thrown by - * another listener.
    - * - * @param cause The instance which caused the veto. - * @param original The original file, that was about to be modified. - * @param veto The thrown exception. - */ - void vetoThrown(AudioFileModificationListener cause, AudioFile original, ModifyVetoException veto); - -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/AudioFileReader.java b/src/main/java/org/jaudiotagger/audio/generic/AudioFileReader.java deleted file mode 100644 index b95e826..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/AudioFileReader.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagException; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Level; -import java.util.logging.Logger; - -/* - * This abstract class is the skeleton for tag readers. It handles the creation/closing of - * the randomaccessfile objects and then call the subclass method getEncodingInfo and getTag. - * These two method have to be implemented in the subclass. - * - *@author Raphael Slinckx - *@version $Id: AudioFileReader.java 976 2011-06-08 10:05:34Z paultaylor $ - *@since v0.02 - */ - -public abstract class AudioFileReader { - - private static final int MINIMUM_SIZE_FOR_VALID_AUDIO_FILE = 150; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.generic"); - - /* - * Returns the encoding info object associated wih the current File. - * The subclass can assume the RAF pointer is at the first byte of the file. - * The RandomAccessFile must be kept open after this function, but can point - * at any offset in the file. - * - * @param raf The RandomAccessFile associtaed with the current file - * @exception IOException is thrown when the RandomAccessFile operations throw it (you should never throw them manually) - * @exception CannotReadException when an error occured during the parsing of the encoding infos - */ - protected abstract GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException; - - /* - * Same as above but returns the Tag contained in the file, or a new one. - * - * @param raf The RandomAccessFile associted with the current file - * @exception IOException is thrown when the RandomAccessFile operations throw it (you should never throw them manually) - * @exception CannotReadException when an error occured during the parsing of the tag - */ - protected abstract Tag getTag(RandomAccessFile raf) throws CannotReadException, IOException; - - /* - * Reads the given file, and return an AudioFile object containing the Tag - * and the encoding infos present in the file. If the file has no tag, an - * empty one is returned. If the encodinginfo is not valid , an exception is thrown. - * - * @param f The file to read - * @exception CannotReadException If anything went bad during the read of this file - */ - public AudioFile read(File f) throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - if (logger.isLoggable(Level.CONFIG)) { - logger.config(ErrorMessage.GENERAL_READ.getMsg(f.getAbsolutePath())); - } - - if (!f.canRead()) { - throw new CannotReadException(ErrorMessage.GENERAL_READ_FAILED_FILE_TOO_SMALL.getMsg(f.getAbsolutePath())); - } - - if (f.length() <= MINIMUM_SIZE_FOR_VALID_AUDIO_FILE) { - throw new CannotReadException(ErrorMessage.GENERAL_READ_FAILED_FILE_TOO_SMALL.getMsg(f.getAbsolutePath())); - } - - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(f, "r"); - raf.seek(0); - - GenericAudioHeader info = getEncodingInfo(raf); - raf.seek(0); - Tag tag = getTag(raf); - return new AudioFile(f, info, tag); - - } catch (CannotReadException cre) { - throw cre; - } catch (Exception e) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_READ.getMsg(f.getAbsolutePath()), e); - throw new CannotReadException(f.getAbsolutePath() + ":" + e.getMessage(), e); - } finally { - try { - if (raf != null) { - raf.close(); - } - } catch (Exception ex) { - logger.log(Level.WARNING, ErrorMessage.GENERAL_READ_FAILED_UNABLE_TO_CLOSE_RANDOM_ACCESS_FILE.getMsg(f.getAbsolutePath())); - } - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/AudioFileWriter.java b/src/main/java/org/jaudiotagger/audio/generic/AudioFileWriter.java deleted file mode 100644 index 64f7c6a..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/AudioFileWriter.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.exceptions.ModifyVetoException; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.Tag; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This abstract class is the skeleton for tag writers. - *

    - *

    - * It handles the creation/closing of the randomaccessfile objects and then call - * the subclass method writeTag or deleteTag. These two method have to be - * implemented in the subclass. - * - * @author Raphael Slinckx - * @version $Id: AudioFileWriter.java,v 1.21 2009/05/05 15:59:14 paultaylor Exp - * $ - * @since v0.02 - */ -public abstract class AudioFileWriter { - private static final String TEMP_FILENAME_SUFFIX = ".tmp"; - private static final String WRITE_MODE = "rws"; - private static final int MINIMUM_FILESIZE = 150; - //If filename too long try recreating it with length no longer than 50 that should be safe on all operating - //systems - private static final String FILE_NAME_TOO_LONG = "File name too long"; - private static final String FILE_NAME_TOO_LONG2 = "The filename, directory name, or volume label syntax is incorrect"; - private static final int FILE_NAME_TOO_LONG_SAFE_LIMIT = 50; - // Logger Object - public static Logger logger = Logger - .getLogger("org.jaudiotagger.audio.generic"); - /** - * If not null, this listener is used to notify the listener - * about modification events.
    - */ - private AudioFileModificationListener modificationListener = null; - - /** - * Delete the tag (if any) present in the given file - * - * @param af The file to process - * @throws CannotWriteException if anything went wrong - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - */ - public void delete(AudioFile af) throws CannotReadException, CannotWriteException { - if (!af.getFile().canWrite()) { - throw new CannotWriteException(ErrorMessage.GENERAL_DELETE_FAILED - .getMsg(af.getFile().getPath())); - } - - if (af.getFile().length() <= MINIMUM_FILESIZE) { - throw new CannotWriteException(ErrorMessage.GENERAL_DELETE_FAILED - .getMsg(af.getFile().getPath())); - } - - RandomAccessFile raf = null; - RandomAccessFile rafTemp = null; - File tempF = null; - - // Will be set to true on VetoException, causing the finally block to - // discard the tempfile. - boolean revert = false; - - try { - - tempF = File.createTempFile(af.getFile().getName() - .replace('.', '_'), TEMP_FILENAME_SUFFIX, af.getFile() - .getParentFile()); - rafTemp = new RandomAccessFile(tempF, WRITE_MODE); - raf = new RandomAccessFile(af.getFile(), WRITE_MODE); - raf.seek(0); - rafTemp.seek(0); - - try { - if (this.modificationListener != null) { - this.modificationListener.fileWillBeModified(af, true); - } - deleteTag(raf, rafTemp); - if (this.modificationListener != null) { - this.modificationListener.fileModified(af, tempF); - } - } catch (ModifyVetoException veto) { - throw new CannotWriteException(veto); - } - - } catch (Exception e) { - revert = true; - throw new CannotWriteException("\"" + af.getFile().getAbsolutePath() + "\" :" + e, e); - } finally { - // will be set to the remaining file. - File result = af.getFile(); - try { - if (raf != null) { - raf.close(); - } - if (rafTemp != null) { - rafTemp.close(); - } - - if (tempF.length() > 0 && !revert) { - boolean deleteResult = af.getFile().delete(); - if (!deleteResult) { - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_ORIGINAL_FILE - .getMsg(af.getFile().getPath(), tempF - .getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_ORIGINAL_FILE - .getMsg(af.getFile().getPath(), tempF - .getPath())); - } - boolean renameResult = tempF.renameTo(af.getFile()); - if (!renameResult) { - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE - .getMsg(af.getFile().getPath(), tempF - .getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE - .getMsg(af.getFile().getPath(), tempF - .getPath())); - } - result = tempF; - - // If still exists we can now delete - if (tempF.exists()) { - if (!tempF.delete()) { - // Non critical failed deletion - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE - .getMsg(tempF.getPath())); - } - } - } else { - // It was created but never used - if (!tempF.delete()) { - // Non critical failed deletion - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE - .getMsg(tempF.getPath())); - } - } - } catch (Exception ex) { - logger.severe("AudioFileWriter exception cleaning up delete:" + af.getFile().getPath() + " or" + tempF.getAbsolutePath() + ":" + ex); - } - // Notify listener - if (this.modificationListener != null) { - this.modificationListener.fileOperationFinished(result); - } - } - } - - /** - * Delete the tag (if any) present in the given randomaccessfile, and do not - * close it at the end. - * - * @param raf The source file, already opened in r-write mode - * @param tempRaf The temporary file opened in r-write mode - * @throws CannotWriteException if anything went wrong - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - * @throws java.io.IOException - */ - public void delete(RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotReadException, CannotWriteException, IOException { - raf.seek(0); - tempRaf.seek(0); - deleteTag(raf, tempRaf); - } - - /** - * Same as above, but delete tag in the file. - * - * @param raf - * @param tempRaf - * @throws IOException is thrown when the RandomAccessFile operations throw it (you - * should never throw them manually) - * @throws CannotWriteException when an error occured during the deletion of the tag - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - */ - protected abstract void deleteTag(RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotReadException, CannotWriteException, IOException; - - /** - * This method sets the {@link AudioFileModificationListener}.
    - * There is only one listener allowed, if you want more instances to be - * supported, use the {@link ModificationHandler} to broadcast those events.
    - * - * @param listener The listener. null allowed to deregister. - */ - public void setAudioFileModificationListener(AudioFileModificationListener listener) { - this.modificationListener = listener; - } - - /** - * Prechecks before normal write - *

    - *

      - *
    • If the tag is actually empty, remove the tag
    • - *
    • if the file is not writable, throw exception - *
    • - *
    • If the file is too small to be a valid file, throw exception - *
    • - *
    - * - * @param af - * @throws CannotWriteException - */ - private void precheckWrite(AudioFile af) throws CannotWriteException { - // Preliminary checks - try { - if (af.getTag().isEmpty()) { - delete(af); - return; - } - } catch (CannotReadException re) { - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED - .getMsg(af.getFile().getPath())); - } - - if (!af.getFile().canWrite()) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(af.getFile() - .getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED - .getMsg(af.getFile().getPath())); - } - - if (af.getFile().length() <= MINIMUM_FILESIZE) { - logger - .severe(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL - .getMsg(af.getFile().getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL - .getMsg(af.getFile().getPath())); - } - } - - /** - * Write the tag (if not empty) present in the AudioFile in the associated - * File - * - * @param af The file we want to process - * @throws CannotWriteException if anything went wrong - */ - // TODO Creates temp file in same folder as the original file, this is safe - // but would impose a performance overhead if the original file is on a networked drive - public void write(AudioFile af) throws CannotWriteException { - logger.config("Started writing tag data for file:" + af.getFile().getName()); - - // Prechecks - precheckWrite(af); - - //mp3's use a different mechanism to the other formats - if (af instanceof MP3File) { - af.commit(); - return; - } - - RandomAccessFile raf = null; - RandomAccessFile rafTemp = null; - File newFile; - File result; - - // Create temporary File - try { - newFile = File.createTempFile(af.getFile().getName().replace('.', '_'), TEMP_FILENAME_SUFFIX, af.getFile().getParentFile()); - } - // Unable to create temporary file, can happen in Vista if have Create - // Files/Write Data set to Deny - catch (IOException ioe) { - if (ioe.getMessage().equals(FILE_NAME_TOO_LONG) && (af.getFile().getName().length() > FILE_NAME_TOO_LONG_SAFE_LIMIT)) { - try { - - newFile = File.createTempFile(af.getFile().getName().substring(0, FILE_NAME_TOO_LONG_SAFE_LIMIT).replace('.', '_'), TEMP_FILENAME_SUFFIX, af.getFile().getParentFile()); - - } catch (IOException ioe2) { - logger - .log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER - .getMsg(af.getFile().getName(), af - .getFile().getParentFile() - .getAbsolutePath()), ioe2); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER - .getMsg(af.getFile().getName(), af.getFile() - .getParentFile().getAbsolutePath())); - } - } else { - logger - .log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER - .getMsg(af.getFile().getName(), af - .getFile().getParentFile() - .getAbsolutePath()), ioe); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER - .getMsg(af.getFile().getName(), af.getFile() - .getParentFile().getAbsolutePath())); - } - } - - // Open temporary file and actual file for editing - try { - rafTemp = new RandomAccessFile(newFile, WRITE_MODE); - raf = new RandomAccessFile(af.getFile(), WRITE_MODE); - - } - // Unable to write to writable file, can happen in Vista if have Create - // Folders/Append Data set to Deny - catch (IOException ioe) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING - .getMsg(af.getFile().getAbsolutePath()), ioe); - - // If we managed to open either file, delete it. - try { - if (raf != null) { - raf.close(); - } - if (rafTemp != null) { - rafTemp.close(); - } - } catch (IOException ioe2) { - // Warn but assume has worked okay - logger.log(Level.WARNING, ErrorMessage.GENERAL_WRITE_PROBLEM_CLOSING_FILE_HANDLE - .getMsg(af.getFile(), ioe.getMessage()), ioe2); - } - - // Delete the temp file ( we cannot delete until closed corresponding - // rafTemp) - if (!newFile.delete()) { - // Non critical failed deletion - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE - .getMsg(newFile.getAbsolutePath())); - } - - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING - .getMsg(af.getFile().getAbsolutePath())); - } - - // Write data to File - try { - - raf.seek(0); - rafTemp.seek(0); - try { - if (this.modificationListener != null) { - this.modificationListener.fileWillBeModified(af, false); - } - writeTag(af.getTag(), raf, rafTemp); - if (this.modificationListener != null) { - this.modificationListener.fileModified(af, newFile); - } - } catch (ModifyVetoException veto) { - throw new CannotWriteException(veto); - } - } catch (Exception e) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE - .getMsg(af.getFile(), e.getMessage()), e); - - try { - if (raf != null) { - raf.close(); - } - if (rafTemp != null) { - rafTemp.close(); - } - } catch (IOException ioe) { - // Warn but assume has worked okay - logger.log(Level.WARNING, ErrorMessage.GENERAL_WRITE_PROBLEM_CLOSING_FILE_HANDLE - .getMsg(af.getFile().getAbsolutePath(), ioe - .getMessage()), ioe); - } - - // Delete the temporary file because either it was never used so - // lets just tidy up or we did start writing to it but - // the write failed and we havent renamed it back to the original - // file so we can just delete it. - if (!newFile.delete()) { - // Non critical failed deletion - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE - .getMsg(newFile.getAbsolutePath())); - } - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(af - .getFile(), e.getMessage())); - } finally { - try { - if (raf != null) { - raf.close(); - } - if (rafTemp != null) { - rafTemp.close(); - } - } catch (IOException ioe) { - // Warn but assume has worked okay - logger.log(Level.WARNING, ErrorMessage.GENERAL_WRITE_PROBLEM_CLOSING_FILE_HANDLE - .getMsg(af.getFile().getAbsolutePath(), ioe - .getMessage()), ioe); - } - } - - // Result held in this file - result = af.getFile(); - - // If the temporary file was used - if (newFile.length() > 0) { - - // Rename Original File - // Can fail on Vista if have Special Permission 'Delete' set Deny - File originalFileBackup = new File(af.getFile().getAbsoluteFile().getParentFile().getPath(), - AudioFile.getBaseFilename(af.getFile()) + ".old"); - - //If already exists modify the suffix - int count = 1; - while (originalFileBackup.exists()) { - originalFileBackup = new File(af.getFile().getAbsoluteFile().getParentFile().getPath(), AudioFile.getBaseFilename(af.getFile()) + ".old" + count); - count++; - } - - boolean renameResult = Utils.rename(af.getFile(), originalFileBackup); - if (!renameResult) { - logger - .log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP - .getMsg(af.getFile().getAbsolutePath(), originalFileBackup.getName())); - //Delete the temp file because write has failed - if (newFile != null) { - newFile.delete(); - } - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP - .getMsg(af.getFile().getPath(), originalFileBackup.getName())); - } - - // Rename Temp File to Original File - renameResult = Utils.rename(newFile, af.getFile()); - if (!renameResult) { - // Renamed failed so lets do some checks rename the backup back to the original file - // New File doesnt exist - if (!newFile.exists()) { - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_NEW_FILE_DOESNT_EXIST - .getMsg(newFile.getAbsolutePath())); - } - - // Rename the backup back to the original - if (!originalFileBackup.renameTo(af.getFile())) { - // TODO now if this happens we are left with testfile.old - // instead of testfile.mp4 - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_BACKUP_TO_ORIGINAL - .getMsg(originalFileBackup - .getAbsolutePath(), af.getFile() - .getName())); - } - - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE - .getMsg(af.getFile().getAbsolutePath(), newFile - .getName())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE - .getMsg(af.getFile().getAbsolutePath(), newFile - .getName())); - } else { - // Rename was okay so we can now delete the backup of the - // original - boolean deleteResult = originalFileBackup.delete(); - if (!deleteResult) { - // Not a disaster but can't delete the backup so make a - // warning - logger - .warning(ErrorMessage.GENERAL_WRITE_WARNING_UNABLE_TO_DELETE_BACKUP_FILE - .getMsg(originalFileBackup - .getAbsolutePath())); - } - } - - // Delete the temporary file if still exists - if (newFile.exists()) { - if (!newFile.delete()) { - // Non critical failed deletion - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE - .getMsg(newFile.getPath())); - } - } - } else { - // Delete the temporary file that wasn't ever used - if (!newFile.delete()) { - // Non critical failed deletion - logger - .warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE - .getMsg(newFile.getPath())); - } - } - - if (this.modificationListener != null) { - this.modificationListener.fileOperationFinished(result); - } - } - - /** - * This is called when a tag has to be written in a file. Three parameters - * are provided, the tag to write (not empty) Two randomaccessfiles, the - * first points to the file where we want to write the given tag, and the - * second is an empty temporary file that can be used if e.g. the file has - * to be bigger than the original. - *

    - * If something has been written in the temporary file, when this method - * returns, the original file is deleted, and the temporary file is renamed - * the the original name - *

    - * If nothing has been written to it, it is simply deleted. - *

    - * This method can assume the raf, rafTemp are pointing to the first byte of - * the file. The subclass must not close these two files when the method - * returns. - * - * @param tag - * @param raf - * @param rafTemp - * @throws IOException is thrown when the RandomAccessFile operations throw it (you - * should never throw them manually) - * @throws CannotWriteException when an error occured during the generation of the tag - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - */ - protected abstract void writeTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotReadException, CannotWriteException, IOException; -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/GenericAudioHeader.java b/src/main/java/org/jaudiotagger/audio/generic/GenericAudioHeader.java deleted file mode 100644 index 648ada0..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/GenericAudioHeader.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioHeader; - -import java.util.HashMap; -import java.util.Set; - -/** - * This class represents a structure for storing and retrieving information - * about the codec respectively the encoding parameters.
    - * Most of the parameters are available for nearly each audio format. Some - * others would result in standard values.
    - * Consider: None of the setter methods will actually affect the audio - * file. This is just a structure for retrieving information, not manipulating - * the audio file.
    - * - * @author Raphael Slinckx - */ -public class GenericAudioHeader implements AudioHeader { - - /** - * The key for the Bitrate.({@link Integer})
    - * - * @see #content - */ - public final static String FIELD_BITRATE = "BITRATE"; - - /** - * The key for the number of audio channels.({@link Integer})
    - * - * @see #content - */ - public final static String FIELD_CHANNEL = "CHANNB"; - - /** - * The key for the extra encoding information.({@link String})
    - * - * @see #content - */ - public final static String FIELD_INFOS = "INFOS"; - - /** - * The key for the audio clip duration in seconds. ({@link Float})
    - * - * @see #content - */ - public final static String FIELD_LENGTH = "LENGTH"; - - /** - * The key for the audio sample rate in "Hz". ({@link Integer})
    - * - * @see #content - */ - public final static String FIELD_SAMPLERATE = "SAMPLING"; - - /** - * The key for the audio bits per sample. ({@link Integer})
    - * - * @see #content - */ - public final static String FIELD_BITSPERSAMPLE = "BITSPERSAMPLE"; - - /** - * The key for the audio type.({@link String})
    - * - * @see #content - */ - public final static String FIELD_TYPE = "TYPE"; - - /** - * The key for the VBR flag. ({@link Boolean})
    - * - * @see #content - */ - public final static String FIELD_VBR = "VBR"; - /** - * This table containts the parameters.
    - */ - protected HashMap content; - /** - * Used for WMA files - */ - private boolean isLossless = false; - - /** - * Creates an instance with emtpy values.
    - */ - public GenericAudioHeader() { - content = new HashMap(6); - content.put(FIELD_BITRATE, -1); - content.put(FIELD_CHANNEL, -1); - content.put(FIELD_TYPE, ""); - content.put(FIELD_INFOS, ""); - content.put(FIELD_SAMPLERATE, -1); - content.put(FIELD_BITSPERSAMPLE, -1); - content.put(FIELD_LENGTH, (float) -1); - content.put(FIELD_VBR, true); - } - - public String getBitRate() { - return content.get(FIELD_BITRATE).toString(); - } - - - /** - * This method returns the bitrate of the represented audio clip in - * "Kbps".
    - * - * @return The bitrate in Kbps. - */ - public long getBitRateAsNumber() { - return ((Integer) content.get(FIELD_BITRATE)).longValue(); - } - - /** - * This method returns the number of audio channels the clip contains.
    - * (The stereo, mono thing). - * - * @return The number of channels. (2 for stereo, 1 for mono) - */ - public int getChannelNumber() { - return (Integer) content.get(FIELD_CHANNEL); - } - - /** - * Sets the number of channels. - * - * @param chanNb number of channels (2 for stereo, 1 for mono). - */ - public void setChannelNumber(int chanNb) { - content.put(FIELD_CHANNEL, chanNb); - } - - /** - * @return - */ - public String getChannels() { - return String.valueOf(getChannelNumber()); - } - - /** - * Returns the encoding type. - * - * @return The encoding type - */ - public String getEncodingType() { - return (String) content.get(FIELD_TYPE); - } - - /** - * Sets the type of the encoding.
    - * This is a bit format specific.
    - * eg:Layer I/II/III - * - * @param encodingType Encoding type. - */ - public void setEncodingType(String encodingType) { - content.put(FIELD_TYPE, encodingType); - } - - /** - * Returns the format, same as encoding type - * - * @return The encoding type - */ - public String getFormat() { - return (String) content.get(FIELD_TYPE); - } - - /** - * This method returns some extra information about the encoding.
    - * This may not contain anything for some audio formats.
    - * - * @return Some extra information. - */ - public String getExtraEncodingInfos() { - return (String) content.get(FIELD_INFOS); - } - - /** - * A string containing anything else that might be interesting - * - * @param infos Extra information. - */ - public void setExtraEncodingInfos(String infos) { - content.put(FIELD_INFOS, infos); - } - - /** - * This method returns the duration of the represented audio clip in - * seconds.
    - * - * @return The duration in seconds. - * @see #getPreciseLength() - */ - public int getTrackLength() { - return (int) getPreciseLength(); - } - - /** - * This method returns the duration of the represented audio clip in seconds - * (single-precision).
    - * - * @return The duration in seconds. - * @see #getTrackLength() - */ - public float getPreciseLength() { - return (Float) content.get(FIELD_LENGTH); - } - - /** - * This method sets the audio duration of the represented clip.
    - * - * @param seconds The duration of the audio clip in seconds (single-precision). - */ - public void setPreciseLength(float seconds) { - content.put(FIELD_LENGTH, seconds); - } - - /** - * This method returns the sample rate, the audio clip was encoded with.
    - * - * @return Sample rate of the audio clip in "Hz". - */ - public String getSampleRate() { - return content.get(FIELD_SAMPLERATE).toString(); - } - - public int getSampleRateAsNumber() { - return (Integer) content.get(FIELD_SAMPLERATE); - } - - /** - * @returns The number of bits per sample - */ - public int getBitsPerSample() { - return (Integer) content.get(FIELD_BITSPERSAMPLE); - } - - /* - * Sets the Bits per Sample
    - * - * @params bitsPerSample Bits Per Sample - */ - public void setBitsPerSample(int bitsPerSample) { - content.put(FIELD_BITSPERSAMPLE, bitsPerSample); - } - - /** - * This method returns true, if the audio file is encoded - * with "Variable Bitrate".
    - * - * @return true if audio clip is encoded with VBR. - */ - public boolean isVariableBitRate() { - return (Boolean) content.get(FIELD_VBR); - } - - /** - * Sets the VBR flag for the represented audio clip.
    - * - * @param b true if VBR. - */ - public void setVariableBitRate(boolean b) { - content.put(FIELD_VBR, b); - } - - /** - * This method returns true, if the audio file is encoded - * with "Lossless".
    - * - * @return true if audio clip is encoded with VBR. - */ - public boolean isLossless() { - return isLossless; - } - - /** - * Sets the Lossless flag for the represented audio clip.
    - * - * @param b true if Lossless. - */ - public void setLossless(boolean b) { - isLossless = b; - } - - /** - * This Method sets the bitrate in "Kbps".
    - * - * @param bitrate bitrate in kbps. - */ - public void setBitrate(int bitrate) { - content.put(FIELD_BITRATE, bitrate); - } - - /** - * This method sets the audio duration of the represented clip.
    - * - * @param length The duration of the audio clip in seconds. - */ - public void setLength(int length) { - content.put(FIELD_LENGTH, (float) length); - } - - /** - * Sets the Sampling rate in "Hz"
    - * - * @param samplingRate Sample rate. - */ - public void setSamplingRate(int samplingRate) { - content.put(FIELD_SAMPLERATE, samplingRate); - } - - /** - * Can be used to add additional information - * - * @param key - * @param value - */ - public void setExtra(String key, Object value) { - content.put(key, value); - } - - /** - * Pretty prints this encoding info - * - * @see java.lang.Object#toString() - */ - public String toString() { - StringBuffer out = new StringBuffer(50); - out.append("Encoding infos content:\n"); - Set set = content.keySet(); - for (String key : set) { - Object val = content.get(key); - out.append("\t"); - out.append(key); - out.append(" : "); - out.append(val); - out.append("\n"); - } - return out.toString().substring(0, out.length() - 1); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/GenericTag.java b/src/main/java/org/jaudiotagger/audio/generic/GenericTag.java deleted file mode 100644 index 6dfd2dc..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/GenericTag.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.images.Artwork; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; - -/** - * This is a complete example implementation of - * {@link AbstractTag} and it currenlty used to provide basic support to audio formats with only read tagging - * ability such as Real or Wav files
    - * - * @author Raphaël Slinckx - */ -public abstract class GenericTag extends AbstractTag { - private static EnumSet supportedKeys; - - static { - supportedKeys = EnumSet.of(FieldKey.ALBUM, FieldKey.ARTIST, FieldKey.TITLE, FieldKey.TRACK, FieldKey.GENRE, FieldKey.COMMENT, FieldKey.YEAR); - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AbstractTag#isAllowedEncoding(java.lang.String) - */ - protected boolean isAllowedEncoding(String enc) { - return true; - } - - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (supportedKeys.contains(genericKey)) { - return new GenericTagTextField(genericKey.name(), value); - } else { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - } - - /** - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public String getFirst(FieldKey genericKey) throws KeyNotFoundException { - return getValue(genericKey, 0); - } - - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException { - if (supportedKeys.contains(genericKey)) { - return getItem(genericKey.name(), index); - } else { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - } - - /** - * @param genericKey The field id. - * @return - * @throws KeyNotFoundException - */ - public List getFields(FieldKey genericKey) throws KeyNotFoundException { - List list = fields.get(genericKey.name()); - if (list == null) { - return new ArrayList(); - } - return list; - } - - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - return super.getAll(genericKey.name()); - } - - /** - * @param genericKey - * @throws KeyNotFoundException - */ - public void deleteField(FieldKey genericKey) throws KeyNotFoundException { - if (supportedKeys.contains(genericKey)) { - deleteField(genericKey.name()); - } else { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - } - - /** - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException { - if (supportedKeys.contains(genericKey)) { - return getFirstField(genericKey.name()); - } else { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - } - - public List getArtworkList() { - return Collections.emptyList(); - } - - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - - /** - * Implementations of {@link TagTextField} for use with - * "ISO-8859-1" strings. - * - * @author Raphaël Slinckx - */ - private class GenericTagTextField implements TagTextField { - - /** - * Stores the identifier. - */ - private final String id; - /** - * Stores the string. - */ - private String content; - - /** - * Creates an instance. - * - * @param fieldId The identifier. - * @param initialContent The string. - */ - public GenericTagTextField(String fieldId, String initialContent) { - this.id = fieldId; - this.content = initialContent; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#copyContent(org.jaudiotagger.tag.TagField) - */ - public void copyContent(TagField field) { - if (field instanceof TagTextField) { - this.content = ((TagTextField) field).getContent(); - } - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#getContent() - */ - public String getContent() { - return this.content; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#setContent(java.lang.String) - */ - public void setContent(String s) { - this.content = s; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#getEncoding() - */ - public String getEncoding() { - return "ISO-8859-1"; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagTextField#setEncoding(java.lang.String) - */ - public void setEncoding(String s) { - /* Not allowed */ - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#getId() - */ - public String getId() { - return id; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#getRawContent() - */ - public byte[] getRawContent() { - return this.content == null ? new byte[]{} : Utils.getDefaultBytes(this.content, getEncoding()); - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isBinary() - */ - public boolean isBinary() { - return false; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isBinary(boolean) - */ - public void isBinary(boolean b) { - /* not supported */ - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isCommon() - */ - public boolean isCommon() { - return true; - } - - /** - * (overridden) - * - * @see org.jaudiotagger.tag.TagField#isEmpty() - */ - public boolean isEmpty() { - return this.content.equals(""); - } - - /** - * (overridden) - * - * @see java.lang.Object#toString() - */ - public String toString() { - return getContent(); - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/ModificationHandler.java b/src/main/java/org/jaudiotagger/audio/generic/ModificationHandler.java deleted file mode 100644 index 94b528f..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/ModificationHandler.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.ModifyVetoException; - -import java.io.File; -import java.util.Vector; - -/** - * This class multicasts the events to multiple listener instances.
    - * Additionally the Vetos are handled. (other listeners are notified). - * - * @author Christian Laireiter - */ -public class ModificationHandler implements AudioFileModificationListener { - - /** - * The listeners to wich events are broadcasted are stored here. - */ - private Vector listeners = new Vector(); - - /** - * This method adds an {@link AudioFileModificationListener} - * - * @param l Listener to add. - */ - public void addAudioFileModificationListener(AudioFileModificationListener l) { - if (!this.listeners.contains(l)) { - this.listeners.add(l); - } - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#fileModified(org.jaudiotagger.audio.AudioFile, - * File) - */ - public void fileModified(AudioFile original, File temporary) throws ModifyVetoException { - for (AudioFileModificationListener listener : this.listeners) { - AudioFileModificationListener current = listener; - try { - current.fileModified(original, temporary); - } catch (ModifyVetoException e) { - vetoThrown(current, original, e); - throw e; - } - } - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#fileOperationFinished(File) - */ - public void fileOperationFinished(File result) { - for (AudioFileModificationListener listener : this.listeners) { - AudioFileModificationListener current = listener; - current.fileOperationFinished(result); - } - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#fileWillBeModified(org.jaudiotagger.audio.AudioFile, - * boolean) - */ - public void fileWillBeModified(AudioFile file, boolean delete) throws ModifyVetoException { - for (AudioFileModificationListener listener : this.listeners) { - AudioFileModificationListener current = listener; - try { - current.fileWillBeModified(file, delete); - } catch (ModifyVetoException e) { - vetoThrown(current, file, e); - throw e; - } - } - } - - /** - * This method removes an {@link AudioFileModificationListener} - * - * @param l Listener to remove. - */ - public void removeAudioFileModificationListener(AudioFileModificationListener l) { - if (this.listeners.contains(l)) { - this.listeners.remove(l); - } - } - - /** - * (overridden) - * - * @see org.jaudiotagger.audio.generic.AudioFileModificationListener#vetoThrown(org.jaudiotagger.audio.generic.AudioFileModificationListener, - * org.jaudiotagger.audio.AudioFile, - * org.jaudiotagger.audio.exceptions.ModifyVetoException) - */ - public void vetoThrown(AudioFileModificationListener cause, AudioFile original, ModifyVetoException veto) { - for (AudioFileModificationListener listener : this.listeners) { - AudioFileModificationListener current = listener; - current.vetoThrown(cause, original, veto); - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/Utils.java b/src/main/java/org/jaudiotagger/audio/generic/Utils.java deleted file mode 100644 index 760d4ee..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/Utils.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.generic; - -import org.jaudiotagger.audio.AudioFile; - -import java.io.*; -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Contains various frequently used static functions in the different tag - * formats - * - * @author Raphael Slinckx - */ -public class Utils { - - private static final int MAX_BASE_TEMP_FILENAME_LENGTH = 20; - // Logger Object - public static Logger logger = Logger - .getLogger("org.jaudiotagger.audio.generic.utils"); - - /** - * Copies the bytes of srd to dst at the - * specified offset. - * - * @param src The byte to be copied. - * @param dst The array to copy to - * @param dstOffset The start offset for the bytes to be copied. - */ - public static void copy(byte[] src, byte[] dst, int dstOffset) { - System.arraycopy(src, 0, dst, dstOffset, src.length); - } - - - /** - * Returns {@link String#getBytes()}.
    - * - * @param s The String to call, decode bytes using the specfied charset - * @param charSet - * @return The bytes. - */ - public static byte[] getDefaultBytes(String s, String charSet) { - try { - return s.getBytes(charSet); - } catch (UnsupportedEncodingException uee) { - throw new RuntimeException(uee); - } - - } - - /* - * Returns the extension of the given file. - * The extension is empty if there is no extension - * The extension is the string after the last "." - * - * @param f The file whose extension is requested - * @return The extension of the given file - */ - public static String getExtension(File f) { - String name = f.getName().toLowerCase(); - int i = name.lastIndexOf("."); - if (i == -1) { - return ""; - } - - return name.substring(i + 1); - } - - - /* - * Computes a number whereby the 1st byte is the least signifcant and the last - * byte is the most significant. - * - * @param b The byte array @param start The starting offset in b - * (b[offset]). The less significant byte @param end The end index - * (included) in b (b[end]). The most significant byte @return a long number - * represented by the byte sequence. - * - * So if storing a number which only requires one byte it will be stored in the first - * byte. - */ - public static long getLongLE(ByteBuffer b, int start, int end) { - long number = 0; - for (int i = 0; i < (end - start + 1); i++) { - number += ((b.get(start + i) & 0xFF) << i * 8); - } - - return number; - } - - /* - * Computes a number whereby the 1st byte is the most significant and the last - * byte is the least significant. - * - * So if storing a number which only requires one byte it will be stored in the last - * byte. - * - * Will fail if end - start >= 8, due to the limitations of the long type. - */ - public static long getLongBE(ByteBuffer b, int start, int end) { - long number = 0; - for (int i = 0; i < (end - start + 1); i++) { - number += ((long) ((b.get(end - i) & 0xFF)) << i * 8); - } - - return number; - } - - /* - * Computes a number whereby the 1st byte is the least significant and the last - * byte is the most significant. This version doesn't take a length, - * and it returns an int rather than a long. - * - * @param b The byte array. Maximum length for valid results is 4 bytes. - * - */ - public static int getIntLE(byte[] b) { - return (int) getLongLE(ByteBuffer.wrap(b), 0, b.length - 1); - } - - /* - * Computes a number whereby the 1st byte is the least significant and the last - * byte is the most significant. end - start must be no greater than 4. - * - * @param b The byte array - * - * @param start The starting offset in b (b[offset]). The less - * significant byte - * - * @param end The end index (included) in b (b[end]) - * - * @return a int number represented by the byte sequence. - */ - public static int getIntLE(byte[] b, int start, int end) { - return (int) getLongLE(ByteBuffer.wrap(b), start, end); - } - - /* - * Computes a number whereby the 1st byte is the most significant and the last - * byte is the least significant. - * - * @param b The byte array - * - * @param start The starting offset in b (b[offset]). The less - * significant byte - * - * @param end The end index (included) in b (b[end]) - * - * @return an int number represented by the byte sequence. - */ - public static int getIntBE(byte[] b, int start, int end) { - return (int) getLongBE(ByteBuffer.wrap(b), start, end); - } - - /* - * Computes a number whereby the 1st byte is the most significant and the last - * byte is the least significant. - * - * @param b The ByteBuffer - * - * @param start The starting offset in b. The less - * significant byte - * - * @param end The end index (included) in b - * - * @return an int number represented by the byte sequence. - */ - public static int getIntBE(ByteBuffer b, int start, int end) { - return (int) getLongBE(b, start, end); - } - - /* - * Computes a number whereby the 1st byte is the most significant and the last - * byte is the least significant. - * - * @param b The ByteBuffer - * - * @param start The starting offset in b. The less - * significant byte - * - * @param end The end index (included) in b - * - * @return a short number represented by the byte sequence. - */ - public static short getShortBE(ByteBuffer b, int start, int end) { - return (short) getIntBE(b, start, end); - } - - /** - * Convert int to byte representation - Big Endian (as used by mp4) - * - * @param size - * @return byte represenetation - */ - public static byte[] getSizeBEInt32(int size) { - byte[] b = new byte[4]; - b[0] = (byte) ((size >> 24) & 0xFF); - b[1] = (byte) ((size >> 16) & 0xFF); - b[2] = (byte) ((size >> 8) & 0xFF); - b[3] = (byte) (size & 0xFF); - return b; - } - - /** - * Convert short to byte representation - Big Endian (as used by mp4) - * - * @param size number to convert - * @return byte represenetation - */ - public static byte[] getSizeBEInt16(short size) { - byte[] b = new byte[2]; - b[0] = (byte) ((size >> 8) & 0xFF); - b[1] = (byte) (size & 0xFF); - return b; - } - - - /** - * Convert int to byte representation - Little Endian (as used by ogg vorbis) - * - * @param size number to convert - * @return byte represenetation - */ - public static byte[] getSizeLEInt32(int size) { - byte[] b = new byte[4]; - b[0] = (byte) (size & 0xff); - b[1] = (byte) ((size >>> 8) & 0xffL); - b[2] = (byte) ((size >>> 16) & 0xffL); - b[3] = (byte) ((size >>> 24) & 0xffL); - return b; - } - - /** - * Create String starting from offset upto length using encoding - * - * @param b - * @param offset - * @param length - * @param encoding - * @return String - * @throws RuntimeException - */ - public static String getString(byte[] b, int offset, int length, String encoding) { - try { - return new String(b, offset, length, encoding); - } catch (UnsupportedEncodingException ue) { - //Shouldnt have to worry about this exception as should only be calling with well defined charsets - throw new RuntimeException(ue); - } - } - - /** - * Create String offset from position by offset upto length using encoding, and position of buffer - * is moved to after position + offset + length - * - * @param buffer - * @param offset - * @param length - * @param encoding - * @return String - * @throws RuntimeException - */ - public static String getString(ByteBuffer buffer, int offset, int length, String encoding) { - byte[] b = new byte[length]; - buffer.position(buffer.position() + offset); - buffer.get(b); - try { - return new String(b, 0, length, encoding); - } catch (UnsupportedEncodingException uee) { - //TODO, will we ever use unsupported encodings - throw new RuntimeException(uee); - } - } - - /* - * Tries to convert a string into an UTF8 array of bytes If the conversion - * fails, return the string converted with the default encoding. - * - * @param s The string to convert @return The byte array representation of - * this string in UTF8 encoding - */ - public static byte[] getUTF8Bytes(String s) throws UnsupportedEncodingException { - return s.getBytes("UTF-8"); - } - - /** - * Reads a 32-bit integer and returns it as a (signed) int. - * Does overflow checking since java can't handle unsigned numbers. - * - * @param di The input source - * @return int - * @throws java.io.IOException - */ - public static int readUint32AsInt(DataInput di) throws IOException { - final long l = readUint32(di); - if (l > Integer.MAX_VALUE) { - throw new IOException("uint32 value read overflows int"); - } - return (int) l; - } - - /** - * Read a 32-bit big-endian unsigned integer using a DataInput. - */ - public static long readUint32(DataInput di) throws IOException { - final byte[] buf8 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - di.readFully(buf8, 4, 4); - final long l = ByteBuffer.wrap(buf8).getLong(); - return l; - } - - /** - * Read a 16-bit big-endian unsigned integer - */ - public static int readUint16(DataInput di) throws IOException { - final byte[] buf = {0x00, 0x00, 0x00, 0x00}; - di.readFully(buf, 2, 2); - final int i = ByteBuffer.wrap(buf).getInt(); - return i; - } - - /** - * Read a 16-bit big-endian signed integer - */ - public static int readInt16(DataInput di) throws IOException { - final byte[] buf = {0x00, 0x00}; - di.readFully(buf, 0, 2); - final int i = ByteBuffer.wrap(buf).getShort(); - return i; - } - - /** - * Read a string of a specified number of ASCII bytes - */ - public static String readString(DataInput di, int charsToRead) throws IOException { - final byte[] buf = new byte[charsToRead]; - di.readFully(buf); - return new String(buf); - } - - /** - * Read a 64-bit unsigned integer using an nio ByteBuffer - */ - public static long readUInt64(ByteBuffer b) { - long result = 0; - result += (readUBEInt32(b) << 32); - result += readUBEInt32(b); - return result; - } - - /** - * Read an unsigned big-endian 32-bit integer using an nio ByteBuffer - */ - public static int readUBEInt32(ByteBuffer b) { - int result = 0; - result += readUBEInt16(b) << 16; - result += readUBEInt16(b); - return result; - } - - /** - * Read an unsigned big-endian 24-bit integer using an - * nio ByteBuffer - */ - public static int readUBEInt24(ByteBuffer b) { - int result = 0; - result += readUBEInt16(b) << 16; - result += readUInt8(b); - return result; - } - - /** - * Read an unsigned big-endian 16-bit integer using an - * nio ByteBuffer - */ - public static int readUBEInt16(ByteBuffer b) { - int result = 0; - result += readUInt8(b) << 8; - result += readUInt8(b); - return result; - } - - /** - * Read an unsigned (endian-neutral) 8-bit integer using an - * nio ByteBuffer - */ - public static int readUInt8(ByteBuffer b) { - return read(b); - } - - - public static int read(ByteBuffer b) { - int result = (b.get() & 0xFF); - return result; - } - - /** - * Get a base for temp file, this should be long enough so that it easy to work out later what file the temp file - * was created for if it is left lying round, but not ridiculously long as this can cause problems with max filename - * limits and is not very useful - * - * @param file - * @return - */ - public static String getBaseFilenameForTempFile(File file) { - String filename = getMinBaseFilenameAllowedForTempFile(file); - if (filename.length() <= MAX_BASE_TEMP_FILENAME_LENGTH) { - return filename; - } - return filename.substring(0, MAX_BASE_TEMP_FILENAME_LENGTH); - } - - /** - * @param file - * @return filename with audioformat separator stripped of, lengthened to ensure not too small for valid tempfile - * creation. - */ - public static String getMinBaseFilenameAllowedForTempFile(File file) { - String s = AudioFile.getBaseFilename(file); - if (s.length() >= 3) { - return s; - } - if (s.length() == 1) { - return s + "000"; - } else if (s.length() == 1) { - return s + "00"; - } else if (s.length() == 2) { - return s + "0"; - } - return s; - } - - /** - * Rename file, and if normal rename fails, try copy and delete instead - * - * @param fromFile - * @param toFile - * @return - */ - public static boolean rename(File fromFile, File toFile) { - logger.log(Level.CONFIG, "Renaming From:" + fromFile.getAbsolutePath() + " to " + toFile.getAbsolutePath()); - - if (toFile.exists()) { - logger.log(Level.SEVERE, "Destination File:" + toFile + " already exists"); - return false; - } - - //Rename File, could fail because being used or because trying to rename over filesystems - final boolean result = fromFile.renameTo(toFile); - if (!result) { - // Might be trying to rename over filesystem, so try copy and delete instead - if (copy(fromFile, toFile)) { - //If copy works but deletion of original file fails then it is because the file is being used - //so we need to delete the file we have just created - boolean deleteResult = fromFile.delete(); - if (!deleteResult) { - logger.log(Level.SEVERE, "Unable to delete File:" + fromFile); - toFile.delete(); - return false; - } - return true; - } else { - return false; - } - } - return true; - } - - /** - * Copy a File - * - * @param fromFile The existing File - * @param toFile The new File - * @return true if and only if the renaming succeeded; - * false otherwise - */ - public static boolean copy(File fromFile, File toFile) { - try { - FileInputStream in = new FileInputStream(fromFile); - FileOutputStream out = new FileOutputStream(toFile); - byte[] buf = new byte[8192]; - - int len; - - while ((len = in.read(buf)) > -1) { - out.write(buf, 0, len); - } - - in.close(); - out.close(); - - // cleanup if files are not the same length - if (fromFile.length() != toFile.length()) { - toFile.delete(); - - return false; - } - - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/generic/package.html b/src/main/java/org/jaudiotagger/audio/generic/package.html deleted file mode 100644 index ed68a17..0000000 --- a/src/main/java/org/jaudiotagger/audio/generic/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -A miscellaneous collection of classes dealing with generic audio files and tags. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/mp3/ByteArrayMP3AudioHeader.java b/src/main/java/org/jaudiotagger/audio/mp3/ByteArrayMP3AudioHeader.java deleted file mode 100644 index 91104c8..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/ByteArrayMP3AudioHeader.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; - -import java.nio.ByteBuffer; - -public class ByteArrayMP3AudioHeader extends MP3AudioHeader { - - public ByteArrayMP3AudioHeader(byte[] fileBytes) { - //References to Xing Header - ByteBuffer header; - - // This is substantially faster than updating the filechannels position - long filePointerCount = 0; - - // Read into Byte Buffer in Chunks - ByteBuffer bb = ByteBuffer.wrap(fileBytes); - - boolean syncFound = false; - do { - if (MPEGFrameHeader.isMPEGFrame(bb)) { - try { - - mp3FrameHeader = MPEGFrameHeader.parseMPEGHeader(bb); - syncFound = true; - if ((header = XingFrame.isXingFrame(bb, mp3FrameHeader)) != null) { - try { - // Parses Xing frame without modifying position of main buffer - mp3XingFrame = XingFrame.parseXingFrame(header); - } catch (InvalidAudioFrameException ex) { - // We Ignore because even if Xing Header is corrupted - // doesn't mean file is corrupted - } - break; - } - // There is a small but real chance that an unsynchronised ID3 Frame could fool the MPEG - // Parser into thinking it was an MPEG Header. If this happens the chances of the next bytes - // forming a Xing frame header are very remote. On the basis that most files these days have - // Xing headers we do an additional check for when an apparent frame header has been found - // but is not followed by a Xing Header:We check the next header this wont impose a large - // overhead because wont apply to most Mpegs anyway ( Most likely to occur if audio - // has an APIC frame which should have been unsynchronised but has not been) , or if the frame - // has been encoded with as Unicode LE because these have a BOM of 0xFF 0xFE - else { - syncFound = isNextFrameValid(bb); - if (syncFound) { - break; - } - } - - } catch (InvalidAudioFrameException ex) { - // We Ignore because likely to be incorrect sync bits , - // will just continue in loop - } - } - bb.position(bb.position() + 1); - filePointerCount++; - } - while (!syncFound); - - setFileSize(fileBytes.length); - setMp3StartByte(filePointerCount); - setTimePerFrame(); - setNumberOfFrames(); - setTrackLength(); - setBitRate(); - setEncoder(); - } - - private boolean isNextFrameValid(ByteBuffer bb) { - boolean result = false; - int currentPosition = bb.position(); - - bb.position(bb.position() + mp3FrameHeader.getFrameLength()); - if (MPEGFrameHeader.isMPEGFrame(bb)) { - try { - MPEGFrameHeader.parseMPEGHeader(bb); - MP3AudioHeader.logger.finer("Check next frame confirms is an audio header "); - result = true; - } catch (InvalidAudioFrameException ex) { - MP3AudioHeader.logger.finer("Check next frame has identified this is not an audio header"); - result = false; - } - } - // Set back to the start of the previous frame - bb.position(currentPosition); - return result; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/mp3/LameFrame.java b/src/main/java/org/jaudiotagger/audio/mp3/LameFrame.java deleted file mode 100644 index 942c0e8..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/LameFrame.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - -/** - * The first frame can sometimes contain a LAME frame at the end of the Xing frame - *

    - *

    This useful to the library because it allows the encoder to be identified, full specification - * can be found at http://gabriel.mp3-tech.org/mp3infotag.html - *

    - * Summarized here: - * 4 bytes:LAME - * 5 bytes:LAME Encoder Version - * 1 bytes:VNR Method - * 1 bytes:Lowpass filter value - * 8 bytes:Replay Gain - * 1 byte:Encoding Flags - * 1 byte:minimal byte rate - * 3 bytes:extra samples - * 1 byte:Stereo Mode - * 1 byte:MP3 Gain - * 2 bytes:Surround Dound - * 4 bytes:MusicLength - * 2 bytes:Music CRC - * 2 bytes:CRC Tag - */ -public class LameFrame { - public static final int LAME_HEADER_BUFFER_SIZE = 36; - public static final int ENCODER_SIZE = 9; //Includes LAME ID - public static final int LAME_ID_SIZE = 4; - public static final String LAME_ID = "LAME"; - private String encoder; - - /** - * Initilise a Lame Mpeg Frame - * - * @param lameHeader - */ - private LameFrame(ByteBuffer lameHeader) { - encoder = Utils.getString(lameHeader, 0, ENCODER_SIZE, TextEncoding.CHARSET_ISO_8859_1); - } - - /** - * Parse frame - * - * @param bb - * @return frame or null if not exists - */ - public static LameFrame parseLameFrame(ByteBuffer bb) { - ByteBuffer lameHeader = bb.slice(); - String id = Utils.getString(lameHeader, 0, LAME_ID_SIZE, TextEncoding.CHARSET_ISO_8859_1); - lameHeader.rewind(); - if (id.equals(LAME_ID)) { - LameFrame lameFrame = new LameFrame(lameHeader); - return lameFrame; - } - return null; - } - - /** - * @return encoder - */ - public String getEncoder() { - return encoder; - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/mp3/MP3AudioHeader.java b/src/main/java/org/jaudiotagger/audio/mp3/MP3AudioHeader.java deleted file mode 100644 index 7830b9d..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/MP3AudioHeader.java +++ /dev/null @@ -1,674 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: MP3AudioHeader.java 1086 2013-01-31 16:38:48Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.AudioHeader; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.logging.Hex; - -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Represents the audio header of an MP3 File - *

    - *

    The audio header consists of a number of - * audio frames. Because we are not trying to play the audio but only extract some information - * regarding the audio we only need to read the first audio frames to ensure that we have correctly - * identified them as audio frames and extracted the metadata we reuire. - *

    - *

    Start of Audio id 0xFF (11111111) and then second byte anded with 0xE0(11100000). - * For example 2nd byte doesnt have to be 0xE0 is just has to have the top 3 signicant - * bits set. For example 0xFB (11111011) is a common occurence of the second match. The 2nd byte - * defines flags to indicate various mp3 values. - *

    - *

    Having found these two values we then read the header which comprises these two bytes plus a further - * two to ensure this really is a MP3Header, sometimes the first frame is actually a dummy frame with summary information - * held within about the whole file, typically using a Xing Header or LAme Header. This is most useful when the file - * is variable bit rate, if the file is variable bit rate but does not use a summary header it will not be correctly - * identified as a VBR frame and the track length will be incorrectly calculated. Strictly speaking MP3 means - * Layer III file but MP2 Layer II), MP1 Layer I) and MPEG-2 files are sometimes used and named with - * the .mp3 suffix so this library attempts to supports all these formats. - */ -public class MP3AudioHeader implements AudioHeader { - private static final SimpleDateFormat timeInFormat = new SimpleDateFormat("ss", Locale.UK); - private static final SimpleDateFormat timeOutFormat = new SimpleDateFormat("mm:ss", Locale.UK); - private static final SimpleDateFormat timeOutOverAnHourFormat = new SimpleDateFormat("kk:mm:ss", Locale.UK); - private static final char isVbrIdentifier = '~'; - private static final int CONVERT_TO_KILOBITS = 1000; - private static final String TYPE_MP3 = "mp3"; - private static final int CONVERTS_BYTE_TO_BITS = 8; - /** - * After testing the average location of the first MP3Header bit was at 5000 bytes so this is - * why chosen as a default. - */ - private final static int FILE_BUFFER_SIZE = 5000; - private final static int MIN_BUFFER_REMAINING_REQUIRED = MPEGFrameHeader.HEADER_SIZE + XingFrame.MAX_BUFFER_SIZE_NEEDED_TO_READ_XING; - private static final int NO_SECONDS_IN_HOUR = 3600; - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.mp3"); - protected MPEGFrameHeader mp3FrameHeader; - protected XingFrame mp3XingFrame; - protected VbriFrame mp3VbriFrame; - private long fileSize; - private long startByte; - private double timePerFrame; - private double trackLength; - private long numberOfFrames; - private long numberOfFramesEstimate; - private long bitrate; - private String encoder = ""; - - public MP3AudioHeader() { - } - - /** - * Search for the first MP3Header in the file - *

    - * The search starts from the start of the file, it is usually safer to use the alternative constructor that - * allows you to provide the length of the tag header as a parameter so the tag can be skipped over. - * - * @param seekFile - * @throws IOException - * @throws InvalidAudioFrameException - */ - public MP3AudioHeader(final File seekFile) throws IOException, InvalidAudioFrameException { - if (!seek(seekFile, 0)) { - throw new InvalidAudioFrameException("No audio header found within" + seekFile.getName()); - } - } - - /** - * Search for the first MP3Header in the file - *

    - * Starts searching from location startByte, this is because there is likely to be an ID3TagHeader - * before the start of the audio. If this tagHeader contains unsynchronized information there is a - * possibility that it might be inaccurately identified as the start of the Audio data. Various checks - * are done in this code to prevent this happening but it cannot be guaranteed. - *

    - * Of course if the startByte provided overstates the length of the tag header, this could mean the - * start of the MP3AudioHeader is missed, further checks are done within the MP3 class to recognize - * if this has occurred and take appropriate action. - * - * @param seekFile - * @param startByte - * @throws IOException - * @throws InvalidAudioFrameException - */ - public MP3AudioHeader(final File seekFile, long startByte) throws IOException, InvalidAudioFrameException { - if (!seek(seekFile, startByte)) { - throw new InvalidAudioFrameException(ErrorMessage.NO_AUDIO_HEADER_FOUND.getMsg(seekFile.getName())); - } - } - - /** - * Returns true if the first MP3 frame can be found for the MP3 file - *

    - * This is the first byte of music data and not the ID3 Tag Frame. * - * - * @param seekFile MP3 file to seek - * @param startByte if there is an ID3v2tag we dont want to start reading from the start of the tag - * @return true if the first MP3 frame can be found - * @throws IOException on any I/O error - * @noinspection NestedTryStatement - */ - public boolean seek(final File seekFile, long startByte) throws IOException { - //References to Xing/VRbi Header - ByteBuffer header; - - //This is substantially faster than updating the filechannels position - long filePointerCount; - - final FileInputStream fis = new FileInputStream(seekFile); - final FileChannel fc = fis.getChannel(); - - //Read into Byte Buffer in Chunks - ByteBuffer bb = ByteBuffer.allocateDirect(FILE_BUFFER_SIZE); - - //Move FileChannel to the starting position (skipping over tag if any) - fc.position(startByte); - - //Update filePointerCount - filePointerCount = startByte; - - //Read from here into the byte buffer , doesn't move location of filepointer - fc.read(bb, startByte); - bb.flip(); - - boolean syncFound = false; - try { - do { - //TODO remaining() is quite an expensive operation, isn't there a way we can work this out without - //interrogating the bytebuffer. Also this is rarely going to be true, and could be made less true - //by increasing FILE_BUFFER_SIZE - if (bb.remaining() <= MIN_BUFFER_REMAINING_REQUIRED) { - bb.clear(); - fc.position(filePointerCount); - fc.read(bb, fc.position()); - bb.flip(); - if (bb.limit() <= MIN_BUFFER_REMAINING_REQUIRED) { - //No mp3 exists - return false; - } - } - //MP3File.logger.finest("fc:"+fc.position() + "bb"+bb.position()); - if (MPEGFrameHeader.isMPEGFrame(bb)) { - try { - if (MP3AudioHeader.logger.isLoggable(Level.FINEST)) { - MP3AudioHeader.logger.finest("Found Possible header at:" + filePointerCount); - } - - mp3FrameHeader = MPEGFrameHeader.parseMPEGHeader(bb); - syncFound = true; - //if(2==1) use this line when you want to test getting the next frame without using xing - - if ((header = XingFrame.isXingFrame(bb, mp3FrameHeader)) != null) { - if (MP3AudioHeader.logger.isLoggable(Level.FINEST)) { - MP3AudioHeader.logger.finest("Found Possible XingHeader"); - } - try { - //Parses Xing frame without modifying position of main buffer - mp3XingFrame = XingFrame.parseXingFrame(header); - } catch (InvalidAudioFrameException ex) { - // We Ignore because even if Xing Header is corrupted - //doesn't mean file is corrupted - } - break; - } else if ((header = VbriFrame.isVbriFrame(bb, mp3FrameHeader)) != null) { - if (MP3AudioHeader.logger.isLoggable(Level.FINEST)) { - MP3AudioHeader.logger.finest("Found Possible VbriHeader"); - } - try { - //Parses Vbri frame without modifying position of main buffer - mp3VbriFrame = VbriFrame.parseVBRIFrame(header); - } catch (InvalidAudioFrameException ex) { - // We Ignore because even if Vbri Header is corrupted - //doesn't mean file is corrupted - } - break; - } - // There is a small but real chance that an unsynchronised ID3 Frame could fool the MPEG - // Parser into thinking it was an MPEG Header. If this happens the chances of the next bytes - // forming a Xing frame header are very remote. On the basis that most files these days have - // Xing headers we do an additional check for when an apparent frame header has been found - // but is not followed by a Xing Header:We check the next header this wont impose a large - // overhead because wont apply to most Mpegs anyway ( Most likely to occur if audio - // has an APIC frame which should have been unsynchronised but has not been) , or if the frame - // has been encoded with as Unicode LE because these have a BOM of 0xFF 0xFE - else { - syncFound = isNextFrameValid(seekFile, filePointerCount, bb, fc); - if (syncFound) { - break; - } - } - - } catch (InvalidAudioFrameException ex) { - // We Ignore because likely to be incorrect sync bits , - // will just continue in loop - } - } - - //TODO position() is quite an expensive operation, isn't there a way we can work this out without - //interrogating the bytebuffer - bb.position(bb.position() + 1); - filePointerCount++; - - - } - while (!syncFound); - } catch (EOFException ex) { - MP3AudioHeader.logger.log(Level.WARNING, "Reached end of file without finding sync match", ex); - syncFound = false; - } catch (IOException iox) { - MP3AudioHeader.logger.log(Level.SEVERE, "IOException occurred whilst trying to find sync", iox); - syncFound = false; - throw iox; - } finally { - if (fc != null) { - fc.close(); - } - - if (fis != null) { - fis.close(); - } - } - - //Return to start of audio header - if (MP3AudioHeader.logger.isLoggable(Level.FINEST)) { - MP3AudioHeader.logger.finer("Return found matching mp3 header starting at" + filePointerCount); - } - setFileSize(seekFile.length()); - setMp3StartByte(filePointerCount); - setTimePerFrame(); - setNumberOfFrames(); - setTrackLength(); - setBitRate(); - setEncoder(); - /*if((filePointerCount - startByte )>0) - { - logger.severe(seekFile.getName()+"length:"+startByte+"Difference:"+(filePointerCount - startByte)); - } - */ - return syncFound; - } - - /** - * Called in some circumstances to check the next frame to ensure we have the correct audio header - * - * @param seekFile - * @param filePointerCount - * @param bb - * @param fc - * @return true if frame is valid - * @throws java.io.IOException - */ - private boolean isNextFrameValid(File seekFile, long filePointerCount, ByteBuffer bb, FileChannel fc) throws IOException { - if (MP3AudioHeader.logger.isLoggable(Level.FINEST)) { - MP3AudioHeader.logger.finer("Checking next frame" + seekFile.getName() + ":fpc:" + filePointerCount + "skipping to:" + (filePointerCount + mp3FrameHeader.getFrameLength())); - } - boolean result = false; - - int currentPosition = bb.position(); - - //Our buffer is not large enough to fit in the whole of this frame, something must - //have gone wrong because frames are not this large, so just return false - //bad frame header - if (mp3FrameHeader.getFrameLength() > (FILE_BUFFER_SIZE - MIN_BUFFER_REMAINING_REQUIRED)) { - MP3AudioHeader.logger.finer("Frame size is too large to be a frame:" + mp3FrameHeader.getFrameLength()); - return false; - } - - //Check for end of buffer if not enough room get some more - if (bb.remaining() <= MIN_BUFFER_REMAINING_REQUIRED + mp3FrameHeader.getFrameLength()) { - MP3AudioHeader.logger.finer("Buffer too small, need to reload, buffer size:" + bb.remaining()); - bb.clear(); - fc.position(filePointerCount); - fc.read(bb, fc.position()); - bb.flip(); - //So now original buffer has been replaced, so set current position to start of buffer - currentPosition = 0; - //Not enough left - if (bb.limit() <= MIN_BUFFER_REMAINING_REQUIRED) { - //No mp3 exists - MP3AudioHeader.logger.finer("Nearly at end of file, no header found:"); - return false; - } - - //Still Not enough left for next alleged frame size so giving up - if (bb.limit() <= MIN_BUFFER_REMAINING_REQUIRED + mp3FrameHeader.getFrameLength()) { - //No mp3 exists - MP3AudioHeader.logger.finer("Nearly at end of file, no room for next frame, no header found:"); - return false; - } - } - - //Position bb to the start of the alleged next frame - bb.position(bb.position() + mp3FrameHeader.getFrameLength()); - if (MPEGFrameHeader.isMPEGFrame(bb)) { - try { - MPEGFrameHeader.parseMPEGHeader(bb); - MP3AudioHeader.logger.finer("Check next frame confirms is an audio header "); - result = true; - } catch (InvalidAudioFrameException ex) { - MP3AudioHeader.logger.finer("Check next frame has identified this is not an audio header"); - result = false; - } - } else { - MP3AudioHeader.logger.finer("isMPEGFrame has identified this is not an audio header"); - } - //Set back to the start of the previous frame - bb.position(currentPosition); - return result; - } - - /** - * Returns the byte position of the first MP3 Frame that the - * file arguement refers to. This is the first byte of music - * data and not the ID3 Tag Frame. - * - * @return the byte position of the first MP3 Frame - */ - public long getMp3StartByte() { - return startByte; - } - - /** - * Set the location of where the Audio file begins in the file - * - * @param startByte - */ - protected void setMp3StartByte(final long startByte) { - this.startByte = startByte; - } - - /** - * Set number of frames in this file, use Xing if exists otherwise ((File Size - Non Audio Part)/Frame Size) - */ - protected void setNumberOfFrames() { - numberOfFramesEstimate = (fileSize - startByte) / mp3FrameHeader.getFrameLength(); - - if (mp3XingFrame != null && mp3XingFrame.isFrameCountEnabled()) { - numberOfFrames = mp3XingFrame.getFrameCount(); - } else if (mp3VbriFrame != null) { - numberOfFrames = mp3VbriFrame.getFrameCount(); - } else { - numberOfFrames = numberOfFramesEstimate; - } - - } - - /** - * @return The number of frames within the Audio File, calculated as accurrately as possible - */ - public long getNumberOfFrames() { - return numberOfFrames; - } - - /** - * @return The number of frames within the Audio File, calculated by dividing the filesize by - * the number of frames, this may not be the most accurate method available. - */ - public long getNumberOfFramesEstimate() { - return numberOfFramesEstimate; - } - - /** - * Set the time each frame contributes to the audio in fractions of seconds, the higher - * the sampling rate the shorter the audio segment provided by the frame, - * the number of samples is fixed by the MPEG Version and Layer - */ - protected void setTimePerFrame() { - timePerFrame = mp3FrameHeader.getNoOfSamples() / mp3FrameHeader.getSamplingRate().doubleValue(); - } - - /** - * @return the the time each frame contributes to the audio in fractions of seconds - */ - private double getTimePerFrame() { - return timePerFrame; - } - - /** - * Estimate the length of the audio track in seconds - * Calculation is Number of frames multiplied by the Time Per Frame using the first frame as a prototype - * Time Per Frame is the number of samples in the frame (which is defined by the MPEGVersion/Layer combination) - * divided by the sampling rate, i.e the higher the sampling rate the shorter the audio represented by the frame is going - * to be. - */ - protected void setTrackLength() { - trackLength = numberOfFrames * getTimePerFrame(); - } - - - /** - * @return Track Length in seconds - */ - public double getPreciseTrackLength() { - return trackLength; - } - - public int getTrackLength() { - return (int) getPreciseTrackLength(); - } - - /** - * Return the length in user friendly format - * - * @return - */ - public String getTrackLengthAsString() { - final Date timeIn; - try { - final long lengthInSecs = getTrackLength(); - synchronized (timeInFormat) { - timeIn = timeInFormat.parse(String.valueOf(lengthInSecs)); - } - - if (lengthInSecs < NO_SECONDS_IN_HOUR) { - synchronized (timeOutFormat) { - return timeOutFormat.format(timeIn); - } - } else { - synchronized (timeOutOverAnHourFormat) { - return timeOutOverAnHourFormat.format(timeIn); - } - } - } catch (ParseException pe) { - logger.warning("Unable to parse:" + getPreciseTrackLength() + " failed with ParseException:" + pe.getMessage()); - return ""; - } - } - - /** - * @return the audio file type - */ - public String getEncodingType() { - return TYPE_MP3; - } - - /** - * Set bitrate in kbps, if Vbr use Xingheader if possible - */ - protected void setBitRate() { - - if (mp3XingFrame != null && mp3XingFrame.isVbr()) { - if (mp3XingFrame.isAudioSizeEnabled() && mp3XingFrame.getAudioSize() > 0) { - bitrate = (long) ((mp3XingFrame.getAudioSize() * CONVERTS_BYTE_TO_BITS) / (timePerFrame * getNumberOfFrames() * CONVERT_TO_KILOBITS)); - } else { - bitrate = (long) (((fileSize - startByte) * CONVERTS_BYTE_TO_BITS) / (timePerFrame * getNumberOfFrames() * CONVERT_TO_KILOBITS)); - } - } else if (mp3VbriFrame != null) { - if (mp3VbriFrame.getAudioSize() > 0) { - bitrate = (long) ((mp3VbriFrame.getAudioSize() * CONVERTS_BYTE_TO_BITS) / (timePerFrame * getNumberOfFrames() * CONVERT_TO_KILOBITS)); - } else { - bitrate = (long) (((fileSize - startByte) * CONVERTS_BYTE_TO_BITS) / (timePerFrame * getNumberOfFrames() * CONVERT_TO_KILOBITS)); - } - } else { - bitrate = mp3FrameHeader.getBitRate(); - } - } - - protected void setEncoder() { - if (mp3XingFrame != null) { - if (mp3XingFrame.getLameFrame() != null) { - encoder = mp3XingFrame.getLameFrame().getEncoder(); - } - } else if (mp3VbriFrame != null) { - encoder = mp3VbriFrame.getEncoder(); - } - } - - /** - * @return bitrate in kbps, no indicator is provided as to whether or not it is vbr - */ - public long getBitRateAsNumber() { - return bitrate; - } - - /** - * @return the BitRate of the Audio, to distinguish cbr from vbr we add a '~' - * for vbr. - */ - public String getBitRate() { - if (mp3XingFrame != null && mp3XingFrame.isVbr()) { - return isVbrIdentifier + String.valueOf(bitrate); - } else if (mp3VbriFrame != null) { - return isVbrIdentifier + String.valueOf(bitrate); - } else { - return String.valueOf(bitrate); - } - } - - - /** - * @return the sampling rate in Hz - */ - public int getSampleRateAsNumber() { - return mp3FrameHeader.getSamplingRate(); - } - - /** - * @return the number of bits per sample - */ - public int getBitsPerSample() { - //TODO: can it really be different in such an MP3 ? I think not. - return 16; - } - - /** - * @return the sampling rate as string - */ - public String getSampleRate() { - return String.valueOf(mp3FrameHeader.getSamplingRate()); - } - - /** - * @return MPEG Version (1-3) - */ - public String getMpegVersion() { - return mp3FrameHeader.getVersionAsString(); - } - - /** - * @return MPEG Layer (1-3) - */ - public String getMpegLayer() { - return mp3FrameHeader.getLayerAsString(); - } - - /** - * @return the format of the audio (i.e. MPEG-1 Layer3) - */ - public String getFormat() { - return mp3FrameHeader.getVersionAsString() + " " + mp3FrameHeader.getLayerAsString(); - } - - /** - * @return the Channel Mode such as Stero or Mono - */ - public String getChannels() { - return mp3FrameHeader.getChannelModeAsString(); - } - - /** - * @return Emphasis - */ - public String getEmphasis() { - return mp3FrameHeader.getEmphasisAsString(); - } - - /** - * @return if the bitrate is variable, Xing header takes precedence if we have one - */ - public boolean isVariableBitRate() { - if (mp3XingFrame != null) { - return mp3XingFrame.isVbr(); - } else if (mp3VbriFrame != null) { - return mp3VbriFrame.isVbr(); - } else { - return mp3FrameHeader.isVariableBitRate(); - } - } - - public boolean isProtected() { - return mp3FrameHeader.isProtected(); - } - - public boolean isPrivate() { - return mp3FrameHeader.isPrivate(); - } - - public boolean isCopyrighted() { - return mp3FrameHeader.isCopyrighted(); - } - - public boolean isOriginal() { - return mp3FrameHeader.isOriginal(); - } - - public boolean isPadding() { - return mp3FrameHeader.isPadding(); - } - - public boolean isLossless() { - return false; - } - - /** - * @return encoder - */ - public String getEncoder() { - return encoder; - } - - /** - * Set the size of the file, required in some calculations - * - * @param fileSize - */ - protected void setFileSize(long fileSize) { - this.fileSize = fileSize; - } - - - /** - * @return a string representation - */ - public String toString() { - String s = "fileSize:" + fileSize - + " encoder:" + encoder - + " startByte:" + Hex.asHex(startByte) - + " numberOfFrames:" + numberOfFrames - + " numberOfFramesEst:" + numberOfFramesEstimate - + " timePerFrame:" + timePerFrame - + " bitrate:" + bitrate - + " trackLength:" + getTrackLengthAsString(); - - if (this.mp3FrameHeader != null) { - s += mp3FrameHeader.toString(); - } else { - s += " mpegframeheader:false"; - } - - if (this.mp3XingFrame != null) { - s += mp3XingFrame.toString(); - } else { - s += " mp3XingFrame:false"; - } - - if (this.mp3VbriFrame != null) { - s += mp3VbriFrame.toString(); - } else { - s += " mp3VbriFrame:false"; - } - return s; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp3/MP3File.java b/src/main/java/org/jaudiotagger/audio/mp3/MP3File.java deleted file mode 100644 index 9818e4a..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/MP3File.java +++ /dev/null @@ -1,933 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: MP3File.java 1086 2013-01-31 16:38:48Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.logging.*; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagException; -import org.jaudiotagger.tag.TagNotFoundException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.*; -import org.jaudiotagger.tag.lyrics3.AbstractLyrics3; -import org.jaudiotagger.tag.reference.ID3V2Version; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Level; - -/** - * This class represents a physical MP3 File - */ -public class MP3File extends AudioFile { - /* Load ID3V1tag if exists */ - public static final int LOAD_IDV1TAG = 2; - /* Load ID3V2tag if exists */ - public static final int LOAD_IDV2TAG = 4; - /** - * This option is currently ignored - */ - public static final int LOAD_LYRICS3 = 8; - public static final int LOAD_ALL = LOAD_IDV1TAG | LOAD_IDV2TAG | LOAD_LYRICS3; - private static final int MINIMUM_FILESIZE = 150; - protected static AbstractTagDisplayFormatter tagFormatter; - /** - * the ID3v2 tag that this file contains. - */ - private AbstractID3v2Tag id3v2tag = null; - /** - * Representation of the idv2 tag as a idv24 tag - */ - private ID3v24Tag id3v2Asv24tag = null; - /** - * The Lyrics3 tag that this file contains. - */ - private AbstractLyrics3 lyrics3tag = null; - /** - * The ID3v1 tag that this file contains. - */ - private ID3v1Tag id3v1tag = null; - - /** - * Creates a new empty MP3File datatype that is not associated with a - * specific file. - */ - public MP3File() { - } - - /** - * Creates a new MP3File datatype and parse the tag from the given filename. - * - * @param filename MP3 file - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(String filename) throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - this(new File(filename)); - } - - /** - * Creates a new MP3File dataType and parse the tag from the given file - * Object, files must be writable to use this constructor. - * - * @param file MP3 file - * @param loadOptions decide what tags to load - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(File file, int loadOptions) throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - this(file, loadOptions, false); - } - - /** - * Creates a new MP3File dataType and parse the tag from the given file - * Object, files can be opened read only if required. - * - * @param file MP3 file - * @param loadOptions decide what tags to load - * @param readOnly causes the files to be opened readonly - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(File file, int loadOptions, boolean readOnly) throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - RandomAccessFile newFile = null; - try { - this.file = file; - - //Check File accessibility - newFile = checkFilePermissions(file, readOnly); - - //Read ID3v2 tag size (if tag exists) to allow audioHeader parsing to skip over tag - long tagSizeReportedByHeader = AbstractID3v2Tag.getV2TagSizeIfExists(file); - logger.config("TagHeaderSize:" + Hex.asHex(tagSizeReportedByHeader)); - audioHeader = new MP3AudioHeader(file, tagSizeReportedByHeader); - - //If the audio header is not straight after the end of the tag then search from start of file - if (tagSizeReportedByHeader != ((MP3AudioHeader) audioHeader).getMp3StartByte()) { - logger.config("First header found after tag:" + audioHeader); - audioHeader = checkAudioStart(tagSizeReportedByHeader, (MP3AudioHeader) audioHeader); - } - - //Read v1 tags (if any) - readV1Tag(file, newFile, loadOptions); - - //Read v2 tags (if any) - readV2Tag(file, loadOptions, (int) ((MP3AudioHeader) audioHeader).getMp3StartByte()); - - //If we have a v2 tag use that, if we do not but have v1 tag use that - //otherwise use nothing - //TODO:if have both should we merge - //rather than just returning specific ID3v22 tag, would it be better to return v24 version ? - if (this.getID3v2Tag() != null) { - tag = this.getID3v2Tag(); - } else if (id3v1tag != null) { - tag = id3v1tag; - } - } finally { - if (newFile != null) { - newFile.close(); - } - } - } - - /** - * Creates a new MP3File datatype and parse the tag from the given file - * Object. - * - * @param file MP3 file - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - * @throws org.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(File file) throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - this(file, LOAD_ALL); - } - - private static void createXMLStructureFormatter() { - tagFormatter = new XMLTagDisplayFormatter(); - } - - private static void createPlainTextStructureFormatter() { - tagFormatter = new PlainTextTagDisplayFormatter(); - } - - public static AbstractTagDisplayFormatter getStructureFormatter() { - return tagFormatter; - } - - /** - * Read v1 tag - * - * @param file - * @param newFile - * @param loadOptions - * @throws IOException - */ - private void readV1Tag(File file, RandomAccessFile newFile, int loadOptions) throws IOException { - if ((loadOptions & LOAD_IDV1TAG) != 0) { - logger.finer("Attempting to read id3v1tags"); - try { - id3v1tag = new ID3v11Tag(newFile, file.getName()); - } catch (TagNotFoundException ex) { - logger.config("No ids3v11 tag found"); - } - - try { - if (id3v1tag == null) { - id3v1tag = new ID3v1Tag(newFile, file.getName()); - } - } catch (TagNotFoundException ex) { - logger.config("No id3v1 tag found"); - } - } - } - - /** - * Read V2tag if exists - *

    - * TODO:shouldn't we be handing TagExceptions:when will they be thrown - * - * @param file - * @param loadOptions - * @throws IOException - * @throws TagException - */ - private void readV2Tag(File file, int loadOptions, int startByte) throws IOException, TagException { - //We know where the actual Audio starts so load all the file from start to that point into - //a buffer then we can read the IDv2 information without needing any more File I/O - if (startByte >= AbstractID3v2Tag.TAG_HEADER_LENGTH) { - logger.finer("Attempting to read id3v2tags"); - FileInputStream fis = null; - FileChannel fc = null; - ByteBuffer bb; - try { - fis = new FileInputStream(file); - fc = fis.getChannel(); - bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, startByte); - } - //#JAUDIOTAGGER-419:If reading networked file map can fail so just copy bytes instead - catch (IOException ioe) { - bb = ByteBuffer.allocate(startByte); - fc.read(bb, 0); - } finally { - if (fc != null) { - fc.close(); - } - - if (fis != null) { - fis.close(); - } - } - - try { - bb.rewind(); - - if ((loadOptions & LOAD_IDV2TAG) != 0) { - logger.config("Attempting to read id3v2tags"); - try { - this.setID3v2Tag(new ID3v24Tag(bb, file.getName())); - } catch (TagNotFoundException ex) { - logger.config("No id3v24 tag found"); - } - - try { - if (id3v2tag == null) { - this.setID3v2Tag(new ID3v23Tag(bb, file.getName())); - } - } catch (TagNotFoundException ex) { - logger.config("No id3v23 tag found"); - } - - try { - if (id3v2tag == null) { - this.setID3v2Tag(new ID3v22Tag(bb, file.getName())); - } - } catch (TagNotFoundException ex) { - logger.config("No id3v22 tag found"); - } - } - } finally { - bb.clear(); - } - } else { - logger.config("Not enough room for valid id3v2 tag:" + startByte); - } - } - - /** - * Read lyrics3 Tag - *

    - * TODO:not working - * - * @param file - * @param newFile - * @param loadOptions - * @throws IOException - */ - private void readLyrics3Tag(File file, RandomAccessFile newFile, int loadOptions) throws IOException { - /*if ((loadOptions & LOAD_LYRICS3) != 0) - { - try - { - lyrics3tag = new Lyrics3v2(newFile); - } - catch (TagNotFoundException ex) - { - } - try - { - if (lyrics3tag == null) - { - lyrics3tag = new Lyrics3v1(newFile); - } - } - catch (TagNotFoundException ex) - { - } - } - */ - } - - /** - * @param startByte - * @param endByte - * @return true if all the bytes between in the file between startByte and endByte are null, false - * otherwise - * @throws Exception - */ - private boolean isFilePortionNull(int startByte, int endByte) throws IOException { - logger.config("Checking file portion:" + Hex.asHex(startByte) + ":" + Hex.asHex(endByte)); - FileInputStream fis = null; - FileChannel fc = null; - try { - fis = new FileInputStream(file); - fc = fis.getChannel(); - fc.position(startByte); - ByteBuffer bb = ByteBuffer.allocateDirect(endByte - startByte); - fc.read(bb); - while (bb.hasRemaining()) { - if (bb.get() != 0) { - return false; - } - } - } finally { - if (fc != null) { - fc.close(); - } - - if (fis != null) { - fis.close(); - } - } - return true; - } - - /** - * Regets the audio header starting from start of file, and write appropriate logging to indicate - * potential problem to user. - * - * @param startByte - * @param firstHeaderAfterTag - * @return - * @throws IOException - * @throws InvalidAudioFrameException - */ - private MP3AudioHeader checkAudioStart(long startByte, MP3AudioHeader firstHeaderAfterTag) throws IOException, InvalidAudioFrameException { - MP3AudioHeader headerOne; - MP3AudioHeader headerTwo; - - logger.warning(ErrorMessage.MP3_ID3TAG_LENGTH_INCORRECT.getMsg(file.getPath(), Hex.asHex(startByte), Hex.asHex(firstHeaderAfterTag.getMp3StartByte()))); - - //because we cant agree on start location we reread the audioheader from the start of the file, at least - //this way we cant overwrite the audio although we might overwrite part of the tag if we write this file - //back later - headerOne = new MP3AudioHeader(file, 0); - logger.config("Checking from start:" + headerOne); - - //Although the id3 tag size appears to be incorrect at least we have found the same location for the start - //of audio whether we start searching from start of file or at the end of the alleged of file so no real - //problem - if (firstHeaderAfterTag.getMp3StartByte() == headerOne.getMp3StartByte()) { - logger.config(ErrorMessage.MP3_START_OF_AUDIO_CONFIRMED.getMsg(file.getPath(), - Hex.asHex(headerOne.getMp3StartByte()))); - return firstHeaderAfterTag; - } else { - - //We get a different value if read from start, can't guarantee 100% correct lets do some more checks - logger.config((ErrorMessage.MP3_RECALCULATED_POSSIBLE_START_OF_MP3_AUDIO.getMsg(file.getPath(), - Hex.asHex(headerOne.getMp3StartByte())))); - - //Same frame count so probably both audio headers with newAudioHeader being the first one - if (firstHeaderAfterTag.getNumberOfFrames() == headerOne.getNumberOfFrames()) { - logger.warning((ErrorMessage.MP3_RECALCULATED_START_OF_MP3_AUDIO.getMsg(file.getPath(), - Hex.asHex(headerOne.getMp3StartByte())))); - return headerOne; - } - - //If the size reported by the tag header is a little short and there is only nulls between the recorded value - //and the start of the first audio found then we stick with the original header as more likely that currentHeader - //DataInputStream not really a header - if (isFilePortionNull((int) startByte, (int) firstHeaderAfterTag.getMp3StartByte())) { - return firstHeaderAfterTag; - } - - //Skip to the next header (header 2, counting from start of file) - headerTwo = new MP3AudioHeader(file, headerOne.getMp3StartByte() - + headerOne.mp3FrameHeader.getFrameLength()); - - //It matches the header we found when doing the original search from after the ID3Tag therefore it - //seems that newAudioHeader was a false match and the original header was correct - if (headerTwo.getMp3StartByte() == firstHeaderAfterTag.getMp3StartByte()) { - logger.warning((ErrorMessage.MP3_START_OF_AUDIO_CONFIRMED.getMsg(file.getPath(), - Hex.asHex(firstHeaderAfterTag.getMp3StartByte())))); - return firstHeaderAfterTag; - } - - //It matches the frameCount the header we just found so lends weight to the fact that the audio does indeed start at new header - //however it maybe that neither are really headers and just contain the same data being misrepresented as headers. - if (headerTwo.getNumberOfFrames() == headerOne.getNumberOfFrames()) { - logger.warning((ErrorMessage.MP3_RECALCULATED_START_OF_MP3_AUDIO.getMsg(file.getPath(), - Hex.asHex(headerOne.getMp3StartByte())))); - return headerOne; - } - ///Doesnt match the frameCount lets go back to the original header - else { - logger.warning((ErrorMessage.MP3_RECALCULATED_START_OF_MP3_AUDIO.getMsg(file.getPath(), - Hex.asHex(firstHeaderAfterTag.getMp3StartByte())))); - return firstHeaderAfterTag; - } - } - } - - /** - * Used by tags when writing to calculate the location of the music file - * - * @param file - * @return the location within the file that the audio starts - * @throws java.io.IOException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public long getMP3StartByte(File file) throws InvalidAudioFrameException, IOException { - try { - //Read ID3v2 tag size (if tag exists) to allow audio header parsing to skip over tag - long startByte = AbstractID3v2Tag.getV2TagSizeIfExists(file); - - MP3AudioHeader audioHeader = new MP3AudioHeader(file, startByte); - if (startByte != audioHeader.getMp3StartByte()) { - logger.config("First header found after tag:" + audioHeader); - audioHeader = checkAudioStart(startByte, audioHeader); - } - return audioHeader.getMp3StartByte(); - } catch (InvalidAudioFrameException iafe) { - throw iafe; - } catch (IOException ioe) { - throw ioe; - } - } - - /** - * Returns true if this datatype contains a Lyrics3 tag - * TODO disabled until Lyrics3 fixed - * @return true if this datatype contains a Lyrics3 tag - */ - /* - public boolean hasLyrics3Tag() - { - return (lyrics3tag != null); - } - */ - - /** - * Extracts the raw ID3v2 tag data into a file. - *

    - * This provides access to the raw data before manipulation, the data is written from the start of the file - * to the start of the Audio Data. This is primarily useful for manipulating corrupted tags that are not - * (fully) loaded using the standard methods. - * - * @param outputFile to write the data to - * @return - * @throws TagNotFoundException - * @throws IOException - */ - public File extractID3v2TagDataIntoFile(File outputFile) throws TagNotFoundException, IOException { - int startByte = (int) ((MP3AudioHeader) audioHeader).getMp3StartByte(); - if (startByte >= 0) { - - //Read byte into buffer - FileInputStream fis = new FileInputStream(file); - FileChannel fc = fis.getChannel(); - ByteBuffer bb = ByteBuffer.allocate(startByte); - fc.read(bb); - - //Write bytes to outputFile - FileOutputStream out = new FileOutputStream(outputFile); - out.write(bb.array()); - out.close(); - fc.close(); - fis.close(); - return outputFile; - } - throw new TagNotFoundException("There is no ID3v2Tag data in this file"); - } - - /** - * Return audio header - * - * @return - */ - public MP3AudioHeader getMP3AudioHeader() { - return (MP3AudioHeader) getAudioHeader(); - } - - /** - * Returns true if this datatype contains an Id3v1 tag - * - * @return true if this datatype contains an Id3v1 tag - */ - public boolean hasID3v1Tag() { - return (id3v1tag != null); - } - - /** - * Returns true if this datatype contains an Id3v2 tag - * - * @return true if this datatype contains an Id3v2 tag - */ - public boolean hasID3v2Tag() { - return (id3v2tag != null); - } - - /** - * Sets the ID3v1(_1)tag to the tag provided as an argument. - * - * @param id3v1tag - */ - public void setID3v1Tag(ID3v1Tag id3v1tag) { - logger.config("setting tagv1:v1 tag"); - this.id3v1tag = id3v1tag; - } - - public void setID3v1Tag(Tag id3v1tag) { - logger.config("setting tagv1:v1 tag"); - this.id3v1tag = (ID3v1Tag) id3v1tag; - } - - /** - * Returns the ID3v1 tag for this dataType. - * - * @return the ID3v1 tag for this dataType - */ - public ID3v1Tag getID3v1Tag() { - return id3v1tag; - } - - /** - * Sets the ID3v1 tag for this dataType. A new - * ID3v1_1 dataType is created from the argument and then used - * here. - * - * @param mp3tag Any MP3Tag dataType can be used and will be converted into a - * new ID3v1_1 dataType. - */ - public void setID3v1Tag(AbstractTag mp3tag) { - logger.config("setting tagv1:abstract"); - id3v1tag = new ID3v11Tag(mp3tag); - } - - /** - * Sets the ID3v2 tag for this dataType. A new - * ID3v2_4 dataType is created from the argument and then used - * here. - * - * @param mp3tag Any MP3Tag dataType can be used and will be converted into a - * new ID3v2_4 dataType. - */ - public void setID3v2Tag(AbstractTag mp3tag) { - id3v2tag = new ID3v24Tag(mp3tag); - - } - - /** - * Set v2 tag ,don't need to set v24 tag because saving - *

    - * - * @param id3v2tag - */ - //TODO temp its rather messy - public void setID3v2TagOnly(AbstractID3v2Tag id3v2tag) { - this.id3v2tag = id3v2tag; - this.id3v2Asv24tag = null; - } - - /** - * Sets the Lyrics3 tag for this dataType. A new - * Lyrics3v2 dataType is created from the argument and then - * - * used here. - * - * @param mp3tag Any MP3Tag dataType can be used and will be converted into a - * new Lyrics3v2 dataType. - */ - /* - public void setLyrics3Tag(AbstractTag mp3tag) - { - lyrics3tag = new Lyrics3v2(mp3tag); - } - */ - - /** - * - * - * @param lyrics3tag - */ - /* - public void setLyrics3Tag(AbstractLyrics3 lyrics3tag) - { - this.lyrics3tag = lyrics3tag; - } - */ - - /** - * Returns the ID3v1 tag for this datatype. - * - * @return the ID3v1 tag for this datatype - */ - /* - public AbstractLyrics3 getLyrics3Tag() - { - return lyrics3tag; - } - */ - - /** - * Returns the ID3v2 tag for this datatype. - * - * @return the ID3v2 tag for this datatype - */ - public AbstractID3v2Tag getID3v2Tag() { - return id3v2tag; - } - - /** - * Sets the v2 tag to the v2 tag provided as an argument. - * Also store a v24 version of tag as v24 is the interface to be used - * when talking with client applications. - * - * @param id3v2tag - */ - public void setID3v2Tag(AbstractID3v2Tag id3v2tag) { - this.id3v2tag = id3v2tag; - if (id3v2tag instanceof ID3v24Tag) { - this.id3v2Asv24tag = (ID3v24Tag) this.id3v2tag; - } else { - this.id3v2Asv24tag = new ID3v24Tag(id3v2tag); - } - } - - /** - * @return a representation of tag as v24 - */ - public ID3v24Tag getID3v2TagAsv24() { - return id3v2Asv24tag; - } - - /** - * Remove tag from file - * - * @param mp3tag - * @throws FileNotFoundException - * @throws IOException - */ - public void delete(AbstractTag mp3tag) throws IOException { - RandomAccessFile raf = new RandomAccessFile(this.file, "rws"); - mp3tag.delete(raf); - raf.close(); - if (mp3tag instanceof ID3v1Tag) { - id3v1tag = null; - } - - if (mp3tag instanceof AbstractID3v2Tag) { - id3v2tag = null; - } - } - - /** - * Saves the tags in this dataType to the file referred to by this dataType. - * - * @throws IOException on any I/O error - * @throws TagException on any exception generated by this library. - */ - public void save() throws IOException, TagException { - save(this.file); - } - - /** - * Overridden for compatibility with merged code - * - * @throws CannotWriteException - */ - public void commit() throws CannotWriteException { - try { - save(); - } catch (IOException ioe) { - throw new CannotWriteException(ioe); - } catch (TagException te) { - throw new CannotWriteException(te); - } - } - - /** - * Check can write to file - * - * @param file - * @throws IOException - */ - public void precheck(File file) throws IOException { - if (!file.exists()) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName())); - throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName())); - } - - if (!file.canWrite()) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(file.getName())); - throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(file.getName())); - } - - if (file.length() <= MINIMUM_FILESIZE) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getName())); - throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getName())); - } - } - - /** - * Saves the tags in this dataType to the file argument. It will be saved as - * TagConstants.MP3_FILE_SAVE_WRITE - * - * @param fileToSave file to save the this dataTypes tags to - * @throws FileNotFoundException if unable to find file - * @throws IOException on any I/O error - */ - public void save(File fileToSave) throws IOException { - //Ensure we are dealing with absolute filepaths not relative ones - File file = fileToSave.getAbsoluteFile(); - - logger.config("Saving : " + file.getPath()); - - //Checks before starting write - precheck(file); - - RandomAccessFile rfile = null; - try { - //ID3v2 Tag - if (TagOptionSingleton.getInstance().isId3v2Save()) { - if (id3v2tag == null) { - rfile = new RandomAccessFile(file, "rws"); - (new ID3v24Tag()).delete(rfile); - (new ID3v23Tag()).delete(rfile); - (new ID3v22Tag()).delete(rfile); - logger.config("Deleting ID3v2 tag:" + file.getName()); - rfile.close(); - } else { - logger.config("Writing ID3v2 tag:" + file.getName()); - id3v2tag.write(file, ((MP3AudioHeader) this.getAudioHeader()).getMp3StartByte()); - } - } - rfile = new RandomAccessFile(file, "rws"); - - //Lyrics 3 Tag - if (TagOptionSingleton.getInstance().isLyrics3Save()) { - if (lyrics3tag != null) { - lyrics3tag.write(rfile); - } - } - //ID3v1 tag - if (TagOptionSingleton.getInstance().isId3v1Save()) { - logger.config("Processing ID3v1"); - if (id3v1tag == null) { - logger.config("Deleting ID3v1"); - (new ID3v1Tag()).delete(rfile); - } else { - logger.config("Saving ID3v1"); - id3v1tag.write(rfile); - } - } - } catch (FileNotFoundException ex) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()), ex); - throw ex; - } catch (IOException iex) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(file.getName(), iex.getMessage()), iex); - throw iex; - } catch (RuntimeException re) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(file.getName(), re.getMessage()), re); - throw re; - } finally { - if (rfile != null) { - rfile.close(); - } - } - } - - /** - * Displays MP3File Structure - */ - public String displayStructureAsXML() { - createXMLStructureFormatter(); - tagFormatter.openHeadingElement("file", this.getFile().getAbsolutePath()); - if (this.getID3v1Tag() != null) { - this.getID3v1Tag().createStructure(); - } - if (this.getID3v2Tag() != null) { - this.getID3v2Tag().createStructure(); - } - tagFormatter.closeHeadingElement("file"); - return tagFormatter.toString(); - } - - /** - * Displays MP3File Structure - */ - public String displayStructureAsPlainText() { - createPlainTextStructureFormatter(); - tagFormatter.openHeadingElement("file", this.getFile().getAbsolutePath()); - if (this.getID3v1Tag() != null) { - this.getID3v1Tag().createStructure(); - } - if (this.getID3v2Tag() != null) { - this.getID3v2Tag().createStructure(); - } - tagFormatter.closeHeadingElement("file"); - return tagFormatter.toString(); - } - - /** - * Set the Tag - *

    - * If the parameter tag is a v1tag then the v1 tag is set if v2tag then the v2tag. - * - * @param tag - */ - public void setTag(Tag tag) { - this.tag = tag; - if (tag instanceof ID3v1Tag) { - setID3v1Tag((ID3v1Tag) tag); - } else { - setID3v2Tag((AbstractID3v2Tag) tag); - } - } - - - /** - * Create Default Tag - * - * @return - */ - @Override - public Tag createDefaultTag() { - if (TagOptionSingleton.getInstance().getID3V2Version() == ID3V2Version.ID3_V24) { - return new ID3v24Tag(); - } else if (TagOptionSingleton.getInstance().getID3V2Version() == ID3V2Version.ID3_V23) { - return new ID3v23Tag(); - } else if (TagOptionSingleton.getInstance().getID3V2Version() == ID3V2Version.ID3_V22) { - return new ID3v22Tag(); - } - //Default in case not set somehow - return new ID3v24Tag(); - } - - /** - * Convert tag from current version to another as specified by id3V2Version - * - * @return - */ - public Tag convertTag(Tag tag, ID3V2Version id3V2Version) { - if (tag instanceof ID3v24Tag) { - switch (id3V2Version) { - case ID3_V22: - return new ID3v22Tag((ID3v24Tag) tag); - case ID3_V23: - return new ID3v23Tag((ID3v24Tag) tag); - case ID3_V24: - return tag; - } - } else if (tag instanceof ID3v23Tag) { - switch (id3V2Version) { - case ID3_V22: - return new ID3v22Tag((ID3v23Tag) tag); - case ID3_V23: - return tag; - case ID3_V24: - return new ID3v24Tag((ID3v23Tag) tag); - } - } else if (tag instanceof ID3v22Tag) { - switch (id3V2Version) { - case ID3_V22: - return tag; - case ID3_V23: - return new ID3v23Tag((ID3v22Tag) tag); - case ID3_V24: - return new ID3v24Tag((ID3v22Tag) tag); - } - } - return tag; - } - - /** - * Overidden to only consider ID3v2 Tag - * - * @return - */ - @Override - public Tag getTagOrCreateDefault() { - Tag tag = getID3v2Tag(); - if (tag == null) { - return createDefaultTag(); - } - return tag; - } - - - /** - * Get the ID3v2 tag and convert to preferred version or if the file doesn't have one at all - * create a default tag of preferred version and set it. The file may already contain a ID3v1 tag but because - * this is not terribly useful the v1tag is not considered for this problem. - * - * @return - */ - @Override - public Tag getTagAndConvertOrCreateAndSetDefault() { - Tag tag = getTagOrCreateDefault(); - tag = convertTag(tag, TagOptionSingleton.getInstance().getID3V2Version()); - setTag(tag); - return tag; - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/mp3/MP3FileReader.java b/src/main/java/org/jaudiotagger/audio/mp3/MP3FileReader.java deleted file mode 100644 index 23f06db..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/MP3FileReader.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagException; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Read Mp3 Info (retrofitted to entagged ,done differently to entagged which is why some methods throw RuntimeException) - * because done elsewhere - */ -public class MP3FileReader extends AudioFileReader { - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException { - throw new RuntimeException("MP3FileReader.getEncodingInfo should be called"); - } - - protected Tag getTag(RandomAccessFile raf) throws CannotReadException, IOException { - throw new RuntimeException("MP3FileReader.getEncodingInfo should be called"); - } - - /** - * @param f - * @return - */ - //Override because we read mp3s differently to the entagged code - public AudioFile read(File f) throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - MP3File mp3File = new MP3File(f, MP3File.LOAD_IDV1TAG | MP3File.LOAD_IDV2TAG, true); - return mp3File; - } - - /** - * Read - * - * @param f - * @return - * @throws ReadOnlyFileException thrown if the file is not writable - * @throws org.jaudiotagger.tag.TagException - * @throws java.io.IOException - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public AudioFile readMustBeWritable(File f) throws IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException { - MP3File mp3File = new MP3File(f, MP3File.LOAD_IDV1TAG | MP3File.LOAD_IDV2TAG, false); - return mp3File; - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/mp3/MP3FileWriter.java b/src/main/java/org/jaudiotagger/audio/mp3/MP3FileWriter.java deleted file mode 100644 index 75f9e7d..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/MP3FileWriter.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.generic.AudioFileWriter; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Write Mp3 Info (retrofitted to entagged ,done differently to entagged which is why some methods throw RuntimeException) - * because done elsewhere - */ -public class MP3FileWriter extends AudioFileWriter { - public void deleteTag(AudioFile f) throws CannotWriteException { - //Because audio file is an instanceof MP3File this directs it to save - //taking into account if the tag has been sent to null in which case it will be deleted - f.commit(); - } - - public void writeFile(AudioFile f) throws CannotWriteException { - //Because audio file is an instanceof MP3File this directs it to save - f.commit(); - } - - /** - * Delete the Id3v1 and ID3v2 tags from file - * - * @param af - * @throws CannotReadException - * @throws CannotWriteException - */ - @Override - public synchronized void delete(AudioFile af) throws CannotReadException, CannotWriteException { - ((MP3File) af).setID3v1Tag(null); - ((MP3File) af).setID3v2Tag(null); - af.commit(); - } - - protected void writeTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException { - throw new RuntimeException("MP3FileReaderwriteTag should not be called"); - } - - protected void deleteTag(RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotWriteException, IOException { - throw new RuntimeException("MP3FileReader.getEncodingInfo should be called"); - } -} - - diff --git a/src/main/java/org/jaudiotagger/audio/mp3/MPEGFrameHeader.java b/src/main/java/org/jaudiotagger/audio/mp3/MPEGFrameHeader.java deleted file mode 100644 index 29251be..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/MPEGFrameHeader.java +++ /dev/null @@ -1,790 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: MPEGFrameHeader.java 970 2011-05-06 12:34:36Z paultaylor $ - * Date :${DATE} - *

    - * Jaikoz Copyright Copyright (C) 2003 -2005 JThink Ltd - */ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.FileConstants; -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import org.jaudiotagger.logging.AbstractTagDisplayFormatter; - -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; - - -/** - * Represents a MPEGFrameHeader, an MP3 is made up of a number of frames each frame starts with a four - * byte frame header. - */ -@SuppressWarnings({"PointlessArithmeticExpression"}) -public class MPEGFrameHeader { - public static final int HEADER_SIZE = 4; - /** - * Sync Value to identify the start of an MPEGFrame - */ - public static final int SYNC_SIZE = 2; - public static final int SYNC_BYTE1 = 0xFF; - public static final int SYNC_BYTE2 = 0xE0; - public static final int SYNC_BIT_ANDSAMPING_BYTE3 = 0xFC; - /** - * Constants for MPEG Version - */ - public static final Map mpegVersionMap = new HashMap(); - public final static int VERSION_2_5 = 0; - public final static int VERSION_2 = 2; - public final static int VERSION_1 = 3; - /** - * Constants for MPEG Layer - */ - public static final Map mpegLayerMap = new HashMap(); - public final static int LAYER_I = 3; - public final static int LAYER_II = 2; - public final static int LAYER_III = 1; - /** - * Slot Size is dependent on Layer - */ - public final static int LAYER_I_SLOT_SIZE = 4; - public final static int LAYER_II_SLOT_SIZE = 1; - public final static int LAYER_III_SLOT_SIZE = 1; - /** - * Constants for Channel mode - */ - public static final Map modeMap = new HashMap(); - public final static int MODE_STEREO = 0; - public final static int MODE_JOINT_STEREO = 1; - public final static int MODE_DUAL_CHANNEL = 2; - public final static int MODE_MONO = 3; - public final static int EMPHASIS_NONE = 0; - public final static int EMPHASIS_5015MS = 1; - public final static int EMPHASIS_RESERVED = 2; - public final static int EMPHASIS_CCITT = 3; - /** - * Constants for MP3 Frame header, each frame has a basic header of - * 4 bytes - */ - private static final int BYTE_1 = 0; - private static final int BYTE_2 = 1; - private static final int BYTE_3 = 2; - private static final int BYTE_4 = 3; - private static final byte[] header = new byte[HEADER_SIZE]; - /** - * Bit Rates, the setBitrate varies for different Version and Layer - */ - private static final Map bitrateMap = new HashMap(); - /** - * Constants for Emphasis - */ - private static final Map emphasisMap = new HashMap(); - private static final Map modeExtensionMap = new HashMap(); - private final static int MODE_EXTENSION_NONE = 0; - private final static int MODE_EXTENSION_ONE = 1; - private final static int MODE_EXTENSION_TWO = 2; - private final static int MODE_EXTENSION_THREE = 3; - private static final Map modeExtensionLayerIIIMap = new HashMap(); - private final static int MODE_EXTENSION_OFF_OFF = 0; - private final static int MODE_EXTENSION_ON_OFF = 1; - private final static int MODE_EXTENSION_OFF_ON = 2; - private final static int MODE_EXTENSION_ON_ON = 3; - /** - * Sampling Rate in Hz - */ - private static final Map> samplingRateMap = new HashMap>(); - private static final Map samplingV1Map = new HashMap(); - private static final Map samplingV2Map = new HashMap(); - private static final Map samplingV25Map = new HashMap(); - /* Samples Per Frame */ - private static final Map> samplesPerFrameMap = new HashMap>(); - private static final Map samplesPerFrameV1Map = new HashMap(); - private static final Map samplesPerFrameV2Map = new HashMap(); - private static final Map samplesPerFrameV25Map = new HashMap(); - private static final int SCALE_BY_THOUSAND = 1000; - private static final int LAYER_I_FRAME_SIZE_COEFFICIENT = 12; - private static final int LAYER_II_FRAME_SIZE_COEFFICIENT = 144; - private static final int LAYER_III_FRAME_SIZE_COEFFICIENT = 144; - /** - * MP3 Frame Header bit mask - */ - private static final int MASK_MP3_ID = FileConstants.BIT3; - /** - * MP3 version, confusingly for MP3s the version is 1. - */ - private static final int MASK_MP3_VERSION = FileConstants.BIT4 | FileConstants.BIT3; - /** - * MP3 Layer, for MP3s the Layer is 3 - */ - private static final int MASK_MP3_LAYER = FileConstants.BIT2 | FileConstants.BIT1; - /** - * Does it include a CRC Checksum at end of header, this can be used to check the header. - */ - private static final int MASK_MP3_PROTECTION = FileConstants.BIT0; - /** - * The setBitrate of this MP3 - */ - private static final int MASK_MP3_BITRATE = FileConstants.BIT7 | FileConstants.BIT6 | FileConstants.BIT5 | FileConstants.BIT4; - /** - * The sampling/frequency rate - */ - private static final int MASK_MP3_FREQUENCY = FileConstants.BIT3 + FileConstants.BIT2; - /** - * An extra padding bit is sometimes used to make sure frames are exactly the right length - */ - private static final int MASK_MP3_PADDING = FileConstants.BIT1; - /** - * Private bit set, for application specific - */ - private static final int MASK_MP3_PRIVACY = FileConstants.BIT0; - /** - * Channel Mode, Stero/Mono/Dual Channel - */ - private static final int MASK_MP3_MODE = FileConstants.BIT7 | FileConstants.BIT6; - /** - * MP3 Frame Header bit mask - */ - private static final int MASK_MP3_MODE_EXTENSION = FileConstants.BIT5 | FileConstants.BIT4; - /** - * MP3 Frame Header bit mask - */ - private static final int MASK_MP3_COPY = FileConstants.BIT3; - /** - * MP3 Frame Header bit mask - */ - private static final int MASK_MP3_HOME = FileConstants.BIT2; - /** - * MP3 Frame Header bit mask - */ - private static final int MASK_MP3_EMPHASIS = FileConstants.BIT1 | FileConstants.BIT0; - - static { - mpegVersionMap.put(VERSION_2_5, "MPEG-2.5"); - mpegVersionMap.put(VERSION_2, "MPEG-2"); - mpegVersionMap.put(VERSION_1, "MPEG-1"); - } - - static { - mpegLayerMap.put(LAYER_I, "Layer 1"); - mpegLayerMap.put(LAYER_II, "Layer 2"); - mpegLayerMap.put(LAYER_III, "Layer 3"); - } - - static { - // MPEG-1, Layer I (E) - bitrateMap.put(0x1E, 32); - bitrateMap.put(0x2E, 64); - bitrateMap.put(0x3E, 96); - bitrateMap.put(0x4E, 128); - bitrateMap.put(0x5E, 160); - bitrateMap.put(0x6E, 192); - bitrateMap.put(0x7E, 224); - bitrateMap.put(0x8E, 256); - bitrateMap.put(0x9E, 288); - bitrateMap.put(0xAE, 320); - bitrateMap.put(0xBE, 352); - bitrateMap.put(0xCE, 384); - bitrateMap.put(0xDE, 416); - bitrateMap.put(0xEE, 448); - // MPEG-1, Layer II (C) - bitrateMap.put(0x1C, 32); - bitrateMap.put(0x2C, 48); - bitrateMap.put(0x3C, 56); - bitrateMap.put(0x4C, 64); - bitrateMap.put(0x5C, 80); - bitrateMap.put(0x6C, 96); - bitrateMap.put(0x7C, 112); - bitrateMap.put(0x8C, 128); - bitrateMap.put(0x9C, 160); - bitrateMap.put(0xAC, 192); - bitrateMap.put(0xBC, 224); - bitrateMap.put(0xCC, 256); - bitrateMap.put(0xDC, 320); - bitrateMap.put(0xEC, 384); - // MPEG-1, Layer III (A) - bitrateMap.put(0x1A, 32); - bitrateMap.put(0x2A, 40); - bitrateMap.put(0x3A, 48); - bitrateMap.put(0x4A, 56); - bitrateMap.put(0x5A, 64); - bitrateMap.put(0x6A, 80); - bitrateMap.put(0x7A, 96); - bitrateMap.put(0x8A, 112); - bitrateMap.put(0x9A, 128); - bitrateMap.put(0xAA, 160); - bitrateMap.put(0xBA, 192); - bitrateMap.put(0xCA, 224); - bitrateMap.put(0xDA, 256); - bitrateMap.put(0xEA, 320); - // MPEG-2, Layer I (6) - bitrateMap.put(0x16, 32); - bitrateMap.put(0x26, 48); - bitrateMap.put(0x36, 56); - bitrateMap.put(0x46, 64); - bitrateMap.put(0x56, 80); - bitrateMap.put(0x66, 96); - bitrateMap.put(0x76, 112); - bitrateMap.put(0x86, 128); - bitrateMap.put(0x96, 144); - bitrateMap.put(0xA6, 160); - bitrateMap.put(0xB6, 176); - bitrateMap.put(0xC6, 192); - bitrateMap.put(0xD6, 224); - bitrateMap.put(0xE6, 256); - // MPEG-2, Layer II (4) - bitrateMap.put(0x14, 8); - bitrateMap.put(0x24, 16); - bitrateMap.put(0x34, 24); - bitrateMap.put(0x44, 32); - bitrateMap.put(0x54, 40); - bitrateMap.put(0x64, 48); - bitrateMap.put(0x74, 56); - bitrateMap.put(0x84, 64); - bitrateMap.put(0x94, 80); - bitrateMap.put(0xA4, 96); - bitrateMap.put(0xB4, 112); - bitrateMap.put(0xC4, 128); - bitrateMap.put(0xD4, 144); - bitrateMap.put(0xE4, 160); - // MPEG-2, Layer III (2) - bitrateMap.put(0x12, 8); - bitrateMap.put(0x22, 16); - bitrateMap.put(0x32, 24); - bitrateMap.put(0x42, 32); - bitrateMap.put(0x52, 40); - bitrateMap.put(0x62, 48); - bitrateMap.put(0x72, 56); - bitrateMap.put(0x82, 64); - bitrateMap.put(0x92, 80); - bitrateMap.put(0xA2, 96); - bitrateMap.put(0xB2, 112); - bitrateMap.put(0xC2, 128); - bitrateMap.put(0xD2, 144); - bitrateMap.put(0xE2, 160); - } - - static { - modeMap.put(MODE_STEREO, "Stereo"); - modeMap.put(MODE_JOINT_STEREO, "Joint Stereo"); - modeMap.put(MODE_DUAL_CHANNEL, "Dual"); - modeMap.put(MODE_MONO, "Mono"); - } - - static { - emphasisMap.put(EMPHASIS_NONE, "None"); - emphasisMap.put(EMPHASIS_5015MS, "5015MS"); - emphasisMap.put(EMPHASIS_RESERVED, "Reserved"); - emphasisMap.put(EMPHASIS_CCITT, "CCITT"); - } - - static { - modeExtensionMap.put(MODE_EXTENSION_NONE, "4-31"); - modeExtensionMap.put(MODE_EXTENSION_ONE, "8-31"); - modeExtensionMap.put(MODE_EXTENSION_TWO, "12-31"); - modeExtensionMap.put(MODE_EXTENSION_THREE, "16-31"); - - modeExtensionLayerIIIMap.put(MODE_EXTENSION_OFF_OFF, "off-off"); - modeExtensionLayerIIIMap.put(MODE_EXTENSION_ON_OFF, "on-off"); - modeExtensionLayerIIIMap.put(MODE_EXTENSION_OFF_ON, "off-on"); - modeExtensionLayerIIIMap.put(MODE_EXTENSION_ON_ON, "on-on"); - } - - static { - samplingV1Map.put(0, 44100); - samplingV1Map.put(1, 48000); - samplingV1Map.put(2, 32000); - - samplingV2Map.put(0, 22050); - samplingV2Map.put(1, 24000); - samplingV2Map.put(2, 16000); - - samplingV25Map.put(0, 11025); - samplingV25Map.put(1, 12000); - samplingV25Map.put(2, 8000); - - samplingRateMap.put(VERSION_1, samplingV1Map); - samplingRateMap.put(VERSION_2, samplingV2Map); - samplingRateMap.put(VERSION_2_5, samplingV25Map); - } - - static { - samplesPerFrameV1Map.put(LAYER_I, 384); - samplesPerFrameV1Map.put(LAYER_II, 1152); - samplesPerFrameV1Map.put(LAYER_III, 1152); - - samplesPerFrameV2Map.put(LAYER_I, 384); - samplesPerFrameV2Map.put(LAYER_II, 1152); - samplesPerFrameV2Map.put(LAYER_III, 576); - - samplesPerFrameV25Map.put(LAYER_I, 384); - samplesPerFrameV25Map.put(LAYER_II, 1152); - samplesPerFrameV25Map.put(LAYER_III, 576); - - samplesPerFrameMap.put(VERSION_1, samplesPerFrameV1Map); - samplesPerFrameMap.put(VERSION_2, samplesPerFrameV2Map); - samplesPerFrameMap.put(VERSION_2_5, samplesPerFrameV25Map); - - } - - private byte[] mpegBytes; - - /** - * The version of this MPEG frame (see the constants) - */ - private int version; - - private String versionAsString; - - /** - * Contains the mpeg layer of this frame (see constants) - */ - private int layer; - - private String layerAsString; - /** - * Bitrate of this frame - */ - private Integer bitRate; - - /** - * Channel Mode of this Frame (see constants) - */ - private int channelMode; - - /** - * Channel Mode of this Frame As English String - */ - private String channelModeAsString; - - /** - * Emphasis of this frame - */ - private int emphasis; - - /** - * Emphasis mode string - */ - private String emphasisAsString; - - /** - * Mode Extension - */ - private String modeExtension; - - /** - * Flag indicating if this frame has padding byte - */ - private boolean isPadding; - - /** - * Flag indicating if this frame contains copyrighted material - */ - private boolean isCopyrighted; - - /** - * Flag indicating if this frame contains original material - */ - private boolean isOriginal; - - /** - * Flag indicating if this frame is protected - */ - private boolean isProtected; - - - /** - * Flag indicating if this frame is private - */ - private boolean isPrivate; - - private Integer samplingRate; - - - /** - * Hide Constructor - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private MPEGFrameHeader() throws InvalidAudioFrameException { - - } - - /** - * Try and create a new MPEG frame with the given byte array and decodes its contents - * If decoding header causes a problem it is not a valid header - * - * @param b the array of bytes representing this mpeg frame - * @throws InvalidAudioFrameException if does not match expected format - */ - private MPEGFrameHeader(byte[] b) throws InvalidAudioFrameException { - mpegBytes = b; - setBitrate(); - setVersion(); - setLayer(); - setProtected(); - setSamplingRate(); - setPadding(); - setPrivate(); - setChannelMode(); - setModeExtension(); - setCopyrighted(); - setOriginal(); - setEmphasis(); - } - - /** - * Parse the MPEGFrameHeader of an MP3File, file pointer returns at end of the frame header - * - * @param bb the byte buffer containing the header - * @return - * @throws InvalidAudioFrameException if there is no header at this point - */ - public static MPEGFrameHeader parseMPEGHeader(ByteBuffer bb) throws InvalidAudioFrameException { - int position = bb.position(); - bb.get(header, 0, HEADER_SIZE); - bb.position(position); - MPEGFrameHeader frameHeader = new MPEGFrameHeader(header); - - return frameHeader; - } - - /** - * Gets the MPEGFrame attribute of the MPEGFrame object - * - * @param bb - * @return The mPEGFrame value - */ - public static boolean isMPEGFrame(ByteBuffer bb) { - int position = bb.position(); - return (((bb.get(position) & SYNC_BYTE1) == SYNC_BYTE1) - && ((bb.get(position + 1) & SYNC_BYTE2) == SYNC_BYTE2) - && ((bb.get(position + 2) & SYNC_BIT_ANDSAMPING_BYTE3) != SYNC_BIT_ANDSAMPING_BYTE3)); - } - - /** - * Gets the layerVersion attribute of the MPEGFrame object - * - * @return The layerVersion value - */ - public int getLayer() { - return layer; - } - - public String getLayerAsString() { - return layerAsString; - } - - /** - * Gets the copyrighted attribute of the MPEGFrame object - */ - private void setCopyrighted() { - isCopyrighted = (mpegBytes[BYTE_4] & MASK_MP3_COPY) != 0; - } - - /** - * Set the version of this frame as an int value (see constants) - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setVersion() throws InvalidAudioFrameException { - //MPEG Version - version = (byte) ((mpegBytes[BYTE_2] & MASK_MP3_VERSION) >> 3); - versionAsString = mpegVersionMap.get(version); - if (versionAsString == null) { - throw new InvalidAudioFrameException("Invalid mpeg version"); - } - } - - /** - * Sets the original attribute of the MPEGFrame object - */ - private void setOriginal() { - isOriginal = (mpegBytes[BYTE_4] & MASK_MP3_HOME) != 0; - } - - /** - * Sets the protected attribute of the MPEGFrame object - */ - private void setProtected() { - isProtected = (mpegBytes[BYTE_2] & MASK_MP3_PROTECTION) == 0x00; - } - - /** - * Sets the private attribute of the MPEGFrame object - */ - private void setPrivate() { - isPrivate = (mpegBytes[BYTE_3] & MASK_MP3_PRIVACY) != 0; - } - - /** - * Get the setBitrate of this frame - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setBitrate() throws InvalidAudioFrameException { - /* BitRate, get by checking header setBitrate bits and MPEG Version and Layer */ - int bitRateIndex = mpegBytes[BYTE_3] & MASK_MP3_BITRATE | mpegBytes[BYTE_2] & MASK_MP3_ID | mpegBytes[BYTE_2] & MASK_MP3_LAYER; - - bitRate = bitrateMap.get(bitRateIndex); - if (bitRate == null) { - throw new InvalidAudioFrameException("Invalid bitrate"); - } - } - - /** - * Set the Mpeg channel mode of this frame as a constant (see constants) - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setChannelMode() throws InvalidAudioFrameException { - channelMode = (mpegBytes[BYTE_4] & MASK_MP3_MODE) >>> 6; - channelModeAsString = modeMap.get(channelMode); - if (channelModeAsString == null) { - throw new InvalidAudioFrameException("Invalid channel mode"); - } - } - - /** - * Get the setEmphasis mode of this frame in a string representation - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setEmphasis() throws InvalidAudioFrameException { - emphasis = mpegBytes[BYTE_4] & MASK_MP3_EMPHASIS; - emphasisAsString = emphasisMap.get(emphasis); - if (getEmphasisAsString() == null) { - throw new InvalidAudioFrameException("Invalid emphasis"); - } - } - - /** - * Set whether this frame uses padding bytes - */ - private void setPadding() { - isPadding = (mpegBytes[BYTE_3] & MASK_MP3_PADDING) != 0; - } - - /** - * Get the layer version of this frame as a constant int value (see constants) - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setLayer() throws InvalidAudioFrameException { - layer = (mpegBytes[BYTE_2] & MASK_MP3_LAYER) >>> 1; - layerAsString = mpegLayerMap.get(layer); - if (layerAsString == null) { - throw new InvalidAudioFrameException("Invalid Layer"); - } - } - - /** - * Sets the string representation of the mode extension of this frame - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setModeExtension() throws InvalidAudioFrameException { - int index = (mpegBytes[BYTE_4] & MASK_MP3_MODE_EXTENSION) >> 4; - if (layer == LAYER_III) { - modeExtension = modeExtensionLayerIIIMap.get(index); - if (getModeExtension() == null) { - throw new InvalidAudioFrameException("Invalid Mode Extension"); - } - } else { - modeExtension = modeExtensionMap.get(index); - if (getModeExtension() == null) { - throw new InvalidAudioFrameException("Invalid Mode Extension"); - } - } - } - - /** - * set the sampling rate in Hz of this frame - * - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - private void setSamplingRate() throws InvalidAudioFrameException { - //Frequency - int index = (mpegBytes[BYTE_3] & MASK_MP3_FREQUENCY) >>> 2; - Map samplingRateMapForVersion = samplingRateMap.get(version); - if (samplingRateMapForVersion == null) { - throw new InvalidAudioFrameException("Invalid version"); - } - samplingRate = samplingRateMapForVersion.get(index); - if (samplingRate == null) { - throw new InvalidAudioFrameException("Invalid sampling rate"); - } - } - - /** - * Gets the number of channels - * - * @return The setChannelMode value - */ - public int getNumberOfChannels() { - switch (channelMode) { - case MODE_DUAL_CHANNEL: - return 2; - case MODE_JOINT_STEREO: - return 2; - case MODE_MONO: - return 1; - case MODE_STEREO: - return 2; - default: - return 0; - } - } - - public int getChannelMode() { - return channelMode; - } - - public String getChannelModeAsString() { - return channelModeAsString; - } - - /** - * Gets the mPEGVersion attribute of the MPEGFrame object - * - * @return The mPEGVersion value - */ - public int getVersion() { - return version; - } - - public String getVersionAsString() { - return versionAsString; - } - - /** - * Gets the paddingLength attribute of the MPEGFrame object - * - * @return The paddingLength value - */ - public int getPaddingLength() { - if (isPadding()) { - return 1; - } else { - return 0; - } - } - - public Integer getBitRate() { - return bitRate; - } - - public Integer getSamplingRate() { - return samplingRate; - } - - /* - * Gets this frame length in bytes, value should always be rounded down to the nearest byte (not rounded up) - * - * Calculation is Bitrate (scaled to bps) divided by sampling frequency (in Hz), The larger the bitrate the larger - * the frame but the more samples per second the smaller the value, also have to take into account frame padding - * Have to multiple by a coefficient constant depending upon the layer it is encoded in, - - */ - public int getFrameLength() { - switch (version) { - case VERSION_2: - case VERSION_2_5: - switch (layer) { - case LAYER_I: - return (LAYER_I_FRAME_SIZE_COEFFICIENT * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength()) * LAYER_I_SLOT_SIZE; - - case LAYER_II: - return (LAYER_II_FRAME_SIZE_COEFFICIENT) * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength() * LAYER_II_SLOT_SIZE; - - case LAYER_III: - if (this.getChannelMode() == MODE_MONO) { - return (LAYER_III_FRAME_SIZE_COEFFICIENT / 2) * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength() * LAYER_III_SLOT_SIZE; - } else { - return (LAYER_III_FRAME_SIZE_COEFFICIENT) * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength() * LAYER_III_SLOT_SIZE; - } - - - default: - throw new RuntimeException("Mp3 Unknown Layer:" + layer); - - } - - - case VERSION_1: - switch (layer) { - case LAYER_I: - return (LAYER_I_FRAME_SIZE_COEFFICIENT * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength()) * LAYER_I_SLOT_SIZE; - - case LAYER_II: - return LAYER_II_FRAME_SIZE_COEFFICIENT * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength() * LAYER_II_SLOT_SIZE; - - case LAYER_III: - return LAYER_III_FRAME_SIZE_COEFFICIENT * (getBitRate() * SCALE_BY_THOUSAND) / getSamplingRate() + getPaddingLength() * LAYER_III_SLOT_SIZE; - - default: - throw new RuntimeException("Mp3 Unknown Layer:" + layer); - - } - - default: - throw new RuntimeException("Mp3 Unknown Version:" + version); - - } - } - - /** - * Get the number of samples in a frame, all frames in a file have a set number of samples as defined by their MPEG Versiona - * and Layer - * - * @return - */ - public int getNoOfSamples() { - Integer noOfSamples = samplesPerFrameMap.get(version).get(layer); - return noOfSamples; - } - - public boolean isPadding() { - return isPadding; - } - - public boolean isCopyrighted() { - return isCopyrighted; - } - - public boolean isOriginal() { - return isOriginal; - } - - public boolean isProtected() { - return isProtected; - } - - public boolean isPrivate() { - return isPrivate; - } - - public boolean isVariableBitRate() { - return false; - } - - public int getEmphasis() { - return emphasis; - } - - public String getEmphasisAsString() { - return emphasisAsString; - } - - public String getModeExtension() { - return modeExtension; - } - - /** - * @return a string represntation - */ - public String toString() { - return " mpeg frameheader:" + " frame length:" + getFrameLength() + " version:" + versionAsString + " layer:" + layerAsString + " channelMode:" + channelModeAsString + " noOfSamples:" + getNoOfSamples() + " samplingRate:" + samplingRate + " isPadding:" + isPadding + " isProtected:" + isProtected + " isPrivate:" + isPrivate + " isCopyrighted:" + isCopyrighted + " isOriginal:" + isCopyrighted + " isVariableBitRate" + this.isVariableBitRate() + " header as binary:" + AbstractTagDisplayFormatter.displayAsBinary(mpegBytes[BYTE_1]) + " " + AbstractTagDisplayFormatter.displayAsBinary(mpegBytes[BYTE_2]) + " " + AbstractTagDisplayFormatter.displayAsBinary(mpegBytes[BYTE_3]) + " " + AbstractTagDisplayFormatter.displayAsBinary(mpegBytes[BYTE_4]); - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/mp3/VbriFrame.java b/src/main/java/org/jaudiotagger/audio/mp3/VbriFrame.java deleted file mode 100644 index 6d2095a..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/VbriFrame.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * Vrbi Frame - *

    - *

    In MP3s encoded using the franhofer encoder which variable bit rate the first frame in the file contains a - * special frame called a Vrbi Frame, instead of audio data (Other Vbr encoders use the more common Xing Frame). - * This is used to store additional information about the file. The most important aspect for - * this library is details allowing us to determine the bitrate of a Variable Bit Rate VBR file without having - * to process the whole file. - *

    - * From http://www.codeproject.com/KB/audio-video/mpegaudioinfo.aspx#SideInfo - *

    - * This header is only used by MPEG audio files encoded with the Fraunhofer Encoder as far as I know. It is different from the XING header. You find it exactly - * 32 bytes after the end of the first MPEG audio header in the file. (Note that the position is zero-based; position, length and example are each in byte-format.) - * Position Length Meaning Example - * 0 4 VBR header ID in 4 ASCII chars, always 'VBRI', not NULL-terminated 'VBRI' - * 4 2 Version ID as Big-Endian WORD 1 - * 6 2 Delay as Big-Endian float 7344 - * 8 2 Quality indicator 75 - * 10 4 Number of Bytes of Audio as Big-Endian DWORD 45000 - * 14 4 Number of Frames as Big-Endian DWORD 7344 - * 18 2 Number of entries within TOC table as Big-Endian WORD 100 - * 20 2 Scale factor of TOC table entries as Big-Endian DWORD 1 - * 22 2 Size per table entry in bytes (max 4) as Big-Endian WORD 2 - * 24 2 Frames per table entry as Big-Endian WORD 845 - * 26 TOC entries for seeking as Big-Endian integral. From size per table entry and number of entries, you can calculate the length of this field. - *

    - */ -public class VbriFrame { - - //The offset into frame - private static final int VBRI_OFFSET = MPEGFrameHeader.HEADER_SIZE + 32; - - private static final int VBRI_HEADER_BUFFER_SIZE = 120; //TODO this is just a guess, not right - public static final int MAX_BUFFER_SIZE_NEEDED_TO_READ_VBRI = VBRI_OFFSET + VBRI_HEADER_BUFFER_SIZE; - private static final int VBRI_IDENTIFIER_BUFFER_SIZE = 4; - private static final int VBRI_DELAY_BUFFER_SIZE = 2; - private static final int VBRI_QUALITY_BUFFER_SIZE = 2; - private static final int VBRI_AUDIOSIZE_BUFFER_SIZE = 4; - private static final int VBRI_FRAMECOUNT_BUFFER_SIZE = 4; - private static final int VBRI_TOC_ENTRY_BUFFER_SIZE = 2; - private static final int BYTE_1 = 0; - private static final int BYTE_2 = 1; - private static final int BYTE_3 = 2; - private static final int BYTE_4 = 3; - - /** - * Identifier - */ - private static final byte[] VBRI_VBR_ID = {'V', 'B', 'R', 'I'}; - - private ByteBuffer header; - - private boolean vbr = false; - private int frameCount = -1; - private int audioSize = -1; - private LameFrame lameFrame; - - /** - * Read the VBRI Properties from the buffer - */ - private VbriFrame(ByteBuffer header) { - this.header = header; - //Go to start of Buffer - header.rewind(); - header.position(10); - setAudioSize(); - setFrameCount(); - } - - /** - * Parse the VBRIFrame of an MP3File, cannot be called until we have validated that - * this is a VBRIFrame - * - * @return - * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public static VbriFrame parseVBRIFrame(ByteBuffer header) throws InvalidAudioFrameException { - VbriFrame VBRIFrame = new VbriFrame(header); - return VBRIFrame; - } - - /** - * IS this a VBRI frame - * - * @param bb - * @param mpegFrameHeader - * @return raw header if this is a VBRI frame - */ - public static ByteBuffer isVbriFrame(ByteBuffer bb, MPEGFrameHeader mpegFrameHeader) { - - //We store this so can return here after scanning through buffer - int startPosition = bb.position(); - MP3File.logger.finest("Checking VBRI Frame at" + startPosition); - - bb.position(startPosition + VBRI_OFFSET); - - //Create header from here - ByteBuffer header = bb.slice(); - - // Return Buffer to start Point - bb.position(startPosition); - - //Check Identifier - byte[] identifier = new byte[VBRI_IDENTIFIER_BUFFER_SIZE]; - header.get(identifier); - if ((!Arrays.equals(identifier, VBRI_VBR_ID))) { - return null; - } - MP3File.logger.finest("Found VBRI Frame"); - return header; - } - - /** - * Set size of AudioData - */ - private void setAudioSize() { - byte frameSizeBuffer[] = new byte[VBRI_AUDIOSIZE_BUFFER_SIZE]; - header.get(frameSizeBuffer); - boolean audioSizeEnabled = true; - audioSize = (frameSizeBuffer[BYTE_1] << 24) & 0xFF000000 | (frameSizeBuffer[BYTE_2] << 16) & 0x00FF0000 | (frameSizeBuffer[BYTE_3] << 8) & 0x0000FF00 | frameSizeBuffer[BYTE_4] & 0x000000FF; - } - - /** - * Set count of frames - */ - private void setFrameCount() { - byte frameCountBuffer[] = new byte[VBRI_FRAMECOUNT_BUFFER_SIZE]; - header.get(frameCountBuffer); - boolean frameCountEnabled = true; - frameCount = (frameCountBuffer[BYTE_1] << 24) & 0xFF000000 | (frameCountBuffer[BYTE_2] << 16) & 0x00FF0000 | (frameCountBuffer[BYTE_3] << 8) & 0x0000FF00 | frameCountBuffer[BYTE_4] & 0x000000FF; - } - - /** - * @return count of frames - */ - public final int getFrameCount() { - return frameCount; - } - - /** - * @return size of audio data in bytes - */ - public final int getAudioSize() { - return audioSize; - } - - /** - * Is this VBRIFrame detailing a varaible bit rate MPEG - * - * @return - */ - public final boolean isVbr() { - return true; - } - - public String getEncoder() { - return "Fraunhofer"; - } - - /** - * @return a string represntation - */ - public String toString() { - return "VBRIheader" + " vbr:" + vbr + " frameCount:" + frameCount + " audioFileSize:" + audioSize + " encoder:" + getEncoder(); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp3/XingFrame.java b/src/main/java/org/jaudiotagger/audio/mp3/XingFrame.java deleted file mode 100644 index a556851..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/XingFrame.java +++ /dev/null @@ -1,237 +0,0 @@ -package org.jaudiotagger.audio.mp3; - -import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * Xing Frame - *

    - *

    In some MP3s which variable bit rate the first frame in the file contains a special frame called a Xing Frame, - * instead of audio data. This is used to store additional information about the file. The most important aspect for - * this library is details allowing us to determine the bitrate of a Variable Bit Rate VBR file without having - * to process the whole file. - *

    - * Xing VBR Tag data format is 120 bytes long - * 4 bytes for Header Tag - * 4 bytes for Header Flags - * 4 bytes for FRAME SIZE - * 4 bytes for AUDIO_SIZE - * 100 bytes for entry (NUMTOCENTRIES) - * 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst - *

    - * It my then contain a Lame Frame ( a Lame frame is in essence an extended Xing Frame - */ -public class XingFrame { - - //The offset into first frame varies based on the MPEG frame properties - private static final int MPEG_VERSION_1_MODE_MONO_OFFSET = 21; - private static final int MPEG_VERSION_1_MODE_STEREO_OFFSET = 36; - private static final int MPEG_VERSION_2_MODE_MONO_OFFSET = 13; - private static final int MPEG_VERSION_2_MODE_STEREO_OFFSET = 21; - - private static final int XING_HEADER_BUFFER_SIZE = 120; - public static final int MAX_BUFFER_SIZE_NEEDED_TO_READ_XING = MPEG_VERSION_1_MODE_STEREO_OFFSET + XING_HEADER_BUFFER_SIZE + LameFrame.LAME_HEADER_BUFFER_SIZE; - private static final int XING_IDENTIFIER_BUFFER_SIZE = 4; - private static final int XING_FLAG_BUFFER_SIZE = 4; - private static final int XING_FRAMECOUNT_BUFFER_SIZE = 4; - private static final int XING_AUDIOSIZE_BUFFER_SIZE = 4; - private static final int BYTE_1 = 0; - private static final int BYTE_2 = 1; - private static final int BYTE_3 = 2; - private static final int BYTE_4 = 3; - - /** - * Use when it is a VBR (Variable Bitrate) file - */ - private static final byte[] XING_VBR_ID = {'X', 'i', 'n', 'g'}; - - /** - * Use when it is a CBR (Constant Bitrate) file - */ - private static final byte[] XING_CBR_ID = {'I', 'n', 'f', 'o'}; - - - private ByteBuffer header; - - private boolean vbr = false; - private boolean isFrameCountEnabled = false; - private int frameCount = -1; - private boolean isAudioSizeEnabled = false; - private int audioSize = -1; - private LameFrame lameFrame; - - /** - * Read the Xing Properties from the buffer - */ - private XingFrame(ByteBuffer header) { - this.header = header; - - //Go to start of Buffer - header.rewind(); - - //Set Vbr - setVbr(); - - //Read Flags, only the fourth byte of interest to us - byte flagBuffer[] = new byte[XING_FLAG_BUFFER_SIZE]; - header.get(flagBuffer); - - //Read FrameCount if flag set - if ((flagBuffer[BYTE_4] & (byte) (1)) != 0) { - setFrameCount(); - } - - //Read Size if flag set - if ((flagBuffer[BYTE_4] & (byte) (1 << 1)) != 0) { - setAudioSize(); - } - - //TODO TOC - //TODO VBR Quality - - //Look for LAME Header as long as we have enough bytes to do it properly - if (header.limit() >= XING_HEADER_BUFFER_SIZE + LameFrame.LAME_HEADER_BUFFER_SIZE) { - header.position(XING_HEADER_BUFFER_SIZE); - lameFrame = LameFrame.parseLameFrame(header); - } - } - - /** - * Parse the XingFrame of an MP3File, cannot be called until we have validated that - * this is a XingFrame - * - * @return - * @throws InvalidAudioFrameException - */ - public static XingFrame parseXingFrame(ByteBuffer header) throws InvalidAudioFrameException { - XingFrame xingFrame = new XingFrame(header); - return xingFrame; - } - - /** - * IS this a Xing frame - * - * @param bb - * @param mpegFrameHeader - * @return true if this is a Xing frame - */ - public static ByteBuffer isXingFrame(ByteBuffer bb, MPEGFrameHeader mpegFrameHeader) { - //We store this so can return here after scanning through buffer - int startPosition = bb.position(); - - //Get to Start of where Xing Frame Should be ( we dont know if it is one at this point) - if (mpegFrameHeader.getVersion() == MPEGFrameHeader.VERSION_1) { - if (mpegFrameHeader.getChannelMode() == MPEGFrameHeader.MODE_MONO) { - bb.position(startPosition + MPEG_VERSION_1_MODE_MONO_OFFSET); - } else { - bb.position(startPosition + MPEG_VERSION_1_MODE_STEREO_OFFSET); - } - } - //MPEGVersion 2 and 2.5 - else { - if (mpegFrameHeader.getChannelMode() == MPEGFrameHeader.MODE_MONO) { - bb.position(startPosition + MPEG_VERSION_2_MODE_MONO_OFFSET); - } else { - bb.position(startPosition + MPEG_VERSION_2_MODE_STEREO_OFFSET); - } - } - - //Create header from here - ByteBuffer header = bb.slice(); - - // Return Buffer to start Point - bb.position(startPosition); - - //Check Identifier - byte[] identifier = new byte[XING_IDENTIFIER_BUFFER_SIZE]; - header.get(identifier); - if ((!Arrays.equals(identifier, XING_VBR_ID)) && (!Arrays.equals(identifier, XING_CBR_ID))) { - return null; - } - MP3File.logger.finest("Found Xing Frame"); - return header; - } - - public LameFrame getLameFrame() { - return lameFrame; - } - - /** - * Set whether or not VBR, (Xing can also be used for CBR though this is less useful) - */ - private void setVbr() { - //Is it VBR or CBR - byte[] identifier = new byte[XING_IDENTIFIER_BUFFER_SIZE]; - header.get(identifier); - if (Arrays.equals(identifier, XING_VBR_ID)) { - MP3File.logger.finest("Is Vbr"); - vbr = true; - } - } - - /** - * Set count of frames - */ - private void setFrameCount() { - byte frameCountBuffer[] = new byte[XING_FRAMECOUNT_BUFFER_SIZE]; - header.get(frameCountBuffer); - isFrameCountEnabled = true; - frameCount = (frameCountBuffer[BYTE_1] << 24) & 0xFF000000 | (frameCountBuffer[BYTE_2] << 16) & 0x00FF0000 | (frameCountBuffer[BYTE_3] << 8) & 0x0000FF00 | frameCountBuffer[BYTE_4] & 0x000000FF; - } - - /** - * @return true if frameCount has been specified in header - */ - public final boolean isFrameCountEnabled() { - return isFrameCountEnabled; - } - - /** - * @return count of frames - */ - public final int getFrameCount() { - return frameCount; - } - - /** - * Set size of AudioData - */ - private void setAudioSize() { - byte frameSizeBuffer[] = new byte[XING_AUDIOSIZE_BUFFER_SIZE]; - header.get(frameSizeBuffer); - isAudioSizeEnabled = true; - audioSize = (frameSizeBuffer[BYTE_1] << 24) & 0xFF000000 | (frameSizeBuffer[BYTE_2] << 16) & 0x00FF0000 | (frameSizeBuffer[BYTE_3] << 8) & 0x0000FF00 | frameSizeBuffer[BYTE_4] & 0x000000FF; - } - - /** - * @return true if audioSize has been specified in header - */ - public final boolean isAudioSizeEnabled() { - return isAudioSizeEnabled; - } - - /** - * @return size of audio data in bytes - */ - public final int getAudioSize() { - return audioSize; - } - - /** - * Is this XingFrame detailing a variable bit rate MPEG - * - * @return - */ - public final boolean isVbr() { - return vbr; - } - - /** - * @return a string representation - */ - public String toString() { - return "xingheader" + " vbr:" + vbr + " frameCountEnabled:" + isFrameCountEnabled + " frameCount:" + frameCount + " audioSizeEnabled:" + isAudioSizeEnabled + " audioFileSize:" + audioSize; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp3/package.html b/src/main/java/org/jaudiotagger/audio/mp3/package.html deleted file mode 100644 index 9c29656..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp3/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for MP3 files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/mp4/EncoderType.java b/src/main/java/org/jaudiotagger/audio/mp4/EncoderType.java deleted file mode 100644 index e333253..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/EncoderType.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jaudiotagger.audio.mp4; - -/** - * Encoder Type actually identifies the format of the audio within the mp4. This is because - * mp4 container can be used to hold different types of files. - */ -public enum EncoderType { - AAC("AAC"), - DRM_AAC("DRM AAC"), - APPLE_LOSSLESS("Apple Lossless"),; - - private String description; - - EncoderType(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java deleted file mode 100644 index 93ffa0e..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.jaudiotagger.audio.mp4; - -/** - * This a list of mp4boxes identifiers that can bwe found in a mp4 container. This list is by no means - * exhaustive. - *

    - * Only a limited number are of interest to Jaudiotagger - */ -public enum Mp4AtomIdentifier { - ALAC("alac", "Apple Lossless File"), - ALBM("albm", "Album title and track number (user-data)"), - AUTH("auth", "Media author name (user-data)"), - BPCC("bpcc", "Bits per component"), - BUFF("buff", "Buffering information"), - BXML("bxml", "Binary XML container"), - CCID("ccid", "OMA DRM Content ID"), - CDEF("cdef", "Type and ordering of the components within the codestream"), - CLSF("clsf", "Media classification (user-data)"), - CMAP("cmap", "Mapping between a palette and codestream components"), - CO64("co64", "64-bit chunk offset"), - COLR("colr", "Specifies the colourspace of the image"), - CPRT("cprt", "Copyright etc. (user-data)"), - CRHD("crhd", "Reserved for ClockReferenceStream header"), - CSLG("cslg", "Composition to decode timeline mapping"), - CTTS("ctts", "(composition) time to sample"), - CVRU("cvru", "OMA DRM Cover URI"), - DCFD("dcfD", "Marlin DCF Duration, user-data atom type"), - DINF("dinf", "Data information box, container"), - DREF("dref", "Data reference box, declares source(s) of media data in track"), - DRMS("drms", "DRM protected File"), - DSCP("dscp", "Media description (user-data)"), - DSGD("dsgd", "DVB Sample Group Description Box"), - DSTG("dstg", "DVB Sample to Group Box"), - EDTS("edts", "Edit list container"), - ELST("elst", "An edit list"), - ESDS("esds", "Track codec specific information"), - FECI("feci", "FEC Informatiom"), - FECR("fecr", "FEC Reservoir"), - FIIN("fiin", "FD Item Information"), - FIRE("fire", "File Reservoir"), - FPAR("fpar", "File Partition"), - FREE("free", "Padding"), - FRMA("frma", "Original format box"), - FTYP("ftyp", "File type Identification"), - GITN("gitn", "Group ID to name"), - GNRE("gnre", "Media genre (user-data)"), - GRPI("grpi", "OMA DRM Group ID"), - HDLR("hdlr", "Metadata Handler"), - HMHD("hmhd", "Hint media header, overall information (hint track only)"), - HNTI("hnti", "Hint tracks to aid a streaming server in remuxing the M4A file to an RTP stream."), - ICNU("icnu", "OMA DRM Icon URI"), - ID32("ID32", "ID3 version 2 container"), - IDAT("idat", "Item data"), - IHDR("ihdr", "Image Header"), - IINF("iinf", "item information"), - ILOC("iloc", "item location"), - ILST("ilst", "MetaInformation Optional"), - IMIF("imif", "IPMP Information box"), - INFU("infu", "OMA DRM Info URL"), - IODS("iods", "Object Descriptor container box"), - IPHD("iphd", "reserved for IPMP Stream header"), - IPMC("ipmc", "IPMP Control Box"), - IPRO("ipro", "Item protection"), - IREF("iref", "Item reference"), - JP2C("jp2c", "JPEG 2000 contiguous codestream"), - JP2H("jp2h", "Header"), - JP2I("jp2i", "Intellectual property information"), - KYWD("kywd", "Media keywords (user-data)"), - LOCI("loci", "Media location information (user-data)"), - LRCU("lrcu", "OMA DRM Lyrics URI"), - M7HD("m7hd", "Reserved for MPEG7Stream header"), - MDAT("mdat", "Audio Data"), - MDHD("mdhd", "Media Header"), - MDIA("mdia", "Container for the media information in a track"), - MDRI("mdri", "Mutable DRM information"), - MECO("meco", "Additional metadata container"), - MEHD("mehd", "Movie extends header box"), - MERE("mere", "Metabox relation"), - META("meta", "MetaInformation"), - MFHD("mfhd", "Movie fragment header"), - MFRA("mfra", "Movie fragment random access "), - MFRO("mfro", "Movie fragment random access offset"), - MINF("minf", "Media information container"), - MJHD("mjhd", "Reserved for MPEG-J Stream header"), - MOOF("moof", "Movie fragment"), - MOOV("moov", "Container for all the meta-data"), - MP4A("mp4a", "AAC Audio"), - MVCG("mvcg", "Multiview group"), - MVCI("mvci", "Multiview Information"), - MVEX("mvex", "Movie extends box"), - MVHD("mvhd", "Movie Header"), - MVRA("mvra", "Multiview Relation Attribute"), - NMHD("nmhd", "Null media header, overall information (some tracks only)"), - OCHD("ochd", "Reserved for ObjectContentInfoStream header"), - ODAF("odaf", "OMA DRM Access Unit Format"), - ODDA("odda", "OMA DRM Content Object"), - ODHD("odhd", "Reserved for ObjectDescriptorStream header"), - ODHE("odhe", "OMA DRM Discrete Media Headers"), - ODRB("odrb", "OMA DRM Rights Object"), - ODRM("odrm", "OMA DRM Container"), - ODTT("odtt", "OMA DRM Transaction Tracking"), - OHDR("ohdr", "OMA DRM Common headers"), - PADB("padb", "Sample padding bits"), - PAEN("paen", "Partition Entry"), - PCLR("pclr", "palette which maps a single component in index space to a multiple- component image"), - PDIN("pdin", "Progressive download information"), - PERF("perf", "Media performer name (user-data)"), - PITM("pitm", "Primary item reference"), - RESC("resc", "Grid resolution at which the image was captured"), - RESD("resd", "Default grid resolution at which the image should be displayed"), - RTNG("rtng", "Media rating (user-data)"), - SBGP("sbgp", "Sample to Group box"), - SCHI("schi", "Scheme information box"), - SCHM("schm", "Scheme type box"), - SDEP("sdep", "Sample dependency"), - SDHD("sdhd", "Reserved for SceneDescriptionStream header"), - SDTP("sdtp", "Independent and Disposable Samples Box"), - SDVP("sdvp", "SD Profile Box"), - SEGR("segr", "File delivery session group"), - SGPD("sgpd", "Sample group definition box"), - SIDX("sidx", "Segment Index Box"), - SINF("sinf", "Protection scheme information box"), - SKIP("skip", "Free space"), - SMHD("smhd", "Sound media header, overall information (sound track only)"), - SRMB("srmb", "System Renewability Message"), - SRMC("srmc", "System Renewability Message container"), - SRPP("srpp", "STRP Process"), - STBL("stbl", "Sample table box, container for the time/space map"), - STCO("stco", "Offsets into Audio Data"), - STDP("stdp", "Sample degradation priority"), - STSC("stsc", "Sample-to-chunk, partial data-offset information"), - STSD("stsd", "Sample descriptions (codec types, initialization etc.)"), - STSH("stsh", "Shadow sync sample table"), - STSS("stss", "Sync sample table (random access points)"), - STSZ("stsz", "Sample sizes (framing)"), - STTS("stts", "(decoding) time-to-sample"), - STYP("styp", "Segment Type Box"), - STZ2("stz2", "Compact sample sizes (framing)"), - SUBS("subs", "Sub-sample information"), - SWTC("swtc", "Multiview Group Relation"), - TAGS("tags", "Nero Encoder Tags"), - TFAD("tfad", "Track fragment adjustment box"), - TFHD("tfhd", "Track fragment header"), - TFMA("tfma", "Track fragment media adjustment box"), - TFRA("tfra", "Track fragment radom access"), - TIBR("tibr", "Tier Bit rate"), - TIRI("tiri", "Tier Information"), - TITL("titl", "Media title (user-data)"), - TKHD("tkhd", "Track header, overall information about the track"), - TRAF("traf", "Track fragment"), - TRAK("trak", "Track"), - TREF("tref", "Track reference container"), - TREX("trex", "Track extends defaults"), - TRGR("trgr", "Track grouping information"), - TRUN("trun", "Track fragment run"), - TSEL("tsel", "Track selection (user-data)"), - UDTA("udta", "User Data"), - UINF("uinf", "A tool by which a vendor may provide access to additional information associated with a UUID"), - ULST("ulst", "A list of UUID’s"), - URL$20("url$20", "a URL"), - UUID("uuid", "User-extension box"), - VMHD("vmhd", "video media header, overall information (video track only)"), - VWDI("vwdi", "Multiview Scene Information"), - XML$20("xml$20", "a tool by which vendors can add XML formatted information"), - YRRC("yrrc", "Year when media was recorded (user-data)"),; - private String fieldName; - private String description; - - Mp4AtomIdentifier(String fieldName, String description) { - this.fieldName = fieldName; - this.description = description; - - } - - /** - * This is the value of the fieldname that is actually used to write mp4 - * - * @return - */ - public String getFieldName() { - return fieldName; - } - - /** - * @return description, human redable description of the atom - */ - public String getDescription() { - return description; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4AtomTree.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4AtomTree.java deleted file mode 100644 index 10cd7c1..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4AtomTree.java +++ /dev/null @@ -1,421 +0,0 @@ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.NullBoxIdException; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.audio.mp4.atom.Mp4MetaBox; -import org.jaudiotagger.audio.mp4.atom.Mp4StcoBox; -import org.jaudiotagger.audio.mp4.atom.NullPadding; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.utils.tree.DefaultMutableTreeNode; -import org.jaudiotagger.utils.tree.DefaultTreeModel; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.logging.Logger; - -/** - * Tree representing atoms in the mp4 file - *

    - * Note it doesn't create the complete tree it delves into subtrees for atom we know about and are interested in. (Note - * it would be impossible to create a complete tree for any file without understanding all the nodes because - * some atoms such as meta contain data and children and therefore need to be specially preprocessed) - *

    - * This class is currently only used when writing tags because it better handles the difficulties of mdat and free - * atoms being optional/multiple places then the older sequential method. It is expected this class will eventually - * be used when reading tags as well. - *

    - * Uses a TreeModel for the tree, with convenience methods holding onto references to most common nodes so they - * can be used without having to traverse the tree again. - */ -public class Mp4AtomTree { - //Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.mp4"); - private DefaultMutableTreeNode rootNode; - private DefaultTreeModel dataTree; - private DefaultMutableTreeNode moovNode; - private DefaultMutableTreeNode mdatNode; - private DefaultMutableTreeNode stcoNode; - private DefaultMutableTreeNode ilstNode; - private DefaultMutableTreeNode metaNode; - private DefaultMutableTreeNode tagsNode; - private DefaultMutableTreeNode udtaNode; - private DefaultMutableTreeNode hdlrWithinMdiaNode; - private DefaultMutableTreeNode hdlrWithinMetaNode; - private List freeNodes = new ArrayList(); - private List mdatNodes = new ArrayList(); - private List trakNodes = new ArrayList(); - private Mp4StcoBox stco; - private ByteBuffer moovBuffer; //Contains all the data under moov - private Mp4BoxHeader moovHeader; - - /** - * Create Atom Tree - * - * @param raf - * @throws IOException - * @throws CannotReadException - */ - public Mp4AtomTree(RandomAccessFile raf) throws IOException, CannotReadException { - buildTree(raf, true); - } - - /** - * Create Atom Tree and maintain open channel to raf, should only be used if will continue - * to use raf after this call, you will have to close raf yourself. - * - * @param raf - * @param closeOnExit to keep randomfileaccess open, only used when randomaccessfile already being used - * @throws IOException - * @throws CannotReadException - */ - public Mp4AtomTree(RandomAccessFile raf, boolean closeOnExit) throws IOException, CannotReadException { - buildTree(raf, closeOnExit); - } - - /** - * Build a tree of the atoms in the file - * - * @param raf - * @param closeExit false to keep randomfileacces open, only used when randomaccessfile already being used - * @return - * @throws java.io.IOException - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - */ - public DefaultTreeModel buildTree(RandomAccessFile raf, boolean closeExit) throws IOException, CannotReadException { - FileChannel fc = null; - try { - fc = raf.getChannel(); - - //make sure at start of file - fc.position(0); - - //Build up map of nodes - rootNode = new DefaultMutableTreeNode(); - dataTree = new DefaultTreeModel(rootNode); - - //Iterate though all the top level Nodes - ByteBuffer headerBuffer = ByteBuffer.allocate(Mp4BoxHeader.HEADER_LENGTH); - while (fc.position() < fc.size()) { - Mp4BoxHeader boxHeader = new Mp4BoxHeader(); - headerBuffer.clear(); - fc.read(headerBuffer); - headerBuffer.rewind(); - - try { - boxHeader.update(headerBuffer); - } catch (NullBoxIdException ne) { - //If we only get this error after all the expected data has been found we allow it - if (moovNode != null & mdatNode != null) { - NullPadding np = new NullPadding(fc.position() - Mp4BoxHeader.HEADER_LENGTH, fc.size()); - DefaultMutableTreeNode trailingPaddingNode = new DefaultMutableTreeNode(np); - rootNode.add(trailingPaddingNode); - logger.warning(ErrorMessage.NULL_PADDING_FOUND_AT_END_OF_MP4.getMsg(np.getFilePos())); - break; - } else { - //File appears invalid - throw ne; - } - } - - boxHeader.setFilePos(fc.position() - Mp4BoxHeader.HEADER_LENGTH); - DefaultMutableTreeNode newAtom = new DefaultMutableTreeNode(boxHeader); - - //Go down moov - if (boxHeader.getId().equals(Mp4AtomIdentifier.MOOV.getFieldName())) { - //A second Moov atom, this is illegal but may just be mess at the end of the file so ignore - //and finish - if (moovNode != null & mdatNode != null) { - logger.warning(ErrorMessage.ADDITIONAL_MOOV_ATOM_AT_END_OF_MP4.getMsg(fc.position() - Mp4BoxHeader.HEADER_LENGTH)); - break; - } - moovNode = newAtom; - moovHeader = boxHeader; - - long filePosStart = fc.position(); - moovBuffer = ByteBuffer.allocate(boxHeader.getDataLength()); - int bytesRead = fc.read(moovBuffer); - - //If Moov atom is incomplete we are not going to be able to read this file properly - if (bytesRead < boxHeader.getDataLength()) { - String msg = ErrorMessage.ATOM_LENGTH_LARGER_THAN_DATA.getMsg(boxHeader.getId(), boxHeader.getDataLength(), bytesRead); - throw new CannotReadException(msg); - } - moovBuffer.rewind(); - buildChildrenOfNode(moovBuffer, newAtom); - fc.position(filePosStart); - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.FREE.getFieldName())) { - //Might be multiple in different locations - freeNodes.add(newAtom); - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.MDAT.getFieldName())) { - //mdatNode always points to the last mDatNode, normally there is just one mdatnode but do have - //a valid example of multiple mdatnode - - //if(mdatNode!=null) - //{ - // throw new CannotReadException(ErrorMessage.MP4_FILE_CONTAINS_MULTIPLE_DATA_ATOMS.getMsg()); - //} - mdatNode = newAtom; - mdatNodes.add(newAtom); - } - rootNode.add(newAtom); - fc.position(fc.position() + boxHeader.getDataLength()); - } - return dataTree; - } finally { - //If we cant find the audio then we cannot modify this file so better to throw exception - //now rather than later when try and write to it. - if (mdatNode == null) { - throw new CannotReadException(ErrorMessage.MP4_CANNOT_FIND_AUDIO.getMsg()); - } - - if (closeExit) { - fc.close(); - } - } - } - - /** - * Display atom tree - */ - @SuppressWarnings("unchecked") - public void printAtomTree() { - Enumeration e = rootNode.preorderEnumeration(); - DefaultMutableTreeNode nextNode; - while (e.hasMoreElements()) { - nextNode = e.nextElement(); - Mp4BoxHeader header = (Mp4BoxHeader) nextNode.getUserObject(); - if (header != null) { - String tabbing = ""; - for (int i = 1; i < nextNode.getLevel(); i++) { - tabbing += "\t"; - } - - if (header instanceof NullPadding) { - System.out.println(tabbing + "Null pad " + " @ " + header.getFilePos() + " of size:" + header.getLength() + " ,ends @ " + (header.getFilePos() + header.getLength())); - } else { - System.out.println(tabbing + "Atom " + header.getId() + " @ " + header.getFilePos() + " of size:" + header.getLength() + " ,ends @ " + (header.getFilePos() + header.getLength())); - } - } - } - } - - /** - * @param moovBuffer - * @param parentNode - * @throws IOException - * @throws CannotReadException - */ - public void buildChildrenOfNode(ByteBuffer moovBuffer, DefaultMutableTreeNode parentNode) throws IOException, CannotReadException { - Mp4BoxHeader boxHeader; - - //Preprocessing for nodes that contain data before their children atoms - Mp4BoxHeader parentBoxHeader = (Mp4BoxHeader) parentNode.getUserObject(); - - //We set the buffers position back to this after processing the children - int justAfterHeaderPos = moovBuffer.position(); - - //Preprocessing for meta that normally contains 4 data bytes, but doesn't where found under track or tags atom - if (parentBoxHeader.getId().equals(Mp4AtomIdentifier.META.getFieldName())) { - Mp4MetaBox meta = new Mp4MetaBox(parentBoxHeader, moovBuffer); - meta.processData(); - - try { - boxHeader = new Mp4BoxHeader(moovBuffer); - } catch (NullBoxIdException nbe) { - //It might be that the meta box didn't actually have any additional data after it so we adjust the buffer - //to be immediately after metabox and code can retry - moovBuffer.position(moovBuffer.position() - Mp4MetaBox.FLAGS_LENGTH); - } finally { - //Skip back last header cos this was only a test - moovBuffer.position(moovBuffer.position() - Mp4BoxHeader.HEADER_LENGTH); - } - } - - //Defines where to start looking for the first child node - int startPos = moovBuffer.position(); - while (moovBuffer.position() < ((startPos + parentBoxHeader.getDataLength()) - Mp4BoxHeader.HEADER_LENGTH)) { - boxHeader = new Mp4BoxHeader(moovBuffer); - if (boxHeader != null) { - boxHeader.setFilePos(moovHeader.getFilePos() + moovBuffer.position()); - logger.finest("Atom " + boxHeader.getId() + " @ " + boxHeader.getFilePos() + " of size:" + boxHeader.getLength() + " ,ends @ " + (boxHeader.getFilePos() + boxHeader.getLength())); - - DefaultMutableTreeNode newAtom = new DefaultMutableTreeNode(boxHeader); - parentNode.add(newAtom); - - if (boxHeader.getId().equals(Mp4AtomIdentifier.UDTA.getFieldName())) { - udtaNode = newAtom; - } - //only interested in metaNode that is child of udta node - else if (boxHeader.getId().equals(Mp4AtomIdentifier.META.getFieldName()) && parentBoxHeader.getId().equals(Mp4AtomIdentifier.UDTA.getFieldName())) { - metaNode = newAtom; - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.HDLR.getFieldName()) && parentBoxHeader.getId().equals(Mp4AtomIdentifier.META.getFieldName())) { - hdlrWithinMetaNode = newAtom; - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.HDLR.getFieldName())) { - hdlrWithinMdiaNode = newAtom; - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.TAGS.getFieldName())) { - tagsNode = newAtom; - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.STCO.getFieldName())) { - if (stco == null) { - stco = new Mp4StcoBox(boxHeader, moovBuffer); - stcoNode = newAtom; - } - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.ILST.getFieldName())) { - DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentNode.getParent(); - if (parent != null) { - Mp4BoxHeader parentsParent = (Mp4BoxHeader) (parent).getUserObject(); - if (parentsParent != null) { - if (parentBoxHeader.getId().equals(Mp4AtomIdentifier.META.getFieldName()) && parentsParent.getId().equals(Mp4AtomIdentifier.UDTA.getFieldName())) { - ilstNode = newAtom; - } - } - } - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.FREE.getFieldName())) { - //Might be multiple in different locations - freeNodes.add(newAtom); - } else if (boxHeader.getId().equals(Mp4AtomIdentifier.TRAK.getFieldName())) { - //Might be multiple in different locations, although only one should be audio track - trakNodes.add(newAtom); - } - - //For these atoms iterate down to build their children - if ((boxHeader.getId().equals(Mp4AtomIdentifier.TRAK.getFieldName())) || - (boxHeader.getId().equals(Mp4AtomIdentifier.MDIA.getFieldName())) || - (boxHeader.getId().equals(Mp4AtomIdentifier.MINF.getFieldName())) || - (boxHeader.getId().equals(Mp4AtomIdentifier.STBL.getFieldName())) || - (boxHeader.getId().equals(Mp4AtomIdentifier.UDTA.getFieldName())) || - (boxHeader.getId().equals(Mp4AtomIdentifier.META.getFieldName())) || - (boxHeader.getId().equals(Mp4AtomIdentifier.ILST.getFieldName()))) { - buildChildrenOfNode(moovBuffer, newAtom); - } - //Now adjust buffer for the next atom header at this level - moovBuffer.position(moovBuffer.position() + boxHeader.getDataLength()); - - } - } - moovBuffer.position(justAfterHeaderPos); - } - - - /** - * @return - */ - public DefaultTreeModel getDataTree() { - return dataTree; - } - - - /** - * @return - */ - public DefaultMutableTreeNode getMoovNode() { - return moovNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getStcoNode() { - return stcoNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getIlstNode() { - return ilstNode; - } - - /** - * @param node - * @return - */ - public Mp4BoxHeader getBoxHeader(DefaultMutableTreeNode node) { - if (node == null) { - return null; - } - return (Mp4BoxHeader) node.getUserObject(); - } - - /** - * @return - */ - public DefaultMutableTreeNode getMdatNode() { - return mdatNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getUdtaNode() { - return udtaNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getMetaNode() { - return metaNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getHdlrWithinMetaNode() { - return hdlrWithinMetaNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getHdlrWithinMdiaNode() { - return hdlrWithinMdiaNode; - } - - /** - * @return - */ - public DefaultMutableTreeNode getTagsNode() { - return tagsNode; - } - - /** - * @return - */ - public List getFreeNodes() { - return freeNodes; - } - - /** - * @return - */ - public List getTrakNodes() { - return trakNodes; - } - - /** - * @return - */ - public Mp4StcoBox getStco() { - return stco; - } - - /** - * @return - */ - public ByteBuffer getMoovBuffer() { - return moovBuffer; - } - - /** - * @return - */ - public Mp4BoxHeader getMoovHeader() { - return moovHeader; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4AudioHeader.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4AudioHeader.java deleted file mode 100644 index 667c8f3..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4AudioHeader.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.audio.mp4.atom.Mp4EsdsBox; - -/** - * Store some additional attributes not available for all audio types - */ -public class Mp4AudioHeader extends GenericAudioHeader { - /** - * The key for the kind field
    - * - * @see #content - */ - public final static String FIELD_KIND = "KIND"; - - /** - * The key for the profile
    - * - * @see #content - */ - public final static String FIELD_PROFILE = "PROFILE"; - - - /** - * The key for the ftyp brand
    - * - * @see #content - */ - public final static String FIELD_BRAND = "BRAND"; - - /** - * @return kind - */ - public Mp4EsdsBox.Kind getKind() { - return (Mp4EsdsBox.Kind) content.get(FIELD_KIND); - } - - public void setKind(Mp4EsdsBox.Kind kind) { - content.put(FIELD_KIND, kind); - } - - /** - * @return audio profile - */ - public Mp4EsdsBox.AudioProfile getProfile() { - return (Mp4EsdsBox.AudioProfile) content.get(FIELD_PROFILE); - } - - /** - * The key for the profile - * - * @param profile - */ - public void setProfile(Mp4EsdsBox.AudioProfile profile) { - content.put(FIELD_PROFILE, profile); - } - - /** - * @return brand - */ - public String getBrand() { - return (String) content.get(FIELD_BRAND); - } - - /** - * @param brand - */ - public void setBrand(String brand) { - content.put(FIELD_BRAND, brand); - } - - -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4FileReader.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4FileReader.java deleted file mode 100644 index 93744b9..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4FileReader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Mp4 File Reader - *

    - *

    This can read files containing either the .mp4 or .m4a suffixes - */ -public class Mp4FileReader extends AudioFileReader { - private Mp4InfoReader ir = new Mp4InfoReader(); - private Mp4TagReader tr = new Mp4TagReader(); - - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException { - return ir.read(raf); - } - - protected Tag getTag(RandomAccessFile raf) throws CannotReadException, IOException { - return tr.read(raf); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4FileWriter.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4FileWriter.java deleted file mode 100644 index 8a26bc3..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4FileWriter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.generic.AudioFileWriter; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Mp4 File Writer - *

    - *

    This can write files containing either the .mp4 or .m4a suffixes - */ -public class Mp4FileWriter extends AudioFileWriter { - - private Mp4TagWriter tw = new Mp4TagWriter(); - - - protected void writeTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException { - tw.write(tag, raf, rafTemp); - } - - protected void deleteTag(RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException { - tw.delete(raf, rafTemp); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4InfoReader.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4InfoReader.java deleted file mode 100644 index d0a0024..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4InfoReader.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotReadVideoException; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.audio.mp4.atom.*; -import org.jaudiotagger.logging.ErrorMessage; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Read audio info from file. - *

    - *

    - * The info is held in the mvdh and mdhd fields as shown below - *

    - * |--- ftyp
    - * |--- moov
    - * |......|
    - * |......|----- mvdh
    - * |......|----- trak
    - * |...............|----- mdia
    - * |.......................|---- mdhd
    - * |.......................|---- minf
    - * |..............................|---- smhd
    - * |..............................|---- stbl
    - * |......................................|--- stsd
    - * |.............................................|--- mp4a
    - * |......|----- udta
    - * |
    - * |--- mdat
    - * 
    - */ -public class Mp4InfoReader { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.mp4.atom"); - - private boolean isTrackAtomVideo(Mp4FtypBox ftyp, Mp4BoxHeader boxHeader, ByteBuffer mvhdBuffer) - throws IOException { - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDIA.getFieldName()); - if (boxHeader == null) { - return false; - } - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDHD.getFieldName()); - if (boxHeader == null) { - return false; - } - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MINF.getFieldName()); - if (boxHeader == null) { - return false; - } - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.VMHD.getFieldName()); - return boxHeader != null; - } - - public GenericAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException { - Mp4AudioHeader info = new Mp4AudioHeader(); - - //File Identification - Mp4BoxHeader ftypHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4AtomIdentifier.FTYP.getFieldName()); - if (ftypHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_CONTAINER.getMsg()); - } - ByteBuffer ftypBuffer = ByteBuffer.allocate(ftypHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH); - raf.getChannel().read(ftypBuffer); - ftypBuffer.rewind(); - Mp4FtypBox ftyp = new Mp4FtypBox(ftypHeader, ftypBuffer); - ftyp.processData(); - info.setBrand(ftyp.getMajorBrand()); - - //Get to the facts everything we are interested in is within the moov box, so just load data from file - //once so no more file I/O needed - Mp4BoxHeader moovHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4AtomIdentifier.MOOV.getFieldName()); - if (moovHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - ByteBuffer moovBuffer = ByteBuffer.allocate(moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH); - raf.getChannel().read(moovBuffer); - moovBuffer.rewind(); - - //Level 2-Searching for "mvhd" somewhere within "moov", we make a slice after finding header - //so all get() methods will be relative to mvdh positions - Mp4BoxHeader boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.MVHD.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - ByteBuffer mvhdBuffer = moovBuffer.slice(); - Mp4MvhdBox mvhd = new Mp4MvhdBox(boxHeader, mvhdBuffer); - info.setLength(mvhd.getLength()); - //Advance position, TODO should we put this in box code ? - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - - //Level 2-Searching for "trak" within "moov" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.TRAK.getFieldName()); - int endOfFirstTrackInBuffer = mvhdBuffer.position() + boxHeader.getDataLength(); - - if (boxHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - //Level 3-Searching for "mdia" within "trak" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDIA.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - //Level 4-Searching for "mdhd" within "mdia" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDHD.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - Mp4MdhdBox mdhd = new Mp4MdhdBox(boxHeader, mvhdBuffer.slice()); - info.setSamplingRate(mdhd.getSampleRate()); - - //Level 4-Searching for "hdlr" within "mdia" - /*We dont currently need to process this because contains nothing we want - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.HDLR.getFieldName()); - if (boxHeader == null) - { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - Mp4HdlrBox hdlr = new Mp4HdlrBox(boxHeader, mvhdBuffer.slice()); - hdlr.processData(); - */ - - //Level 4-Searching for "minf" within "mdia" - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MINF.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - - //Level 5-Searching for "smhd" within "minf" - //Only an audio track would have a smhd frame - int pos = mvhdBuffer.position(); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.SMHD.getFieldName()); - if (boxHeader == null) { - mvhdBuffer.position(pos); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.VMHD.getFieldName()); - //try easy check to confirm that it is video - if (boxHeader != null) { - throw new CannotReadVideoException(ErrorMessage.MP4_FILE_IS_VIDEO.getMsg()); - } else { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - } - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - - //Level 5-Searching for "stbl within "minf" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STBL.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - - //Level 6-Searching for "stsd within "stbl" and process it direct data, dont think these are mandatory so dont throw - //exception if unable to find - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STSD.getFieldName()); - if (boxHeader != null) { - Mp4StsdBox stsd = new Mp4StsdBox(boxHeader, mvhdBuffer); - stsd.processData(); - int positionAfterStsdHeaderAndData = mvhdBuffer.position(); - - ///Level 7-Searching for "mp4a within "stsd" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MP4A.getFieldName()); - if (boxHeader != null) { - ByteBuffer mp4aBuffer = mvhdBuffer.slice(); - Mp4Mp4aBox mp4a = new Mp4Mp4aBox(boxHeader, mp4aBuffer); - mp4a.processData(); - //Level 8-Searching for "esds" within mp4a to get No Of Channels and bitrate - boxHeader = Mp4BoxHeader.seekWithinLevel(mp4aBuffer, Mp4AtomIdentifier.ESDS.getFieldName()); - if (boxHeader != null) { - Mp4EsdsBox esds = new Mp4EsdsBox(boxHeader, mp4aBuffer.slice()); - - //Set Bitrate in kbps - info.setBitrate(esds.getAvgBitrate() / 1000); - - //Set Number of Channels - info.setChannelNumber(esds.getNumberOfChannels()); - - info.setKind(esds.getKind()); - info.setProfile(esds.getAudioProfile()); - - info.setEncodingType(EncoderType.AAC.getDescription()); - } - } else { - //Level 7 -Searching for drms within stsd instead (m4p files) - mvhdBuffer.position(positionAfterStsdHeaderAndData); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.DRMS.getFieldName()); - if (boxHeader != null) { - Mp4DrmsBox drms = new Mp4DrmsBox(boxHeader, mvhdBuffer); - drms.processData(); - - //Level 8-Searching for "esds" within drms to get No Of Channels and bitrate - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.ESDS.getFieldName()); - if (boxHeader != null) { - Mp4EsdsBox esds = new Mp4EsdsBox(boxHeader, mvhdBuffer.slice()); - - //Set Bitrate in kbps - info.setBitrate(esds.getAvgBitrate() / 1000); - - //Set Number of Channels - info.setChannelNumber(esds.getNumberOfChannels()); - - info.setKind(esds.getKind()); - info.setProfile(esds.getAudioProfile()); - - info.setEncodingType(EncoderType.DRM_AAC.getDescription()); - } - } - //Level 7-Searching for alac (Apple Lossless) instead - else { - mvhdBuffer.position(positionAfterStsdHeaderAndData); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.ALAC.getFieldName()); - if (boxHeader != null) { - //Process First Alac - Mp4AlacBox alac = new Mp4AlacBox(boxHeader, mvhdBuffer); - alac.processData(); - - //Level 8-Searching for 2nd "alac" within box that contains the info we really want - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.ALAC.getFieldName()); - if (boxHeader != null) { - alac = new Mp4AlacBox(boxHeader, mvhdBuffer); - alac.processData(); - info.setEncodingType(EncoderType.APPLE_LOSSLESS.getDescription()); - info.setChannelNumber(alac.getChannels()); - info.setBitrate(alac.getBitRate() / 1000); - info.setBitsPerSample(alac.getSampleSize()); - } - } - } - } - } - //Set default channels if couldn't calculate it - if (info.getChannelNumber() == -1) { - info.setChannelNumber(2); - } - - //Set default bitrate if couldnt calculate it - if (info.getBitRateAsNumber() == -1) { - info.setBitrate(128); - } - - //Set default bits per sample if couldn't calculate it - if (info.getBitsPerSample() == -1) { - info.setBitsPerSample(16); - } - - //This is the most likely option if cant find a match - if (info.getEncodingType().equals("")) { - info.setEncodingType(EncoderType.AAC.getDescription()); - } - - logger.config(info.toString()); - - //Level 2-Searching for others "trak" within "moov", if we find any traks containing video - //then reject it if no track if not video then we allow it because many encoders seem to contain all sorts - //of stuff that you wouldn't expect in an audio track - mvhdBuffer.position(endOfFirstTrackInBuffer); - while (mvhdBuffer.hasRemaining()) { - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.TRAK.getFieldName()); - if (boxHeader != null) { - if (isTrackAtomVideo(ftyp, boxHeader, mvhdBuffer)) { - throw new CannotReadVideoException(ErrorMessage.MP4_FILE_IS_VIDEO.getMsg()); - } - } else { - break; - } - } - - //Build AtomTree to ensure it is valid, this means we can detect any problems early on - new Mp4AtomTree(raf, false); - - return info; - } - - -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4TagReader.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4TagReader.java deleted file mode 100644 index 2aa502e..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4TagReader.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.audio.mp4.atom.Mp4MetaBox; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.Mp4NonStandardFieldKey; -import org.jaudiotagger.tag.mp4.Mp4Tag; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import org.jaudiotagger.tag.mp4.field.*; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Reads metadata from mp4, - *

    - *

    The metadata tags are usually held under the ilst atom as shown below

    - *

    Valid Exceptions to the rule:

    - *

    Can be no udta atom with meta rooted immediately under moov instead

    - *

    Can be no udta/meta atom at all

    - *

    - *

    - * |--- ftyp
    - * |--- moov
    - * |......|
    - * |......|----- mvdh
    - * |......|----- trak
    - * |......|----- udta
    - * |..............|
    - * |..............|-- meta
    - * |....................|
    - * |....................|-- hdlr
    - * |....................|-- ilst
    - * |.........................|
    - * |.........................|---- @nam (Optional for each metadatafield)
    - * |.........................|.......|-- data
    - * |.........................|....... ecetera
    - * |.........................|---- ---- (Optional for reverse dns field)
    - * |.................................|-- mean
    - * |.................................|-- name
    - * |.................................|-- data
    - * |.................................... ecetere
    - * |
    - * |--- mdat
    - * 
    - * Note:In the case of coverart MP4 holds all the coverart within individual dataitems all within - * a single covr atom, we will add separate mp4field for each image. - * - * @param tag - * @param header - * @param raw - * @return - * @throws UnsupportedEncodingException - */ - private void createMp4Field(Mp4Tag tag, Mp4BoxHeader header, ByteBuffer raw) throws UnsupportedEncodingException { - //Reverse Dns Atom - if (header.getId().equals(Mp4TagReverseDnsField.IDENTIFIER)) { - // - try { - TagField field = new Mp4TagReverseDnsField(header, raw); - tag.addField(field); - } catch (Exception e) { - logger.warning(ErrorMessage.MP4_UNABLE_READ_REVERSE_DNS_FIELD.getMsg(e.getMessage())); - TagField field = new Mp4TagRawBinaryField(header, raw); - tag.addField(field); - } - } - //Normal Parent with Data atom - else { - int currentPos = raw.position(); - boolean isDataIdentifier = Utils.getString(raw, Mp4BoxHeader.IDENTIFIER_POS, Mp4BoxHeader.IDENTIFIER_LENGTH, "ISO-8859-1").equals(Mp4DataBox.IDENTIFIER); - raw.position(currentPos); - if (isDataIdentifier) { - //Need this to decide what type of Field to create - int type = Utils.getIntBE(raw, Mp4DataBox.TYPE_POS_INCLUDING_HEADER, Mp4DataBox.TYPE_POS_INCLUDING_HEADER + Mp4DataBox.TYPE_LENGTH - 1); - Mp4FieldType fieldType = Mp4FieldType.getFieldType(type); - logger.config("Box Type id:" + header.getId() + ":type:" + fieldType); - - //Special handling for some specific identifiers otherwise just base on class id - if (header.getId().equals(Mp4FieldKey.TRACK.getFieldName())) { - TagField field = new Mp4TrackField(header.getId(), raw); - tag.addField(field); - } else if (header.getId().equals(Mp4FieldKey.DISCNUMBER.getFieldName())) { - TagField field = new Mp4DiscNoField(header.getId(), raw); - tag.addField(field); - } else if (header.getId().equals(Mp4FieldKey.GENRE.getFieldName())) { - TagField field = new Mp4GenreField(header.getId(), raw); - tag.addField(field); - } else if (header.getId().equals(Mp4FieldKey.ARTWORK.getFieldName()) || Mp4FieldType.isCoverArtType(fieldType)) { - int processedDataSize = 0; - int imageCount = 0; - //The loop should run for each image (each data atom) - while (processedDataSize < header.getDataLength()) { - //There maybe a mixture of PNG and JPEG images so have to check type - //for each subimage (if there are more than one image) - if (imageCount > 0) { - type = Utils.getIntBE(raw, processedDataSize + Mp4DataBox.TYPE_POS_INCLUDING_HEADER, - processedDataSize + Mp4DataBox.TYPE_POS_INCLUDING_HEADER + Mp4DataBox.TYPE_LENGTH - 1); - fieldType = Mp4FieldType.getFieldType(type); - } - Mp4TagCoverField field = new Mp4TagCoverField(raw, fieldType); - tag.addField(field); - processedDataSize += field.getDataAndHeaderSize(); - imageCount++; - } - } else if (fieldType == Mp4FieldType.TEXT) { - TagField field = new Mp4TagTextField(header.getId(), raw); - tag.addField(field); - } else if (fieldType == Mp4FieldType.IMPLICIT) { - TagField field = new Mp4TagTextNumberField(header.getId(), raw); - tag.addField(field); - } else if (fieldType == Mp4FieldType.INTEGER) { - TagField field = new Mp4TagByteField(header.getId(), raw); - tag.addField(field); - } else { - boolean existingId = false; - for (Mp4FieldKey key : Mp4FieldKey.values()) { - if (key.getFieldName().equals(header.getId())) { - //The parentHeader is a known id but its field type is not one of the expected types so - //this field is invalid. i.e I received a file with the TMPO set to 15 (Oxf) when it should - //be 21 (ox15) so looks like somebody got their decimal and hex numbering confused - //So in this case best to ignore this field and just write a warning - existingId = true; - logger.warning("Known Field:" + header.getId() + " with invalid field type of:" + type + " is ignored"); - break; - } - } - - //Unknown field id with unknown type so just create as binary - if (!existingId) { - logger.warning("UnKnown Field:" + header.getId() + " with invalid field type of:" + type + " created as binary"); - TagField field = new Mp4TagBinaryField(header.getId(), raw); - tag.addField(field); - } - } - } - //Special Cases - else { - //MediaMonkey 3 CoverArt Attributes field, does not have data items so just - //copy parent and child as is without modification - if (header.getId().equals(Mp4NonStandardFieldKey.AAPR.getFieldName())) { - TagField field = new Mp4TagRawBinaryField(header, raw); - tag.addField(field); - } - //Default case - else { - TagField field = new Mp4TagRawBinaryField(header, raw); - tag.addField(field); - } - } - } - - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/Mp4TagWriter.java b/src/main/java/org/jaudiotagger/audio/mp4/Mp4TagWriter.java deleted file mode 100644 index a1493d8..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/Mp4TagWriter.java +++ /dev/null @@ -1,836 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.mp4.atom.*; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.mp4.Mp4Tag; -import org.jaudiotagger.tag.mp4.Mp4TagCreator; -import org.jaudiotagger.utils.tree.DefaultMutableTreeNode; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - - -/** - * Writes metadata from mp4, the metadata tags are held under the ilst atom as shown below, (note all free atoms are - * optional). - *

    - *

    - * When writing changes the size of all the atoms upto ilst has to be recalculated, then if the size of - * the metadata is increased the size of the free atom (below meta) should be reduced accordingly or vice versa. - * If the size of the metadata has increased by more than the size of the free atom then the size of meta, udta - * and moov should be recalculated and the top level free atom reduced accordingly - * If there is not enough space even if using both of the free atoms, then the mdat atom has to be shifted down - * accordingly to make space, and the stco atom has to have its offsets to mdat chunks table adjusted accordingly. - *

    - * Exceptions are that the meta/udta/ilst do not currently exist, in which udta/meta/ilst are created. Note it is valid - * to have meta/ilst without udta but this is less common so we always try to write files according to the Apple/iTunes - * specification. * - *

    - *

    - *

    - * |--- ftyp
    - * |--- free
    - * |--- moov
    - * |......|
    - * |......|----- mvdh
    - * |......|----- trak
    - * |......|----- udta
    - * |..............|
    - * |..............|-- meta
    - * |....................|
    - * |....................|-- hdlr
    - * |....................|-- ilst
    - * |....................|.. ..|
    - * |....................|.....|---- @nam (Optional for each metadatafield)
    - * |....................|.....|.......|-- data
    - * |....................|.....|....... ecetera
    - * |....................|.....|---- ---- (Optional for reverse dns field)
    - * |....................|.............|-- mean
    - * |....................|.............|-- name
    - * |....................|.............|-- data
    - * |....................|................ ecetere
    - * |....................|-- free
    - * |--- free
    - * |--- mdat
    - * 
    - */ -public class Mp4TagWriter { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.mp4"); - - private Mp4TagCreator tc = new Mp4TagCreator(); - - - /** - * Replace the ilst metadata - *

    - * Because it is the same size as the original data nothing else has to be modified - * - * @param rawIlstData - * @param oldIlstSize - * @param startIstWithinFile - * @param fileReadChannel - * @param fileWriteChannel - * @throws CannotWriteException - * @throws IOException - */ - private void writeMetadataSameSize(ByteBuffer rawIlstData, - long oldIlstSize, - long startIstWithinFile, - FileChannel fileReadChannel, - FileChannel fileWriteChannel, - Mp4BoxHeader tagsHeader) throws CannotWriteException, IOException { - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, startIstWithinFile); - fileWriteChannel.position(startIstWithinFile); - fileWriteChannel.write(rawIlstData); - fileReadChannel.position(startIstWithinFile + oldIlstSize); - - writeDataAfterIlst(fileReadChannel, fileWriteChannel, tagsHeader); - } - - /** - * If the existing files contains a tags atom and chp1 atom underneath the meta atom that means the file was - * encoded by Nero. Applications such as foobar read this non-standard tag before the more usual data within - * ilst causing problems. So the solution is to convert the tags atom and its children into a free atom whilst - * leaving the chp1 atom alone. - * - * @param fileReadChannel - * @param fileWriteChannel - * @param tagsHeader - * @throws IOException - */ - private void writeNeroData(FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader tagsHeader) - throws IOException, CannotWriteException { - //Write from after ilst upto tags atom - long writeBetweenIlstAndTags = tagsHeader.getFilePos() - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), writeBetweenIlstAndTags); - fileWriteChannel.position(fileWriteChannel.position() + writeBetweenIlstAndTags); - - //Replace tags atom (and children) by a free atom - convertandWriteTagsAtomToFreeAtom(fileWriteChannel, tagsHeader); - - //Write after tags atom - fileReadChannel.position(tagsHeader.getFilePos() + tagsHeader.getLength()); - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - - /** - * When the size of the metadata has changed and it cant be compensated for by free atom - * we have to adjust the size of the size field upto the moovheader level for the udta atom and - * its child meta atom. - * - * @param moovHeader - * @param moovBuffer - * @param sizeAdjustment can be negative or positive * - * @param udtaHeader - * @param metaHeader - * @return - * @throws java.io.IOException - */ - private void adjustSizeOfMoovHeader - (Mp4BoxHeader moovHeader, - ByteBuffer moovBuffer, - int sizeAdjustment, - Mp4BoxHeader udtaHeader, - Mp4BoxHeader metaHeader) throws IOException { - //Adjust moov header size, adjusts the underlying buffer - moovHeader.setLength(moovHeader.getLength() + sizeAdjustment); - - //Edit the fields in moovBuffer (note moovbuffer doesnt include header) - if (udtaHeader != null) { - //Write the updated udta atom header to moov buffer - udtaHeader.setLength(udtaHeader.getLength() + sizeAdjustment); - moovBuffer.position((int) (udtaHeader.getFilePos() - moovHeader.getFilePos() - Mp4BoxHeader.HEADER_LENGTH)); - moovBuffer.put(udtaHeader.getHeaderData()); - } - - if (metaHeader != null) { - //Write the updated udta atom header to moov buffer - metaHeader.setLength(metaHeader.getLength() + sizeAdjustment); - moovBuffer.position((int) (metaHeader.getFilePos() - moovHeader.getFilePos() - Mp4BoxHeader.HEADER_LENGTH)); - moovBuffer.put(metaHeader.getHeaderData()); - } - } - - - private void createMetadataAtoms - (Mp4BoxHeader moovHeader, - ByteBuffer moovBuffer, - int sizeAdjustment, - Mp4BoxHeader udtaHeader, - Mp4BoxHeader metaHeader) throws IOException { - //Adjust moov header size - moovHeader.setLength(moovHeader.getLength() + sizeAdjustment); - - } - - - /** - * Write tag to rafTemp file - * - * @param tag tag data - * @param raf current file - * @param rafTemp temporary file for writing - * @throws CannotWriteException - * @throws IOException - */ - public void write(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException { - logger.config("Started writing tag data"); - - //Read Channel for reading from old file - FileChannel fileReadChannel = raf.getChannel(); - - //Write channel for writing to new file - FileChannel fileWriteChannel = rafTemp.getChannel(); - - //TODO we shouldn't need all these variables, and some are very badly named - used by new and old methods - int oldIlstSize = 0; - int relativeIlstposition; - int startIlstWithinFile; - int newIlstSize; - int oldMetaLevelFreeAtomSize; - int topLevelFreePosition; - int topLevelFreeSize; - long endOfMoov = 0; - //Found top level free atom that comes after moov and before mdat, (also true if no free atom ?) - boolean topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata; - - //Found top level free atom that comes between ftyp and moov - boolean topLevelFreeAtomComesBeforeMdatAndMetadata; - - Mp4BoxHeader topLevelFreeHeader; - - Mp4AtomTree atomTree; - - //Build AtomTree - try { - atomTree = new Mp4AtomTree(raf, false); - } catch (CannotReadException cre) { - throw new CannotWriteException(cre.getMessage()); - } - - Mp4BoxHeader mdatHeader = atomTree.getBoxHeader(atomTree.getMdatNode()); - //Unable to find audio so no chance of saving any changes - if (mdatHeader == null) { - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_CANNOT_FIND_AUDIO.getMsg()); - } - - //Go through every field constructing the data that will appear starting from ilst box - ByteBuffer rawIlstData = tc.convert(tag); - rawIlstData.rewind(); - newIlstSize = rawIlstData.limit(); - - //Moov Box header - Mp4BoxHeader moovHeader = atomTree.getBoxHeader(atomTree.getMoovNode()); - long positionWithinFileAfterFindingMoovHeader = moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH; - endOfMoov = moovHeader.getFilePos() + moovHeader.getLength(); - - Mp4StcoBox stco = atomTree.getStco(); - Mp4BoxHeader ilstHeader = atomTree.getBoxHeader(atomTree.getIlstNode()); - Mp4BoxHeader udtaHeader = atomTree.getBoxHeader(atomTree.getUdtaNode()); - Mp4BoxHeader metaHeader = atomTree.getBoxHeader(atomTree.getMetaNode()); - Mp4BoxHeader hdlrMetaHeader = atomTree.getBoxHeader(atomTree.getHdlrWithinMetaNode()); - Mp4BoxHeader tagsHeader = atomTree.getBoxHeader(atomTree.getTagsNode()); - Mp4BoxHeader trakHeader = atomTree.getBoxHeader(atomTree.getTrakNodes().get(0)); - ByteBuffer moovBuffer = atomTree.getMoovBuffer(); - - - //Work out if we/what kind of metadata hierachy we currently have in the file - //Udta - if (udtaHeader != null) { - //Meta - if (metaHeader != null) { - //ilst - record where ilst is,and where it ends - if (ilstHeader != null) { - oldIlstSize = ilstHeader.getLength(); - - //Relative means relative to moov buffer after moov header - startIlstWithinFile = (int) ilstHeader.getFilePos(); - relativeIlstposition = (int) (startIlstWithinFile - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } else { - //Place ilst immediately after existing hdlr atom - if (hdlrMetaHeader != null) { - startIlstWithinFile = (int) hdlrMetaHeader.getFilePos() + hdlrMetaHeader.getLength(); - relativeIlstposition = (int) (startIlstWithinFile - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } - //Place ilst after data fields in meta atom - //TODO Should we create a hdlr atom - else { - startIlstWithinFile = (int) metaHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH + Mp4MetaBox.FLAGS_LENGTH; - relativeIlstposition = (int) ((startIlstWithinFile) - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } - } - } else { - //There no ilst or meta header so we set to position where it would be if it existed - relativeIlstposition = moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH; - startIlstWithinFile = (int) (moovHeader.getFilePos() + moovHeader.getLength()); - } - } - //There no udta header so we are going to create a new structure, but we have to be aware that there might be - //an existing meta box structure in which case we preserve it but with our new structure before it. - else { - //Create new structure just after the end of the trak atom - if (metaHeader != null) { - startIlstWithinFile = (int) trakHeader.getFilePos() + trakHeader.getLength(); - relativeIlstposition = (int) (startIlstWithinFile - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } else { - //There no udta,ilst or meta header so we set to position where it would be if it existed - relativeIlstposition = moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH; - startIlstWithinFile = (int) (moovHeader.getFilePos() + moovHeader.getLength()); - } - } - - //Find size of Level-4 Free atom (if any) immediately after ilst atom - oldMetaLevelFreeAtomSize = getMetaLevelFreeAtomSize(atomTree); - - - //Level-1 free atom - topLevelFreePosition = 0; - topLevelFreeSize = 0; - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata = true; - topLevelFreeAtomComesBeforeMdatAndMetadata = false; - for (DefaultMutableTreeNode freeNode : atomTree.getFreeNodes()) { - DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) freeNode.getParent(); - if (parentNode.isRoot()) { - topLevelFreeHeader = ((Mp4BoxHeader) freeNode.getUserObject()); - topLevelFreeSize = topLevelFreeHeader.getLength(); - topLevelFreePosition = (int) topLevelFreeHeader.getFilePos(); - break; - } - } - - if (topLevelFreeSize > 0) { - if (topLevelFreePosition > mdatHeader.getFilePos()) { - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata = false; - } else if (topLevelFreePosition < moovHeader.getFilePos()) { - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata = false; - topLevelFreeAtomComesBeforeMdatAndMetadata = true; - } - } else { - topLevelFreePosition = (int) mdatHeader.getFilePos(); - } - - logger.config("Read header successfully ready for writing"); - //The easiest option since no difference in the size of the metadata so all we have to do is - //create a new file identical to first file but with replaced metadata - if (oldIlstSize == newIlstSize) { - logger.config("Writing:Option 1:Same Size"); - writeMetadataSameSize(rawIlstData, oldIlstSize, startIlstWithinFile, fileReadChannel, fileWriteChannel, tagsHeader); - } - //.. we just need to increase the size of the free atom below the meta atom, and replace the metadata - //no other changes necessary and total file size remains the same - else if (oldIlstSize > newIlstSize) { - //Create an amended freeBaos atom and write it if it previously existed as a free atom immediately - //after ilst as a child of meta - if (oldMetaLevelFreeAtomSize > 0) { - logger.config("Writing:Option 2:Smaller Size have free atom:" + oldIlstSize + ":" + newIlstSize); - writeDataUptoIncludingIlst(fileReadChannel, fileWriteChannel, oldIlstSize, startIlstWithinFile, rawIlstData); - - //Write the modified free atom that comes after ilst - int newFreeSize = oldMetaLevelFreeAtomSize + (oldIlstSize - newIlstSize); - Mp4FreeBox newFreeBox = new Mp4FreeBox(newFreeSize - Mp4BoxHeader.HEADER_LENGTH); - fileWriteChannel.write(newFreeBox.getHeader().getHeaderData()); - fileWriteChannel.write(newFreeBox.getData()); - - //Skip over the read channel old free atom - fileReadChannel.position(fileReadChannel.position() + oldMetaLevelFreeAtomSize); - - writeDataAfterIlst(fileReadChannel, fileWriteChannel, tagsHeader); - } - //No free atom we need to create a new one or adjust top level free atom - else { - int newFreeSize = (oldIlstSize - newIlstSize) - Mp4BoxHeader.HEADER_LENGTH; - //We need to create a new one, so dont have to adjust all the headers but only works if the size - //of tags has decreased by more 8 characters so there is enough room for the free boxes header we take - //into account size of new header in calculating size of box - if (newFreeSize > 0) { - logger.config("Writing:Option 3:Smaller Size can create free atom"); - writeDataUptoIncludingIlst(fileReadChannel, fileWriteChannel, oldIlstSize, startIlstWithinFile, rawIlstData); - - //Create new free box - Mp4FreeBox newFreeBox = new Mp4FreeBox(newFreeSize); - fileWriteChannel.write(newFreeBox.getHeader().getHeaderData()); - fileWriteChannel.write(newFreeBox.getData()); - - writeDataAfterIlst(fileReadChannel, fileWriteChannel, tagsHeader); - } - //Ok everything in this bit of tree has to be recalculated because eight or less bytes smaller - else { - logger.config("Writing:Option 4:Smaller Size <=8 cannot create free atoms"); - - //Size will be this amount smaller - int sizeReducedBy = oldIlstSize - newIlstSize; - - //Write stuff before Moov (ftyp) - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, moovHeader.getFilePos()); - fileWriteChannel.position(moovHeader.getFilePos()); - - //Edit stco atom within moov header, we need to adjust offsets by the amount mdat is going to be shifted - //unless mdat is at start of file - if (mdatHeader.getFilePos() > moovHeader.getFilePos()) { - stco.adjustOffsets(-sizeReducedBy); - } - - //Edit and rewrite the Moov,Udta and Meta header in moov buffer - adjustSizeOfMoovHeader(moovHeader, moovBuffer, -sizeReducedBy, udtaHeader, metaHeader); - fileWriteChannel.write(moovHeader.getHeaderData()); - moovBuffer.rewind(); - moovBuffer.limit(relativeIlstposition); - fileWriteChannel.write(moovBuffer); - - //Now write ilst data - fileWriteChannel.write(rawIlstData); - fileReadChannel.position(startIlstWithinFile + oldIlstSize); - writeDataAfterIlst(fileReadChannel, fileWriteChannel, tagsHeader); - } - } - } - //Size of metadata has increased, the most complex situation, more atoms affected - else { - int additionalSpaceRequiredForMetadata = newIlstSize - oldIlstSize; - - //We can fit the metadata in under the meta item just by using some of the padding available in the free - //atom under the meta atom need to take of the side of free header otherwise might end up with - //solution where can fit in data, but cant fit in free atom header - if (additionalSpaceRequiredForMetadata <= (oldMetaLevelFreeAtomSize - Mp4BoxHeader.HEADER_LENGTH)) { - int newFreeSize = oldMetaLevelFreeAtomSize - (additionalSpaceRequiredForMetadata); - logger.config("Writing:Option 5;Larger Size can use meta free atom need extra:" + newFreeSize + "bytes"); - - writeDataUptoIncludingIlst(fileReadChannel, fileWriteChannel, oldIlstSize, startIlstWithinFile, rawIlstData); - - //Create an amended smaller freeBaos atom and write it to file - Mp4FreeBox newFreeBox = new Mp4FreeBox(newFreeSize - Mp4BoxHeader.HEADER_LENGTH); - fileWriteChannel.write(newFreeBox.getHeader().getHeaderData()); - fileWriteChannel.write(newFreeBox.getData()); - - //Skip over the read channel old free atom - fileReadChannel.position(fileReadChannel.position() + oldMetaLevelFreeAtomSize); - - writeDataAfterIlst(fileReadChannel, fileWriteChannel, tagsHeader); - } - //There is not enough padding in the metadata free atom anyway - //Size meta needs to be increased by (if not writing a free atom) - //Special Case this could actually be negative (upto -8)if is actually enough space but would - //not be able to write free atom properly, it doesn't matter the parent atoms would still - //need their sizes adjusted. - else { - int additionalMetaSizeThatWontFitWithinMetaAtom = additionalSpaceRequiredForMetadata - (oldMetaLevelFreeAtomSize); - - //Write stuff before Moov (ftyp) - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, positionWithinFileAfterFindingMoovHeader - Mp4BoxHeader.HEADER_LENGTH); - fileWriteChannel.position(positionWithinFileAfterFindingMoovHeader - Mp4BoxHeader.HEADER_LENGTH); - - if (udtaHeader == null) { - logger.config("Writing:Option 5.1;No udta atom"); - - Mp4HdlrBox hdlrBox = Mp4HdlrBox.createiTunesStyleHdlrBox(); - Mp4MetaBox metaBox = Mp4MetaBox.createiTunesStyleMetaBox(hdlrBox.getHeader().getLength() + rawIlstData.limit()); - udtaHeader = new Mp4BoxHeader(Mp4AtomIdentifier.UDTA.getFieldName()); - udtaHeader.setLength(Mp4BoxHeader.HEADER_LENGTH + metaBox.getHeader().getLength()); - - additionalMetaSizeThatWontFitWithinMetaAtom = - additionalMetaSizeThatWontFitWithinMetaAtom + (udtaHeader.getLength() - rawIlstData.limit()); - - //Edit stco atom within moov header, if the free atom comes after mdat OR - //(there is not enough space in the top level free atom - //or special case of matching exactly the free atom plus header) - if ((!topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata) - || ((topLevelFreeSize - Mp4BoxHeader.HEADER_LENGTH < additionalMetaSizeThatWontFitWithinMetaAtom) - && (topLevelFreeSize != additionalMetaSizeThatWontFitWithinMetaAtom))) { - //We don't bother using the top level free atom coz not big enough anyway, we need to adjust offsets - //by the amount mdat is going to be shifted - if (mdatHeader.getFilePos() > moovHeader.getFilePos()) { - logger.config("Adjusting Offsets"); - stco.adjustOffsets(additionalMetaSizeThatWontFitWithinMetaAtom); - } - } - - //Edit and rewrite the Moov header - moovHeader.setLength(moovHeader.getLength() + additionalMetaSizeThatWontFitWithinMetaAtom); - - fileWriteChannel.write(moovHeader.getHeaderData()); - moovBuffer.rewind(); - moovBuffer.limit(relativeIlstposition); - fileWriteChannel.write(moovBuffer); - - //Write new atoms required for holding metadata in itunes format - fileWriteChannel.write(udtaHeader.getHeaderData()); - fileWriteChannel.write(metaBox.getHeader().getHeaderData()); - fileWriteChannel.write(metaBox.getData()); - fileWriteChannel.write(hdlrBox.getHeader().getHeaderData()); - fileWriteChannel.write(hdlrBox.getData()); - } else if (metaHeader == null) { - //#291:In this case we throwaway editing udta header and create a new one, would be beter if we coul - //keep the info but rather difficult. - logger.config("Writing:Option 5.2;No meta atom"); - - int oldUdtaHeaderLength = udtaHeader.getLength(); - Mp4HdlrBox hdlrBox = Mp4HdlrBox.createiTunesStyleHdlrBox(); - Mp4MetaBox metaBox = Mp4MetaBox.createiTunesStyleMetaBox(hdlrBox.getHeader().getLength() + rawIlstData.limit()); - udtaHeader = new Mp4BoxHeader(Mp4AtomIdentifier.UDTA.getFieldName()); - udtaHeader.setLength(Mp4BoxHeader.HEADER_LENGTH + metaBox.getHeader().getLength()); - - additionalMetaSizeThatWontFitWithinMetaAtom = - additionalMetaSizeThatWontFitWithinMetaAtom + (udtaHeader.getLength() - rawIlstData.limit()); - - //Edit stco atom within moov header, if the free atom comes after mdat OR - //(there is not enough space in the top level free atom - //or special case of matching exactly the free atom plus header) - if ((!topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata) - || ((topLevelFreeSize - Mp4BoxHeader.HEADER_LENGTH < additionalMetaSizeThatWontFitWithinMetaAtom) - && (topLevelFreeSize != additionalMetaSizeThatWontFitWithinMetaAtom))) { - //We don't bother using the top level free atom coz not big enough anyway, we need to adjust offsets - //by the amount mdat is going to be shifted - if (mdatHeader.getFilePos() > moovHeader.getFilePos()) { - logger.config("Adjusting Offsets"); - stco.adjustOffsets(additionalMetaSizeThatWontFitWithinMetaAtom); - } - } - - //Edit and rewrite the Moov header - moovHeader.setLength(moovHeader.getLength() - oldUdtaHeaderLength + additionalMetaSizeThatWontFitWithinMetaAtom); - - fileWriteChannel.write(moovHeader.getHeaderData()); - moovBuffer.rewind(); - moovBuffer.limit(relativeIlstposition - oldUdtaHeaderLength); - fileWriteChannel.write(moovBuffer); - - //Write new atoms required for holding metadata in itunes format - fileWriteChannel.write(udtaHeader.getHeaderData()); - fileWriteChannel.write(metaBox.getHeader().getHeaderData()); - fileWriteChannel.write(metaBox.getData()); - fileWriteChannel.write(hdlrBox.getHeader().getHeaderData()); - fileWriteChannel.write(hdlrBox.getData()); - } else { - logger.config("Writing:Option 5.3;udta atom exists"); - - //Edit stco atom within moov header, if the free atom comes after mdat OR - //(there is not enough space in the top level free atom - //or special case of matching exactly the free atom plus header) - if ((!topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata) - || ((topLevelFreeSize - Mp4BoxHeader.HEADER_LENGTH < additionalMetaSizeThatWontFitWithinMetaAtom) - && (topLevelFreeSize != additionalMetaSizeThatWontFitWithinMetaAtom))) { - //We don't bother using the top level free atom coz not big enough anyway, we need to adjust offsets - //by the amount mdat is going to be shifted - if (mdatHeader.getFilePos() > moovHeader.getFilePos()) { - stco.adjustOffsets(additionalMetaSizeThatWontFitWithinMetaAtom); - } - } - - //Edit and rewrite the Moov header - adjustSizeOfMoovHeader(moovHeader, moovBuffer, additionalMetaSizeThatWontFitWithinMetaAtom, udtaHeader, metaHeader); - - fileWriteChannel.write(moovHeader.getHeaderData()); - - //Now write from this edited buffer up until ilst atom - moovBuffer.rewind(); - moovBuffer.limit(relativeIlstposition); - fileWriteChannel.write(moovBuffer); - } - - //Now write ilst data - fileWriteChannel.write(rawIlstData); - - //Skip over the read channel old meta level free atom because now used up - fileReadChannel.position(startIlstWithinFile + oldIlstSize); - fileReadChannel.position(fileReadChannel.position() + oldMetaLevelFreeAtomSize); - - if (tagsHeader != null) { - //Write from after ilst upto tags atom - long writeBetweenIlstAndTags = tagsHeader.getFilePos() - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), writeBetweenIlstAndTags); - fileWriteChannel.position(fileWriteChannel.position() + writeBetweenIlstAndTags); - convertandWriteTagsAtomToFreeAtom(fileWriteChannel, tagsHeader); - - //Write after tags atom upto end of moov - fileReadChannel.position(tagsHeader.getFilePos() + tagsHeader.getLength()); - long extraData = endOfMoov - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), extraData); - } else { - //Now write the rest of children under moov which wont have changed - long extraData = endOfMoov - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), extraData); - fileWriteChannel.position(fileWriteChannel.position() + extraData); - } - - //If we have top level free atom that comes before mdat we might be able to use it but only if - //the free atom actually come after the the metadata - if (topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata && (topLevelFreePosition >= startIlstWithinFile)) { - //If the shift is less than the space available in this second free atom data size we should - //minimize the free atom accordingly (then we don't have to update stco atom) - //note could be a double negative as additionalMetaSizeThatWontFitWithinMetaAtom could be -1 to -8 but thats ok stills works - //ok - if (topLevelFreeSize - Mp4BoxHeader.HEADER_LENGTH >= additionalMetaSizeThatWontFitWithinMetaAtom) { - logger.config("Writing:Option 6;Larger Size can use top free atom"); - Mp4FreeBox freeBox = new Mp4FreeBox((topLevelFreeSize - Mp4BoxHeader.HEADER_LENGTH) - additionalMetaSizeThatWontFitWithinMetaAtom); - fileWriteChannel.write(freeBox.getHeader().getHeaderData()); - fileWriteChannel.write(freeBox.getData()); - - //Skip over the read channel old free atom - fileReadChannel.position(fileReadChannel.position() + topLevelFreeSize); - - //Write Mdat - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - //If the space required is identical to total size of the free space (inc header) - //we could just remove the header - else if (topLevelFreeSize == additionalMetaSizeThatWontFitWithinMetaAtom) { - logger.config("Writing:Option 7;Larger Size uses top free atom including header"); - //Skip over the read channel old free atom - fileReadChannel.position(fileReadChannel.position() + topLevelFreeSize); - - //Write Mdat - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - //Mdat is going to have to move anyway, so keep free atom as is and write it and mdat - //(have already updated stco above) - else { - logger.config("Writing:Option 8;Larger Size cannot use top free atom"); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), fileReadChannel.size() - fileReadChannel.position()); - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - } else { - logger.config("Writing:Option 9;Top Level Free comes after Mdat or before Metadata so cant use it"); - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - } - } - //Close all channels to original file - fileReadChannel.close(); - raf.close(); - - checkFileWrittenCorrectly(rafTemp, mdatHeader, fileWriteChannel, stco); - } - - /** - * #385 Write data in chunks, needed if writing large amounts of data - * - * @param fileReadChannel - * @param fileWriteChannel - * @throws IOException - * @throws CannotWriteException - */ - private void writeDataInChunks(FileChannel fileReadChannel, FileChannel fileWriteChannel) - throws IOException, CannotWriteException { - long amountToBeWritten = fileReadChannel.size() - fileReadChannel.position(); - long written = 0; - long chunksize = TagOptionSingleton.getInstance().getWriteChunkSize(); - long count = amountToBeWritten / chunksize; - - long mod = amountToBeWritten % chunksize; - for (int i = 0; i < count; i++) { - written += fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), chunksize); - fileWriteChannel.position(fileWriteChannel.position() + chunksize); - } - written += fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), mod); - if (written != amountToBeWritten) { - throw new CannotWriteException("Was meant to write " + amountToBeWritten + " bytes but only written " + written + " bytes"); - } - } - - /** - * Replace tags atom (and children) by a free atom - * - * @param fileWriteChannel - * @param tagsHeader - * @throws IOException - */ - private void convertandWriteTagsAtomToFreeAtom(FileChannel fileWriteChannel, Mp4BoxHeader tagsHeader) throws IOException { - Mp4FreeBox freeBox = new Mp4FreeBox(tagsHeader.getDataLength()); - fileWriteChannel.write(freeBox.getHeader().getHeaderData()); - fileWriteChannel.write(freeBox.getData()); - } - - /** - * Write the data including new ilst - *

    can be used as long as we dont have to adjust the size of moov header - * - * @param fileReadChannel - * @param fileWriteChannel - * @param oldIlstSize - * @param startIlstWithinFile - * @param rawIlstData - * @throws IOException - */ - private void writeDataUptoIncludingIlst(FileChannel fileReadChannel, FileChannel fileWriteChannel, int oldIlstSize, int startIlstWithinFile, ByteBuffer rawIlstData) throws IOException { - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, startIlstWithinFile); - fileWriteChannel.position(startIlstWithinFile); - fileWriteChannel.write(rawIlstData); - fileReadChannel.position(startIlstWithinFile + oldIlstSize); - } - - /** - * Write data after ilst upto the end of the file - *

    - *

    Can be used if dont need to adjust size of moov header of modify top level free atoms - * - * @param fileReadChannel - * @param fileWriteChannel - * @param tagsHeader - * @throws IOException - */ - private void writeDataAfterIlst(FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader tagsHeader) - throws IOException, CannotWriteException { - if (tagsHeader != null) { - //Write from after free upto tags atom - writeNeroData(fileReadChannel, fileWriteChannel, tagsHeader); - } else { - //Now write the rest of the file which won't have changed - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - } - - /** - * Determine the size of the free atom immediately after ilst atom at the same level (if any), we can use this if - * ilst needs to grow or shrink because of more less metadata - * - * @param atomTree - * @return - */ - private int getMetaLevelFreeAtomSize(Mp4AtomTree atomTree) { - int oldMetaLevelFreeAtomSize;//Level 4 - Free - oldMetaLevelFreeAtomSize = 0; - - for (DefaultMutableTreeNode freeNode : atomTree.getFreeNodes()) { - DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) freeNode.getParent(); - DefaultMutableTreeNode brotherNode = freeNode.getPreviousSibling(); - if (!parentNode.isRoot()) { - Mp4BoxHeader parentHeader = ((Mp4BoxHeader) parentNode.getUserObject()); - Mp4BoxHeader freeHeader = ((Mp4BoxHeader) freeNode.getUserObject()); - - //We are only interested in free atoms at this level if they come after the ilst node - if (brotherNode != null) { - Mp4BoxHeader brotherHeader = ((Mp4BoxHeader) brotherNode.getUserObject()); - - if (parentHeader.getId().equals(Mp4AtomIdentifier.META.getFieldName()) - && - brotherHeader.getId().equals(Mp4AtomIdentifier.ILST.getFieldName())) { - oldMetaLevelFreeAtomSize = freeHeader.getLength(); - break; - } - } - } - } - return oldMetaLevelFreeAtomSize; - } - - /** - * Check File Written Correctly - * - * @param rafTemp - * @param mdatHeader - * @param fileWriteChannel - * @param stco - * @throws CannotWriteException - * @throws IOException - */ - private void checkFileWrittenCorrectly(RandomAccessFile rafTemp, Mp4BoxHeader mdatHeader, FileChannel fileWriteChannel, Mp4StcoBox stco) - throws CannotWriteException, IOException { - - logger.config("Checking file has been written correctly"); - - try { - //Create a tree from the new file - Mp4AtomTree newAtomTree; - newAtomTree = new Mp4AtomTree(rafTemp, false); - - //Check we still have audio data file, and check length - Mp4BoxHeader newMdatHeader = newAtomTree.getBoxHeader(newAtomTree.getMdatNode()); - if (newMdatHeader == null) { - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_NO_DATA.getMsg()); - } - if (newMdatHeader.getLength() != mdatHeader.getLength()) { - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_DATA_CORRUPT.getMsg()); - } - - //Should always have udta atom after writing to file - Mp4BoxHeader newUdtaHeader = newAtomTree.getBoxHeader(newAtomTree.getUdtaNode()); - if (newUdtaHeader == null) { - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_NO_TAG_DATA.getMsg()); - } - - //Should always have meta atom after writing to file - Mp4BoxHeader newMetaHeader = newAtomTree.getBoxHeader(newAtomTree.getMetaNode()); - if (newMetaHeader == null) { - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_NO_TAG_DATA.getMsg()); - } - - //Check offsets are correct, may not match exactly in original file so just want to make - //sure that the discrepancy if any is preserved - Mp4StcoBox newStco = newAtomTree.getStco(); - - logger.finer("stco:Original First Offset" + stco.getFirstOffSet()); - logger.finer("stco:Original Diff" + (int) (stco.getFirstOffSet() - mdatHeader.getFilePos())); - logger.finer("stco:Original Mdat Pos" + mdatHeader.getFilePos()); - logger.finer("stco:New First Offset" + newStco.getFirstOffSet()); - logger.finer("stco:New Diff" + (int) ((newStco.getFirstOffSet() - newMdatHeader.getFilePos()))); - logger.finer("stco:New Mdat Pos" + newMdatHeader.getFilePos()); - int diff = (int) (stco.getFirstOffSet() - mdatHeader.getFilePos()); - if ((newStco.getFirstOffSet() - newMdatHeader.getFilePos()) != diff) { - int discrepancy = (int) ((newStco.getFirstOffSet() - newMdatHeader.getFilePos()) - diff); - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_INCORRECT_OFFSETS.getMsg(discrepancy)); - } - } catch (Exception e) { - if (e instanceof CannotWriteException) { - throw (CannotWriteException) e; - } else { - e.printStackTrace(); - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED.getMsg() + ":" + e.getMessage()); - } - } finally { - //Close references to new file - rafTemp.close(); - fileWriteChannel.close(); - } - logger.config("File has been written correctly"); - } - - /** - * Delete the tag - *

    - *

    - *

    This is achieved by writing an empty ilst atom - * - * @param raf - * @param rafTemp - * @throws IOException - */ - public void delete(RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException { - Mp4Tag tag = new Mp4Tag(); - - try { - write(tag, raf, rafTemp); - } catch (CannotWriteException cwe) { - throw new IOException(cwe.getMessage()); - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java deleted file mode 100644 index d080672..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import java.nio.ByteBuffer; - -/** - * Abstract mp4 box, contain a header and then rawdata (which may include child boxes) - */ -public class AbstractMp4Box { - protected Mp4BoxHeader header; - protected ByteBuffer dataBuffer; - - /** - * @return the box header - */ - public Mp4BoxHeader getHeader() { - return header; - } - - /** - * @return rawdata of this box - */ - public ByteBuffer getData() { - return dataBuffer; - } - - -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java deleted file mode 100644 index fb80460..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; - -/** - * AlacBox ( Apple Lossless Codec information description box), - *

    - * Normally occurs twice, the first ALAC contaisn the default values, the second ALAC within contains the real - * values for this audio. - */ -public class Mp4AlacBox extends AbstractMp4Box { - public static final int OTHER_FLAG_LENGTH = 4; - - private int maxSamplePerFrame; // 32bit - private int unknown1; // 8bit - private int sampleSize; // 8bit - private int historyMult; // 8bit - private int initialHistory; // 8bit - private int kModifier; // 8bit - private int channels; // 8bit - private int unknown2; // 16bit - private int maxCodedFrameSize; // 32bit - private int bitRate; // 32bit - private int sampleRate; // 32bit - - - /** - * DataBuffer must start from from the start of the body - * - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4AlacBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - this.dataBuffer = dataBuffer; - } - - public void processData() throws CannotReadException { - //Skip version/other flags - dataBuffer.position(dataBuffer.position() + OTHER_FLAG_LENGTH); - - maxSamplePerFrame = Utils.readUBEInt32(dataBuffer); - unknown1 = Utils.readUInt8(dataBuffer); - sampleSize = Utils.readUInt8(dataBuffer); - historyMult = Utils.readUInt8(dataBuffer); - initialHistory = Utils.readUInt8(dataBuffer); - kModifier = Utils.readUInt8(dataBuffer); - channels = Utils.readUInt8(dataBuffer); - unknown2 = Utils.readUBEInt16(dataBuffer); - maxCodedFrameSize = Utils.readUBEInt32(dataBuffer); - bitRate = Utils.readUBEInt32(dataBuffer); - sampleRate = Utils.readUBEInt32(dataBuffer); - } - - public int getMaxSamplePerFrame() { - return maxSamplePerFrame; - } - - public int getUnknown1() { - return unknown1; - } - - public int getSampleSize() { - return sampleSize; - } - - public int getHistoryMult() { - return historyMult; - } - - public int getInitialHistory() { - return initialHistory; - } - - public int getKModifier() { - return kModifier; - } - - public int getChannels() { - return channels; - } - - public int getUnknown2() { - return unknown2; - } - - public int getMaxCodedFrameSize() { - return maxCodedFrameSize; - } - - public int getBitRate() { - return bitRate; - } - - public int getSampleRate() { - return sampleRate; - } - - public String toString() { - String s = "maxSamplePerFrame:" + maxSamplePerFrame - + "unknown1:" + unknown1 - + "sampleSize:" + sampleSize - + "historyMult:" + historyMult - + "initialHistory:" + initialHistory - + "kModifier:" + kModifier - + "channels:" + channels - + "unknown2 :" + unknown2 - + "maxCodedFrameSize:" + maxCodedFrameSize - + "bitRate:" + bitRate - + "sampleRate:" + sampleRate; - return s; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java deleted file mode 100644 index 1ccef60..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.InvalidBoxHeaderException; -import org.jaudiotagger.audio.exceptions.NullBoxIdException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.logging.ErrorMessage; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Everything in MP4s are held in boxes (formally known as atoms), they are held as a hierachial tree within the MP4. - *

    - * We are most interested in boxes that are used to hold metadata, but we have to know about some other boxes - * as well in order to find them. - *

    - * All boxes consist of a 4 byte box length (big Endian), and then a 4 byte identifier, this is the header - * which is model in this class. - *

    - * The length includes the length of the box including the identifier and the length itself. - * Then they may contain data and/or sub boxes, if they contain subboxes they are known as a parent box. Parent boxes - * shouldn't really contain data, but sometimes they do. - *

    - * Parent boxes length includes the length of their immediate sub boxes - *

    - * This class is normally used by instantiating with the empty constructor, then use the update method - * to pass the header data which is used to read the identifier and the the size of the box - */ -public class Mp4BoxHeader { - public static final int OFFSET_POS = 0; - public static final int IDENTIFIER_POS = 4; - public static final int OFFSET_LENGTH = 4; - public static final int IDENTIFIER_LENGTH = 4; - public static final int HEADER_LENGTH = OFFSET_LENGTH + IDENTIFIER_LENGTH; - //Mp4 uses UTF-8 for all text - public static final String CHARSET_UTF_8 = "UTF-8"; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.mp4.atom"); - //Box length - protected int length; - //Raw Header data - protected ByteBuffer dataBuffer; - //Box identifier - private String id; - //If reading from file , this can be used to hold the headers position in the file - private long filePos; - - /** - * Construct empty header - *

    - * Can be populated later with update method - */ - public Mp4BoxHeader() { - - } - - /** - * Construct header to allow manual creation of header for writing to file - *

    - * - * @param id - */ - public Mp4BoxHeader(String id) { - if (id.length() != IDENTIFIER_LENGTH) { - throw new RuntimeException("Invalid length:atom idenifier should always be 4 characters long"); - } - dataBuffer = ByteBuffer.allocate(HEADER_LENGTH); - try { - this.id = id; - dataBuffer.put(4, id.getBytes("ISO-8859-1")[0]); - dataBuffer.put(5, id.getBytes("ISO-8859-1")[1]); - dataBuffer.put(6, id.getBytes("ISO-8859-1")[2]); - dataBuffer.put(7, id.getBytes("ISO-8859-1")[3]); - } catch (UnsupportedEncodingException uee) { - //Should never happen - throw new RuntimeException(uee); - } - } - - /** - * Construct header - *

    - * Create header using headerdata, expected to find header at headerdata current position - *

    - * Note after processing adjusts position to immediately after header - * - * @param headerData - */ - public Mp4BoxHeader(ByteBuffer headerData) { - update(headerData); - } - - /** - * Seek for box with the specified id starting from the current location of filepointer, - *

    - * Note it wont find the box if it is contained with a level below the current level, nor if we are - * at a parent atom that also contains data and we havent yet processed the data. It will work - * if we are at the start of a child box even if it not the required box as long as the box we are - * looking for is the same level (or the level above in some cases). - * - * @param raf - * @param id - * @return - * @throws java.io.IOException - */ - public static Mp4BoxHeader seekWithinLevel(RandomAccessFile raf, String id) throws IOException { - logger.finer("Started searching for:" + id + " in file at:" + raf.getChannel().position()); - - Mp4BoxHeader boxHeader = new Mp4BoxHeader(); - ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_LENGTH); - int bytesRead = raf.getChannel().read(headerBuffer); - if (bytesRead != HEADER_LENGTH) { - return null; - } - headerBuffer.rewind(); - boxHeader.update(headerBuffer); - while (!boxHeader.getId().equals(id)) { - logger.finer("Found:" + boxHeader.getId() + " Still searching for:" + id + " in file at:" + raf.getChannel().position()); - - //Something gone wrong probably not at the start of an atom so return null; - if (boxHeader.getLength() < Mp4BoxHeader.HEADER_LENGTH) { - return null; - } - int noOfBytesSkipped = raf.skipBytes(boxHeader.getDataLength()); - logger.finer("Skipped:" + noOfBytesSkipped); - if (noOfBytesSkipped < boxHeader.getDataLength()) { - return null; - } - headerBuffer.rewind(); - bytesRead = raf.getChannel().read(headerBuffer); - logger.finer("Header Bytes Read:" + bytesRead); - headerBuffer.rewind(); - if (bytesRead == Mp4BoxHeader.HEADER_LENGTH) { - boxHeader.update(headerBuffer); - } else { - return null; - } - } - return boxHeader; - } - - /** - * Seek for box with the specified id starting from the current location of filepointer, - *

    - * Note it won't find the box if it is contained with a level below the current level, nor if we are - * at a parent atom that also contains data and we havent yet processed the data. It will work - * if we are at the start of a child box even if it not the required box as long as the box we are - * looking for is the same level (or the level above in some cases). - * - * @param data - * @param id - * @return - * @throws java.io.IOException - */ - public static Mp4BoxHeader seekWithinLevel(ByteBuffer data, String id) throws IOException { - logger.finer("Started searching for:" + id + " in bytebuffer at" + data.position()); - - Mp4BoxHeader boxHeader = new Mp4BoxHeader(); - if (data.remaining() >= Mp4BoxHeader.HEADER_LENGTH) { - boxHeader.update(data); - } else { - return null; - } - while (!boxHeader.getId().equals(id)) { - logger.finer("Found:" + boxHeader.getId() + " Still searching for:" + id + " in bytebuffer at" + data.position()); - //Something gone wrong probably not at the start of an atom so return null; - if (boxHeader.getLength() < Mp4BoxHeader.HEADER_LENGTH) { - return null; - } - if (data.remaining() < (boxHeader.getLength() - HEADER_LENGTH)) { - //i.e Could happen if Moov header had size incorrectly recorded - return null; - } - data.position(data.position() + (boxHeader.getLength() - HEADER_LENGTH)); - if (data.remaining() >= Mp4BoxHeader.HEADER_LENGTH) { - boxHeader.update(data); - } else { - return null; - } - } - logger.finer("Found:" + id + " in bytebuffer at" + data.position()); - - return boxHeader; - } - - /** - * Create header using headerdata, expected to find header at headerdata current position - *

    - * Note after processing adjusts position to immediately after header - * - * @param headerData - */ - public void update(ByteBuffer headerData) { - //Read header data into byte array - byte[] b = new byte[HEADER_LENGTH]; - headerData.get(b); - //Keep reference to copy of RawData - dataBuffer = ByteBuffer.wrap(b); - - //Calculate box size - this.length = Utils.getIntBE(b, OFFSET_POS, OFFSET_LENGTH - 1); - //Calculate box id - this.id = Utils.getString(b, IDENTIFIER_POS, IDENTIFIER_LENGTH, "ISO-8859-1"); - - logger.finest("Mp4BoxHeader id:" + id + ":length:" + length); - if (id.equals("\0\0\0\0")) { - throw new NullBoxIdException(ErrorMessage.MP4_UNABLE_TO_FIND_NEXT_ATOM_BECAUSE_IDENTIFIER_IS_INVALID.getMsg(id)); - } - - if (length < HEADER_LENGTH) { - throw new InvalidBoxHeaderException(ErrorMessage.MP4_UNABLE_TO_FIND_NEXT_ATOM_BECAUSE_IDENTIFIER_IS_INVALID.getMsg(id, length)); - } - } - - /** - * @return the box identifier - */ - public String getId() { - return id; - } - - /** - * Set the Id. - *

    - * Allows you to manully create a header - * This will modify the databuffer accordingly - * - * @param length - */ - public void setId(int length) { - byte[] headerSize = Utils.getSizeBEInt32(length); - dataBuffer.put(5, headerSize[0]); - dataBuffer.put(6, headerSize[1]); - dataBuffer.put(7, headerSize[2]); - dataBuffer.put(8, headerSize[3]); - - this.length = length; - - } - - /** - * @return the length of the boxes data (includes the header size) - */ - public int getLength() { - return length; - } - - /** - * Set the length. - *

    - * This will modify the databuffer accordingly - * - * @param length - */ - public void setLength(int length) { - byte[] headerSize = Utils.getSizeBEInt32(length); - dataBuffer.put(0, headerSize[0]); - dataBuffer.put(1, headerSize[1]); - dataBuffer.put(2, headerSize[2]); - dataBuffer.put(3, headerSize[3]); - - this.length = length; - - } - - /** - * @return the 8 byte header buffer - */ - public ByteBuffer getHeaderData() { - dataBuffer.rewind(); - return dataBuffer; - } - - /** - * @return the length of the data only (does not include the header size) - */ - public int getDataLength() { - return length - HEADER_LENGTH; - } - - public String toString() { - return "Box " + id + ":length" + length + ":filepos:" + filePos; - } - - /** - * @return UTF_8 (always used by Mp4) - */ - public String getEncoding() { - return CHARSET_UTF_8; - } - - /** - * @return location in file of the start of file header (i.e where the 4 byte length field starts) - */ - public long getFilePos() { - return filePos; - } - - /** - * Set location in file of the start of file header (i.e where the 4 byte length field starts) - * - * @param filePos - */ - public void setFilePos(long filePos) { - this.filePos = filePos; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java deleted file mode 100644 index 49b0634..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; - -import java.nio.ByteBuffer; - -/** - * DrmsBox Replaces mp4a box on drm files - *

    - * Need to skip over data in order to find esds atom - *

    - * Specification not known, so just look for byte by byte 'esds' and then step back four bytes for size - */ -public class Mp4DrmsBox extends AbstractMp4Box { - /** - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4DrmsBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - this.dataBuffer = dataBuffer; - } - - /** - * Process direct data - * - * @throws CannotReadException - */ - public void processData() throws CannotReadException { - while (dataBuffer.hasRemaining()) { - byte next = dataBuffer.get(); - if (next != (byte) 'e') { - continue; - } - - //Have we found esds identifier, if so adjust buffer to start of esds atom - ByteBuffer tempBuffer = dataBuffer.slice(); - if ((tempBuffer.get() == (byte) 's') & (tempBuffer.get() == (byte) 'd') & (tempBuffer.get() == (byte) 's')) { - dataBuffer.position(dataBuffer.position() - 1 - Mp4BoxHeader.OFFSET_LENGTH); - return; - } - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java deleted file mode 100644 index 5f7f49b..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java +++ /dev/null @@ -1,317 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; - -/** - * EsdsBox ( stream specific description box), usually holds the Bitrate/No of Channels - *

    - * It contains a number of (possibly optional?) sections (section 3 - 6) (containing optional filler) with - * differeent info in each section. - *

    - *

    - * -> 4 bytes version/flags = 8-bit hex version + 24-bit hex flags - * (current = 0) - *

    - * Section 3 - * -> 1 byte ES descriptor type tag = 8-bit hex value 0x03 - * -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - * - types are 0x80,0x81,0xFE - * -> 1 byte descriptor type length = 8-bit unsigned length - * -> 2 bytes ES ID = 16-bit unsigned value - * -> 1 byte stream priority = 8-bit unsigned value - * - Defaults to 16 and ranges from 0 through to 31 - *

    - * Section 4 - * -> 1 byte decoder config descriptor type tag = 8-bit hex value 0x04 - * -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - * - types are 0x80,0x81,0xFE - * -> 1 byte descriptor type length = 8-bit unsigned length * - * -> 1 byte object type ID = 8-bit unsigned value - * -> 6 bits stream type = 3/4 byte hex value - * - type IDs are object descript. = 1 ; clock ref. = 2 - * - type IDs are scene descript. = 4 ; visual = 4 - * - type IDs are audio = 5 ; MPEG-7 = 6 ; IPMP = 7 - * - type IDs are OCI = 8 ; MPEG Java = 9 - * - type IDs are user private = 32 - * -> 1 bit upstream flag = 1/8 byte hex value - * -> 1 bit reserved flag = 1/8 byte hex value set to 1 - * -> 3 bytes buffer size = 24-bit unsigned value - * -> 4 bytes maximum bit rate = 32-bit unsigned value - * -> 4 bytes average bit rate = 32-bit unsigned value - *

    - * Section 5 - * -> 1 byte decoder specific descriptor type tag 8-bit hex value 0x05 - * -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - * - types are 0x80,0x81,0xFE - * -> 1 byte descriptor type length = 8-bit unsigned length - * -> 1 byte Audio profile Id - * - 5 bits Profile Id - * - 3 bits Unknown - * -> 8 bits other flags - * - 3 bits unknown - * - 2 bits is No of Channels - * - 3 bits unknown - *

    - * Section 6 - *

    - * -> 1 byte SL config descriptor type tag = 8-bit hex value 0x06 - * -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - * - types are 0x80,0x81,0xFE - * -> 1 byte descriptor type length = 8-bit unsigned length - * -> 1 byte SL value = 8-bit hex value set to 0x02 - */ -public class Mp4EsdsBox extends AbstractMp4Box { - public static final int VERSION_FLAG_LENGTH = 1; - public static final int OTHER_FLAG_LENGTH = 3; - public static final int DESCRIPTOR_TYPE_LENGTH = 1; - public static final int ES_ID_LENGTH = 2; - public static final int STREAM_PRIORITY_LENGTH = 1; - public static final int CONFIG_TYPE_LENGTH = 1; - public static final int OBJECT_TYPE_LENGTH = 1; - public static final int STREAM_TYPE_LENGTH = 1; - public static final int BUFFER_SIZE_LENGTH = 3; - public static final int MAX_BITRATE_LENGTH = 4; - public static final int AVERAGE_BITRATE_LENGTH = 4; - public static final int DESCRIPTOR_OBJECT_TYPE_LENGTH = 1; - public static final int CHANNEL_FLAGS_LENGTH = 1; - //Section indentifiers - private static final int SECTION_THREE = 0x03; - private static final int SECTION_FOUR = 0x04; - private static final int SECTION_FIVE = 0x05; - private static final int SECTION_SIX = 0x06; - //Possible Section Filler values - private static final int FILLER_START = 0x80; - private static final int FILLER_OTHER = 0x81; - private static final int FILLER_END = 0xFE; - private static Map kindMap; - private static Map audioProfileMap; - - static { - //Create maps to speed up lookup from raw value to enum - kindMap = new HashMap(); - for (Kind next : Kind.values()) { - kindMap.put(next.getId(), next); - } - - audioProfileMap = new HashMap(); - for (AudioProfile next : AudioProfile.values()) { - audioProfileMap.put(next.getId(), next); - } - } - - //Data we are tring to extract - private Kind kind; - private AudioProfile audioProfile; - private int numberOfChannels; - private int maxBitrate; - private int avgBitrate; - - /** - * DataBuffer must start from from the start of the body - * - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4EsdsBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - - //Not currently used, as lengths can extend over more than one section i think - int sectionThreeLength; - int sectionFourLength; - int sectionFiveLength; - int sectionSixLength; - - //As explained earlier the length of this atom is not fixed so processing is a bit more difficult - //Process Flags - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH); - - //Process Section 3 if exists - if (dataBuffer.get() == SECTION_THREE) { - sectionThreeLength = processSectionHeader(dataBuffer); - //Skip Other Section 3 data - dataBuffer.position(dataBuffer.position() + ES_ID_LENGTH + STREAM_PRIORITY_LENGTH); - } - - //Process Section 4 (to getFields type and bitrate) - if (dataBuffer.get() == SECTION_FOUR) { - sectionFourLength = processSectionHeader(dataBuffer); - - //kind (in iTunes) - kind = kindMap.get((int) dataBuffer.get()); - - //Skip Other Section 4 data - dataBuffer.position(dataBuffer.position() + STREAM_TYPE_LENGTH + BUFFER_SIZE_LENGTH); - - //Bit rates - this.maxBitrate = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + MAX_BITRATE_LENGTH - 1)); - dataBuffer.position(dataBuffer.position() + MAX_BITRATE_LENGTH); - - this.avgBitrate = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + AVERAGE_BITRATE_LENGTH - 1)); - dataBuffer.position(dataBuffer.position() + AVERAGE_BITRATE_LENGTH); - - - } - //Process Section 5,(to getFields no of channels and audioprofile(profile in itunes)) - if (dataBuffer.get() == SECTION_FIVE) { - sectionFiveLength = processSectionHeader(dataBuffer); - - //Audio Profile - audioProfile = audioProfileMap.get((dataBuffer.get() >> 3)); - - //Channels - byte channelByte = dataBuffer.get(); - numberOfChannels = (channelByte << 1) >> 4; - } - - //Process Section 6, not needed ... - - - } - - public int getNumberOfChannels() { - return numberOfChannels; - } - - /** - * @return maximum bit rate (bps) - */ - public int getMaxBitrate() { - return maxBitrate; - } - - /** - * @return average bit rate (bps) - */ - public int getAvgBitrate() { - return avgBitrate; - } - - /** - * Process header, skipping filler bytes and calculating size - * - * @param dataBuffer - * @return section header - */ - public int processSectionHeader(ByteBuffer dataBuffer) { - int datalength; - byte nextByte = dataBuffer.get(); - if (((nextByte & 0xFF) == FILLER_START) || ((nextByte & 0xFF) == FILLER_OTHER) || ((nextByte & 0xFF) == FILLER_END)) { - dataBuffer.get(); - dataBuffer.get(); - datalength = dataBuffer.get(); - } else { - datalength = nextByte; - } - return datalength; - } - - /** - * Only expext MPG_Audio, - * TODO shouldnt matter if another type of audio, but something gone wrong if type of video - * - * @return the file type for the track - */ - public Kind getKind() { - return kind; - } - - /** - * Get audio profile, usually AAC Low Complexity - * - * @return the audio profile - */ - public AudioProfile getAudioProfile() { - return audioProfile; - } - - /** - * File type, held in Section 4 , only really expecting type 0x64 (AAC) - */ - public enum Kind { - V1(1), - V2(2), - MPEG4_VIDEO(32), - MPEG4_AVC_SPS(33), - MPEG4_AVC_PPS(34), - MPEG4_AUDIO(64), - MPEG2_SIMPLE_VIDEO(96), - MPEG2_MAIN_VIDEO(97), - MPEG2_SNR_VIDEO(98), - MPEG2_SPATIAL_VIDEO(99), - MPEG2_HIGH_VIDEO(100), - MPEG2_422_VIDEO(101), - MPEG4_ADTS_MAIN(102), - MPEG4_ADTS_LOW_COMPLEXITY(103), - MPEG4_ADTS_SCALEABLE_SAMPLING(104), - MPEG2_ADTS_MAIN(105), - MPEG1_VIDEO(106), - MPEG1_ADTS(107), - JPEG_VIDEO(108), - PRIVATE_AUDIO(192), - PRIVATE_VIDEO(208), - PCM_LITTLE_ENDIAN_AUDIO(224), - VORBIS_AUDIO(225), - DOLBY_V3_AUDIO(226), - ALAW_AUDIO(227), - MULAW_AUDIO(228), - ADPCM_AUDIO(229), - PCM_BIG_ENDIAN_AUDIO(230), - YV12_VIDEO(240), - H264_VIDEO(241), - H263_VIDEO(242), - H261_VIDEO(243); - - private int id; - - Kind(int id) { - this.id = id; - } - - public int getId() { - return id; - } - } - - /** - * Audio profile, held in Section 5 this is usually type LOW_COMPLEXITY - */ - public enum AudioProfile { - MAIN(1, "Main"), - LOW_COMPLEXITY(2, "Low Complexity"), - SCALEABLE(3, "Scaleable Sample rate"), - T_F(4, "T/F"), - T_F_MAIN(5, "T/F Main"), - T_F_LC(6, "T/F LC"), - TWIN_VQ(7, "TWIN"), - CELP(8, "CELP"), - HVXC(9, "HVXC"), - HILN(10, "HILN"), - TTSI(11, "TTSI"), - MAIN_SYNTHESIS(12, "MAIN_SYNTHESIS"), - WAVETABLE(13, "WAVETABLE"),; - - private int id; - private String description; - - /** - * @param id it is stored as in file - * @param description human readable description - */ - AudioProfile(int id, String description) { - this.id = id; - this.description = description; - } - - public int getId() { - return id; - } - - public String getDescription() { - return description; - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java deleted file mode 100644 index e7b78f1..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.Mp4AtomIdentifier; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * FreeBox ( padding) - *

    - *

    There are usually two free boxes, one beneath the meta atom and one toplevel atom - */ -public class Mp4FreeBox extends AbstractMp4Box { - /** - * Construct a new FreeBox containing datasize padding (i.e doesnt include header size) - * - * @param datasize padding size - */ - public Mp4FreeBox(int datasize) { - try { - //Header - header = new Mp4BoxHeader(); - ByteArrayOutputStream headerBaos = new ByteArrayOutputStream(); - headerBaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + datasize)); - headerBaos.write(Utils.getDefaultBytes(Mp4AtomIdentifier.FREE.getFieldName(), "ISO-8859-1")); - header.update(ByteBuffer.wrap(headerBaos.toByteArray())); - - //Body - ByteArrayOutputStream freeBaos = new ByteArrayOutputStream(); - for (int i = 0; i < datasize; i++) { - freeBaos.write(0x0); - } - dataBuffer = ByteBuffer.wrap(freeBaos.toByteArray()); - } catch (IOException ioe) { - //This should never happen as were not actually writing to/from a file - throw new RuntimeException(ioe); - } - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java deleted file mode 100644 index 4971ebb..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CodingErrorAction; -import java.util.ArrayList; -import java.util.List; - -/** - * Ftyp (File Type) is the first atom, can be used to help identify the mp4 container type - */ -public class Mp4FtypBox extends AbstractMp4Box { - private static final int MAJOR_BRAND_POS = 0; - private static final int MAJOR_BRAND_LENGTH = 4; - private static final int MAJOR_BRAND_VERSION_POS = 4; - private static final int MAJOR_BRAND_VERSION_LENGTH = 4; - private static final int COMPATIBLE_BRAND_LENGTH = 4; //Can be multiple of these - private String majorBrand; - private int majorBrandVersion; - private List compatibleBrands = new ArrayList(); - - /** - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4FtypBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - this.dataBuffer = dataBuffer; - } - - public void processData() throws CannotReadException { - CharsetDecoder decoder = Charset.forName("ISO-8859-1").newDecoder(); - try { - majorBrand = decoder.decode((ByteBuffer) dataBuffer.slice().limit(MAJOR_BRAND_LENGTH)).toString(); - } catch (CharacterCodingException cee) { - //Ignore - - } - dataBuffer.position(dataBuffer.position() + MAJOR_BRAND_LENGTH); - - majorBrandVersion = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + MAJOR_BRAND_VERSION_LENGTH - 1)); - dataBuffer.position(dataBuffer.position() + MAJOR_BRAND_VERSION_LENGTH); - - while ((dataBuffer.position() < dataBuffer.limit()) && (dataBuffer.limit() - dataBuffer.position() >= COMPATIBLE_BRAND_LENGTH)) { - decoder.onMalformedInput(CodingErrorAction.REPORT); - decoder.onMalformedInput(CodingErrorAction.REPORT); - try { - String brand = decoder.decode((ByteBuffer) dataBuffer.slice().limit(COMPATIBLE_BRAND_LENGTH)).toString(); - //Sometimes just extra groups of four nulls - if (!brand.equals("\u0000\u0000\u0000\u0000")) { - compatibleBrands.add(brand); - } - } catch (CharacterCodingException cee) { - //Ignore - } - dataBuffer.position(dataBuffer.position() + COMPATIBLE_BRAND_LENGTH); - } - } - - - public String toString() { - - String info = "Major Brand:" + majorBrand + "Version:" + majorBrandVersion; - if (compatibleBrands.size() > 0) { - info += "Compatible:"; - for (String brand : compatibleBrands) { - info += brand; - info += ","; - } - return info.substring(0, info.length() - 1); - } - return info; - } - - public String getMajorBrand() { - return majorBrand; - } - - - public int getMajorBrandVersion() { - return majorBrandVersion; - } - - - public List getCompatibleBrands() { - return compatibleBrands; - } - - /** - * Major brand, helps identify whats contained in the file, used by major and compatible brands - * but this is not an exhaustive list, so for that reason we don't force the values read from the file - * to tie in with this enum. - */ - public enum Brand { - ISO14496_1_BASE_MEDIA("isom", "ISO 14496-1"), - ISO14496_12_BASE_MEDIA("iso2", "ISO 14496-12"), - ISO14496_1_VERSION_1("mp41", "ISO 14496-1"), - ISO14496_1_VERSION_2("mp42", "ISO 14496-2:Multi track with BIFS scenes"), - QUICKTIME_MOVIE("qt ", "Original Quicktime"), - JVT_AVC("avc1", "JVT"), - THREEG_MOBILE_MP4("MPA ", "3G Mobile"), - APPLE_AAC_AUDIO("M4P ", "Apple Audio"), - AES_ENCRYPTED_AUDIO("M4B ", "Apple encrypted Audio"), - APPLE_AUDIO("mp71", "Apple Audio"), - ISO14496_12_MPEG7_METADATA("mp71", "MAIN_SYNTHESIS"), - APPLE_AUDIO_ONLY("M4A ", "M4A Audio"), //SOmetimes used by protected mutli track audio - ; - - private String id; - private String description; - - /** - * @param id it is stored as in file - * @param description human readable description - */ - Brand(String id, String description) { - this.id = id; - this.description = description; - } - - public String getId() { - return id; - } - - public String getDescription() { - return description; - } - - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java deleted file mode 100644 index 4509556..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.mp4.Mp4AtomIdentifier; - -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.util.HashMap; -import java.util.Map; - -/** - * HdlrBox ( Handler box), - *

    - * Describes the type of metadata in the following ilst or minf atom - */ -public class Mp4HdlrBox extends AbstractMp4Box { - public static final int VERSION_FLAG_LENGTH = 1; - public static final int OTHER_FLAG_LENGTH = 3; - public static final int RESERVED_FLAG_LENGTH = 4; - public static final int HANDLER_LENGTH = 4; - public static final int RESERVED1_LENGTH = 4; - public static final int RESERVED2_LENGTH = 4; - public static final int RESERVED3_LENGTH = 4; - public static final int NAME_LENGTH = 2; - - public static final int HANDLER_POS = VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + RESERVED_FLAG_LENGTH; - public static final int RESERVED1_POS = HANDLER_POS + HANDLER_LENGTH; - - //Size used by iTunes, but other application could use different size because name field is variable - public static final int ITUNES_META_HDLR_DAT_LENGTH = - VERSION_FLAG_LENGTH + - OTHER_FLAG_LENGTH + - RESERVED_FLAG_LENGTH + - HANDLER_LENGTH + - RESERVED1_LENGTH + - RESERVED2_LENGTH + - RESERVED3_LENGTH + - NAME_LENGTH; - private static Map mediaDataTypeMap; - - static { - //Create maps to speed up lookup from raw value to enum - mediaDataTypeMap = new HashMap(); - for (MediaDataType next : MediaDataType.values()) { - mediaDataTypeMap.put(next.getId(), next); - } - } - - private int reserved; // 32 bit - private String handlerType; // 4 bytes; - private String name; // Variable length but 4 bytes in existing files - private MediaDataType mediaDataType; - - /** - * DataBuffer must start from from the start of the body - * - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4HdlrBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - this.dataBuffer = dataBuffer; - } - - /** - * Create an iTunes style Hdlr box for use within Meta box - *

    - *

    Useful when writing to mp4 that previously didn't contain an mp4 meta atom

    - *

    - *

    Doesnt write the child data but uses it to set the header length, only sets the atoms immediate - * data

    - *

    Useful when writing to mp4 that previously didn't contain an mp4 meta atom

    - * - * @param childrenSize - * @return - */ - public static Mp4MetaBox createiTunesStyleMetaBox(int childrenSize) { - Mp4BoxHeader metaHeader = new Mp4BoxHeader(Mp4AtomIdentifier.META.getFieldName()); - metaHeader.setLength(Mp4BoxHeader.HEADER_LENGTH + Mp4MetaBox.FLAGS_LENGTH + childrenSize); - ByteBuffer metaData = ByteBuffer.allocate(Mp4MetaBox.FLAGS_LENGTH); - Mp4MetaBox metaBox = new Mp4MetaBox(metaHeader, metaData); - return metaBox; - } - - public void processData() throws CannotReadException { - //4-skip the meta flags and check they are the meta flags - byte[] b = new byte[FLAGS_LENGTH]; - dataBuffer.get(b); - if (b[0] != 0) { - throw new CannotReadException(ErrorMessage.MP4_FILE_META_ATOM_CHILD_DATA_NOT_NULL.getMsg()); - } - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java deleted file mode 100644 index 67dbb40..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; - -import java.nio.ByteBuffer; - -/** - * Mp4aBox ( sample (frame encoding) description box) - *

    - * At first glance appears to hold no of channels but actually always returns 2 even for mono recordings - * so just need to skip over data in order to get to child atom esds - *

    - *

    4 bytes version/flags = byte hex version + 24-bit hex flags - * (current = 0) - *

    - * -> 6 bytes reserved = 48-bit value set to zero - * -> 2 bytes data reference index - * = short unsigned index from 'dref' box - * -> 2 bytes QUICKTIME audio encoding version = short hex version - * - default = 0 ; audio data size before decompression = 1 - * -> 2 bytes QUICKTIME audio encoding revision level - * = byte hex version - * - default = 0 ; video can revise this value - * -> 4 bytes QUICKTIME audio encoding vendor - * = long ASCII text string - * - default = 0 - * -> 2 bytes audio channels = short unsigned count - * (mono = 1 ; stereo = 2) - * -> 2 bytes audio sample size = short unsigned value - * (8 or 16) - * -> 2 bytes QUICKTIME audio compression id = short integer value - * - default = 0 - * -> 2 bytes QUICKTIME audio packet size = short value set to zero - * -> 4 bytes audio sample rate = long unsigned fixed point rate - */ -public class Mp4Mp4aBox extends AbstractMp4Box { - public static final int RESERVED_POS = 0; - public static final int REFERENCE_INDEX_POS = 6; - public static final int AUDIO_ENCODING_POS = 8; - public static final int AUDIO_REVISION_POS = 10; - public static final int AUDIO_ENCODING_VENDOR_POS = 12; - public static final int CHANNELS_POS = 16; - public static final int AUDIO_SAMPLE_SIZE_POS = 18; - public static final int AUDIO_COMPRESSION_ID_POS = 20; - public static final int AUDIO_PACKET_SIZE_POS = 22; - public static final int AUDIO_SAMPLE_RATE_POS = 24; - - public static final int RESERVED_LENGTH = 6; - public static final int REFERENCE_INDEX_LENGTH = 2; - public static final int AUDIO_ENCODING_LENGTH = 2; - public static final int AUDIO_REVISION_LENGTH = 2; - public static final int AUDIO_ENCODING_VENDOR_LENGTH = 4; - public static final int CHANNELS_LENGTH = 2; - public static final int AUDIO_SAMPLE_SIZE_LENGTH = 2; - public static final int AUDIO_COMPRESSION_ID_LENGTH = 2; - public static final int AUDIO_PACKET_SIZE_LENGTH = 2; - public static final int AUDIO_SAMPLE_RATE_LENGTH = 4; - - public static final int TOTAL_LENGTH = RESERVED_LENGTH + REFERENCE_INDEX_LENGTH + AUDIO_ENCODING_LENGTH + AUDIO_REVISION_LENGTH + AUDIO_ENCODING_VENDOR_LENGTH + CHANNELS_LENGTH + AUDIO_SAMPLE_SIZE_LENGTH + AUDIO_COMPRESSION_ID_LENGTH + AUDIO_PACKET_SIZE_LENGTH + AUDIO_SAMPLE_RATE_LENGTH; - - - /** - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4Mp4aBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - this.dataBuffer = dataBuffer; - } - - - public void processData() throws CannotReadException { - dataBuffer.position(dataBuffer.position() + TOTAL_LENGTH); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.java deleted file mode 100644 index e142651..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; - -/** - * MvhdBox (movie (presentation) header box) - *

    - *

    This MP4Box contains important audio information we need. It can be used to calculate track length, - * depending on the version field this can be in either short or long format - */ -public class Mp4MvhdBox extends AbstractMp4Box { - public static final int VERSION_FLAG_POS = 0; - public static final int OTHER_FLAG_POS = 1; - public static final int CREATED_DATE_SHORT_POS = 4; - public static final int MODIFIED_DATE_SHORT_POS = 8; - public static final int TIMESCALE_SHORT_POS = 12; - public static final int DURATION_SHORT_POS = 16; - - public static final int CREATED_DATE_LONG_POS = 4; - public static final int MODIFIED_DATE_LONG_POS = 12; - public static final int TIMESCALE_LONG_POS = 20; - public static final int DURATION_LONG_POS = 24; - - public static final int VERSION_FLAG_LENGTH = 1; - public static final int OTHER_FLAG_LENGTH = 3; - public static final int CREATED_DATE_SHORT_LENGTH = 4; - public static final int MODIFIED_DATE_SHORT_LENGTH = 4; - public static final int CREATED_DATE_LONG_LENGTH = 8; - public static final int MODIFIED_DATE_LONG_LENGTH = 8; - public static final int TIMESCALE_LENGTH = 4; - public static final int DURATION_SHORT_LENGTH = 4; - public static final int DURATION_LONG_LENGTH = 8; - - private static final int LONG_FORMAT = 1; - - private int timeScale; - private long timeLength; - - /** - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4MvhdBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - byte version = dataBuffer.get(VERSION_FLAG_POS); - - if (version == LONG_FORMAT) { - this.timeScale = Utils.getIntBE(dataBuffer, TIMESCALE_LONG_POS, (TIMESCALE_LONG_POS + TIMESCALE_LENGTH - 1)); - this.timeLength = Utils.getLongBE(dataBuffer, DURATION_LONG_POS, (DURATION_LONG_POS + DURATION_LONG_LENGTH - 1)); - } else { - this.timeScale = Utils.getIntBE(dataBuffer, TIMESCALE_SHORT_POS, (TIMESCALE_SHORT_POS + TIMESCALE_LENGTH - 1)); - this.timeLength = Utils.getIntBE(dataBuffer, DURATION_SHORT_POS, (DURATION_SHORT_POS + DURATION_SHORT_LENGTH - 1)); - } - } - - public int getLength() { - return (int) (this.timeLength / this.timeScale); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java deleted file mode 100644 index ca526d7..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java +++ /dev/null @@ -1,208 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.Mp4AtomIdentifier; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - -/** - * StcoBox ( media (stream) header), holds offsets into the Audio data - */ -public class Mp4StcoBox extends AbstractMp4Box { - public static final int VERSION_FLAG_POS = 0; - public static final int OTHER_FLAG_POS = 1; - public static final int NO_OF_OFFSETS_POS = 4; - - - public static final int VERSION_FLAG_LENGTH = 1; - public static final int OTHER_FLAG_LENGTH = 3; - public static final int NO_OF_OFFSETS_LENGTH = 4; - public static final int OFFSET_LENGTH = 4; - private int noOfOffSets = 0; - private int firstOffSet; - - /** - * Construct box from data and show contents - * - * @param header header info - * @param buffer data of box (doesnt include header data) - */ - public Mp4StcoBox(Mp4BoxHeader header, ByteBuffer buffer) { - this.header = header; - - //Make a slice of databuffer then we can work with relative or absolute methods safetly - dataBuffer = buffer.slice(); - - //Skip the flags - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH); - - //No of offsets - this.noOfOffSets = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1)); - dataBuffer.position(dataBuffer.position() + NO_OF_OFFSETS_LENGTH); - - //First Offset, useful for sanity checks - firstOffSet = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1)); - } - - /** - * Construct box from data and adjust offets accordingly - * - * @param header header info - * @param originalDataBuffer data of box (doesnt include header data) - * @param adjustment - */ - public Mp4StcoBox(Mp4BoxHeader header, ByteBuffer originalDataBuffer, int adjustment) { - this.header = header; - - //Make a slice of databuffer then we can work with relative or absolute methods safetly - this.dataBuffer = originalDataBuffer.slice(); - - //Skip the flags - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH); - - //No of offsets - this.noOfOffSets = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1)); - dataBuffer.position(dataBuffer.position() + NO_OF_OFFSETS_LENGTH); - - for (int i = 0; i < noOfOffSets; i++) { - int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1)); - - //Calculate new offset and update buffer - offset = offset + adjustment; - dataBuffer.put(Utils.getSizeBEInt32(offset)); - } - } - - public static void debugShowStcoInfo(RandomAccessFile raf) throws IOException, CannotReadException { - Mp4BoxHeader moovHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4AtomIdentifier.MOOV.getFieldName()); - if (moovHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - ByteBuffer moovBuffer = ByteBuffer.allocate(moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH); - raf.getChannel().read(moovBuffer); - moovBuffer.rewind(); - - //Level 2-Searching for "mvhd" somewhere within "moov", we make a slice after finding header - //so all getFields() methods will be relative to mvdh positions - Mp4BoxHeader boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.MVHD.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - ByteBuffer mvhdBuffer = moovBuffer.slice(); - Mp4MvhdBox mvhd = new Mp4MvhdBox(boxHeader, mvhdBuffer); - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - - //Level 2-Searching for "trak" within "moov" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.TRAK.getFieldName()); - int endOfFirstTrackInBuffer = mvhdBuffer.position() + boxHeader.getDataLength(); - - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - //Level 3-Searching for "mdia" within "trak" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDIA.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - - //Level 4-Searching for "mdhd" within "mdia" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDHD.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - - //Level 4-Searching for "minf" within "mdia" - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MINF.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - - //Level 5-Searching for "smhd" within "minf" - //Only an audio track would have a smhd frame - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.SMHD.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength()); - - //Level 5-Searching for "stbl within "minf" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STBL.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - - //Level 6-Searching for "stco within "stbl" - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STCO.getFieldName()); - if (boxHeader == null) { - throw new CannotReadException("This file does not appear to be an audio file"); - } - Mp4StcoBox stco = new Mp4StcoBox(boxHeader, mvhdBuffer); - stco.printAlloffsets(); - } - - public void printTotalOffset() { - int offset = 0; - dataBuffer.rewind(); - dataBuffer.position(VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_OFFSETS_LENGTH); - for (int i = 0; i < noOfOffSets - 1; i++) { - offset += Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1)); - dataBuffer.position(dataBuffer.position() + OFFSET_LENGTH); - } - offset += Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1)); - System.out.println("Print Offset Total:" + offset); - } - - /** - * Show All offsets, useful for debugging - */ - public void printAlloffsets() { - System.out.println("Print Offsets:start"); - dataBuffer.rewind(); - dataBuffer.position(VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_OFFSETS_LENGTH); - for (int i = 0; i < noOfOffSets - 1; i++) { - int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1)); - System.out.println("offset into audio data is:" + offset); - - dataBuffer.position(dataBuffer.position() + OFFSET_LENGTH); - } - int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1)); - System.out.println("offset into audio data is:" + offset); - System.out.println("Print Offsets:end"); - - } - - public void adjustOffsets(int adjustment) { - //Skip the flags - dataBuffer.rewind(); - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_OFFSETS_LENGTH); - for (int i = 0; i < noOfOffSets; i++) { - int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1)); - - //Calculate new offset and update buffer - offset = offset + adjustment; - dataBuffer.put(Utils.getSizeBEInt32(offset)); - } - } - - /** - * The number of offsets - * - * @return - */ - public int getNoOfOffSets() { - return noOfOffSets; - } - - /** - * The value of the first offset - * - * @return - */ - public int getFirstOffSet() { - return firstOffSet; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java deleted file mode 100644 index 6645cf5..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -import org.jaudiotagger.audio.exceptions.CannotReadException; - -import java.nio.ByteBuffer; - -/** - * StsdBox ( sample (frame encoding) description box) - *

    - *

    4 bytes version/flags = byte hex version + 24-bit hex flags - * (current = 0) - * - > 4 bytes number of descriptions = long unsigned total - * (default = 1) - * Then if audio contains mp4a,alac or drms box - */ -public class Mp4StsdBox extends AbstractMp4Box { - public static final int VERSION_FLAG_POS = 0; - public static final int OTHER_FLAG_POS = 1; - public static final int NO_OF_DESCRIPTIONS_POS = 4; - - public static final int VERSION_FLAG_LENGTH = 1; - public static final int OTHER_FLAG_LENGTH = 3; - public static final int NO_OF_DESCRIPTIONS_POS_LENGTH = 4; - - /** - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4StsdBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - this.dataBuffer = dataBuffer; - } - - public void processData() throws CannotReadException { - //Skip the data - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_DESCRIPTIONS_POS_LENGTH); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/NullPadding.java b/src/main/java/org/jaudiotagger/audio/mp4/atom/NullPadding.java deleted file mode 100644 index 096e5d4..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/NullPadding.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.jaudiotagger.audio.mp4.atom; - -/** - * Some mp4s contain null padding at the end of the file, possibly do with gapless playback. This is not really - * allowable but seeing as seems to cccur in files encoded with iTunes 6 and players such as Winamp and iTunes deal - * with it we should - *

    - * It isnt actually a box, but it helps to keep as a subclass of this type - */ -public class NullPadding extends Mp4BoxHeader { - - public NullPadding(long startPosition, long fileSize) { - setFilePos(startPosition); - length = ((int) (fileSize - startPosition)); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/mp4/atom/package.html b/src/main/java/org/jaudiotagger/audio/mp4/atom/package.html deleted file mode 100644 index 00fefd9..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/atom/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for MP4 boxes, aka atoms. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/mp4/package.html b/src/main/java/org/jaudiotagger/audio/mp4/package.html deleted file mode 100644 index e1e49d4..0000000 --- a/src/main/java/org/jaudiotagger/audio/mp4/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for MP4 files (including AAC). - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/OggFileReader.java b/src/main/java/org/jaudiotagger/audio/ogg/OggFileReader.java deleted file mode 100644 index 22d9893..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/OggFileReader.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.audio.ogg.util.OggInfoReader; -import org.jaudiotagger.audio.ogg.util.OggPageHeader; -import org.jaudiotagger.tag.Tag; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Logger; - -/** - * Read Ogg File Tag and Encoding information - *

    - * Only implemented for ogg files containing a vorbis stream with vorbis comments - */ -public class OggFileReader extends AudioFileReader { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg"); - - private OggInfoReader ir; - private OggVorbisTagReader vtr; - - public OggFileReader() { - ir = new OggInfoReader(); - vtr = new OggVorbisTagReader(); - } - - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException { - return ir.read(raf); - } - - protected Tag getTag(RandomAccessFile raf) throws CannotReadException, IOException { - return vtr.read(raf); - } - - /** - * Return count Ogg Page header, count starts from zero - *

    - * count=0; should return PageHeader that contains Vorbis Identification Header - * count=1; should return Pageheader that contains VorbisComment and possibly SetupHeader - * count>=2; should return PageHeader containing remaining VorbisComment,SetupHeader and/or Audio - * - * @param raf - * @param count - * @return - * @throws CannotReadException - * @throws IOException - */ - public OggPageHeader readOggPageHeader(RandomAccessFile raf, int count) throws CannotReadException, IOException { - OggPageHeader pageHeader = OggPageHeader.read(raf); - while (count > 0) { - raf.seek(raf.getFilePointer() + pageHeader.getPageLength()); - pageHeader = OggPageHeader.read(raf); - count--; - } - return pageHeader; - } - - /** - * Summarize all the ogg headers in a file - *

    - * A useful utility function - * - * @param oggFile - * @throws CannotReadException - * @throws IOException - */ - public void summarizeOggPageHeaders(File oggFile) throws CannotReadException, IOException { - RandomAccessFile raf = new RandomAccessFile(oggFile, "r"); - - while (raf.getFilePointer() < raf.length()) { - System.out.println("pageHeader starts at absolute file position:" + raf.getFilePointer()); - OggPageHeader pageHeader = OggPageHeader.read(raf); - System.out.println("pageHeader finishes at absolute file position:" + raf.getFilePointer()); - System.out.println(pageHeader + "\n"); - raf.seek(raf.getFilePointer() + pageHeader.getPageLength()); - } - System.out.println("Raf File Pointer at:" + raf.getFilePointer() + "File Size is:" + raf.length()); - raf.close(); - } - - /** - * Summarizes the first five pages, normally all we are interested in - * - * @param oggFile - * @throws CannotReadException - * @throws IOException - */ - public void shortSummarizeOggPageHeaders(File oggFile) throws CannotReadException, IOException { - RandomAccessFile raf = new RandomAccessFile(oggFile, "r"); - - int i = 0; - while (raf.getFilePointer() < raf.length()) { - System.out.println("pageHeader starts at absolute file position:" + raf.getFilePointer()); - OggPageHeader pageHeader = OggPageHeader.read(raf); - System.out.println("pageHeader finishes at absolute file position:" + raf.getFilePointer()); - System.out.println(pageHeader + "\n"); - raf.seek(raf.getFilePointer() + pageHeader.getPageLength()); - i++; - if (i >= 5) { - break; - } - } - System.out.println("Raf File Pointer at:" + raf.getFilePointer() + "File Size is:" + raf.length()); - raf.close(); - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/OggFileWriter.java b/src/main/java/org/jaudiotagger/audio/ogg/OggFileWriter.java deleted file mode 100644 index f06fb9d..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/OggFileWriter.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.generic.AudioFileWriter; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Logger; - -/** - * Write tag data to Ogg File - *

    - * Only works for Ogg files containing a vorbis stream - */ -public class OggFileWriter extends AudioFileWriter { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg"); - - private OggVorbisTagWriter vtw = new OggVorbisTagWriter(); - - protected void writeTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotReadException, CannotWriteException, IOException { - vtw.write(tag, raf, rafTemp); - } - - protected void deleteTag(RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotReadException, CannotWriteException, IOException { - vtw.delete(raf, tempRaf); - } -} diff --git a/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java b/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java deleted file mode 100644 index b4589cc..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg; - -import org.jaudiotagger.audio.ogg.util.VorbisHeader; -import org.jaudiotagger.audio.ogg.util.VorbisPacketType; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentCreator; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Creates an OggVorbis Comment Tag from a VorbisComment for use within an OggVorbis Container - *

    - * When a Vorbis Comment is used within OggVorbis it additionally has a vorbis header and a framing - * bit. - */ -public class OggVorbisCommentTagCreator { - public static final int FIELD_FRAMING_BIT_LENGTH = 1; - public static final byte FRAMING_BIT_VALID_VALUE = (byte) 0x01; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg"); - private VorbisCommentCreator creator = new VorbisCommentCreator(); - - //Creates the ByteBuffer for the ogg tag - public ByteBuffer convert(Tag tag) throws UnsupportedEncodingException { - ByteBuffer ogg = creator.convert(tag); - int tagLength = ogg.capacity() + VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH + OggVorbisCommentTagCreator.FIELD_FRAMING_BIT_LENGTH; - - ByteBuffer buf = ByteBuffer.allocate(tagLength); - - //[packet type=comment0x03]['vorbis'] - buf.put((byte) VorbisPacketType.COMMENT_HEADER.getType()); - buf.put(VorbisHeader.CAPTURE_PATTERN_AS_BYTES); - - //The actual tag - buf.put(ogg); - - //Framing bit = 1 - buf.put(FRAMING_BIT_VALID_VALUE); - - buf.rewind(); - return buf; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisTagReader.java b/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisTagReader.java deleted file mode 100644 index 7886f54..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisTagReader.java +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.ogg.util.OggPageHeader; -import org.jaudiotagger.audio.ogg.util.VorbisHeader; -import org.jaudiotagger.audio.ogg.util.VorbisPacketType; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentReader; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * Read Vorbis Comment Tag within ogg - *

    - * Vorbis is the audiostream within an ogg file, Vorbis uses VorbisComments as its tag - */ -public class OggVorbisTagReader { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg"); - - private VorbisCommentReader vorbisCommentReader; - - public OggVorbisTagReader() { - vorbisCommentReader = new VorbisCommentReader(); - } - - - /** - * Read the Logical VorbisComment Tag from the file - *

    - *

    Read the CommenyTag, within an OggVorbis file the VorbisCommentTag is mandatory - * - * @param raf - * @return - * @throws CannotReadException - * @throws IOException - */ - public Tag read(RandomAccessFile raf) throws CannotReadException, IOException { - logger.config("Starting to read ogg vorbis tag from file:"); - byte[] rawVorbisCommentData = readRawPacketData(raf); - - //Begin tag reading - VorbisCommentTag tag = vorbisCommentReader.read(rawVorbisCommentData, true); - logger.fine("CompletedReadCommentTag"); - return tag; - } - - /** - * Retrieve the Size of the VorbisComment packet including the oggvorbis header - * - * @param raf - * @return - * @throws CannotReadException - * @throws IOException - */ - public int readOggVorbisRawSize(RandomAccessFile raf) throws CannotReadException, IOException { - byte[] rawVorbisCommentData = readRawPacketData(raf); - return rawVorbisCommentData.length + VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH; - } - - /** - * Retrieve the raw VorbisComment packet data, does not include the OggVorbis header - * - * @param raf - * @return - * @throws CannotReadException if unable to find vorbiscomment header - * @throws IOException - */ - public byte[] readRawPacketData(RandomAccessFile raf) throws CannotReadException, IOException { - logger.fine("Read 1st page"); - //1st page = codec infos - OggPageHeader pageHeader = OggPageHeader.read(raf); - //Skip over data to end of page header 1 - raf.seek(raf.getFilePointer() + pageHeader.getPageLength()); - - logger.fine("Read 2nd page"); - //2nd page = comment, may extend to additional pages or not , may also have setup header - pageHeader = OggPageHeader.read(raf); - - //Now at start of packets on page 2 , check this is the vorbis comment header - byte[] b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH]; - raf.read(b); - if (!isVorbisCommentHeader(b)) { - throw new CannotReadException("Cannot find comment block (no vorbiscomment header)"); - } - - //Convert the comment raw data which maybe over many pages back into raw packet - byte[] rawVorbisCommentData = convertToVorbisCommentPacket(pageHeader, raf); - return rawVorbisCommentData; - } - - - /** - * Is this a Vorbis Comment header, check - *

    - * Note this check only applies to Vorbis Comments embedded within an OggVorbis File which is why within here - * - * @param headerData - * @return true if the headerData matches a VorbisComment header i.e is a Vorbis header of type COMMENT_HEADER - */ - public boolean isVorbisCommentHeader(byte[] headerData) { - String vorbis = Utils.getString(headerData, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH, "ISO-8859-1"); - return !(headerData[VorbisHeader.FIELD_PACKET_TYPE_POS] != VorbisPacketType.COMMENT_HEADER.getType() || !vorbis.equals(VorbisHeader.CAPTURE_PATTERN)); - } - - /** - * Is this a Vorbis SetupHeader check - * - * @param headerData - * @return true if matches vorbis setupheader - */ - public boolean isVorbisSetupHeader(byte[] headerData) { - String vorbis = Utils.getString(headerData, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH, "ISO-8859-1"); - return !(headerData[VorbisHeader.FIELD_PACKET_TYPE_POS] != VorbisPacketType.SETUP_HEADER.getType() || !vorbis.equals(VorbisHeader.CAPTURE_PATTERN)); - } - - /** - * The Vorbis Comment may span multiple pages so we we need to identify the pages they contain and then - * extract the packet data from the pages - * - * @param startVorbisCommentPage - * @param raf - * @return - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - * @throws java.io.IOException - */ - private byte[] convertToVorbisCommentPacket(OggPageHeader startVorbisCommentPage, RandomAccessFile raf) throws IOException, CannotReadException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] b = new byte[startVorbisCommentPage.getPacketList().get(0).getLength() - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH)]; - raf.read(b); - baos.write(b); - - //Because there is at least one other packet (SetupHeaderPacket) this means the Comment Packet has finished - //on this page so thats all we need and we can return - if (startVorbisCommentPage.getPacketList().size() > 1) { - logger.config("Comments finish on 2nd Page because there is another packet on this page"); - return baos.toByteArray(); - } - - //There is only the VorbisComment packet on page if it has completed on this page we can return - if (!startVorbisCommentPage.isLastPacketIncomplete()) { - logger.config("Comments finish on 2nd Page because this packet is complete"); - return baos.toByteArray(); - } - - //The VorbisComment extends to the next page, so should be at end of page already - //so carry on reading pages until we get to the end of comment - while (true) { - logger.config("Reading next page"); - OggPageHeader nextPageHeader = OggPageHeader.read(raf); - b = new byte[nextPageHeader.getPacketList().get(0).getLength()]; - raf.read(b); - baos.write(b); - - //Because there is at least one other packet (SetupHeaderPacket) this means the Comment Packet has finished - //on this page so thats all we need and we can return - if (nextPageHeader.getPacketList().size() > 1) { - logger.config("Comments finish on Page because there is another packet on this page"); - return baos.toByteArray(); - } - - //There is only the VorbisComment packet on page if it has completed on this page we can return - if (!nextPageHeader.isLastPacketIncomplete()) { - logger.config("Comments finish on Page because this packet is complete"); - return baos.toByteArray(); - } - } - } - - /** - * The Vorbis Setup Header may span multiple(2) pages, athough it doesnt normally. We pass the start of the - * file offset of the OggPage it belongs on, it probably won't be first packet. - * - * @param fileOffsetOfStartingOggPage - * @param raf - * @return - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - * @throws java.io.IOException - */ - public byte[] convertToVorbisSetupHeaderPacket(long fileOffsetOfStartingOggPage, RandomAccessFile raf) throws IOException, CannotReadException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - //Seek to specified offset - raf.seek(fileOffsetOfStartingOggPage); - - //Read Page - OggPageHeader setupPageHeader = OggPageHeader.read(raf); - - //Assume that if multiple packets first packet is VorbisComment and second packet - //is setupheader - if (setupPageHeader.getPacketList().size() > 1) { - raf.skipBytes(setupPageHeader.getPacketList().get(0).getLength()); - } - - //Now should be at start of next packet, check this is the vorbis setup header - byte[] b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH]; - raf.read(b); - if (!isVorbisSetupHeader(b)) { - throw new CannotReadException("Unable to find setup header(2), unable to write ogg file"); - } - - //Go back to start of setupheader data - raf.seek(raf.getFilePointer() - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH)); - - //Read data - if (setupPageHeader.getPacketList().size() > 1) { - b = new byte[setupPageHeader.getPacketList().get(1).getLength()]; - raf.read(b); - baos.write(b); - } else { - b = new byte[setupPageHeader.getPacketList().get(0).getLength()]; - raf.read(b); - baos.write(b); - } - - //Return Data - if (!setupPageHeader.isLastPacketIncomplete() || setupPageHeader.getPacketList().size() > 2) { - logger.config("Setupheader finishes on this page"); - return baos.toByteArray(); - } - - //The Setupheader extends to the next page, so should be at end of page already - //so carry on reading pages until we get to the end of comment - while (true) { - logger.config("Reading another page"); - OggPageHeader nextPageHeader = OggPageHeader.read(raf); - b = new byte[nextPageHeader.getPacketList().get(0).getLength()]; - raf.read(b); - baos.write(b); - - //Because there is at least one other packet this means the Setupheader Packet has finished - //on this page so thats all we need and we can return - if (nextPageHeader.getPacketList().size() > 1) { - logger.config("Setupheader finishes on this page"); - return baos.toByteArray(); - } - - //There is only the Setupheader packet on page if it has completed on this page we can return - if (!nextPageHeader.isLastPacketIncomplete()) { - logger.config("Setupheader finish on Page because this packet is complete"); - return baos.toByteArray(); - } - } - } - - - /** - * The Vorbis Setup Header may span multiple(2) pages, athough it doesnt normally. We pass the start of the - * file offset of the OggPage it belongs on, it probably won't be first packet, also returns any addditional - * packets that immediately follow the setup header in original file - * - * @param fileOffsetOfStartingOggPage - * @param raf - * @return - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - * @throws java.io.IOException - */ - public byte[] convertToVorbisSetupHeaderPacketAndAdditionalPackets(long fileOffsetOfStartingOggPage, RandomAccessFile raf) throws IOException, CannotReadException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - //Seek to specified offset - raf.seek(fileOffsetOfStartingOggPage); - - //Read Page - OggPageHeader setupPageHeader = OggPageHeader.read(raf); - - //Assume that if multiple packets first packet is VorbisComment and second packet - //is setupheader - if (setupPageHeader.getPacketList().size() > 1) { - raf.skipBytes(setupPageHeader.getPacketList().get(0).getLength()); - } - - //Now should be at start of next packet, check this is the vorbis setup header - byte[] b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH]; - raf.read(b); - if (!isVorbisSetupHeader(b)) { - throw new CannotReadException("Unable to find setup header(2), unable to write ogg file"); - } - - //Go back to start of setupheader data - raf.seek(raf.getFilePointer() - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH)); - - //Read data - if (setupPageHeader.getPacketList().size() > 1) { - b = new byte[setupPageHeader.getPacketList().get(1).getLength()]; - raf.read(b); - baos.write(b); - } else { - b = new byte[setupPageHeader.getPacketList().get(0).getLength()]; - raf.read(b); - baos.write(b); - } - - //Return Data - if (!setupPageHeader.isLastPacketIncomplete() || setupPageHeader.getPacketList().size() > 2) { - logger.config("Setupheader finishes on this page"); - if (setupPageHeader.getPacketList().size() > 2) { - for (int i = 2; i < setupPageHeader.getPacketList().size(); i++) { - b = new byte[setupPageHeader.getPacketList().get(i).getLength()]; - raf.read(b); - baos.write(b); - } - } - return baos.toByteArray(); - } - - //The Setupheader extends to the next page, so should be at end of page already - //so carry on reading pages until we get to the end of comment - while (true) { - logger.config("Reading another page"); - OggPageHeader nextPageHeader = OggPageHeader.read(raf); - b = new byte[nextPageHeader.getPacketList().get(0).getLength()]; - raf.read(b); - baos.write(b); - - //Because there is at least one other packet this means the Setupheader Packet has finished - //on this page so thats all we need and we can return - if (nextPageHeader.getPacketList().size() > 1) { - logger.config("Setupheader finishes on this page"); - return baos.toByteArray(); - } - - //There is only the Setupheader packet on page if it has completed on this page we can return - if (!nextPageHeader.isLastPacketIncomplete()) { - logger.config("Setupheader finish on Page because this packet is complete"); - return baos.toByteArray(); - } - } - } - - - /** - * Calculate the size of the packet data for the comment and setup headers - * - * @param raf - * @return - * @throws CannotReadException - * @throws IOException - */ - public OggVorbisHeaderSizes readOggVorbisHeaderSizes(RandomAccessFile raf) throws CannotReadException, IOException { - logger.fine("Started to read comment and setup header sizes:"); - - //Stores filepointers so return file in same state - long filepointer = raf.getFilePointer(); - - //Extra Packets on same page as setup header - List extraPackets = new ArrayList(); - - long commentHeaderStartPosition; - long setupHeaderStartPosition; - int commentHeaderSize = 0; - int setupHeaderSize; - //1st page = codec infos - OggPageHeader pageHeader = OggPageHeader.read(raf); - //Skip over data to end of page header 1 - raf.seek(raf.getFilePointer() + pageHeader.getPageLength()); - - //2nd page = comment, may extend to additional pages or not , may also have setup header - pageHeader = OggPageHeader.read(raf); - commentHeaderStartPosition = raf.getFilePointer() - (OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageHeader.getSegmentTable().length); - - //Now at start of packets on page 2 , check this is the vorbis comment header - byte[] b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH]; - raf.read(b); - if (!isVorbisCommentHeader(b)) { - throw new CannotReadException("Cannot find comment block (no vorbiscomment header)"); - } - raf.seek(raf.getFilePointer() - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH)); - logger.config("Found start of comment header at:" + raf.getFilePointer()); - - //Calculate Comment Size (not inc header) - while (true) { - List packetList = pageHeader.getPacketList(); - commentHeaderSize += packetList.get(0).getLength(); - raf.skipBytes(packetList.get(0).getLength()); - - //If this page contains multiple packets or if this last packet is complete then the Comment header - //end son this page and we can break - if (packetList.size() > 1 || !pageHeader.isLastPacketIncomplete()) { - //done comment size - logger.config("Found end of comment:size:" + commentHeaderSize + "finishes at file position:" + raf.getFilePointer()); - break; - } - pageHeader = OggPageHeader.read(raf); - } - - //If there are no more packets on this page we need to go to next page to get the setup header - OggPageHeader.PacketStartAndLength packet; - if (pageHeader.getPacketList().size() == 1) { - pageHeader = OggPageHeader.read(raf); - List packetList = pageHeader.getPacketList(); - packet = pageHeader.getPacketList().get(0); - - //Now at start of next packet , check this is the vorbis setup header - b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH]; - raf.read(b); - if (!isVorbisSetupHeader(b)) { - throw new CannotReadException(ErrorMessage.OGG_VORBIS_NO_VORBIS_HEADER_FOUND.getMsg()); - } - raf.seek(raf.getFilePointer() - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH)); - logger.config("Found start of vorbis setup header at file position:" + raf.getFilePointer()); - - //Set this to the start of the OggPage that setupheader was found on - setupHeaderStartPosition = raf.getFilePointer() - (OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageHeader.getSegmentTable().length); - - //Add packet data to size to the setup header size - setupHeaderSize = packet.getLength(); - logger.fine("Adding:" + packet.getLength() + " to setup header size"); - - //Skip over the packet data - raf.skipBytes(packet.getLength()); - - //If there are other packets that follow this one, or if the last packet is complete then we must have - //got the size of the setup header. - if (packetList.size() > 1 || !pageHeader.isLastPacketIncomplete()) { - logger.config("Found end of setupheader:size:" + setupHeaderSize + "finishes at:" + raf.getFilePointer()); - if (packetList.size() > 1) { - extraPackets = packetList.subList(1, packetList.size()); - } - } - //The setup header continues onto the next page - else { - pageHeader = OggPageHeader.read(raf); - packetList = pageHeader.getPacketList(); - while (true) { - setupHeaderSize += packetList.get(0).getLength(); - logger.fine("Adding:" + packetList.get(0).getLength() + " to setup header size"); - raf.skipBytes(packetList.get(0).getLength()); - if (packetList.size() > 1 || !pageHeader.isLastPacketIncomplete()) { - //done setup size - logger.fine("Found end of setupheader:size:" + setupHeaderSize + "finishes at:" + raf.getFilePointer()); - if (packetList.size() > 1) { - extraPackets = packetList.subList(1, packetList.size()); - } - break; - } - //Continues onto another page - pageHeader = OggPageHeader.read(raf); - } - } - } - //else its next packet on this page - else { - packet = pageHeader.getPacketList().get(1); - List packetList = pageHeader.getPacketList(); - - //Now at start of next packet , check this is the vorbis setup header - b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH]; - raf.read(b); - if (!isVorbisSetupHeader(b)) { - logger.warning("Expecting but got:" + new String(b) + "at " + (raf.getFilePointer() - b.length)); - throw new CannotReadException(ErrorMessage.OGG_VORBIS_NO_VORBIS_HEADER_FOUND.getMsg()); - } - raf.seek(raf.getFilePointer() - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH)); - logger.config("Found start of vorbis setup header at file position:" + raf.getFilePointer()); - - //Set this to the start of the OggPage that setupheader was found on - setupHeaderStartPosition = raf.getFilePointer() - (OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageHeader.getSegmentTable().length) - - pageHeader.getPacketList().get(0).getLength(); - - //Add packet data to size to the setup header size - setupHeaderSize = packet.getLength(); - logger.fine("Adding:" + packet.getLength() + " to setup header size"); - - //Skip over the packet data - raf.skipBytes(packet.getLength()); - - //If there are other packets that follow this one, or if the last packet is complete then we must have - //got the size of the setup header. - if (packetList.size() > 2 || !pageHeader.isLastPacketIncomplete()) { - logger.fine("Found end of setupheader:size:" + setupHeaderSize + "finishes at:" + raf.getFilePointer()); - if (packetList.size() > 2) { - extraPackets = packetList.subList(2, packetList.size()); - } - } - //The setup header continues onto the next page - else { - pageHeader = OggPageHeader.read(raf); - packetList = pageHeader.getPacketList(); - while (true) { - setupHeaderSize += packetList.get(0).getLength(); - logger.fine("Adding:" + packetList.get(0).getLength() + " to setup header size"); - raf.skipBytes(packetList.get(0).getLength()); - if (packetList.size() > 1 || !pageHeader.isLastPacketIncomplete()) { - //done setup size - logger.fine("Found end of setupheader:size:" + setupHeaderSize + "finishes at:" + raf.getFilePointer()); - if (packetList.size() > 1) { - extraPackets = packetList.subList(1, packetList.size()); - } - break; - } - //Continues onto another page - pageHeader = OggPageHeader.read(raf); - } - } - } - - //Reset filepointer to location that it was in at start of method - raf.seek(filepointer); - return new OggVorbisHeaderSizes(commentHeaderStartPosition, setupHeaderStartPosition, commentHeaderSize, setupHeaderSize, extraPackets); - } - - /** - * Find the length of the raw packet data and the start position of the ogg page header they start in - * for the two OggVorbisHeader we need to know about when writing data (sizes included vorbis header) - */ - public static class OggVorbisHeaderSizes { - private long commentHeaderStartPosition; - private long setupHeaderStartPosition; - private int commentHeaderSize; - private int setupHeaderSize; - private List packetList; - - OggVorbisHeaderSizes(long commentHeaderStartPosition, long setupHeaderStartPosition, int commentHeaderSize, int setupHeaderSize, List packetList) { - this.packetList = packetList; - this.commentHeaderStartPosition = commentHeaderStartPosition; - this.setupHeaderStartPosition = setupHeaderStartPosition; - this.commentHeaderSize = commentHeaderSize; - this.setupHeaderSize = setupHeaderSize; - } - - /** - * @return the size of the raw packet data for the vorbis comment header (includes vorbis header) - */ - public int getCommentHeaderSize() { - return commentHeaderSize; - } - - /** - * @return he size of the raw packet data for the vorbis setup header (includes vorbis header) - */ - public int getSetupHeaderSize() { - return setupHeaderSize; - } - - /** - * Return the size required by all the extra packets on same page as setup header, usually there are - * no packets immediately after the setup packet. - * - * @return extra data size required for additional packets on same page - */ - public int getExtraPacketDataSize() { - int extraPacketSize = 0; - for (OggPageHeader.PacketStartAndLength packet : packetList) { - extraPacketSize += packet.getLength(); - } - return extraPacketSize; - } - - /** - * @return the start position in the file of the ogg header which contains the start of the Vorbis Comment - */ - public long getCommentHeaderStartPosition() { - return commentHeaderStartPosition; - } - - /** - * @return the start position in the file of the ogg header which contains the start of the Setup Header - */ - public long getSetupHeaderStartPosition() { - return setupHeaderStartPosition; - } - - public List getExtraPacketList() { - return packetList; - } - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisTagWriter.java b/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisTagWriter.java deleted file mode 100644 index 3d037bf..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/OggVorbisTagWriter.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.ogg.util.OggCRCFactory; -import org.jaudiotagger.audio.ogg.util.OggPageHeader; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.List; -import java.util.logging.Logger; - -/** - * Write Vorbis Tag within an ogg - *

    - * VorbisComment holds the tag information within an ogg file - */ -public class OggVorbisTagWriter { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg"); - - private OggVorbisCommentTagCreator tc = new OggVorbisCommentTagCreator(); - private OggVorbisTagReader reader = new OggVorbisTagReader(); - - public void delete(RandomAccessFile raf, RandomAccessFile tempRaf) throws IOException, CannotReadException, CannotWriteException { - try { - reader.read(raf); - } catch (CannotReadException e) { - write(VorbisCommentTag.createNewTag(), raf, tempRaf); - return; - } - - VorbisCommentTag emptyTag = VorbisCommentTag.createNewTag(); - - //Go back to start of file - raf.seek(0); - write(emptyTag, raf, tempRaf); - } - - public void write(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotReadException, CannotWriteException, IOException { - logger.config("Starting to write file:"); - - //1st Page:Identification Header - logger.fine("Read 1st Page:identificationHeader:"); - OggPageHeader pageHeader = OggPageHeader.read(raf); - raf.seek(pageHeader.getStartByte()); - - //Write 1st page (unchanged) and place writer pointer at end of data - rafTemp.getChannel().transferFrom(raf.getChannel(), 0, pageHeader.getPageLength() + OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageHeader.getSegmentTable().length); - rafTemp.skipBytes(pageHeader.getPageLength() + OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageHeader.getSegmentTable().length); - logger.fine("Written identificationHeader:"); - - //2nd page:Comment and Setup if there is enough room, may also (although not normally) contain audio frames - OggPageHeader secondPageHeader = OggPageHeader.read(raf); - - //2nd Page:Store the end of Header - long secondPageHeaderEndPos = raf.getFilePointer(); - logger.fine("Read 2nd Page:comment and setup and possibly audio:Header finishes at file position:" + secondPageHeaderEndPos); - - //Get header sizes - raf.seek(0); - OggVorbisTagReader.OggVorbisHeaderSizes vorbisHeaderSizes = reader.readOggVorbisHeaderSizes(raf); - - //Convert the OggVorbisComment header to raw packet data - ByteBuffer newComment = tc.convert(tag); - - //Compute new comment length(this may need to be spread over multiple pages) - int newCommentLength = newComment.capacity(); - - //Calculate new size of new 2nd page - int newSecondPageDataLength = vorbisHeaderSizes.getSetupHeaderSize() + newCommentLength + vorbisHeaderSizes.getExtraPacketDataSize(); - logger.fine("Old 2nd Page no of packets: " + secondPageHeader.getPacketList().size()); - logger.fine("Old 2nd Page size: " + secondPageHeader.getPageLength()); - logger.fine("Old last packet incomplete: " + secondPageHeader.isLastPacketIncomplete()); - logger.fine("Setup Header Size: " + vorbisHeaderSizes.getSetupHeaderSize()); - logger.fine("Extra Packets: " + vorbisHeaderSizes.getExtraPacketList().size()); - logger.fine("Extra Packet Data Size: " + vorbisHeaderSizes.getExtraPacketDataSize()); - logger.fine("Old comment: " + vorbisHeaderSizes.getCommentHeaderSize()); - logger.fine("New comment: " + newCommentLength); - logger.fine("New Page Data Size: " + newSecondPageDataLength); - //Second Page containing new vorbis, setup and possibly some extra packets can fit on one page - if (isCommentAndSetupHeaderFitsOnASinglePage(newCommentLength, vorbisHeaderSizes.getSetupHeaderSize(), vorbisHeaderSizes.getExtraPacketList())) { - //And if comment and setup header originally fitted on both, the length of the 2nd - //page must be less than maximum size allowed - //AND - //there must be two packets with last being complete because they may have - //elected to split the setup over multiple pages instead of using up whole page - (as long - //as the last lacing value is 255 they can do this) - // OR - //There are more than the packets in which case have complete setup header and some audio packets - //we dont care if the last audio packet is split on next page as long as we preserve it - if ((secondPageHeader.getPageLength() < OggPageHeader.MAXIMUM_PAGE_DATA_SIZE) && (((secondPageHeader.getPacketList().size() == 2) && (!secondPageHeader.isLastPacketIncomplete())) || (secondPageHeader.getPacketList().size() > 2))) { - logger.fine("Header and Setup remain on single page:"); - replaceSecondPageOnly(vorbisHeaderSizes, newCommentLength, newSecondPageDataLength, secondPageHeader, newComment, secondPageHeaderEndPos, raf, rafTemp); - } - //Original 2nd page spanned multiple pages so more work to do - else { - logger.fine("Header and Setup now on single page:"); - replaceSecondPageAndRenumberPageSeqs(vorbisHeaderSizes, newCommentLength, newSecondPageDataLength, secondPageHeader, newComment, raf, rafTemp); - } - } - //Bit more complicated, have to create more than one new page and renumber subsequent audio - else { - logger.fine("Header and Setup with shift audio:"); - replacePagesAndRenumberPageSeqs(vorbisHeaderSizes, newCommentLength, secondPageHeader, newComment, raf, rafTemp); - } - } - - /** - * Calculate checkSum over the Page - * - * @param page - */ - private void calculateChecksumOverPage(ByteBuffer page) { - //CRC should be zero before calculating it - page.putInt(OggPageHeader.FIELD_PAGE_CHECKSUM_POS, 0); - - //Compute CRC over the page //TODO shouldnt really use array(); - byte[] crc = OggCRCFactory.computeCRC(page.array()); - for (int i = 0; i < crc.length; i++) { - page.put(OggPageHeader.FIELD_PAGE_CHECKSUM_POS + i, crc[i]); - } - - //Rewind to start of Page - page.rewind(); - } - - /** - * Create a second Page, and add comment header to it, but page is incomplete may want to add addition header and need to calculate CRC - * - * @param vorbisHeaderSizes - * @param newCommentLength - * @param newSecondPageLength - * @param secondPageHeader - * @param newComment - * @return - * @throws IOException - */ - private ByteBuffer startCreateBasicSecondPage( - OggVorbisTagReader.OggVorbisHeaderSizes vorbisHeaderSizes, - int newCommentLength, - int newSecondPageLength, - OggPageHeader secondPageHeader, - ByteBuffer newComment) throws IOException { - logger.fine("WriteOgg Type 1"); - byte[] segmentTable = createSegmentTable(newCommentLength, vorbisHeaderSizes.getSetupHeaderSize(), vorbisHeaderSizes.getExtraPacketList()); - int newSecondPageHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length; - logger.fine("New second page header length:" + newSecondPageHeaderLength); - logger.fine("No of segments:" + segmentTable.length); - - ByteBuffer secondPageBuffer = ByteBuffer.allocate(newSecondPageLength + newSecondPageHeaderLength); - secondPageBuffer.order(ByteOrder.LITTLE_ENDIAN); - - //Build the new 2nd page header, can mostly be taken from the original upto the segment length OggS capture - secondPageBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1); - - //Number of Page Segments - secondPageBuffer.put((byte) segmentTable.length); - - //Page segment table - for (byte aSegmentTable : segmentTable) { - secondPageBuffer.put(aSegmentTable); - } - - //Add New VorbisComment - secondPageBuffer.put(newComment); - return secondPageBuffer; - - } - - - /** - * Usually can use this method, previously comment and setup header all fit on page 2 - * and they still do, so just replace this page. And copy further pages as is. - * - * @param vorbisHeaderSizes - * @param newCommentLength - * @param newSecondPageLength - * @param secondPageHeader - * @param newComment - * @param secondPageHeaderEndPos - * @param raf - * @param rafTemp - * @throws IOException - */ - private void replaceSecondPageOnly( - OggVorbisTagReader.OggVorbisHeaderSizes vorbisHeaderSizes, - int newCommentLength, - int newSecondPageLength, - OggPageHeader secondPageHeader, - ByteBuffer newComment, - long secondPageHeaderEndPos, - RandomAccessFile raf, - RandomAccessFile rafTemp) throws IOException { - logger.fine("WriteOgg Type 1"); - ByteBuffer secondPageBuffer = startCreateBasicSecondPage(vorbisHeaderSizes, newCommentLength, newSecondPageLength, secondPageHeader, newComment); - - raf.seek(secondPageHeaderEndPos); - //Skip comment header - raf.skipBytes(vorbisHeaderSizes.getCommentHeaderSize()); - //Read in setup header and extra packets - raf.getChannel().read(secondPageBuffer); - calculateChecksumOverPage(secondPageBuffer); - rafTemp.getChannel().write(secondPageBuffer); - rafTemp.getChannel().transferFrom(raf.getChannel(), rafTemp.getFilePointer(), raf.length() - raf.getFilePointer()); - } - - /** - * Previously comment and/or setup header was on a number of pages now can just replace this page fitting all - * on 2nd page, and renumber subsequent sequence pages - * - * @param originalHeaderSizes - * @param newCommentLength - * @param newSecondPageLength - * @param secondPageHeader - * @param newComment - * @param raf - * @param rafTemp - * @throws IOException - * @throws org.jaudiotagger.audio.exceptions.CannotReadException - * @throws org.jaudiotagger.audio.exceptions.CannotWriteException - */ - private void replaceSecondPageAndRenumberPageSeqs(OggVorbisTagReader.OggVorbisHeaderSizes originalHeaderSizes, int newCommentLength, int newSecondPageLength, OggPageHeader secondPageHeader, ByteBuffer newComment, RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException, CannotReadException, CannotWriteException { - logger.fine("WriteOgg Type 2"); - ByteBuffer secondPageBuffer = startCreateBasicSecondPage(originalHeaderSizes, newCommentLength, newSecondPageLength, secondPageHeader, newComment); - - //Add setup header and packets - int pageSequence = secondPageHeader.getPageSequence(); - byte[] setupHeaderData = reader.convertToVorbisSetupHeaderPacketAndAdditionalPackets(originalHeaderSizes.getSetupHeaderStartPosition(), raf); - logger.finest(setupHeaderData.length + ":" + secondPageBuffer.position() + ":" + secondPageBuffer.capacity()); - secondPageBuffer.put(setupHeaderData); - - calculateChecksumOverPage(secondPageBuffer); - rafTemp.getChannel().write(secondPageBuffer); - writeRemainingPages(pageSequence, raf, rafTemp); - } - - /** - * CommentHeader extends over multiple pages OR Comment Header doesnt but it's got larger causing some extra - * packets to be shifted onto another page. - * - * @param originalHeaderSizes - * @param newCommentLength - * @param secondPageHeader - * @param newComment - * @param raf - * @param rafTemp - * @throws IOException - * @throws CannotReadException - * @throws CannotWriteException - */ - private void replacePagesAndRenumberPageSeqs(OggVorbisTagReader.OggVorbisHeaderSizes originalHeaderSizes, int newCommentLength, OggPageHeader secondPageHeader, ByteBuffer newComment, RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException, CannotReadException, CannotWriteException { - int pageSequence = secondPageHeader.getPageSequence(); - - //We need to work out how to split the newcommentlength over the pages - int noOfCompletePagesNeededForComment = newCommentLength / OggPageHeader.MAXIMUM_PAGE_DATA_SIZE; - logger.config("Comment requires:" + noOfCompletePagesNeededForComment + " complete pages"); - - //Create the Pages - int newCommentOffset = 0; - if (noOfCompletePagesNeededForComment > 0) { - for (int i = 0; i < noOfCompletePagesNeededForComment; i++) { - //Create ByteBuffer for the New page - byte[] segmentTable = this.createSegments(OggPageHeader.MAXIMUM_PAGE_DATA_SIZE, false); - int pageHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length; - ByteBuffer pageBuffer = ByteBuffer.allocate(pageHeaderLength + OggPageHeader.MAXIMUM_PAGE_DATA_SIZE); - pageBuffer.order(ByteOrder.LITTLE_ENDIAN); - - //Now create the page basing it on the existing 2ndpageheader - pageBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1); - //Number of Page Segments - pageBuffer.put((byte) segmentTable.length); - //Page segment table - for (byte aSegmentTable : segmentTable) { - pageBuffer.put(aSegmentTable); - } - //Get next bit of Comment - ByteBuffer nextPartOfComment = newComment.slice(); - nextPartOfComment.limit(OggPageHeader.MAXIMUM_PAGE_DATA_SIZE); - pageBuffer.put(nextPartOfComment); - - //Recalculate Page Sequence Number - pageBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS, pageSequence); - pageSequence++; - - //Set Header Flag to indicate continuous (except for first flag) - if (i != 0) { - pageBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS, OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue()); - } - calculateChecksumOverPage(pageBuffer); - rafTemp.getChannel().write(pageBuffer); - newCommentOffset += OggPageHeader.MAXIMUM_PAGE_DATA_SIZE; - newComment.position(newCommentOffset); - } - } - - int lastPageCommentPacketSize = newCommentLength % OggPageHeader.MAXIMUM_PAGE_DATA_SIZE; - logger.fine("Last comment packet size:" + lastPageCommentPacketSize); - - //End of comment and setup header cannot fit on the last page - if (!isCommentAndSetupHeaderFitsOnASinglePage(lastPageCommentPacketSize, originalHeaderSizes.getSetupHeaderSize(), originalHeaderSizes.getExtraPacketList())) { - logger.fine("WriteOgg Type 3"); - - //Write the last part of comment only (its possible it might be the only comment) - { - byte[] segmentTable = createSegments(lastPageCommentPacketSize, true); - int pageHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length; - ByteBuffer pageBuffer = ByteBuffer.allocate(lastPageCommentPacketSize + pageHeaderLength); - pageBuffer.order(ByteOrder.LITTLE_ENDIAN); - pageBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1); - pageBuffer.put((byte) segmentTable.length); - for (byte aSegmentTable : segmentTable) { - pageBuffer.put(aSegmentTable); - } - newComment.position(newCommentOffset); - pageBuffer.put(newComment.slice()); - pageBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS, pageSequence); - - if (noOfCompletePagesNeededForComment > 0) { - pageBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS, OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue()); - } - logger.fine("Writing Last Comment Page " + pageSequence + " to file"); - pageSequence++; - calculateChecksumOverPage(pageBuffer); - rafTemp.getChannel().write(pageBuffer); - } - - //Now write header and extra packets onto next page - { - byte[] segmentTable = this.createSegmentTable(originalHeaderSizes.getSetupHeaderSize(), originalHeaderSizes.getExtraPacketList()); - int pageHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length; - byte[] setupHeaderData = reader.convertToVorbisSetupHeaderPacketAndAdditionalPackets(originalHeaderSizes.getSetupHeaderStartPosition(), raf); - ByteBuffer pageBuffer = ByteBuffer.allocate(setupHeaderData.length + pageHeaderLength); - pageBuffer.order(ByteOrder.LITTLE_ENDIAN); - pageBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1); - pageBuffer.put((byte) segmentTable.length); - for (byte aSegmentTable : segmentTable) { - pageBuffer.put(aSegmentTable); - } - pageBuffer.put(setupHeaderData); - pageBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS, pageSequence); - //pageBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS, OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue()); - logger.fine("Writing Setup Header and packets Page " + pageSequence + " to file"); - - calculateChecksumOverPage(pageBuffer); - rafTemp.getChannel().write(pageBuffer); - } - } else { - //End of Comment and SetupHeader and extra packets can fit on one page - logger.fine("WriteOgg Type 4"); - - //Create last header page - int newSecondPageDataLength = originalHeaderSizes.getSetupHeaderSize() + lastPageCommentPacketSize + originalHeaderSizes.getExtraPacketDataSize(); - newComment.position(newCommentOffset); - ByteBuffer lastComment = newComment.slice(); - ByteBuffer lastHeaderBuffer = startCreateBasicSecondPage( - originalHeaderSizes, - lastPageCommentPacketSize, - newSecondPageDataLength, - secondPageHeader, - lastComment); - //Now find the setupheader which is on a different page - raf.seek(originalHeaderSizes.getSetupHeaderStartPosition()); - - //Add setup Header and Extra Packets (although it will fit in this page, it may be over multiple pages in its original form - //so need to use this function to convert to raw data - byte[] setupHeaderData = reader.convertToVorbisSetupHeaderPacketAndAdditionalPackets(originalHeaderSizes.getSetupHeaderStartPosition(), raf); - lastHeaderBuffer.put(setupHeaderData); - - //Page Sequence No - lastHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS, pageSequence); - - //Set Header Flag to indicate continuous (contains end of comment) - lastHeaderBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS, OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue()); - calculateChecksumOverPage(lastHeaderBuffer); - rafTemp.getChannel().write(lastHeaderBuffer); - } - - //Write the rest of the original file - writeRemainingPages(pageSequence, raf, rafTemp); - } - - /** - * Write all the remaining pages as they are except that the page sequence needs to be modified. - * - * @param pageSequence - * @param raf - * @param rafTemp - * @throws IOException - * @throws CannotReadException - * @throws CannotWriteException - */ - public void writeRemainingPages(int pageSequence, RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException, CannotReadException, CannotWriteException { - long startAudio = raf.getFilePointer(); - long startAudioWritten = rafTemp.getFilePointer(); - - //TODO there is a risk we wont have enough memory to create these buffers - ByteBuffer bb = ByteBuffer.allocate((int) (raf.length() - raf.getFilePointer())); - ByteBuffer bbTemp = ByteBuffer.allocate((int) (raf.length() - raf.getFilePointer())); - - //Read in the rest of the data into bytebuffer and rewind it to start - raf.getChannel().read(bb); - bb.rewind(); - while (bb.hasRemaining()) { - OggPageHeader nextPage = OggPageHeader.read(bb); - - //Create buffer large enough for next page (header and data) and set byte order to LE so we can use - //putInt method - ByteBuffer nextPageHeaderBuffer = ByteBuffer.allocate(nextPage.getRawHeaderData().length + nextPage.getPageLength()); - nextPageHeaderBuffer.order(ByteOrder.LITTLE_ENDIAN); - nextPageHeaderBuffer.put(nextPage.getRawHeaderData()); - ByteBuffer data = bb.slice(); - data.limit(nextPage.getPageLength()); - nextPageHeaderBuffer.put(data); - nextPageHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS, ++pageSequence); - calculateChecksumOverPage(nextPageHeaderBuffer); - bb.position(bb.position() + nextPage.getPageLength()); - - nextPageHeaderBuffer.rewind(); - bbTemp.put(nextPageHeaderBuffer); - } - //Now just write as a single IO operation - bbTemp.rewind(); - rafTemp.getChannel().write(bbTemp); - //Check we have written all the data - //TODO could we do any other checks to check data written correctly ? - if ((raf.length() - startAudio) != (rafTemp.length() - startAudioWritten)) { - throw new CannotWriteException("File written counts don't match, file not written"); - } - } - - public void writeRemainingPagesOld(int pageSequence, RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException, CannotReadException, CannotWriteException { - //Now the Page Sequence Number for all the subsequent pages (containing audio frames) are out because there are - //less pages before then there used to be, so need to adjust - long startAudio = raf.getFilePointer(); - long startAudioWritten = rafTemp.getFilePointer(); - logger.fine("Writing audio, audio starts in original file at :" + startAudio + ":Written to:" + startAudioWritten); - while (raf.getFilePointer() < raf.length()) { - logger.fine("Reading Ogg Page"); - OggPageHeader nextPage = OggPageHeader.read(raf); - - //Create buffer large enough for next page (header and data) and set byte order to LE so we can use - //putInt method - ByteBuffer nextPageHeaderBuffer = ByteBuffer.allocate(nextPage.getRawHeaderData().length + nextPage.getPageLength()); - nextPageHeaderBuffer.order(ByteOrder.LITTLE_ENDIAN); - - nextPageHeaderBuffer.put(nextPage.getRawHeaderData()); - raf.getChannel().read(nextPageHeaderBuffer); - - //Recalculate Page Sequence Number - nextPageHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS, ++pageSequence); - - //Calculate Checksum - calculateChecksumOverPage(nextPageHeaderBuffer); - rafTemp.getChannel().write(nextPageHeaderBuffer); - } - if ((raf.length() - startAudio) != (rafTemp.length() - startAudioWritten)) { - throw new CannotWriteException("File written counts don't match, file not written"); - } - } - - /** - * This method creates a new segment table for the second page (header). - * - * @param newCommentLength The length of the Vorbis Comment - * @param setupHeaderLength The length of Setup Header, zero if comment String extends - * over multiple pages and this is not the last page. - * @param extraPackets If there are packets immediately after setup header in same page, they - * need including in the segment table - * @return new segment table. - */ - private byte[] createSegmentTable(int newCommentLength, int setupHeaderLength, List extraPackets) { - logger.finest("Create SegmentTable CommentLength:" + newCommentLength + ":SetupHeaderLength:" + setupHeaderLength); - ByteArrayOutputStream resultBaos = new ByteArrayOutputStream(); - - byte[] newStart; - byte[] restShouldBe; - byte[] nextPacket; - - //Vorbis Comment - if (setupHeaderLength == 0) { - //Comment Stream continues onto next page so last lacing value can be 255 - newStart = createSegments(newCommentLength, false); - return newStart; - } else { - //Comment Stream finishes on this page so if is a multiple of 255 - //have to add an extra entry. - newStart = createSegments(newCommentLength, true); - } - - //Setup Header, should be closed - if (extraPackets.size() > 0) { - restShouldBe = createSegments(setupHeaderLength, true); - } - //.. continue sonto next page - else { - restShouldBe = createSegments(setupHeaderLength, false); - } - - logger.finest("Created " + newStart.length + " segments for header"); - logger.finest("Created " + restShouldBe.length + " segments for setup"); - - try { - resultBaos.write(newStart); - resultBaos.write(restShouldBe); - if (extraPackets.size() > 0) { - //Packets are being copied literally not converted from a length, so always pass - //false parameter, TODO is this statement correct - logger.finer("Creating segments for " + extraPackets.size() + " packets"); - for (OggPageHeader.PacketStartAndLength packet : extraPackets) { - nextPacket = createSegments(packet.getLength(), false); - resultBaos.write(nextPacket); - } - } - } catch (IOException ioe) { - throw new RuntimeException("Unable to create segment table:" + ioe.getMessage()); - } - return resultBaos.toByteArray(); - - } - - /** - * This method creates a new segment table for the second half of setup header - * - * @param setupHeaderLength The length of Setup Header, zero if comment String extends - * over multiple pages and this is not the last page. - * @param extraPackets If there are packets immediately after setup header in same page, they - * need including in the segment table - * @return new segment table. - */ - private byte[] createSegmentTable(int setupHeaderLength, List extraPackets) { - ByteArrayOutputStream resultBaos = new ByteArrayOutputStream(); - - byte[] restShouldBe; - byte[] nextPacket; - - //Setup Header - restShouldBe = createSegments(setupHeaderLength, true); - - try { - resultBaos.write(restShouldBe); - if (extraPackets.size() > 0) { - //Packets are being copied literally not converted from a length, so always pass - //false parameter, TODO is this statement correct - for (OggPageHeader.PacketStartAndLength packet : extraPackets) { - nextPacket = createSegments(packet.getLength(), false); - resultBaos.write(nextPacket); - } - } - } catch (IOException ioe) { - throw new RuntimeException("Unable to create segment table:" + ioe.getMessage()); - } - return resultBaos.toByteArray(); - } - - - /** - * This method creates a byte array of values whose sum should - * be the value of length.
    - * - * @param length Size of the page which should be - * represented as 255 byte packets. - * @param quitStream If true and a length is a multiple of 255 we need another - * segment table entry with the value of 0. Else it's the last stream of the - * table which is already ended. - * @return Array of packet sizes. However only the last packet will - * differ from 255. - *

    - */ - //TODO if pass is data of max length (65025 bytes) and have quitStream==true - //this will return 256 segments which is illegal, should be checked somewhere - private byte[] createSegments(int length, boolean quitStream) { - logger.finest("Create Segments for length:" + length + ":QuitStream:" + quitStream); - //It is valid to have nil length packets - if (length == 0) { - byte[] result = new byte[1]; - result[0] = (byte) 0x00; - return result; - } - - byte[] result = new byte[length / OggPageHeader.MAXIMUM_SEGMENT_SIZE + ((length % OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0 && !quitStream) ? 0 : 1)]; - int i = 0; - for (; i < result.length - 1; i++) { - result[i] = (byte) 0xFF; - } - result[result.length - 1] = (byte) (length - (i * OggPageHeader.MAXIMUM_SEGMENT_SIZE)); - return result; - } - - /** - * @param commentLength - * @param setupHeaderLength - * @param extraPacketList - * @return true if there is enough room to fit the comment and the setup headers on one page taking into - * account the maximum no of segments allowed per page and zero lacing values. - */ - private boolean isCommentAndSetupHeaderFitsOnASinglePage(int commentLength, int setupHeaderLength, List extraPacketList) { - int totalDataSize = 0; - - if (commentLength == 0) { - totalDataSize++; - } else { - totalDataSize = (commentLength / OggPageHeader.MAXIMUM_SEGMENT_SIZE) + 1; - if (commentLength % OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0) { - totalDataSize++; - } - } - logger.finest("Require:" + totalDataSize + " segments for comment"); - - if (setupHeaderLength == 0) { - totalDataSize++; - } else { - totalDataSize += (setupHeaderLength / OggPageHeader.MAXIMUM_SEGMENT_SIZE) + 1; - if (setupHeaderLength % OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0) { - totalDataSize++; - } - } - logger.finest("Require:" + totalDataSize + " segments for comment plus setup"); - - for (OggPageHeader.PacketStartAndLength extraPacket : extraPacketList) { - if (extraPacket.getLength() == 0) { - totalDataSize++; - } else { - totalDataSize += (extraPacket.getLength() / OggPageHeader.MAXIMUM_SEGMENT_SIZE) + 1; - if (extraPacket.getLength() % OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0) { - totalDataSize++; - } - } - } - - logger.finest("Total No Of Segment If New Comment And Header Put On One Page:" + totalDataSize); - return totalDataSize <= OggPageHeader.MAXIMUM_NO_OF_SEGMENT_SIZE; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/ogg/VorbisVersion.java b/src/main/java/org/jaudiotagger/audio/ogg/VorbisVersion.java deleted file mode 100644 index 85df289..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/VorbisVersion.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.jaudiotagger.audio.ogg; - -/** - * Vorbis Version - *

    - * Ordinal is used to map from internal representation - */ -public enum VorbisVersion { - VERSION_ONE("Ogg Vorbis v1"); - - //The display name for this version - private String displayName; - - - VorbisVersion(String displayName) { - this.displayName = displayName; - } - - public String toString() { - return displayName; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/ogg/package.html b/src/main/java/org/jaudiotagger/audio/ogg/package.html deleted file mode 100644 index a65b64a..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for Ogg Vorbis files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/OggCRCFactory.java b/src/main/java/org/jaudiotagger/audio/ogg/util/OggCRCFactory.java deleted file mode 100644 index f97403c..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/OggCRCFactory.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg.util; - -import java.util.logging.Logger; - - -/** - * OffCRC Calculations - *

    - * $Id: OggCRCFactory.java 836 2009-11-12 15:44:07Z paultaylor $ - * - * @author Raphael Slinckx (KiKiDonK) - * @version 19 d�cembre 2003 - */ -public class OggCRCFactory { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg"); - - private static long[] crc_lookup = new long[256]; - private static boolean init = false; - - - public static void init() { - for (int i = 0; i < 256; i++) { - long r = i << 24; - - for (int j = 0; j < 8; j++) { - if ((r & 0x80000000L) != 0) { - r = (r << 1) ^ 0x04c11db7L; - } else { - r <<= 1; - } - } - - crc_lookup[i] = (r); - } - init = true; - } - - public static byte[] computeCRC(byte[] data) { - - if (!init) { - init(); - } - - long crc_reg = 0; - - for (byte aData : data) { - int tmp = (int) (((crc_reg >>> 24) & 0xff) ^ u(aData)); - - crc_reg = (crc_reg << 8) ^ crc_lookup[tmp]; - crc_reg &= 0xffffffff; - } - - byte[] sum = new byte[4]; - - sum[0] = (byte) (crc_reg & 0xffL); - sum[1] = (byte) ((crc_reg >>> 8) & 0xffL); - sum[2] = (byte) ((crc_reg >>> 16) & 0xffL); - sum[3] = (byte) ((crc_reg >>> 24) & 0xffL); - - return sum; - } - - private static int u(int n) { - return n & 0xff; - } - - public boolean checkCRC(byte[] data, byte[] crc) { - return new String(crc).equals(new String(computeCRC(data))); - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/OggInfoReader.java b/src/main/java/org/jaudiotagger/audio/ogg/util/OggInfoReader.java deleted file mode 100644 index 5625daa..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/OggInfoReader.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg.util; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.id3.AbstractID3v2Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Arrays; -import java.util.logging.Logger; - -/** - * Read encoding info, only implemented for vorbis streams - */ -public class OggInfoReader { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg.atom"); - - public GenericAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException { - long start = raf.getFilePointer(); - GenericAudioHeader info = new GenericAudioHeader(); - logger.fine("Started"); - long oldPos; - - //Check start of file does it have Ogg pattern - byte[] b = new byte[OggPageHeader.CAPTURE_PATTERN.length]; - raf.read(b); - if (!(Arrays.equals(b, OggPageHeader.CAPTURE_PATTERN))) { - raf.seek(0); - if (AbstractID3v2Tag.isId3Tag(raf)) { - raf.read(b); - if ((Arrays.equals(b, OggPageHeader.CAPTURE_PATTERN))) { - start = raf.getFilePointer(); - } - } else { - throw new CannotReadException(ErrorMessage.OGG_HEADER_CANNOT_BE_FOUND.getMsg(new String(b))); - } - } - - //Now work backwards from file looking for the last ogg page, it reads the granule position for this last page - //which must be set. - //TODO should do buffering to cut down the number of file reads - raf.seek(start); - double pcmSamplesNumber = -1; - raf.seek(raf.length() - 2); - while (raf.getFilePointer() >= 4) { - if (raf.read() == OggPageHeader.CAPTURE_PATTERN[3]) { - raf.seek(raf.getFilePointer() - OggPageHeader.FIELD_CAPTURE_PATTERN_LENGTH); - byte[] ogg = new byte[3]; - raf.readFully(ogg); - if (ogg[0] == OggPageHeader.CAPTURE_PATTERN[0] && ogg[1] == OggPageHeader.CAPTURE_PATTERN[1] && ogg[2] == OggPageHeader.CAPTURE_PATTERN[2]) { - raf.seek(raf.getFilePointer() - 3); - - oldPos = raf.getFilePointer(); - raf.seek(raf.getFilePointer() + OggPageHeader.FIELD_PAGE_SEGMENTS_POS); - int pageSegments = raf.readByte() & 0xFF; //Unsigned - raf.seek(oldPos); - - b = new byte[OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageSegments]; - raf.readFully(b); - - OggPageHeader pageHeader = new OggPageHeader(b); - raf.seek(0); - pcmSamplesNumber = pageHeader.getAbsoluteGranulePosition(); - break; - } - } - raf.seek(raf.getFilePointer() - 2); - } - - if (pcmSamplesNumber == -1) { - //According to spec a value of -1 indicates no packet finished on this page, this should not occur - throw new CannotReadException(ErrorMessage.OGG_VORBIS_NO_SETUP_BLOCK.getMsg()); - } - - //1st page = Identification Header - OggPageHeader pageHeader = OggPageHeader.read(raf); - byte[] vorbisData = new byte[pageHeader.getPageLength()]; - raf.read(vorbisData); - VorbisIdentificationHeader vorbisIdentificationHeader = new VorbisIdentificationHeader(vorbisData); - - //Map to generic encodingInfo - info.setPreciseLength((float) (pcmSamplesNumber / vorbisIdentificationHeader.getSamplingRate())); - info.setChannelNumber(vorbisIdentificationHeader.getChannelNumber()); - info.setSamplingRate(vorbisIdentificationHeader.getSamplingRate()); - info.setEncodingType(vorbisIdentificationHeader.getEncodingType()); - info.setExtraEncodingInfos(""); - - //According to Wikipedia Vorbis Page, Vorbis only works on 16bits 44khz - info.setBitsPerSample(16); - - //TODO this calculation should be done within identification header - if (vorbisIdentificationHeader.getNominalBitrate() != 0 && vorbisIdentificationHeader.getMaxBitrate() == vorbisIdentificationHeader.getNominalBitrate() && vorbisIdentificationHeader.getMinBitrate() == vorbisIdentificationHeader.getNominalBitrate()) { - //CBR (in kbps) - info.setBitrate(vorbisIdentificationHeader.getNominalBitrate() / 1000); - info.setVariableBitRate(false); - } else if (vorbisIdentificationHeader.getNominalBitrate() != 0 && vorbisIdentificationHeader.getMaxBitrate() == 0 && vorbisIdentificationHeader.getMinBitrate() == 0) { - //Average vbr (in kpbs) - info.setBitrate(vorbisIdentificationHeader.getNominalBitrate() / 1000); - info.setVariableBitRate(true); - } else { - //TODO need to remove comment from raf.getLength() - info.setBitrate(computeBitrate(info.getTrackLength(), raf.length())); - info.setVariableBitRate(true); - } - logger.fine("Finished"); - return info; - } - - private int computeBitrate(int length, long size) { - return (int) ((size / 1000) * 8 / length); - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/OggPageHeader.java b/src/main/java/org/jaudiotagger/audio/ogg/util/OggPageHeader.java deleted file mode 100644 index adae645..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/OggPageHeader.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg.util; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.id3.AbstractID3v2Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - - -/** - * $Id: OggPageHeader.java 965 2011-04-28 11:34:43Z paultaylor $ - *

    - * reference:http://xiph.org/ogg/doc/framing.html - * - * @author Raphael Slinckx (KiKiDonK) - * @version 16 d�cembre 2003 - */ -public class OggPageHeader { - //Capture pattern at start of header - public static final byte[] CAPTURE_PATTERN = {'O', 'g', 'g', 'S'}; - //Ogg Page header is always 27 bytes plus the size of the segment table which is variable - public static final int OGG_PAGE_HEADER_FIXED_LENGTH = 27; - //Can have upto 255 segments in a page - public static final int MAXIMUM_NO_OF_SEGMENT_SIZE = 255; - //Each segment can be upto 255 bytes - public static final int MAXIMUM_SEGMENT_SIZE = 255; - //Maximum size of pageheader (27 + 255 = 282) - public static final int MAXIMUM_PAGE_HEADER_SIZE = OGG_PAGE_HEADER_FIXED_LENGTH + MAXIMUM_NO_OF_SEGMENT_SIZE; - //Maximum size of page data following the page header (255 * 255 = 65025) - public static final int MAXIMUM_PAGE_DATA_SIZE = MAXIMUM_NO_OF_SEGMENT_SIZE * MAXIMUM_SEGMENT_SIZE; - //Maximum size of page includes header and data (282 + 65025 = 65307 bytes) - public static final int MAXIMUM_PAGE_SIZE = MAXIMUM_PAGE_HEADER_SIZE + MAXIMUM_PAGE_DATA_SIZE; - //Starting positions of the various attributes - public static final int FIELD_CAPTURE_PATTERN_POS = 0; - public static final int FIELD_STREAM_STRUCTURE_VERSION_POS = 4; - public static final int FIELD_HEADER_TYPE_FLAG_POS = 5; - public static final int FIELD_ABSOLUTE_GRANULE_POS = 6; - public static final int FIELD_STREAM_SERIAL_NO_POS = 14; - public static final int FIELD_PAGE_SEQUENCE_NO_POS = 18; - public static final int FIELD_PAGE_CHECKSUM_POS = 22; - public static final int FIELD_PAGE_SEGMENTS_POS = 26; - public static final int FIELD_SEGMENT_TABLE_POS = 27; - //Length of various attributes - public static final int FIELD_CAPTURE_PATTERN_LENGTH = 4; - public static final int FIELD_STREAM_STRUCTURE_VERSION_LENGTH = 1; - public static final int FIELD_HEADER_TYPE_FLAG_LENGTH = 1; - public static final int FIELD_ABSOLUTE_GRANULE_LENGTH = 8; - public static final int FIELD_STREAM_SERIAL_NO_LENGTH = 4; - public static final int FIELD_PAGE_SEQUENCE_NO_LENGTH = 4; - public static final int FIELD_PAGE_CHECKSUM_LENGTH = 4; - public static final int FIELD_PAGE_SEGMENTS_LENGTH = 1; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg.atom"); - private byte[] rawHeaderData; - private double absoluteGranulePosition; - private int checksum; - private byte headerTypeFlag; - - private boolean isValid = false; - private int pageLength = 0; - private int pageSequenceNumber, streamSerialNumber; - private byte[] segmentTable; - - private List packetList = new ArrayList(); - private boolean lastPacketIncomplete = false; - - private long startByte = 0; - - public OggPageHeader(byte[] b) { - this.rawHeaderData = b; - int streamStructureRevision = b[FIELD_STREAM_STRUCTURE_VERSION_POS]; - headerTypeFlag = b[FIELD_HEADER_TYPE_FLAG_POS]; - if (streamStructureRevision == 0) { - this.absoluteGranulePosition = 0; - for (int i = 0; i < FIELD_ABSOLUTE_GRANULE_LENGTH; i++) { - this.absoluteGranulePosition += u(b[i + FIELD_ABSOLUTE_GRANULE_POS]) * Math.pow(2, 8 * i); - } - - streamSerialNumber = Utils.getIntLE(b, FIELD_STREAM_SERIAL_NO_POS, 17); - pageSequenceNumber = Utils.getIntLE(b, FIELD_PAGE_SEQUENCE_NO_POS, 21); - checksum = Utils.getIntLE(b, FIELD_PAGE_CHECKSUM_POS, 25); - int pageSegments = u(b[FIELD_PAGE_SEGMENTS_POS]); - - this.segmentTable = new byte[b.length - OGG_PAGE_HEADER_FIXED_LENGTH]; - int packetLength = 0; - Integer segmentLength = null; - for (int i = 0; i < segmentTable.length; i++) { - segmentTable[i] = b[OGG_PAGE_HEADER_FIXED_LENGTH + i]; - segmentLength = u(segmentTable[i]); - this.pageLength += segmentLength; - packetLength += segmentLength; - - if (segmentLength < MAXIMUM_SEGMENT_SIZE) { - packetList.add(new PacketStartAndLength(pageLength - packetLength, packetLength)); - packetLength = 0; - } - } - - //If last segment value is 255 this packet continues onto next page - //and will not have been added to the packetStartAndEnd list yet - if (segmentLength != null) { - if (segmentLength == MAXIMUM_SEGMENT_SIZE) { - packetList.add(new PacketStartAndLength(pageLength - packetLength, packetLength)); - lastPacketIncomplete = true; - } - } - isValid = true; - } - - if (logger.isLoggable(Level.CONFIG)) { - logger.config("Constructed OggPage:" + this.toString()); - } - } - - /** - * Read next PageHeader from Buffer - * - * @param byteBuffer - * @return - * @throws IOException - * @throws CannotReadException - */ - public static OggPageHeader read(ByteBuffer byteBuffer) throws IOException, CannotReadException { - //byteBuffer - int start = byteBuffer.position(); - logger.fine("Trying to read OggPage at:" + start); - - byte[] b = new byte[OggPageHeader.CAPTURE_PATTERN.length]; - byteBuffer.get(b); - if (!(Arrays.equals(b, OggPageHeader.CAPTURE_PATTERN))) { - throw new CannotReadException(ErrorMessage.OGG_HEADER_CANNOT_BE_FOUND.getMsg(new String(b))); - } - - byteBuffer.position(start + OggPageHeader.FIELD_PAGE_SEGMENTS_POS); - int pageSegments = byteBuffer.get() & 0xFF; //unsigned - byteBuffer.position(start); - - b = new byte[OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageSegments]; - byteBuffer.get(b); - OggPageHeader pageHeader = new OggPageHeader(b); - - //Now just after PageHeader, ready for Packet Data - return pageHeader; - } - - /** - * Read next PageHeader from file - * - * @param raf - * @return - * @throws IOException - * @throws CannotReadException - */ - public static OggPageHeader read(RandomAccessFile raf) throws IOException, CannotReadException { - long start = raf.getFilePointer(); - logger.fine("Trying to read OggPage at:" + start); - - byte[] b = new byte[OggPageHeader.CAPTURE_PATTERN.length]; - raf.read(b); - if (!(Arrays.equals(b, OggPageHeader.CAPTURE_PATTERN))) { - raf.seek(start); - if (AbstractID3v2Tag.isId3Tag(raf)) { - logger.warning(ErrorMessage.OGG_CONTAINS_ID3TAG.getMsg(raf.getFilePointer() - start)); - raf.read(b); - if ((Arrays.equals(b, OggPageHeader.CAPTURE_PATTERN))) { - //Go to the end of the ID3 header - start = raf.getFilePointer() - OggPageHeader.CAPTURE_PATTERN.length; - } - } else { - throw new CannotReadException(ErrorMessage.OGG_HEADER_CANNOT_BE_FOUND.getMsg(new String(b))); - } - } - - raf.seek(start + OggPageHeader.FIELD_PAGE_SEGMENTS_POS); - int pageSegments = raf.readByte() & 0xFF; //unsigned - raf.seek(start); - - b = new byte[OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + pageSegments]; - raf.read(b); - - - OggPageHeader pageHeader = new OggPageHeader(b); - pageHeader.setStartByte(start); - //Now just after PageHeader, ready for Packet Data - return pageHeader; - } - - private int u(int i) { - return i & 0xFF; - } - - /** - * @return true if the last packet on this page extends to the next page - */ - public boolean isLastPacketIncomplete() { - return lastPacketIncomplete; - } - - public double getAbsoluteGranulePosition() { - logger.fine("Number Of Samples: " + absoluteGranulePosition); - return this.absoluteGranulePosition; - } - - - public int getCheckSum() { - return checksum; - } - - - public byte getHeaderType() { - return headerTypeFlag; - } - - - public int getPageLength() { - logger.fine("This page length: " + pageLength); - return this.pageLength; - } - - public int getPageSequence() { - return pageSequenceNumber; - } - - public int getSerialNumber() { - return streamSerialNumber; - } - - public byte[] getSegmentTable() { - return this.segmentTable; - } - - public boolean isValid() { - return isValid; - } - - /** - * @return a list of packet start position and size within this page. - */ - public List getPacketList() { - return packetList; - } - - /** - * @return the raw header data that this pageheader is derived from - */ - public byte[] getRawHeaderData() { - return rawHeaderData; - } - - public String toString() { - String out = "Ogg Page Header:isValid:" + isValid + ":type:" + headerTypeFlag + ":oggPageHeaderLength:" + rawHeaderData.length + ":length:" + pageLength + ":seqNo:" + getPageSequence() + ":packetIncomplete:" + isLastPacketIncomplete() + ":serNum:" + this.getSerialNumber(); - - for (PacketStartAndLength packet : getPacketList()) { - out += packet.toString(); - } - return out; - } - - /** - * Startbyte of this pageHeader in the file - *

    - * This is useful for Ogg files that contain unsupported additional data at the start of the file such - * as ID3 data - */ - public long getStartByte() { - return startByte; - } - - public void setStartByte(long startByte) { - this.startByte = startByte; - } - - /** - * This represents all the flags that can be set in the headerType field. - * Note these values can be ORED together. For example the last packet in - * a file would normally have a value of 0x5 because both the CONTINUED_PACKET - * bit and the END_OF_BITSTREAM bit would be set. - */ - public enum HeaderTypeFlag { - FRESH_PACKET((byte) 0x0), - CONTINUED_PACKET((byte) 0x1), - START_OF_BITSTREAM((byte) 0x2), - END_OF_BITSTREAM((byte) 0x4); - - byte fileValue; - - HeaderTypeFlag(byte fileValue) { - this.fileValue = fileValue; - } - - /** - * @return the value that should be written to file to enable this flag - */ - public byte getFileValue() { - return fileValue; - } - } - - /** - * Within the page specifies the start and length of each packet - * in the page offset from the end of the pageheader (after the segment table) - */ - public static class PacketStartAndLength { - private Integer startPosition = 0; - private Integer length = 0; - - public PacketStartAndLength(int startPosition, int length) { - this.startPosition = startPosition; - this.length = length; - } - - public int getStartPosition() { - return startPosition; - } - - public void setStartPosition(int startPosition) { - this.startPosition = startPosition; - } - - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } - - public String toString() { - return "NextPkt(start:" + startPosition + ":length:" + length + "),"; - } - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisHeader.java b/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisHeader.java deleted file mode 100644 index c116def..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisHeader.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jaudiotagger.audio.ogg.util; - -/** - * Defines variables common to all vorbis headers - */ -public interface VorbisHeader { - //Capture pattern at start of header - String CAPTURE_PATTERN = "vorbis"; - - byte[] CAPTURE_PATTERN_AS_BYTES = {'v', 'o', 'r', 'b', 'i', 's'}; - - int FIELD_PACKET_TYPE_POS = 0; - int FIELD_CAPTURE_PATTERN_POS = 1; - - int FIELD_PACKET_TYPE_LENGTH = 1; - int FIELD_CAPTURE_PATTERN_LENGTH = 6; - - //Vorbis uses UTF-8 for all text - String CHARSET_UTF_8 = "UTF-8"; - -} diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java b/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java deleted file mode 100644 index 44f3152..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.ogg.util; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.ogg.VorbisVersion; - -import java.util.logging.Logger; - - -/** - * Vorbis Identification header - *

    - * From http://xiph.org/vorbis/doc/Vorbis_I_spec.html#id326710 - *

    - * The identification header is a short header of only a few fields used to declare the stream definitively as Vorbis, - * and provide a few externally relevant pieces of information about the audio stream. The identification header is - * coded as follows: - *

    - * 1) [vorbis_version] = read 32 bits as unsigned integer - * 2) [audio_channels] = read 8 bit integer as unsigned - * 3) [audio_sample_rate] = read 32 bits as unsigned integer - * 4) [bitrate_maximum] = read 32 bits as signed integer - * 5) [bitrate_nominal] = read 32 bits as signed integer - * 6) [bitrate_minimum] = read 32 bits as signed integer - * 7) [blocksize_0] = 2 exponent (read 4 bits as unsigned integer) - * 8) [blocksize_1] = 2 exponent (read 4 bits as unsigned integer) - * 9) [framing_flag] = read one bit - *

    - * $Id: VorbisIdentificationHeader.java 813 2009-09-03 09:23:25Z paultaylor $ - * - * @author Raphael Slinckx (KiKiDonK) - * @version 16 d�cembre 2003 - */ -public class VorbisIdentificationHeader implements VorbisHeader { - public static final int FIELD_VORBIS_VERSION_POS = 7; - public static final int FIELD_AUDIO_CHANNELS_POS = 11; - public static final int FIELD_AUDIO_SAMPLE_RATE_POS = 12; - public static final int FIELD_BITRATE_MAX_POS = 16; - public static final int FIELD_BITRATE_NOMAIML_POS = 20; - public static final int FIELD_BITRATE_MIN_POS = 24; - public static final int FIELD_BLOCKSIZE_POS = 28; - public static final int FIELD_FRAMING_FLAG_POS = 29; - public static final int FIELD_VORBIS_VERSION_LENGTH = 4; - public static final int FIELD_AUDIO_CHANNELS_LENGTH = 1; - public static final int FIELD_AUDIO_SAMPLE_RATE_LENGTH = 4; - public static final int FIELD_BITRATE_MAX_LENGTH = 4; - public static final int FIELD_BITRATE_NOMAIML_LENGTH = 4; - public static final int FIELD_BITRATE_MIN_LENGTH = 4; - public static final int FIELD_BLOCKSIZE_LENGTH = 1; - public static final int FIELD_FRAMING_FLAG_LENGTH = 1; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg.atom"); - private int audioChannels; - private boolean isValid = false; - private int vorbisVersion, audioSampleRate; - private int bitrateMinimal, bitrateNominal, bitrateMaximal; - - - public VorbisIdentificationHeader(byte[] vorbisData) { - decodeHeader(vorbisData); - } - - - public int getChannelNumber() { - return audioChannels; - } - - - public String getEncodingType() { - return VorbisVersion.values()[vorbisVersion].toString(); - } - - - public int getSamplingRate() { - return audioSampleRate; - } - - public int getNominalBitrate() { - return bitrateNominal; - } - - public int getMaxBitrate() { - return bitrateMaximal; - } - - public int getMinBitrate() { - return bitrateMinimal; - } - - public boolean isValid() { - return isValid; - } - - - public void decodeHeader(byte[] b) { - int packetType = b[FIELD_PACKET_TYPE_POS]; - logger.fine("packetType" + packetType); - String vorbis = Utils.getString(b, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH, "ISO-8859-1"); - - if (packetType == VorbisPacketType.IDENTIFICATION_HEADER.getType() && vorbis.equals(CAPTURE_PATTERN)) { - this.vorbisVersion = b[7] + (b[8] << 8) + (b[9] << 16) + (b[10] << 24); - logger.fine("vorbisVersion" + vorbisVersion); - this.audioChannels = u(b[FIELD_AUDIO_CHANNELS_POS]); - logger.fine("audioChannels" + audioChannels); - this.audioSampleRate = u(b[12]) + (u(b[13]) << 8) + (u(b[14]) << 16) + (u(b[15]) << 24); - logger.fine("audioSampleRate" + audioSampleRate); - logger.fine("audioSampleRate" + b[12] + " " + b[13] + " " + b[14]); - - //TODO is this right spec says signed - this.bitrateMinimal = u(b[16]) + (u(b[17]) << 8) + (u(b[18]) << 16) + (u(b[19]) << 24); - this.bitrateNominal = u(b[20]) + (u(b[21]) << 8) + (u(b[22]) << 16) + (u(b[23]) << 24); - this.bitrateMaximal = u(b[24]) + (u(b[25]) << 8) + (u(b[26]) << 16) + (u(b[27]) << 24); - //byte blockSize0 = (byte) ( b[28] & 240 ); - //byte blockSize1 = (byte) ( b[28] & 15 ); - - int framingFlag = b[FIELD_FRAMING_FLAG_POS]; - logger.fine("framingFlag" + framingFlag); - if (framingFlag != 0) { - isValid = true; - } - - } - } - - private int u(int i) { - return i & 0xFF; - } -} - diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisPacketType.java b/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisPacketType.java deleted file mode 100644 index e6151a3..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisPacketType.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.jaudiotagger.audio.ogg.util; - -/** - * Vorbis Packet Type - *

    - * In an Vorbis Stream there should be one instance of the three headers, and many audio packets - */ -public enum VorbisPacketType { - AUDIO(0), - IDENTIFICATION_HEADER(1), - COMMENT_HEADER(3), - SETUP_HEADER(5); - - int type; - - VorbisPacketType(int type) { - this.type = type; - } - - public int getType() { - return type; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java b/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java deleted file mode 100644 index 509c2d7..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.jaudiotagger.audio.ogg.util; - -import org.jaudiotagger.audio.generic.Utils; - -import java.util.logging.Logger; - -/** - * Vorbis Setup header - *

    - * We dont need to decode a vorbis setup header for metatagging, but we should be able to identify - * it. - * - * @author Paul Taylor - * @version 12th August 2007 - */ -public class VorbisSetupHeader implements VorbisHeader { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.ogg.atom"); - - private boolean isValid = false; - - public VorbisSetupHeader(byte[] vorbisData) { - decodeHeader(vorbisData); - } - - public boolean isValid() { - return isValid; - } - - public void decodeHeader(byte[] b) { - int packetType = b[FIELD_PACKET_TYPE_POS]; - logger.fine("packetType" + packetType); - String vorbis = Utils.getString(b, FIELD_CAPTURE_PATTERN_POS, FIELD_CAPTURE_PATTERN_LENGTH, "ISO-8859-1"); - if (packetType == VorbisPacketType.SETUP_HEADER.getType() && vorbis.equals(CAPTURE_PATTERN)) { - isValid = true; - } - } - -} diff --git a/src/main/java/org/jaudiotagger/audio/ogg/util/package.html b/src/main/java/org/jaudiotagger/audio/ogg/util/package.html deleted file mode 100644 index 4cf9fe1..0000000 --- a/src/main/java/org/jaudiotagger/audio/ogg/util/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Utility classes for Ogg Vorbis files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/package.html b/src/main/java/org/jaudiotagger/audio/package.html deleted file mode 100644 index 4651816..0000000 --- a/src/main/java/org/jaudiotagger/audio/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes and interfaces generic to all audio formats. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/real/RealChunk.java b/src/main/java/org/jaudiotagger/audio/real/RealChunk.java deleted file mode 100644 index 713b958..0000000 --- a/src/main/java/org/jaudiotagger/audio/real/RealChunk.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.jaudiotagger.audio.real; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.RandomAccessFile; - -public class RealChunk { - - protected static final String RMF = ".RMF"; - protected static final String PROP = "PROP"; - protected static final String MDPR = "MDPR"; - protected static final String CONT = "CONT"; - protected static final String DATA = "DATA"; - protected static final String INDX = "INDX"; - - private final String id; - private final int size; - private final byte[] bytes; - - public RealChunk(String id, int size, byte[] bytes) { - super(); - this.id = id; - this.size = size; - this.bytes = bytes; - } - - public static RealChunk readChunk(RandomAccessFile raf) - throws CannotReadException, IOException { - final String id = Utils.readString(raf, 4); - final int size = Utils.readUint32AsInt(raf); - if (size < 8) { - throw new CannotReadException( - "Corrupt file: RealAudio chunk length at position " - + (raf.getFilePointer() - 4) - + " cannot be less than 8"); - } - if (size > (raf.length() - raf.getFilePointer() + 8)) { - throw new CannotReadException( - "Corrupt file: RealAudio chunk length of " + size - + " at position " + (raf.getFilePointer() - 4) - + " extends beyond the end of the file"); - } - final byte[] bytes = new byte[size - 8]; - raf.readFully(bytes); - return new RealChunk(id, size, bytes); - } - - public DataInputStream getDataInputStream() { - return new DataInputStream(new ByteArrayInputStream(getBytes())); - } - - public boolean isCONT() { - return CONT.equals(id); - } - - public boolean isPROP() { - return PROP.equals(id); - } - - public byte[] getBytes() { - return bytes; - } - - public String getId() { - return id; - } - - public int getSize() { - return size; - } - - @Override - public String toString() { - return id + "\t" + size; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/real/RealFileReader.java b/src/main/java/org/jaudiotagger/audio/real/RealFileReader.java deleted file mode 100644 index d22c1d9..0000000 --- a/src/main/java/org/jaudiotagger/audio/real/RealFileReader.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.jaudiotagger.audio.real; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.FieldDataInvalidException; -import org.jaudiotagger.tag.FieldKey; -import org.jaudiotagger.tag.Tag; - -import java.io.DataInputStream; -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Real Media File Format: Major Chunks: .RMF PROP MDPR CONT DATA INDX - */ -public class RealFileReader extends AudioFileReader { - - @Override - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException { - final GenericAudioHeader rv = new GenericAudioHeader(); - final RealChunk prop = findPropChunk(raf); - final DataInputStream dis = prop.getDataInputStream(); - final int objVersion = Utils.readUint16(dis); - if (objVersion == 0) { - final long maxBitRate = Utils.readUint32(dis) / 1000; - final long avgBitRate = Utils.readUint32(dis) / 1000; - final long maxPacketSize = Utils.readUint32(dis); - final long avgPacketSize = Utils.readUint32(dis); - final long packetCnt = Utils.readUint32(dis); - final int duration = Utils.readUint32AsInt(dis) / 1000; - final long preroll = Utils.readUint32(dis); - final long indexOffset = Utils.readUint32(dis); - final long dataOffset = Utils.readUint32(dis); - final int numStreams = Utils.readUint16(dis); - final int flags = Utils.readUint16(dis); - rv.setBitrate((int) avgBitRate); - rv.setLength(duration); - rv.setVariableBitRate(maxBitRate != avgBitRate); - } - return rv; - } - - private RealChunk findPropChunk(RandomAccessFile raf) throws IOException, CannotReadException { - final RealChunk rmf = RealChunk.readChunk(raf); - final RealChunk prop = RealChunk.readChunk(raf); - return prop; - } - - private RealChunk findContChunk(RandomAccessFile raf) throws IOException, CannotReadException { - final RealChunk rmf = RealChunk.readChunk(raf); - final RealChunk prop = RealChunk.readChunk(raf); - RealChunk rv = RealChunk.readChunk(raf); - while (!rv.isCONT()) rv = RealChunk.readChunk(raf); - return rv; - } - - @Override - protected Tag getTag(RandomAccessFile raf) throws CannotReadException, IOException { - final RealChunk cont = findContChunk(raf); - final DataInputStream dis = cont.getDataInputStream(); - final String title = Utils.readString(dis, Utils.readUint16(dis)); - final String author = Utils.readString(dis, Utils.readUint16(dis)); - final String copyright = Utils.readString(dis, Utils.readUint16(dis)); - final String comment = Utils.readString(dis, Utils.readUint16(dis)); - final RealTag rv = new RealTag(); - // NOTE: frequently these fields are off-by-one, thus the crazy - // logic below... - try { - rv.addField(FieldKey.TITLE, (title.length() == 0 ? author : title)); - rv.addField(FieldKey.ARTIST, title.length() == 0 ? copyright : author); - rv.addField(FieldKey.COMMENT, comment); - } catch (FieldDataInvalidException fdie) { - throw new RuntimeException(fdie); - } - return rv; - } - -} - diff --git a/src/main/java/org/jaudiotagger/audio/real/RealTag.java b/src/main/java/org/jaudiotagger/audio/real/RealTag.java deleted file mode 100644 index 7727412..0000000 --- a/src/main/java/org/jaudiotagger/audio/real/RealTag.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.jaudiotagger.audio.real; - -import org.jaudiotagger.audio.generic.GenericTag; - -public class RealTag extends GenericTag { - public String toString() { - String output = "REAL " + super.toString(); - return output; - } - - -} diff --git a/src/main/java/org/jaudiotagger/audio/real/package.html b/src/main/java/org/jaudiotagger/audio/real/package.html deleted file mode 100644 index 12ff71e..0000000 --- a/src/main/java/org/jaudiotagger/audio/real/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes dealing with RealAudio (TM) files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/wav/WavFileReader.java b/src/main/java/org/jaudiotagger/audio/wav/WavFileReader.java deleted file mode 100644 index ded044f..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/WavFileReader.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.wav; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.AudioFileReader; -import org.jaudiotagger.audio.generic.GenericAudioHeader; -import org.jaudiotagger.audio.wav.util.WavInfoReader; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class WavFileReader extends AudioFileReader { - - private WavInfoReader ir = new WavInfoReader(); - - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException { - return ir.read(raf); - } - - protected Tag getTag(RandomAccessFile raf) throws CannotReadException { - return new WavTag(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/wav/WavFileWriter.java b/src/main/java/org/jaudiotagger/audio/wav/WavFileWriter.java deleted file mode 100644 index b647d83..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/WavFileWriter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.wav; - -import org.jaudiotagger.audio.exceptions.CannotWriteException; -import org.jaudiotagger.audio.generic.AudioFileWriter; -import org.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class WavFileWriter extends AudioFileWriter { - protected void writeTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException { - //Nothing to do for wav file, no tag are supported - } - - protected void deleteTag(RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotWriteException, IOException { - //Nothing to do for wav file, no tag are supported - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/wav/WavTag.java b/src/main/java/org/jaudiotagger/audio/wav/WavTag.java deleted file mode 100644 index e3472ec..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/WavTag.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.wav; - -import org.jaudiotagger.audio.generic.GenericTag; - -public class WavTag extends GenericTag { - public String toString() { - String output = "WAV " + super.toString(); - return output; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/wav/package.html b/src/main/java/org/jaudiotagger/audio/wav/package.html deleted file mode 100644 index f185ff5..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for WAVE audio files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/audio/wav/util/WavFormatHeader.java b/src/main/java/org/jaudiotagger/audio/wav/util/WavFormatHeader.java deleted file mode 100644 index 8308be5..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/util/WavFormatHeader.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.wav.util; - -public class WavFormatHeader { - private static final int WAVE_FORMAT_PCM = 0x0001; - private static final int WAVE_FORMAT_EXTENSIBLE = 0xFFFE; - - private boolean isValid = false; - - private int format, channels, sampleRate, bytesPerSecond, bitsPerSample, validBitsPerSample, channelMask, subFormat; - - public WavFormatHeader(byte[] b) { - String fmt = new String(b, 0, 3); - format = u(b[9]) * 256 + u(b[8]); - //System.err.println("format : "+ format); - //System.err.println(fmt); - if (fmt.equals("fmt") && (format == WAVE_FORMAT_PCM || format == WAVE_FORMAT_EXTENSIBLE)) { - channels = b[10]; - //System.err.println(channels); - sampleRate = u(b[15]) * 16777216 + u(b[14]) * 65536 + u(b[13]) * 256 + u(b[12]); - //System.err.println(sampleRate); - bytesPerSecond = u(b[19]) * 16777216 + u(b[18]) * 65536 + u(b[17]) * 256 + u(b[16]); - //System.err.println(bytesPerSecond); - bitsPerSample = u(b[22]); - - if (format == WAVE_FORMAT_EXTENSIBLE && u(b[24]) == 22) { - validBitsPerSample = u(b[26]); - channelMask = u(b[31]) * 16777216 + u(b[20]) * 65536 + u(b[29]) * 256 + u(b[28]); - subFormat = u(b[33]) * 256 + u(b[32]); - } - - isValid = true; - } - - } - - public boolean isExtensible() { - return format == WAVE_FORMAT_EXTENSIBLE; - } - - public int getFormat() { - return format; - } - - public boolean isValid() { - return isValid; - } - - public int getChannelMask() { - return channelMask; - } - - public int getSubFormat() { - return subFormat; - } - - public int getValidBitsPerSample() { - return validBitsPerSample; - } - - public int getChannelNumber() { - return channels; - } - - public int getSamplingRate() { - return sampleRate; - } - - public int getBytesPerSecond() { - return bytesPerSecond; - } - - public int getBitsPerSample() { - return bitsPerSample; - } - - private int u(int n) { - return n & 0xff; - } - - public String toString() { - String out = "RIFF-WAVE Header:\n"; - out += "Is valid?: " + isValid; - return out; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/wav/util/WavInfoReader.java b/src/main/java/org/jaudiotagger/audio/wav/util/WavInfoReader.java deleted file mode 100644 index 30f38d1..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/util/WavInfoReader.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.wav.util; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.GenericAudioHeader; - -import java.io.IOException; -import java.io.RandomAccessFile; - -public class WavInfoReader { - public GenericAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException { - // Reads wav header---------------------------------------- - GenericAudioHeader info = new GenericAudioHeader(); - - if (raf.length() < 12) { - throw new CannotReadException("This is not a WAV File (<12 bytes)"); - } - byte[] b = new byte[12]; - raf.read(b); - - WavRIFFHeader wh = new WavRIFFHeader(b); - if (wh.isValid()) { - b = new byte[34]; - raf.read(b); - - WavFormatHeader wfh = new WavFormatHeader(b); - if (wfh.isValid()) { - // Populates - // encodingInfo---------------------------------------------------- - info.setPreciseLength(((float) raf.length() - (float) 36) / wfh.getBytesPerSecond()); - info.setChannelNumber(wfh.getChannelNumber()); - info.setSamplingRate(wfh.getSamplingRate()); - info.setBitsPerSample(wfh.getBitsPerSample()); - info.setEncodingType("WAV-RIFF " + wfh.getBitsPerSample() + " bits"); - info.setExtraEncodingInfos(""); - info.setBitrate(wfh.getBytesPerSecond() * 8 / 1000); - info.setVariableBitRate(false); - } else { - throw new CannotReadException("Wav Format Header not valid"); - } - } else { - throw new CannotReadException("Wav RIFF Header not valid"); - } - - return info; - } -} diff --git a/src/main/java/org/jaudiotagger/audio/wav/util/WavRIFFHeader.java b/src/main/java/org/jaudiotagger/audio/wav/util/WavRIFFHeader.java deleted file mode 100644 index 349803e..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/util/WavRIFFHeader.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.audio.wav.util; - -public class WavRIFFHeader { - - private boolean isValid = false; - - public WavRIFFHeader(byte[] b) { - //System.err.println(b.length); - String RIFF = new String(b, 0, 4); - //System.err.println(RIFF); - String WAVE = new String(b, 8, 4); - //System.err.println(WAVE); - if (RIFF.equals("RIFF") && WAVE.equals("WAVE")) { - isValid = true; - } - - } - - public boolean isValid() { - return isValid; - } - - public String toString() { - String out = "RIFF-WAVE Header:\n"; - out += "Is valid?: " + isValid; - return out; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/audio/wav/util/package.html b/src/main/java/org/jaudiotagger/audio/wav/util/package.html deleted file mode 100644 index fd0ed3f..0000000 --- a/src/main/java/org/jaudiotagger/audio/wav/util/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Utility classes for WAVE audio files. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/logging/AbstractTagDisplayFormatter.java b/src/main/java/org/jaudiotagger/logging/AbstractTagDisplayFormatter.java deleted file mode 100644 index 71e56f6..0000000 --- a/src/main/java/org/jaudiotagger/logging/AbstractTagDisplayFormatter.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractTagDisplayFormatter.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * This abstract class defines methods for writing out the contents of a tag in a user-friendly way - * Concrete subclasses could implement different versions such as XML Output, PDF and so on. The tag - * in all cases is diaplyed as a sort of tree hierachy. - */ -package org.jaudiotagger.logging; - -import java.util.HashMap; - -/** - * Abstract class that provides structure to use for displaying a files metadata content - */ -public abstract class AbstractTagDisplayFormatter { - private static HashMap hexBinaryMap = new HashMap(); - - static { - hexBinaryMap.put("0", "0000"); - hexBinaryMap.put("1", "0001"); - hexBinaryMap.put("2", "0010"); - hexBinaryMap.put("3", "0011"); - hexBinaryMap.put("4", "0100"); - hexBinaryMap.put("5", "0101"); - hexBinaryMap.put("6", "0110"); - hexBinaryMap.put("7", "0111"); - hexBinaryMap.put("8", "1000"); - hexBinaryMap.put("9", "1001"); - hexBinaryMap.put("a", "1010"); - hexBinaryMap.put("b", "1011"); - hexBinaryMap.put("c", "1100"); - hexBinaryMap.put("d", "1101"); - hexBinaryMap.put("e", "1110"); - hexBinaryMap.put("f", "1111"); - } - - protected int level; - - /** - * Use to display headers as their binary representation - * - * @param buffer - * @return - */ - public static String displayAsBinary(byte buffer) { - //Convert buffer to hex representation - String hexValue = Integer.toHexString(buffer); - String char1 = ""; - String char2 = ""; - try { - if (hexValue.length() == 8) { - char1 = hexValue.substring(6, 7); - char2 = hexValue.substring(7, 8); - } else if (hexValue.length() == 2) { - char1 = hexValue.substring(0, 1); - char2 = hexValue.substring(1, 2); - } else if (hexValue.length() == 1) { - char1 = "0"; - char2 = hexValue.substring(0, 1); - } - } catch (StringIndexOutOfBoundsException se) { - return ""; - } - return hexBinaryMap.get(char1) + hexBinaryMap.get(char2); - } - - public abstract void openHeadingElement(String type, String value); - - public abstract void openHeadingElement(String type, boolean value); - - public abstract void openHeadingElement(String type, int value); - - public abstract void closeHeadingElement(String type); - - public abstract void addElement(String type, String value); - - public abstract void addElement(String type, int value); - - public abstract void addElement(String type, boolean value); - - public abstract String toString(); -} diff --git a/src/main/java/org/jaudiotagger/logging/ErrorMessage.java b/src/main/java/org/jaudiotagger/logging/ErrorMessage.java deleted file mode 100644 index 7094372..0000000 --- a/src/main/java/org/jaudiotagger/logging/ErrorMessage.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.jaudiotagger.logging; - -import java.text.MessageFormat; - -/** - * Defines Error Messages - */ -public enum ErrorMessage { - GENERAL_READ("File {0} being read"), - MP4_FILE_NOT_CONTAINER("This file does not appear to be an Mp4 file"), - MP4_FILE_NOT_AUDIO("This file does not appear to be an Mp4 Audio file, could be corrupted or video "), - MP4_FILE_IS_VIDEO("This file appears to be an Mp4 Video file, video files are not supported "), - MP4_UNABLE_TO_PRIME_FILE_FOR_WRITE_SAFETLY("Unable to safetly check consistency in Mp4 file so cancelling save"), - MP4_FILE_CONTAINS_MULTIPLE_DATA_ATOMS("File contains multiple data atoms"), - MP4_CHANGES_TO_FILE_FAILED("Unable to make changes to Mp4 file"), - MP4_CHANGES_TO_FILE_FAILED_NO_DATA("Unable to make changes to Mp4 file, no data was written"), - MP4_CHANGES_TO_FILE_FAILED_DATA_CORRUPT("Unable to make changes to Mp4 file, invalid data length has been written"), - MP4_CHANGES_TO_FILE_FAILED_NO_TAG_DATA("Unable to make changes to Mp4 file, no tag data has been written"), - MP4_CHANGES_TO_FILE_FAILED_INCORRECT_OFFSETS("Unable to make changes to Mp4 file, incorrect offsets written difference was {0}"), - MP4_CHANGES_TO_FILE_FAILED_CANNOT_FIND_AUDIO("Unable to make changes to Mp4 file, unable to determine start of audio"), - FLAC_NO_FLAC_HEADER_FOUND("Flac Header not found, not a flac file"), - OGG_VORBIS_NO_VORBIS_HEADER_FOUND("Cannot find vorbis setup parentHeader"), - MP4_REVERSE_DNS_FIELD_HAS_NO_DATA("Reverse dns field:{0} has no data"), - MP4_UNABLE_READ_REVERSE_DNS_FIELD("Unable to create reverse dns field because of exception:{0} adding as binary data instead"), - OGG_VORBIS_NO_FRAMING_BIT("The OGG Stream is not valid, Vorbis tag valid framing bit is wrong {0} "), - GENERAL_WRITE_FAILED("Cannot make changes to file {0}"), - GENERAL_WRITE_FAILED_FILE_LOCKED("Cannot make changes to file {0} because it is being used by another application"), - GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL("Cannot make changes to file {0} because too small to be an audio file"), - GENERAL_WRITE_FAILED_TO_DELETE_ORIGINAL_FILE("Cannot make changes to file {0} because unable to delete the original file ready for updating from temporary file {1}"), - GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE("Cannot make changes to file {0} because unable to rename from temporary file {1}"), - GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP("Cannot make changes to file {0} because unable to rename the original file to {1}"), - GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_BACKUP_TO_ORIGINAL("Unable to rename backup {0} back to file {1}"), - GENERAL_WRITE_FAILED_NEW_FILE_DOESNT_EXIST("New file {0} does not appear to exist"), - GENERAL_WRITE_FAILED_BECAUSE("Cannot make changes to file {0} because {1}"), - GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND("Cannot make changes to file {0} because the file cannot be found"), - GENERAL_WRITE_WARNING_UNABLE_TO_DELETE_BACKUP_FILE("Unable to delete the backup file {0}"), - GENERAL_WRITE_PROBLEM_CLOSING_FILE_HANDLE("Problem closing file handles for file {0} because {1}"), - GENERAL_DELETE_FAILED("Cannot delete file {0}"), - GENERAL_DELETE_FAILED_FILE_LOCKED("Cannot delete file {0} because it is being used by another application"), - GENERAL_DELETE_FAILED_BECAUSE_FILE_IS_TOO_SMALL("Cannot write to file {0} because too small to be an audio file"), - MP3_ID3TAG_LENGTH_INCORRECT(" {0}:Checking further because the ID3 Tag ends at {1} but the mp3 audio doesnt start until {2}"), - MP3_RECALCULATED_POSSIBLE_START_OF_MP3_AUDIO("{0}: Recalculated possible start of the audio to be at {1}"), - MP3_RECALCULATED_START_OF_MP3_AUDIO("{0}: Recalculated the start of the audio to be at {1}"), - MP3_START_OF_AUDIO_CONFIRMED("{0}: Confirmed audio starts at {1} whether searching from start or from end of ID3 tag"), - MP3_URL_SAVED_ENCODED("Url:{0} saved in encoded form as {1}"), - MP3_UNABLE_TO_ENCODE_URL("Unable to save url:{0} because cannot encode all characters setting to blank instead"), - MP4_UNABLE_TO_FIND_NEXT_ATOM_BECAUSE_IDENTIFIER_IS_INVALID("Unable to find next atom because identifier is invalid {0}"), - MP4_UNABLE_TO_FIND_NEXT_ATOM_BECAUSE_LENGTH_IS_INVALID("Unable to find next atom {0} because length is invalid {1}"), - GENERAL_INVALID_NULL_ARGUMENT("Argument cannot be null"), - MP4_NO_GENREID_FOR_GENRE("No genre id could be found for this genre atom with data length {0}"), - MP4_GENRE_OUT_OF_RANGE("Genre Id {0} does not map to a valid genre"), - MP3_PICTURE_TYPE_INVALID("Picture Type is set to invalid value:{0}"), - MP3_REFERENCE_KEY_INVALID("{0}:No key could be found with the value of:{1}"), - MP3_UNABLE_TO_ADJUST_PADDING("Problem adjusting padding in large file, expecting to write:{0} only wrote:{1}"), - GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE("Unable to delete the temporary file {0}"), - GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER("Cannot modify {0} because do not have permissions to create files in the folder {1}"), - GENERAL_WRITE_FAILED_TO_MODIFY_TEMPORARY_FILE_IN_FOLDER("Cannot modify {0} because do not have permissions to modify files in the folder {1}"), - GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING("Cannot modify {0} because do not have permissions to modify file"), - NULL_PADDING_FOUND_AT_END_OF_MP4("Null Padding found at end of file starting at offset {0}"), - OGG_VORBIS_NO_SETUP_BLOCK("Could not find the Ogg Setup block"), - OGG_HEADER_CANNOT_BE_FOUND("OggS Header could not be found, not an ogg stream {0}"), - GENERAL_READ_FAILED_UNABLE_TO_CLOSE_RANDOM_ACCESS_FILE("Unable to close random access file: {0}"), - GENERAL_READ_FAILED_FILE_TOO_SMALL("Unable to read file because it is too small to be valid audio file: {0}"), - GENERAL_READ_FAILED_DO_NOT_HAVE_PERMISSION_TO_READ_FILE("Unable to read file do not have permission to read: {0}"), - ASF_FILE_HEADER_SIZE_DOES_NOT_MATCH_FILE_SIZE("For file {0} the File header size is {1} but different to actual file size of {2}"), - ASF_FILE_HEADER_MISSING("For file {0} the File Header missing. Invalid ASF/WMA file."), - ASF_HEADER_MISSING("For file {0} the Asf Header missing. Invalid ASF/WMA file."), - GENERAL_UNIDENITIFED_IMAGE_FORMAT("Cannot safetly identify the format of this image setting to default type of Png"), - MP4_IMAGE_FORMAT_IS_NOT_TO_EXPECTED_TYPE("ImageFormat for cover art atom is not set to a known image format, instead set to {0}"), - MP3_FRAME_IS_COMPRESSED("Filename {0}:{1} is compressed"), - MP3_FRAME_IS_ENCRYPTED("Filename {0}:{1} is encrypted"), - MP3_FRAME_IS_GROUPED("Filename {0}:{1} is grouped"), - MP3_FRAME_IS_UNSYNCHRONISED("Filename {0}:{1} is unsynchronised"), - MP3_FRAME_IS_DATA_LENGTH_INDICATOR("Filename {0}:{1} has a data length indicator"), - MP4_FILE_HAS_NO_METADATA("This file does not currently contain any metadata"), - MP4_FILE_META_ATOM_CHILD_DATA_NOT_NULL("Expect data in meta box to be null"), - WMA_INVALID_FIELD_NAME("The field name {0} is not allowed for {1}"), - WMA_INVALID_LANGUAGE_USE("The use of language {0} ist not allowed for {1} (only {2} allowed)"), - WMA_INVALID_STREAM_REFERNCE("The stream number {0} is invalid. Only {1} allowed for {2}."), - WMA_INVALID_GUID_USE("The use of GUID ist not allowed for {0}"), - WMA_LENGTH_OF_DATA_IS_TOO_LARGE("Trying to create field with {0} bytes of data but the maximum data allowed in WMA files is {1} for {2}."), - WMA_LENGTH_OF_LANGUAGE_IS_TOO_LARGE("Trying to create language entry, but UTF-16LE representation is {0} and exceeds maximum allowed of 255."), - WMA_LENGTH_OF_STRING_IS_TOO_LARGE("Trying to create field but UTF-16LE representation is {0} and exceeds maximum allowed of 65535."), - WMA_ONLY_STRING_IN_CD("Only Strings are allowed in content description objects"), - ID3_EXTENDED_HEADER_SIZE_INVALID("{0} Invalid Extended Header Size of {0} assuming no extended header after all"), - ID3_EXTENDED_HEADER_SIZE_TOO_SMALL("{0} Invalid Extended Header Size of {0} is too smal to be valid"), - ID3_INVALID_OR_UNKNOWN_FLAG_SET("{0} Invalid or unknown bit flag 0x{1} set in ID3 tag header"), - ID3_TAG_UNSYNCHRONIZED("{0} the ID3 Tag is unsynchronized"), - ID3_TAG_EXPERIMENTAL("{0} the ID3 Tag is experimental"), - ID3_TAG_FOOTER("{0} the ID3 Tag is has a footer"), - ID3_TAG_EXTENDED("{0} the ID3 Tag is extended"), - ID3_TAG_CRC("{0} the ID3 Tag has crc check"), - ID3_TAG_COMPRESSED("{0} the ID3 Tag is compressed"), - ID3_TAG_CRC_SIZE("{0} According to Extended Header the ID3 Tag has crc32 of {1}"), - ID3_TAG_PADDING_SIZE("{0} According to Extended Header the ID3 Tag has padding size of {1}"), - ID_TAG_SIZE("{0} Tag size is {1} according to header (does not include header size, add 10)"), - ID3_TAG_CRC_FLAG_SET_INCORRECTLY("{0} CRC Data flag not set correctly."), - MP4_CANNOT_FIND_AUDIO("Unable to determine start of audio in file"), - VORBIS_COMMENT_LENGTH_TOO_LARGE("Comment field length is very large {0} , assuming comment is corrupt"), - VORBIS_COMMENT_LENGTH_LARGE_THAN_HEADER("Comment field length {0} is larger than total comment header {1} "), - ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD("Cover Art cannot be created using this method"), - ARTWORK_CANNOT_BE_RETRIEVED_WITH_THIS_METHOD("Cover Art cannot be retrieved using this method"), - GENERIC_NOT_SUPPORTED("Not implemented for this format"), - ID3_UNABLE_TO_DECOMPRESS_FRAME("Unable to decompress frame {0} in file {1} because {2}"), - NO_WRITER_FOR_THIS_FORMAT("No Writer associated with this extension:{0}"), - NO_READER_FOR_THIS_FORMAT("No Reader associated with this extension:{0}"), - NO_DELETER_FOR_THIS_FORMAT("No Deleter associated with this extension:{0}"), - UNABLE_TO_FIND_FILE("Unable to find:{0}"), - NO_PERMISSIONS_TO_WRITE_TO_FILE("Unable to write to:{0}"), - DO_NOT_KNOW_HOW_TO_CREATE_THIS_ATOM_TYPE("DO not know how to create this atom type {0}"), - OGG_CONTAINS_ID3TAG("Ogg File contains invalid ID3 Tag, skipping ID3 Tag of length:{0}"), - FLAC_CONTAINS_ID3TAG("Flac File contains invalid ID3 Tag, skipping ID3 Tag of length:{0}"), - ADDITIONAL_MOOV_ATOM_AT_END_OF_MP4("Additional moov atom found at end of file starting at offset {0}"), - ATOM_LENGTH_LARGER_THAN_DATA("The atom {0} states its data length to be {1} but there are only {2} bytes remaining in the file"), - INVALID_FIELD_FOR_ID3V1TAG("Invalid field {0} for ID3v1 tag"), - NO_AUDIO_HEADER_FOUND("No audio header found within {0}"),; - - - String msg; - - ErrorMessage(String msg) { - this.msg = msg; - } - - public String getMsg() { - return msg; - } - - public String getMsg(Object... args) { - return MessageFormat.format(getMsg(), args); - } - -} diff --git a/src/main/java/org/jaudiotagger/logging/FileSystemMessage.java b/src/main/java/org/jaudiotagger/logging/FileSystemMessage.java deleted file mode 100644 index e503d75..0000000 --- a/src/main/java/org/jaudiotagger/logging/FileSystemMessage.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.jaudiotagger.logging; - -/** - * For parsing the exact cause of a file exception, because variations not handled well by Java - */ -public enum FileSystemMessage { - ACCESS_IS_DENIED("Access is denied"),; - String msg; - - FileSystemMessage(String msg) { - this.msg = msg; - } - - public String getMsg() { - return msg; - } -} diff --git a/src/main/java/org/jaudiotagger/logging/Hex.java b/src/main/java/org/jaudiotagger/logging/Hex.java deleted file mode 100644 index a216478..0000000 --- a/src/main/java/org/jaudiotagger/logging/Hex.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.jaudiotagger.logging; - -/** - * Display as hex - */ -public class Hex { - /** - * Display as hex - * - * @param value - * @return - */ - public static String asHex(long value) { - return "0x" + Long.toHexString(value); - } - - /** - * Display as hex - * - * @param value - * @return - */ - public static String asHex(byte value) { - return "0x" + Integer.toHexString(value); - } -} diff --git a/src/main/java/org/jaudiotagger/logging/LogFormatter.java b/src/main/java/org/jaudiotagger/logging/LogFormatter.java deleted file mode 100644 index 36537f2..0000000 --- a/src/main/java/org/jaudiotagger/logging/LogFormatter.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.jaudiotagger.logging; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.logging.Formatter; -import java.util.logging.LogRecord; - -/** - * For Formatting log output - *

    - *

    This is not required by jaudiotagger, but its advantage over the default formatter is that all the format for a log - * entry is on one line, making it much easier to read. To use this formatter with your code edit loggin.properties - * within your jre/lib folder and modify as follows - * e.g java.util.logging.ConsoleHandler.formatter = org.jaudiotagger.logging.LogFormatter

    - */ -public final class LogFormatter extends Formatter { - public static final String ACTION_PERFORMED = "actionPerformed"; - public static final String IDENT = "$Id: LogFormatter.java 836 2009-11-12 15:44:07Z paultaylor $"; - // Line separator string. This is the value of the line.separator - // property at the moment that the SimpleFormatter was created. - private final String lineSeparator = System.lineSeparator(); - - private final SimpleDateFormat sfDateOut = new SimpleDateFormat("dd/MM/yyyy HH.mm.ss:"); - private final Date date = new Date(); - private boolean isObsfucated = false; - - public LogFormatter() { - - } - - public final String format(final LogRecord record) { - final StringBuffer sb = new StringBuffer(); - - date.setTime(record.getMillis()); - - sb.append(sfDateOut.format(date)); - - String recordName; - - if (record.getSourceClassName() != null) { - recordName = record.getSourceClassName() + ":" + record.getSourceMethodName(); - } else { - recordName = record.getLoggerName() + ":"; - } - if (recordName != null) { - sb.append(recordName); - sb.append(":"); - } - final String message = formatMessage(record); - sb.append(record.getLevel().getLocalizedName()); - sb.append(": "); - sb.append(message); - sb.append(lineSeparator); - - if (record.getThrown() != null) { - try { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - record.getThrown().printStackTrace(pw); - pw.close(); - sb.append(sw.toString()); - } catch (Exception ex) { - } - } - return sb.toString(); - } -} - diff --git a/src/main/java/org/jaudiotagger/logging/PlainTextTagDisplayFormatter.java b/src/main/java/org/jaudiotagger/logging/PlainTextTagDisplayFormatter.java deleted file mode 100644 index 97fa0be..0000000 --- a/src/main/java/org/jaudiotagger/logging/PlainTextTagDisplayFormatter.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: PlainTextTagDisplayFormatter.java 792 2009-05-05 15:59:19Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.logging; - - -/* - * For Formatting metadata contents of a file as simple text -*/ -public class PlainTextTagDisplayFormatter extends AbstractTagDisplayFormatter { - private static PlainTextTagDisplayFormatter formatter; - - StringBuffer sb = new StringBuffer(); - StringBuffer indent = new StringBuffer(); - - public PlainTextTagDisplayFormatter() { - - } - - public static AbstractTagDisplayFormatter getInstanceOf() { - if (formatter == null) { - formatter = new PlainTextTagDisplayFormatter(); - } - return formatter; - } - - public void openHeadingElement(String type, String value) { - addElement(type, value); - increaseLevel(); - } - - public void openHeadingElement(String type, boolean value) { - openHeadingElement(type, String.valueOf(value)); - } - - public void openHeadingElement(String type, int value) { - openHeadingElement(type, String.valueOf(value)); - } - - public void closeHeadingElement(String type) { - decreaseLevel(); - } - - public void increaseLevel() { - level++; - indent.append(" "); - } - - public void decreaseLevel() { - level--; - indent = new StringBuffer(indent.substring(0, indent.length() - 2)); - } - - public void addElement(String type, String value) { - sb.append(indent).append(type).append(":").append(value).append('\n'); - } - - public void addElement(String type, int value) { - addElement(type, String.valueOf(value)); - } - - public void addElement(String type, boolean value) { - addElement(type, String.valueOf(value)); - } - - public String toString() { - return sb.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/logging/XMLTagDisplayFormatter.java b/src/main/java/org/jaudiotagger/logging/XMLTagDisplayFormatter.java deleted file mode 100644 index 705743a..0000000 --- a/src/main/java/org/jaudiotagger/logging/XMLTagDisplayFormatter.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: XMLTagDisplayFormatter.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.logging; - -import java.text.CharacterIterator; -import java.text.StringCharacterIterator; - -/* - * For Formatting the metadata contents of a file in an XML format - * - * This could provide the basis of a representation of a files metadata, which can then be manipulated to -* to create technical reports. -*/ -public class XMLTagDisplayFormatter extends AbstractTagDisplayFormatter { - protected static final String xmlOpenStart = "<"; - protected static final String xmlOpenEnd = ">"; - protected static final String xmlCloseStart = ""; - protected static final String xmlSingleTagClose = " />"; - protected static final String xmlCDataTagOpen = ""; - private static XMLTagDisplayFormatter formatter; - StringBuffer sb = new StringBuffer(); - - public XMLTagDisplayFormatter() { - - } - - /** - * Return xml open tag round a string e.g - * - * @param xmlName - * @return - */ - public static String xmlOpen(String xmlName) { - return xmlOpenStart + xmlName + xmlOpenEnd; - } - - public static String xmlOpenHeading(String name, String data) { - return (xmlOpen(name + " id=\"" + data + "\"")); - } - - - /** - * Return CDATA tag around xml data e.g - * We also need to deal with special chars - * - * @param xmlData - * @return - */ - public static String xmlCData(String xmlData) { - char tempChar; - StringBuffer replacedString = new StringBuffer(); - for (int i = 0; i < xmlData.length(); i++) { - tempChar = xmlData.charAt(i); - if ((Character.isLetterOrDigit(tempChar)) || (Character.isSpaceChar(tempChar))) { - replacedString.append(tempChar); - } else { - replacedString.append("#x").append(Character.digit(tempChar, 16)); - } - } - return xmlCDataTagOpen + replacedString + xmlCDataTagClose; - } - - /** - * Return xml close tag around a string e.g - * - * @param xmlName - * @return - */ - public static String xmlClose(String xmlName) { - return xmlCloseStart + xmlName + xmlCloseEnd; - } - - public static String xmlSingleTag(String data) { - return xmlOpenStart + data + xmlSingleTagClose; - } - - public static String xmlFullTag(String xmlName, String data) { - return xmlOpen(xmlName) + xmlCData(data) + xmlClose(xmlName); - } - - /** - * Replace any special xml characters with the appropiate escape sequences - * required to be done for the actual element names - * - * @param xmlData - * @return - */ - public static String replaceXMLCharacters(String xmlData) { - StringBuffer sb = new StringBuffer(); - StringCharacterIterator sCI = new StringCharacterIterator(xmlData); - for (char c = sCI.first(); c != CharacterIterator.DONE; c = sCI.next()) { - switch (c) { - case '&': - sb.append("&"); - break; - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '"': - sb.append("""); - break; - case '\'': - sb.append("'"); - break; - - - default: - sb.append(c); - } - } - return sb.toString(); - } - - public void openHeadingElement(String type, String value) { - if (value.length() == 0) { - sb.append(xmlOpen(type)); - } else { - sb.append(xmlOpenHeading(type, replaceXMLCharacters(value))); - } - } - - public void openHeadingElement(String type, boolean value) { - openHeadingElement(type, String.valueOf(value)); - } - - public void openHeadingElement(String type, int value) { - openHeadingElement(type, String.valueOf(value)); - } - - public void closeHeadingElement(String type) { - sb.append(xmlClose(type)); - } - - public void addElement(String type, String value) { - sb.append(xmlFullTag(type, replaceXMLCharacters(value))); - } - - public void addElement(String type, int value) { - addElement(type, String.valueOf(value)); - } - - public void addElement(String type, boolean value) { - addElement(type, String.valueOf(value)); - } - - public String toString() { - return sb.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/logging/package.html b/src/main/java/org/jaudiotagger/logging/package.html deleted file mode 100644 index 781a86e..0000000 --- a/src/main/java/org/jaudiotagger/logging/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Error messages and log message formatting. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/package.html b/src/main/java/org/jaudiotagger/package.html deleted file mode 100644 index c2fe9a2..0000000 --- a/src/main/java/org/jaudiotagger/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Just a few constants are defined here. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/EmptyFrameException.java b/src/main/java/org/jaudiotagger/tag/EmptyFrameException.java deleted file mode 100644 index e76d1f5..0000000 --- a/src/main/java/org/jaudiotagger/tag/EmptyFrameException.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: EmptyFrameException.java 520 2008-01-01 15:16:38Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - -/** - * Thrown when find a Frame but it contains no data. - * - * @version $Revision: 520 $ - */ -public class EmptyFrameException extends InvalidFrameException { - /** - * Creates a new EmptyFrameException datatype. - */ - public EmptyFrameException() { - } - - /** - * Creates a new EmptyFrameException datatype. - * - * @param ex the cause. - */ - public EmptyFrameException(Throwable ex) { - super(ex); - } - - /** - * Creates a new EmptyFrameException datatype. - * - * @param msg the detail message. - */ - public EmptyFrameException(String msg) { - super(msg); - } - - /** - * Creates a new EmptyFrameException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public EmptyFrameException(String msg, Throwable ex) { - super(msg, ex); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/FieldDataInvalidException.java b/src/main/java/org/jaudiotagger/tag/FieldDataInvalidException.java deleted file mode 100644 index 3a4fd18..0000000 --- a/src/main/java/org/jaudiotagger/tag/FieldDataInvalidException.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.jaudiotagger.tag; - -/** - * Thrown if the try and create a field with invalid data - *

    - *

    For example if try and create an Mp4Field with type Byte using data that cannot be parsed as a number - * then this exception will be thrown - */ -public class FieldDataInvalidException extends TagException { - /** - * Creates a new KeyNotFoundException datatype. - */ - public FieldDataInvalidException() { - } - - /** - * Creates a new KeyNotFoundException datatype. - * - * @param ex the cause. - */ - public FieldDataInvalidException(Throwable ex) { - super(ex); - } - - /** - * Creates a new KeyNotFoundException datatype. - * - * @param msg the detail message. - */ - public FieldDataInvalidException(String msg) { - super(msg); - } - - /** - * Creates a new KeyNotFoundException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public FieldDataInvalidException(String msg, Throwable ex) { - super(msg, ex); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/FieldKey.java b/src/main/java/org/jaudiotagger/tag/FieldKey.java deleted file mode 100644 index cda7622..0000000 --- a/src/main/java/org/jaudiotagger/tag/FieldKey.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.jaudiotagger.tag; - -/** - * This is an enumeration of fields implemented by all major formats - *

    - *

    - *

    - * This enumeration is used by subclasses to map from the common key to their implementation key, the keys - * are grouped within EnumSets within Tag class. - */ -public enum FieldKey { - ACOUSTID_FINGERPRINT, - ACOUSTID_ID, - ALBUM, - ALBUM_ARTIST, - ALBUM_ARTIST_SORT, - ALBUM_SORT, - AMAZON_ID, - ARRANGER, - ARTIST, - ARTIST_SORT, - ARTISTS, - BARCODE, - BPM, - CATALOG_NO, - COMMENT, - COMPOSER, - COMPOSER_SORT, - CONDUCTOR, - COUNTRY, - COVER_ART, - CUSTOM1, - CUSTOM2, - CUSTOM3, - CUSTOM4, - CUSTOM5, - DISC_NO, - DISC_SUBTITLE, - DISC_TOTAL, - DJMIXER, - ENCODER, - ENGINEER, - FBPM, - GENRE, - GROUPING, - ISRC, - IS_COMPILATION, - KEY, - LANGUAGE, - LYRICIST, - LYRICS, - MEDIA, - MIXER, - MOOD, - MUSICBRAINZ_ARTISTID, - MUSICBRAINZ_DISC_ID, - MUSICBRAINZ_ORIGINAL_RELEASE_ID, - MUSICBRAINZ_RELEASEARTISTID, - MUSICBRAINZ_RELEASEID, - MUSICBRAINZ_RELEASE_COUNTRY, - MUSICBRAINZ_RELEASE_GROUP_ID, - MUSICBRAINZ_RELEASE_STATUS, - MUSICBRAINZ_RELEASE_TYPE, - MUSICBRAINZ_TRACK_ID, - MUSICBRAINZ_WORK_ID, - MUSICIP_ID, - OCCASION, - ORIGINAL_ALBUM, - ORIGINAL_ARTIST, - ORIGINAL_LYRICIST, - ORIGINAL_YEAR, - QUALITY, - PRODUCER, - RATING, - RECORD_LABEL, - REMIXER, - SCRIPT, - SUBTITLE, - TAGS, - TEMPO, - TITLE, - TITLE_SORT, - TRACK, - TRACK_TOTAL, - URL_DISCOGS_ARTIST_SITE, - URL_DISCOGS_RELEASE_SITE, - URL_LYRICS_SITE, - URL_OFFICIAL_ARTIST_SITE, - URL_OFFICIAL_RELEASE_SITE, - URL_WIKIPEDIA_ARTIST_SITE, - URL_WIKIPEDIA_RELEASE_SITE, - YEAR,; -} diff --git a/src/main/java/org/jaudiotagger/tag/InvalidDataTypeException.java b/src/main/java/org/jaudiotagger/tag/InvalidDataTypeException.java deleted file mode 100644 index c823085..0000000 --- a/src/main/java/org/jaudiotagger/tag/InvalidDataTypeException.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag; - -/** - * Indicates there was a problem parsing this datatype due to a problem with the data - * such as the array being empty when trying to read from a file. - * - * @version $Revision: 520 $ - */ -public class InvalidDataTypeException extends InvalidTagException { - /** - * Creates a new InvalidDataTypeException datatype. - */ - public InvalidDataTypeException() { - } - - /** - * Creates a new InvalidDataTypeException datatype. - * - * @param ex the cause. - */ - public InvalidDataTypeException(Throwable ex) { - super(ex); - } - - /** - * Creates a new InvalidDataTypeException datatype. - * - * @param msg the detail message. - */ - public InvalidDataTypeException(String msg) { - super(msg); - } - - /** - * Creates a new InvalidDataTypeException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public InvalidDataTypeException(String msg, Throwable ex) { - super(msg, ex); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/InvalidFrameException.java b/src/main/java/org/jaudiotagger/tag/InvalidFrameException.java deleted file mode 100644 index 6f5f029..0000000 --- a/src/main/java/org/jaudiotagger/tag/InvalidFrameException.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: InvalidFrameException.java 520 2008-01-01 15:16:38Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - -/** - * Thrown if frame cannot be read correctly. - * - * @author Eric Farng - * @version $Revision: 520 $ - */ -public class InvalidFrameException extends InvalidTagException { - /** - * Creates a new InvalidFrameException datatype. - */ - public InvalidFrameException() { - } - - /** - * Creates a new InvalidFrameException datatype. - * - * @param ex the cause. - */ - public InvalidFrameException(Throwable ex) { - super(ex); - } - - /** - * Creates a new InvalidFrameException datatype. - * - * @param msg the detail message. - */ - public InvalidFrameException(String msg) { - super(msg); - } - - /** - * Creates a new InvalidFrameException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public InvalidFrameException(String msg, Throwable ex) { - super(msg, ex); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/InvalidFrameIdentifierException.java b/src/main/java/org/jaudiotagger/tag/InvalidFrameIdentifierException.java deleted file mode 100644 index 4bca29e..0000000 --- a/src/main/java/org/jaudiotagger/tag/InvalidFrameIdentifierException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: InvalidFrameIdentifierException.java 520 2008-01-01 15:16:38Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - -/** - * Thrown if a frame identifier isn't valid. - * - * @author Eric Farng - * @version $Revision: 520 $ - */ -public class InvalidFrameIdentifierException extends InvalidFrameException { - /** - * Creates a new InvalidFrameIdentifierException datatype. - */ - public InvalidFrameIdentifierException() { - } - - /** - * Creates a new InvalidFrameIdentifierException datatype. - * - * @param ex the cause. - */ - public InvalidFrameIdentifierException(Throwable ex) { - super(ex); - } - - /** - * Creates a new InvalidFrameIdentifierException datatype. - * - * @param msg the detail message. - */ - public InvalidFrameIdentifierException(String msg) { - super(msg); - } - - /** - * Creates a new InvalidFrameIdentifierException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public InvalidFrameIdentifierException(String msg, Throwable ex) { - super(msg, ex); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/InvalidTagException.java b/src/main/java/org/jaudiotagger/tag/InvalidTagException.java deleted file mode 100644 index f392fe7..0000000 --- a/src/main/java/org/jaudiotagger/tag/InvalidTagException.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: InvalidTagException.java 520 2008-01-01 15:16:38Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - -/** - * An InvalidTagException is thrown if a parse error occurs while - * a tag is being read from a file. This is different from a - * TagNotFoundException. Each tag (or MP3 Frame Header) has an ID - * string or some way saying that it simply exists. If this string is missing, - * TagNotFoundException is thrown. If the ID string exists, then - * any other error while reading throws an InvalidTagException. - * - * @version $Revision: 520 $ - */ -public class InvalidTagException extends TagException { - /** - * Creates a new InvalidTagException datatype. - */ - public InvalidTagException() { - } - - /** - * Creates a new InvalidTagException datatype. - * - * @param ex the cause. - */ - public InvalidTagException(Throwable ex) { - super(ex); - } - - /** - * Creates a new InvalidTagException datatype. - * - * @param msg the detail message. - */ - public InvalidTagException(String msg) { - super(msg); - } - - /** - * Creates a new InvalidTagException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public InvalidTagException(String msg, Throwable ex) { - super(msg, ex); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/KeyNotFoundException.java b/src/main/java/org/jaudiotagger/tag/KeyNotFoundException.java deleted file mode 100644 index 7c6336f..0000000 --- a/src/main/java/org/jaudiotagger/tag/KeyNotFoundException.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jaudiotagger.tag; - -/** - * Thrown if the key cannot be found - *

    - *

    Should not happen with well written code, hence RuntimeException. - */ -public class KeyNotFoundException extends RuntimeException { - /** - * Creates a new KeyNotFoundException datatype. - */ - public KeyNotFoundException() { - } - - /** - * Creates a new KeyNotFoundException datatype. - * - * @param ex the cause. - */ - public KeyNotFoundException(Throwable ex) { - super(ex); - } - - /** - * Creates a new KeyNotFoundException datatype. - * - * @param msg the detail message. - */ - public KeyNotFoundException(String msg) { - super(msg); - } - - /** - * Creates a new KeyNotFoundException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public KeyNotFoundException(String msg, Throwable ex) { - super(msg, ex); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/PaddingException.java b/src/main/java/org/jaudiotagger/tag/PaddingException.java deleted file mode 100644 index ff1c003..0000000 --- a/src/main/java/org/jaudiotagger/tag/PaddingException.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: PaddingException.java 917 2010-09-27 18:34:30Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - - -public class PaddingException extends InvalidFrameIdentifierException { - /** - * Creates a new PaddingException datatype. - */ - public PaddingException() { - } - - /** - * Creates a new PaddingException datatype. - * - * @param ex the cause. - */ - public PaddingException(Throwable ex) { - super(ex); - } - - /** - * Creates a new PaddingException datatype. - * - * @param msg the detail message. - */ - public PaddingException(String msg) { - super(msg); - } - - /** - * Creates a new PaddingException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public PaddingException(String msg, Throwable ex) { - super(msg, ex); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/Tag.java b/src/main/java/org/jaudiotagger/tag/Tag.java deleted file mode 100644 index 10f61fd..0000000 --- a/src/main/java/org/jaudiotagger/tag/Tag.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2010 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag; - -import org.jaudiotagger.tag.images.Artwork; - -import java.util.Iterator; -import java.util.List; - -/** - * This interface represents the basic data structure for the default - * audio library functionality.
    - *

    - * Some audio file tagging systems allow to specify multiple values for one type - * of information. The artist for example. Some songs may be a cooperation of - * two or more artists. Sometimes a tagging user wants to specify them in the - * tag without making one long text string.
    - *

    - * The addField() method can be used for this but it is possible the underlying implementation - * does not support that kind of storing multiple values and will just overwrite the existing value
    - *
    - * Code Examples:
    - *

    - *

    - * 
    - * AudioFile file = AudioFileIO.read(new File("C:\\test.mp3"));
    - * 

    - * Tag tag = file.getTag(); - * - *

    - * - * @author Raphael Slinckx - * @author Paul Taylor - */ -public interface Tag { - /** - * Create the field based on the generic key and set it in the tag - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException; - - /** - * Create the field based on the generic key and add it to the tag - *

    - * This is handled differently by different formats - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException; - - /** - * Delete any fields with this key - * - * @param fieldKey - * @throws KeyNotFoundException - */ - void deleteField(FieldKey fieldKey) throws KeyNotFoundException; - - /** - * Delete any fields with this Flac (Vorbis Comment) id - * - * @param key - * @throws KeyNotFoundException - */ - void deleteField(String key) throws KeyNotFoundException; - - /** - * Returns a {@linkplain List list} of {@link TagField} objects whose "{@linkplain TagField#getId() id}" - * is the specified one.
    - *

    - *

    Can be used to retrieve fields with any identifier, useful if the identifier is not within {@link FieldKey} - * - * @param id The field id. - * @return A list of {@link TagField} objects with the given "id". - */ - List getFields(String id); - - /** - * Returns a {@linkplain List list} of {@link TagField} objects whose "{@linkplain TagField#getId() id}" - * is the specified one.
    - * - * @param id The field id. - * @return A list of {@link TagField} objects with the given "id". - * @throws KeyNotFoundException - */ - List getFields(FieldKey id) throws KeyNotFoundException; - - - /** - * Iterator over all the fields within the tag, handle multiple fields with the same id - * - * @return iterator over whole list - */ - Iterator getFields(); - - - /** - * Retrieve String value of the first value that exists for this format specific key - *

    - *

    Can be used to retrieve fields with any identifier, useful if the identifier is not within {@link FieldKey} - * - * @param id - * @return - */ - String getFirst(String id); - - /** - * Retrieve String value of the first tag field that exists for this generic key - * - * @param id - * @return String value or empty string - * @throws KeyNotFoundException - */ - String getFirst(FieldKey id) throws KeyNotFoundException; - - /** - * Retrieve all String values that exist for this generic key - * - * @param id - * @return - * @throws KeyNotFoundException - */ - List getAll(FieldKey id) throws KeyNotFoundException; - - /** - * Retrieve String value of the nth tag field that exists for this generic key - * - * @param id - * @param n - * @return - */ - String getValue(FieldKey id, int n); - - /** - * Retrieve the first field that exists for this format specific key - *

    - *

    Can be used to retrieve fields with any identifier, useful if the identifier is not within {@link FieldKey} - * - * @param id audio specific key - * @return tag field or null if doesn't exist - */ - TagField getFirstField(String id); - - /** - * @param id - * @return the first field that matches this generic key - */ - TagField getFirstField(FieldKey id); - - - /** - * Returns true, if at least one of the contained - * {@linkplain TagField fields} is a common field ({@link TagField#isCommon()}). - * - * @return true if a {@linkplain TagField#isCommon() common} - * field is present. - */ - boolean hasCommonFields(); - - /** - * Determines whether the tag has at least one field with the specified field key. - * - * @param fieldKey - * @return - */ - boolean hasField(FieldKey fieldKey); - - /** - * Determines whether the tag has at least one field with the specified - * "id". - * - * @param id The field id to look for. - * @return true if tag contains a {@link TagField} with the - * given {@linkplain TagField#getId() id}. - */ - boolean hasField(String id); - - /** - * Determines whether the tag has no fields specified.
    - * - * @return true if tag contains no field. - */ - boolean isEmpty(); - - - //TODO, do we need this - String toString(); - - - /** - * Return the number of fields - *

    - *

    Fields with the same identifiers are counted separately - *

    - * i.e two TITLE fields in a Vorbis Comment file would count as two - * - * @return total number of fields - */ - int getFieldCount(); - - - /** - * Return the number of fields taking multiple value fields into consideration - *

    - * Fields that actually contain multiple values are counted seperately - *

    - * i.e. a TCON frame in ID3v24 frame containing multiple genres would add to count for each genre. - * - * @return total number of fields taking multiple value fields into consideration - */ - int getFieldCountIncludingSubValues(); - - - //TODO is this a special field? - boolean setEncoding(String enc) throws FieldDataInvalidException; - - - /** - * @return a list of all artwork in this file using the format independent Artwork class - */ - List getArtworkList(); - - /** - * @return first artwork or null if none exist - */ - Artwork getFirstArtwork(); - - /** - * Delete any instance of tag fields used to store artwork - *

    - *

    We need this additional deleteField method because in some formats artwork can be stored - * in multiple fields - * - * @throws KeyNotFoundException - */ - void deleteArtworkField() throws KeyNotFoundException; - - - /** - * Create artwork field based on the data in artwork - * - * @param artwork - * @return suitable tagfield for this format that represents the artwork data - * @throws FieldDataInvalidException - */ - TagField createField(Artwork artwork) throws FieldDataInvalidException; - - /** - * Create artwork field based on the data in artwork and then set it in the tag itself - *

    - * - * @param artwork - * @throws FieldDataInvalidException - */ - void setField(Artwork artwork) throws FieldDataInvalidException; - - /** - * Create artwork field based on the data in artwork and then add it to the tag itself - *

    - * - * @param artwork - * @throws FieldDataInvalidException - */ - void addField(Artwork artwork) throws FieldDataInvalidException; - - /** - * Sets a field in the structure, used internally by the library
    - *

    - * - * @param field The field to add. - * @throws FieldDataInvalidException - */ - void setField(TagField field) throws FieldDataInvalidException; - - /** - * Adds a field to the structure, used internally by the library
    - *

    - * - * @param field The field to add. - * @throws FieldDataInvalidException - */ - void addField(TagField field) throws FieldDataInvalidException; - - /** - * Create a new field based on generic key, used internally by the library - *

    - *

    Only textual data supported at the moment. The genericKey will be mapped - * to the correct implementation key and return a TagField. - *

    - * - * @param genericKey is the generic key - * @param value to store - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException; - - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/TagException.java b/src/main/java/org/jaudiotagger/tag/TagException.java deleted file mode 100644 index eb7fc76..0000000 --- a/src/main/java/org/jaudiotagger/tag/TagException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: TagException.java 520 2008-01-01 15:16:38Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - -/** - * This is the exception that is always generated by any class in these - * packages. - * - * @author Eric Farng - * @version $Revision: 520 $ - */ -public class TagException extends Exception { - /** - * Creates a new TagException datatype. - */ - public TagException() { - } - - /** - * Creates a new TagException datatype. - * - * @param ex the cause. - */ - public TagException(Throwable ex) { - super(ex); - } - - /** - * Creates a new TagException datatype. - * - * @param msg the detail message. - */ - public TagException(String msg) { - super(msg); - } - - /** - * Creates a new TagException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public TagException(String msg, Throwable ex) { - super(msg, ex); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/TagField.java b/src/main/java/org/jaudiotagger/tag/TagField.java deleted file mode 100644 index efabfff..0000000 --- a/src/main/java/org/jaudiotagger/tag/TagField.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag; - -import java.io.UnsupportedEncodingException; - -/** - * Implementing classes represent a tag field for the entagged audio library.
    - * Very basic functionality is defined for use with - * {@link org.jaudiotagger.tag.Tag}. - * - * @author Rapha�l Slinckx - */ -public interface TagField { - - /** - * This method copies the data of the given field to the current data.
    - * - * @param field The field containing the data to be taken. - */ - void copyContent(TagField field); - - /** - * Returns the Id of the represented tag field.
    - * This value should uniquely identify a kind of tag data, like title. - * {@link org.jaudiotagger.audio.generic.AbstractTag} will use the "id" to summarize multiple - * fields. - * - * @return Unique identifier for the fields type. (title, artist...) - */ - String getId(); - - /** - * This method delivers the binary representation of the fields data in - * order to be directly written to the file.
    - * - * @return Binary data representing the current tag field.
    - * @throws UnsupportedEncodingException Most tag data represents text. In some cases the underlying - * implementation will need to convert the text data in java to - * a specific charset encoding. In these cases an - * {@link UnsupportedEncodingException} may occur. - */ - byte[] getRawContent() throws UnsupportedEncodingException; - - /** - * Determines whether the represented field contains (is made up of) binary - * data, instead of text data.
    - * Software can identify fields to be displayed because they are human - * readable if this method returns false. - * - * @return true if field represents binary data (not human - * readable). - */ - boolean isBinary(); - - /** - * This method will set the field to represent binary data.
    - *

    - * Some implementations may support conversions.
    - * As of now (Octobre 2005) there is no implementation really using this - * method to perform useful operations. - * - * @param b true, if the field contains binary data. - * //@deprecated As for now is of no use. Implementations should use another - * // way of setting this property. - */ - void isBinary(boolean b); - - /** - * Identifies a field to be of common use.
    - *

    - * Some software may differ between common and not common fields. A common - * one is for sure the title field. A web link may not be of common use for - * tagging. However some file formats, or future development of users - * expectations will make more fields common than now can be known. - * - * @return true if the field is of common use. - */ - boolean isCommon(); - - /** - * Determines whether the content of the field is empty.
    - * - * @return true if no data is stored (or empty String). - */ - boolean isEmpty(); - - /** - * This method returns a human readable description of the fields contents.
    - * For text fields it should be the text itself. Other fields containing - * images may return a formatted string with image properties like width, - * height and so on. - * - * @return Description of the fields content. - */ - String toString(); -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/TagNotFoundException.java b/src/main/java/org/jaudiotagger/tag/TagNotFoundException.java deleted file mode 100644 index a66ab33..0000000 --- a/src/main/java/org/jaudiotagger/tag/TagNotFoundException.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id: TagNotFoundException.java 520 2008-01-01 15:16:38Z paultaylor $ - * - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.jaudiotagger.tag; - -/** - * Thrown if the tag o isn't found. This is different from - * the InvalidTagException. Each tag has an - * ID string or some way saying that it simply exists. If this string is - * missing, TagNotFoundException is thrown. If the ID string - * exists, then any other error while reading throws an - * InvalidTagException. - * - * @author Eric Farng - * @version $Revision: 520 $ - */ -public class TagNotFoundException extends TagException { - /** - * Creates a new TagNotFoundException datatype. - */ - public TagNotFoundException() { - } - - /** - * Creates a new TagNotFoundException datatype. - * - * @param ex the cause. - */ - public TagNotFoundException(Throwable ex) { - super(ex); - } - - /** - * Creates a new TagNotFoundException datatype. - * - * @param msg the detail message. - */ - public TagNotFoundException(String msg) { - super(msg); - } - - /** - * Creates a new TagNotFoundException datatype. - * - * @param msg the detail message. - * @param ex the cause. - */ - public TagNotFoundException(String msg, Throwable ex) { - super(msg, ex); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/TagOptionSingleton.java b/src/main/java/org/jaudiotagger/tag/TagOptionSingleton.java deleted file mode 100644 index 205b1ad..0000000 --- a/src/main/java/org/jaudiotagger/tag/TagOptionSingleton.java +++ /dev/null @@ -1,1093 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: TagOptionSingleton.java 1055 2012-06-07 16:52:29Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Options that are used for every datatype and class in this library. - */ -package org.jaudiotagger.tag; - -import org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import org.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import org.jaudiotagger.tag.id3.framebody.FrameBodyTIPL; -import org.jaudiotagger.tag.id3.framebody.ID3v24FrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.lyrics3.Lyrics3v2Fields; -import org.jaudiotagger.tag.options.PadNumberOption; -import org.jaudiotagger.tag.reference.GenreTypes; -import org.jaudiotagger.tag.reference.ID3V2Version; -import org.jaudiotagger.tag.reference.Languages; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; - -public class TagOptionSingleton { - /** - * - */ - private static HashMap tagOptionTable = new HashMap(); - - /** - * - */ - private static String DEFAULT = "default"; - - /** - * - */ - private static String defaultOptions = DEFAULT; - - /** - * - */ - private HashMap, LinkedList> keywordMap = new HashMap, LinkedList>(); - - /** - * Map of lyric ID's to Boolean objects if we should or should not save the - * specific lyrics3 field. Defaults to true. - */ - private HashMap lyrics3SaveFieldMap = new HashMap(); - - /** - * parenthesis map stuff - */ - private HashMap parenthesisMap = new HashMap(); - - /** - * HashMap listing words to be replaced if found - */ - private HashMap replaceWordMap = new HashMap(); - - - /** - * default language for any ID3v2 tags frames which require it. This string - * is in the [ISO-639-2] ISO/FDIS 639-2 definition - */ - private String language = "eng"; - - - /** - * - */ - private boolean filenameTagSave = false; - - /** - * if we should save any fields of the ID3v1 tag or not. Defaults to true. - */ - private boolean id3v1Save = true; - - /** - * if we should save the album field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveAlbum = true; - - /** - * if we should save the artist field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveArtist = true; - - /** - * if we should save the comment field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveComment = true; - - /** - * if we should save the genre field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveGenre = true; - - /** - * if we should save the title field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveTitle = true; - - /** - * if we should save the track field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveTrack = true; - - /** - * if we should save the year field of the ID3v1 tag or not. Defaults to - * true. - */ - private boolean id3v1SaveYear = true; - - - /** - * When adjusting the ID3v2 padding, if should we copy the current ID3v2 - * tag to the new MP3 file. Defaults to true. - */ - private boolean id3v2PaddingCopyTag = true; - - /** - * When adjusting the ID3v2 padding, if we should shorten the length of the - * ID3v2 tag padding. Defaults to false. - */ - private boolean id3v2PaddingWillShorten = false; - - /** - * if we should save any fields of the ID3v2 tag or not. Defaults to true. - */ - private boolean id3v2Save = true; - - - /** - * if we should keep an empty Lyrics3 field while we're reading. This is - * different from a string of white space. Defaults to false. - */ - private boolean lyrics3KeepEmptyFieldIfRead = false; - - /** - * if we should save any fields of the Lyrics3 tag or not. Defaults to - * true. - */ - private boolean lyrics3Save = true; - - /** - * if we should save empty Lyrics3 field or not. Defaults to false. - *

    - * todo I don't think this is implemented yet. - */ - private boolean lyrics3SaveEmptyField = false; - - /** - * - */ - private boolean originalSavedAfterAdjustingID3v2Padding = true; - - - /** - * default time stamp format for any ID3v2 tag frames which require it. - */ - private byte timeStampFormat = 2; - - /** - * number of frames to sync when trying to find the start of the MP3 frame - * data. The start of the MP3 frame data is the start of the music and is - * different from the ID3v2 frame data. - */ - private int numberMP3SyncFrame = 3; - - /** - * Unsynchronize tags/frames this is rarely required these days and can cause more - * problems than it solves - */ - private boolean unsyncTags = false; - - /** - * iTunes needlessly writes null terminators at the end for TextEncodedStringSizeTerminated values, - * if this option is enabled these characters are removed - */ - private boolean removeTrailingTerminatorOnWrite = true; - - /** - * This is the default text encoding to use for new v23 frames, when unicode is required - * UTF16 will always be used because that is the only valid option for v23. - */ - private byte id3v23DefaultTextEncoding = TextEncoding.ISO_8859_1; - - /** - * This is the default text encoding to use for new v24 frames, it defaults to simple ISO8859 - * but by changing this value you could always used UTF8 for example whether you needed to or not - */ - private byte id3v24DefaultTextEncoding = TextEncoding.ISO_8859_1; - - /** - * This is text encoding to use for new v24 frames when unicode is required, it defaults to UTF16 just - * because this encoding is understand by all ID3 versions - */ - private byte id3v24UnicodeTextEncoding = TextEncoding.UTF_16; - - - /** - * When writing frames if this is set to true then the frame will be written - * using the defaults disregarding the text encoding originally used to create - * the frame. - */ - private boolean resetTextEncodingForExistingFrames = false; - - /** - * Some formats impose maxmimum lengths for fields , if the text provided is longer - * than the formats allows it will truncate and write a warning, if this is not set - * it will throw an exception - */ - private boolean truncateTextWithoutErrors = false; - - /** - * Frames such as TRCK and TPOS sometimes pad single digit numbers to aid sorting - *

    - * Currently only applies to ID3 files - */ - private boolean padNumbers = false; - - /** - * Number of padding zeroes digits 1- 9, numbers larger than nine will be padded accordingly based on the value. - * Only has any effect if padNumbers is set to true - *

    - * Currently only applies to ID3 files - */ - private PadNumberOption padNumberTotalLength = PadNumberOption.PAD_ONE_ZERO; - - /** - * There are a couple of problems with the Java implementation on Google Android, enabling this value - * switches on Google workarounds - */ - private boolean isAndroid = false; - - /** - * When you specify a field should be stored as UTF16 in ID3 this means write with BOM indicating whether - * written as Little Endian or Big Endian, its defaults to little Endian - */ - private boolean isEncodeUTF16BomAsLittleEndian = true; - - /** - * When this is set and using the generic interface jaudiotagger will make some adjustments - * when saving field so they work best with the specified Tagger - */ - //TODO Not Actually Used yet, originally intended for dealing with ratings and genres - private int playerCompatability = -1; - - /** - * max size of data to copy when copying audiodata from one file to another - */ - private long writeChunkSize = 5000000; - - private boolean isWriteMp4GenresAsText = false; - - private ID3V2Version id3v2Version = ID3V2Version.ID3_V23; - - /** - * Creates a new TagOptions datatype. All Options are set to their default - * values - */ - private TagOptionSingleton() { - setToDefault(); - } - - - /** - * @return - */ - public static TagOptionSingleton getInstance() { - return getInstance(defaultOptions); - } - - /** - * @param instanceKey - * @return - */ - public static TagOptionSingleton getInstance(String instanceKey) { - TagOptionSingleton tagOptions = tagOptionTable.get(instanceKey); - - if (tagOptions == null) { - tagOptions = new TagOptionSingleton(); - tagOptionTable.put(instanceKey, tagOptions); - } - - return tagOptions; - } - - /** - * @return - */ - public static String getInstanceKey() { - return defaultOptions; - } - - /** - * @param instanceKey - */ - public void setInstanceKey(String instanceKey) { - TagOptionSingleton.defaultOptions = instanceKey; - } - - /** - * @return - */ - public boolean isFilenameTagSave() { - return filenameTagSave; - } - - /** - * @param filenameTagSave - */ - public void setFilenameTagSave(boolean filenameTagSave) { - this.filenameTagSave = filenameTagSave; - } - - /** - * @return - */ - public ID3V2Version getID3V2Version() { - return id3v2Version; - } - - /** - * @param id3v2Version - */ - public void setID3V2Version(ID3V2Version id3v2Version) { - this.id3v2Version = id3v2Version; - } - - /** - * @return - */ - public boolean isId3v1Save() { - return id3v1Save; - } - - /** - * @param id3v1Save - */ - public void setId3v1Save(boolean id3v1Save) { - this.id3v1Save = id3v1Save; - } - - /** - * @return - */ - public boolean isId3v1SaveAlbum() { - return id3v1SaveAlbum; - } - - /** - * @param id3v1SaveAlbum - */ - public void setId3v1SaveAlbum(boolean id3v1SaveAlbum) { - this.id3v1SaveAlbum = id3v1SaveAlbum; - } - - /** - * @return - */ - public boolean isId3v1SaveArtist() { - return id3v1SaveArtist; - } - - /** - * @param id3v1SaveArtist - */ - public void setId3v1SaveArtist(boolean id3v1SaveArtist) { - this.id3v1SaveArtist = id3v1SaveArtist; - } - - /** - * @return - */ - public boolean isId3v1SaveComment() { - return id3v1SaveComment; - } - - /** - * @param id3v1SaveComment - */ - public void setId3v1SaveComment(boolean id3v1SaveComment) { - this.id3v1SaveComment = id3v1SaveComment; - } - - /** - * @return - */ - public boolean isId3v1SaveGenre() { - return id3v1SaveGenre; - } - - /** - * @param id3v1SaveGenre - */ - public void setId3v1SaveGenre(boolean id3v1SaveGenre) { - this.id3v1SaveGenre = id3v1SaveGenre; - } - - /** - * @return - */ - public boolean isId3v1SaveTitle() { - return id3v1SaveTitle; - } - - /** - * @param id3v1SaveTitle - */ - public void setId3v1SaveTitle(boolean id3v1SaveTitle) { - this.id3v1SaveTitle = id3v1SaveTitle; - } - - /** - * @return - */ - public boolean isId3v1SaveTrack() { - return id3v1SaveTrack; - } - - /** - * @param id3v1SaveTrack - */ - public void setId3v1SaveTrack(boolean id3v1SaveTrack) { - this.id3v1SaveTrack = id3v1SaveTrack; - } - - /** - * @return - */ - public boolean isId3v1SaveYear() { - return id3v1SaveYear; - } - - /** - * @param id3v1SaveYear - */ - public void setId3v1SaveYear(boolean id3v1SaveYear) { - this.id3v1SaveYear = id3v1SaveYear; - } - - /** - * @return - */ - public boolean isId3v2PaddingCopyTag() { - return id3v2PaddingCopyTag; - } - - /** - * @param id3v2PaddingCopyTag - */ - public void setId3v2PaddingCopyTag(boolean id3v2PaddingCopyTag) { - this.id3v2PaddingCopyTag = id3v2PaddingCopyTag; - } - - /** - * @return - */ - public boolean isId3v2PaddingWillShorten() { - return id3v2PaddingWillShorten; - } - - /** - * @param id3v2PaddingWillShorten - */ - public void setId3v2PaddingWillShorten(boolean id3v2PaddingWillShorten) { - this.id3v2PaddingWillShorten = id3v2PaddingWillShorten; - } - - /** - * @return - */ - public boolean isId3v2Save() { - return id3v2Save; - } - - /** - * @param id3v2Save - */ - public void setId3v2Save(boolean id3v2Save) { - this.id3v2Save = id3v2Save; - } - - /** - * @return - */ - public Iterator> getKeywordIterator() { - return keywordMap.keySet().iterator(); - } - - /** - * @param id3v2_4FrameBody - * @return - */ - public Iterator getKeywordListIterator(Class id3v2_4FrameBody) { - return keywordMap.get(id3v2_4FrameBody).iterator(); - } - - /** - * Returns the default language for any ID3v2 tag frames which require it. - * - * @return language ID, [ISO-639-2] ISO/FDIS 639-2 definition - */ - public String getLanguage() { - return language; - } - - /** - * Sets the default language for any ID3v2 tag frames which require it. - * While the value will already exist when reading from a file, this value - * will be used when a new ID3v2 Frame is created from scratch. - * - * @param lang language ID, [ISO-639-2] ISO/FDIS 639-2 definition - */ - public void setLanguage(String lang) { - if (Languages.getInstanceOf().getIdToValueMap().containsKey(lang)) { - language = lang; - } - } - - /** - * @return - */ - public boolean isLyrics3KeepEmptyFieldIfRead() { - return lyrics3KeepEmptyFieldIfRead; - } - - /** - * @param lyrics3KeepEmptyFieldIfRead - */ - public void setLyrics3KeepEmptyFieldIfRead(boolean lyrics3KeepEmptyFieldIfRead) { - this.lyrics3KeepEmptyFieldIfRead = lyrics3KeepEmptyFieldIfRead; - } - - /** - * @return - */ - public boolean isLyrics3Save() { - return lyrics3Save; - } - - /** - * @param lyrics3Save - */ - public void setLyrics3Save(boolean lyrics3Save) { - this.lyrics3Save = lyrics3Save; - } - - /** - * @return - */ - public boolean isLyrics3SaveEmptyField() { - return lyrics3SaveEmptyField; - } - - /** - * @param lyrics3SaveEmptyField - */ - public void setLyrics3SaveEmptyField(boolean lyrics3SaveEmptyField) { - this.lyrics3SaveEmptyField = lyrics3SaveEmptyField; - } - - /** - * Sets if we should save the Lyrics3 field. Defaults to true. - * - * @param id Lyrics3 id string - * @param save true if you want to save this specific Lyrics3 field. - */ - public void setLyrics3SaveField(String id, boolean save) { - this.lyrics3SaveFieldMap.put(id, save); - } - - /** - * Returns true if we should save the Lyrics3 field asked for in the - * argument. Defaults to true. - * - * @param id Lyrics3 id string - * @return true if we should save the Lyrics3 field. - */ - public boolean getLyrics3SaveField(String id) { - return lyrics3SaveFieldMap.get(id); - } - - /** - * @return - */ - public HashMap getLyrics3SaveFieldMap() { - return lyrics3SaveFieldMap; - } - - /** - * @param oldWord - * @return - */ - public String getNewReplaceWord(String oldWord) { - return replaceWordMap.get(oldWord); - } - - /** - * Returns the number of MP3 frames to sync when trying to find the start - * of the MP3 frame data. The start of the MP3 frame data is the start of - * the music and is different from the ID3v2 frame data. WinAmp 2.8 seems - * to sync 3 frames. Default is 5. - * - * @return number of MP3 frames to sync - */ - public int getNumberMP3SyncFrame() { - return numberMP3SyncFrame; - } - - /** - * Sets the number of MP3 frames to sync when trying to find the start of - * the MP3 frame data. The start of the MP3 frame data is the start of the - * music and is different from the ID3v2 frame data. WinAmp 2.8 seems to - * sync 3 frames. Default is 5. - * - * @param numberMP3SyncFrame number of MP3 frames to sync - */ - public void setNumberMP3SyncFrame(int numberMP3SyncFrame) { - this.numberMP3SyncFrame = numberMP3SyncFrame; - } - - /** - * @return - */ - public Iterator getOldReplaceWordIterator() { - return replaceWordMap.keySet().iterator(); - } - - /** - * @param open - * @return - */ - public boolean isOpenParenthesis(String open) { - return parenthesisMap.containsKey(open); - } - - /** - * @return - */ - public Iterator getOpenParenthesisIterator() { - return parenthesisMap.keySet().iterator(); - } - - /** - * @return - */ - public boolean isOriginalSavedAfterAdjustingID3v2Padding() { - return originalSavedAfterAdjustingID3v2Padding; - } - - /** - * @param originalSavedAfterAdjustingID3v2Padding - */ - public void setOriginalSavedAfterAdjustingID3v2Padding(boolean originalSavedAfterAdjustingID3v2Padding) { - this.originalSavedAfterAdjustingID3v2Padding = originalSavedAfterAdjustingID3v2Padding; - } - - /** - * Returns the default time stamp format for ID3v2 tags which require it. - *

    - *

    - * $01 Absolute time, 32 bit sized, using MPEG frames as unit
    - * $02 Absolute time, 32 bit sized, using milliseconds as unit
    - *

    - * - * @return the default time stamp format - */ - public byte getTimeStampFormat() { - return timeStampFormat; - } - - /** - * Sets the default time stamp format for ID3v2 tags which require it. - * While the value will already exist when reading from a file, this value - * will be used when a new ID3v2 Frame is created from scratch. - *

    - *

    - * $01 Absolute time, 32 bit sized, using MPEG frames as unit
    - * $02 Absolute time, 32 bit sized, using milliseconds as unit
    - *

    - * - * @param tsf the new default time stamp format - */ - public void setTimeStampFormat(byte tsf) { - if ((tsf == 1) || (tsf == 2)) { - timeStampFormat = tsf; - } - } - - /** - * - */ - public void setToDefault() { - keywordMap = new HashMap, LinkedList>(); - filenameTagSave = false; - id3v1Save = true; - id3v1SaveAlbum = true; - id3v1SaveArtist = true; - id3v1SaveComment = true; - id3v1SaveGenre = true; - id3v1SaveTitle = true; - id3v1SaveTrack = true; - id3v1SaveYear = true; - id3v2PaddingCopyTag = true; - id3v2PaddingWillShorten = false; - id3v2Save = true; - language = "eng"; - lyrics3KeepEmptyFieldIfRead = false; - lyrics3Save = true; - lyrics3SaveEmptyField = false; - lyrics3SaveFieldMap = new HashMap(); - numberMP3SyncFrame = 3; - parenthesisMap = new HashMap(); - replaceWordMap = new HashMap(); - timeStampFormat = 2; - unsyncTags = false; - removeTrailingTerminatorOnWrite = true; - id3v23DefaultTextEncoding = TextEncoding.ISO_8859_1; - id3v24DefaultTextEncoding = TextEncoding.ISO_8859_1; - id3v24UnicodeTextEncoding = TextEncoding.UTF_16; - resetTextEncodingForExistingFrames = false; - truncateTextWithoutErrors = false; - padNumbers = false; - isAndroid = false; - isEncodeUTF16BomAsLittleEndian = true; - writeChunkSize = 5000000; - isWriteMp4GenresAsText = false; - padNumberTotalLength = PadNumberOption.PAD_ONE_ZERO; - id3v2Version = ID3V2Version.ID3_V23; - //default all lyrics3 fields to save. id3v1 fields are individual - // settings. id3v2 fields are always looked at to save. - Iterator iterator = Lyrics3v2Fields.getInstanceOf().getIdToValueMap().keySet().iterator(); - String fieldId; - - while (iterator.hasNext()) { - fieldId = iterator.next(); - lyrics3SaveFieldMap.put(fieldId, true); - } - - try { - addKeyword(FrameBodyCOMM.class, "ultimix"); - addKeyword(FrameBodyCOMM.class, "dance"); - addKeyword(FrameBodyCOMM.class, "mix"); - addKeyword(FrameBodyCOMM.class, "remix"); - addKeyword(FrameBodyCOMM.class, "rmx"); - addKeyword(FrameBodyCOMM.class, "live"); - addKeyword(FrameBodyCOMM.class, "cover"); - addKeyword(FrameBodyCOMM.class, "soundtrack"); - addKeyword(FrameBodyCOMM.class, "version"); - addKeyword(FrameBodyCOMM.class, "acoustic"); - addKeyword(FrameBodyCOMM.class, "original"); - addKeyword(FrameBodyCOMM.class, "cd"); - addKeyword(FrameBodyCOMM.class, "extended"); - addKeyword(FrameBodyCOMM.class, "vocal"); - addKeyword(FrameBodyCOMM.class, "unplugged"); - addKeyword(FrameBodyCOMM.class, "acapella"); - addKeyword(FrameBodyCOMM.class, "edit"); - addKeyword(FrameBodyCOMM.class, "radio"); - addKeyword(FrameBodyCOMM.class, "original"); - addKeyword(FrameBodyCOMM.class, "album"); - addKeyword(FrameBodyCOMM.class, "studio"); - addKeyword(FrameBodyCOMM.class, "instrumental"); - addKeyword(FrameBodyCOMM.class, "unedited"); - addKeyword(FrameBodyCOMM.class, "karoke"); - addKeyword(FrameBodyCOMM.class, "quality"); - addKeyword(FrameBodyCOMM.class, "uncensored"); - addKeyword(FrameBodyCOMM.class, "clean"); - addKeyword(FrameBodyCOMM.class, "dirty"); - - addKeyword(FrameBodyTIPL.class, "f."); - addKeyword(FrameBodyTIPL.class, "feat"); - addKeyword(FrameBodyTIPL.class, "feat."); - addKeyword(FrameBodyTIPL.class, "featuring"); - addKeyword(FrameBodyTIPL.class, "ftng"); - addKeyword(FrameBodyTIPL.class, "ftng."); - addKeyword(FrameBodyTIPL.class, "ft."); - addKeyword(FrameBodyTIPL.class, "ft"); - - iterator = GenreTypes.getInstanceOf().getValueToIdMap().keySet().iterator(); - - while (iterator.hasNext()) { - addKeyword(FrameBodyCOMM.class, iterator.next()); - } - } catch (TagException ex) { - // this shouldn't happen, indicates coding error - throw new RuntimeException(ex); - } - - - addReplaceWord("v.", "vs."); - addReplaceWord("vs.", "vs."); - addReplaceWord("versus", "vs."); - addReplaceWord("f.", "feat."); - addReplaceWord("feat", "feat."); - addReplaceWord("featuring", "feat."); - addReplaceWord("ftng.", "feat."); - addReplaceWord("ftng", "feat."); - addReplaceWord("ft.", "feat."); - addReplaceWord("ft", "feat."); - - - iterator = this.getKeywordListIterator(FrameBodyTIPL.class); - - - addParenthesis("(", ")"); - addParenthesis("[", "]"); - addParenthesis("{", "}"); - addParenthesis("<", ">"); - } - - - /** - * @param id3v2FrameBodyClass - * @param keyword - * @throws TagException - */ - public void addKeyword(Class id3v2FrameBodyClass, String keyword) throws TagException { - if (!AbstractID3v2FrameBody.class.isAssignableFrom(id3v2FrameBodyClass)) { - throw new TagException("Invalid class type. Must be AbstractId3v2FrameBody " + id3v2FrameBodyClass); - } - - if ((keyword != null) && (keyword.length() > 0)) { - LinkedList keywordList; - - if (!keywordMap.containsKey(id3v2FrameBodyClass)) { - keywordList = new LinkedList(); - keywordMap.put(id3v2FrameBodyClass, keywordList); - } else { - keywordList = keywordMap.get(id3v2FrameBodyClass); - } - - keywordList.add(keyword); - } - } - - /** - * @param open - * @param close - */ - public void addParenthesis(String open, String close) { - parenthesisMap.put(open, close); - } - - /** - * @param oldWord - * @param newWord - */ - public void addReplaceWord(String oldWord, String newWord) { - replaceWordMap.put(oldWord, newWord); - } - - /** - * @return are tags unsynchronized when written if contain bit pattern that could be mistaken for audio marker - */ - public boolean isUnsyncTags() { - return unsyncTags; - } - - /** - * Unsync tag where necessary, currently only applies to IDv23 - * - * @param unsyncTags set whether tags are unsynchronized when written if contain bit pattern that could - * be mistaken for audio marker - */ - public void setUnsyncTags(boolean unsyncTags) { - this.unsyncTags = unsyncTags; - } - - /** - * Do we remove unnecessary trailing null characters on write - * - * @return true if we remove unnecessary trailing null characters on write - */ - public boolean isRemoveTrailingTerminatorOnWrite() { - return removeTrailingTerminatorOnWrite; - } - - /** - * Remove unnecessary trailing null characters on write - * - * @param removeTrailingTerminatorOnWrite - */ - public void setRemoveTrailingTerminatorOnWrite(boolean removeTrailingTerminatorOnWrite) { - this.removeTrailingTerminatorOnWrite = removeTrailingTerminatorOnWrite; - } - - /** - * Get the default text encoding to use for new v23 frames, when unicode is required - * UTF16 will always be used because that is the only valid option for v23/v22 - * - * @return - */ - public byte getId3v23DefaultTextEncoding() { - return id3v23DefaultTextEncoding; - } - - /** - * Set the default text encoding to use for new v23 frames, when unicode is required - * UTF16 will always be used because that is the only valid option for v23/v22 - * - * @param id3v23DefaultTextEncoding - */ - public void setId3v23DefaultTextEncoding(byte id3v23DefaultTextEncoding) { - if ((id3v23DefaultTextEncoding == TextEncoding.ISO_8859_1) || (id3v23DefaultTextEncoding == TextEncoding.UTF_16)) { - this.id3v23DefaultTextEncoding = id3v23DefaultTextEncoding; - } - } - - /** - * Get the default text encoding to use for new v24 frames, it defaults to simple ISO8859 - * but by changing this value you could always used UTF8 for example whether you needed to or not - * - * @return - */ - public byte getId3v24DefaultTextEncoding() { - return id3v24DefaultTextEncoding; - } - - /** - * Set the default text encoding to use for new v24 frames, it defaults to simple ISO8859 - * but by changing this value you could always used UTF8 for example whether you needed to or not - * - * @param id3v24DefaultTextEncoding - */ - public void setId3v24DefaultTextEncoding(byte id3v24DefaultTextEncoding) { - if ((id3v24DefaultTextEncoding == TextEncoding.ISO_8859_1) || (id3v24DefaultTextEncoding == TextEncoding.UTF_16) || (id3v24DefaultTextEncoding == TextEncoding.UTF_16BE) || (id3v24DefaultTextEncoding == TextEncoding.UTF_8)) { - this.id3v24DefaultTextEncoding = id3v24DefaultTextEncoding; - } - - } - - /** - * Get the text encoding to use for new v24 frames when unicode is required, it defaults to UTF16 just - * because this encoding is understand by all ID3 versions - * - * @return - */ - public byte getId3v24UnicodeTextEncoding() { - return id3v24UnicodeTextEncoding; - } - - /** - * Set the text encoding to use for new v24 frames when unicode is required, it defaults to UTF16 just - * because this encoding is understand by all ID3 versions - * - * @param id3v24UnicodeTextEncoding - */ - public void setId3v24UnicodeTextEncoding(byte id3v24UnicodeTextEncoding) { - if ((id3v24UnicodeTextEncoding == TextEncoding.UTF_16) || (id3v24UnicodeTextEncoding == TextEncoding.UTF_16BE) || (id3v24UnicodeTextEncoding == TextEncoding.UTF_8)) { - this.id3v24UnicodeTextEncoding = id3v24UnicodeTextEncoding; - } - } - - /** - * When writing frames if this is set to true then the frame will be written - * using the defaults disregarding the text encoding originally used to create - * the frame. - * - * @return - */ - public boolean isResetTextEncodingForExistingFrames() { - return resetTextEncodingForExistingFrames; - } - - /** - * When writing frames if this is set to true then the frame will be written - * using the defaults disregarding the text encoding originally used to create - * the frame. - * - * @param resetTextEncodingForExistingFrames - */ - public void setResetTextEncodingForExistingFrames(boolean resetTextEncodingForExistingFrames) { - this.resetTextEncodingForExistingFrames = resetTextEncodingForExistingFrames; - } - - /** - * @return truncate without errors - */ - public boolean isTruncateTextWithoutErrors() { - return truncateTextWithoutErrors; - } - - /** - * Set truncate without errors - * - * @param truncateTextWithoutErrors - */ - public void setTruncateTextWithoutErrors(boolean truncateTextWithoutErrors) { - this.truncateTextWithoutErrors = truncateTextWithoutErrors; - } - - public boolean isPadNumbers() { - return padNumbers; - } - - public void setPadNumbers(boolean padNumbers) { - this.padNumbers = padNumbers; - } - - public boolean isAndroid() { - return isAndroid; - } - - public void setAndroid(boolean android) { - isAndroid = android; - } - - /** - * When this is set and using the generic interface jaudiotagger will make some adjustmensts - * when saving field sso they work best with the specified Tagger - */ - public int getPlayerCompatability() { - return playerCompatability; - } - - public void setPlayerCompatability(int playerCompatability) { - this.playerCompatability = playerCompatability; - } - - /** - * When you specify a field should be stored as UTF16 in ID3 this means write with BOM indicating whether - * written as Little Endian or Big Endian, its defaults to little Endian - */ - public boolean isEncodeUTF16BomAsLittleEndian() { - return isEncodeUTF16BomAsLittleEndian; - } - - public void setEncodeUTF16BomAsLittleEndian(boolean encodeUTF16BomAsLittleEndian) { - isEncodeUTF16BomAsLittleEndian = encodeUTF16BomAsLittleEndian; - } - - /** - * When we have to create new audio files and shift audio data to fit in more metadata this value - * set the maximum amount in bytes that can be transferred in one call, this is to protect against - * various OutOfMemoryExceptions that cna occur, especially on networked filesystems. - */ - public long getWriteChunkSize() { - return writeChunkSize; - } - - public void setWriteChunkSize(long writeChunkSize) { - this.writeChunkSize = writeChunkSize; - } - - /** - * If enabled we always use the ©gen atom rather than the gnre atom when writing genres to mp4s - * This is known to help some android apps - */ - public boolean isWriteMp4GenresAsText() { - return isWriteMp4GenresAsText; - } - - public void setWriteMp4GenresAsText(boolean writeMp4GenresAsText) { - isWriteMp4GenresAsText = writeMp4GenresAsText; - } - - /** - * Total length of number, i.e if set to 2 the value 1 would be stored as 01, if set to 3 would bs stored as 001 - */ - public PadNumberOption getPadNumberTotalLength() { - return padNumberTotalLength; - } - - public void setPadNumberTotalLength(PadNumberOption padNumberTotalLength) { - this.padNumberTotalLength = padNumberTotalLength; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/TagTextField.java b/src/main/java/org/jaudiotagger/tag/TagTextField.java deleted file mode 100644 index ba4df89..0000000 --- a/src/main/java/org/jaudiotagger/tag/TagTextField.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag; - -/** - * This interface extends the default field definition by methods for working - * with human readable text.
    - * A TagTextField does not store binary data. - * - * @author Rapha�l Slinckx - */ -public interface TagTextField extends TagField { - - /** - * Returns the content of the field. - * - * @return Content - */ - String getContent(); - - /** - * Sets the content of the field. - * - * @param content fields content. - */ - void setContent(String content); - - /** - * Returns the current used charset encoding. - * - * @return Charset encoding. - */ - String getEncoding(); - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - void setEncoding(String encoding); -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/aiff/AiffTag.java b/src/main/java/org/jaudiotagger/tag/aiff/AiffTag.java deleted file mode 100644 index 177f064..0000000 --- a/src/main/java/org/jaudiotagger/tag/aiff/AiffTag.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.jaudiotagger.tag.aiff; - -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.id3.AbstractID3v2Tag; -import org.jaudiotagger.tag.images.Artwork; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * AiffTag wraps ID3Tag for most of its metadata - */ -public class AiffTag /* extends GenericTag */ implements Tag { - - private AbstractID3v2Tag id3Tag; - - /** - * No-argument constructor - */ - public AiffTag() { - } - - public AiffTag(AbstractID3v2Tag t) { - id3Tag = t; - } - - /** - * Returns the ID3 tag - */ - public AbstractID3v2Tag getID3Tag() { - return id3Tag; - } - - /** - * Sets the ID3 tag - */ - public void setID3Tag(AbstractID3v2Tag t) { - id3Tag = t; - } - - public void addField(TagField field) throws FieldDataInvalidException { - id3Tag.addField(field); - } - - public List getFields(String id) { - return id3Tag.getFields(id); - } - - /** - * Maps the generic key to the specific key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - return id3Tag.getAll(genericKey); - } - - public boolean hasCommonFields() { - return id3Tag.hasCommonFields(); - } - - /** - * Determines whether the tag has no fields specified.
    - *

    - *

    If there are no images we return empty if either there is no VorbisTag or if there is a - * VorbisTag but it is empty - * - * @return true if tag contains no field. - */ - public boolean isEmpty() { - return (id3Tag == null || id3Tag.isEmpty()); - } - - public void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - /** - * @param field - * @throws FieldDataInvalidException - */ - public void setField(TagField field) throws FieldDataInvalidException { - id3Tag.setField(field); - } - - - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - return id3Tag.createField(genericKey, value); - } - - - public String getFirst(String id) { - return id3Tag.getFirst(id); - } - - public String getValue(FieldKey id, int index) throws KeyNotFoundException { - return id3Tag.getValue(id, index); - } - - public String getFirst(FieldKey id) throws KeyNotFoundException { - return getValue(id, 0); - } - - public TagField getFirstField(String id) { - return id3Tag.getFirstField(id); - } - - public TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } else { - return id3Tag.getFirstField(genericKey); - } - } - - /** - * Delete any instance of tag fields with this key - * - * @param fieldKey - */ - public void deleteField(FieldKey fieldKey) throws KeyNotFoundException { - id3Tag.deleteField(fieldKey); - } - - public void deleteField(String id) throws KeyNotFoundException { - id3Tag.deleteField(id); - } - - public Iterator getFields() { - return id3Tag.getFields(); - } - - public int getFieldCount() { - return id3Tag.getFieldCount(); - } - - public int getFieldCountIncludingSubValues() { - return getFieldCount(); - } - - public boolean setEncoding(String enc) throws FieldDataInvalidException { - return id3Tag.setEncoding(enc); - } - - /** - * Create artwork field. Not currently supported. - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - throw new FieldDataInvalidException("Not supported"); - } - - public void setField(Artwork artwork) throws FieldDataInvalidException { - throw new FieldDataInvalidException("Not supported"); - } - - public void addField(Artwork artwork) throws FieldDataInvalidException { - throw new FieldDataInvalidException("Not supported"); - } - - - public List getArtworkList() { - return new ArrayList(); - } - - public List getFields(FieldKey id) throws KeyNotFoundException { - return id3Tag.getFields(id); - } - - public Artwork getFirstArtwork() { - return null; - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException { - } - - /** - * @param genericKey - * @return - */ - public boolean hasField(FieldKey genericKey) { - return id3Tag.hasField(genericKey); - } - - - public boolean hasField(String id) { - return id3Tag.hasField(id); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/aiff/AiffTagFieldKey.java b/src/main/java/org/jaudiotagger/tag/aiff/AiffTagFieldKey.java deleted file mode 100644 index 2c6c884..0000000 --- a/src/main/java/org/jaudiotagger/tag/aiff/AiffTagFieldKey.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.jaudiotagger.tag.aiff; - -/** - * Enum for AIFF fields that don't have obvious matches in FieldKey - */ -public enum AiffTagFieldKey { - TIMESTAMP("TIMESTAMP"); - - private String fieldName; - - AiffTagFieldKey(String fieldName) { - this.fieldName = fieldName; - } - - public String getFieldName() { - return fieldName; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/AbstractAsfTagImageField.java b/src/main/java/org/jaudiotagger/tag/asf/AbstractAsfTagImageField.java deleted file mode 100644 index 4d25fd7..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AbstractAsfTagImageField.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.MetadataDescriptor; -import org.jaudiotagger.tag.TagField; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -/** - * An AbstractAsfTagImageField is an abstract class for representing tag - * fields containing image data.
    - * - * @author Christian Laireiter - */ -abstract class AbstractAsfTagImageField extends AsfTagField { - - /** - * Creates a image tag field. - * - * @param field the ASF field that should be represented. - */ - public AbstractAsfTagImageField(final AsfFieldKey field) { - super(field); - } - - /** - * Creates an instance. - * - * @param source The descriptor which should be represented as a - * {@link TagField}. - */ - public AbstractAsfTagImageField(final MetadataDescriptor source) { - super(source); - } - - /** - * Creates a tag field. - * - * @param fieldKey The field identifier to use. - */ - public AbstractAsfTagImageField(final String fieldKey) { - super(fieldKey); - } - - /** - * This method returns an image instance from the - * {@linkplain #getRawImageData() image content}. - * - * @return the image instance - * @throws IOException - */ - public BufferedImage getImage() throws IOException { - return ImageIO.read(new ByteArrayInputStream(getRawImageData())); - } - - /** - * Returns the size of the {@linkplain #getRawImageData() image data}.
    - * - * @return image data size in bytes. - */ - public abstract int getImageDataSize(); - - /** - * Returns the raw data of the represented image.
    - * - * @return raw image data - */ - public abstract byte[] getRawImageData(); - -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/AsfFieldKey.java b/src/main/java/org/jaudiotagger/tag/asf/AsfFieldKey.java deleted file mode 100644 index 05c241e..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AsfFieldKey.java +++ /dev/null @@ -1,298 +0,0 @@ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.ContainerType; -import org.jaudiotagger.audio.asf.data.ContentBranding; -import org.jaudiotagger.audio.asf.data.ContentDescription; - -import java.util.HashMap; -import java.util.Map; - -/** - * Field keys which need to be mapped for ASF files, or only specified for ASF. - *

    - * TODO These attributes and their v23 mapping that havent been added to enum yet - *

    - * WMA ID3v1 ID3v22 ID3v2324 - *

    - * CopyrightURL WCP WCOP - * Duration TLE TLEN - * FileSize TSIZ - * WM/AudioFileURL WAF WOAF - * WM/AudioSourceURL WAS WOAS - * WM/Binary GEO GEOB - * WM/EncodingSettings TSS TSSE - * WM/EncodingTime TDEN - * WM/MCDI MCDI - * WM/ModifiedBy TPE4 - * WM/OriginalFilename TOF TOFN - * WM/PlaylistDelay TDLY - * WM/RadioStationName TRN TRSN - * WM/RadioStationOwner TRO TRSO - * WM/SetSubTitle TSST - * WM/Text TXX TXXX - * WM/UniqueFileIdentifier UFI UFID - * WM/UserWebURL WXX WXXX - * - * @author Christian Laireiter - */ -public enum AsfFieldKey { - /* - * Keys are arbitrary because these fields don't have 'keys' internally because they are stored in preset contents descriptor - */ - - // Content Description Object keys - AUTHOR(ContentDescription.KEY_AUTHOR, false, ContainerType.CONTENT_DESCRIPTION), - TITLE(ContentDescription.KEY_TITLE, false, ContainerType.CONTENT_DESCRIPTION), - RATING(ContentDescription.KEY_RATING, false, ContainerType.CONTENT_DESCRIPTION), - COPYRIGHT(ContentDescription.KEY_COPYRIGHT, false, ContainerType.CONTENT_DESCRIPTION), - DESCRIPTION(ContentDescription.KEY_DESCRIPTION, false, ContainerType.CONTENT_DESCRIPTION), - - // Content Branding Object keys - BANNER_IMAGE(ContentBranding.KEY_BANNER_IMAGE, false, ContainerType.CONTENT_BRANDING), - BANNER_IMAGE_TYPE(ContentBranding.KEY_BANNER_TYPE, false, ContainerType.CONTENT_BRANDING), - BANNER_IMAGE_URL(ContentBranding.KEY_BANNER_URL, false, ContainerType.CONTENT_BRANDING), - COPYRIGHT_URL(ContentBranding.KEY_COPYRIGHT_URL, false, ContainerType.CONTENT_BRANDING), - - /* - * keys are important because this is how values will be looked up by other applications - */ - ALBUM("WM/AlbumTitle", false), - ALBUM_ARTIST("WM/AlbumArtist", true), - ALBUM_ARTIST_SORT("WM/AlbumArtistSortOrder", false), - ALBUM_SORT("WM/AlbumSortOrder", false), - AMAZON_ID("ASIN", false), - ARTIST_SORT("WM/ArtistSortOrder", false), - ARTISTS("WM/ARTISTS", true), - BARCODE("WM/Barcode", false), - BPM("WM/BeatsPerMinute", false), - CATALOG_NO("WM/CatalogNo", false), - CATEGORY("WM/Category", true), - COMPOSER("WM/Composer", true), - COMPOSER_SORT("WM/ComposerSort", false), - CONDUCTOR("WM/Conductor", true), - COVER_ART("WM/Picture", true), - COVER_ART_URL("WM/AlbumCoverURL", true), - CUSTOM1("CUSTOM1", true), - CUSTOM2("CUSTOM2", true), - CUSTOM3("CUSTOM3", true), - CUSTOM4("CUSTOM4", true), - CUSTOM5("CUSTOM5", true), - DIRECTOR("WM/Director", true), - DISC_NO("WM/PartOfSet", false), - DISC_SUBTITLE("WM/SetSubTitle", false), - DISC_TOTAL("WM/DiscTotal", false), - ENCODER("WM/ToolName", false), - ENCODED_BY("WM/EncodedBy", false), - FBPM("FBPM", true), - GENRE("WM/Genre", true), - GENRE_ID("WM/GenreID", true), - GROUPING("WM/ContentGroupDescription", false), - INITIAL_KEY("WM/InitialKey", false), - IS_COMPILATION("WM/IsCompilation", false), - ISRC("WM/ISRC", false), - ISVBR("IsVBR", true), - LANGUAGE("WM/Language", true), - LYRICIST("WM/Writer", true), - LYRICS("WM/Lyrics", false), - LYRICS_SYNCHRONISED("WM/Lyrics_Synchronised", true), - MEDIA("WM/Media", false), - MOOD("WM/Mood", true), - MUSICBRAINZ_ARTISTID("MusicBrainz/Artist Id", false), - MUSICBRAINZ_DISC_ID("MusicBrainz/Disc Id", false), - MUSICBRAINZ_ORIGINAL_RELEASEID("MusicBrainz/Original Album Id", false), - MUSICBRAINZ_RELEASE_COUNTRY("MusicBrainz/Album Release Country", false), - MUSICBRAINZ_RELEASE_STATUS("MusicBrainz/Album Status", false), - MUSICBRAINZ_RELEASE_TYPE("MusicBrainz/Album Type", false), - MUSICBRAINZ_RELEASEARTISTID("MusicBrainz/Album Artist Id", false), - MUSICBRAINZ_RELEASEID("MusicBrainz/Album Id", false), - MUSICBRAINZ_RELEASEGROUPID("MusicBrainz/Release Group Id", false), - MUSICBRAINZ_TRACK_ID("MusicBrainz/Track Id", false), - MUSICBRAINZ_WORKID("MusicBrainz/Work Id", false), - MUSICIP_ID("MusicIP/PUID", false), - ACOUSTID_FINGERPRINT("Acoustid/Fingerprint", false), - ACOUSTID_FINGERPRINT_OLD("AcoustId/Fingerprint", false), - ACOUSTID_ID("Acoustid/Id", false), - OCCASION("Occasion", true), - ORIGINAL_ALBUM("WM/OriginalAlbumTitle", true), - ORIGINAL_ARTIST("WM/OriginalArtist", true), - ORIGINAL_LYRICIST("WM/OriginalLyricist", true), - ORIGINAL_YEAR("WM/OriginalReleaseYear", true), - PRODUCER("WM/Producer", false), - QUALITY("Quality", true), - USER_RATING("WM/SharedUserRating", true), - MM_RATING("SDB/Rating", true), - RECORD_LABEL("WM/Publisher", false), - REMIXER("WM/ModifiedBy", false), - SCRIPT("WM/Script", false), - SUBTITLE("WM/SubTitle", false), - TAGS("WM/Tags", false), - TEMPO("Tempo", true), - TITLE_SORT("WM/TitleSortOrder", false), - TRACK("WM/TrackNumber", false), - TRACK_TOTAL("WM/TrackTotal", false), - URL_DISCOGS_ARTIST_SITE("WM/DiscogsArtistUrl", false), - URL_DISCOGS_RELEASE_SITE("WM/DiscogsReleaseUrl", false), - URL_OFFICIAL_ARTIST_SITE("WM/AuthorURL", false), - URL_OFFICIAL_RELEASE_SITE("WM/OfficialReleaseUrl", false), - URL_PROMOTIONAL_SITE("WM/PromotionURL", true), - URL_WIKIPEDIA_ARTIST_SITE("WM/WikipediaArtistUrl", false), - URL_WIKIPEDIA_RELEASE_SITE("WM/WikipediaReleaseUrl", false), - URL_LYRICS_SITE("WM/LyricsUrl", false), - YEAR("WM/Year", false), - - ENGINEER("WM/Engineer", false), - DJMIXER("WM/DJMixer", false), - MIXER("WM/Mixer", false), - ARRANGER("WM/Arranger", false), - COUNTRY("WM/Country", false), - - // Special field for all unknown field names, which will getFields maximum support - CUSTOM("___CUSTOM___", true); - - /** - * Stores the {@link AsfFieldKey#fieldName} to the field key. - */ - private final static Map FIELD_ID_MAP; - - static { - FIELD_ID_MAP = new HashMap(AsfFieldKey.values().length); - for (AsfFieldKey curr : AsfFieldKey.values()) { - if (curr != CUSTOM) { - assert !FIELD_ID_MAP.containsKey(curr.getFieldName()) : "duplicate field entry: " + curr.getFieldName(); - FIELD_ID_MAP.put(curr.getFieldName(), curr); - } - } - } - - /** - * If set, the field has a standard id assigned. - */ - private final String fieldName; - /** - * If true, the field will be stored repeatedly if occurs so in tags. - */ - private final boolean multiValued; - /** - * The lowest possible container type, such a field can be stored into.
    - * Low means, container with least capabilities. - */ - private final ContainerType lowestContainer; - /** - * The highest possible container type, such a field can be stored into.
    - * High means, most capabilities, for example string length exceeds that of - * the extended content description, it will be stored one level up (metadata library). - */ - private final ContainerType highestContainer; - - /** - * Creates an instance
    - * Lowest/Highest will be {@link ContainerType#EXTENDED_CONTENT} / - * {@link ContainerType#METADATA_LIBRARY_OBJECT} - * - * @param asfFieldName standard field identifier. - * @param multiValue true if the this ASF field can have multiple - * values. - */ - AsfFieldKey(final String asfFieldName, final boolean multiValue) { - this(asfFieldName, multiValue, ContainerType.EXTENDED_CONTENT, - ContainerType.METADATA_LIBRARY_OBJECT); - } - - /** - * Creates an instance.
    - * - * @param asfFieldName standard field identifier. - * @param multiValue true if the this ASF field can have multiple - * values. - * @param restrictedTo fields must be stored in this container. - */ - AsfFieldKey(final String asfFieldName, final boolean multiValue, - final ContainerType restrictedTo) { - this(asfFieldName, multiValue, restrictedTo, restrictedTo); - } - - /** - * Creates an instance.
    - * - * @param asfFieldName standard field identifier. - * @param multiValue true if the this ASF field can have multiple - * values. - * @param lowest fields must be stored at least in this container. - * @param highest fields aren't allowed to be stored in better containers than - * this. - */ - AsfFieldKey(final String asfFieldName, final boolean multiValue, - final ContainerType lowest, final ContainerType highest) { - this.fieldName = asfFieldName; - assert !multiValue || highest.isMultiValued() : "Definition error"; - this.multiValued = multiValue && highest.isMultiValued(); - this.lowestContainer = lowest; - this.highestContainer = highest; - assert ContainerType.areInCorrectOrder(lowest, highest); - } - - /** - * Searches for an ASF field key which represents the given id string.
    - * - * @param fieldName the field name used for this key - * @return the Enum that represents this field - */ - public static AsfFieldKey getAsfFieldKey(final String fieldName) { - AsfFieldKey result = FIELD_ID_MAP.get(fieldName); - if (result == null) { - result = CUSTOM; - } - return result; - } - - /** - * Tests whether the field is enabled for multiple values.
    - * - * @param fieldName field id to test. - * @return true if ASF implementation supports multiple values for the field. - */ - public static boolean isMultiValued(final String fieldName) { - final AsfFieldKey fieldKey = getAsfFieldKey(fieldName); - return fieldKey != null && fieldKey.isMultiValued(); - } - - /** - * Returns the standard field id. - * - * @return the standard field id. (may be null) - */ - public String getFieldName() { - return this.fieldName; - } - - /** - * @return the highestContainer - */ - public ContainerType getHighestContainer() { - return this.highestContainer; - } - - /** - * @return the lowestContainer - */ - public ContainerType getLowestContainer() { - return this.lowestContainer; - } - - /** - * Returns true if this field can store multiple values. - * - * @return true if multiple values are supported for this field. - */ - public boolean isMultiValued() { - return this.multiValued; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return getFieldName(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/AsfTag.java b/src/main/java/org/jaudiotagger/tag/asf/AsfTag.java deleted file mode 100644 index 40c5da1..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AsfTag.java +++ /dev/null @@ -1,631 +0,0 @@ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.generic.AbstractTag; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.UnsupportedEncodingException; -import java.util.*; - -/** - * Tag implementation for ASF.
    - * - * @author Christian Laireiter - */ -public final class AsfTag extends AbstractTag { - /** - * Stores a list of field keys, which identify common fields.
    - */ - public final static Set COMMON_FIELDS; - /** - * This map contains the mapping from {@link org.jaudiotagger.tag.FieldKey} to - * {@link AsfFieldKey}. - */ - private static final EnumMap tagFieldToAsfField; - - static { - tagFieldToAsfField = new EnumMap(FieldKey.class); - tagFieldToAsfField.put(FieldKey.ALBUM, AsfFieldKey.ALBUM); - tagFieldToAsfField.put(FieldKey.ALBUM_ARTIST, AsfFieldKey.ALBUM_ARTIST); - tagFieldToAsfField.put(FieldKey.ALBUM_ARTIST_SORT, AsfFieldKey.ALBUM_ARTIST_SORT); - tagFieldToAsfField.put(FieldKey.ALBUM_SORT, AsfFieldKey.ALBUM_SORT); - tagFieldToAsfField.put(FieldKey.AMAZON_ID, AsfFieldKey.AMAZON_ID); - tagFieldToAsfField.put(FieldKey.ARTIST, AsfFieldKey.AUTHOR); - tagFieldToAsfField.put(FieldKey.ARTIST_SORT, AsfFieldKey.ARTIST_SORT); - tagFieldToAsfField.put(FieldKey.ARTISTS, AsfFieldKey.ARTISTS); - tagFieldToAsfField.put(FieldKey.BARCODE, AsfFieldKey.BARCODE); - tagFieldToAsfField.put(FieldKey.BPM, AsfFieldKey.BPM); - tagFieldToAsfField.put(FieldKey.CATALOG_NO, AsfFieldKey.CATALOG_NO); - tagFieldToAsfField.put(FieldKey.COMMENT, AsfFieldKey.DESCRIPTION); - tagFieldToAsfField.put(FieldKey.COMPOSER, AsfFieldKey.COMPOSER); - tagFieldToAsfField.put(FieldKey.COMPOSER_SORT, AsfFieldKey.COMPOSER_SORT); - tagFieldToAsfField.put(FieldKey.CONDUCTOR, AsfFieldKey.CONDUCTOR); - tagFieldToAsfField.put(FieldKey.COVER_ART, AsfFieldKey.COVER_ART); - tagFieldToAsfField.put(FieldKey.CUSTOM1, AsfFieldKey.CUSTOM1); - tagFieldToAsfField.put(FieldKey.CUSTOM2, AsfFieldKey.CUSTOM2); - tagFieldToAsfField.put(FieldKey.CUSTOM3, AsfFieldKey.CUSTOM3); - tagFieldToAsfField.put(FieldKey.CUSTOM4, AsfFieldKey.CUSTOM4); - tagFieldToAsfField.put(FieldKey.CUSTOM5, AsfFieldKey.CUSTOM5); - tagFieldToAsfField.put(FieldKey.DISC_NO, AsfFieldKey.DISC_NO); - tagFieldToAsfField.put(FieldKey.DISC_SUBTITLE, AsfFieldKey.DISC_SUBTITLE); - tagFieldToAsfField.put(FieldKey.DISC_TOTAL, AsfFieldKey.DISC_TOTAL); - tagFieldToAsfField.put(FieldKey.ENCODER, AsfFieldKey.ENCODER); - tagFieldToAsfField.put(FieldKey.FBPM, AsfFieldKey.FBPM); - tagFieldToAsfField.put(FieldKey.GENRE, AsfFieldKey.GENRE); - tagFieldToAsfField.put(FieldKey.GROUPING, AsfFieldKey.GROUPING); - tagFieldToAsfField.put(FieldKey.ISRC, AsfFieldKey.ISRC); - tagFieldToAsfField.put(FieldKey.IS_COMPILATION, AsfFieldKey.IS_COMPILATION); - tagFieldToAsfField.put(FieldKey.KEY, AsfFieldKey.INITIAL_KEY); - tagFieldToAsfField.put(FieldKey.LANGUAGE, AsfFieldKey.LANGUAGE); - tagFieldToAsfField.put(FieldKey.LYRICIST, AsfFieldKey.LYRICIST); - tagFieldToAsfField.put(FieldKey.LYRICS, AsfFieldKey.LYRICS); - tagFieldToAsfField.put(FieldKey.MEDIA, AsfFieldKey.MEDIA); - tagFieldToAsfField.put(FieldKey.MOOD, AsfFieldKey.MOOD); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_ARTISTID, AsfFieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_DISC_ID, AsfFieldKey.MUSICBRAINZ_DISC_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, AsfFieldKey.MUSICBRAINZ_ORIGINAL_RELEASEID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, AsfFieldKey.MUSICBRAINZ_RELEASEARTISTID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_RELEASEID, AsfFieldKey.MUSICBRAINZ_RELEASEID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, AsfFieldKey.MUSICBRAINZ_RELEASE_COUNTRY); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, AsfFieldKey.MUSICBRAINZ_RELEASEGROUPID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, AsfFieldKey.MUSICBRAINZ_RELEASE_STATUS); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, AsfFieldKey.MUSICBRAINZ_RELEASE_TYPE); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_TRACK_ID, AsfFieldKey.MUSICBRAINZ_TRACK_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_ID, AsfFieldKey.MUSICBRAINZ_WORKID); - tagFieldToAsfField.put(FieldKey.MUSICIP_ID, AsfFieldKey.MUSICIP_ID); - tagFieldToAsfField.put(FieldKey.OCCASION, AsfFieldKey.OCCASION); - tagFieldToAsfField.put(FieldKey.ORIGINAL_ARTIST, AsfFieldKey.ORIGINAL_ARTIST); - tagFieldToAsfField.put(FieldKey.ORIGINAL_ALBUM, AsfFieldKey.ORIGINAL_ALBUM); - tagFieldToAsfField.put(FieldKey.ORIGINAL_LYRICIST, AsfFieldKey.ORIGINAL_LYRICIST); - tagFieldToAsfField.put(FieldKey.ORIGINAL_YEAR, AsfFieldKey.ORIGINAL_YEAR); - tagFieldToAsfField.put(FieldKey.RATING, AsfFieldKey.USER_RATING); - tagFieldToAsfField.put(FieldKey.RECORD_LABEL, AsfFieldKey.RECORD_LABEL); - tagFieldToAsfField.put(FieldKey.QUALITY, AsfFieldKey.QUALITY); - tagFieldToAsfField.put(FieldKey.REMIXER, AsfFieldKey.REMIXER); - tagFieldToAsfField.put(FieldKey.SCRIPT, AsfFieldKey.SCRIPT); - tagFieldToAsfField.put(FieldKey.SUBTITLE, AsfFieldKey.SUBTITLE); - tagFieldToAsfField.put(FieldKey.TAGS, AsfFieldKey.TAGS); - tagFieldToAsfField.put(FieldKey.TEMPO, AsfFieldKey.TEMPO); - tagFieldToAsfField.put(FieldKey.TITLE, AsfFieldKey.TITLE); - tagFieldToAsfField.put(FieldKey.TITLE_SORT, AsfFieldKey.TITLE_SORT); - tagFieldToAsfField.put(FieldKey.TRACK, AsfFieldKey.TRACK); - tagFieldToAsfField.put(FieldKey.TRACK_TOTAL, AsfFieldKey.TRACK_TOTAL); - tagFieldToAsfField.put(FieldKey.URL_DISCOGS_ARTIST_SITE, AsfFieldKey.URL_DISCOGS_ARTIST_SITE); - tagFieldToAsfField.put(FieldKey.URL_DISCOGS_RELEASE_SITE, AsfFieldKey.URL_DISCOGS_RELEASE_SITE); - tagFieldToAsfField.put(FieldKey.URL_LYRICS_SITE, AsfFieldKey.URL_LYRICS_SITE); - tagFieldToAsfField.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, AsfFieldKey.URL_OFFICIAL_ARTIST_SITE); - tagFieldToAsfField.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, AsfFieldKey.URL_OFFICIAL_RELEASE_SITE); - tagFieldToAsfField.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, AsfFieldKey.URL_WIKIPEDIA_ARTIST_SITE); - tagFieldToAsfField.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, AsfFieldKey.URL_WIKIPEDIA_RELEASE_SITE); - tagFieldToAsfField.put(FieldKey.YEAR, AsfFieldKey.YEAR); - tagFieldToAsfField.put(FieldKey.ENGINEER, AsfFieldKey.ENGINEER); - tagFieldToAsfField.put(FieldKey.PRODUCER, AsfFieldKey.PRODUCER); - tagFieldToAsfField.put(FieldKey.DJMIXER, AsfFieldKey.DJMIXER); - tagFieldToAsfField.put(FieldKey.MIXER, AsfFieldKey.MIXER); - tagFieldToAsfField.put(FieldKey.ARRANGER, AsfFieldKey.ARRANGER); - tagFieldToAsfField.put(FieldKey.ACOUSTID_FINGERPRINT, AsfFieldKey.ACOUSTID_FINGERPRINT); - tagFieldToAsfField.put(FieldKey.ACOUSTID_ID, AsfFieldKey.ACOUSTID_ID); - tagFieldToAsfField.put(FieldKey.COUNTRY, AsfFieldKey.COUNTRY); - } - - // Mapping from generic key to asf key - - static { - COMMON_FIELDS = new HashSet(); - COMMON_FIELDS.add(AsfFieldKey.ALBUM); - COMMON_FIELDS.add(AsfFieldKey.AUTHOR); - COMMON_FIELDS.add(AsfFieldKey.DESCRIPTION); - COMMON_FIELDS.add(AsfFieldKey.GENRE); - COMMON_FIELDS.add(AsfFieldKey.TITLE); - COMMON_FIELDS.add(AsfFieldKey.TRACK); - COMMON_FIELDS.add(AsfFieldKey.YEAR); - } - - /** - * @see #isCopyingFields() - */ - private final boolean copyFields; - - /** - * Creates an empty instance. - */ - public AsfTag() { - this(false); - } - - /** - * Creates an instance and sets the field conversion property.
    - * - * @param copy look at {@link #isCopyingFields()}. - */ - public AsfTag(final boolean copy) { - super(); - this.copyFields = copy; - } - - /** - * Creates an instance and copies the fields of the source into the own - * structure.
    - * - * @param source source to read tag fields from. - * @param copy look at {@link #isCopyingFields()}. - * @throws UnsupportedEncodingException {@link TagField#getRawContent()} which may be called - */ - public AsfTag(final Tag source, final boolean copy) throws UnsupportedEncodingException { - this(copy); - copyFrom(source); - } - - /** - * {@inheritDoc} - */ - @Override - // TODO introduce copy idea to all formats - public void addField(final TagField field) { - if (isValidField(field)) { - if (AsfFieldKey.isMultiValued(field.getId())) { - super.addField(copyFrom(field)); - } else { - super.setField(copyFrom(field)); - } - } - } - - /** - * Creates a field for copyright and adds it.
    - * - * @param copyRight copyright content - */ - public void addCopyright(final String copyRight) { - addField(createCopyrightField(copyRight)); - } - - /** - * Creates a field for rating and adds it.
    - * - * @param rating rating. - */ - public void addRating(final String rating) { - addField(createRatingField(rating)); - } - - /** - * This method copies tag fields from the source.
    - * - * @param source source to read tag fields from. - */ - private void copyFrom(final Tag source) { - final Iterator fieldIterator = source.getFields(); - // iterate over all fields - while (fieldIterator.hasNext()) { - final TagField copy = copyFrom(fieldIterator.next()); - if (copy != null) { - super.addField(copy); - } - } - } - - /** - * If {@link #isCopyingFields()} is true, Creates a copy of - * source, if its not empty-
    - * However, plain {@link TagField} objects can only be transformed into - * binary fields using their {@link TagField#getRawContent()} method.
    - * - * @param source source field to copy. - * @return A copy, which is as close to the source as possible, or - * null if the field is empty (empty byte[] or blank - * string}. - */ - private TagField copyFrom(final TagField source) { - TagField result; - if (isCopyingFields()) { - if (source instanceof AsfTagField) { - try { - result = (TagField) ((AsfTagField) source).clone(); - } catch (CloneNotSupportedException e) { - result = new AsfTagField(((AsfTagField) source).getDescriptor()); - } - } else if (source instanceof TagTextField) { - final String content = ((TagTextField) source).getContent(); - result = new AsfTagTextField(source.getId(), content); - } else { - throw new RuntimeException("Unknown Asf Tag Field class:" // NOPMD - // by - // Christian - // Laireiter - // on - // 5/9/09 - // 5:44 - // PM - + source.getClass()); - } - } else { - result = source; - } - return result; - } - - /** - * Creates an {@link AsfTagCoverField} from given artwork - * - * @param artwork artwork to create a ASF field from. - * @return ASF field capable of storing artwork. - */ - public AsfTagCoverField createField(final Artwork artwork) { - return new AsfTagCoverField(artwork.getBinaryData(), artwork.getPictureType(), artwork.getDescription(), artwork.getMimeType()); - } - - /** - * Create artwork field - * - * @param data raw image data - * @return creates a default ASF picture field with default - * {@linkplain PictureTypes#DEFAULT_ID picture type}. - */ - public AsfTagCoverField createArtworkField(final byte[] data) { - return new AsfTagCoverField(data, PictureTypes.DEFAULT_ID, null, null); - } - - /** - * Creates a field for storing the copyright.
    - * - * @param content Copyright value. - * @return {@link AsfTagTextField} - */ - public AsfTagTextField createCopyrightField(final String content) { - return new AsfTagTextField(AsfFieldKey.COPYRIGHT, content); - } - - /** - * Creates a field for storing the copyright.
    - * - * @param content Rating value. - * @return {@link AsfTagTextField} - */ - public AsfTagTextField createRatingField(final String content) { - return new AsfTagTextField(AsfFieldKey.RATING, content); - } - - /** - * Create tag text field using ASF key - *

    - * Uses the correct subclass for the key.
    - * - * @param asfFieldKey field key to create field for. - * @param value string value for the created field. - * @return text field with given content. - */ - public AsfTagTextField createField(final AsfFieldKey asfFieldKey, final String value) { - if (value == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - if (asfFieldKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - switch (asfFieldKey) { - case COVER_ART: - throw new UnsupportedOperationException("Cover Art cannot be created using this method"); - case BANNER_IMAGE: - throw new UnsupportedOperationException("Banner Image cannot be created using this method"); - default: - return new AsfTagTextField(asfFieldKey.getFieldName(), value); - } - } - - /** - * {@inheritDoc} - */ - @Override - public AsfTagTextField createField(final FieldKey genericKey, final String value) throws KeyNotFoundException, FieldDataInvalidException { - if (value == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - if (genericKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - final AsfFieldKey asfFieldKey = tagFieldToAsfField.get(genericKey); - if (asfFieldKey == null) { - throw new KeyNotFoundException(genericKey.toString()); - } - return createField(asfFieldKey, value); - } - - /** - * Removes all fields which are stored to the provided field key. - * - * @param fieldKey fields to remove. - */ - public void deleteField(final AsfFieldKey fieldKey) { - super.deleteField(fieldKey.getFieldName()); - } - - /** - * {@inheritDoc} - */ - @Override - public void deleteField(final FieldKey fieldKey) throws KeyNotFoundException { - if (fieldKey == null) { - throw new KeyNotFoundException(); - } - super.deleteField(tagFieldToAsfField.get(fieldKey).getFieldName()); - } - - /** - * {@inheritDoc} - */ - public List getFields(final FieldKey fieldKey) throws KeyNotFoundException { - if (fieldKey == null) { - throw new KeyNotFoundException(); - } - return super.getFields(tagFieldToAsfField.get(fieldKey).getFieldName()); - } - - /** - * Maps the generic key to the ogg key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - AsfFieldKey asfFieldKey = tagFieldToAsfField.get(genericKey); - if (asfFieldKey == null) { - throw new KeyNotFoundException(); - } - return super.getAll(asfFieldKey.getFieldName()); - } - - /** - * @return - */ - public List getArtworkList() { - final List coverartList = getFields(FieldKey.COVER_ART); - final List artworkList = new ArrayList(coverartList.size()); - - for (final TagField next : coverartList) { - final AsfTagCoverField coverArt = (AsfTagCoverField) next; - final Artwork artwork = ArtworkFactory.getNew(); - artwork.setBinaryData(coverArt.getRawImageData()); - artwork.setMimeType(coverArt.getMimeType()); - artwork.setDescription(coverArt.getDescription()); - artwork.setPictureType(coverArt.getPictureType()); - artworkList.add(artwork); - } - return artworkList; - } - - /** - * This method iterates through all stored fields.
    - * This method can only be used if this class has been created with field - * conversion turned on. - * - * @return Iterator for iterating through ASF fields. - */ - public Iterator getAsfFields() { - if (!isCopyingFields()) { - throw new IllegalStateException("Since the field conversion is not enabled, this method cannot be executed"); - } - return new AsfFieldIterator(getFields()); - } - - /** - * Returns a list of stored copyrights. - * - * @return list of stored copyrights. - */ - public List getCopyright() { - return getFields(AsfFieldKey.COPYRIGHT.getFieldName()); - } - - /** - * Sets the copyright.
    - * - * @param Copyright the copyright to set. - */ - public void setCopyright(final String Copyright) { - setField(createCopyrightField(Copyright)); - } - - /** - * {@inheritDoc} - */ - @Override - public String getFirst(final FieldKey genericKey) throws KeyNotFoundException { - return getValue(genericKey, 0); - } - - /** - * Retrieve the first value that exists for this asfkey - * - * @param asfKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public String getFirst(AsfFieldKey asfKey) throws KeyNotFoundException { - if (asfKey == null) { - throw new KeyNotFoundException(); - } - return super.getFirst(asfKey.getFieldName()); - } - - /** - * {@inheritDoc} - */ - public String getValue(final FieldKey genericKey, int index) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - return super.getItem(tagFieldToAsfField.get(genericKey).getFieldName(), index); - } - - /** - * Returns the Copyright. - * - * @return the Copyright. - */ - public String getFirstCopyright() { - return getFirst(AsfFieldKey.COPYRIGHT.getFieldName()); - } - - /** - * {@inheritDoc} - */ - @Override - public AsfTagField getFirstField(final FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - return (AsfTagField) super.getFirstField(tagFieldToAsfField.get(genericKey).getFieldName()); - } - - /** - * Returns the Rating. - * - * @return the Rating. - */ - public String getFirstRating() { - return getFirst(AsfFieldKey.RATING.getFieldName()); - } - - /** - * Returns a list of stored ratings. - * - * @return list of stored ratings. - */ - public List getRating() { - return getFields(AsfFieldKey.RATING.getFieldName()); - } - - /** - * Sets the Rating.
    - * - * @param rating the rating to set. - */ - public void setRating(final String rating) { - setField(createRatingField(rating)); - } - - /** - * {@inheritDoc} - */ - @Override - protected boolean isAllowedEncoding(final String enc) { - return AsfHeader.ASF_CHARSET.name().equals(enc); - } - - /** - * If true, the {@link #copyFrom(TagField)} method creates a - * new {@link AsfTagField} instance and copies the content from the source.
    - * This method is utilized by {@link #addField(TagField)} and - * {@link #setField(TagField)}.
    - * So if true it is ensured that the {@link AsfTag} instance - * has its own copies of fields, which cannot be modified after assignment - * (which could pass some checks), and it just stores {@link AsfTagField} - * objects.
    - * Only then {@link #getAsfFields()} can work. otherwise - * {@link IllegalStateException} is thrown. - * - * @return state of field conversion. - */ - public boolean isCopyingFields() { - return this.copyFields; - } - - /** - * Check field is valid and can be added to this tag - * - * @param field field to add - * @return true if field may be added. - */ - // TODO introduce this concept to all formats - private boolean isValidField(final TagField field) { - if (field == null) { - return false; - } - - if (!(field instanceof AsfTagField)) { - return false; - } - - return !field.isEmpty(); - } - - /** - * {@inheritDoc} - */ - @Override - // TODO introduce copy idea to all formats - public void setField(final TagField field) { - if (isValidField(field)) { - // Copy only occurs if flag setField - super.setField(copyFrom(field)); - } - } - - /** - * @param genericKey - * @return - */ - public boolean hasField(FieldKey genericKey) { - AsfFieldKey mp4FieldKey = tagFieldToAsfField.get(genericKey); - return getFields(mp4FieldKey.getFieldName()).size() != 0; - } - - /** - * @param asfFieldKey - * @return - */ - public boolean hasField(AsfFieldKey asfFieldKey) { - return getFields(asfFieldKey.getFieldName()).size() != 0; - } - - /** - * This iterator is used to iterator an {@link Iterator} with - * {@link TagField} objects and returns them by casting to - * {@link AsfTagField}.
    - * - * @author Christian Laireiter - */ - private static class AsfFieldIterator implements Iterator { - - /** - * source iterator. - */ - private final Iterator fieldIterator; - - /** - * Creates an isntance. - * - * @param iterator iterator to read from. - */ - public AsfFieldIterator(final Iterator iterator) { - assert iterator != null; - this.fieldIterator = iterator; - } - - /** - * {@inheritDoc} - */ - public boolean hasNext() { - return this.fieldIterator.hasNext(); - } - - /** - * {@inheritDoc} - */ - public AsfTagField next() { - return (AsfTagField) this.fieldIterator.next(); - } - - /** - * {@inheritDoc} - */ - public void remove() { - this.fieldIterator.remove(); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/AsfTagBannerField.java b/src/main/java/org/jaudiotagger/tag/asf/AsfTagBannerField.java deleted file mode 100644 index 31db189..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AsfTagBannerField.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.ContainerType; -import org.jaudiotagger.audio.asf.data.ContentBranding; -import org.jaudiotagger.audio.asf.data.MetadataDescriptor; - -/** - * This field represents the image content of the banner image which is stored - * in the {@linkplain ContentBranding content branding} chunk of ASF files.
    - * - * @author Christian Laireiter - */ -public class AsfTagBannerField extends AbstractAsfTagImageField { - - /** - * Creates an instance with no image data.
    - */ - public AsfTagBannerField() { - super(AsfFieldKey.BANNER_IMAGE); - } - - /** - * Creates an instance with given descriptor as image content.
    - * - * @param descriptor image content. - */ - public AsfTagBannerField(final MetadataDescriptor descriptor) { - super(descriptor); - assert descriptor.getName().equals( - AsfFieldKey.BANNER_IMAGE.getFieldName()); - } - - /** - * Creates an instance with specified data as image content. - * - * @param imageData image content. - */ - public AsfTagBannerField(final byte[] imageData) { - super(new MetadataDescriptor(ContainerType.CONTENT_BRANDING, - AsfFieldKey.BANNER_IMAGE.getFieldName(), - MetadataDescriptor.TYPE_BINARY)); - this.toWrap.setBinaryValue(imageData); - } - - /** - * {@inheritDoc} - */ - @Override - public int getImageDataSize() { - return this.toWrap.getRawDataSize(); - } - - /** - * {@inheritDoc} - */ - @Override - public byte[] getRawImageData() { - return getRawContent(); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/AsfTagCoverField.java b/src/main/java/org/jaudiotagger/tag/asf/AsfTagCoverField.java deleted file mode 100644 index 36eb10d..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AsfTagCoverField.java +++ /dev/null @@ -1,221 +0,0 @@ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.asf.data.MetadataDescriptor; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.util.logging.Logger; - -/** - * Encapsulates the WM/Pictures provides some convenience methods for decoding - * the binary data it contains - *

    - * The value of a WM/Pictures metadata descriptor is as follows: - *

    - * byte0 Picture Type byte1-4 Length of the image data mime type encoded as - * UTF-16LE null byte null byte description encoded as UTF-16LE (optional) null - * byte null byte image data - */ -public class AsfTagCoverField extends AbstractAsfTagImageField { - /** - * Logger Object - */ - public final static Logger LOGGER = Logger - .getLogger("org.jaudiotagger.audio.asf.tag"); - - /** - * Description - */ - private String description; - - /** - * We need this to retrieve the buffered image, if required - */ - private int endOfName = 0; - - /** - * Image Data Size as read - */ - private int imageDataSize; - - /** - * Mimetype of binary - */ - private String mimeType; - - /** - * Picture Type - */ - private int pictureType; - - /** - * Create New Image Field - * - * @param imageData - * @param pictureType - * @param description - * @param mimeType - */ - public AsfTagCoverField(final byte[] imageData, final int pictureType, - final String description, final String mimeType) { - super(new MetadataDescriptor(AsfFieldKey.COVER_ART.getFieldName(), - MetadataDescriptor.TYPE_BINARY)); - this.getDescriptor() - .setBinaryValue( - createRawContent(imageData, pictureType, description, - mimeType)); - } - - /** - * Creates an instance from a metadata descriptor - * - * @param source The metadata descriptor, whose content is published.
    - */ - public AsfTagCoverField(final MetadataDescriptor source) { - super(source); - - if (!source.getName().equals(AsfFieldKey.COVER_ART.getFieldName())) { - throw new IllegalArgumentException( - "Descriptor description must be WM/Picture"); - } - if (source.getType() != MetadataDescriptor.TYPE_BINARY) { - throw new IllegalArgumentException("Descriptor type must be binary"); - } - - try { - processRawContent(); - } catch (final UnsupportedEncodingException uee) { - // Should never happen - throw new RuntimeException(uee); // NOPMD by Christian Laireiter on 5/9/09 5:45 PM - } - } - - private byte[] createRawContent(final byte[] data, final int pictureType, - final String description, String mimeType) { // NOPMD by Christian Laireiter on 5/9/09 5:46 PM - this.description = description; - - // Get Mimetype from data if not already setField - if (mimeType == null) { - mimeType = ImageFormats.getMimeTypeForBinarySignature(data); - // Couldnt identify lets default to png because probably error in - // code because not 100% sure how to identify - // formats - if (mimeType == null) { - LOGGER.warning(ErrorMessage.GENERAL_UNIDENITIFED_IMAGE_FORMAT - .getMsg()); - mimeType = ImageFormats.MIME_TYPE_PNG; - } - } - - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - // PictureType - baos.write(pictureType); - - // ImageDataSize - baos.write(org.jaudiotagger.audio.generic.Utils - .getSizeLEInt32(data.length), 0, 4); - - // mimetype - byte[] mimeTypeData; - try { - mimeTypeData = mimeType.getBytes(AsfHeader.ASF_CHARSET.name()); - } catch (final UnsupportedEncodingException uee) { - // Should never happen - throw new RuntimeException("Unable to find encoding:" // NOPMD by Christian Laireiter on 5/9/09 5:45 PM - + AsfHeader.ASF_CHARSET.name()); - } - baos.write(mimeTypeData, 0, mimeTypeData.length); - - // Seperator - baos.write(0x00); - baos.write(0x00); - - // description - if (description != null && description.length() > 0) { - byte[] descriptionData; - try { - descriptionData = description.getBytes(AsfHeader.ASF_CHARSET - .name()); - } catch (final UnsupportedEncodingException uee) { - // Should never happen - throw new RuntimeException("Unable to find encoding:" // NOPMD by Christian Laireiter on 5/9/09 5:45 PM - + AsfHeader.ASF_CHARSET.name()); - } - baos.write(descriptionData, 0, descriptionData.length); - } - - // Seperator (always write whther or not we have descriptor field) - baos.write(0x00); - baos.write(0x00); - - // Image data - baos.write(data, 0, data.length); - - return baos.toByteArray(); - } - - public String getDescription() { - return this.description; - } - - @Override - public int getImageDataSize() { - return this.imageDataSize; - } - - public String getMimeType() { - return this.mimeType; - } - - public int getPictureType() { - return this.pictureType; - } - - /** - * @return the raw image data only - */ - @Override - public byte[] getRawImageData() { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(getRawContent(), this.endOfName, this.toWrap - .getRawDataSize() - - this.endOfName); - return baos.toByteArray(); - } - - private void processRawContent() throws UnsupportedEncodingException { - // PictureType - this.pictureType = this.getRawContent()[0]; - - // ImageDataSize - this.imageDataSize = org.jaudiotagger.audio.generic.Utils.getIntLE(this - .getRawContent(), 1, 2); - - // Set Count to after picture type,datasize and two byte nulls - int count = 5; - this.mimeType = null; - this.description = null; // Optional - int endOfMimeType = 0; - - while (count < this.getRawContent().length - 1) { - if (getRawContent()[count] == 0 && getRawContent()[count + 1] == 0) { - if (this.mimeType == null) { - this.mimeType = new String(getRawContent(), 5, (count) - 5, - "UTF-16LE"); - endOfMimeType = count + 2; - } else if (this.description == null) { - this.description = new String(getRawContent(), - endOfMimeType, count - endOfMimeType, "UTF-16LE"); - this.endOfName = count + 2; - break; - } - } - count += 2; // keep on two byte word boundary - } - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/AsfTagField.java b/src/main/java/org/jaudiotagger/tag/asf/AsfTagField.java deleted file mode 100644 index a72cbc7..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AsfTagField.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.MetadataDescriptor; -import org.jaudiotagger.tag.TagField; - -/** - * This class encapsulates a - * {@link org.jaudiotagger.audio.asf.data.MetadataDescriptor}and provides access - * to it.
    - * The metadata descriptor used for construction is copied. - * - * @author Christian Laireiter (liree) - */ -public class AsfTagField implements TagField, Cloneable { - - /** - * This descriptor is wrapped. - */ - protected MetadataDescriptor toWrap; - - /** - * Creates a tag field. - * - * @param field the ASF field that should be represented. - */ - public AsfTagField(final AsfFieldKey field) { - assert field != null; - this.toWrap = new MetadataDescriptor(field.getHighestContainer(), field - .getFieldName(), MetadataDescriptor.TYPE_STRING); - } - - /** - * Creates an instance. - * - * @param source The descriptor which should be represented as a - * {@link TagField}. - */ - public AsfTagField(final MetadataDescriptor source) { - assert source != null; - // XXX Copy ? maybe not really. - this.toWrap = source.createCopy(); - } - - /** - * Creates a tag field. - * - * @param fieldKey The field identifier to use. - */ - public AsfTagField(final String fieldKey) { - assert fieldKey != null; - this.toWrap = new MetadataDescriptor(AsfFieldKey.getAsfFieldKey( - fieldKey).getHighestContainer(), fieldKey, - MetadataDescriptor.TYPE_STRING); - } - - /** - * {@inheritDoc} - */ - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - /** - * {@inheritDoc} - */ - public void copyContent(final TagField field) { - throw new UnsupportedOperationException("Not implemented yet."); - } - - /** - * Returns the wrapped metadata descriptor (which actually stores the - * values). - * - * @return the wrapped metadata descriptor - */ - public MetadataDescriptor getDescriptor() { - return this.toWrap; - } - - /** - * {@inheritDoc} - */ - public String getId() { - return this.toWrap.getName(); - } - - /** - * {@inheritDoc} - */ - public byte[] getRawContent() { - return this.toWrap.getRawData(); - } - - /** - * {@inheritDoc} - */ - public boolean isBinary() { - return this.toWrap.getType() == MetadataDescriptor.TYPE_BINARY; - } - - /** - * {@inheritDoc} - */ - public void isBinary(final boolean value) { - if (!value && isBinary()) { - throw new UnsupportedOperationException("No conversion supported."); - } - this.toWrap.setBinaryValue(this.toWrap.getRawData()); - } - - /** - * {@inheritDoc} - */ - public boolean isCommon() { - // HashSet is safe against null comparison - return AsfTag.COMMON_FIELDS.contains(AsfFieldKey - .getAsfFieldKey(getId())); - } - - /** - * {@inheritDoc} - */ - public boolean isEmpty() { - return this.toWrap.isEmpty(); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return this.toWrap.getString(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/asf/AsfTagTextField.java b/src/main/java/org/jaudiotagger/tag/asf/AsfTagTextField.java deleted file mode 100644 index ecfb65e..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/AsfTagTextField.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.jaudiotagger.tag.asf; - -import org.jaudiotagger.audio.asf.data.AsfHeader; -import org.jaudiotagger.audio.asf.data.MetadataDescriptor; -import org.jaudiotagger.audio.asf.util.Utils; -import org.jaudiotagger.tag.TagTextField; - -/** - * Represents a tag text field for ASF fields.
    - * - * @author Christian Laireiter - */ -public class AsfTagTextField extends AsfTagField implements TagTextField { - - /** - * Creates a tag text field and assigns the string value. - * - * @param field ASF field to represent. - * @param value the value to assign. - */ - public AsfTagTextField(final AsfFieldKey field, final String value) { - super(field); - toWrap.setString(value); - } - - /** - * Creates an instance. - * - * @param source The metadata descriptor, whose content is published.
    - * Must not be of type {@link MetadataDescriptor#TYPE_BINARY}. - */ - public AsfTagTextField(final MetadataDescriptor source) { - super(source); - if (source.getType() == MetadataDescriptor.TYPE_BINARY) { - throw new IllegalArgumentException( - "Cannot interpret binary as string."); - } - } - - /** - * Creates a tag text field and assigns the string value. - * - * @param fieldKey The fields identifier. - * @param value the value to assign. - */ - public AsfTagTextField(final String fieldKey, final String value) { - super(fieldKey); - toWrap.setString(value); - } - - /** - * {@inheritDoc} - */ - public String getContent() { - return getDescriptor().getString(); - } - - /** - * {@inheritDoc} - */ - public void setContent(final String content) { - getDescriptor().setString(content); - } - - /** - * {@inheritDoc} - */ - public String getEncoding() { - return AsfHeader.ASF_CHARSET.name(); - } - - /** - * {@inheritDoc} - */ - public void setEncoding(final String encoding) { - if (!AsfHeader.ASF_CHARSET.name().equals(encoding)) { - throw new IllegalArgumentException( - "Only UTF-16LE is possible with ASF."); - } - } - - /** - * @return true if blank or only contains whitespace - */ - @Override - public boolean isEmpty() { - return Utils.isBlank(getContent()); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/asf/package.html b/src/main/java/org/jaudiotagger/tag/asf/package.html deleted file mode 100644 index fe81bbb..0000000 --- a/src/main/java/org/jaudiotagger/tag/asf/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Support for a pseudo-tag representing ASF metadata. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/datatype/AbstractDataType.java b/src/main/java/org/jaudiotagger/tag/datatype/AbstractDataType.java deleted file mode 100644 index 43e1429..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/AbstractDataType.java +++ /dev/null @@ -1,311 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractDataType.java 923 2010-10-16 21:59:49Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.util.Arrays; -import java.util.logging.Logger; - -/** - * Represents a field/data type that can be held within a frames body, these map loosely onto - * Section 4. ID3v2 frame overview at http://www.id3.org/id3v2.4.0-structure.txt - */ -public abstract class AbstractDataType { - protected static final String TYPE_ELEMENT = "element"; - - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.datatype"); - - /** - * Holds the data - */ - protected Object value = null; - - /** - * Holds the key such as "Text" or "PictureType", the naming of keys are fairly arbitary but are intended - * to make it easier to for the developer, the keys themseleves are not written to the tag. - */ - protected String identifier = ""; - - /** - * Holds the calling body, allows an datatype to query other objects in the - * body such as the Text Encoding of the frame - */ - protected AbstractTagFrameBody frameBody = null; - - /** - * Holds the size of the data in file when read/written - */ - protected int size; - - /** - * Construct an abstract datatype identified by identifier and linked to a framebody without setting - * an initial value. - * - * @param identifier to allow retrieval of this datatype by name from framebody - * @param frameBody that the dataype is associated with - */ - protected AbstractDataType(String identifier, AbstractTagFrameBody frameBody) { - this.identifier = identifier; - this.frameBody = frameBody; - } - - /** - * Construct an abstract datatype identified by identifier and linked to a framebody initilised with a value - * - * @param identifier to allow retrieval of this datatype by name from framebody - * @param frameBody that the dataype is associated with - * @param value of this DataType - */ - protected AbstractDataType(String identifier, AbstractTagFrameBody frameBody, Object value) { - this.identifier = identifier; - this.frameBody = frameBody; - setValue(value); - } - - /** - * This is used by subclasses, to clone the data within the copyObject - *

    - * TODO:It seems to be missing some of the more complex value types. - * - * @param copyObject - */ - public AbstractDataType(AbstractDataType copyObject) { - // no copy constructor in super class - this.identifier = copyObject.identifier; - if (copyObject.value == null) { - this.value = null; - } else if (copyObject.value instanceof String) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Boolean) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Byte) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Character) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Double) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Float) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Integer) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Long) { - this.value = copyObject.value; - } else if (copyObject.value instanceof Short) { - this.value = copyObject.value; - } else if (copyObject.value instanceof MultipleTextEncodedStringNullTerminated.Values) { - this.value = copyObject.value; - } else if (copyObject.value instanceof PairedTextEncodedStringNullTerminated.ValuePairs) { - this.value = copyObject.value; - } else if (copyObject.value instanceof PartOfSet.PartOfSetValue) { - this.value = copyObject.value; - } else if (copyObject.value instanceof boolean[]) { - this.value = ((boolean[]) copyObject.value).clone(); - } else if (copyObject.value instanceof byte[]) { - this.value = ((byte[]) copyObject.value).clone(); - } else if (copyObject.value instanceof char[]) { - this.value = ((char[]) copyObject.value).clone(); - } else if (copyObject.value instanceof double[]) { - this.value = ((double[]) copyObject.value).clone(); - } else if (copyObject.value instanceof float[]) { - this.value = ((float[]) copyObject.value).clone(); - } else if (copyObject.value instanceof int[]) { - this.value = ((int[]) copyObject.value).clone(); - } else if (copyObject.value instanceof long[]) { - this.value = ((long[]) copyObject.value).clone(); - } else if (copyObject.value instanceof short[]) { - this.value = ((short[]) copyObject.value).clone(); - } else if (copyObject.value instanceof Object[]) { - this.value = ((Object[]) copyObject.value).clone(); - } else { - throw new UnsupportedOperationException("Unable to create copy of class " + copyObject.getClass()); - } - } - - /** - * Get the framebody associated with this datatype - * - * @return the framebody that this datatype is associated with - */ - public AbstractTagFrameBody getBody() { - return frameBody; - } - - /** - * Set the framebody that this datatype is associated with - * - * @param frameBody - */ - public void setBody(AbstractTagFrameBody frameBody) { - this.frameBody = frameBody; - } - - /** - * Return the key as declared by the frame bodies datatype list - * - * @return the key used to reference this datatype from a framebody - */ - public String getIdentifier() { - return identifier; - } - - /** - * Get value held by this Object - * - * @return value held by this Object - */ - public Object getValue() { - return value; - } - - /** - * Set the value held by this datatype, this is used typically used when the - * user wants to modify the value in an existing frame. - * - * @param value - */ - public void setValue(Object value) { - this.value = value; - } - - /** - * Simplified wrapper for reading bytes from file into Object. - * Used for reading Strings, this class should be overridden - * for non String Objects - * - * @param arr - * @throws org.jaudiotagger.tag.InvalidDataTypeException - */ - final public void readByteArray(byte[] arr) throws InvalidDataTypeException { - readByteArray(arr, 0); - } - - /** - * This defines the size in bytes of the datatype being - * held when read/written to file. - * - * @return the size in bytes of the datatype - */ - abstract public int getSize(); - - /** - * @param obj - * @return whether this and obj are deemed equivalent - */ - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (!(obj instanceof AbstractDataType)) { - return false; - } - AbstractDataType object = (AbstractDataType) obj; - if (!this.identifier.equals(object.identifier)) { - return false; - } - if ((this.value == null) && (object.value == null)) { - return true; - } else if ((this.value == null) || (object.value == null)) { - return false; - } - // boolean[] - if (this.value instanceof boolean[] && object.value instanceof boolean[]) { - if (!Arrays.equals((boolean[]) this.value, (boolean[]) object.value)) { - return false; - } - // byte[] - } else if (this.value instanceof byte[] && object.value instanceof byte[]) { - if (!Arrays.equals((byte[]) this.value, (byte[]) object.value)) { - return false; - } - // char[] - } else if (this.value instanceof char[] && object.value instanceof char[]) { - if (!Arrays.equals((char[]) this.value, (char[]) object.value)) { - return false; - } - // double[] - } else if (this.value instanceof double[] && object.value instanceof double[]) { - if (!Arrays.equals((double[]) this.value, (double[]) object.value)) { - return false; - } - // float[] - } else if (this.value instanceof float[] && object.value instanceof float[]) { - if (!Arrays.equals((float[]) this.value, (float[]) object.value)) { - return false; - } - // int[] - } else if (this.value instanceof int[] && object.value instanceof int[]) { - if (!Arrays.equals((int[]) this.value, (int[]) object.value)) { - return false; - } - // long[] - } else if (this.value instanceof long[] && object.value instanceof long[]) { - if (!Arrays.equals((long[]) this.value, (long[]) object.value)) { - return false; - } - // Object[] - } else if (this.value instanceof Object[] && object.value instanceof Object[]) { - if (!Arrays.equals((Object[]) this.value, (Object[]) object.value)) { - return false; - } - // short[] - } else if (this.value instanceof short[] && object.value instanceof short[]) { - if (!Arrays.equals((short[]) this.value, (short[]) object.value)) { - return false; - } - } else if (!this.value.equals(object.value)) { - return false; - } - return true; - } - - /** - * This is the starting point for reading bytes from the file into the ID3 datatype - * starting at offset. - * This class must be overridden - * - * @param arr - * @param offset - * @throws org.jaudiotagger.tag.InvalidDataTypeException - */ - public abstract void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException; - - - /** - * Starting point write ID3 Datatype back to array of bytes. - * This class must be overridden. - * - * @return the array of bytes representing this datatype that should be written to file - */ - public abstract byte[] writeByteArray(); - - /** - * Return String Representation of Datatype * - */ - public void createStructure() { - MP3File.getStructureFormatter().addElement(identifier, getValue().toString()); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/AbstractIntStringValuePair.java b/src/main/java/org/jaudiotagger/tag/datatype/AbstractIntStringValuePair.java deleted file mode 100644 index e765da4..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/AbstractIntStringValuePair.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: AbstractIntStringValuePair.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import java.util.Collections; -import java.util.Map; - -/** - * A two way mapping between an Integral Id and a String value - */ -public class AbstractIntStringValuePair extends AbstractValuePair { - protected Integer key = null; - - /** - * Get Id for Value - * - * @param value - * @return - */ - public Integer getIdForValue(String value) { - return valueToId.get(value); - } - - /** - * Get value for Id - * - * @param id - * @return - */ - public String getValueForId(int id) { - return idToValue.get(id); - } - - protected void createMaps() { - //Create the reverse the map - for (Map.Entry entry : idToValue.entrySet()) { - valueToId.put(entry.getValue(), entry.getKey()); - } - - //Value List sort alphabetically - valueList.addAll(idToValue.values()); - Collections.sort(valueList); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/AbstractString.java b/src/main/java/org/jaudiotagger/tag/datatype/AbstractString.java deleted file mode 100644 index 470f1e3..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/AbstractString.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractString.java 899 2010-04-19 14:32:20Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; - -/** - * A partial implementation for String based ID3 fields - */ -public abstract class AbstractString extends AbstractDataType { - /** - * Creates a new datatype - * - * @param identifier - * @param frameBody - */ - protected AbstractString(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - /** - * Creates a new datatype, with value - * - * @param identifier - * @param frameBody - * @param value - */ - public AbstractString(String identifier, AbstractTagFrameBody frameBody, String value) { - super(identifier, frameBody, value); - } - - /** - * Copy constructor - * - * @param object - */ - protected AbstractString(AbstractString object) { - super(object); - } - - /** - * Return the size in bytes of this datatype as it was/is held in file this - * will be effected by the encoding type. - * - * @return the size - */ - public int getSize() { - return size; - } - - /** - * Sets the size in bytes of this data type. - * This is set after writing the data to allow us to recalculate the size for - * frame header. - * - * @param size - */ - protected void setSize(int size) { - this.size = size; - } - - /** - * Return String representation of data type - * - * @return a string representation of the value - */ - public String toString() { - return (String) value; - } - - /** - * Check the value can be encoded with the specified encoding - * - * @return - */ - public boolean canBeEncoded() { - //Try and write to buffer using the CharSet defined by the textEncoding field (note if using UTF16 we dont - //need to worry about LE,BE at this point it makes no difference) - byte textEncoding = this.getBody().getTextEncoding(); - String charSetName = TextEncoding.getInstanceOf().getValueForId(textEncoding); - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - - if (encoder.canEncode((String) value)) { - return true; - } else { - logger.finest("Failed Trying to decode" + value + "with" + encoder.toString()); - return false; - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java b/src/main/java/org/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java deleted file mode 100644 index 83b5d5f..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: AbstractStringStringValuePair.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import java.util.Collections; - -public class AbstractStringStringValuePair extends AbstractValuePair { - protected String lkey = null; - - /** - * Get Id for Value - * - * @param value - * @return - */ - public String getIdForValue(String value) { - return valueToId.get(value); - } - - /** - * Get value for Id - * - * @param id - * @return - */ - public String getValueForId(String id) { - return idToValue.get(id); - } - - protected void createMaps() { - iterator = idToValue.keySet().iterator(); - while (iterator.hasNext()) { - lkey = iterator.next(); - value = idToValue.get(lkey); - valueToId.put(value, lkey); - } - - //Value List - iterator = idToValue.keySet().iterator(); - while (iterator.hasNext()) { - valueList.add(idToValue.get(iterator.next())); - } - //Sort alphabetically - Collections.sort(valueList); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/AbstractValuePair.java b/src/main/java/org/jaudiotagger/tag/datatype/AbstractValuePair.java deleted file mode 100644 index d629770..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/AbstractValuePair.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: AbstractValuePair.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import java.util.*; - -/** - * A two way mapping between an id and a value - */ -public abstract class AbstractValuePair { - protected final Map idToValue = new LinkedHashMap(); - protected final Map valueToId = new LinkedHashMap(); - protected final List valueList = new ArrayList(); - - protected Iterator iterator = idToValue.keySet().iterator(); - - protected String value; - - /** - * Get list in alphabetical order - * - * @return - */ - public List getAlphabeticalValueList() { - return valueList; - } - - public Map getIdToValueMap() { - return idToValue; - } - - public Map getValueToIdMap() { - return valueToId; - } - - /** - * @return the number of elements in the mapping - */ - public int getSize() { - return valueList.size(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/BooleanByte.java b/src/main/java/org/jaudiotagger/tag/datatype/BooleanByte.java deleted file mode 100644 index 843b254..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/BooleanByte.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: BooleanByte.java 920 2010-10-04 13:47:19Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -/** - * Represents a bit flag within a byte - */ -public class BooleanByte extends AbstractDataType { - /** - * - */ - int bitPosition = -1; - - /** - * Creates a new ObjectBooleanByte datatype. - * - * @param identifier - * @param frameBody - * @param bitPosition - * @throws IndexOutOfBoundsException - */ - public BooleanByte(String identifier, AbstractTagFrameBody frameBody, int bitPosition) { - super(identifier, frameBody); - if ((bitPosition < 0) || (bitPosition > 7)) { - throw new IndexOutOfBoundsException("Bit position needs to be from 0 - 7 : " + bitPosition); - } - - this.bitPosition = bitPosition; - } - - public BooleanByte(BooleanByte copy) { - super(copy); - this.bitPosition = copy.bitPosition; - } - - /** - * @return - */ - public int getBitPosition() { - return bitPosition; - } - - /** - * @return - */ - public int getSize() { - return 1; - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof BooleanByte)) { - return false; - } - - BooleanByte object = (BooleanByte) obj; - - return this.bitPosition == object.bitPosition && super.equals(obj); - - } - - /** - * @param arr - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - if (arr == null) { - throw new NullPointerException("Byte array is null"); - } - - if ((offset < 0) || (offset >= arr.length)) { - throw new IndexOutOfBoundsException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length); - } - - byte newValue = arr[offset]; - - newValue >>= bitPosition; - newValue &= 0x1; - this.value = newValue == 1; - } - - /** - * @return - */ - public String toString() { - return "" + value; - } - - /** - * @return - */ - public byte[] writeByteArray() { - byte[] retValue; - - retValue = new byte[1]; - - if (value != null) { - retValue[0] = (byte) ((Boolean) value ? 1 : 0); - retValue[0] <<= bitPosition; - } - - return retValue; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/BooleanString.java b/src/main/java/org/jaudiotagger/tag/datatype/BooleanString.java deleted file mode 100644 index d6937cf..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/BooleanString.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: BooleanString.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -public class BooleanString extends AbstractDataType { - /** - * Creates a new ObjectBooleanString datatype. - * - * @param identifier - * @param frameBody - */ - public BooleanString(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public BooleanString(BooleanString object) { - super(object); - } - - /** - * @return - */ - public int getSize() { - return 1; - } - - public boolean equals(Object obj) { - return obj instanceof BooleanString && super.equals(obj); - - } - - /** - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - byte b = arr[offset]; - value = b != '0'; - } - - /** - * @return - */ - public String toString() { - return "" + value; - } - - /** - * @return - */ - public byte[] writeByteArray() { - byte[] booleanValue = new byte[1]; - if (value == null) { - booleanValue[0] = '0'; - } else { - if ((Boolean) value) { - booleanValue[0] = '0'; - } else { - booleanValue[0] = '1'; - } - } - return booleanValue; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java deleted file mode 100644 index 454e849..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: ByteArraySizeTerminated.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -/** - * Represents a stream of bytes, continuing until the end of the buffer. Usually used for binary data or where - * we havent yet mapped the data to a better fitting type. - */ -public class ByteArraySizeTerminated extends AbstractDataType { - public ByteArraySizeTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public ByteArraySizeTerminated(ByteArraySizeTerminated object) { - super(object); - } - - /** - * Return the size in byte of this datatype - * - * @return the size in bytes - */ - public int getSize() { - int len = 0; - - if (value != null) { - len = ((byte[]) value).length; - } - - return len; - } - - public boolean equals(Object obj) { - return obj instanceof ByteArraySizeTerminated && super.equals(obj); - - } - - /** - * @param arr - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - if (arr == null) { - throw new NullPointerException("Byte array is null"); - } - - if (offset < 0) { - throw new IndexOutOfBoundsException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length); - } - - //Empty Byte Array - if (offset >= arr.length) { - value = null; - return; - } - - int len = arr.length - offset; - value = new byte[len]; - System.arraycopy(arr, offset, value, 0, len); - } - - /** - * Because this is usually binary data and could be very long we just return - * the number of bytes held - * - * @return the number of bytes - */ - public String toString() { - return getSize() + " bytes"; - } - - /** - * Write contents to a byte array - * - * @return a byte array that that contians the data that should be perisisted to file - */ - public byte[] writeByteArray() { - logger.config("Writing byte array" + this.getIdentifier()); - return (byte[]) value; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/DataTypes.java b/src/main/java/org/jaudiotagger/tag/datatype/DataTypes.java deleted file mode 100644 index d90599e..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/DataTypes.java +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: DataTypes.java 520 2008-01-01 15:16:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Object Types,all types used by the various frame bodies and associated objects are defined here - * this works better than putting them with their associated bodies because bodies dont all fall - * the neccessary hierachy, and values are also required in some Objects (which were previously - * defined seperately). - *

    - * Warning:Values should not be seperated by space as this will break XML display of tag. - */ -package org.jaudiotagger.tag.datatype; - - -public class DataTypes { - /** - * Represents a text encoding, now only IDv2Frames not Lyrics3 tags use - * text encoding objects but both use Object Strings and these check - * for a text encoding. The method below returns a default if one not set. - */ - public static final String OBJ_TEXT_ENCODING = "TextEncoding"; - //Reference to datatype holding the main textual data - public static final String OBJ_TEXT = "Text"; - //Reference to datatype holding non textual textual data - public static final String OBJ_DATA = "Data"; - //Reference to datatype holding a description of the textual data - public static final String OBJ_DESCRIPTION = "Description"; - //Reference to datatype holding reference to owner of frame. - public static final String OBJ_OWNER = "Owner"; - //Reference to datatype holding a number - public static final String OBJ_NUMBER = "Number"; - //Reference to timestamps - public static final String OBJ_DATETIME = "DateTime"; - /** - * - */ - public static final String OBJ_GENRE = "Genre"; - /** - * - */ - public static final String OBJ_ID3V2_FRAME_DESCRIPTION = "ID3v2FrameDescription"; - /** - * - */ - public static final String OBJ_TYPE_OF_EVENT = "TypeOfEvent"; - /** - * - */ - public static final String OBJ_TIME_STAMP_FORMAT = "TimeStampFormat"; - /** - * - */ - public static final String OBJ_TYPE_OF_CHANNEL = "TypeOfChannel"; - /** - * - */ - public static final String OBJ_RECIEVED_AS = "RecievedAs"; - - //APIC Frame - public static final String OBJ_PICTURE_TYPE = "PictureType"; - public static final String OBJ_PICTURE_DATA = "PictureData"; - public static final String OBJ_MIME_TYPE = "MIMEType"; - public static final String OBJ_IMAGE_FORMAT = "ImageType"; - - //AENC Frame - public static final String OBJ_PREVIEW_START = "PreviewStart"; - public static final String OBJ_PREVIEW_LENGTH = "PreviewLength"; - public static final String OBJ_ENCRYPTION_INFO = "EncryptionInfo"; - - //COMR Frame - public static final String OBJ_PRICE_STRING = "PriceString"; - public static final String OBJ_VALID_UNTIL = "ValidUntil"; - public static final String OBJ_CONTACT_URL = "ContactURL"; - public static final String OBJ_SELLER_NAME = "SellerName"; - public static final String OBJ_SELLER_LOGO = "SellerLogo"; - - //CRM Frame - public static final String OBJ_ENCRYPTED_DATABLOCK = "EncryptedDataBlock"; - - //ENCR Frame - public static final String OBJ_METHOD_SYMBOL = "MethodSymbol"; - - //EQU2 Frame - public static final String OBJ_FREQUENCY = "Frequency"; - public static final String OBJ_VOLUME_ADJUSTMENT = "Volume Adjustment"; - public static final String OBJ_INTERPOLATION_METHOD = "InterpolationMethod"; - - public static final String OBJ_FILENAME = "Filename"; - - //GRID Frame - public static final String OBJ_GROUP_SYMBOL = "GroupSymbol"; - public static final String OBJ_GROUP_DATA = "GroupData"; - - //LINK Frame - public static final String OBJ_URL = "URL"; - public static final String OBJ_ID = "ID"; - - //OWNE Frame - public static final String OBJ_PRICE_PAID = "PricePaid"; - public static final String OBJ_PURCHASE_DATE = "PurchaseDate"; - - //POPM Frame - public static final String OBJ_EMAIL = "Email"; - public static final String OBJ_RATING = "Rating"; - public static final String OBJ_COUNTER = "Counter"; - - //POSS Frame - public static final String OBJ_POSITION = "Position"; - - //RBUF Frame - public static final String OBJ_BUFFER_SIZE = "BufferSize"; - public static final String OBJ_EMBED_FLAG = "EmbedFlag"; - public static final String OBJ_OFFSET = "Offset"; - - //RVRB Frame - public static final String OBJ_REVERB_LEFT = "ReverbLeft"; - public static final String OBJ_REVERB_RIGHT = "ReverbRight"; - public static final String OBJ_REVERB_BOUNCE_LEFT = "ReverbBounceLeft"; - public static final String OBJ_REVERB_BOUNCE_RIGHT = "ReverbBounceRight"; - public static final String OBJ_REVERB_FEEDBACK_LEFT_TO_LEFT = "ReverbFeedbackLeftToLeft"; - public static final String OBJ_REVERB_FEEDBACK_LEFT_TO_RIGHT = "ReverbFeedbackLeftToRight"; - public static final String OBJ_REVERB_FEEDBACK_RIGHT_TO_RIGHT = "ReverbFeedbackRightToRight"; - public static final String OBJ_REVERB_FEEDBACK_RIGHT_TO_LEFT = "ReverbFeedbackRightToLeft"; - public static final String OBJ_PREMIX_LEFT_TO_RIGHT = "PremixLeftToRight"; - public static final String OBJ_PREMIX_RIGHT_TO_LEFT = "PremixRightToLeft"; - - //SIGN Frame - public static final String OBJ_SIGNATURE = "Signature"; - - //SYLT Frame - public static final String OBJ_CONTENT_TYPE = "contentType"; - - //ULST Frame - public static final String OBJ_LANGUAGE = "Language"; - public static final String OBJ_LYRICS = "Lyrics"; - public static final String OBJ_URLLINK = "URLLink"; - - //CHAP Frame - public static final String OBJ_ELEMENT_ID = "ElementID"; - public static final String OBJ_START_TIME = "StartTime"; - public static final String OBJ_END_TIME = "EndTime"; - public static final String OBJ_START_OFFSET = "StartOffset"; - public static final String OBJ_END_OFFSET = "EndOffset"; - - //CTOC Frame -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/HashMapInterface.java b/src/main/java/org/jaudiotagger/tag/datatype/HashMapInterface.java deleted file mode 100644 index f5e639c..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/HashMapInterface.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: HashMapInterface.java 625 2008-07-21 10:49:58Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * A simple Interface required by classes which use a HashMap to Store ValuePairs - */ - -package org.jaudiotagger.tag.datatype; - -import java.util.Iterator; -import java.util.Map; - -/** - * Represents an interface allowing maping from key to value and value to key - */ -public interface HashMapInterface { - /** - * @return a mapping between the key within the frame and the value - */ - Map getKeyToValue(); - - /** - * @return a mapping between the value to the key within the frame - */ - Map getValueToKey(); - - /** - * @return an interator of the values within the map - */ - Iterator iterator(); -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/ID3v2LyricLine.java b/src/main/java/org/jaudiotagger/tag/datatype/ID3v2LyricLine.java deleted file mode 100644 index af248cc..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/ID3v2LyricLine.java +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: ID3v2LyricLine.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -public class ID3v2LyricLine extends AbstractDataType { - /** - * - */ - String text = ""; - - /** - * - */ - long timeStamp = 0; - - public ID3v2LyricLine(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public ID3v2LyricLine(ID3v2LyricLine copy) { - super(copy); - this.text = copy.text; - this.timeStamp = copy.timeStamp; - } - - /** - * @return - */ - public int getSize() { - return text.length() + 1 + 4; - } - - /** - * @return - */ - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - /** - * @return - */ - public long getTimeStamp() { - return timeStamp; - } - - public void setTimeStamp(long timeStamp) { - this.timeStamp = timeStamp; - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof ID3v2LyricLine)) { - return false; - } - - ID3v2LyricLine object = (ID3v2LyricLine) obj; - - if (!this.text.equals(object.text)) { - return false; - } - - return this.timeStamp == object.timeStamp && super.equals(obj); - - } - - /** - * @param arr - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - if (arr == null) { - throw new NullPointerException("Byte array is null"); - } - - if ((offset < 0) || (offset >= arr.length)) { - throw new IndexOutOfBoundsException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length); - } - - //offset += (); - text = Utils.getString(arr, offset, arr.length - offset - 4, "ISO-8859-1"); - - //text = text.substring(0, text.length() - 5); - timeStamp = 0; - - for (int i = arr.length - 4; i < arr.length; i++) { - timeStamp <<= 8; - timeStamp += arr[i]; - } - } - - /** - * @return - */ - public String toString() { - return timeStamp + " " + text; - } - - /** - * @return - */ - public byte[] writeByteArray() { - int i; - byte[] arr = new byte[getSize()]; - - for (i = 0; i < text.length(); i++) { - arr[i] = (byte) text.charAt(i); - } - - arr[i++] = 0; - arr[i++] = (byte) ((timeStamp & 0xFF000000) >> 24); - arr[i++] = (byte) ((timeStamp & 0x00FF0000) >> 16); - arr[i++] = (byte) ((timeStamp & 0x0000FF00) >> 8); - arr[i++] = (byte) (timeStamp & 0x000000FF); - - return arr; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3Image.java b/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3Image.java deleted file mode 100644 index 400cd08..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3Image.java +++ /dev/null @@ -1,234 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3Image.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -public class Lyrics3Image extends AbstractDataType { - /** - * - */ - private Lyrics3TimeStamp time = null; - - /** - * - */ - private String description = ""; - - /** - * - */ - private String filename = ""; - - /** - * Creates a new ObjectLyrics3Image datatype. - * - * @param identifier - * @param frameBody - */ - public Lyrics3Image(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public Lyrics3Image(Lyrics3Image copy) { - super(copy); - this.time = new Lyrics3TimeStamp(copy.time); - this.description = copy.description; - this.filename = copy.filename; - } - - /** - * @return - */ - public String getDescription() { - return this.description; - } - - /** - * @param description - */ - public void setDescription(String description) { - this.description = description; - } - - /** - * @return - */ - public String getFilename() { - return this.filename; - } - - /** - * @param filename - */ - public void setFilename(String filename) { - this.filename = filename; - } - - /** - * @return - */ - public int getSize() { - int size; - - size = filename.length() + 2 + description.length() + 2; - - if (time != null) { - size += time.getSize(); - } - - return size; - } - - /** - * @return - */ - public Lyrics3TimeStamp getTimeStamp() { - return this.time; - } - - /** - * @param time - */ - public void setTimeStamp(Lyrics3TimeStamp time) { - this.time = time; - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof Lyrics3Image)) { - return false; - } - - Lyrics3Image object = (Lyrics3Image) obj; - - if (!this.description.equals(object.description)) { - return false; - } - - if (!this.filename.equals(object.filename)) { - return false; - } - - if (this.time == null) { - if (object.time != null) { - return false; - } - } else { - if (!this.time.equals(object.time)) { - return false; - } - } - - return super.equals(obj); - } - - /** - * @param imageString - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readString(String imageString, int offset) { - if (imageString == null) { - throw new NullPointerException("Image string is null"); - } - - if ((offset < 0) || (offset >= imageString.length())) { - throw new IndexOutOfBoundsException("Offset to image string is out of bounds: offset = " + offset + ", string.length()" + imageString.length()); - } - - if (imageString != null) { - String timestamp; - int delim; - - delim = imageString.indexOf("||", offset); - filename = imageString.substring(offset, delim); - - offset = delim + 2; - delim = imageString.indexOf("||", offset); - description = imageString.substring(offset, delim); - - offset = delim + 2; - timestamp = imageString.substring(offset); - - if (timestamp.length() == 7) { - time = new Lyrics3TimeStamp("Time Stamp"); - time.readString(timestamp); - } - } - } - - /** - * @return - */ - public String toString() { - String str; - str = "filename = " + filename + ", description = " + description; - - if (time != null) { - str += (", timestamp = " + time.toString()); - } - - return str + "\n"; - } - - /** - * @return - */ - public String writeString() { - String str; - - if (filename == null) { - str = "||"; - } else { - str = filename + "||"; - } - - if (description == null) { - str += "||"; - } else { - str += (description + "||"); - } - - if (time != null) { - str += time.writeString(); - } - - return str; - } - - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - readString(arr.toString(), offset); - } - - public byte[] writeByteArray() { - return Utils.getDefaultBytes(writeString(), "ISO-8859-1"); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3Line.java b/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3Line.java deleted file mode 100644 index 2173b1d..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3Line.java +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3Line.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.util.Iterator; -import java.util.LinkedList; - -public class Lyrics3Line extends AbstractDataType { - /** - * - */ - private LinkedList timeStamp = new LinkedList(); - - /** - * - */ - private String lyric = ""; - - /** - * Creates a new ObjectLyrics3Line datatype. - * - * @param identifier - * @param frameBody - */ - public Lyrics3Line(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public Lyrics3Line(Lyrics3Line copy) { - super(copy); - this.lyric = copy.lyric; - Lyrics3TimeStamp newTimeStamp; - for (int i = 0; i < copy.timeStamp.size(); i++) { - newTimeStamp = new Lyrics3TimeStamp(copy.timeStamp.get(i)); - this.timeStamp.add(newTimeStamp); - } - } - - public void setLyric(String lyric) { - this.lyric = lyric; - } - - /** - * @return - */ - public String getLyric() { - return lyric; - } - - public void setLyric(ID3v2LyricLine line) { - this.lyric = line.getText(); - } - - /** - * @return - */ - public int getSize() { - int size = 0; - for (Object aTimeStamp : timeStamp) { - size += ((Lyrics3TimeStamp) aTimeStamp).getSize(); - } - return size + lyric.length(); - } - - /** - * @return - */ - public Iterator getTimeStamp() { - return timeStamp.iterator(); - } - - /** - * @param time - */ - public void setTimeStamp(Lyrics3TimeStamp time) { - timeStamp.clear(); - timeStamp.add(time); - } - - public void addLyric(String newLyric) { - this.lyric += newLyric; - } - - public void addLyric(ID3v2LyricLine line) { - this.lyric += line.getText(); - } - - /** - * @param time - */ - public void addTimeStamp(Lyrics3TimeStamp time) { - timeStamp.add(time); - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof Lyrics3Line)) { - return false; - } - Lyrics3Line object = (Lyrics3Line) obj; - if (!this.lyric.equals(object.lyric)) { - return false; - } - return this.timeStamp.equals(object.timeStamp) && super.equals(obj); - } - - /** - * @return - */ - public boolean hasTimeStamp() { - return !timeStamp.isEmpty(); - } - - /** - * @param lineString - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readString(String lineString, int offset) { - if (lineString == null) { - throw new NullPointerException("Image is null"); - } - if ((offset < 0) || (offset >= lineString.length())) { - throw new IndexOutOfBoundsException("Offset to line is out of bounds: offset = " + offset + ", line.length()" + lineString.length()); - } - int delim; - Lyrics3TimeStamp time; - timeStamp = new LinkedList(); - delim = lineString.indexOf("[", offset); - while (delim >= 0) { - offset = lineString.indexOf("]", delim) + 1; - time = new Lyrics3TimeStamp("Time Stamp"); - time.readString(lineString.substring(delim, offset)); - timeStamp.add(time); - delim = lineString.indexOf("[", offset); - } - lyric = lineString.substring(offset); - } - - /** - * @return - */ - public String toString() { - String str = ""; - for (Object aTimeStamp : timeStamp) { - str += aTimeStamp.toString(); - } - return "timeStamp = " + str + ", lyric = " + lyric + "\n"; - } - - /** - * @return - */ - public String writeString() { - String str = ""; - Lyrics3TimeStamp time; - for (Object aTimeStamp : timeStamp) { - time = (Lyrics3TimeStamp) aTimeStamp; - str += time.writeString(); - } - return str + lyric; - } - - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - readString(arr.toString(), offset); - } - - public byte[] writeByteArray() { - return Utils.getDefaultBytes(writeString(), "ISO8859-1"); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java b/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java deleted file mode 100644 index 402aa72..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java +++ /dev/null @@ -1,206 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3TimeStamp.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -public class Lyrics3TimeStamp extends AbstractDataType { - /** - * - */ - private long minute = 0; - - /** - * - */ - private long second = 0; - - /** - * Creates a new ObjectLyrics3TimeStamp datatype. - * - * @param identifier - * @param frameBody - */ - public Lyrics3TimeStamp(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public Lyrics3TimeStamp(String identifier) { - super(identifier, null); - } - - public Lyrics3TimeStamp(Lyrics3TimeStamp copy) { - super(copy); - this.minute = copy.minute; - this.second = copy.second; - } - - /** - * Todo this is wrong - * - * @param s - */ - public void readString(String s) { - } - - /** - * @return - */ - public long getMinute() { - return minute; - } - - public void setMinute(long minute) { - this.minute = minute; - } - - /** - * @return - */ - public long getSecond() { - return second; - } - - public void setSecond(long second) { - this.second = second; - } - - /** - * @return - */ - public int getSize() { - return 7; - } - - /** - * Creates a new ObjectLyrics3TimeStamp datatype. - * - * @param timeStamp - * @param timeStampFormat - */ - public void setTimeStamp(long timeStamp, byte timeStampFormat) { - /** - * @todo convert both types of formats - */ - timeStamp = timeStamp / 1000; - minute = timeStamp / 60; - second = timeStamp % 60; - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof Lyrics3TimeStamp)) { - return false; - } - - Lyrics3TimeStamp object = (Lyrics3TimeStamp) obj; - - if (this.minute != object.minute) { - return false; - } - - return this.second == object.second && super.equals(obj); - - } - - /** - * @param timeStamp - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readString(String timeStamp, int offset) { - if (timeStamp == null) { - throw new NullPointerException("Image is null"); - } - - if ((offset < 0) || (offset >= timeStamp.length())) { - throw new IndexOutOfBoundsException("Offset to timeStamp is out of bounds: offset = " + offset + ", timeStamp.length()" + timeStamp.length()); - } - - timeStamp = timeStamp.substring(offset); - - if (timeStamp.length() == 7) { - minute = Integer.parseInt(timeStamp.substring(1, 3)); - second = Integer.parseInt(timeStamp.substring(4, 6)); - } else { - minute = 0; - second = 0; - } - } - - /** - * @return - */ - public String toString() { - return writeString(); - } - - /** - * @return - */ - public String writeString() { - String str; - str = "["; - - if (minute < 0) { - str += "00"; - } else { - if (minute < 10) { - str += '0'; - } - - str += Long.toString(minute); - } - - str += ':'; - - if (second < 0) { - str += "00"; - } else { - if (second < 10) { - str += '0'; - } - - str += Long.toString(second); - } - - str += ']'; - - return str; - } - - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - readString(arr.toString(), offset); - } - - public byte[] writeByteArray() { - return Utils.getDefaultBytes(writeString(), "ISO8859-1"); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java deleted file mode 100644 index f9f6169..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; -import java.util.logging.Level; - -/** - * Represents a data type that supports multiple terminated Strings (there may only be one) - */ -public class MultipleTextEncodedStringNullTerminated extends AbstractDataType { - - /** - * Creates a new ObjectStringSizeTerminated datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public MultipleTextEncodedStringNullTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - value = new MultipleTextEncodedStringNullTerminated.Values(); - } - - public MultipleTextEncodedStringNullTerminated(TextEncodedStringSizeTerminated object) { - super(object); - value = new MultipleTextEncodedStringNullTerminated.Values(); - } - - public MultipleTextEncodedStringNullTerminated(MultipleTextEncodedStringNullTerminated object) { - super(object); - } - - public boolean equals(Object obj) { - return obj instanceof MultipleTextEncodedStringNullTerminated && super.equals(obj); - } - - /** - * Returns the size in bytes of this datatype when written to file - * - * @return size of this datatype - */ - public int getSize() { - return size; - } - - /** - * Check the value can be encoded with the specified encoding - * - * @return - */ - public boolean canBeEncoded() { - for (ListIterator li = ((Values) value).getList().listIterator(); li.hasNext(); ) { - TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, li.next()); - if (!next.canBeEncoded()) { - return false; - } - } - return true; - } - - /** - * Read Null Terminated Strings from the array starting at offset, continue until unable to find any null terminated - * Strings or until reached the end of the array. The offset should be set to byte after the last null terminated - * String found. - * - * @param arr to read the Strings from - * @param offset in the array to start reading from - * @throws InvalidDataTypeException if unable to find any null terminated Strings - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - logger.finer("Reading MultipleTextEncodedStringNullTerminated from array from offset:" + offset); - //Continue until unable to read a null terminated String - while (true) { - try { - //Read String - TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody); - next.readByteArray(arr, offset); - - if (next.getSize() == 0) { - break; - } else { - //Add to value - ((Values) value).add((String) next.getValue()); - - //Add to size calculation - size += next.getSize(); - - //Increment Offset to start of next datatype. - offset += next.getSize(); - } - } catch (InvalidDataTypeException idte) { - break; - } - - if (size == 0) { - logger.warning("No null terminated Strings found"); - throw new InvalidDataTypeException("No null terminated Strings found"); - } - } - logger.finer("Read MultipleTextEncodedStringNullTerminated:" + value + " size:" + size); - } - - /** - * For every String write to bytebuffer - * - * @return bytebuffer that should be written to file to persist this datatype. - */ - public byte[] writeByteArray() { - logger.finer("Writing MultipleTextEncodedStringNullTerminated"); - - int localSize = 0; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - try { - for (ListIterator li = ((Values) value).getList().listIterator(); li.hasNext(); ) { - TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, li.next()); - buffer.write(next.writeByteArray()); - localSize += next.getSize(); - } - } catch (IOException ioe) { - //This should never happen because the write is internal with the JVM it is not to a file - logger.log(Level.SEVERE, "IOException in MultipleTextEncodedStringNullTerminated when writing byte array", ioe); - throw new RuntimeException(ioe); - } - - //Update size member variable - size = localSize; - - logger.finer("Written MultipleTextEncodedStringNullTerminated"); - return buffer.toByteArray(); - } - - /** - * This holds the values held by a MultipleTextEncodedData type - */ - public static class Values { - private List valueList = new ArrayList(); - - public Values() { - - } - - /** - * Add String Data type to the value list - * - * @param value to add to the list - */ - public void add(String value) { - valueList.add(value); - } - - - /** - * Return the list of values - * - * @return the list of values - */ - public List getList() { - return valueList; - } - - /** - * @return no of values - */ - public int getNumberOfValues() { - return valueList.size(); - } - - /** - * Return the list of values as a single string separated by a comma - * - * @return a string representation of the value - */ - public String toString() { - StringBuffer sb = new StringBuffer(); - for (ListIterator li = valueList.listIterator(); li.hasNext(); ) { - String next = li.next(); - sb.append(next); - if (li.hasNext()) { - sb.append(","); - } - } - return sb.toString(); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/NumberFixedLength.java b/src/main/java/org/jaudiotagger/tag/datatype/NumberFixedLength.java deleted file mode 100644 index 292c741..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/NumberFixedLength.java +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: NumberFixedLength.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Represents a Number of a fixed number of decimal places. - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.ID3Tags; - - -/** - * Represents a number held as a fixed number of digits. - *

    - * The bitorder in ID3v2 is most significant bit first (MSB). The byteorder in multibyte numbers is most significant - * byte first (e.g. $12345678 would be encoded $12 34 56 78), also known as big endian and network byte order. - *

    - * In ID3Specification would be denoted as $xx xx this denotes exactly two bytes required - */ -public class NumberFixedLength extends AbstractDataType { - /** - * Creates a new ObjectNumberFixedLength datatype. - * - * @param identifier - * @param frameBody - * @param size the number of significant places that the number is held to - * @throws IllegalArgumentException - */ - public NumberFixedLength(String identifier, AbstractTagFrameBody frameBody, int size) { - super(identifier, frameBody); - if (size < 0) { - throw new IllegalArgumentException("Length is less than zero: " + size); - } - this.size = size; - - } - - public NumberFixedLength(NumberFixedLength copy) { - super(copy); - this.size = copy.size; - } - - /** - * Return size - * - * @return the size of this number - */ - public int getSize() { - return size; - } - - /** - * Set Size in Bytes of this Object - * - * @param size in bytes that this number will be held as - */ - public void setSize(int size) { - if (size > 0) { - this.size = size; - } - } - - public void setValue(Object value) { - if (!(value instanceof Number)) { - throw new IllegalArgumentException("Invalid value type for NumberFixedLength:" + value.getClass()); - } - super.setValue(value); - } - - - /** - * @param obj - * @return true if obj equivalent to this - */ - public boolean equals(Object obj) { - if (!(obj instanceof NumberFixedLength)) { - return false; - } - NumberFixedLength object = (NumberFixedLength) obj; - return this.size == object.size && super.equals(obj); - } - - /** - * Read the number from the byte array - * - * @param arr - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - if (arr == null) { - throw new NullPointerException("Byte array is null"); - } - if ((offset < 0) || (offset >= arr.length)) { - throw new InvalidDataTypeException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length); - } - - if (offset + size > arr.length) { - throw new InvalidDataTypeException("Offset plus size to byte array is out of bounds: offset = " - + offset + ", size = " + size + " + arr.length " + arr.length); - } - - long lvalue = 0; - for (int i = offset; i < (offset + size); i++) { - lvalue <<= 8; - lvalue += (arr[i] & 0xff); - } - value = lvalue; - logger.config("Read NumberFixedlength:" + value); - } - - - /** - * @return String representation of this datatype - */ - public String toString() { - if (value == null) { - return ""; - } else { - return value.toString(); - } - } - - /** - * Write data to byte array - * - * @return the datatype converted to a byte array - */ - public byte[] writeByteArray() { - byte[] arr; - arr = new byte[size]; - if (value != null) { - //Convert value to long - long temp = ID3Tags.getWholeNumber(value); - - for (int i = size - 1; i >= 0; i--) { - arr[i] = (byte) (temp & 0xFF); - temp >>= 8; - } - } - return arr; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/NumberHashMap.java b/src/main/java/org/jaudiotagger/tag/datatype/NumberHashMap.java deleted file mode 100644 index dd636c0..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/NumberHashMap.java +++ /dev/null @@ -1,219 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: NumberHashMap.java 857 2009-12-03 11:21:11Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.*; -import org.jaudiotagger.tag.reference.GenreTypes; -import org.jaudiotagger.tag.reference.PictureTypes; -import org.jaudiotagger.utils.EqualsUtil; - -import java.util.Iterator; -import java.util.Map; -import java.util.TreeSet; - -/** - * Represents a number thats acts as a key into an enumeration of values - */ -public class NumberHashMap extends NumberFixedLength implements HashMapInterface { - - /** - * key to value map - */ - private Map keyToValue = null; - - /** - * value to key map - */ - private Map valueToKey = null; - - /** - * - */ - private boolean hasEmptyValue = false; - - - /** - * Creates a new ObjectNumberHashMap datatype. - * - * @param identifier - * @param frameBody - * @param size - * @throws IllegalArgumentException - */ - public NumberHashMap(String identifier, AbstractTagFrameBody frameBody, int size) { - super(identifier, frameBody, size); - - if (identifier.equals(DataTypes.OBJ_GENRE)) { - valueToKey = GenreTypes.getInstanceOf().getValueToIdMap(); - keyToValue = GenreTypes.getInstanceOf().getIdToValueMap(); - - //genres can be an id or literal value - hasEmptyValue = true; - } else if (identifier.equals(DataTypes.OBJ_TEXT_ENCODING)) { - valueToKey = TextEncoding.getInstanceOf().getValueToIdMap(); - keyToValue = TextEncoding.getInstanceOf().getIdToValueMap(); - } else if (identifier.equals(DataTypes.OBJ_INTERPOLATION_METHOD)) { - valueToKey = InterpolationTypes.getInstanceOf().getValueToIdMap(); - keyToValue = InterpolationTypes.getInstanceOf().getIdToValueMap(); - } else if (identifier.equals(DataTypes.OBJ_PICTURE_TYPE)) { - valueToKey = PictureTypes.getInstanceOf().getValueToIdMap(); - keyToValue = PictureTypes.getInstanceOf().getIdToValueMap(); - - //Issue #224 Values should map, but have examples where they dont, this is a workaround - hasEmptyValue = true; - } else if (identifier.equals(DataTypes.OBJ_TYPE_OF_EVENT)) { - valueToKey = EventTimingTypes.getInstanceOf().getValueToIdMap(); - keyToValue = EventTimingTypes.getInstanceOf().getIdToValueMap(); - } else if (identifier.equals(DataTypes.OBJ_TIME_STAMP_FORMAT)) { - valueToKey = EventTimingTimestampTypes.getInstanceOf().getValueToIdMap(); - keyToValue = EventTimingTimestampTypes.getInstanceOf().getIdToValueMap(); - } else if (identifier.equals(DataTypes.OBJ_TYPE_OF_CHANNEL)) { - valueToKey = ChannelTypes.getInstanceOf().getValueToIdMap(); - keyToValue = ChannelTypes.getInstanceOf().getIdToValueMap(); - } else if (identifier.equals(DataTypes.OBJ_RECIEVED_AS)) { - valueToKey = ReceivedAsTypes.getInstanceOf().getValueToIdMap(); - keyToValue = ReceivedAsTypes.getInstanceOf().getIdToValueMap(); - } else if (identifier.equals(DataTypes.OBJ_CONTENT_TYPE)) { - valueToKey = SynchronisedLyricsContentType.getInstanceOf().getValueToIdMap(); - keyToValue = SynchronisedLyricsContentType.getInstanceOf().getIdToValueMap(); - } else { - throw new IllegalArgumentException("Hashmap identifier not defined in this class: " + identifier); - } - } - - public NumberHashMap(NumberHashMap copyObject) { - super(copyObject); - - this.hasEmptyValue = copyObject.hasEmptyValue; - - // we don't need to clone/copy the maps here because they are static - this.keyToValue = copyObject.keyToValue; - this.valueToKey = copyObject.valueToKey; - } - - /** - * @return the key to value map - */ - public Map getKeyToValue() { - return keyToValue; - } - - /** - * @return the value to key map - */ - public Map getValueToKey() { - return valueToKey; - } - - /** - * @param value - */ - public void setValue(Object value) { - if (value instanceof Byte) { - this.value = (long) ((Byte) value).byteValue(); - } else if (value instanceof Short) { - this.value = (long) ((Short) value).shortValue(); - } else if (value instanceof Integer) { - this.value = (long) ((Integer) value).intValue(); - } else { - this.value = value; - } - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof NumberHashMap)) { - return false; - } - - NumberHashMap that = (NumberHashMap) obj; - - return - EqualsUtil.areEqual(hasEmptyValue, that.hasEmptyValue) && - EqualsUtil.areEqual(keyToValue, that.keyToValue) && - EqualsUtil.areEqual(valueToKey, that.valueToKey) && - super.equals(that); - } - - /** - * @return - */ - public Iterator iterator() { - if (keyToValue == null) { - return null; - } else { - // put them in a treeset first to sort them - TreeSet treeSet = new TreeSet(keyToValue.values()); - - if (hasEmptyValue) { - treeSet.add(""); - } - - return treeSet.iterator(); - } - } - - /** - * Read the key from the buffer. - * - * @param arr - * @param offset - * @throws InvalidDataTypeException if emptyValues are not allowed and the eky was invalid. - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - super.readByteArray(arr, offset); - - //Mismatch:Superclass uses Long, but maps expect Integer - Integer intValue = ((Long) value).intValue(); - if (!keyToValue.containsKey(intValue)) { - if (!hasEmptyValue) { - throw new InvalidDataTypeException(ErrorMessage.MP3_REFERENCE_KEY_INVALID.getMsg(identifier, intValue)); - } else if (identifier.equals(DataTypes.OBJ_PICTURE_TYPE)) { - logger.warning(ErrorMessage.MP3_PICTURE_TYPE_INVALID.getMsg(value)); - } - } - } - - /** - * @return - */ - public String toString() { - if (value == null) { - return ""; - } else if (keyToValue.get(value) == null) { - return ""; - } else { - return keyToValue.get(value); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/NumberVariableLength.java b/src/main/java/org/jaudiotagger/tag/datatype/NumberVariableLength.java deleted file mode 100644 index d0ba00d..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/NumberVariableLength.java +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: NumberVariableLength.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.ID3Tags; - -/** - * Represents a number which may span a number of bytes when written to file depending what size is to be represented. - *

    - * The bitorder in ID3v2 is most significant bit first (MSB). The byteorder in multibyte numbers is most significant - * byte first (e.g. $12345678 would be encoded $12 34 56 78), also known as big endian and network byte order. - *

    - * In ID3Specification would be denoted as $xx xx xx xx (xx ...) , this denotes at least four bytes but may be more. - * Sometimes may be completely optional (zero bytes) - */ -public class NumberVariableLength extends AbstractDataType { - private static final int MINIMUM_NO_OF_DIGITS = 1; - private static final int MAXIMUM_NO_OF_DIGITS = 8; - - int minLength = MINIMUM_NO_OF_DIGITS; - - - /** - * Creates a new ObjectNumberVariableLength datatype, set minimum length to zero - * if this datatype is optional. - * - * @param identifier - * @param frameBody - * @param minimumSize - */ - public NumberVariableLength(String identifier, AbstractTagFrameBody frameBody, int minimumSize) { - super(identifier, frameBody); - - //Set minimum length, which can be zero if optional - this.minLength = minimumSize; - - } - - public NumberVariableLength(NumberVariableLength copy) { - super(copy); - this.minLength = copy.minLength; - } - - /** - * Return the maximum number of digits that can be used to express the number - * - * @return the maximum number of digits that can be used to express the number - */ - public int getMaximumLenth() { - return MAXIMUM_NO_OF_DIGITS; - } - - /** - * Return the minimum number of digits that can be used to express the number - * - * @return the minimum number of digits that can be used to express the number - */ - public int getMinimumLength() { - return minLength; - } - - /** - * @param minimumSize - */ - public void setMinimumSize(int minimumSize) { - if (minimumSize > 0) { - this.minLength = minimumSize; - } - } - - /** - * @return the number of bytes required to write this to a file - */ - public int getSize() { - if (value == null) { - return 0; - } else { - int current; - long temp = ID3Tags.getWholeNumber(value); - int size = 0; - - for (int i = MINIMUM_NO_OF_DIGITS; i <= MAXIMUM_NO_OF_DIGITS; i++) { - current = (byte) temp & 0xFF; - - if (current != 0) { - size = i; - } - - temp >>= MAXIMUM_NO_OF_DIGITS; - } - - return (minLength > size) ? minLength : size; - } - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof NumberVariableLength)) { - return false; - } - - NumberVariableLength object = (NumberVariableLength) obj; - - return this.minLength == object.minLength && super.equals(obj); - - } - - /** - * Read from Byte Array - * - * @param arr - * @param offset - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - //Coding error, should never happen - if (arr == null) { - throw new NullPointerException("Byte array is null"); - } - - //Coding error, should never happen as far as I can see - if (offset < 0) { - throw new IllegalArgumentException("negativer offset into an array offset:" + offset); - } - - //If optional then set value to zero, this will mean that if this frame is written back to file it will be created - //with this additional datatype wheras it didnt exist but I think this is probably an advantage the frame is - //more likely to be parsed by other applications if it contains optional fields. - //if not optional problem with this frame - if (offset >= arr.length) { - if (minLength == 0) { - value = (long) 0; - return; - } else { - throw new InvalidDataTypeException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length); - } - } - - long lvalue = 0; - - //Read the bytes (starting from offset), the most significant byte of the number being constructed is read first, - //we then shift the resulting long one byte over to make room for the next byte - for (int i = offset; i < arr.length; i++) { - lvalue <<= 8; - lvalue += (arr[i] & 0xff); - } - - value = lvalue; - } - - - /** - * @return String representation of the number - */ - public String toString() { - if (value == null) { - return ""; - } else { - return value.toString(); - } - } - - /** - * Write to Byte Array - * - * @return the datatype converted to a byte array - */ - public byte[] writeByteArray() { - int size = getSize(); - byte[] arr; - - if (size == 0) { - arr = new byte[0]; - } else { - long temp = ID3Tags.getWholeNumber(value); - arr = new byte[size]; - - //keeps shifting the number downwards and masking the last 8 bist to get the value for the next byte - //to be written - for (int i = size - 1; i >= 0; i--) { - arr[i] = (byte) (temp & 0xFF); - temp >>= 8; - } - } - return arr; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/Pair.java b/src/main/java/org/jaudiotagger/tag/datatype/Pair.java deleted file mode 100644 index 6f9fc47..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/Pair.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.jaudiotagger.tag.datatype; - -/** - * A pair - */ -public class Pair { - private String key; - private String value; - - public Pair(String key, String value) { - setKey(key); - setValue(value); - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java deleted file mode 100644 index 25a8543..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; - -/** - * Represents a data type that allow multiple Strings but they should be paired as key values, i.e should be 2,4,6.. - * But keys are not unique so we don't store as a map, so could have same key pointing to two different values - * such as two ENGINEER keys - *

    - */ -public class PairedTextEncodedStringNullTerminated extends AbstractDataType { - public PairedTextEncodedStringNullTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - value = new PairedTextEncodedStringNullTerminated.ValuePairs(); - } - - public PairedTextEncodedStringNullTerminated(TextEncodedStringSizeTerminated object) { - super(object); - value = new PairedTextEncodedStringNullTerminated.ValuePairs(); - } - - public PairedTextEncodedStringNullTerminated(PairedTextEncodedStringNullTerminated object) { - super(object); - } - - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof PairedTextEncodedStringNullTerminated)) { - return false; - } - - PairedTextEncodedStringNullTerminated that = (PairedTextEncodedStringNullTerminated) obj; - - return EqualsUtil.areEqual(value, that.value); - } - - /** - * Returns the size in bytes of this dataType when written to file - * - * @return size of this dataType - */ - public int getSize() { - return size; - } - - /** - * Check the value can be encoded with the specified encoding - * - * @return - */ - public boolean canBeEncoded() { - for (Pair entry : ((ValuePairs) value).mapping) { - TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, entry.getValue()); - if (!next.canBeEncoded()) { - return false; - } - } - return true; - } - - /** - * Read Null Terminated Strings from the array starting at offset, continue until unable to find any null terminated - * Strings or until reached the end of the array. The offset should be set to byte after the last null terminated - * String found. - * - * @param arr to read the Strings from - * @param offset in the array to start reading from - * @throws InvalidDataTypeException if unable to find any null terminated Strings - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - logger.finer("Reading PairTextEncodedStringNullTerminated from array from offset:" + offset); - //Continue until unable to read a null terminated String - while (true) { - try { - //Read Key - TextEncodedStringNullTerminated key = new TextEncodedStringNullTerminated(identifier, frameBody); - key.readByteArray(arr, offset); - size += key.getSize(); - offset += key.getSize(); - if (key.getSize() == 0) { - break; - } - - try { - //Read Value - TextEncodedStringNullTerminated result = new TextEncodedStringNullTerminated(identifier, frameBody); - result.readByteArray(arr, offset); - size += result.getSize(); - offset += result.getSize(); - if (result.getSize() == 0) { - break; - } - //Add to value - ((ValuePairs) value).add((String) key.getValue(), (String) result.getValue()); - } catch (InvalidDataTypeException idte) { - //Value may not be null terminated if it is the last value - //Read Value - if (offset >= arr.length) { - break; - } - TextEncodedStringSizeTerminated result = new TextEncodedStringSizeTerminated(identifier, frameBody); - result.readByteArray(arr, offset); - size += result.getSize(); - offset += result.getSize(); - if (result.getSize() == 0) { - break; - } - //Add to value - ((ValuePairs) value).add((String) key.getValue(), (String) result.getValue()); - break; - } - } catch (InvalidDataTypeException idte) { - break; - } - - if (size == 0) { - logger.warning("No null terminated Strings found"); - throw new InvalidDataTypeException("No null terminated Strings found"); - } - } - logger.finer("Read PairTextEncodedStringNullTerminated:" + value + " size:" + size); - } - - - /** - * For every String write to byteBuffer - * - * @return byteBuffer that should be written to file to persist this dataType. - */ - public byte[] writeByteArray() { - logger.finer("Writing PairTextEncodedStringNullTerminated"); - - int localSize = 0; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - try { - for (Pair pair : ((ValuePairs) value).mapping) { - { - TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, pair.getKey()); - buffer.write(next.writeByteArray()); - localSize += next.getSize(); - } - { - TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, pair.getValue()); - buffer.write(next.writeByteArray()); - localSize += next.getSize(); - } - } - } catch (IOException ioe) { - //This should never happen because the write is internal with the JVM it is not to a file - logger.log(Level.SEVERE, "IOException in MultipleTextEncodedStringNullTerminated when writing byte array", ioe); - throw new RuntimeException(ioe); - } - - //Update size member variable - size = localSize; - - logger.finer("Written PairTextEncodedStringNullTerminated"); - return buffer.toByteArray(); - } - - public ValuePairs getValue() { - return (ValuePairs) value; - } - - /** - * This holds the values held by this PairedTextEncodedDataType, always held as pairs of values - */ - public static class ValuePairs { - private List mapping = new ArrayList(); - - public ValuePairs() { - super(); - } - - /** - * Add String Data type to the value list - * - * @param value to add to the list - */ - public void add(String key, String value) { - mapping.add(new Pair(key, value)); - } - - - /** - * Return the list of values - * - * @return the list of values - */ - public List getMapping() { - return mapping; - } - - /** - * @return no of values - */ - public int getNumberOfValues() { - return mapping.size(); - } - - /** - * Return the list of values as a single string separated by a colon,comma - * - * @return a string representation of the value - */ - public String toString() { - StringBuffer sb = new StringBuffer(); - for (Pair next : mapping) { - sb.append(next.getKey() + ':' + next.getValue() + ','); - } - return sb.toString(); - } - - /** - * @return no of values - */ - public int getNumberOfPairs() { - return mapping.size(); - } - - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof ValuePairs)) { - return false; - } - - ValuePairs that = (ValuePairs) obj; - - return EqualsUtil.areEqual(getNumberOfValues(), that.getNumberOfValues()); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/PartOfSet.java b/src/main/java/org/jaudiotagger/tag/datatype/PartOfSet.java deleted file mode 100644 index aa6093a..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/PartOfSet.java +++ /dev/null @@ -1,427 +0,0 @@ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.options.PadNumberOption; -import org.jaudiotagger.utils.EqualsUtil; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Represents the form 01/10 whereby the second part is optional. This is used by frame such as TRCK and TPOS - *

    - * Some applications like to prepend the count with a zero to aid sorting, (i.e 02 comes before 10) - *

    - * If TagOptionSingleton.getInstance().isPadNumbers() is enabled then all fields will be written to file padded - * depending on the value of agOptionSingleton.getInstance().getPadNumberTotalLength(). Additionally fields returned - * from file will be returned as padded even if they are not currently stored as padded in the file. - *

    - * If TagOptionSingleton.getInstance().isPadNumbers() is disabled then count and track are written to file as they - * are provided, i.e if provided pre-padded they will be stored pre-padded, if not they will not. Values read from - * file will be returned as they are currently stored in file. - */ -@SuppressWarnings({"EmptyCatchBlock"}) -public class PartOfSet extends AbstractString { - /** - * Creates a new empty PartOfSet datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public PartOfSet(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - /** - * Copy constructor - * - * @param object - */ - public PartOfSet(PartOfSet object) { - super(object); - } - - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof PartOfSet)) { - return false; - } - - PartOfSet that = (PartOfSet) obj; - - return EqualsUtil.areEqual(value, that.value); - } - - /** - * Read a 'n' bytes from buffer into a String where n is the frameSize - offset - * so therefore cannot use this if there are other objects after it because it has no - * delimiter. - *

    - * Must take into account the text encoding defined in the Encoding Object - * ID3 Text Frames often allow multiple strings separated by the null char - * appropriate for the encoding. - * - * @param arr this is the buffer for the frame - * @param offset this is where to start reading in the buffer for this field - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - logger.finest("Reading from array from offset:" + offset); - - //Get the Specified Decoder - String charSetName = getTextEncodingCharSet(); - CharsetDecoder decoder = Charset.forName(charSetName).newDecoder(); - - //Decode sliced inBuffer - ByteBuffer inBuffer = ByteBuffer.wrap(arr, offset, arr.length - offset).slice(); - CharBuffer outBuffer = CharBuffer.allocate(arr.length - offset); - decoder.reset(); - CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true); - if (coderResult.isError()) { - logger.warning("Decoding error:" + coderResult.toString()); - } - decoder.flush(outBuffer); - outBuffer.flip(); - - //Store value - String stringValue = outBuffer.toString(); - value = new PartOfSetValue(stringValue); - - //SetSize, important this is correct for finding the next datatype - setSize(arr.length - offset); - logger.config("Read SizeTerminatedString:" + value + " size:" + size); - } - - /** - * Write String into byte array - *

    - * It will remove a trailing null terminator if exists if the option - * RemoveTrailingTerminatorOnWrite has been set. - * - * @return the data as a byte array in format to write to file - */ - public byte[] writeByteArray() { - String value = getValue().toString(); - byte[] data; - //Try and write to buffer using the CharSet defined by getTextEncodingCharSet() - try { - if (TagOptionSingleton.getInstance().isRemoveTrailingTerminatorOnWrite()) { - if (value.length() > 0) { - if (value.charAt(value.length() - 1) == '\0') { - value = value.substring(0, value.length() - 1); - } - } - } - - String charSetName = getTextEncodingCharSet(); - if (charSetName.equals(TextEncoding.CHARSET_UTF_16)) { - charSetName = TextEncoding.CHARSET_UTF_16_LE_ENCODING_FORMAT; - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - //Note remember LE BOM is ff fe but this is handled by encoder Unicode char is fe ff - ByteBuffer bb = encoder.encode(CharBuffer.wrap('\ufeff' + value)); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - - } else { - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - ByteBuffer bb = encoder.encode(CharBuffer.wrap(value)); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } - } - //Should never happen so if does throw a RuntimeException - catch (CharacterCodingException ce) { - logger.severe(ce.getMessage()); - throw new RuntimeException(ce); - } - setSize(data.length); - return data; - } - - /** - * Get the text encoding being used. - *

    - * The text encoding is defined by the frame body that the text field belongs to. - * - * @return the text encoding charset - */ - protected String getTextEncodingCharSet() { - byte textEncoding = this.getBody().getTextEncoding(); - String charSetName = TextEncoding.getInstanceOf().getValueForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charSetName); - return charSetName; - } - - public PartOfSetValue getValue() { - return (PartOfSetValue) value; - } - - public String toString() { - return value.toString(); - } - - /** - * Holds data - */ - public static class PartOfSetValue { - private static final Pattern trackNoPatternWithTotalCount; - private static final Pattern trackNoPattern; - private static final String SEPARATOR = "/"; - - static { - //Match track/total pattern allowing for extraneous nulls ecetera at the end - trackNoPatternWithTotalCount = Pattern.compile("([0-9]+)/([0-9]+)(.*)", Pattern.CASE_INSENSITIVE); - trackNoPattern = Pattern.compile("([0-9]+)(.*)", Pattern.CASE_INSENSITIVE); - } - - private Integer count; - private Integer total; - private String extra; //Any extraneous info such as null chars - private String rawText; // raw text representation used to actually save the data IF !TagOptionSingleton.getInstance().isPadNumbers() - private String rawCount; //count value as provided - private String rawTotal; //total value as provided - - public PartOfSetValue() { - rawText = ""; - } - - /** - * When constructing from data - * - * @param value - */ - public PartOfSetValue(String value) { - this.rawText = value; - initFromValue(value); - } - - /** - * Newly created - * - * @param count - * @param total - */ - public PartOfSetValue(Integer count, Integer total) { - this.count = count; - this.rawCount = count.toString(); - this.total = total; - this.rawTotal = total.toString(); - resetValueFromCounts(); - } - - /** - * Given a raw value that could contain both a count and total and extra stuff (but needdnt contain - * anything tries to parse it) - * - * @param value - */ - private void initFromValue(String value) { - try { - Matcher m = trackNoPatternWithTotalCount.matcher(value); - if (m.matches()) { - this.extra = m.group(3); - this.count = Integer.parseInt(m.group(1)); - this.rawCount = m.group(1); - this.total = Integer.parseInt(m.group(2)); - this.rawTotal = m.group(2); - return; - } - - m = trackNoPattern.matcher(value); - if (m.matches()) { - this.extra = m.group(2); - this.count = Integer.parseInt(m.group(1)); - this.rawCount = m.group(1); - } - } catch (NumberFormatException nfe) { - //#JAUDIOTAGGER-366 Could occur if actually value is a long not an int - this.count = 0; - } - } - - private void resetValueFromCounts() { - StringBuffer sb = new StringBuffer(); - if (rawCount != null) { - sb.append(rawCount); - } else { - sb.append("0"); - } - if (rawTotal != null) { - sb.append(SEPARATOR + rawTotal); - } - if (extra != null) { - sb.append(extra); - } - this.rawText = sb.toString(); - } - - public Integer getCount() { - return count; - } - - public void setCount(String count) { - try { - this.count = Integer.parseInt(count); - this.rawCount = count; - resetValueFromCounts(); - } catch (NumberFormatException nfe) { - - } - } - - public Integer getTotal() { - return total; - } - - public void setTotal(String total) { - try { - this.total = Integer.parseInt(total); - this.rawTotal = total; - resetValueFromCounts(); - } catch (NumberFormatException nfe) { - - } - } - - public void setCount(Integer count) { - this.count = count; - this.rawCount = count.toString(); - resetValueFromCounts(); - } - - public void setTotal(Integer total) { - this.total = total; - this.rawTotal = total.toString(); - resetValueFromCounts(); - - } - - public String getRawValue() { - return rawText; - } - - public void setRawValue(String value) { - this.rawText = value; - initFromValue(value); - } - - /** - * Get Count including padded if padding is enabled - * - * @return - */ - public String getCountAsText() { - //Don't Pad - StringBuffer sb = new StringBuffer(); - if (!TagOptionSingleton.getInstance().isPadNumbers()) { - return rawCount; - } else { - padNumber(sb, count, TagOptionSingleton.getInstance().getPadNumberTotalLength()); - } - return sb.toString(); - } - - /** - * Pad number so number is defined as long as length - * - * @param sb - * @param count - * @param padNumberLength - */ - private void padNumber(StringBuffer sb, Integer count, PadNumberOption padNumberLength) { - if (count != null) { - if (padNumberLength == PadNumberOption.PAD_ONE_ZERO) { - if (count > 0 && count < 10) { - sb.append("0").append(count); - } else { - sb.append(count.intValue()); - } - } else if (padNumberLength == PadNumberOption.PAD_TWO_ZERO) { - if (count > 0 && count < 10) { - sb.append("00").append(count); - } else if (count > 9 && count < 100) { - sb.append("0").append(count); - } else { - sb.append(count.intValue()); - } - } else if (padNumberLength == PadNumberOption.PAD_THREE_ZERO) { - if (count > 0 && count < 10) { - sb.append("000").append(count); - } else if (count > 9 && count < 100) { - sb.append("00").append(count); - } else if (count > 99 && count < 1000) { - sb.append("0").append(count); - } else { - sb.append(count.intValue()); - } - } - } - } - - /** - * Get Total padded - * - * @return - */ - public String getTotalAsText() { - //Don't Pad - StringBuffer sb = new StringBuffer(); - if (!TagOptionSingleton.getInstance().isPadNumbers()) { - return rawTotal; - } else { - padNumber(sb, total, TagOptionSingleton.getInstance().getPadNumberTotalLength()); - - } - return sb.toString(); - } - - public String toString() { - - //Don't Pad - StringBuffer sb = new StringBuffer(); - if (!TagOptionSingleton.getInstance().isPadNumbers()) { - return rawText; - } else { - if (count != null) { - padNumber(sb, count, TagOptionSingleton.getInstance().getPadNumberTotalLength()); - } else if (total != null) { - padNumber(sb, 0, TagOptionSingleton.getInstance().getPadNumberTotalLength()); - } - if (total != null) { - sb.append(SEPARATOR); - padNumber(sb, total, TagOptionSingleton.getInstance().getPadNumberTotalLength()); - } - if (extra != null) { - sb.append(extra); - } - } - return sb.toString(); - } - - - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof PartOfSetValue)) { - return false; - } - - PartOfSetValue that = (PartOfSetValue) obj; - - return EqualsUtil.areEqual(getCount(), that.getCount()) - && EqualsUtil.areEqual(getTotal(), that.getTotal()); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/StringDate.java b/src/main/java/org/jaudiotagger/tag/datatype/StringDate.java deleted file mode 100644 index f92626d..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/StringDate.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: StringDate.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.ID3Tags; - -/** - * Represents a timestamp field - */ -public class StringDate extends StringFixedLength { - /** - * Creates a new ObjectStringDate datatype. - * - * @param identifier - * @param frameBody - */ - public StringDate(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody, 8); - } - - public StringDate(StringDate object) { - super(object); - } - - /** - * @return - */ - public Object getValue() { - if (value != null) { - return ID3Tags.stripChar(value.toString(), '-'); - } else { - return null; - } - } - - /** - * @param value - */ - public void setValue(Object value) { - if (value != null) { - this.value = ID3Tags.stripChar(value.toString(), '-'); - } - } - - public boolean equals(Object obj) { - return obj instanceof StringDate && super.equals(obj); - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/StringDateTime.java b/src/main/java/org/jaudiotagger/tag/datatype/StringDateTime.java deleted file mode 100644 index 3e087b0..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/StringDateTime.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: StringDateTime.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - - -/** - * Represents a timestamp field - */ -public class StringDateTime extends StringSizeTerminated { - /** - * Creates a new ObjectStringDateTime datatype. - * - * @param identifier - * @param frameBody - */ - public StringDateTime(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public StringDateTime(StringDateTime object) { - super(object); - } - - /** - * @return - */ - public Object getValue() { - if (value != null) { - return value.toString().replace(' ', 'T'); - } else { - return null; - } - } - - /** - * @param value - */ - public void setValue(Object value) { - if (value != null) { - this.value = value.toString().replace(' ', 'T'); - } - } - - public boolean equals(Object obj) { - return obj instanceof StringDateTime && super.equals(obj); - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/StringFixedLength.java b/src/main/java/org/jaudiotagger/tag/datatype/StringFixedLength.java deleted file mode 100644 index be6fe01..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/StringFixedLength.java +++ /dev/null @@ -1,197 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: StringFixedLength.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; - - -/** - * Represents a fixed length String, whereby the length of the String is known. The String - * will be encoded based upon the text encoding of the frame that it belongs to. - */ -public class StringFixedLength extends AbstractString { - /** - * Creates a new ObjectStringFixedsize datatype. - * - * @param identifier - * @param frameBody - * @param size - * @throws IllegalArgumentException - */ - public StringFixedLength(String identifier, AbstractTagFrameBody frameBody, int size) { - super(identifier, frameBody); - if (size < 0) { - throw new IllegalArgumentException("size is less than zero: " + size); - } - setSize(size); - } - - public StringFixedLength(StringFixedLength copyObject) { - super(copyObject); - this.size = copyObject.size; - } - - /** - * @param obj - * @return if obj is equivalent to this - */ - public boolean equals(Object obj) { - if (!(obj instanceof StringFixedLength)) { - return false; - } - StringFixedLength object = (StringFixedLength) obj; - return this.size == object.size && super.equals(obj); - } - - /** - * Read a string from buffer of fixed size(size has already been set in constructor) - * - * @param arr this is the buffer for the frame - * @param offset this is where to start reading in the buffer for this field - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - logger.config("Reading from array from offset:" + offset); - try { - String charSetName = getTextEncodingCharSet(); - CharsetDecoder decoder = Charset.forName(charSetName).newDecoder(); - - //Decode buffer if runs into problems should through exception which we - //catch and then set value to empty string. - logger.finest("Array length is:" + arr.length + "offset is:" + offset + "Size is:" + size); - - - if (arr.length - offset < size) { - throw new InvalidDataTypeException("byte array is to small to retrieve string of declared length:" + size); - } - String str = decoder.decode(ByteBuffer.wrap(arr, offset, size)).toString(); - if (str == null) { - throw new NullPointerException("String is null"); - } - value = str; - } catch (CharacterCodingException ce) { - logger.severe(ce.getMessage()); - value = ""; - } - logger.config("Read StringFixedLength:" + value); - } - - /** - * Write String into byte array - *

    - * The string will be adjusted to ensure the correct number of bytes are written, If the current value is null - * or to short the written value will have the 'space' character appended to ensure this. We write this instead of - * the null character because the null character is likely to confuse the parser into misreading the next field. - * - * @return the byte array to be written to the file - */ - public byte[] writeByteArray() { - ByteBuffer dataBuffer; - byte[] data; - - //Create with a series of empty of spaces to try and ensure integrity of field - if (value == null) { - logger.warning("Value of StringFixedlength Field is null using default value instead"); - data = new byte[size]; - for (int i = 0; i < size; i++) { - data[i] = ' '; - } - return data; - } - - try { - String charSetName = getTextEncodingCharSet(); - if (charSetName.equals(TextEncoding.CHARSET_UTF_16)) { - charSetName = TextEncoding.CHARSET_UTF_16_LE_ENCODING_FORMAT; - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - //Note remember LE BOM is ff fe but tis is handled by encoder Unicode char is fe ff - dataBuffer = encoder.encode(CharBuffer.wrap('\ufeff' + (String) value)); - } else { - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - dataBuffer = encoder.encode(CharBuffer.wrap((String) value)); - } - } catch (CharacterCodingException ce) { - logger.warning("There was a problem writing the following StringFixedlength Field:" + value + ":" + ce.getMessage() + "using default value instead"); - data = new byte[size]; - for (int i = 0; i < size; i++) { - data[i] = ' '; - } - return data; - } - - // We must return the defined size. - // To check now because size is in bytes not chars - if (dataBuffer != null) { - //Everything ok - if (dataBuffer.limit() == size) { - data = new byte[dataBuffer.limit()]; - dataBuffer.get(data, 0, dataBuffer.limit()); - return data; - } - //There is more data available than allowed for this field strip - else if (dataBuffer.limit() > size) { - logger.warning("There was a problem writing the following StringFixedlength Field:" + value + " when converted to bytes has length of:" + dataBuffer.limit() + " but field was defined with length of:" + size + " too long so stripping extra length"); - data = new byte[size]; - dataBuffer.get(data, 0, size); - return data; - } - //There is not enough data - else { - logger.warning("There was a problem writing the following StringFixedlength Field:" + value + " when converted to bytes has length of:" + dataBuffer.limit() + " but field was defined with length of:" + size + " too short so padding with spaces to make up extra length"); - - data = new byte[size]; - dataBuffer.get(data, 0, dataBuffer.limit()); - - for (int i = dataBuffer.limit(); i < size; i++) { - data[i] = ' '; - } - return data; - } - } else { - logger.warning("There was a serious problem writing the following StringFixedlength Field:" + value + ":" + "using default value instead"); - data = new byte[size]; - for (int i = 0; i < size; i++) { - data[i] = ' '; - } - return data; - } - } - - /** - * @return the encoding of the frame body this datatype belongs to - */ - protected String getTextEncodingCharSet() { - byte textEncoding = this.getBody().getTextEncoding(); - String charSetName = TextEncoding.getInstanceOf().getValueForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charSetName); - return charSetName; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/StringHashMap.java b/src/main/java/org/jaudiotagger/tag/datatype/StringHashMap.java deleted file mode 100644 index 90c6d88..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/StringHashMap.java +++ /dev/null @@ -1,187 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: StringHashMap.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.Languages; - -import java.util.Iterator; -import java.util.Map; -import java.util.TreeSet; - - -/** - * Represents a String thats acts as a key into an enumeration of values. The String will be encoded - * using the default encoding regardless of what encoding may be specified in the framebody - */ -public class StringHashMap extends StringFixedLength implements HashMapInterface { - - /** - * - */ - Map keyToValue = null; - - /** - * - */ - Map valueToKey = null; - - /** - * - */ - boolean hasEmptyValue = false; - - /** - * Creates a new ObjectStringHashMap datatype. - * - * @param identifier - * @param frameBody - * @param size - * @throws IllegalArgumentException - */ - public StringHashMap(String identifier, AbstractTagFrameBody frameBody, int size) { - super(identifier, frameBody, size); - - if (identifier.equals(DataTypes.OBJ_LANGUAGE)) { - valueToKey = Languages.getInstanceOf().getValueToIdMap(); - keyToValue = Languages.getInstanceOf().getIdToValueMap(); - } else { - throw new IllegalArgumentException("Hashmap identifier not defined in this class: " + identifier); - } - } - - public StringHashMap(StringHashMap copyObject) { - super(copyObject); - - this.hasEmptyValue = copyObject.hasEmptyValue; - this.keyToValue = copyObject.keyToValue; - this.valueToKey = copyObject.valueToKey; - } - - /** - * @return - */ - public Map getKeyToValue() { - return keyToValue; - } - - /** - * @return - */ - public Map getValueToKey() { - return valueToKey; - } - - /** - * @param value - */ - public void setValue(Object value) { - if (value instanceof String) { - //Issue #273 temporary hack for MM - if (value.equals("XXX")) { - this.value = value.toString(); - } else { - this.value = ((String) value).toLowerCase(); - } - } else { - this.value = value; - } - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof StringHashMap)) { - return false; - } - - StringHashMap object = (StringHashMap) obj; - - if (this.hasEmptyValue != object.hasEmptyValue) { - return false; - } - - if (this.keyToValue == null) { - if (object.keyToValue != null) { - return false; - } - } else { - if (!this.keyToValue.equals(object.keyToValue)) { - return false; - } - } - - if (this.keyToValue == null) { - if (object.keyToValue != null) { - return false; - } - } else { - if (!this.valueToKey.equals(object.valueToKey)) { - return false; - } - } - - return super.equals(obj); - } - - /** - * @return - */ - public Iterator iterator() { - if (keyToValue == null) { - return null; - } else { - // put them in a treeset first to sort them - TreeSet treeSet = new TreeSet(keyToValue.values()); - - if (hasEmptyValue) { - treeSet.add(""); - } - - return treeSet.iterator(); - } - } - - /** - * @return - */ - public String toString() { - if (value == null) { - return ""; - } else if (keyToValue.get(value) == null) { - return ""; - } else { - return keyToValue.get(value); - } - } - - /** - * @return the ISO_8859 encoding for Datatypes of this type - */ - protected String getTextEncodingCharSet() { - return TextEncoding.CHARSET_ISO_8859_1; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/StringNullTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/StringNullTerminated.java deleted file mode 100644 index d27cc4d..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/StringNullTerminated.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: StringNullTerminated.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -/** - * Represents a String whose size is determined by finding of a null character at the end of the String with fixed text encoding. - *

    - * The String will be encoded using the default encoding regardless of what encoding may be specified in the framebody - */ -public class StringNullTerminated extends TextEncodedStringNullTerminated { - /** - * Creates a new ObjectStringNullTerminated datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public StringNullTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public StringNullTerminated(StringNullTerminated object) { - super(object); - } - - public boolean equals(Object obj) { - return obj instanceof StringNullTerminated && super.equals(obj); - } - - protected String getTextEncodingCharSet() { - return TextEncoding.CHARSET_ISO_8859_1; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/StringSizeTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/StringSizeTerminated.java deleted file mode 100644 index 0c54254..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/StringSizeTerminated.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: StringSizeTerminated.java 899 2010-04-19 14:32:20Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Contains a string which is NOT null terminated. - * Warning this datatype type can only be used as the last datatype in a frame because - * it reads the remainder of the frame as there is no null terminated or provision - * for setting a defined size. - */ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -/** - * Represents a String which is not delimited by null character with fixed text encoding. - *

    - * This type of String will usually only be used when it is the last field within a frame, when reading the remainder of the byte array will - * be read, when writing the frame will accommodate the required size for the String. The String will be encoded - * using the default encoding regardless of what encoding may be specified in the framebody - */ -public class StringSizeTerminated extends TextEncodedStringSizeTerminated { - - /** - * Creates a new ObjectStringSizeTerminated datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public StringSizeTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - public StringSizeTerminated(StringSizeTerminated object) { - super(object); - } - - public boolean equals(Object obj) { - return obj instanceof StringSizeTerminated && super.equals(obj); - } - - protected String getTextEncodingCharSet() { - return TextEncoding.CHARSET_ISO_8859_1; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java deleted file mode 100644 index d05d291..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java +++ /dev/null @@ -1,217 +0,0 @@ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.*; - -/** - * Represents a String whose size is determined by finding of a null character at the end of the String. - *

    - * The String itself might be of length zero (i.e just consist of the null character). The String will be encoded based - * upon the text encoding of the frame that it belongs to. - */ -public class TextEncodedStringNullTerminated extends AbstractString { - /** - * Creates a new TextEncodedStringNullTerminated datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public TextEncodedStringNullTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - /** - * Creates a new TextEncodedStringNullTerminated datatype, with value - * - * @param identifier - * @param frameBody - * @param value - */ - public TextEncodedStringNullTerminated(String identifier, AbstractTagFrameBody frameBody, String value) { - super(identifier, frameBody, value); - } - - public TextEncodedStringNullTerminated(TextEncodedStringNullTerminated object) { - super(object); - } - - public boolean equals(Object obj) { - return obj instanceof TextEncodedStringNullTerminated && super.equals(obj); - } - - /** - * Read a string from buffer upto null character (if exists) - *

    - * Must take into account the text encoding defined in the Encoding Object - * ID3 Text Frames often allow multiple strings separated by the null char - * appropriate for the encoding. - * - * @param arr this is the buffer for the frame - * @param offset this is where to start reading in the buffer for this field - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - if (offset >= arr.length) { - throw new InvalidDataTypeException("Unable to find null terminated string"); - } - int bufferSize; - - logger.finer("Reading from array starting from offset:" + offset); - int size; - - //Get the Specified Decoder - String charSetName = getTextEncodingCharSet(); - CharsetDecoder decoder = Charset.forName(charSetName).newDecoder(); - - //We only want to load up to null terminator, data after this is part of different - //field and it may not be possible to decode it so do the check before we do - //do the decoding,encoding dependent. - ByteBuffer buffer = ByteBuffer.wrap(arr, offset, arr.length - offset); - int endPosition = 0; - - //Latin-1 and UTF-8 strings are terminated by a single-byte null, - //while UTF-16 and its variants need two bytes for the null terminator. - final boolean nullIsOneByte = (charSetName.equals(TextEncoding.CHARSET_ISO_8859_1) || charSetName.equals(TextEncoding.CHARSET_UTF_8)); - - boolean isNullTerminatorFound = false; - while (buffer.hasRemaining()) { - byte nextByte = buffer.get(); - if (nextByte == 0x00) { - if (nullIsOneByte) { - buffer.mark(); - buffer.reset(); - endPosition = buffer.position() - 1; - logger.finest("Null terminator found starting at:" + endPosition); - - isNullTerminatorFound = true; - break; - } else { - // Looking for two-byte null - if (buffer.hasRemaining()) { - nextByte = buffer.get(); - if (nextByte == 0x00) { - buffer.mark(); - buffer.reset(); - endPosition = buffer.position() - 2; - logger.finest("UTF16:Null terminator found starting at:" + endPosition); - isNullTerminatorFound = true; - break; - } else { - //Nothing to do, we have checked 2nd value of pair it was not a null terminator - //so will just start looking again in next invocation of loop - } - } else { - buffer.mark(); - buffer.reset(); - endPosition = buffer.position() - 1; - logger.warning("UTF16:Should be two null terminator marks but only found one starting at:" + endPosition); - - isNullTerminatorFound = true; - break; - } - } - } else { - //If UTF16, we should only be looking on 2 byte boundaries - if (!nullIsOneByte) { - if (buffer.hasRemaining()) { - buffer.get(); - } - } - } - } - - if (!isNullTerminatorFound) { - throw new InvalidDataTypeException("Unable to find null terminated string"); - } - - - logger.finest("End Position is:" + endPosition + "Offset:" + offset); - - //Set Size so offset is ready for next field (includes the null terminator) - size = endPosition - offset; - size++; - if (!nullIsOneByte) { - size++; - } - setSize(size); - - //Decode buffer if runs into problems should throw exception which we - //catch and then set value to empty string. (We don't read the null terminator - //because we dont want to display this) - bufferSize = endPosition - offset; - logger.finest("Text size is:" + bufferSize); - if (bufferSize == 0) { - value = ""; - } else { - //Decode sliced inBuffer - ByteBuffer inBuffer = ByteBuffer.wrap(arr, offset, bufferSize).slice(); - CharBuffer outBuffer = CharBuffer.allocate(bufferSize); - decoder.reset(); - CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true); - if (coderResult.isError()) { - logger.warning("Problem decoding text encoded null terminated string:" + coderResult.toString()); - } - decoder.flush(outBuffer); - outBuffer.flip(); - value = outBuffer.toString(); - } - //Set Size so offset is ready for next field (includes the null terminator) - logger.config("Read NullTerminatedString:" + value + " size inc terminator:" + size); - } - - /** - * Write String into byte array, adding a null character to the end of the String - * - * @return the data as a byte array in format to write to file - */ - public byte[] writeByteArray() { - logger.config("Writing NullTerminatedString." + value); - byte[] data; - //Write to buffer using the CharSet defined by getTextEncodingCharSet() - //Add a null terminator which will be encoded based on encoding. - try { - String charSetName = getTextEncodingCharSet(); - if (charSetName.equals(TextEncoding.CHARSET_UTF_16)) { - if (TagOptionSingleton.getInstance().isEncodeUTF16BomAsLittleEndian()) { - charSetName = TextEncoding.CHARSET_UTF_16_LE_ENCODING_FORMAT; - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - //Note remember LE BOM is ff fe but this is handled by encoder Unicode char is fe ff - ByteBuffer bb = encoder.encode(CharBuffer.wrap('\ufeff' + (String) value + '\0')); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } else { - charSetName = TextEncoding.CHARSET_UTF_16_BE_ENCODING_FORMAT; - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - //Note BE BOM will leave as fe ff - ByteBuffer bb = encoder.encode(CharBuffer.wrap('\ufeff' + (String) value + '\0')); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } - } else { - CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); - ByteBuffer bb = encoder.encode(CharBuffer.wrap((String) value + '\0')); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } - } - //Should never happen so if does throw a RuntimeException - catch (CharacterCodingException ce) { - logger.severe(ce.getMessage()); - throw new RuntimeException(ce); - } - setSize(data.length); - return data; - } - - protected String getTextEncodingCharSet() { - byte textEncoding = this.getBody().getTextEncoding(); - String charSetName = TextEncoding.getInstanceOf().getValueForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charSetName); - return charSetName; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java b/src/main/java/org/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java deleted file mode 100644 index dd50446..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java +++ /dev/null @@ -1,368 +0,0 @@ -package org.jaudiotagger.tag.datatype; - -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Represents a String which is not delimited by null character. - *

    - * This type of String will usually only be used when it is the last field within a frame, when reading the remainder of - * the byte array will be read, when writing the frame will be accommodate the required size for the String. The String - * will be encoded based upon the text encoding of the frame that it belongs to. - *

    - * All TextInformation frames support multiple strings, stored as a null separated list, where null is represented by - * the termination code for the character encoding. This functionality is only officially support in ID3v24. - *

    - * Most applications will ignore any but the first value, but some such as Foobar 2000 will decode them properly - *

    - * iTunes write null terminators characters after the String even though it only writes a single value. - */ -public class TextEncodedStringSizeTerminated extends AbstractString { - - /** - * Creates a new empty TextEncodedStringSizeTerminated datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public TextEncodedStringSizeTerminated(String identifier, AbstractTagFrameBody frameBody) { - super(identifier, frameBody); - } - - /** - * Copy constructor - * - * @param object - */ - public TextEncodedStringSizeTerminated(TextEncodedStringSizeTerminated object) { - super(object); - } - - /** - * Split the values separated by null character - * - * @param value the raw value - * @return list of values, guaranteed to be at least one value - */ - public static List splitByNullSeperator(String value) { - String[] valuesarray = value.split("\\u0000"); - List values = Arrays.asList(valuesarray); - //Read only list so if empty have to create new list - if (values.size() == 0) { - values = new ArrayList(1); - values.add(""); - } - return values; - } - - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - return obj instanceof TextEncodedStringSizeTerminated && super.equals(obj); - } - - /** - * Read a 'n' bytes from buffer into a String where n is the framesize - offset - * so thefore cannot use this if there are other objects after it because it has no - * delimiter. - *

    - * Must take into account the text encoding defined in the Encoding Object - * ID3 Text Frames often allow multiple strings seperated by the null char - * appropriate for the encoding. - * - * @param arr this is the buffer for the frame - * @param offset this is where to start reading in the buffer for this field - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException { - logger.finest("Reading from array from offset:" + offset); - - //Get the Specified Decoder - String charSetName = getTextEncodingCharSet(); - CharsetDecoder decoder = Charset.forName(charSetName).newDecoder(); - decoder.reset(); - - //Decode sliced inBuffer - ByteBuffer inBuffer; - if (TagOptionSingleton.getInstance().isAndroid()) { - //#302 [dallen] truncating array manually since the decoder.decode() does not honor the offset in the in buffer - byte[] truncArr = new byte[arr.length - offset]; - System.arraycopy(arr, offset, truncArr, 0, truncArr.length); - inBuffer = ByteBuffer.wrap(truncArr); - } else { - inBuffer = ByteBuffer.wrap(arr, offset, arr.length - offset).slice(); - } - - CharBuffer outBuffer = CharBuffer.allocate(arr.length - offset); - CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true); - if (coderResult.isError()) { - logger.warning("Decoding error:" + coderResult.toString()); - } - decoder.flush(outBuffer); - outBuffer.flip(); - - //If using UTF16 with BOM we then search through the text removing any BOMs that could exist - //for multiple values, BOM could be Big Endian or Little Endian - if (charSetName.equals(TextEncoding.CHARSET_UTF_16)) { - value = outBuffer.toString().replace("\ufeff", "").replace("\ufffe", ""); - } else { - value = outBuffer.toString(); - } - //SetSize, important this is correct for finding the next datatype - setSize(arr.length - offset); - logger.config("Read SizeTerminatedString:" + value + " size:" + size); - - } - - /** - * Write String using specified encoding - *

    - * When this is called multiple times, all but the last value has a trailing null - * - * @param encoder - * @param next - * @param i - * @param noOfValues - * @return - * @throws CharacterCodingException - */ - private ByteBuffer writeString(CharsetEncoder encoder, String next, int i, int noOfValues) - throws CharacterCodingException { - - ByteBuffer bb; - if ((i + 1) == noOfValues) { - bb = encoder.encode(CharBuffer.wrap(next)); - } else { - bb = encoder.encode(CharBuffer.wrap(next + '\0')); - } - bb.rewind(); - return bb; - } - - /** - * Write String in UTF-LEBOM format - *

    - * When this is called multiple times, all but the last value has a trailing null - *

    - * Remember we are using this charset because the charset that writes BOM does it the wrong way for us - * so we use this none and then manually add the BOM ourselves. - * - * @param next - * @param i - * @param noOfValues - * @return - * @throws CharacterCodingException - */ - private ByteBuffer writeStringUTF16LEBOM(String next, int i, int noOfValues) - throws CharacterCodingException { - CharsetEncoder encoder = Charset.forName(TextEncoding.CHARSET_UTF_16_LE_ENCODING_FORMAT).newEncoder(); - ByteBuffer bb = null; - //Note remember LE BOM is ff fe but this is handled by encoder Unicode char is fe ff - if ((i + 1) == noOfValues) { - bb = encoder.encode(CharBuffer.wrap('\ufeff' + next)); - } else { - bb = encoder.encode(CharBuffer.wrap('\ufeff' + next + '\0')); - } - bb.rewind(); - return bb; - } - - /** - * Write String in UTF-BEBOM format - *

    - * When this is called multiple times, all but the last value has a trailing null - * - * @param next - * @param i - * @param noOfValues - * @return - * @throws CharacterCodingException - */ - private ByteBuffer writeStringUTF16BEBOM(String next, int i, int noOfValues) - throws CharacterCodingException { - CharsetEncoder encoder = Charset.forName(TextEncoding.CHARSET_UTF_16_BE_ENCODING_FORMAT).newEncoder(); - ByteBuffer bb = null; - //Add BOM - if ((i + 1) == noOfValues) { - bb = encoder.encode(CharBuffer.wrap('\ufeff' + next)); - } else { - bb = encoder.encode(CharBuffer.wrap('\ufeff' + next + '\0')); - } - bb.rewind(); - return bb; - } - - /** - * Removing trailing null from end of String, this should be there but some applications continue to write - * this unnecessary null char. - */ - private void stripTrailingNull() { - if (TagOptionSingleton.getInstance().isRemoveTrailingTerminatorOnWrite()) { - String stringValue = (String) value; - if (stringValue.length() > 0) { - if (stringValue.charAt(stringValue.length() - 1) == '\0') { - stringValue = (stringValue).substring(0, stringValue.length() - 1); - value = stringValue; - } - } - } - } - - /** - * Because nulls are stripped we need to check if not removing trailing nulls whether the original - * value ended with a null and if so add it back in. - * - * @param values - * @param stringValue - */ - private void checkTrailingNull(List values, String stringValue) { - if (!TagOptionSingleton.getInstance().isRemoveTrailingTerminatorOnWrite()) { - if (stringValue.length() > 0 && stringValue.charAt(stringValue.length() - 1) == '\0') { - String lastVal = values.get(values.size() - 1); - String newLastVal = lastVal + '\0'; - values.set(values.size() - 1, newLastVal); - } - } - } - - /** - * Write String into byte array - *

    - * It will remove a trailing null terminator if exists if the option - * RemoveTrailingTerminatorOnWrite has been set. - * - * @return the data as a byte array in format to write to file - */ - public byte[] writeByteArray() { - byte[] data; - //Try and write to buffer using the CharSet defined by getTextEncodingCharSet() - try { - - stripTrailingNull(); - - //Special Handling because there is no UTF16 BOM LE charset - String stringValue = (String) value; - String charSetName = getTextEncodingCharSet(); - String actualCharSet = null; - if (charSetName.equals(TextEncoding.CHARSET_UTF_16)) { - if (TagOptionSingleton.getInstance().isEncodeUTF16BomAsLittleEndian()) { - actualCharSet = TextEncoding.CHARSET_UTF_16_LE_ENCODING_FORMAT; - } else { - actualCharSet = TextEncoding.CHARSET_UTF_16_BE_ENCODING_FORMAT; - } - } - - //Ensure large enough for any encoding - ByteBuffer outputBuffer = ByteBuffer.allocate((stringValue.length() + 3) * 3); - - //Ensure each string (if multiple values) is written with BOM by writing separately - List values = splitByNullSeperator(stringValue); - checkTrailingNull(values, stringValue); - - //For each value - for (int i = 0; i < values.size(); i++) { - String next = values.get(i); - if (actualCharSet != null) { - if (actualCharSet.equals(TextEncoding.CHARSET_UTF_16_LE_ENCODING_FORMAT)) { - outputBuffer.put(writeStringUTF16LEBOM(next, i, values.size())); - } else if (actualCharSet.equals(TextEncoding.CHARSET_UTF_16_BE_ENCODING_FORMAT)) { - outputBuffer.put(writeStringUTF16BEBOM(next, i, values.size())); - } - } else { - outputBuffer.put(writeString(Charset.forName(charSetName).newEncoder(), next, i, values.size())); - } - } - outputBuffer.flip(); - data = new byte[outputBuffer.limit()]; - outputBuffer.rewind(); - outputBuffer.get(data, 0, outputBuffer.limit()); - setSize(data.length); - } - //Should never happen so if does throw a RuntimeException - catch (CharacterCodingException ce) { - logger.severe(ce.getMessage()); - throw new RuntimeException(ce); - } - return data; - } - - /** - * Get the text encoding being used. - *

    - * The text encoding is defined by the frame body that the text field belongs to. - * - * @return the text encoding charset - */ - protected String getTextEncodingCharSet() { - byte textEncoding = this.getBody().getTextEncoding(); - String charSetName = TextEncoding.getInstanceOf().getValueForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charSetName); - return charSetName; - } - - /** - * Add an additional String to the current String value - * - * @param value - */ - public void addValue(String value) { - setValue(this.value + "\u0000" + value); - } - - /** - * How many values are held, each value is separated by a null terminator - * - * @return number of values held, usually this will be one. - */ - public int getNumberOfValues() { - return splitByNullSeperator(((String) value)).size(); - } - - /** - * Get the nth value - * - * @param index - * @return the nth value - * @throws IndexOutOfBoundsException if value does not exist - */ - public String getValueAtIndex(int index) { - //Split String into separate components - List values = splitByNullSeperator((String) value); - return (String) values.get(index); - } - - /** - * @return list of all values - */ - public List getValues() { - return splitByNullSeperator((String) value); - } - - /** - * Get value(s) whilst removing any trailing nulls - * - * @return - */ - public String getValueWithoutTrailingNull() { - List values = splitByNullSeperator((String) value); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < values.size(); i++) { - if (i != 0) { - sb.append("\u0000"); - } - sb.append(values.get(i)); - } - return sb.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/datatype/package.html b/src/main/java/org/jaudiotagger/tag/datatype/package.html deleted file mode 100644 index 28004cc..0000000 --- a/src/main/java/org/jaudiotagger/tag/datatype/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Data type implementations, primarily for ID3 metadata. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/flac/FlacTag.java b/src/main/java/org/jaudiotagger/tag/flac/FlacTag.java deleted file mode 100644 index 94b490d..0000000 --- a/src/main/java/org/jaudiotagger/tag/flac/FlacTag.java +++ /dev/null @@ -1,402 +0,0 @@ -package org.jaudiotagger.tag.flac; - -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.reference.PictureTypes; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey; -import org.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Flac uses Vorbis Comment for most of its metadata and a Flac Picture Block for images - *

    - *

    - * This class enscapulates the items into a single tag - */ -public class FlacTag implements Tag { - private VorbisCommentTag tag = null; - private List images = new ArrayList(); - - public FlacTag() { - this(VorbisCommentTag.createNewTag(), new ArrayList()); - } - - public FlacTag(VorbisCommentTag tag, List images) { - this.tag = tag; - this.images = images; - } - - /** - * @return images - */ - public List getImages() { - return images; - } - - /** - * @return the vorbis tag (this is what handles text metadata) - */ - public VorbisCommentTag getVorbisCommentTag() { - return tag; - } - - public void addField(TagField field) throws FieldDataInvalidException { - if (field instanceof MetadataBlockDataPicture) { - images.add((MetadataBlockDataPicture) field); - } else { - tag.addField(field); - } - } - - public List getFields(String id) { - if (id.equals(FieldKey.COVER_ART.name())) { - List castImages = new ArrayList(); - for (MetadataBlockDataPicture image : images) { - castImages.add(image); - } - return castImages; - } else { - return tag.getFields(id); - } - } - - /** - * Maps the generic key to the specific key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == FieldKey.COVER_ART) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } else { - return tag.getAll(genericKey); - } - } - - public boolean hasCommonFields() { - return tag.hasCommonFields(); - } - - - /** - * Determines whether the tag has no fields specified.
    - *

    - *

    If there are no images we return empty if either there is no VorbisTag or if there is a - * VorbisTag but it is empty - * - * @return true if tag contains no field. - */ - public boolean isEmpty() { - return (tag == null || tag.isEmpty()) && images.size() == 0; - } - - public void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - /** - * Create and set field with name of vorbisCommentkey - * - * @param vorbisCommentKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void setField(String vorbisCommentKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(vorbisCommentKey, value); - setField(tagfield); - } - - /** - * Create and add field with name of vorbisCommentkey - * - * @param vorbisCommentKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void addField(String vorbisCommentKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(vorbisCommentKey, value); - addField(tagfield); - } - - /** - * @param field - * @throws FieldDataInvalidException - */ - public void setField(TagField field) throws FieldDataInvalidException { - if (field instanceof MetadataBlockDataPicture) { - if (images.size() == 0) { - images.add(0, (MetadataBlockDataPicture) field); - } else { - images.set(0, (MetadataBlockDataPicture) field); - } - } else { - tag.setField(field); - } - } - - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (genericKey.equals(FieldKey.COVER_ART)) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } else { - return tag.createField(genericKey, value); - } - } - - /** - * Create Tag Field using ogg key - * - * @param vorbisCommentFieldKey - * @param value - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public TagField createField(VorbisCommentFieldKey vorbisCommentFieldKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (vorbisCommentFieldKey.equals(VorbisCommentFieldKey.COVERART)) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } - return tag.createField(vorbisCommentFieldKey, value); - } - - /** - * Create Tag Field using ogg key - *

    - * This method is provided to allow you to create key of any value because VorbisComment allows - * arbitary keys. - * - * @param vorbisCommentFieldKey - * @param value - * @return - */ - public TagField createField(String vorbisCommentFieldKey, String value) { - if (vorbisCommentFieldKey.equals(VorbisCommentFieldKey.COVERART.getFieldName())) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } - return tag.createField(vorbisCommentFieldKey, value); - } - - public String getFirst(String id) { - if (id.equals(FieldKey.COVER_ART.name())) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } else { - return tag.getFirst(id); - } - } - - public String getValue(FieldKey id, int index) throws KeyNotFoundException { - if (id.equals(FieldKey.COVER_ART)) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_RETRIEVED_WITH_THIS_METHOD.getMsg()); - } else { - return tag.getValue(id, index); - } - } - - public String getFirst(FieldKey id) throws KeyNotFoundException { - return getValue(id, 0); - } - - public TagField getFirstField(String id) { - if (id.equals(FieldKey.COVER_ART.name())) { - if (images.size() > 0) { - return images.get(0); - } else { - return null; - } - } else { - return tag.getFirstField(id); - } - } - - public TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - if (genericKey == FieldKey.COVER_ART) { - return getFirstField(FieldKey.COVER_ART.name()); - } else { - return tag.getFirstField(genericKey); - } - } - - /** - * Delete any instance of tag fields with this key - * - * @param fieldKey - */ - public void deleteField(FieldKey fieldKey) throws KeyNotFoundException { - if (fieldKey.equals(FieldKey.COVER_ART)) { - images.clear(); - } else { - tag.deleteField(fieldKey); - } - } - - public void deleteField(String id) throws KeyNotFoundException { - if (id.equals(FieldKey.COVER_ART.name())) { - images.clear(); - } else { - tag.deleteField(id); - } - } - - - //TODO addField images to iterator - public Iterator getFields() { - return tag.getFields(); - } - - public int getFieldCount() { - return tag.getFieldCount() + images.size(); - } - - public int getFieldCountIncludingSubValues() { - return getFieldCount(); - } - - public boolean setEncoding(String enc) throws FieldDataInvalidException { - return tag.setEncoding(enc); - } - - public List getFields(FieldKey id) throws KeyNotFoundException { - if (id.equals(FieldKey.COVER_ART)) { - List castImages = new ArrayList(); - for (MetadataBlockDataPicture image : images) { - castImages.add(image); - } - return castImages; - } else { - return tag.getFields(id); - } - } - - public TagField createArtworkField(byte[] imageData, int pictureType, String mimeType, String description, int width, int height, int colourDepth, int indexedColouredCount) throws FieldDataInvalidException { - return new MetadataBlockDataPicture(imageData, pictureType, mimeType, description, width, height, colourDepth, indexedColouredCount); - } - - /** - * Create Link to Image File, not recommended because if either flac or image file is moved link - * will be broken. - * - * @param url - * @return - */ - public TagField createLinkedArtworkField(String url) { - //Add to image list - return new MetadataBlockDataPicture(Utils.getDefaultBytes(url, TextEncoding.CHARSET_ISO_8859_1), PictureTypes.DEFAULT_ID, MetadataBlockDataPicture.IMAGE_IS_URL, "", 0, 0, 0, 0); - } - - /** - * Create artwork field - * - * @return - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - if (artwork.isLinked()) { - return new MetadataBlockDataPicture( - Utils.getDefaultBytes(artwork.getImageUrl(), TextEncoding.CHARSET_ISO_8859_1), - artwork.getPictureType(), - MetadataBlockDataPicture.IMAGE_IS_URL, - "", - 0, - 0, - 0, - 0); - } else { - if (!artwork.setImageFromData()) { - throw new FieldDataInvalidException("Unable to createField buffered image from the image"); - } - - return new MetadataBlockDataPicture(artwork.getBinaryData(), - artwork.getPictureType(), - artwork.getMimeType(), - artwork.getDescription(), - artwork.getWidth(), - artwork.getHeight(), - 0, - 0); - } - } - - public void setField(Artwork artwork) throws FieldDataInvalidException { - this.setField(createField(artwork)); - } - - public void addField(Artwork artwork) throws FieldDataInvalidException { - this.addField(createField(artwork)); - } - - public List getArtworkList() { - List artworkList = new ArrayList(images.size()); - - for (MetadataBlockDataPicture coverArt : images) { - Artwork artwork = ArtworkFactory.createArtworkFromMetadataBlockDataPicture(coverArt); - artworkList.add(artwork); - } - return artworkList; - } - - public Artwork getFirstArtwork() { - List artwork = getArtworkList(); - if (artwork.size() > 0) { - return artwork.get(0); - } - return null; - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException { - this.deleteField(FieldKey.COVER_ART); - } - - /** - * @param genericKey - * @return - */ - public boolean hasField(FieldKey genericKey) { - if (genericKey == FieldKey.COVER_ART) { - return images.size() > 0; - } else { - return tag.hasField(genericKey); - } - } - - /** - * @param vorbisFieldKey - * @return - */ - public boolean hasField(VorbisCommentFieldKey vorbisFieldKey) { - return tag.hasField(vorbisFieldKey); - } - - public boolean hasField(String id) { - if (id.equals(FieldKey.COVER_ART.name())) { - return images.size() > 0; - } else { - return tag.hasField(id); - } - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/flac/package.html b/src/main/java/org/jaudiotagger/tag/flac/package.html deleted file mode 100644 index 540f6d2..0000000 --- a/src/main/java/org/jaudiotagger/tag/flac/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Implements a pseudo-tag data object for FLAC. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3Tag.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractID3Tag.java deleted file mode 100644 index f8f6a1d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3Tag.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractID3Tag.java 973 2011-06-07 13:51:31Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Base class for all ID3 tags - */ -package org.jaudiotagger.tag.id3; - -import java.util.logging.Logger; - -/** - * This is the abstract base class for all ID3 tags. - * - * @author : Eric Farng - * @author : Paul Taylor - */ -public abstract class AbstractID3Tag extends AbstractTag { - protected static final String TAG_RELEASE = "ID3v"; - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - //The purpose of this is to provide the filename that should be used when writing debug messages - //when problems occur reading or writing to file, otherwise it is difficult to track down the error - //when processing many files - private String loggingFilename = ""; - - public AbstractID3Tag() { - } - - public AbstractID3Tag(AbstractID3Tag copyObject) { - super(copyObject); - } - - /** - * Get full version - */ - public String getIdentifier() { - return TAG_RELEASE + getRelease() + "." + getMajorVersion() + "." + getRevision(); - } - - /** - * Retrieve the Release - * - * @return - */ - public abstract byte getRelease(); - - /** - * Retrieve the Major Version - * - * @return - */ - public abstract byte getMajorVersion(); - - /** - * Retrieve the Revision - * - * @return - */ - public abstract byte getRevision(); - - /** - * Retrieve the logging filename to be used in debugging - * - * @return logging filename to be used in debugging - */ - protected String getLoggingFilename() { - return loggingFilename; - } - - /** - * Set logging filename when construct tag for read from file - * - * @param loggingFilename - */ - protected void setLoggingFilename(String loggingFilename) { - this.loggingFilename = loggingFilename; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v1Tag.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v1Tag.java deleted file mode 100644 index f6c6c7d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v1Tag.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractID3v1Tag.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Abstract superclass of all URL Frames - */ -package org.jaudiotagger.tag.id3; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.Arrays; -import java.util.logging.Logger; -import java.util.regex.Pattern; - -/** - * This is the abstract base class for all ID3v1 tags. - * - * @author : Eric Farng - * @author : Paul Taylor - */ -abstract public class AbstractID3v1Tag extends AbstractID3Tag { - - //If field is less than maximum field length this is how it is terminated - protected static final byte END_OF_FIELD = (byte) 0; - //Tag ID as held in file - protected static final byte[] TAG_ID = {(byte) 'T', (byte) 'A', (byte) 'G'}; - //Fields Lengths common to v1 and v1.1 tags - protected static final int TAG_LENGTH = 128; - protected static final int TAG_DATA_LENGTH = 125; - protected static final int FIELD_TAGID_LENGTH = 3; - protected static final int FIELD_TITLE_LENGTH = 30; - protected static final int FIELD_ARTIST_LENGTH = 30; - protected static final int FIELD_ALBUM_LENGTH = 30; - protected static final int FIELD_YEAR_LENGTH = 4; - protected static final int FIELD_GENRE_LENGTH = 1; - //Field Positions, starting from zero so fits in with Java Terminology - protected static final int FIELD_TAGID_POS = 0; - protected static final int FIELD_TITLE_POS = 3; - protected static final int FIELD_ARTIST_POS = 33; - protected static final int FIELD_ALBUM_POS = 63; - protected static final int FIELD_YEAR_POS = 93; - protected static final int FIELD_GENRE_POS = 127; - //For writing output - protected static final String TYPE_TITLE = "title"; - protected static final String TYPE_ARTIST = "artist"; - protected static final String TYPE_ALBUM = "album"; - protected static final String TYPE_YEAR = "year"; - protected static final String TYPE_GENRE = "genre"; - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - //Used to detect end of field in String constructed from Data - protected static Pattern endofStringPattern = Pattern.compile("\\x00"); - public AbstractID3v1Tag() { - } - public AbstractID3v1Tag(AbstractID3v1Tag copyObject) { - super(copyObject); - } - - /** - * Does a v1tag or a v11tag exist - * - * @return whether tag exists within the byteBuffer - */ - public static boolean seekForV1OrV11Tag(ByteBuffer byteBuffer) { - byte[] buffer = new byte[FIELD_TAGID_LENGTH]; - // read the TAG value - byteBuffer.get(buffer, 0, FIELD_TAGID_LENGTH); - return (Arrays.equals(buffer, TAG_ID)); - } - - /** - * Return the size of this tag, the size is fixed for tags of this type - * - * @return size of this tag in bytes - */ - public int getSize() { - return TAG_LENGTH; - } - - /** - * Delete tag from file - * Looks for tag and if found lops it off the file. - * - * @param file to delete the tag from - * @throws IOException if there was a problem accessing the file - */ - public void delete(RandomAccessFile file) throws IOException { - //Read into Byte Buffer - logger.config("Deleting ID3v1 from file if exists"); - - FileChannel fc; - ByteBuffer byteBuffer; - fc = file.getChannel(); - - if (file.length() < TAG_LENGTH) { - throw new IOException("File not not appear large enough to contain a tag"); - } - fc.position(file.length() - TAG_LENGTH); - byteBuffer = ByteBuffer.allocate(TAG_LENGTH); - fc.read(byteBuffer); - byteBuffer.rewind(); - if (AbstractID3v1Tag.seekForV1OrV11Tag(byteBuffer)) { - logger.config("Deleted ID3v1 tag"); - file.setLength(file.length() - TAG_LENGTH); - } else { - logger.config("Unable to find ID3v1 tag to deleteField"); - } - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v2Frame.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v2Frame.java deleted file mode 100644 index 5e571bb..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v2Frame.java +++ /dev/null @@ -1,554 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import org.jaudiotagger.tag.id3.framebody.FrameBodyEncrypted; -import org.jaudiotagger.tag.id3.framebody.FrameBodyUnsupported; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.nio.ByteBuffer; -import java.util.logging.Level; - -/** - * This abstract class is each frame header inside a ID3v2 tag. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: AbstractID3v2Frame.java 1028 2012-03-01 11:07:39Z paultaylor $ - */ -public abstract class AbstractID3v2Frame extends AbstractTagFrame implements TagTextField { - - protected static final String TYPE_FRAME = "frame"; - protected static final String TYPE_FRAME_SIZE = "frameSize"; - protected static final String UNSUPPORTED_ID = "Unsupported"; - - //Frame identifier - protected String identifier = ""; - - //Frame Size - protected int frameSize; - /** - * This holds the Status flags (not supported in v2.20 - */ - StatusFlags statusFlags = null; - /** - * This holds the Encoding flags (not supported in v2.20) - */ - EncodingFlags encodingFlags = null; - //The purpose of this is to provide the filename that should be used when writing debug messages - //when problems occur reading or writing to file, otherwise it is difficult to track down the error - //when processing many files - private String loggingFilename = ""; - - /** - * Create an empty frame - */ - protected AbstractID3v2Frame() { - } - - /** - * Create a frame based on another frame - * - * @param frame - */ - public AbstractID3v2Frame(AbstractID3v2Frame frame) { - super(frame); - } - - /** - * Create a frame based on a body - * - * @param body - */ - public AbstractID3v2Frame(AbstractID3v2FrameBody body) { - this.frameBody = body; - this.frameBody.setHeader(this); - } - - /** - * Create a new frame with empty body based on identifier - * - * @param identifier - */ - //TODO the identifier checks should be done in the relevent subclasses - public AbstractID3v2Frame(String identifier) { - logger.config("Creating empty frame of type" + identifier); - this.identifier = identifier; - - // Use reflection to map id to frame body, which makes things much easier - // to keep things up to date. - try { - Class c = (Class) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier); - frameBody = c.newInstance(); - } catch (ClassNotFoundException cnfe) { - logger.severe(cnfe.getMessage()); - frameBody = new FrameBodyUnsupported(identifier); - } - //Instantiate Interface/Abstract should not happen - catch (InstantiationException ie) { - logger.log(Level.SEVERE, "InstantiationException:" + identifier, ie); - throw new RuntimeException(ie); - } - //Private Constructor shouild not happen - catch (IllegalAccessException iae) { - logger.log(Level.SEVERE, "IllegalAccessException:" + identifier, iae); - throw new RuntimeException(iae); - } - frameBody.setHeader(this); - if (this instanceof ID3v24Frame) { - frameBody.setTextEncoding(TagOptionSingleton.getInstance().getId3v24DefaultTextEncoding()); - } else if (this instanceof ID3v23Frame) { - frameBody.setTextEncoding(TagOptionSingleton.getInstance().getId3v23DefaultTextEncoding()); - } - - logger.config("Created empty frame of type" + identifier); - } - - /** - * @return size in bytes of the frameid field - */ - protected abstract int getFrameIdSize(); - - /** - * @return the size in bytes of the frame size field - */ - protected abstract int getFrameSizeSize(); - - /** - * @return the size in bytes of the frame header - */ - protected abstract int getFrameHeaderSize(); - - /** - * Retrieve the logging filename to be used in debugging - * - * @return logging filename to be used in debugging - */ - protected String getLoggingFilename() { - return loggingFilename; - } - - /** - * Set logging filename when construct tag for read from file - * - * @param loggingFilename - */ - protected void setLoggingFilename(String loggingFilename) { - this.loggingFilename = loggingFilename; - } - - /** - * Return the frame identifier, this only identifies the frame it does not provide a unique - * key, when using frames such as TXXX which are used by many fields * - * - * @return the frame identifier (Tag Field Interface) - */ - //TODO, this is confusing only returns the frameId, which does not neccessarily uniquely - //identify the frame - public String getId() { - return getIdentifier(); - } - - /** - * Return the frame identifier - * - * @return the frame identifier - */ - public String getIdentifier() { - return identifier; - } - - //TODO:needs implementing but not sure if this method is required at all - public void copyContent(TagField field) { - - } - - /** - * Read the frameBody when frame marked as encrypted - * - * @param identifier - * @param byteBuffer - * @param frameSize - * @return - * @throws InvalidFrameException - * @throws InvalidDataTypeException - * @throws InvalidTagException - */ - protected AbstractID3v2FrameBody readEncryptedBody(String identifier, ByteBuffer byteBuffer, int frameSize) - throws InvalidFrameException, InvalidDataTypeException { - try { - AbstractID3v2FrameBody frameBody = new FrameBodyEncrypted(identifier, byteBuffer, frameSize); - frameBody.setHeader(this); - return frameBody; - } catch (InvalidTagException ite) { - throw new InvalidDataTypeException(ite); - } - } - - protected boolean isPadding(byte[] buffer) { - return (buffer[0] == '\0') && - (buffer[1] == '\0') && - (buffer[2] == '\0') && - (buffer[3] == '\0'); - } - - /** - * Read the frame body from the specified file via the buffer - * - * @param identifier the frame identifier - * @param byteBuffer to read the frame body from - * @param frameSize - * @return a newly created FrameBody - * @throws InvalidFrameException unable to construct a framebody from the data - */ - @SuppressWarnings("unchecked") - //TODO using reflection is rather slow perhaps we should change this - protected AbstractID3v2FrameBody readBody(String identifier, ByteBuffer byteBuffer, int frameSize) - throws InvalidFrameException, InvalidDataTypeException { - //Use reflection to map id to frame body, which makes things much easier - //to keep things up to date,although slight performance hit. - logger.finest("Creating framebody:start"); - - AbstractID3v2FrameBody frameBody; - try { - Class c = (Class) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier); - Class[] constructorParameterTypes = {Class.forName("java.nio.ByteBuffer"), Integer.TYPE}; - Object[] constructorParameterValues = {byteBuffer, frameSize}; - Constructor construct = c.getConstructor(constructorParameterTypes); - frameBody = (construct.newInstance(constructorParameterValues)); - } - //No class defined for this frame type,use FrameUnsupported - catch (ClassNotFoundException cex) { - logger.config(getLoggingFilename() + ":" + "Identifier not recognised:" + identifier + " using FrameBodyUnsupported"); - try { - frameBody = new FrameBodyUnsupported(byteBuffer, frameSize); - } - //Should only throw InvalidFrameException but unfortunately legacy hierachy forces - //read method to declare it can throw InvalidtagException - catch (InvalidFrameException ife) { - throw ife; - } catch (InvalidTagException te) { - throw new InvalidFrameException(te.getMessage()); - } - } - //An error has occurred during frame instantiation, if underlying cause is an unchecked exception or error - //propagate it up otherwise mark this frame as invalid - catch (InvocationTargetException ite) { - logger.severe(getLoggingFilename() + ":" + "An error occurred within abstractID3v2FrameBody for identifier:" + identifier + ":" + ite.getCause().getMessage()); - if (ite.getCause() instanceof Error) { - throw (Error) ite.getCause(); - } else if (ite.getCause() instanceof RuntimeException) { - throw (RuntimeException) ite.getCause(); - } else if (ite.getCause() instanceof InvalidFrameException) { - throw (InvalidFrameException) ite.getCause(); - } else if (ite.getCause() instanceof InvalidDataTypeException) { - throw (InvalidDataTypeException) ite.getCause(); - } else { - throw new InvalidFrameException(ite.getCause().getMessage()); - } - } - //No Such Method should not happen - catch (NoSuchMethodException sme) { - logger.log(Level.SEVERE, getLoggingFilename() + ":" + "No such method:" + sme.getMessage(), sme); - throw new RuntimeException(sme.getMessage()); - } - //Instantiate Interface/Abstract should not happen - catch (InstantiationException ie) { - logger.log(Level.SEVERE, getLoggingFilename() + ":" + "Instantiation exception:" + ie.getMessage(), ie); - throw new RuntimeException(ie.getMessage()); - } - //Private Constructor shouild not happen - catch (IllegalAccessException iae) { - logger.log(Level.SEVERE, getLoggingFilename() + ":" + "Illegal access exception :" + iae.getMessage(), iae); - throw new RuntimeException(iae.getMessage()); - } - logger.finest(getLoggingFilename() + ":" + "Created framebody:end" + frameBody.getIdentifier()); - frameBody.setHeader(this); - return frameBody; - } - - /** - * Get the next frame id, throwing an exception if unable to do this and check against just having padded data - * - * @param byteBuffer - * @return - * @throws PaddingException - * @throws InvalidFrameException - */ - protected String readIdentifier(ByteBuffer byteBuffer) throws InvalidFrameException { - byte[] buffer = new byte[getFrameIdSize()]; - - if (byteBuffer.position() + getFrameHeaderSize() >= byteBuffer.limit()) { - logger.warning(getLoggingFilename() + ":" + "No space to find another frame:"); - throw new InvalidFrameException(getLoggingFilename() + ":" + "No space to find another frame"); - } - - //Read the Frame Identifier - byteBuffer.get(buffer, 0, getFrameIdSize()); - - if (isPadding(buffer)) { - throw new PaddingException(getLoggingFilename() + ":only padding found"); - } - - identifier = new String(buffer); - logger.fine(getLoggingFilename() + ":" + "Identifier is" + identifier); - return identifier; - } - - /** - * This creates a new body based of type identifier but populated by the data - * in the body. This is a different type to the body being created which is why - * TagUtility.copyObject() can't be used. This is used when converting between - * different versions of a tag for frames that have a non-trivial mapping such - * as TYER in v3 to TDRC in v4. This will only work where appropriate constructors - * exist in the frame body to be created, for example a FrameBodyTYER requires a constructor - * consisting of a FrameBodyTDRC. - *

    - * If this method is called and a suitable constructor does not exist then an InvalidFrameException - * will be thrown - * - * @param identifier to determine type of the frame - * @param body - * @return newly created framebody for this type - * @throws InvalidFrameException if unable to construct a framebody for the identifier and body provided. - */ - @SuppressWarnings("unchecked") - //TODO using reflection is rather slow perhaps we should change this - protected AbstractID3v2FrameBody readBody(String identifier, AbstractID3v2FrameBody body) throws InvalidFrameException { - /* Use reflection to map id to frame body, which makes things much easier - * to keep things up to date, although slight performance hit. - */ - AbstractID3v2FrameBody frameBody; - try { - Class c = (Class) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier); - Class[] constructorParameterTypes = {body.getClass()}; - Object[] constructorParameterValues = {body}; - Constructor construct = c.getConstructor(constructorParameterTypes); - frameBody = (construct.newInstance(constructorParameterValues)); - } catch (ClassNotFoundException cex) { - logger.config("Identifier not recognised:" + identifier + " unable to create framebody"); - throw new InvalidFrameException("FrameBody" + identifier + " does not exist"); - } - //If suitable constructor does not exist - catch (NoSuchMethodException sme) { - logger.log(Level.SEVERE, "No such method:" + sme.getMessage(), sme); - throw new InvalidFrameException("FrameBody" + identifier + " does not have a constructor that takes:" + body.getClass().getName()); - } catch (InvocationTargetException ite) { - logger.severe("An error occurred within abstractID3v2FrameBody"); - logger.log(Level.SEVERE, "Invocation target exception:" + ite.getCause().getMessage(), ite.getCause()); - if (ite.getCause() instanceof Error) { - throw (Error) ite.getCause(); - } else if (ite.getCause() instanceof RuntimeException) { - throw (RuntimeException) ite.getCause(); - } else { - throw new InvalidFrameException(ite.getCause().getMessage()); - } - } - - //Instantiate Interface/Abstract should not happen - catch (InstantiationException ie) { - logger.log(Level.SEVERE, "Instantiation exception:" + ie.getMessage(), ie); - throw new RuntimeException(ie.getMessage()); - } - //Private Constructor shouild not happen - catch (IllegalAccessException iae) { - logger.log(Level.SEVERE, "Illegal access exception :" + iae.getMessage(), iae); - throw new RuntimeException(iae.getMessage()); - } - - logger.finer("frame Body created" + frameBody.getIdentifier()); - frameBody.setHeader(this); - return frameBody; - } - - public byte[] getRawContent() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - write(baos); - return baos.toByteArray(); - } - - public abstract void write(ByteArrayOutputStream tagBuffer); - - /** - * @param b - */ - public void isBinary(boolean b) { - //do nothing because whether or not a field is binary is defined by its id and is immutable - } - - - public boolean isEmpty() { - AbstractTagFrameBody body = this.getBody(); - if (body == null) { - return true; - } - //TODO depends on the body - return false; - } - - public StatusFlags getStatusFlags() { - return statusFlags; - } - - public EncodingFlags getEncodingFlags() { - return encodingFlags; - } - - /** - * Return String Representation of frame - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FRAME, getIdentifier()); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FRAME); - } - - public boolean equals(Object obj) { - if (this == obj) return true; - if (!(obj instanceof AbstractID3v2Frame)) { - return false; - } - - AbstractID3v2Frame that = (AbstractID3v2Frame) obj; - return super.equals(that); - } - - /** - * Returns the content of the field. - *

    - * For frames consisting of different fields, this will return the value deemed to be most - * likely to be required - * - * @return Content - */ - public String getContent() { - return getBody().getUserFriendlyValue(); - } - - /** - * Sets the content of the field. - * - * @param content fields content. - */ - public void setContent(String content) { - throw new UnsupportedOperationException("Not implemented please use the generic tag methods for setting content"); - } - - /** - * Returns the current used charset encoding. - * - * @return Charset encoding. - */ - public String getEncoding() { - return TextEncoding.getInstanceOf().getValueForId(this.getBody().getTextEncoding()); - } - - public class StatusFlags { - protected static final String TYPE_FLAGS = "statusFlags"; - - protected byte originalFlags; - protected byte writeFlags; - - protected StatusFlags() { - - } - - /** - * This returns the flags as they were originally read or created - * - * @return - */ - public byte getOriginalFlags() { - return originalFlags; - } - - /** - * This returns the flags amended to meet specification - * - * @return - */ - public byte getWriteFlags() { - return writeFlags; - } - - public void createStructure() { - } - - public boolean equals(Object obj) { - if (this == obj) return true; - - if (!(obj instanceof StatusFlags)) { - return false; - } - StatusFlags that = (StatusFlags) obj; - - - return - EqualsUtil.areEqual(this.getOriginalFlags(), that.getOriginalFlags()) && - EqualsUtil.areEqual(this.getWriteFlags(), that.getWriteFlags()); - - } - } - - class EncodingFlags { - protected static final String TYPE_FLAGS = "encodingFlags"; - - protected byte flags; - - protected EncodingFlags() { - resetFlags(); - } - - protected EncodingFlags(byte flags) { - setFlags(flags); - } - - public byte getFlags() { - return flags; - } - - public void setFlags(byte flags) { - this.flags = flags; - } - - public void resetFlags() { - setFlags((byte) 0); - } - - public void createStructure() { - } - - public boolean equals(Object obj) { - if (this == obj) return true; - - if (!(obj instanceof EncodingFlags)) { - return false; - } - EncodingFlags that = (EncodingFlags) obj; - - - return EqualsUtil.areEqual(this.getFlags(), that.getFlags()); - - } - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v2Tag.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v2Tag.java deleted file mode 100644 index c324018..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractID3v2Tag.java +++ /dev/null @@ -1,2367 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.exceptions.UnableToCreateFileException; -import org.jaudiotagger.audio.exceptions.UnableToModifyFileException; -import org.jaudiotagger.audio.exceptions.UnableToRenameFileException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.logging.FileSystemMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.Pair; -import org.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import org.jaudiotagger.tag.id3.framebody.*; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.reference.Languages; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.nio.channels.WritableByteChannel; -import java.util.*; -import java.util.logging.Level; - -/** - * This is the abstract base class for all ID3v2 tags. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: AbstractID3v2Tag.java 1082 2013-01-06 09:38:14Z paultaylor $ - */ -public abstract class AbstractID3v2Tag extends AbstractID3Tag implements Tag { - //The tag header is the same for ID3v2 versions - public static final int TAG_HEADER_LENGTH = 10; - protected static final String TYPE_HEADER = "header"; - protected static final String TYPE_BODY = "body"; - //Tag ID as held in file - protected static final byte[] TAG_ID = {'I', 'D', '3'}; - protected static final int FIELD_TAGID_LENGTH = 3; - protected static final int FIELD_TAG_MAJOR_VERSION_LENGTH = 1; - protected static final int FIELD_TAG_MINOR_VERSION_LENGTH = 1; - protected static final int FIELD_TAG_FLAG_LENGTH = 1; - protected static final int FIELD_TAG_SIZE_LENGTH = 4; - - protected static final int FIELD_TAGID_POS = 0; - protected static final int FIELD_TAG_MAJOR_VERSION_POS = 3; - protected static final int FIELD_TAG_MINOR_VERSION_POS = 4; - protected static final int FIELD_TAG_FLAG_POS = 5; - protected static final int FIELD_TAG_SIZE_POS = 6; - - protected static final int TAG_SIZE_INCREMENT = 100; - /** - * Holds the ids of invalid duplicate frames - */ - protected static final String TYPE_DUPLICATEFRAMEID = "duplicateFrameId"; - /** - * Holds count the number of bytes used up by invalid duplicate frames - */ - protected static final String TYPE_DUPLICATEBYTES = "duplicateBytes"; - /** - * Holds count the number bytes used up by empty frames - */ - protected static final String TYPE_EMPTYFRAMEBYTES = "emptyFrameBytes"; - /** - * Holds the size of the tag as reported by the tag header - */ - protected static final String TYPE_FILEREADSIZE = "fileReadSize"; - /** - * Holds count of invalid frames, (frames that could not be read) - */ - protected static final String TYPE_INVALIDFRAMES = "invalidFrames"; - //The max size we try to write in one go to avoid out of memory errors (10mb) - private static final long MAXIMUM_WRITABLE_CHUNK_SIZE = 10000000; - /** - * Map of all frames for this tag - */ - public HashMap frameMap = null; - /** - * Map of all encrypted frames, these cannot be unencrypted by jaudiotagger - */ - public HashMap encryptedFrameMap = null; - protected String duplicateFrameId = ""; - protected int duplicateBytes = 0; - protected int emptyFrameBytes = 0; - protected int fileReadSize = 0; - protected int invalidFrames = 0; - - /** - * Empty Constructor - */ - public AbstractID3v2Tag() { - } - - /** - * This constructor is used when a tag is created as a duplicate of another - * tag of the same type and version. - * - * @param copyObject - */ - protected AbstractID3v2Tag(AbstractID3v2Tag copyObject) { - } - - /** - * True if files has a ID3v2 header - * - * @param raf - * @return - * @throws IOException - */ - private static boolean isID3V2Header(RandomAccessFile raf) throws IOException { - long start = raf.getFilePointer(); - byte[] tagIdentifier = new byte[FIELD_TAGID_LENGTH]; - raf.read(tagIdentifier); - raf.seek(start); - return Arrays.equals(tagIdentifier, TAG_ID); - } - - /** - * Determines if file contain an id3 tag and if so positions the file pointer just after the end - * of the tag. - *

    - * This method is used by non mp3s (such as .ogg and .flac) to determine if they contain an id3 tag - * - * @param raf - * @return - * @throws IOException - */ - public static boolean isId3Tag(RandomAccessFile raf) throws IOException { - if (!isID3V2Header(raf)) { - return false; - } - //So we have a tag - byte[] tagHeader = new byte[FIELD_TAG_SIZE_LENGTH]; - raf.seek(raf.getFilePointer() + 6); - raf.read(tagHeader); - ByteBuffer bb = ByteBuffer.wrap(tagHeader); - - int size = ID3SyncSafeInteger.bufferToValue(bb); - raf.seek(size + TAG_HEADER_LENGTH); - return true; - } - - /** - * Checks to see if the file contains an ID3tag and if so return its size as reported in - * the tag header and return the size of the tag (including header), if no such tag exists return - * zero. - * - * @param file - * @return the end of the tag in the file or zero if no tag exists. - * @throws java.io.IOException - */ - public static long getV2TagSizeIfExists(File file) throws IOException { - FileInputStream fis = null; - FileChannel fc = null; - ByteBuffer bb = null; - try { - //Files - fis = new FileInputStream(file); - fc = fis.getChannel(); - - //Read possible Tag header Byte Buffer - bb = ByteBuffer.allocate(TAG_HEADER_LENGTH); - fc.read(bb); - bb.flip(); - if (bb.limit() < (TAG_HEADER_LENGTH)) { - return 0; - } - } finally { - if (fc != null) { - fc.close(); - } - - if (fis != null) { - fis.close(); - } - } - - //ID3 identifier - byte[] tagIdentifier = new byte[FIELD_TAGID_LENGTH]; - bb.get(tagIdentifier, 0, FIELD_TAGID_LENGTH); - if (!(Arrays.equals(tagIdentifier, TAG_ID))) { - return 0; - } - - //Is it valid Major Version - byte majorVersion = bb.get(); - if ((majorVersion != ID3v22Tag.MAJOR_VERSION) && (majorVersion != ID3v23Tag.MAJOR_VERSION) && (majorVersion != ID3v24Tag.MAJOR_VERSION)) { - return 0; - } - - //Skip Minor Version - bb.get(); - - //Skip Flags - bb.get(); - - //Get size as recorded in frame header - int frameSize = ID3SyncSafeInteger.bufferToValue(bb); - - //addField header size to frame size - frameSize += TAG_HEADER_LENGTH; - return frameSize; - } - - /** - * Copy primitives apply to all tags - * - * @param copyObject - */ - protected void copyPrimitives(AbstractID3v2Tag copyObject) { - logger.config("Copying Primitives"); - //Primitives type variables common to all IDv2 Tags - this.duplicateFrameId = copyObject.duplicateFrameId; - this.duplicateBytes = copyObject.duplicateBytes; - this.emptyFrameBytes = copyObject.emptyFrameBytes; - this.fileReadSize = copyObject.fileReadSize; - this.invalidFrames = copyObject.invalidFrames; - } - - /** - * Copy frames from another tag, - * - * @param copyObject - */ - //TODO Copy Encrypted frames needs implementing - protected void copyFrames(AbstractID3v2Tag copyObject) { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - //Copy Frames that are a valid 2.4 type - - for (Object o1 : copyObject.frameMap.keySet()) { - String id = (String) o1; - Object o = copyObject.frameMap.get(id); - //SingleFrames - if (o instanceof AbstractID3v2Frame) { - addFrame((AbstractID3v2Frame) o); - } - //MultiFrames - else if (o instanceof ArrayList) { - for (AbstractID3v2Frame frame : (ArrayList) o) { - addFrame(frame); - } - } - } - } - - protected abstract void addFrame(AbstractID3v2Frame frame); - - /** - * Returns the number of bytes which come from duplicate frames - * - * @return the number of bytes which come from duplicate frames - */ - public int getDuplicateBytes() { - return duplicateBytes; - } - - /** - * Return the string which holds the ids of all - * duplicate frames. - * - * @return the string which holds the ids of all duplicate frames. - */ - public String getDuplicateFrameId() { - return duplicateFrameId; - } - - /** - * Returns the number of bytes which come from empty frames - * - * @return the number of bytes which come from empty frames - */ - public int getEmptyFrameBytes() { - return emptyFrameBytes; - } - - /** - * Return byte count of invalid frames - * - * @return byte count of invalid frames - */ - public int getInvalidFrames() { - return invalidFrames; - } - - /** - * Returns the tag size as reported by the tag header - * - * @return the tag size as reported by the tag header - */ - public int getFileReadBytes() { - return fileReadSize; - } - - /** - * Return whether tag has frame with this identifier - *

    - * Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body - * but happens to have an identifier that is valid for another version of the tag it will return true - * - * @param identifier frameId to lookup - * @return true if tag has frame with this identifier - */ - public boolean hasFrame(String identifier) { - return frameMap.containsKey(identifier); - } - - /** - * Return whether tag has frame with this identifier and a related body. This is required to protect - * against circumstances whereby a tag contains a frame with an unsupported body - * but happens to have an identifier that is valid for another version of the tag which it has been converted to - *

    - * e.g TDRC is an invalid frame in a v23 tag but if somehow a v23tag has been created by another application - * with a TDRC frame we construct an UnsupportedFrameBody to hold it, then this library constructs a - * v24 tag, it will contain a frame with id TDRC but it will not have the expected frame body it is not really a - * TDRC frame. - * - * @param identifier frameId to lookup - * @return true if tag has frame with this identifier - */ - public boolean hasFrameAndBody(String identifier) { - if (hasFrame(identifier)) { - Object o = getFrame(identifier); - if (o instanceof AbstractID3v2Frame) { - return !(((AbstractID3v2Frame) o).getBody() instanceof FrameBodyUnsupported); - } - return true; - } - return false; - } - - /** - * Return whether tag has frame starting with this identifier - *

    - * Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body - * but happens to have an identifier that is valid for another version of the tag it will return true - * - * @param identifier start of frameId to lookup - * @return tag has frame starting with this identifier - */ - public boolean hasFrameOfType(String identifier) { - Iterator iterator = frameMap.keySet().iterator(); - String key; - boolean found = false; - while (iterator.hasNext() && !found) { - key = iterator.next(); - if (key.startsWith(identifier)) { - found = true; - } - } - return found; - } - - /** - * For single frames return the frame in this tag with given identifier if it exists, if multiple frames - * exist with the same identifier it will return a list containing all the frames with this identifier - *

    - * Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body - * but happens to have an identifier that is valid for another version of the tag it will be returned. - *

    - * - * @param identifier is an ID3Frame identifier - * @return matching frame, or list of matching frames - */ - //TODO:This method is problematic because sometimes it returns a list and sometimes a frame, we need to - //replace with two separate methods as in the tag interface. - public Object getFrame(String identifier) { - return frameMap.get(identifier); - } - - /** - * Return any encrypted frames with this identifier - *

    - *

    For single frames return the frame in this tag with given identifier if it exists, if multiple frames - * exist with the same identifier it will return a list containing all the frames with this identifier - * - * @param identifier - * @return - */ - public Object getEncryptedFrame(String identifier) { - return encryptedFrameMap.get(identifier); - } - - /** - * Retrieve the first value that exists for this identifier - *

    - * If the value is a String it returns that, otherwise returns a summary of the fields information - *

    - * - * @param identifier - * @return - */ - public String getFirst(String identifier) { - AbstractID3v2Frame frame = getFirstField(identifier); - if (frame == null) { - return ""; - } - return getTextValueForFrame(frame); - } - - /** - * @param frame - * @return - */ - private String getTextValueForFrame(AbstractID3v2Frame frame) { - return frame.getBody().getUserFriendlyValue(); - } - - public TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException { - List fields = getFields(genericKey); - if (fields.size() > 0) { - return fields.get(0); - } - return null; - } - - /** - * Retrieve the first tag field that exists for this identifier - * - * @param identifier - * @return tag field or null if doesn't exist - */ - public AbstractID3v2Frame getFirstField(String identifier) { - Object object = getFrame(identifier); - if (object == null) { - return null; - } - if (object instanceof List) { - return ((List) object).get(0); - } else { - return (AbstractID3v2Frame) object; - } - } - - /** - * Add a frame to this tag - * - * @param frame the frame to add - *

    - *

    - * Warning if frame(s) already exists for this identifier that they are overwritten - *

    - */ - //TODO needs to ensure do not addField an invalid frame for this tag - //TODO what happens if already contains a list with this ID - public void setFrame(AbstractID3v2Frame frame) { - frameMap.put(frame.getIdentifier(), frame); - } - - protected abstract ID3Frames getID3Frames(); - - public void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - /** - * Add frame taking into account existing frames of the same type - * - * @param newFrame - * @param frames - */ - public void mergeDuplicateFrames(AbstractID3v2Frame newFrame, List frames) { - for (ListIterator li = frames.listIterator(); li.hasNext(); ) { - AbstractID3v2Frame nextFrame = li.next(); - - if (newFrame.getBody() instanceof FrameBodyTXXX) { - //Value with matching key exists so replace - if (((FrameBodyTXXX) newFrame.getBody()).getDescription().equals(((FrameBodyTXXX) nextFrame.getBody()).getDescription())) { - li.set(newFrame); - frameMap.put(newFrame.getId(), frames); - return; - } - } else if (newFrame.getBody() instanceof FrameBodyWXXX) { - //Value with matching key exists so replace - if (((FrameBodyWXXX) newFrame.getBody()).getDescription().equals(((FrameBodyWXXX) nextFrame.getBody()).getDescription())) { - li.set(newFrame); - frameMap.put(newFrame.getId(), frames); - return; - } - } else if (newFrame.getBody() instanceof FrameBodyCOMM) { - if (((FrameBodyCOMM) newFrame.getBody()).getDescription().equals(((FrameBodyCOMM) nextFrame.getBody()).getDescription())) { - li.set(newFrame); - frameMap.put(newFrame.getId(), frames); - return; - } - } else if (newFrame.getBody() instanceof FrameBodyUFID) { - if (((FrameBodyUFID) newFrame.getBody()).getOwner().equals(((FrameBodyUFID) nextFrame.getBody()).getOwner())) { - li.set(newFrame); - frameMap.put(newFrame.getId(), frames); - return; - } - } else if (newFrame.getBody() instanceof FrameBodyUSLT) { - if (((FrameBodyUSLT) newFrame.getBody()).getDescription().equals(((FrameBodyUSLT) nextFrame.getBody()).getDescription())) { - li.set(newFrame); - frameMap.put(newFrame.getId(), frames); - return; - } - } else if (newFrame.getBody() instanceof FrameBodyPOPM) { - if (((FrameBodyPOPM) newFrame.getBody()).getEmailToUser().equals(((FrameBodyPOPM) nextFrame.getBody()).getEmailToUser())) { - li.set(newFrame); - frameMap.put(newFrame.getId(), frames); - return; - } - } - //Just grab any additional info from new TRCK Frame and add to the existing one - else if (newFrame.getBody() instanceof FrameBodyTRCK) { - FrameBodyTRCK newBody = (FrameBodyTRCK) newFrame.getBody(); - FrameBodyTRCK oldBody = (FrameBodyTRCK) nextFrame.getBody(); - - if (newBody.getTrackNo() != null && newBody.getTrackNo() > 0) { - oldBody.setTrackNo(newBody.getTrackNoAsText()); - } - - if (newBody.getTrackTotal() != null && newBody.getTrackTotal() > 0) { - oldBody.setTrackTotal(newBody.getTrackTotalAsText()); - } - return; - } - //Just grab any additional info from new TPOS Frame and add to the existing one - else if (newFrame.getBody() instanceof FrameBodyTPOS) { - FrameBodyTPOS newBody = (FrameBodyTPOS) newFrame.getBody(); - FrameBodyTPOS oldBody = (FrameBodyTPOS) nextFrame.getBody(); - - Integer newDiscNo = newBody.getDiscNo(); - if ((newDiscNo != null) && (newDiscNo > 0)) { - oldBody.setDiscNo(newBody.getDiscNoAsText()); - } - - Integer newDiscTotal = newBody.getDiscTotal(); - if ((newDiscTotal != null) && (newDiscTotal > 0)) { - oldBody.setDiscTotal(newBody.getDiscTotalAsText()); - } - return; - } else if (newFrame.getBody() instanceof FrameBodyIPLS) { - FrameBodyIPLS frameBody = (FrameBodyIPLS) newFrame.getBody(); - FrameBodyIPLS existingFrameBody = (FrameBodyIPLS) nextFrame.getBody(); - existingFrameBody.addPair(frameBody.getText()); - return; - } else if (newFrame.getBody() instanceof FrameBodyTIPL) { - FrameBodyTIPL frameBody = (FrameBodyTIPL) newFrame.getBody(); - FrameBodyTIPL existingFrameBody = (FrameBodyTIPL) nextFrame.getBody(); - existingFrameBody.addPair(frameBody.getText()); - return; - } - } - - if (!getID3Frames().isMultipleAllowed(newFrame.getId())) { - frameMap.put(newFrame.getId(), newFrame); - } else { - //No match found so addField new one - frames.add(newFrame); - frameMap.put(newFrame.getId(), frames); - } - } - - /** - * Add another frame to the map - * - * @param list - * @param frameMap - * @param existingFrame - * @param frame - */ - private void addNewFrameToMap(List list, HashMap frameMap, AbstractID3v2Frame existingFrame, AbstractID3v2Frame frame) { - if (list.size() == 0) { - list.add(existingFrame); - list.add(frame); - frameMap.put(frame.getId(), list); - } else { - list.add(frame); - } - } - - /** - * Handles adding of a new field that's shares a frame with other fields, so modifies the existing frame rather - * than creating a new frame for these special cases - * - * @param list - * @param frameMap - * @param existingFrame - * @param frame - */ - private void addNewFrameOrAddField(List list, HashMap frameMap, AbstractID3v2Frame existingFrame, AbstractID3v2Frame frame) { - ArrayList mergedList = new ArrayList(); - if (existingFrame != null) { - mergedList.add(existingFrame); - } else { - mergedList.addAll(list); - } - - /** - * If the frame is a TXXX frame then we add an extra string to the existing frame - * if same description otherwise we create a new frame - */ - if (frame.getBody() instanceof FrameBodyTXXX) { - FrameBodyTXXX frameBody = (FrameBodyTXXX) frame.getBody(); - boolean match = false; - Iterator i = mergedList.listIterator(); - while (i.hasNext()) { - FrameBodyTXXX existingFrameBody = (FrameBodyTXXX) ((AbstractID3v2Frame) i.next()).getBody(); - if (frameBody.getDescription().equals(existingFrameBody.getDescription())) { - existingFrameBody.addTextValue(frameBody.getText()); - match = true; - break; - } - } - if (!match) { - addNewFrameToMap(list, frameMap, existingFrame, frame); - } - } else if (frame.getBody() instanceof FrameBodyWXXX) { - FrameBodyWXXX frameBody = (FrameBodyWXXX) frame.getBody(); - boolean match = false; - Iterator i = mergedList.listIterator(); - while (i.hasNext()) { - FrameBodyWXXX existingFrameBody = (FrameBodyWXXX) ((AbstractID3v2Frame) i.next()).getBody(); - if (frameBody.getDescription().equals(existingFrameBody.getDescription())) { - existingFrameBody.addUrlLink(frameBody.getUrlLink()); - match = true; - break; - } - } - if (!match) { - addNewFrameToMap(list, frameMap, existingFrame, frame); - } - } else if (frame.getBody() instanceof AbstractFrameBodyTextInfo) { - AbstractFrameBodyTextInfo frameBody = (AbstractFrameBodyTextInfo) frame.getBody(); - AbstractFrameBodyTextInfo existingFrameBody = (AbstractFrameBodyTextInfo) existingFrame.getBody(); - existingFrameBody.addTextValue(frameBody.getText()); - } else if (frame.getBody() instanceof FrameBodyIPLS) { - FrameBodyIPLS frameBody = (FrameBodyIPLS) frame.getBody(); - FrameBodyIPLS existingFrameBody = (FrameBodyIPLS) existingFrame.getBody(); - existingFrameBody.addPair(frameBody.getText()); - } else if (frame.getBody() instanceof FrameBodyTIPL) { - FrameBodyTIPL frameBody = (FrameBodyTIPL) frame.getBody(); - FrameBodyTIPL existingFrameBody = (FrameBodyTIPL) existingFrame.getBody(); - existingFrameBody.addPair(frameBody.getText()); - } else if (frame.getBody() instanceof FrameBodyTRCK) { - FrameBodyTRCK frameBody = (FrameBodyTRCK) frame.getBody(); - FrameBodyTRCK existingFrameBody = (FrameBodyTRCK) existingFrame.getBody(); - - if (frameBody.getTrackNo() != null && frameBody.getTrackNo() > 0) { - existingFrameBody.setTrackNo(frameBody.getTrackNoAsText()); - } - - if (frameBody.getTrackTotal() != null && frameBody.getTrackTotal() > 0) { - existingFrameBody.setTrackTotal(frameBody.getTrackTotalAsText()); - } - } else if (frame.getBody() instanceof FrameBodyTPOS) { - FrameBodyTPOS frameBody = (FrameBodyTPOS) frame.getBody(); - FrameBodyTPOS existingFrameBody = (FrameBodyTPOS) existingFrame.getBody(); - - if (frameBody.getDiscNo() != null && frameBody.getDiscNo() > 0) { - existingFrameBody.setDiscNo(frameBody.getDiscNoAsText()); - } - - if (frameBody.getDiscTotal() != null && frameBody.getDiscTotal() > 0) { - existingFrameBody.setDiscTotal(frameBody.getDiscTotalAsText()); - } - } else { - addNewFrameToMap(list, frameMap, existingFrame, frame); - } - } - - /** - * Set Field - * - * @param field - * @throws FieldDataInvalidException - */ - public void setField(TagField field) throws FieldDataInvalidException { - if ((!(field instanceof AbstractID3v2Frame)) && (!(field instanceof AggregatedFrame))) { - throw new FieldDataInvalidException("Field " + field + " is not of type AbstractID3v2Frame nor AggregatedFrame"); - } - - if (field instanceof AbstractID3v2Frame) { - AbstractID3v2Frame newFrame = (AbstractID3v2Frame) field; - - Object obj = frameMap.get(field.getId()); - - - //If no frame of this type exist or if multiples are not allowed - if (obj == null) { - frameMap.put(field.getId(), field); - } - //frame of this type already exists - else if (obj instanceof AbstractID3v2Frame) { - List frames = new ArrayList(); - frames.add((AbstractID3v2Frame) obj); - mergeDuplicateFrames(newFrame, frames); - } - //Multiple frames of this type already exist - else if (obj instanceof List) { - mergeDuplicateFrames(newFrame, (List) obj); - } - } else - //TODO not handling multiple aggregated frames of same type - { - frameMap.put(field.getId(), field); - } - } - - /** - * Add new field - *

    - * There is a special handling if adding another text field of the same type, in this case the value will - * be appended to the existing field, separated by the null character. - * - * @param field - * @throws FieldDataInvalidException - */ - public void addField(TagField field) throws FieldDataInvalidException { - if (field == null) { - return; - } - - if ((!(field instanceof AbstractID3v2Frame)) && (!(field instanceof AggregatedFrame))) { - throw new FieldDataInvalidException("Field " + field + " is not of type AbstractID3v2Frame or AggregatedFrame"); - } - - if (field instanceof AbstractID3v2Frame) { - AbstractID3v2Frame frame = (AbstractID3v2Frame) field; - - Object o = frameMap.get(field.getId()); - - //No frame of this type - if (o == null) { - frameMap.put(field.getId(), field); - } - //There are already frames of this type, adding another may need to merge - else if (o instanceof List) { - List list = (List) o; - addNewFrameOrAddField(list, frameMap, null, frame); - } - //One frame exists, we are adding another so may need to convert to list - else { - AbstractID3v2Frame existingFrame = (AbstractID3v2Frame) o; - List list = new ArrayList(); - addNewFrameOrAddField(list, frameMap, existingFrame, frame); - } - } else { - frameMap.put(field.getId(), field); - } - } - - /** - * Return the number of frames in this tag of a particular type, multiple frames - * of the same time will only be counted once - * - * @return a count of different frames - */ - /* - public int getFrameCount() - { - if (frameMap == null) - { - return 0; - } - else - { - return frameMap.size(); - } - } - */ - - /** - * Used for setting multiple frames for a single frame Identifier - *

    - * Warning if frame(s) already exists for this identifier they are overwritten - * TODO needs to ensure do not add an invalid frame for this tag - * - * @param identifier - * @param multiFrame - */ - public void setFrame(String identifier, List multiFrame) { - logger.finest("Adding " + multiFrame.size() + " frames for " + identifier); - frameMap.put(identifier, multiFrame); - } - - /** - * Return all frames which start with the identifier, this - * can be more than one which is useful if trying to retrieve - * similar frames e.g TIT1,TIT2,TIT3 ... and don't know exactly - * which ones there are. - *

    - * Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body - * but happens to have an identifier that is valid for another version of the tag it will be returned. - * - * @param identifier - * @return an iterator of all the frames starting with a particular identifier - */ - public Iterator getFrameOfType(String identifier) { - Iterator iterator = frameMap.keySet().iterator(); - HashSet result = new HashSet(); - String key; - while (iterator.hasNext()) { - key = iterator.next(); - if (key.startsWith(identifier)) { - Object o = frameMap.get(key); - if (o instanceof List) { - for (Object next : (List) o) { - result.add(next); - } - } else { - result.add(o); - } - } - } - return result.iterator(); - } - - /** - * Delete Tag - * - * @param file to delete the tag from - * @throws IOException if problem accessing the file - *

    - */ - //TODO should clear all data and preferably recover lost space and go upto end of mp3s - public void delete(RandomAccessFile file) throws IOException { - // this works by just erasing the "ID3" tag at the beginning - // of the file - byte[] buffer = new byte[FIELD_TAGID_LENGTH]; - //Read into Byte Buffer - final FileChannel fc = file.getChannel(); - fc.position(); - ByteBuffer byteBuffer = ByteBuffer.allocate(TAG_HEADER_LENGTH); - fc.read(byteBuffer, 0); - byteBuffer.flip(); - if (seek(byteBuffer)) { - file.seek(0L); - file.write(buffer); - } - } - - /** - * Is this tag equivalent to another - * - * @param obj to test for equivalence - * @return true if they are equivalent - */ - public boolean equals(Object obj) { - if (!(obj instanceof AbstractID3v2Tag)) { - return false; - } - AbstractID3v2Tag object = (AbstractID3v2Tag) obj; - return this.frameMap.equals(object.frameMap) && super.equals(obj); - } - - /** - * Return the frames in the order they were added - * - * @return and iterator of the frmaes/list of multi value frames - */ - public Iterator iterator() { - return frameMap.values().iterator(); - } - - /** - * Remove frame(s) with this identifier from tag - * - * @param identifier frameId to look for - */ - public void removeFrame(String identifier) { - logger.finest("Removing frame with identifier:" + identifier); - frameMap.remove(identifier); - } - - /** - * Remove all frame(s) which have an unsupported body, in other words - * remove all frames that are not part of the standard frameSet for - * this tag - */ - public void removeUnsupportedFrames() { - for (Iterator i = iterator(); i.hasNext(); ) { - Object o = i.next(); - if (o instanceof AbstractID3v2Frame) { - if (((AbstractID3v2Frame) o).getBody() instanceof FrameBodyUnsupported) { - logger.finest("Removing frame" + ((AbstractID3v2Frame) o).getIdentifier()); - i.remove(); - } - } - } - } - - /** - * Remove any frames starting with this identifier from tag - * - * @param identifier start of frameId to look for - */ - public void removeFrameOfType(String identifier) { - //First fine matching keys - HashSet result = new HashSet(); - for (Object match : frameMap.keySet()) { - String key = (String) match; - if (key.startsWith(identifier)) { - result.add(key); - } - } - //Then deleteField outside of loop to prevent concurrent modificatioon eception if there are two keys - //with the same id - for (String match : result) { - logger.finest("Removing frame with identifier:" + match + "because starts with:" + identifier); - frameMap.remove(match); - } - } - - /** - * Write tag to file. - * - * @param file - * @param audioStartByte - * @throws IOException TODO should be abstract - */ - public void write(File file, long audioStartByte) throws IOException { - } - - /** - * Get file lock for writing too file - *

    - * TODO:this appears to have little effect on Windows Vista - * - * @param fileChannel - * @param filePath - * @return lock or null if locking is not supported - * @throws IOException if unable to get lock because already locked by another program - * @throws java.nio.channels.OverlappingFileLockException if already locked by another thread in the same VM, we dont catch this - * because indicates a programming error - */ - protected FileLock getFileLockForWriting(FileChannel fileChannel, String filePath) throws IOException { - logger.finest("locking fileChannel for " + filePath); - FileLock fileLock; - try { - fileLock = fileChannel.tryLock(); - } - //Assumes locking is not supported on this platform so just returns null - catch (IOException exception) { - return null; - } - - //Couldnt getFields lock because file is already locked by another application - if (fileLock == null) { - throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(filePath)); - } - return fileLock; - } - - /** - * Write tag to file. - * - * @param file - * @throws IOException TODO should be abstract - */ - public void write(RandomAccessFile file) throws IOException { - } - - /** - * Write tag to channel. - * - * @param channel - * @throws IOException TODO should be abstract - */ - public void write(WritableByteChannel channel) throws IOException { - } - - /** - * Write tag to output stream - * - * @param outputStream - * @throws IOException - */ - public void write(OutputStream outputStream) throws IOException { - write(Channels.newChannel(outputStream)); - } - - /** - * Does a tag of the correct version exist in this file. - * - * @param byteBuffer to search through - * @return true if tag exists. - */ - public boolean seek(ByteBuffer byteBuffer) { - byteBuffer.rewind(); - logger.config("ByteBuffer pos:" + byteBuffer.position() + ":limit" + byteBuffer.limit() + ":cap" + byteBuffer.capacity()); - - - byte[] tagIdentifier = new byte[FIELD_TAGID_LENGTH]; - byteBuffer.get(tagIdentifier, 0, FIELD_TAGID_LENGTH); - if (!(Arrays.equals(tagIdentifier, TAG_ID))) { - return false; - } - //Major Version - if (byteBuffer.get() != getMajorVersion()) { - return false; - } - //Minor Version - return byteBuffer.get() == getRevision(); - } - - /** - * This method determines the total tag size taking into account - * where the audio file starts, the size of the tagging data and - * user options for defining how tags should shrink or grow. - * - * @param tagSize - * @param audioStart - * @return - */ - protected int calculateTagSize(int tagSize, int audioStart) { - /** We can fit in the tag so no adjustments required */ - if (tagSize <= audioStart) { - return audioStart; - } - /** There is not enough room as we need to move the audio file we might - * as well increase it more than neccessary for future changes - */ - return tagSize + TAG_SIZE_INCREMENT; - } - - /** - * Adjust the length of the padding at the beginning of the MP3 file, this is only called when there is currently - * not enough space before the start of the audio to write the tag. - *

    - * A new file will be created with enough size to fit the ID3v2 tag. - * The old file will be deleted, and the new file renamed. - * - * @param paddingSize This is total size required to store tag before audio - * @param audioStart - * @param file The file to adjust the padding length of - * @throws FileNotFoundException if the file exists but is a directory - * rather than a regular file or cannot be opened for any other - * reason - * @throws IOException on any I/O error - */ - public void adjustPadding(File file, int paddingSize, long audioStart) throws IOException { - logger.finer("Need to move audio file to accommodate tag"); - FileChannel fcIn = null; - FileChannel fcOut; - - //Create buffer holds the necessary padding - ByteBuffer paddingBuffer = ByteBuffer.wrap(new byte[paddingSize]); - - //Create Temporary File and write channel, make sure it is locked - File paddedFile; - - try { - paddedFile = File.createTempFile(Utils.getBaseFilenameForTempFile(file), ".new", file.getParentFile()); - logger.finest("Created temp file:" + paddedFile.getName() + " for " + file.getName()); - } - //Vista:Can occur if have Write permission on folder this file would be created in Denied - catch (IOException ioe) { - logger.log(Level.SEVERE, ioe.getMessage(), ioe); - if (ioe.getMessage().equals(FileSystemMessage.ACCESS_IS_DENIED.getMsg())) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath())); - throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath())); - } else { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath())); - throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath())); - } - } - - try { - fcOut = new FileOutputStream(paddedFile).getChannel(); - } - //Vista:Can occur if have special permission Create Folder/Append Data denied - catch (FileNotFoundException ioe) { - logger.log(Level.SEVERE, ioe.getMessage(), ioe); - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_MODIFY_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath())); - throw new UnableToModifyFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_MODIFY_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath())); - } - - try { - //Create read channel from original file - //TODO lock so cant be modified by anything else whilst reading from it ? - fcIn = new FileInputStream(file).getChannel(); - - //Write padding to new file (this is where the tag will be written to later) - long written = fcOut.write(paddingBuffer); - - //Write rest of file starting from audio - logger.finer("Copying:" + (file.length() - audioStart) + "bytes"); - - //If the amount to be copied is very large we split into 10MB lumps to try and avoid - //out of memory errors - long audiolength = file.length() - audioStart; - if (audiolength <= MAXIMUM_WRITABLE_CHUNK_SIZE) { - fcIn.position(audioStart); - long written2 = fcOut.transferFrom(fcIn, paddingSize, audiolength); - logger.finer("Written padding:" + written + " Data:" + written2); - if (written2 != audiolength) { - throw new RuntimeException(ErrorMessage.MP3_UNABLE_TO_ADJUST_PADDING.getMsg(audiolength, written2)); - } - } else { - long noOfChunks = audiolength / MAXIMUM_WRITABLE_CHUNK_SIZE; - long lastChunkSize = audiolength % MAXIMUM_WRITABLE_CHUNK_SIZE; - long written2 = 0; - for (int i = 0; i < noOfChunks; i++) { - written2 += fcIn.transferTo(audioStart + (i * MAXIMUM_WRITABLE_CHUNK_SIZE), MAXIMUM_WRITABLE_CHUNK_SIZE, fcOut); - } - written2 += fcIn.transferTo(audioStart + (noOfChunks * MAXIMUM_WRITABLE_CHUNK_SIZE), lastChunkSize, fcOut); - logger.finer("Written padding:" + written + " Data:" + written2); - if (written2 != audiolength) { - throw new RuntimeException(ErrorMessage.MP3_UNABLE_TO_ADJUST_PADDING.getMsg(audiolength, written2)); - } - } - - //Store original modification time - long lastModified = file.lastModified(); - - //Close Channels and locks - if (fcIn != null) { - if (fcIn.isOpen()) { - fcIn.close(); - } - } - - if (fcOut != null) { - if (fcOut.isOpen()) { - fcOut.close(); - } - } - - //Replace file with paddedFile - replaceFile(file, paddedFile); - - //Update modification time - //TODO is this the right file ? - paddedFile.setLastModified(lastModified); - } catch (UnableToRenameFileException ure) { - paddedFile.delete(); - throw ure; - } finally { - try { - //Whatever happens ensure all locks and channels are closed/released - if (fcIn != null) { - if (fcIn.isOpen()) { - fcIn.close(); - } - } - - if (fcOut != null) { - if (fcOut.isOpen()) { - fcOut.close(); - } - } - } catch (Exception e) { - logger.log(Level.WARNING, "Problem closing channels and locks:" + e.getMessage(), e); - } - } - } - - /** - * Write the data from the buffer to the file - * - * @param file - * @param headerBuffer - * @param bodyByteBuffer - * @param padding - * @param sizeIncPadding - * @param audioStartLocation - * @throws IOException - */ - protected void writeBufferToFile(File file, ByteBuffer headerBuffer, byte[] bodyByteBuffer, int padding, int sizeIncPadding, long audioStartLocation) throws IOException { - FileChannel fc = null; - FileLock fileLock = null; - - //We need to adjust location of audio file if true - if (sizeIncPadding > audioStartLocation) { - logger.finest("Adjusting Padding"); - adjustPadding(file, sizeIncPadding, audioStartLocation); - } - - try { - fc = new RandomAccessFile(file, "rws").getChannel(); - fileLock = getFileLockForWriting(fc, file.getPath()); - fc.write(headerBuffer); - fc.write(ByteBuffer.wrap(bodyByteBuffer)); - fc.write(ByteBuffer.wrap(new byte[padding])); - } catch (FileNotFoundException fe) { - logger.log(Level.SEVERE, getLoggingFilename() + fe.getMessage(), fe); - if (fe.getMessage().equals(FileSystemMessage.ACCESS_IS_DENIED.getMsg())) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath())); - throw new UnableToModifyFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath())); - } else { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath())); - throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath())); - } - } catch (IOException ioe) { - logger.log(Level.SEVERE, getLoggingFilename() + ioe.getMessage(), ioe); - if (ioe.getMessage().equals(FileSystemMessage.ACCESS_IS_DENIED.getMsg())) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath())); - throw new UnableToModifyFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath())); - } else { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath())); - throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath())); - } - } finally { - if (fc != null) { - if (fileLock != null) { - fileLock.release(); - } - fc.close(); - } - } - } - - /** - * Replace originalFile with the contents of newFile - *

    - * Both files must exist in the same folder so that there are no problems with filesystem mount points - * - * @param newFile - * @param originalFile - * @throws IOException - */ - private void replaceFile(File originalFile, File newFile) throws IOException { - boolean renameOriginalResult; - //Rename Original File to make a backup in case problem with new file - File originalFileBackup = new File(originalFile.getAbsoluteFile().getParentFile().getPath(), AudioFile.getBaseFilename(originalFile) + ".old"); - //If already exists modify the suffix - int count = 1; - while (originalFileBackup.exists()) { - originalFileBackup = new File(originalFile.getAbsoluteFile().getParentFile().getPath(), AudioFile.getBaseFilename(originalFile) + ".old" + count); - count++; - } - - renameOriginalResult = originalFile.renameTo(originalFileBackup); - if (!renameOriginalResult) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP.getMsg(originalFile.getAbsolutePath(), originalFileBackup.getName())); - newFile.delete(); - throw new UnableToRenameFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP.getMsg(originalFile.getAbsolutePath(), originalFileBackup.getName())); - } - - //Rename new Temporary file to the final file - boolean renameResult = newFile.renameTo(originalFile); - if (!renameResult) { - //Renamed failed so lets do some checks rename the backup back to the original file - //New File doesnt exist - if (!newFile.exists()) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_NEW_FILE_DOESNT_EXIST.getMsg(newFile.getAbsolutePath())); - } - - //Rename the backup back to the original - renameOriginalResult = originalFileBackup.renameTo(originalFile); - if (!renameOriginalResult) { - //TODO now if this happens we are left with testfile.old instead of testfile.mp3 - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_BACKUP_TO_ORIGINAL.getMsg(originalFileBackup.getAbsolutePath(), originalFile.getName())); - } - - - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName())); - newFile.delete(); - throw new UnableToRenameFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName())); - } else { - //Rename was okay so we can now deleteField the backup of the original - boolean deleteResult = originalFileBackup.delete(); - if (!deleteResult) { - //Not a disaster but can't deleteField the backup so make a warning - logger.warning(ErrorMessage.GENERAL_WRITE_WARNING_UNABLE_TO_DELETE_BACKUP_FILE.getMsg(originalFileBackup.getAbsolutePath())); - } - } - } - - /* - * Copy frame into map, whilst accounting for multiple frame of same type which can occur even if there were - * not frames of the same type in the original tag - */ - - protected void copyFrameIntoMap(String id, AbstractID3v2Frame newFrame) { - - if (frameMap.containsKey(newFrame.getIdentifier())) { - Object o = frameMap.get(newFrame.getIdentifier()); - if (o instanceof AbstractID3v2Frame) { - List list = new ArrayList(); - list.add((AbstractID3v2Frame) o); - list.add(newFrame); - frameMap.put(newFrame.getIdentifier(), list); - } else { - List list = (List) o; - list.add(newFrame); - } - } else { - frameMap.put(newFrame.getIdentifier(), newFrame); - } - } - - /** - * Add frame to the frame map - * - * @param frameId - * @param next - */ - protected void loadFrameIntoMap(String frameId, AbstractID3v2Frame next) { - if (next.getBody() instanceof FrameBodyEncrypted) { - loadFrameIntoSpecifiedMap(encryptedFrameMap, frameId, next); - } else { - loadFrameIntoSpecifiedMap(frameMap, frameId, next); - } - } - - - /** - * Decides what to with the frame that has just been read from file. - * If the frame is an allowable duplicate frame and is a duplicate we add all - * frames into an ArrayList and add the ArrayList to the HashMap. if not allowed - * to be duplicate we store the number of bytes in the duplicateBytes variable and discard - * the frame itself. - * - * @param frameId - * @param next - */ - protected void loadFrameIntoSpecifiedMap(HashMap map, String frameId, AbstractID3v2Frame next) { - if ((ID3v24Frames.getInstanceOf().isMultipleAllowed(frameId)) || - (ID3v23Frames.getInstanceOf().isMultipleAllowed(frameId)) || - (ID3v22Frames.getInstanceOf().isMultipleAllowed(frameId))) { - //If a frame already exists of this type - if (map.containsKey(frameId)) { - Object o = map.get(frameId); - if (o instanceof ArrayList) { - ArrayList multiValues = (ArrayList) o; - multiValues.add(next); - logger.finer("Adding Multi Frame(1)" + frameId); - } else { - ArrayList multiValues = new ArrayList(); - multiValues.add((AbstractID3v2Frame) o); - multiValues.add(next); - map.put(frameId, multiValues); - logger.finer("Adding Multi Frame(2)" + frameId); - } - } else { - logger.finer("Adding Multi FrameList(3)" + frameId); - map.put(frameId, next); - } - } - //If duplicate frame just stores the name of the frame and the number of bytes the frame contains - else if (map.containsKey(frameId)) { - logger.warning("Ignoring Duplicate Frame:" + frameId); - //If we have multiple duplicate frames in a tag separate them with semicolons - if (this.duplicateFrameId.length() > 0) { - this.duplicateFrameId += ";"; - } - this.duplicateFrameId += frameId; - this.duplicateBytes += ((AbstractID3v2Frame) frameMap.get(frameId)).getSize(); - } else { - logger.finer("Adding Frame" + frameId); - map.put(frameId, next); - } - } - - /** - * Return tag size based upon the sizes of the tags rather than the physical - * no of bytes between start of ID3Tag and start of Audio Data.Should be extended - * by subclasses to include header. - * - * @return size of the tag - */ - public int getSize() { - int size = 0; - Iterator iterator = frameMap.values().iterator(); - AbstractID3v2Frame frame; - while (iterator.hasNext()) { - Object o = iterator.next(); - if (o instanceof AbstractID3v2Frame) { - frame = (AbstractID3v2Frame) o; - size += frame.getSize(); - } else { - ArrayList multiFrames = (ArrayList) o; - for (ListIterator li = multiFrames.listIterator(); li.hasNext(); ) { - frame = li.next(); - size += frame.getSize(); - } - } - } - return size; - } - - /** - * Write all the frames to the byteArrayOutputStream - *

    - *

    Currently Write all frames, defaults to the order in which they were loaded, newly - * created frames will be at end of tag. - * - * @return ByteBuffer Contains all the frames written within the tag ready for writing to file - * @throws IOException - */ - protected ByteArrayOutputStream writeFramesToBuffer() throws IOException { - ByteArrayOutputStream bodyBuffer = new ByteArrayOutputStream(); - writeFramesToBufferStream(frameMap, bodyBuffer); - writeFramesToBufferStream(encryptedFrameMap, bodyBuffer); - return bodyBuffer; - } - - /** - * Write frames in map to bodyBuffer - * - * @param map - * @param bodyBuffer - * @throws IOException - */ - private void writeFramesToBufferStream(Map map, ByteArrayOutputStream bodyBuffer) throws IOException { - //Sort keys into Preferred Order - TreeSet sortedWriteOrder = new TreeSet(getPreferredFrameOrderComparator()); - sortedWriteOrder.addAll(map.keySet()); - - AbstractID3v2Frame frame; - for (String id : sortedWriteOrder) { - Object o = map.get(id); - if (o instanceof AbstractID3v2Frame) { - frame = (AbstractID3v2Frame) o; - frame.setLoggingFilename(getLoggingFilename()); - frame.write(bodyBuffer); - } else if (o instanceof AggregatedFrame) { - AggregatedFrame ag = (AggregatedFrame) o; - for (AbstractID3v2Frame next : ag.getFrames()) { - next.setLoggingFilename(getLoggingFilename()); - next.write(bodyBuffer); - } - } else { - List multiFrames = (List) o; - for (AbstractID3v2Frame nextFrame : multiFrames) { - nextFrame.setLoggingFilename(getLoggingFilename()); - nextFrame.write(bodyBuffer); - } - } - } - } - - /** - * @return comparator used to order frames in preferred order for writing to file - * so that most important frames are written first. - */ - public abstract Comparator getPreferredFrameOrderComparator(); - - public void createStructure() { - createStructureHeader(); - createStructureBody(); - } - - public void createStructureHeader() { - MP3File.getStructureFormatter().addElement(TYPE_DUPLICATEBYTES, this.duplicateBytes); - MP3File.getStructureFormatter().addElement(TYPE_DUPLICATEFRAMEID, this.duplicateFrameId); - MP3File.getStructureFormatter().addElement(TYPE_EMPTYFRAMEBYTES, this.emptyFrameBytes); - MP3File.getStructureFormatter().addElement(TYPE_FILEREADSIZE, this.fileReadSize); - MP3File.getStructureFormatter().addElement(TYPE_INVALIDFRAMES, this.invalidFrames); - } - - public void createStructureBody() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_BODY, ""); - - AbstractID3v2Frame frame; - for (Object o : frameMap.values()) { - if (o instanceof AbstractID3v2Frame) { - frame = (AbstractID3v2Frame) o; - frame.createStructure(); - } else { - ArrayList multiFrames = (ArrayList) o; - for (ListIterator li = multiFrames.listIterator(); li.hasNext(); ) { - frame = li.next(); - frame.createStructure(); - } - } - } - MP3File.getStructureFormatter().closeHeadingElement(TYPE_BODY); - } - - /** - * Maps the generic key to the id3 key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - //Special case here because the generic key to frameid/subid mapping is identical for trackno versus tracktotal - //and discno versus disctotal so we have to handle here, also want to ignore index parameter. - if ((genericKey == FieldKey.TRACK) || - (genericKey == FieldKey.TRACK_TOTAL) || - (genericKey == FieldKey.DISC_NO) || - (genericKey == FieldKey.DISC_TOTAL)) { - List values = new ArrayList(); - List fields = getFields(genericKey); - if (fields != null && fields.size() > 0) { - //Should only be one frame so ignore index value, and we ignore multiple values within the frame - //it would make no sense if it existed. - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - if (genericKey == FieldKey.TRACK) { - values.add(((FrameBodyTRCK) frame.getBody()).getTrackNoAsText()); - } else if (genericKey == FieldKey.TRACK_TOTAL) { - values.add(((FrameBodyTRCK) frame.getBody()).getTrackTotalAsText()); - } else if (genericKey == FieldKey.DISC_NO) { - values.add(((FrameBodyTPOS) frame.getBody()).getDiscNoAsText()); - } else if (genericKey == FieldKey.DISC_TOTAL) { - values.add(((FrameBodyTPOS) frame.getBody()).getDiscTotalAsText()); - } else if (genericKey == FieldKey.RATING) { - values.add(String.valueOf(((FrameBodyPOPM) frame.getBody()).getRating())); - } - } - return values; - } - return this.doGetValues(getFrameAndSubIdFromGenericKey(genericKey)); - } - - /** - * Retrieve the values that exists for this id3 frame id - */ - public List getFields(String id) throws KeyNotFoundException { - Object o = getFrame(id); - if (o == null) { - return new ArrayList(); - } else if (o instanceof List) { - //TODO should return copy - return (List) o; - } else if (o instanceof AbstractID3v2Frame) { - List list = new ArrayList(); - list.add((TagField) o); - return list; - } else { - throw new RuntimeException("Found entry in frameMap that was not a frame or a list:" + o); - } - } - - - /** - * Create Frame of correct ID3 version with the specified id - * - * @param id - * @return - */ - public abstract AbstractID3v2Frame createFrame(String id); - - //TODO - - public boolean hasCommonFields() { - return true; - } - - /** - * Does this tag contain a field with the specified key - * - * @param key The field id to look for. - * @return true if has field , false if does not or if no mapping for key exists - */ - public boolean hasField(FieldKey key) { - if (key == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - - try { - return getFirstField(key) != null; - } catch (KeyNotFoundException knfe) { - logger.log(Level.SEVERE, knfe.getMessage(), knfe); - return false; - } - } - - /** - * Does this tag contain a field with the specified id - * - * @see org.jaudiotagger.tag.Tag#hasField(java.lang.String) - */ - public boolean hasField(String id) { - return hasFrame(id); - } - - /** - * Is this tag empty - * - * @see org.jaudiotagger.tag.Tag#isEmpty() - */ - public boolean isEmpty() { - return frameMap.size() == 0; - } - - /** - * @return iterator of all fields, multiple values for the same Id (e.g multiple TXXX frames) count as separate - * fields - */ - public Iterator getFields() { - //Iterator of each different frameId in this tag - final Iterator> it = this.frameMap.entrySet().iterator(); - - //Iterator used by hasNext() so doesn't effect next() - final Iterator> itHasNext = this.frameMap.entrySet().iterator(); - - - return new Iterator() { - Map.Entry latestEntry = null; - - //this iterates through frames through for a particular frameId - private Iterator fieldsIt; - - private void changeIt() { - if (!it.hasNext()) { - return; - } - - while (it.hasNext()) { - Map.Entry e = it.next(); - latestEntry = itHasNext.next(); - if (e.getValue() instanceof List) { - List l = (List) e.getValue(); - //If list is empty (which it shouldn't be) we skip over this entry - if (l.size() == 0) { - continue; - } else { - fieldsIt = l.iterator(); - break; - } - } else { - //TODO must be a better way - List l = new ArrayList(); - l.add((TagField) e.getValue()); - fieldsIt = l.iterator(); - break; - } - } - } - - //TODO assumes if have entry its valid, but what if empty list but very different to check this - //without causing a side effect on next() so leaving for now - public boolean hasNext() { - //Check Current frameId, does it contain more values - if (fieldsIt != null) { - if (fieldsIt.hasNext()) { - return true; - } - } - - //No remaining entries return false - if (!itHasNext.hasNext()) { - return false; - } - - //Issue #236 - //TODO assumes if have entry its valid, but what if empty list but very different to check this - //without causing a side effect on next() so leaving for now - return itHasNext.hasNext(); - } - - public TagField next() { - //Hasn't been initialized yet - if (fieldsIt == null) { - changeIt(); - } - - if (fieldsIt != null) { - //Go to the end of the run - if (!fieldsIt.hasNext()) { - changeIt(); - } - } - - if (fieldsIt == null) { - throw new NoSuchElementException(); - } - return fieldsIt.next(); - } - - public void remove() { - fieldsIt.remove(); - } - }; - } - - /** - * Count number of frames/fields in this tag - * - * @return - */ - public int getFieldCount() { - Iterator it = getFields(); - int count = 0; - - //Done this way because it.hasNext() incorrectly counts empty list - //whereas it.next() works correctly - try { - while (true) { - TagField next = it.next(); - count++; - } - } catch (NoSuchElementException nse) { - //this is thrown when no more elements - } - return count; - } - - /** - * Return count of fields, this considers a text frame with two null separated values as two fields, if you want - * a count of frames @see getFrameCount - * - * @return count of fields - */ - public int getFieldCountIncludingSubValues() { - Iterator it = getFields(); - int count = 0; - - //Done this way because it.hasNext() incorrectly counts empty list - //whereas it.next() works correctly - try { - while (true) { - TagField next = it.next(); - if (next instanceof AbstractID3v2Frame) { - AbstractID3v2Frame frame = (AbstractID3v2Frame) next; - if ((frame.getBody() instanceof AbstractFrameBodyTextInfo) && !(frame.getBody() instanceof FrameBodyTXXX)) { - AbstractFrameBodyTextInfo frameBody = (AbstractFrameBodyTextInfo) frame.getBody(); - count += frameBody.getNumberOfValues(); - continue; - } - } - count++; - } - } catch (NoSuchElementException nse) { - //this is thrown when no more elements - } - return count; - } - - //TODO is this a special field? - - public boolean setEncoding(String enc) throws FieldDataInvalidException { - throw new UnsupportedOperationException("Not Implemented Yet"); - } - - /** - * Retrieve the first value that exists for this generic key - * - * @param genericKey - * @return - */ - public String getFirst(FieldKey genericKey) throws KeyNotFoundException { - return getValue(genericKey, 0); - } - - /** - * Retrieve the value that exists for this generic key and this index - *

    - * Have to do some special mapping for certain generic keys because they share frame - * with another generic key. - * - * @param genericKey - * @return - */ - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - //Special case here because the generic key to frameid/subid mapping is identical for trackno versus tracktotal - //and discno versus disctotal so we have to handle here, also want to ignore index parameter. - if ((genericKey == FieldKey.TRACK) || - (genericKey == FieldKey.TRACK_TOTAL) || - (genericKey == FieldKey.DISC_NO) || - (genericKey == FieldKey.DISC_TOTAL)) { - List fields = getFields(genericKey); - if (fields != null && fields.size() > 0) { - //Should only be one frame so ignore index value, and we ignore multiple values within the frame - //it would make no sense if it existed. - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - if (genericKey == FieldKey.TRACK) { - return ((FrameBodyTRCK) frame.getBody()).getTrackNoAsText(); - } else if (genericKey == FieldKey.TRACK_TOTAL) { - return ((FrameBodyTRCK) frame.getBody()).getTrackTotalAsText(); - } else if (genericKey == FieldKey.DISC_NO) { - return ((FrameBodyTPOS) frame.getBody()).getDiscNoAsText(); - } else if (genericKey == FieldKey.DISC_TOTAL) { - return ((FrameBodyTPOS) frame.getBody()).getDiscTotalAsText(); - } - } else { - return ""; - } - } - - //Special Case, TODO may be possible to put into doGetValueAtIndex but getUserFriendlyValue in POPMGFrameBody - //is implemented different to what we would need. - if (genericKey == FieldKey.RATING) { - List fields = getFields(genericKey); - if (fields != null && fields.size() > index) { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(index); - return String.valueOf(((FrameBodyPOPM) frame.getBody()).getRating()); - } else { - return ""; - } - } - FrameAndSubId frameAndSubId = getFrameAndSubIdFromGenericKey(genericKey); - return doGetValueAtIndex(frameAndSubId, index); - } - - /** - * Create a new TagField - *

    - * Only textual data supported at the moment. The genericKey will be mapped - * to the correct implementation key and return a TagField. - * - * @param genericKey is the generic key - * @param value to store - * @return - */ - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey); - - //FrameAndSubId does not contain enough info for these fields to be able to work out what to update - //that is why we need the extra processing here instead of doCreateTagField() - if (genericKey == FieldKey.TRACK) { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTRCK framebody = (FrameBodyTRCK) frame.getBody(); - framebody.setTrackNo(value); - return frame; - } else if (genericKey == FieldKey.TRACK_TOTAL) { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTRCK framebody = (FrameBodyTRCK) frame.getBody(); - framebody.setTrackTotal(value); - return frame; - } else if (genericKey == FieldKey.DISC_NO) { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTPOS framebody = (FrameBodyTPOS) frame.getBody(); - framebody.setDiscNo(value); - return frame; - } else if (genericKey == FieldKey.DISC_TOTAL) { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTPOS framebody = (FrameBodyTPOS) frame.getBody(); - framebody.setDiscTotal(value); - return frame; - } else { - return doCreateTagField(formatKey, value); - } - } - - - /** - * Create Frame for Id3 Key - *

    - * Only textual data supported at the moment, should only be used with frames that - * support a simple string argument. - * - * @param formatKey - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - protected TagField doCreateTagField(FrameAndSubId formatKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - if (frame.getBody() instanceof FrameBodyUFID) { - ((FrameBodyUFID) frame.getBody()).setOwner(formatKey.getSubId()); - try { - ((FrameBodyUFID) frame.getBody()).setUniqueIdentifier(value.getBytes("ISO-8859-1")); - } catch (UnsupportedEncodingException uee) { - //This will never happen because we are using a charset supported on all platforms - //but just in case - throw new RuntimeException("When encoding UFID charset ISO-8859-1 was deemed unsupported"); - } - } else if (frame.getBody() instanceof FrameBodyTXXX) { - ((FrameBodyTXXX) frame.getBody()).setDescription(formatKey.getSubId()); - ((FrameBodyTXXX) frame.getBody()).setText(value); - } else if (frame.getBody() instanceof FrameBodyWXXX) { - ((FrameBodyWXXX) frame.getBody()).setDescription(formatKey.getSubId()); - ((FrameBodyWXXX) frame.getBody()).setUrlLink(value); - } else if (frame.getBody() instanceof FrameBodyCOMM) { - //Set description if set - if (formatKey.getSubId() != null) { - ((FrameBodyCOMM) frame.getBody()).setDescription(formatKey.getSubId()); - //Special Handling for Media Monkey Compatability - if (((FrameBodyCOMM) frame.getBody()).isMediaMonkeyFrame()) { - ((FrameBodyCOMM) frame.getBody()).setLanguage(Languages.MEDIA_MONKEY_ID); - } - } - ((FrameBodyCOMM) frame.getBody()).setText(value); - } else if (frame.getBody() instanceof FrameBodyUSLT) { - ((FrameBodyUSLT) frame.getBody()).setDescription(""); - ((FrameBodyUSLT) frame.getBody()).setLyric(value); - } else if (frame.getBody() instanceof FrameBodyWOAR) { - ((FrameBodyWOAR) frame.getBody()).setUrlLink(value); - } else if (frame.getBody() instanceof AbstractFrameBodyTextInfo) { - ((AbstractFrameBodyTextInfo) frame.getBody()).setText(value); - } else if (frame.getBody() instanceof FrameBodyPOPM) { - ((FrameBodyPOPM) frame.getBody()).parseString(value); - } else if (frame.getBody() instanceof FrameBodyIPLS) { - PairedTextEncodedStringNullTerminated.ValuePairs pair = new PairedTextEncodedStringNullTerminated.ValuePairs(); - pair.add(formatKey.getSubId(), value); - frame.getBody().setObjectValue(DataTypes.OBJ_TEXT, pair); - } else if (frame.getBody() instanceof FrameBodyTIPL) { - PairedTextEncodedStringNullTerminated.ValuePairs pair = new PairedTextEncodedStringNullTerminated.ValuePairs(); - pair.add(formatKey.getSubId(), value); - frame.getBody().setObjectValue(DataTypes.OBJ_TEXT, pair); - } else if ((frame.getBody() instanceof FrameBodyAPIC) || (frame.getBody() instanceof FrameBodyPIC)) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } else { - throw new FieldDataInvalidException("Field with key of:" + formatKey.getFrameId() + ":does not accept cannot parse data:" + value); - } - return frame; - } - - /** - * Create a list of values for this key - *

    - * This method does all the complex stuff of splitting multiple values in one frame into separate values. - * - * @param formatKey - * @return - * @throws KeyNotFoundException - */ - protected List doGetValues(FrameAndSubId formatKey) throws KeyNotFoundException { - List values = new ArrayList(); - //Simple 1 to 1 mapping - if (formatKey.getSubId() == null) { - List list = getFields(formatKey.getFrameId()); - for (TagField next : list) { - AbstractID3v2Frame frame = (AbstractID3v2Frame) next; - if (frame != null) { - if (frame.getBody() instanceof AbstractFrameBodyTextInfo) { - AbstractFrameBodyTextInfo fb = (AbstractFrameBodyTextInfo) frame.getBody(); - values.addAll(fb.getValues()); - } else { - values.add(getTextValueForFrame(frame)); - } - } - } - return values; - } else { - //Get list of frames that this uses - List list = getFields(formatKey.getFrameId()); - ListIterator li = list.listIterator(); - while (li.hasNext()) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) li.next()).getBody(); - - if (next instanceof FrameBodyTXXX) { - if (((FrameBodyTXXX) next).getDescription().equals(formatKey.getSubId())) { - values.addAll((((FrameBodyTXXX) next).getValues())); - } - } else if (next instanceof FrameBodyWXXX) { - if (((FrameBodyWXXX) next).getDescription().equals(formatKey.getSubId())) { - values.addAll((((FrameBodyWXXX) next).getUrlLinks())); - } - } else if (next instanceof FrameBodyCOMM) { - if (((FrameBodyCOMM) next).getDescription().equals(formatKey.getSubId())) { - values.addAll((((FrameBodyCOMM) next).getValues())); - } - } else if (next instanceof FrameBodyUFID) { - if (((FrameBodyUFID) next).getOwner().equals(formatKey.getSubId())) { - values.add(new String(((FrameBodyUFID) next).getUniqueIdentifier())); - } - } else if (next instanceof FrameBodyIPLS) { - for (Pair entry : ((FrameBodyIPLS) next).getPairing().getMapping()) { - if (entry.getKey().equals(formatKey.getSubId())) { - values.add(entry.getValue()); - } - } - } else if (next instanceof FrameBodyTIPL) { - for (Pair entry : ((FrameBodyTIPL) next).getPairing().getMapping()) { - if (entry.getKey().equals(formatKey.getSubId())) { - values.add(entry.getValue()); - } - } - } else { - throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass()); - } - } - } - - return values; - } - - /** - * Get the value at the index, we massage the values so that the index as used in the generic interface rather - * than simply taking the frame index. For example if two composers have been added then then they can be retrieved - * individually using index=0, index=1 despite the fact that both internally will be stored in a single TCOM frame. - * - * @param formatKey - * @param index the index specified by the user - * @return - * @throws KeyNotFoundException - */ - protected String doGetValueAtIndex(FrameAndSubId formatKey, int index) throws KeyNotFoundException { - List values = doGetValues(formatKey); - if (values.size() > index) { - return values.get(index); - } - return ""; - } - - /** - * Create a link to artwork, this is not recommended because the link may be broken if the mp3 or image - * file is moved - * - * @param url specifies the link, it could be a local file or could be a full url - * @return - */ - public TagField createLinkedArtworkField(String url) { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - if (frame.getBody() instanceof FrameBodyAPIC) { - FrameBodyAPIC body = (FrameBodyAPIC) frame.getBody(); - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, Utils.getDefaultBytes(url, TextEncoding.CHARSET_ISO_8859_1)); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, FrameBodyAPIC.IMAGE_IS_URL); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - } else if (frame.getBody() instanceof FrameBodyPIC) { - FrameBodyPIC body = (FrameBodyPIC) frame.getBody(); - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, Utils.getDefaultBytes(url, TextEncoding.CHARSET_ISO_8859_1)); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID); - body.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, FrameBodyAPIC.IMAGE_IS_URL); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - } - return frame; - } - - - /** - * Delete fields with this generic key - * - * @param genericKey - */ - public void deleteField(FieldKey genericKey) throws KeyNotFoundException { - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey); - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - if (genericKey == FieldKey.TRACK) { - String trackTotal = this.getFirst(FieldKey.TRACK_TOTAL); - if (trackTotal.length() == 0) { - doDeleteTagField(formatKey); - return; - } else { - AbstractID3v2Frame frame = (AbstractID3v2Frame) this.getFrame(formatKey.getFrameId()); - FrameBodyTRCK frameBody = (FrameBodyTRCK) frame.getBody(); - frameBody.setTrackNo(0); - return; - } - } else if (genericKey == FieldKey.TRACK_TOTAL) { - String track = this.getFirst(FieldKey.TRACK); - if (track.length() == 0) { - doDeleteTagField(formatKey); - return; - } else { - AbstractID3v2Frame frame = (AbstractID3v2Frame) this.getFrame(formatKey.getFrameId()); - FrameBodyTRCK frameBody = (FrameBodyTRCK) frame.getBody(); - frameBody.setTrackTotal(0); - return; - } - } else if (genericKey == FieldKey.DISC_NO) { - String discTotal = this.getFirst(FieldKey.DISC_TOTAL); - if (discTotal.length() == 0) { - doDeleteTagField(formatKey); - return; - } else { - AbstractID3v2Frame frame = (AbstractID3v2Frame) this.getFrame(formatKey.getFrameId()); - FrameBodyTPOS frameBody = (FrameBodyTPOS) frame.getBody(); - frameBody.setDiscNo(0); - return; - } - } else if (genericKey == FieldKey.DISC_TOTAL) { - String discno = this.getFirst(FieldKey.DISC_NO); - if (discno.length() == 0) { - doDeleteTagField(formatKey); - return; - } else { - AbstractID3v2Frame frame = (AbstractID3v2Frame) this.getFrame(formatKey.getFrameId()); - FrameBodyTPOS frameBody = (FrameBodyTPOS) frame.getBody(); - frameBody.setDiscTotal(0); - return; - } - } - - doDeleteTagField(formatKey); - } - - /** - * Internal delete method - * - * @param formatKey - * @throws KeyNotFoundException - */ - protected void doDeleteTagField(FrameAndSubId formatKey) throws KeyNotFoundException { - //Simple 1 to 1 mapping - if (formatKey.getSubId() == null) { - removeFrame(formatKey.getFrameId()); - } else { - //Get list of frames that this uses - List list = getFields(formatKey.getFrameId()); - ListIterator li = list.listIterator(); - while (li.hasNext()) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) li.next()).getBody(); - if (next instanceof FrameBodyTXXX) { - if (((FrameBodyTXXX) next).getDescription().equals(formatKey.getSubId())) { - if (list.size() == 1) { - removeFrame(formatKey.getFrameId()); - } else { - li.remove(); - } - } - } else if (next instanceof FrameBodyCOMM) { - if (((FrameBodyCOMM) next).getDescription().equals(formatKey.getSubId())) { - if (list.size() == 1) { - removeFrame(formatKey.getFrameId()); - } else { - li.remove(); - } - } - } else if (next instanceof FrameBodyWXXX) { - if (((FrameBodyWXXX) next).getDescription().equals(formatKey.getSubId())) { - if (list.size() == 1) { - removeFrame(formatKey.getFrameId()); - } else { - li.remove(); - } - } - } else if (next instanceof FrameBodyUFID) { - if (((FrameBodyUFID) next).getOwner().equals(formatKey.getSubId())) { - if (list.size() == 1) { - removeFrame(formatKey.getFrameId()); - } else { - li.remove(); - } - } - } - //A single TIPL frame is used for multiple fields, so we just delete the matching pairs rather than - //deleting the frame itself unless now empty - else if (next instanceof FrameBodyTIPL) { - PairedTextEncodedStringNullTerminated.ValuePairs pairs = ((FrameBodyTIPL) next).getPairing(); - ListIterator pairIterator = pairs.getMapping().listIterator(); - while (pairIterator.hasNext()) { - Pair nextPair = pairIterator.next(); - if (nextPair.getKey().equals(formatKey.getSubId())) { - pairIterator.remove(); - } - } - if (pairs.getMapping().size() == 0) { - removeFrame(formatKey.getFrameId()); - } - } - //A single IPLS frame is used for multiple fields, so we just delete the matching pairs rather than - //deleting the frame itself unless now empty - else if (next instanceof FrameBodyIPLS) { - PairedTextEncodedStringNullTerminated.ValuePairs pairs = ((FrameBodyIPLS) next).getPairing(); - ListIterator pairIterator = pairs.getMapping().listIterator(); - while (pairIterator.hasNext()) { - Pair nextPair = pairIterator.next(); - if (nextPair.getKey().equals(formatKey.getSubId())) { - pairIterator.remove(); - } - } - - if (pairs.getMapping().size() == 0) { - removeFrame(formatKey.getFrameId()); - } - } else { - throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass()); - } - } - } - } - - protected abstract FrameAndSubId getFrameAndSubIdFromGenericKey(FieldKey genericKey); - - /** - * Get field(s) for this generic key - *

    - * This will return the number of underlying frames of this type, for example if you have added two TCOM field - * values these will be stored within a single frame so only one field will be returned not two. This can be - * confusing because getValues() would return two values. - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getFields(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey); - - //Get list of frames that this uses, as we are going to remove entries we don't want take a copy - List list = getFields(formatKey.getFrameId()); - List filteredList = new ArrayList(); - String subFieldId = formatKey.getSubId(); - - //... do we need to refine the list further i.e we only want TXXX frames that relate to the particular - //key that was passed as a parameter - if (subFieldId != null) { - for (TagField tagfield : list) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof FrameBodyTXXX) { - if (((FrameBodyTXXX) next).getDescription().equals(formatKey.getSubId())) { - filteredList.add(tagfield); - } - } else if (next instanceof FrameBodyWXXX) { - if (((FrameBodyWXXX) next).getDescription().equals(formatKey.getSubId())) { - filteredList.add(tagfield); - } - } else if (next instanceof FrameBodyCOMM) { - if (((FrameBodyCOMM) next).getDescription().equals(formatKey.getSubId())) { - filteredList.add(tagfield); - } - } else if (next instanceof FrameBodyUFID) { - if (((FrameBodyUFID) next).getOwner().equals(formatKey.getSubId())) { - filteredList.add(tagfield); - } - } else if (next instanceof FrameBodyIPLS) { - for (Pair entry : ((FrameBodyIPLS) next).getPairing().getMapping()) { - if (entry.getKey().equals(formatKey.getSubId())) { - filteredList.add(tagfield); - } - } - } else if (next instanceof FrameBodyTIPL) { - for (Pair entry : ((FrameBodyTIPL) next).getPairing().getMapping()) { - if (entry.getKey().equals(formatKey.getSubId())) { - filteredList.add(tagfield); - } - } - } else { - throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass()); - } - } - return filteredList; - } else if (genericKey == FieldKey.TRACK) { - for (TagField tagfield : list) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof FrameBodyTRCK) { - if (((FrameBodyTRCK) next).getTrackNo() != null) { - filteredList.add(tagfield); - } - } - } - return filteredList; - } else if (genericKey == FieldKey.TRACK_TOTAL) { - for (TagField tagfield : list) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof FrameBodyTRCK) { - if (((FrameBodyTRCK) next).getTrackTotal() != null) { - filteredList.add(tagfield); - } - } - } - return filteredList; - } else if (genericKey == FieldKey.DISC_NO) { - for (TagField tagfield : list) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof FrameBodyTPOS) { - if (((FrameBodyTPOS) next).getDiscNo() != null) { - filteredList.add(tagfield); - } - } - } - return filteredList; - } else if (genericKey == FieldKey.DISC_TOTAL) { - for (TagField tagfield : list) { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof FrameBodyTPOS) { - if (((FrameBodyTPOS) next).getDiscTotal() != null) { - filteredList.add(tagfield); - } - } - } - return filteredList; - } else { - return list; - } - } - - public Artwork getFirstArtwork() { - List artwork = getArtworkList(); - if (artwork.size() > 0) { - return artwork.get(0); - } - return null; - } - - /** - * Create field and then set within tag itself - * - * @param artwork - * @throws FieldDataInvalidException - */ - public void setField(Artwork artwork) throws FieldDataInvalidException { - this.setField(createField(artwork)); - } - - /** - * Create field and then set within tag itself - * - * @param artwork - * @throws FieldDataInvalidException - */ - public void addField(Artwork artwork) throws FieldDataInvalidException { - this.addField(createField(artwork)); - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException { - this.deleteField(FieldKey.COVER_ART); - } - - @Override - public String toString() { - final StringBuilder out = new StringBuilder(); - out.append("Tag content:\n"); - final Iterator it = getFields(); - while (it.hasNext()) { - final TagField field = it.next(); - out.append("\t"); - out.append(field.getId()); - out.append(":"); - out.append(field.toString()); - out.append("\n"); - } - - return out.toString(); - } - - /** - * This class had to be created to minimize the duplicate code in concrete subclasses - * of this class. It is required in some cases when using the fieldKey enums because enums - * cannot be sub classed. We want to use enums instead of regular classes because they are - * much easier for end users to to use. - */ - class FrameAndSubId { - private String frameId; - private String subId; - - public FrameAndSubId(String frameId, String subId) { - this.frameId = frameId; - this.subId = subId; - } - - public String getFrameId() { - return frameId; - } - - public String getSubId() { - return subId; - } - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractTag.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractTag.java deleted file mode 100644 index f71b3cd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractTag.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractTag.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description:This class represents any type of tag in an MP3 file, including ID3 and - * Lyrics and the file name. - */ -package org.jaudiotagger.tag.id3; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.Iterator; - -/** - * A tag is term given to a container that holds audio metadata - */ -public abstract class AbstractTag extends AbstractTagItem { - protected static final String TYPE_TAG = "tag"; - - - public AbstractTag() { - } - - public AbstractTag(AbstractTag copyObject) { - super(copyObject); - } - - /** - * Looks for this tag in the buffer - * - * @param byteBuffer - * @return returns true if found, false otherwise. - */ - abstract public boolean seek(ByteBuffer byteBuffer); - - /** - * Writes the tag to the file - * - * @param file - * @throws IOException - */ - public abstract void write(RandomAccessFile file) throws IOException; - - - /** - * Removes the specific tag from the file - * - * @param file MP3 file to append to. - * @throws IOException on any I/O error - */ - abstract public void delete(RandomAccessFile file) throws IOException; - - - /** - * Determines whether another datatype is equal to this tag. It just compares - * if they are the same class, then calls super.equals(obj). - * - * @param obj The object to compare - * @return if they are equal - */ - public boolean equals(Object obj) { - return (obj instanceof AbstractTag) && super.equals(obj); - - } - - /** - * @return - */ - abstract public Iterator iterator(); -} - - - diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractTagFrame.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractTagFrame.java deleted file mode 100644 index 67de62b..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractTagFrame.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractTagFrame.java 973 2011-06-07 13:51:31Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * This class represents 'parts of tags'. It contains methods that they all use - * use. ID3v2 tags have frames. Lyrics3 tags have fields. ID3v1 tags do not - * have parts. It also contains their header while the body contains the - * actual fragments. - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.utils.EqualsUtil; - -/** - * A frame contains meta-information of a particular type. A frame contains a header and a body - */ -public abstract class AbstractTagFrame extends AbstractTagItem { - - /** - * Actual data this fragment holds - */ - protected AbstractTagFrameBody frameBody; - - public AbstractTagFrame() { - } - - /** - * This constructs the bodies copy constructor this in turn invokes - * * bodies objectlist. - * - * @param copyObject - */ - public AbstractTagFrame(AbstractTagFrame copyObject) { - this.frameBody = (AbstractTagFrameBody) ID3Tags.copyObject(copyObject.frameBody); - this.frameBody.setHeader(this); - } - - /** - * Returns the body datatype for this fragment. The body datatype contains the - * actual information for the fragment. - * - * @return the body datatype - */ - public AbstractTagFrameBody getBody() { - return this.frameBody; - } - - /** - * Sets the body datatype for this fragment. The body datatype contains the - * actual information for the fragment. - * - * @param frameBody the body datatype - */ - public void setBody(AbstractTagFrameBody frameBody) { - this.frameBody = frameBody; - this.frameBody.setHeader(this); - } - - /** - * Returns true if this datatype and it's body is a subset of the argument. - * This datatype is a subset if the argument is the same class. - * - * @param obj datatype to determine if subset of - * @return true if this datatype and it's body is a subset of the argument. - */ - public boolean isSubsetOf(Object obj) { - if (!(obj instanceof AbstractTagFrame)) { - return false; - } - - if ((frameBody == null) && (((AbstractTagFrame) obj).frameBody == null)) { - return true; - } - - if ((frameBody == null) || (((AbstractTagFrame) obj).frameBody == null)) { - return false; - } - - return frameBody.isSubsetOf(((AbstractTagFrame) obj).frameBody) && super.isSubsetOf(obj); - - } - - /** - * Returns true if this datatype and its body equals the argument and its - * body. this datatype is equal if and only if they are the same class and - * have the same getSubId id string. - * - * @param obj datatype to determine equality of - * @return true if this datatype and its body equals the argument and its - * body. - */ - public boolean equals(Object obj) { - if (this == obj) return true; - if (!(obj instanceof AbstractTagFrame)) { - return false; - } - - AbstractTagFrame that = (AbstractTagFrame) obj; - return - EqualsUtil.areEqual(this.getIdentifier(), that.getIdentifier()) && - EqualsUtil.areEqual(this.frameBody, that.frameBody) && - super.equals(that); - - } - - @Override - public String toString() { - return getBody().toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractTagFrameBody.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractTagFrameBody.java deleted file mode 100644 index 6448c3d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractTagFrameBody.java +++ /dev/null @@ -1,302 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractTagFrameBody.java 1028 2012-03-01 11:07:39Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * FragmentBody contains the data for a fragment. - * ID3v2 tags have frames bodys. Lyrics3 tags have fields bodys - * ID3v1 tags do not have fragments bodys. - * Fragment Bodies consist of a number of MP3Objects held in an objectList - * Methods are additionally defined here to restrieve and set these objects. - * We also specify methods for getting/setting the text encoding of textual - * data. - * Fragment bodies should not be concerned about their parent fragment. For - * example most ID3v2 frames can be applied to ID3v2tags of different versions. - * The frame header will need modification based on the frame version but this - * should have no effect on the frame body. - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.datatype.AbstractDataType; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.util.ArrayList; -import java.util.Iterator; - -/** - * A frame body contains the data content for a frame - */ -public abstract class AbstractTagFrameBody extends AbstractTagItem { - /** - * List of data types that make up this particular frame body. - */ - protected ArrayList objectList = new ArrayList(); - /** - * Reference to the header associated with this frame body, a framebody can be created without a header - * but one it is associated with a header this should be set. It is principally useful for the framebody to know - * its header, because this will specify its tag version and some framebodies behave slighly different - * between tag versions. - */ - private AbstractTagFrame header; - - /** - * Creates a new framebody, at this point the bodys - * ObjectList is setup which defines what datatypes are expected in body - */ - protected AbstractTagFrameBody() { - setupObjectList(); - } - - /** - * Copy Constructor for fragment body. Copies all objects in the - * Object Iterator with data. - * - * @param copyObject - */ - protected AbstractTagFrameBody(AbstractTagFrameBody copyObject) { - AbstractDataType newObject; - for (int i = 0; i < copyObject.objectList.size(); i++) { - newObject = (AbstractDataType) ID3Tags.copyObject(copyObject.objectList.get(i)); - newObject.setBody(this); - this.objectList.add(newObject); - } - } - - public void createStructure() { - } - - /** - * Return the Text Encoding - * - * @return the text encoding used by this framebody - */ - public final byte getTextEncoding() { - AbstractDataType o = getObject(DataTypes.OBJ_TEXT_ENCODING); - - if (o != null) { - Long encoding = (Long) (o.getValue()); - return encoding.byteValue(); - } else { - return TextEncoding.ISO_8859_1; - } - } - - /** - * Set the Text Encoding to use for this frame body - * - * @param textEncoding to use for this frame body - */ - public final void setTextEncoding(byte textEncoding) { - //Number HashMap actually converts this byte to a long - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - } - - /** - * @return the text value that the user would expect to see for this framebody type, this should be overridden - * for all frame-bodies - */ - public String getUserFriendlyValue() { - return toString(); - } - - /** - * This method calls toString for all it's objects and appends - * them without any newline characters. - * - * @return brief description string - */ - public String getBriefDescription() { - String str = ""; - for (AbstractDataType object : objectList) { - if ((object.toString() != null) && (object.toString().length() > 0)) { - str += (object.getIdentifier() + "=\"" + object.toString() + "\"; "); - } - } - return str; - } - - - /** - * This method calls toString for all it's objects and appends - * them. It contains new line characters and is more suited for display - * purposes - * - * @return formatted description string - */ - public final String getLongDescription() { - String str = ""; - for (AbstractDataType object : objectList) { - if ((object.toString() != null) && (object.toString().length() > 0)) { - str += (object.getIdentifier() + " = " + object.toString() + "\n"); - } - } - return str; - } - - /** - * Sets all objects of identifier type to value defined by obj argument. - * - * @param identifier MP3Object identifier - * @param value new datatype value - */ - public final void setObjectValue(String identifier, Object value) { - AbstractDataType object; - Iterator iterator = objectList.listIterator(); - while (iterator.hasNext()) { - object = iterator.next(); - if (object.getIdentifier().equals(identifier)) { - object.setValue(value); - } - } - } - - /** - * Returns the value of the datatype with the specified - * identifier - * - * @param identifier - * @return the value of the dattype with the specified - * identifier - */ - public final Object getObjectValue(String identifier) { - return getObject(identifier).getValue(); - } - - /** - * Returns the datatype with the specified - * identifier - * - * @param identifier - * @return the datatype with the specified - * identifier - */ - public final AbstractDataType getObject(String identifier) { - AbstractDataType object; - Iterator iterator = objectList.listIterator(); - while (iterator.hasNext()) { - object = iterator.next(); - if (object.getIdentifier().equals(identifier)) { - return object; - } - } - return null; - } - - /** - * Returns the size in bytes of this fragmentbody - * - * @return estimated size in bytes of this datatype - */ - public int getSize() { - int size = 0; - AbstractDataType object; - Iterator iterator = objectList.listIterator(); - while (iterator.hasNext()) { - object = iterator.next(); - size += object.getSize(); - } - return size; - } - - /** - * Returns true if this instance and its entire DataType - * array list is a subset of the argument. This class is a subset if it is - * the same class as the argument. - * - * @param obj datatype to determine subset of - * @return true if this instance and its entire datatype array list is a - * subset of the argument. - */ - public boolean isSubsetOf(Object obj) { - if (!(obj instanceof AbstractTagFrameBody)) { - return false; - } - ArrayList superset = ((AbstractTagFrameBody) obj).objectList; - for (AbstractDataType anObjectList : objectList) { - if (anObjectList.getValue() != null) { - if (!superset.contains(anObjectList)) { - return false; - } - } - } - return true; - } - - /** - * Returns true if this datatype and its entire DataType array - * list equals the argument. This datatype is equal to the argument if they - * are the same class. - * - * @param obj datatype to determine equality of - * @return true if this datatype and its entire MP3Object array - * list equals the argument. - */ - public boolean equals(Object obj) { - if (!(obj instanceof AbstractTagFrameBody)) { - return false; - } - AbstractTagFrameBody object = (AbstractTagFrameBody) obj; - boolean check = this.objectList.equals(object.objectList) && super.equals(obj); - return check; - } - - /** - * Returns an iterator of the DataType list. - * - * @return iterator of the DataType list. - */ - public Iterator iterator() { - return objectList.iterator(); - } - - - /** - * Return brief description of FrameBody - * - * @return brief description of FrameBody - */ - public String toString() { - return getBriefDescription(); - } - - - /** - * Create the list of Datatypes that this body - * expects in the correct order This method needs to be implemented by concrete subclasses - */ - protected abstract void setupObjectList(); - - /** - * Get Reference to header - * - * @return - */ - public AbstractTagFrame getHeader() { - return header; - } - - /** - * Set header - * - * @param header - */ - public void setHeader(AbstractTagFrame header) { - this.header = header; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AbstractTagItem.java b/src/main/java/org/jaudiotagger/tag/id3/AbstractTagItem.java deleted file mode 100644 index f4d9693..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AbstractTagItem.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractTagItem.java 857 2009-12-03 11:21:11Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * This class is a facade for all classes that can write to an MP3 file. This includes - * fragments and fragment body . It has abstract methods that needs to be implemented, - * and a few default implementations of other methods. - */ - -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.TagException; - -import java.nio.ByteBuffer; -import java.util.logging.Logger; - - -/** - * This specifies a series of methods that have to be implemented by all structural subclasses, - * required to support all copy constructors,iterative methods and so on. - *

    - * TODO Not sure if this is really correct, if really needed should probably be an interface - */ -public abstract class AbstractTagItem { - - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - - - public AbstractTagItem() { - } - - public AbstractTagItem(AbstractTagItem copyObject) { - // no copy constructor in super class - } - - /** - * ID string that usually corresponds to the class name, but can be - * displayed to the user. It is not indended to identify each individual - * instance. - * - * @return ID string - */ - abstract public String getIdentifier(); - - /** - * Return size of this item - * - * @return size of this item - */ - abstract public int getSize(); - - /** - * @param byteBuffer file to read from - * @throws TagException on any exception generated by this library. - */ - abstract public void read(ByteBuffer byteBuffer) throws TagException; - - /** - * Returns true if this datatype is a subset of the argument. This instance - * is a subset if it is the same class as the argument. - * - * @param obj datatype to determine subset of - * @return true if this instance and its entire datatype array list is a - * subset of the argument. - */ - public boolean isSubsetOf(Object obj) { - return obj instanceof AbstractTagItem; - } - - /** - * Returns true if this datatype and its body equals the argument and its - * body. this datatype is equal if and only if they are the same class - * - * @param obj datatype to determine equality of - * @return true if this datatype and its body are equal - */ - public boolean equals(Object obj) { - if (this == obj) return true; - return obj instanceof AbstractTagItem; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/AggregatedFrame.java b/src/main/java/org/jaudiotagger/tag/id3/AggregatedFrame.java deleted file mode 100644 index 10424df..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/AggregatedFrame.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.TagTextField; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.UnsupportedEncodingException; -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * Required when a single generic field maps to multiple ID3 Frames - */ -public class AggregatedFrame implements TagTextField { - //TODO rather than just maintaining insertion order we want to define a preset order - protected Set frames = new LinkedHashSet(); - - public void addFrame(AbstractID3v2Frame frame) { - frames.add(frame); - } - - public Set getFrames() { - return frames; - } - - /** - * Returns the content of the underlying frames in order. - * - * @return Content - */ - public String getContent() { - StringBuilder sb = new StringBuilder(); - for (AbstractID3v2Frame next : frames) { - sb.append(next.getContent()); - } - return sb.toString(); - } - - /** - * Sets the content of the field. - * - * @param content fields content. - */ - public void setContent(String content) { - - } - - /** - * Returns the current used charset encoding. - * - * @return Charset encoding. - */ - public String getEncoding() { - return TextEncoding.getInstanceOf().getValueForId(frames.iterator().next().getBody().getTextEncoding()); - } - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - public void setEncoding(String encoding) { - - } - - //TODO:needs implementing but not sure if this method is required at all - public void copyContent(TagField field) { - - } - - public String getId() { - StringBuilder sb = new StringBuilder(); - for (AbstractID3v2Frame next : frames) { - sb.append(next.getId()); - } - return sb.toString(); - } - - - public boolean isCommon() { - return true; - } - - public boolean isBinary() { - return false; - } - - public void isBinary(boolean b) { - } - - public boolean isEmpty() { - return false; - } - - public byte[] getRawContent() throws UnsupportedEncodingException { - throw new UnsupportedEncodingException(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3Compression.java b/src/main/java/org/jaudiotagger/tag/id3/ID3Compression.java deleted file mode 100644 index 8207009..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3Compression.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.InvalidFrameException; - -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.DataFormatException; -import java.util.zip.Inflater; - -/** - * compresses frame data - *

    - * Is currently required for V23Frames and V24Frames - *

    - */ -//TODO also need to support compress framedata -public class ID3Compression { - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - - /** - * Decompress realFrameSize bytes to decompressedFrameSize bytes and return as ByteBuffer - * - * @param byteBuffer - * @param decompressedFrameSize - * @param realFrameSize - * @return - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - protected static ByteBuffer uncompress(String identifier, String filename, ByteBuffer byteBuffer, int decompressedFrameSize, int realFrameSize) throws InvalidFrameException { - logger.config(filename + ":About to decompress " + realFrameSize + " bytes, expect result to be:" + decompressedFrameSize + " bytes"); - // Decompress the bytes into this buffer, size initialized from header field - byte[] result = new byte[decompressedFrameSize]; - byte[] input = new byte[realFrameSize]; - - //Store position ( just after frame header and any extra bits) - //Read frame data into array, and then put buffer back to where it was - int position = byteBuffer.position(); - byteBuffer.get(input, 0, realFrameSize); - byteBuffer.position(position); - - Inflater decompresser = new Inflater(); - decompresser.setInput(input); - try { - int inflatedTo = decompresser.inflate(result); - logger.config(filename + ":Decompressed to " + inflatedTo + " bytes"); - } catch (DataFormatException dfe) { - logger.log(Level.CONFIG, "Unable to decompress this frame:" + identifier, dfe); - - //Update position of main buffer, so no attempt is made to reread these bytes - byteBuffer.position(byteBuffer.position() + realFrameSize); - throw new InvalidFrameException(ErrorMessage.ID3_UNABLE_TO_DECOMPRESS_FRAME.getMsg(identifier, filename, dfe.getMessage())); - } - decompresser.end(); - return ByteBuffer.wrap(result); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3Frames.java b/src/main/java/org/jaudiotagger/tag/id3/ID3Frames.java deleted file mode 100644 index 846e12d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3Frames.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.datatype.AbstractStringStringValuePair; - -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.TreeSet; - -/** - * Subclasses Defines ID3 frames for their Tag Version - *

    - * Here we specify how frames are mapped between different Tag Versions - * - * @author Paul Taylor - * @version $Id: ID3Frames.java 1081 2013-01-04 20:09:36Z paultaylor $ - */ -public abstract class ID3Frames extends AbstractStringStringValuePair { - /** - * Mapping from v22 to v23 - */ - public static final Map convertv22Tov23 = new LinkedHashMap(); - public static final Map convertv23Tov22 = new LinkedHashMap(); - public static final Map forcev22Tov23 = new LinkedHashMap(); - public static final Map forcev23Tov22 = new LinkedHashMap(); - public static final Map convertv23Tov24 = new LinkedHashMap(); - public static final Map convertv24Tov23 = new LinkedHashMap(); - public static final Map forcev23Tov24 = new LinkedHashMap(); - public static final Map forcev24Tov23 = new LinkedHashMap(); - - static { - loadID3v22ID3v23Mapping(); - loadID3v23ID3v24Mapping(); - } - - /** - * Holds frames whereby multiple occurences are allowed - */ - protected TreeSet multipleFrames = new TreeSet(); - /** - * These frames should be lost if file changes - */ - protected TreeSet discardIfFileAlteredFrames = new TreeSet(); - /** - * These frames are part of the Official Specification for that Tag Version - */ - protected TreeSet supportedFrames = new TreeSet(); - /** - * These frames are extensions to the Specification for that Tag Version - */ - protected TreeSet extensionFrames = new TreeSet(); - /** - * These frames are Common , this is a loose term - */ - protected TreeSet commonFrames = new TreeSet(); - /** - * These frames are Binary - */ - protected TreeSet binaryFrames = new TreeSet(); - - private static void loadID3v23ID3v24Mapping() { - // Define the mapping from v23 to v24 only maps values where - // the v23 ID is not a v24 ID and where the translation from v23 to v24 - // ID does not affect the framebody. - //This one way allows us to convert XSOT to TSOT,XSOP to TSOP and XSOA - TSOA but in the other direction gets converted to TSOT,TSOP,TSOA - convertv23Tov24.put(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ, ID3v24Frames.FRAME_ID_TITLE_SORT_ORDER); - convertv23Tov24.put(ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ, ID3v24Frames.FRAME_ID_ARTIST_SORT_ORDER); - convertv23Tov24.put(ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ, ID3v24Frames.FRAME_ID_ALBUM_SORT_ORDER); - - // No others exist because most v23 mappings are identical to v24 therefore no mapping required and the ones that - // are different need to be forced. - - // Force v23 to v24 These are deprecated and need to do a forced mapping - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT, ID3v24Frames.FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_EQUALISATION, ID3v24Frames.FRAME_ID_EQUALISATION2); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_IPLS, ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_TDAT, ID3v24Frames.FRAME_ID_YEAR); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_TIME, ID3v24Frames.FRAME_ID_YEAR); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_TORY, ID3v24Frames.FRAME_ID_ORIGINAL_RELEASE_TIME); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_TRDA, ID3v24Frames.FRAME_ID_YEAR); - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_TYER, ID3v24Frames.FRAME_ID_YEAR); - - forcev23Tov24.put(ID3v23Frames.FRAME_ID_V3_TYER, ID3v24Frames.FRAME_ID_YEAR); - - //Note Force v24 to v23, TDRC is a 1M relationship handled specially. - // @TODO EQUALISATION - forcev24Tov23.put(ID3v24Frames.FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2, ID3v23Frames.FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT); - //Used to be a special frame now a text frame - forcev24Tov23.put(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, ID3v23Frames.FRAME_ID_V3_IPLS); - //No Mood frame in v23 so use a TXXX frame - forcev24Tov23.put(ID3v24Frames.FRAME_ID_MOOD, ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO); - //Release time can be mapped to release year (but can only hold year) - forcev24Tov23.put(ID3v24Frames.FRAME_ID_ORIGINAL_RELEASE_TIME, ID3v23Frames.FRAME_ID_V3_TORY); - - } - - private static void loadID3v22ID3v23Mapping() { - Iterator iterator; - String key; - String value; - - // All v22 ids were renamed in v23, but are essentially the same - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ACCOMPANIMENT, ID3v23Frames.FRAME_ID_V3_ACCOMPANIMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ALBUM, ID3v23Frames.FRAME_ID_V3_ALBUM); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ARTIST, ID3v23Frames.FRAME_ID_V3_ARTIST); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_AUDIO_ENCRYPTION, ID3v23Frames.FRAME_ID_V3_AUDIO_ENCRYPTION); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_BPM, ID3v23Frames.FRAME_ID_V3_BPM); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_COMMENT, ID3v23Frames.FRAME_ID_V3_COMMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_COMMENT, ID3v23Frames.FRAME_ID_V3_COMMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_COMPOSER, ID3v23Frames.FRAME_ID_V3_COMPOSER); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_CONDUCTOR, ID3v23Frames.FRAME_ID_V3_CONDUCTOR); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_CONTENT_GROUP_DESC, ID3v23Frames.FRAME_ID_V3_CONTENT_GROUP_DESC); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_COPYRIGHTINFO, ID3v23Frames.FRAME_ID_V3_COPYRIGHTINFO); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ENCODEDBY, ID3v23Frames.FRAME_ID_V3_ENCODEDBY); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_EQUALISATION, ID3v23Frames.FRAME_ID_V3_EQUALISATION); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_EVENT_TIMING_CODES, ID3v23Frames.FRAME_ID_V3_EVENT_TIMING_CODES); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_FILE_TYPE, ID3v23Frames.FRAME_ID_V3_FILE_TYPE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_GENERAL_ENCAPS_OBJECT, ID3v23Frames.FRAME_ID_V3_GENERAL_ENCAPS_OBJECT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_GENRE, ID3v23Frames.FRAME_ID_V3_GENRE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_HW_SW_SETTINGS, ID3v23Frames.FRAME_ID_V3_HW_SW_SETTINGS); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_INITIAL_KEY, ID3v23Frames.FRAME_ID_V3_INITIAL_KEY); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_IPLS, ID3v23Frames.FRAME_ID_V3_IPLS); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ISRC, ID3v23Frames.FRAME_ID_V3_ISRC); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_LANGUAGE, ID3v23Frames.FRAME_ID_V3_LANGUAGE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_LENGTH, ID3v23Frames.FRAME_ID_V3_LENGTH); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_LINKED_INFO, ID3v23Frames.FRAME_ID_V3_LINKED_INFO); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_LYRICIST, ID3v23Frames.FRAME_ID_V3_LYRICIST); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_MEDIA_TYPE, ID3v23Frames.FRAME_ID_V3_MEDIA_TYPE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_MPEG_LOCATION_LOOKUP_TABLE, ID3v23Frames.FRAME_ID_V3_MPEG_LOCATION_LOOKUP_TABLE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_MUSIC_CD_ID, ID3v23Frames.FRAME_ID_V3_MUSIC_CD_ID); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ORIGARTIST, ID3v23Frames.FRAME_ID_V3_ORIGARTIST); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ORIG_FILENAME, ID3v23Frames.FRAME_ID_V3_ORIG_FILENAME); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ORIG_LYRICIST, ID3v23Frames.FRAME_ID_V3_ORIG_LYRICIST); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ORIG_TITLE, ID3v23Frames.FRAME_ID_V3_ORIG_TITLE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_PLAYLIST_DELAY, ID3v23Frames.FRAME_ID_V3_PLAYLIST_DELAY); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_PLAY_COUNTER, ID3v23Frames.FRAME_ID_V3_PLAY_COUNTER); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_PLAY_COUNTER, ID3v23Frames.FRAME_ID_V3_PLAY_COUNTER); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_POPULARIMETER, ID3v23Frames.FRAME_ID_V3_POPULARIMETER); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_PUBLISHER, ID3v23Frames.FRAME_ID_V3_PUBLISHER); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE, ID3v23Frames.FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE, ID3v23Frames.FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_RELATIVE_VOLUME_ADJUSTMENT, ID3v23Frames.FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_REMIXED, ID3v23Frames.FRAME_ID_V3_REMIXED); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_REVERB, ID3v23Frames.FRAME_ID_V3_REVERB); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_SET, ID3v23Frames.FRAME_ID_V3_SET); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_SET_SUBTITLE, ID3v23Frames.FRAME_ID_V3_SET_SUBTITLE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_SYNC_LYRIC, ID3v23Frames.FRAME_ID_V3_SYNC_LYRIC); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_SYNC_TEMPO, ID3v23Frames.FRAME_ID_V3_SYNC_TEMPO); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TDAT, ID3v23Frames.FRAME_ID_V3_TDAT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TIME, ID3v23Frames.FRAME_ID_V3_TIME); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TITLE_REFINEMENT, ID3v23Frames.FRAME_ID_V3_TITLE_REFINEMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TORY, ID3v23Frames.FRAME_ID_V3_TORY); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TRACK, ID3v23Frames.FRAME_ID_V3_TRACK); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TRDA, ID3v23Frames.FRAME_ID_V3_TRDA); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TSIZ, ID3v23Frames.FRAME_ID_V3_TSIZ); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TYER, ID3v23Frames.FRAME_ID_V3_TYER); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_UNIQUE_FILE_ID, ID3v23Frames.FRAME_ID_V3_UNIQUE_FILE_ID); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_UNIQUE_FILE_ID, ID3v23Frames.FRAME_ID_V3_UNIQUE_FILE_ID); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_UNSYNC_LYRICS, ID3v23Frames.FRAME_ID_V3_UNSYNC_LYRICS); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_ARTIST_WEB, ID3v23Frames.FRAME_ID_V3_URL_ARTIST_WEB); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_COMMERCIAL, ID3v23Frames.FRAME_ID_V3_URL_COMMERCIAL); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_COPYRIGHT, ID3v23Frames.FRAME_ID_V3_URL_COPYRIGHT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_FILE_WEB, ID3v23Frames.FRAME_ID_V3_URL_FILE_WEB); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_OFFICIAL_RADIO, ID3v23Frames.FRAME_ID_V3_URL_OFFICIAL_RADIO); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_PAYMENT, ID3v23Frames.FRAME_ID_V3_URL_PAYMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_PUBLISHERS, ID3v23Frames.FRAME_ID_V3_URL_PUBLISHERS); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_URL_SOURCE_WEB, ID3v23Frames.FRAME_ID_V3_URL_SOURCE_WEB); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TITLE, ID3v23Frames.FRAME_ID_V3_TITLE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_IS_COMPILATION, ID3v23Frames.FRAME_ID_V3_IS_COMPILATION); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES, ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES, ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_ITUNES); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES, ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_ITUNES); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES, ID3v23Frames.FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES, ID3v23Frames.FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES); - - // v23 to v22 The translation is both way - iterator = convertv22Tov23.keySet().iterator(); - while (iterator.hasNext()) { - key = iterator.next(); - value = convertv22Tov23.get(key); - convertv23Tov22.put(value, key); - } - - //This one way translation allows us to convert XSOT to TST, but in the other direction gets converted to TSOT - convertv23Tov22.put(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ, ID3v22Frames.FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES); - convertv23Tov22.put(ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ, ID3v22Frames.FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES); - convertv23Tov22.put(ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ, ID3v22Frames.FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES); - - //TODO What does CRM Map to ? - // Force v22 to v23, Extra fields in v23 version - forcev22Tov23.put(ID3v22Frames.FRAME_ID_V2_ATTACHED_PICTURE, ID3v23Frames.FRAME_ID_V3_ATTACHED_PICTURE); - - // Force v23 to v22 - forcev23Tov22.put(ID3v23Frames.FRAME_ID_V3_ATTACHED_PICTURE, ID3v22Frames.FRAME_ID_V2_ATTACHED_PICTURE); - } - - /** - * If file changes discard these frames - * - * @param frameID - * @return - */ - public boolean isDiscardIfFileAltered(String frameID) { - return discardIfFileAlteredFrames.contains(frameID); - } - - /** - * Are multiple occurrences of frame allowed - * - * @param frameID - * @return - */ - public boolean isMultipleAllowed(String frameID) { - return multipleFrames.contains(frameID); - } - - /** - * @param frameID - * @return true if frames with this id are part of the specification - */ - public boolean isSupportedFrames(String frameID) { - return supportedFrames.contains(frameID); - } - - public TreeSet getSupportedFrames() { - return supportedFrames; - } - - /** - * @param frameID - * @return true if frames with this id are considered common - */ - public boolean isCommon(String frameID) { - return commonFrames.contains(frameID); - } - - /** - * @param frameID - * @return true if frames with this id are binary (non textual data) - */ - public boolean isBinary(String frameID) { - return binaryFrames.contains(frameID); - } - - /** - * @param frameID - * @return true if frame is a known extension - */ - public boolean isExtensionFrames(String frameID) { - return extensionFrames.contains(frameID); - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3SyncSafeInteger.java b/src/main/java/org/jaudiotagger/tag/id3/ID3SyncSafeInteger.java deleted file mode 100644 index 0dc065c..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3SyncSafeInteger.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import java.nio.ByteBuffer; - -/** - * Peforms encoding/decoding of an syncsafe integer - *

    - *

    Syncsafe integers are used for the size in the tag header of v23 and v24 tags, and in the frame size in - * the frame header of v24 frames. - *

    - *

    In some parts of the tag it is inconvenient to use the - * unsychronisation scheme because the size of unsynchronised data is - * not known in advance, which is particularly problematic with size - * descriptors. The solution in ID3v2 is to use synchsafe integers, in - * which there can never be any false synchs. Synchsafe integers are - * integers that keep its highest bit (bit 7) zeroed, making seven bits - * out of eight available. Thus a 32 bit synchsafe integer can store 28 - * bits of information. - *

    - * Example: - *

    - * 255 (%11111111) encoded as a 16 bit synchsafe integer is 383 - * (%00000001 01111111). - */ -public class ID3SyncSafeInteger { - public static final int INTEGRAL_SIZE = 4; - - /** - * Sizes equal or smaller than this are the same whether held as sync safe integer or normal integer so - * it doesnt matter. - */ - public static final int MAX_SAFE_SIZE = 127; - - /** - * Read syncsafe value from byteArray in format specified in spec and convert to int. - * - * @param buffer syncsafe integer - * @return decoded int - */ - private static int bufferToValue(byte[] buffer) { - //Note Need to && with 0xff otherwise if value is greater than 128 we get a negative number - //when cast byte to int - return ((buffer[0] & 0xff) << 21) + ((buffer[1] & 0xff) << 14) + ((buffer[2] & 0xff) << 7) + ((buffer[3]) & 0xff); - } - - /** - * Read syncsafe value from buffer in format specified in spec and convert to int. - *

    - * The buffers position is moved to just after the location of the syncsafe integer - * - * @param buffer syncsafe integer - * @return decoded int - */ - protected static int bufferToValue(ByteBuffer buffer) { - byte byteBuffer[] = new byte[INTEGRAL_SIZE]; - buffer.get(byteBuffer, 0, INTEGRAL_SIZE); - return bufferToValue(byteBuffer); - } - - /** - * Is buffer holding a value that is definently not syncsafe - *

    - * We cannot guarantee a buffer is holding a syncsafe integer but there are some checks - * we can do to show that it definently is not. - *

    - * The buffer is NOT moved after reading. - *

    - * This function is useful for reading ID3v24 frames created in iTunes because iTunes does not use syncsafe - * integers in its frames. - * - * @param buffer - * @return true if this buffer is definently not holding a syncsafe integer - */ - protected static boolean isBufferNotSyncSafe(ByteBuffer buffer) { - int position = buffer.position(); - - //Check Bit7 not set - for (int i = 0; i < INTEGRAL_SIZE; i++) { - byte nextByte = buffer.get(position + i); - if ((nextByte & 0x80) > 0) { - return true; - } - } - return false; - } - - /** - * Checks if the buffer just contains zeros - *

    - * This can be used to identify when accessing padding of a tag - * - * @param buffer - * @return true if buffer only contains zeros - */ - protected static boolean isBufferEmpty(byte[] buffer) { - for (byte aBuffer : buffer) { - if (aBuffer != 0) { - return false; - } - } - return true; - } - - /** - * Convert int value to syncsafe value held in bytearray - * - * @param size - * @return buffer syncsafe integer - */ - protected static byte[] valueToBuffer(int size) { - byte[] buffer = new byte[4]; - buffer[0] = (byte) ((size & 0x0FE00000) >> 21); - buffer[1] = (byte) ((size & 0x001FC000) >> 14); - buffer[2] = (byte) ((size & 0x00003F80) >> 7); - buffer[3] = (byte) (size & 0x0000007F); - return buffer; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3Tags.java b/src/main/java/org/jaudiotagger/tag/id3/ID3Tags.java deleted file mode 100644 index fb91b0a..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3Tags.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.TagException; - -import java.lang.reflect.Constructor; -import java.util.logging.Logger; - -/** - * This contains static methods that can be performed on tags - * and to convert between tags. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3Tags.java 919 2010-10-04 13:46:39Z paultaylor $ - */ -public class ID3Tags { - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - - - private ID3Tags() { - } - - /** - * Returns true if the identifier is a valid ID3v2.2 frame identifier - * - * @param identifier string to test - * @return true if the identifier is a valid ID3v2.2 frame identifier - */ - public static boolean isID3v22FrameIdentifier(String identifier) { - //If less than 3 cant be an identifier - if (identifier.length() < 3) { - return false; - } - //If 3 is it a known identifier - else return identifier.length() == 3 && ID3v22Frames.getInstanceOf().getIdToValueMap().containsKey(identifier); - } - - /** - * Returns true if the identifier is a valid ID3v2.3 frame identifier - * - * @param identifier string to test - * @return true if the identifier is a valid ID3v2.3 frame identifier - */ - public static boolean isID3v23FrameIdentifier(String identifier) { - return identifier.length() >= 4 && ID3v23Frames.getInstanceOf().getIdToValueMap().containsKey(identifier.substring(0, 4)); - } - - /** - * Returns true if the identifier is a valid ID3v2.4 frame identifier - * - * @param identifier string to test - * @return true if the identifier is a valid ID3v2.4 frame identifier - */ - public static boolean isID3v24FrameIdentifier(String identifier) { - return identifier.length() >= 4 && ID3v24Frames.getInstanceOf().getIdToValueMap().containsKey(identifier.substring(0, 4)); - } - - /** - * Given an datatype, try to return it as a long. This tries to - * parse a string, and takes Long, Short, Byte, Integer - * objects and gets their value. An exception is not explicitly thrown - * here because it would causes too many other methods to also throw it. - * - * @param value datatype to find long from. - * @return long value - * @throws IllegalArgumentException - */ - static public long getWholeNumber(Object value) { - long number; - if (value instanceof String) { - number = Long.parseLong((String) value); - } else if (value instanceof Byte) { - number = (Byte) value; - } else if (value instanceof Short) { - number = (Short) value; - } else if (value instanceof Integer) { - number = (Integer) value; - } else if (value instanceof Long) { - number = (Long) value; - } else { - throw new IllegalArgumentException("Unsupported value class: " + value.getClass().getName()); - } - return number; - } - - /** - * Convert from ID3v22 FrameIdentifier to ID3v23 - * - * @param identifier - * @return - */ - public static String convertFrameID22To23(String identifier) { - if (identifier.length() < 3) { - return null; - } - return ID3Frames.convertv22Tov23.get(identifier.subSequence(0, 3)); - } - - /** - * Convert from ID3v22 FrameIdentifier to ID3v24 - * - * @param identifier - * @return - */ - public static String convertFrameID22To24(String identifier) { - //Idv22 identifiers are only of length 3 times - if (identifier.length() < 3) { - return null; - } - //Has idv22 been mapped to v23 - String id = ID3Frames.convertv22Tov23.get(identifier.substring(0, 3)); - if (id != null) { - //has v2.3 been mapped to v2.4 - String v23id = ID3Frames.convertv23Tov24.get(id); - if (v23id == null) { - //if not it may be because v2.3 and and v2.4 are same so wont be - //in mapping - if (ID3v24Frames.getInstanceOf().getIdToValueMap().get(id) != null) { - return id; - } else { - return null; - } - } else { - return v23id; - } - } else { - return null; - } - } - - /** - * Convert from ID3v23 FrameIdentifier to ID3v22 - * - * @param identifier - * @return - */ - public static String convertFrameID23To22(String identifier) { - if (identifier.length() < 4) { - return null; - } - - //If it is a v23 identifier - if (ID3v23Frames.getInstanceOf().getIdToValueMap().containsKey(identifier)) { - //If only name has changed v22 and modified in v23 return result of. - return ID3Frames.convertv23Tov22.get(identifier.substring(0, 4)); - } - return null; - } - - /** - * Convert from ID3v23 FrameIdentifier to ID3v24 - * - * @param identifier - * @return - */ - public static String convertFrameID23To24(String identifier) { - if (identifier.length() < 4) { - return null; - } - - //If it is a ID3v23 identifier - if (ID3v23Frames.getInstanceOf().getIdToValueMap().containsKey(identifier)) { - //If no change between ID3v23 and ID3v24 should be in ID3v24 list. - if (ID3v24Frames.getInstanceOf().getIdToValueMap().containsKey(identifier)) { - return identifier; - } - //If only name has changed ID3v23 and modified in ID3v24 return result of. - else { - return ID3Frames.convertv23Tov24.get(identifier.substring(0, 4)); - } - } - return null; - } - - /** - * Force from ID3v22 FrameIdentifier to ID3v23, this is where the frame and structure - * has changed from v2 to v3 but we can still do some kind of conversion. - * - * @param identifier - * @return - */ - public static String forceFrameID22To23(String identifier) { - return ID3Frames.forcev22Tov23.get(identifier); - } - - /** - * Force from ID3v22 FrameIdentifier to ID3v23, this is where the frame and structure - * has changed from v2 to v3 but we can still do some kind of conversion. - * - * @param identifier - * @return - */ - public static String forceFrameID23To22(String identifier) { - return ID3Frames.forcev23Tov22.get(identifier); - } - - /** - * Force from ID3v2.30 FrameIdentifier to ID3v2.40, this is where the frame and structure - * has changed from v3 to v4 but we can still do some kind of conversion. - * - * @param identifier - * @return - */ - public static String forceFrameID23To24(String identifier) { - return ID3Frames.forcev23Tov24.get(identifier); - } - - /** - * Force from ID3v2.40 FrameIdentifier to ID3v2.30, this is where the frame and structure - * has changed between v4 to v3 but we can still do some kind of conversion. - * - * @param identifier - * @return - */ - public static String forceFrameID24To23(String identifier) { - return ID3Frames.forcev24Tov23.get(identifier); - } - - /** - * Convert from ID3v24 FrameIdentifier to ID3v23 - * - * @param identifier - * @return - */ - public static String convertFrameID24To23(String identifier) { - String id; - if (identifier.length() < 4) { - return null; - } - id = ID3Frames.convertv24Tov23.get(identifier); - if (id == null) { - if (ID3v23Frames.getInstanceOf().getIdToValueMap().containsKey(identifier)) { - id = identifier; - } - } - return id; - } - - /** - * Unable to instantiate abstract classes, so can't call the copy - * constructor. So find out the instantiated class name and call the copy - * constructor through reflection (e.g for a a FrameBody would have to have a constructor - * that takes another frameBody as the same type as a parameter) - * - * @param copyObject - * @return - * @throws IllegalArgumentException if no suitable constructor exists - */ - public static Object copyObject(Object copyObject) { - Constructor constructor; - Class[] constructorParameterArray; - Object[] parameterArray; - if (copyObject == null) { - return null; - } - try { - constructorParameterArray = new Class[1]; - constructorParameterArray[0] = copyObject.getClass(); - constructor = copyObject.getClass().getConstructor(constructorParameterArray); - parameterArray = new Object[1]; - parameterArray[0] = copyObject; - return constructor.newInstance(parameterArray); - } catch (NoSuchMethodException ex) { - throw new IllegalArgumentException("NoSuchMethodException: Error finding constructor to create copy:" + copyObject.getClass().getName()); - } catch (IllegalAccessException ex) { - throw new IllegalArgumentException("IllegalAccessException: No access to run constructor to create copy" + copyObject.getClass().getName()); - } catch (InstantiationException ex) { - throw new IllegalArgumentException("InstantiationException: Unable to instantiate constructor to copy" + copyObject.getClass().getName()); - } catch (java.lang.reflect.InvocationTargetException ex) { - if (ex.getCause() instanceof Error) { - throw (Error) ex.getCause(); - } else if (ex.getCause() instanceof RuntimeException) { - throw (RuntimeException) ex.getCause(); - } else { - throw new IllegalArgumentException("InvocationTargetException: Unable to invoke constructor to create copy"); - } - } - } - - /** - * Find the first whole number that can be parsed from the string - * - * @param str string to search - * @return first whole number that can be parsed from the string - * @throws TagException - */ - public static long findNumber(String str) throws TagException { - return findNumber(str, 0); - } - - /** - * Find the first whole number that can be parsed from the string - * - * @param str string to search - * @param offset start seaching from this index - * @return first whole number that can be parsed from the string - * @throws TagException - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public static long findNumber(String str, int offset) throws TagException { - if (str == null) { - throw new NullPointerException("String is null"); - } - if ((offset < 0) || (offset >= str.length())) { - throw new IndexOutOfBoundsException("Offset to image string is out of bounds: offset = " + offset + ", string.length()" + str.length()); - } - int i; - int j; - long num; - i = offset; - while (i < str.length()) { - if (((str.charAt(i) >= '0') && (str.charAt(i) <= '9')) || (str.charAt(i) == '-')) { - break; - } - i++; - } - j = i + 1; - while (j < str.length()) { - if (((str.charAt(j) < '0') || (str.charAt(j) > '9'))) { - break; - } - j++; - } - if ((j <= str.length()) && (j > i)) { - num = Long.parseLong(str.substring(i, j)); - } else { - throw new TagException("Unable to find integer in string: " + str); - } - return num; - } - - /** - * Remove all occurances of the given character from the string argument. - * - * @param str String to search - * @param ch character to remove - * @return new String without the given charcter - */ - static public String stripChar(String str, char ch) { - if (str != null) { - char[] buffer = new char[str.length()]; - int next = 0; - for (int i = 0; i < str.length(); i++) { - if (str.charAt(i) != ch) { - buffer[next++] = str.charAt(i); - } - } - return new String(buffer, 0, next); - } else { - return null; - } - } - - /** - * truncate a string if it longer than the argument - * - * @param str String to truncate - * @param len maximum desired length of new string - * @return - */ - public static String truncate(String str, int len) { - if (str == null) { - return null; - } - if (len < 0) { - return null; - } - if (str.length() > len) { - return str.substring(0, len); - } else { - return str; - } - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3TextEncodingConversion.java b/src/main/java/org/jaudiotagger/tag/id3/ID3TextEncodingConversion.java deleted file mode 100644 index 503f2dd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3TextEncodingConversion.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.util.logging.Logger; - -/** - * Functions to encode text according to encodingoptions and ID3 version - */ -public class ID3TextEncodingConversion { - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - - - /** - * Check the text encoding is valid for this header type and is appropriate for - * user text encoding options. * - *

    - * This is called before writing any frames that use text encoding - * - * @param header used to identify the ID3tagtype - * @param textEncoding currently set - * @return valid encoding according to version type and user options - */ - public static byte getTextEncoding(AbstractTagFrame header, byte textEncoding) { - - //Should not happen, assume v23 and provide a warning - if (header == null) { - logger.warning("Header has not yet been set for this framebody"); - - if (TagOptionSingleton.getInstance().isResetTextEncodingForExistingFrames()) { - return TagOptionSingleton.getInstance().getId3v23DefaultTextEncoding(); - } else { - return convertV24textEncodingToV23textEncoding(textEncoding); - } - } else if (header instanceof ID3v24Frame) { - if (TagOptionSingleton.getInstance().isResetTextEncodingForExistingFrames()) { - //Replace with default - return TagOptionSingleton.getInstance().getId3v24DefaultTextEncoding(); - } else { - //All text encodings supported nothing to do - return textEncoding; - } - } else { - if (TagOptionSingleton.getInstance().isResetTextEncodingForExistingFrames()) { - //Replace with default - return TagOptionSingleton.getInstance().getId3v23DefaultTextEncoding(); - } else { - //If text encoding is an unsupported v24 one we use unicode v23 equivalent - return convertV24textEncodingToV23textEncoding(textEncoding); - } - } - } - - /** - * Sets the text encoding to best Unicode type for the version - * - * @param header - * @return - */ - public static byte getUnicodeTextEncoding(AbstractTagFrame header) { - if (header == null) { - logger.warning("Header has not yet been set for this framebody"); - return TextEncoding.UTF_16; - } else if (header instanceof ID3v24Frame) { - return TagOptionSingleton.getInstance().getId3v24UnicodeTextEncoding(); - } else { - return TextEncoding.UTF_16; - } - } - - /** - * Convert v24 text encoding to a valid v23 encoding - * - * @param textEncoding - * @return valid encoding - */ - private static byte convertV24textEncodingToV23textEncoding(byte textEncoding) { - //Convert to equivalent UTF16 format - if (textEncoding == TextEncoding.UTF_16BE) { - return TextEncoding.UTF_16; - } - //UTF-8 is not supported in ID3v23 and UTF-16 Format can be problematic on ID3v23 so change - //to ISO-8859-1, a check before writing data will check the format is capable of writing the data - else if (textEncoding == TextEncoding.UTF_8) { - return TextEncoding.ISO_8859_1; - } else { - return textEncoding; - } - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3Unsynchronization.java b/src/main/java/org/jaudiotagger/tag/id3/ID3Unsynchronization.java deleted file mode 100644 index 524d4ce..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3Unsynchronization.java +++ /dev/null @@ -1,222 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.mp3.MPEGFrameHeader; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Performs unsynchronization and synchronization tasks on a buffer. - *

    - * Is currently required for V23Tags and V24Frames - */ -public class ID3Unsynchronization { - //Logger - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.id3"); - - - /** - * Check if a byte array will require unsynchronization before being written as a tag. - * If the byte array contains any $FF $E0 bytes, then it will require unsynchronization. - * - * @param abySource the byte array to be examined - * @return true if unsynchronization is required, false otherwise - */ - public static boolean requiresUnsynchronization(byte[] abySource) { - for (int i = 0; i < abySource.length - 1; i++) { - if (((abySource[i] & MPEGFrameHeader.SYNC_BYTE1) == MPEGFrameHeader.SYNC_BYTE1) && ((abySource[i + 1] & MPEGFrameHeader.SYNC_BYTE2) == MPEGFrameHeader.SYNC_BYTE2)) { - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Unsynchronisation required found bit at:" + i); - } - return true; - } - } - - return false; - } - - /** - * Unsynchronize an array of bytes, this should only be called if the decision has already been made to - * unsynchronize the byte array - *

    - * In order to prevent a media player from incorrectly interpreting the contents of a tag, all $FF bytes - * followed by a byte with value >=224 must be followed by a $00 byte (thus, $FF $F0 sequences become $FF $00 $F0). - * Additionally because unsynchronisation is being applied any existing $FF $00 have to be converted to - * $FF $00 $00 - * - * @param abySource a byte array to be unsynchronized - * @return a unsynchronized representation of the source - */ - public static byte[] unsynchronize(byte[] abySource) { - ByteArrayInputStream input = new ByteArrayInputStream(abySource); - ByteArrayOutputStream output = new ByteArrayOutputStream(abySource.length); - - int count = 0; - while (input.available() > 0) { - int firstByte = input.read(); - count++; - output.write(firstByte); - if ((firstByte & MPEGFrameHeader.SYNC_BYTE1) == MPEGFrameHeader.SYNC_BYTE1) { - // if byte is $FF, we must check the following byte if there is one - if (input.available() > 0) { - input.mark(1); // remember where we were, if we don't need to unsynchronize - int secondByte = input.read(); - if ((secondByte & MPEGFrameHeader.SYNC_BYTE2) == MPEGFrameHeader.SYNC_BYTE2) { - // we need to unsynchronize here - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Writing unsynchronisation bit at:" + count); - } - output.write(0); - - } else if (secondByte == 0) { - // we need to unsynchronize here - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Inserting zero unsynchronisation bit at:" + count); - } - output.write(0); - } - input.reset(); - } - } - } - // if we needed to unsynchronize anything, and this tag ends with 0xff, we have to append a zero byte, - // which will be removed on de-unsynchronization later - if ((abySource[abySource.length - 1] & MPEGFrameHeader.SYNC_BYTE1) == MPEGFrameHeader.SYNC_BYTE1) { - logger.finest("Adding unsynchronisation bit at end of stream"); - output.write(0); - } - return output.toByteArray(); - } - - - /** - * Synchronize an array of bytes, this should only be called if it has been determined the tag is unsynchronised - *

    - * Any patterns of the form $FF $00 should be replaced by $FF - * - * @param source a ByteBuffer to be unsynchronized - * @return a synchronized representation of the source - */ - /* - public static ByteBuffer synchronize(ByteBuffer source) - { - long start = System.nanoTime(); - - int bufferSize = source.limit(); - ByteArrayOutputStream oBAOS = new ByteArrayOutputStream(bufferSize); - int position = 0; - while (position < bufferSize) - { - int byteValue = source.get(); - position ++; - oBAOS.write(byteValue); - if ((byteValue & MPEGFrameHeader.SYNC_BYTE1) == MPEGFrameHeader.SYNC_BYTE1) - { - // we are skipping if $00 byte but check not an end of stream - if (position < bufferSize) - { - int unsyncByteValue = source.get(); - position++; - //If its the null byte we just ignore it - if (unsyncByteValue != 0) - { - oBAOS.write(unsyncByteValue); - } - } - } - } - long time = System.nanoTime() - start; - ByteBuffer bb = ByteBuffer.wrap(oBAOS.toByteArray()); - System.out.printf("Took %6.3f ms, was %d bytes, now %,d bytes%n", time/1e6, source.limit(), bb.limit()); - return bb; - } - */ - - /** - * Synchronize an array of bytes, this should only be called if it has been determined the tag is unsynchronised - *

    - * Any patterns of the form $FF $00 should be replaced by $FF - * - * @param source a ByteBuffer to be unsynchronized - * @return a synchronized representation of the source - */ - /* - public static ByteBuffer synchronize(ByteBuffer source) - { - long start = System.nanoTime(); - - int bufferSize = source.limit(); - ByteBuffer output = ByteBuffer.allocate(bufferSize); - int position = 0; - int offset = 0; - int length = 0; - while (position < bufferSize) - { - int byteValue = source.get(); - position++; - length++; - if ((byteValue & MPEGFrameHeader.SYNC_BYTE1) == MPEGFrameHeader.SYNC_BYTE1) - { - // we are skipping if $00 byte but check not an end of stream - if (position < bufferSize) - { - int unsyncByteValue = source.get(); - position++; - //If this is null byte, then write upto this point - if (unsyncByteValue == 0) - { - output.put(source.array(), source.arrayOffset() + offset, length); - offset = position; - length = 0; - } - else - { - length++; - } - } - } - } - if (length > 0) - { - output.put(source.array(), source.arrayOffset() + offset, length); - } - output.flip(); - long time = System.nanoTime() - start; - System.out.printf("Took %6.3f ms, was %d bytes, now %,d bytes%n", time/1e6, source.limit(), output.limit()); - return output; - } - */ - - /** - * Synchronize an array of bytes, this should only be called if it has been determined the tag is unsynchronised - *

    - * Any patterns of the form $FF $00 should be replaced by $FF - * - * @param source a ByteBuffer to be unsynchronized - * @return a synchronized representation of the source - */ - - public static ByteBuffer synchronize(ByteBuffer source) { - //long start = System.nanoTime(); - - int len = source.remaining(); - byte[] bytes = new byte[len + 1]; // an extra byte saves a check later. - source.get(bytes, 0, len); - int from = 0, to = 0; - boolean copy = true; // whether to copy the byte, if false, check the byte != 0. - while (from < len) { - byte byteValue = bytes[from++]; - if (copy || byteValue != 0) bytes[to++] = byteValue; - copy = ((byteValue & MPEGFrameHeader.SYNC_BYTE1) != MPEGFrameHeader.SYNC_BYTE1); - } - - ByteBuffer bb2 = ByteBuffer.wrap(bytes, 0, to); - //long time = System.nanoTime() - start; - //System.out.printf("Took %6.3f ms, was %d bytes, now %,d bytes%n", time/1e6, source.limit(), bb2.limit()); - return bb2; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v11Tag.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v11Tag.java deleted file mode 100644 index 73cd9d7..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v11Tag.java +++ /dev/null @@ -1,531 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: ID3v11Tag.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * This class is for a ID3v1.1 Tag - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.id3.framebody.*; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Level; -import java.util.regex.Matcher; - -/** - * Represents an ID3v11 tag. - * - * @author : Eric Farng - * @author : Paul Taylor - */ -public class ID3v11Tag extends ID3v1Tag { - - //For writing output - protected static final String TYPE_TRACK = "track"; - - protected static final int TRACK_UNDEFINED = 0; - protected static final int TRACK_MAX_VALUE = 255; - protected static final int TRACK_MIN_VALUE = 1; - - protected static final int FIELD_COMMENT_LENGTH = 28; - protected static final int FIELD_COMMENT_POS = 97; - - protected static final int FIELD_TRACK_INDICATOR_LENGTH = 1; - protected static final int FIELD_TRACK_INDICATOR_POS = 125; - - protected static final int FIELD_TRACK_LENGTH = 1; - protected static final int FIELD_TRACK_POS = 126; - private static final byte RELEASE = 1; - private static final byte MAJOR_VERSION = 1; - private static final byte REVISION = 0; - /** - * Track is held as a single byte in v1.1 - */ - protected byte track = (byte) TRACK_UNDEFINED; - - /** - * Creates a new ID3v11 datatype. - */ - public ID3v11Tag() { - - } - - public ID3v11Tag(ID3v11Tag copyObject) { - super(copyObject); - this.track = copyObject.track; - } - - /** - * Creates a new ID3v11 datatype from a non v11 tag - * - * @param mp3tag - * @throws UnsupportedOperationException - */ - public ID3v11Tag(AbstractTag mp3tag) { - if (mp3tag != null) { - if (mp3tag instanceof ID3v1Tag) { - if (mp3tag instanceof ID3v11Tag) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - // id3v1_1 objects are also id3v1 objects - ID3v1Tag id3old = (ID3v1Tag) mp3tag; - this.title = id3old.title; - this.artist = id3old.artist; - this.album = id3old.album; - this.comment = id3old.comment; - this.year = id3old.year; - this.genre = id3old.genre; - } else { - ID3v24Tag id3tag; - // first change the tag to ID3v2_4 tag if not one already - if (!(mp3tag instanceof ID3v24Tag)) { - id3tag = new ID3v24Tag(mp3tag); - } else { - id3tag = (ID3v24Tag) mp3tag; - } - ID3v24Frame frame; - String text; - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_TITLE)) { - frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_TITLE); - text = ((FrameBodyTIT2) frame.getBody()).getText(); - this.title = ID3Tags.truncate(text, FIELD_TITLE_LENGTH); - } - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_ARTIST)) { - frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_ARTIST); - text = ((FrameBodyTPE1) frame.getBody()).getText(); - this.artist = ID3Tags.truncate(text, FIELD_ARTIST_LENGTH); - } - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_ALBUM)) { - frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_ALBUM); - text = ((FrameBodyTALB) frame.getBody()).getText(); - this.album = ID3Tags.truncate(text, FIELD_ALBUM_LENGTH); - } - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_YEAR)) { - frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_YEAR); - text = ((FrameBodyTDRC) frame.getBody()).getText(); - this.year = ID3Tags.truncate(text, FIELD_YEAR_LENGTH); - } - - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_COMMENT)) { - Iterator iterator = id3tag.getFrameOfType(ID3v24Frames.FRAME_ID_COMMENT); - text = ""; - while (iterator.hasNext()) { - frame = (ID3v24Frame) iterator.next(); - text += (((FrameBodyCOMM) frame.getBody()).getText() + " "); - } - this.comment = ID3Tags.truncate(text, FIELD_COMMENT_LENGTH); - } - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_GENRE)) { - frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_GENRE); - text = ((FrameBodyTCON) frame.getBody()).getText(); - try { - this.genre = (byte) ID3Tags.findNumber(text); - } catch (TagException ex) { - logger.log(Level.WARNING, getLoggingFilename() + ":" + "Unable to convert TCON frame to format suitable for v11 tag", ex); - this.genre = (byte) ID3v1Tag.GENRE_UNDEFINED; - } - } - if (id3tag.hasFrame(ID3v24Frames.FRAME_ID_TRACK)) { - frame = (ID3v24Frame) id3tag.getFrame(ID3v24Frames.FRAME_ID_TRACK); - this.track = (byte) ((FrameBodyTRCK) frame.getBody()).getTrackNo().intValue(); - } - } - } - } - - /** - * Creates a new ID3v11 datatype. - * - * @param file - * @param loggingFilename - * @throws TagNotFoundException - * @throws IOException - */ - public ID3v11Tag(RandomAccessFile file, String loggingFilename) throws TagNotFoundException, IOException { - setLoggingFilename(loggingFilename); - FileChannel fc; - ByteBuffer byteBuffer = ByteBuffer.allocate(TAG_LENGTH); - - fc = file.getChannel(); - fc.position(file.length() - TAG_LENGTH); - - fc.read(byteBuffer); - byteBuffer.flip(); - read(byteBuffer); - - } - - /** - * Creates a new ID3v11 datatype. - * - * @param file - * @throws TagNotFoundException - * @throws IOException - * @deprecated use {@link #ID3v11Tag(RandomAccessFile, String)} instead - */ - public ID3v11Tag(RandomAccessFile file) throws TagNotFoundException, IOException { - this(file, ""); - - } - - /** - * Retrieve the Release - */ - public byte getRelease() { - return RELEASE; - } - - /** - * Retrieve the Major Version - */ - public byte getMajorVersion() { - return MAJOR_VERSION; - } - - /** - * Retrieve the Revision - */ - public byte getRevision() { - return REVISION; - } - - public int getFieldCount() { - return 7; - } - - /** - * Set Comment - * - * @param comment - */ - public void setComment(String comment) { - if (comment == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - this.comment = ID3Tags.truncate(comment, FIELD_COMMENT_LENGTH); - } - - /** - * Get Comment - * - * @return comment - */ - public String getFirstComment() { - return comment; - } - - /** - * Return the track number as a String. - * - * @return track - */ - - public String getFirstTrack() { - return String.valueOf(track & BYTE_TO_UNSIGNED); - } - - public void addTrack(String track) { - setTrack(track); - } - - public List getTrack() { - if (getFirst(FieldKey.TRACK).length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.TRACK.name(), getFirst(FieldKey.TRACK)); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Set the track, v11 stores track numbers in a single byte value so can only - * handle a simple number in the range 0-255. - * - * @param trackValue - */ - - public void setTrack(String trackValue) { - int trackAsInt; - //Try and convert String representation of track into an integer - try { - trackAsInt = Integer.parseInt(trackValue); - } catch (NumberFormatException e) { - trackAsInt = 0; - } - - //This value cannot be held in v1_1 - if ((trackAsInt > TRACK_MAX_VALUE) || (trackAsInt < TRACK_MIN_VALUE)) { - this.track = (byte) TRACK_UNDEFINED; - } else { - this.track = (byte) Integer.parseInt(trackValue); - } - } - - public void setField(TagField field) { - FieldKey genericKey = FieldKey.valueOf(field.getId()); - if (genericKey == FieldKey.TRACK) { - setTrack(field.toString()); - } else { - super.setField(field); - } - } - - public List getFields(FieldKey genericKey) { - if (genericKey == FieldKey.TRACK) { - return getTrack(); - } else { - return super.getFields(genericKey); - } - } - - public String getFirst(FieldKey genericKey) { - switch (genericKey) { - case ARTIST: - return getFirstArtist(); - - case ALBUM: - return getFirstAlbum(); - - case TITLE: - return getFirstTitle(); - - case GENRE: - return getFirstGenre(); - - case YEAR: - return getFirstYear(); - - case TRACK: - return getFirstTrack(); - - case COMMENT: - return getFirstComment(); - - default: - return ""; - } - } - - public TagField getFirstField(String id) { - List results; - - if (FieldKey.TRACK.name().equals(id)) { - results = getTrack(); - if (results != null) { - if (results.size() > 0) { - return results.get(0); - } - } - return null; - } else { - return super.getFirstField(id); - } - } - - public boolean isEmpty() { - return track <= 0 && super.isEmpty(); - } - - /** - * Delete any instance of tag fields with this key - * - * @param genericKey - */ - public void deleteField(FieldKey genericKey) { - if (genericKey == FieldKey.TRACK) { - track = 0; - } else { - super.deleteField(genericKey); - } - } - - /** - * Compares Object with this only returns true if both v1_1 tags with all - * fields set to same value - * - * @param obj Comparing Object - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof ID3v11Tag)) { - return false; - } - ID3v11Tag object = (ID3v11Tag) obj; - return this.track == object.track && super.equals(obj); - } - - - /** - * Find identifier within byteBuffer to indicate that a v11 tag exists within the buffer - * - * @param byteBuffer - * @return true if find header for v11 tag within buffer - */ - public boolean seek(ByteBuffer byteBuffer) { - byte[] buffer = new byte[FIELD_TAGID_LENGTH]; - // read the TAG value - byteBuffer.get(buffer, 0, FIELD_TAGID_LENGTH); - if (!(Arrays.equals(buffer, TAG_ID))) { - return false; - } - - // Check for the empty byte before the TRACK - byteBuffer.position(FIELD_TRACK_INDICATOR_POS); - if (byteBuffer.get() != END_OF_FIELD) { - return false; - } - //Now check for TRACK if the next byte is also null byte then not v1.1 - //tag, however this means cannot have v1_1 tag with track setField to zero/undefined - //because on next read will be v1 tag. - return byteBuffer.get() != END_OF_FIELD; - } - - /** - * Read in a tag from the ByteBuffer - * - * @param byteBuffer from where to read in a tag - * @throws TagNotFoundException if unable to read a tag in the byteBuffer - */ - public void read(ByteBuffer byteBuffer) throws TagNotFoundException { - if (!seek(byteBuffer)) { - throw new TagNotFoundException("ID3v1 tag not found"); - } - logger.finer("Reading v1.1 tag"); - - //Do single file read of data to cut down on file reads - byte[] dataBuffer = new byte[TAG_LENGTH]; - byteBuffer.position(0); - byteBuffer.get(dataBuffer, 0, TAG_LENGTH); - title = Utils.getString(dataBuffer, FIELD_TITLE_POS, FIELD_TITLE_LENGTH, "ISO-8859-1").trim(); - Matcher m = AbstractID3v1Tag.endofStringPattern.matcher(title); - if (m.find()) { - title = title.substring(0, m.start()); - } - artist = Utils.getString(dataBuffer, FIELD_ARTIST_POS, FIELD_ARTIST_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(artist); - if (m.find()) { - artist = artist.substring(0, m.start()); - } - album = Utils.getString(dataBuffer, FIELD_ALBUM_POS, FIELD_ALBUM_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(album); - if (m.find()) { - album = album.substring(0, m.start()); - } - year = Utils.getString(dataBuffer, FIELD_YEAR_POS, FIELD_YEAR_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(year); - if (m.find()) { - year = year.substring(0, m.start()); - } - comment = Utils.getString(dataBuffer, FIELD_COMMENT_POS, FIELD_COMMENT_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(comment); - if (m.find()) { - comment = comment.substring(0, m.start()); - } - track = dataBuffer[FIELD_TRACK_POS]; - genre = dataBuffer[FIELD_GENRE_POS]; - } - - - /** - * Write this representation of tag to the file indicated - * - * @param file that this tag should be written to - * @throws IOException thrown if there were problems writing to the file - */ - public void write(RandomAccessFile file) throws IOException { - logger.config("Saving ID3v11 tag to file"); - byte[] buffer = new byte[TAG_LENGTH]; - int i; - String str; - delete(file); - file.seek(file.length()); - System.arraycopy(TAG_ID, FIELD_TAGID_POS, buffer, FIELD_TAGID_POS, TAG_ID.length); - int offset = FIELD_TITLE_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveTitle()) { - str = ID3Tags.truncate(title, FIELD_TITLE_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_ARTIST_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveArtist()) { - str = ID3Tags.truncate(artist, FIELD_ARTIST_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_ALBUM_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveAlbum()) { - str = ID3Tags.truncate(album, FIELD_ALBUM_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_YEAR_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveYear()) { - str = ID3Tags.truncate(year, FIELD_YEAR_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_COMMENT_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveComment()) { - str = ID3Tags.truncate(comment, FIELD_COMMENT_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_TRACK_POS; - buffer[offset] = track; // skip one byte extra blank for 1.1 definition - offset = FIELD_GENRE_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveGenre()) { - buffer[offset] = genre; - } - file.write(buffer); - - logger.config("Saved ID3v11 tag to file"); - } - - - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier()); - //Header - MP3File.getStructureFormatter().addElement(TYPE_TITLE, this.title); - MP3File.getStructureFormatter().addElement(TYPE_ARTIST, this.artist); - MP3File.getStructureFormatter().addElement(TYPE_ALBUM, this.album); - MP3File.getStructureFormatter().addElement(TYPE_YEAR, this.year); - MP3File.getStructureFormatter().addElement(TYPE_COMMENT, this.comment); - MP3File.getStructureFormatter().addElement(TYPE_TRACK, this.track); - MP3File.getStructureFormatter().addElement(TYPE_GENRE, this.genre); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG); - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v1FieldKey.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v1FieldKey.java deleted file mode 100644 index df700de..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v1FieldKey.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.jaudiotagger.tag.id3; - -/** - * Basic ID3v11 Field Names - */ -public enum ID3v1FieldKey { - ARTIST, - ALBUM, - GENRE, - TITLE, - YEAR, - TRACK, - COMMENT -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v1Iterator.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v1Iterator.java deleted file mode 100644 index 4210038..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v1Iterator.java +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: ID3v1Iterator.java 520 2008-01-01 15:16:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3; - -import java.util.Iterator; -import java.util.NoSuchElementException; - - -public class ID3v1Iterator implements Iterator { - /** - * - */ - private static final int TITLE = 1; - - /** - * - */ - private static final int ARTIST = 2; - - /** - * - */ - private static final int ALBUM = 3; - - /** - * - */ - private static final int COMMENT = 4; - - /** - * - */ - private static final int YEAR = 5; - - /** - * - */ - private static final int GENRE = 6; - - /** - * - */ - private static final int TRACK = 7; - - /** - * - */ - private ID3v1Tag id3v1tag; - - /** - * - */ - private int lastIndex = 0; - - /** - * Creates a new ID3v1Iterator datatype. - * - * @param id3v1tag - */ - public ID3v1Iterator(ID3v1Tag id3v1tag) { - this.id3v1tag = id3v1tag; - } - - /** - * @return - */ - public boolean hasNext() { - return hasNext(lastIndex); - } - - /** - * @return - */ - public Object next() { - return next(lastIndex); - } - - /** - * - */ - public void remove() { - switch (lastIndex) { - case TITLE: - id3v1tag.title = ""; - - case ARTIST: - id3v1tag.artist = ""; - - case ALBUM: - id3v1tag.album = ""; - - case COMMENT: - id3v1tag.comment = ""; - - case YEAR: - id3v1tag.year = ""; - - case GENRE: - id3v1tag.genre = (byte) -1; - - case TRACK: - - if (id3v1tag instanceof ID3v11Tag) { - ((ID3v11Tag) id3v1tag).track = (byte) -1; - } - } - } - - /** - * @param index - * @return - */ - private boolean hasNext(int index) { - switch (index) { - case TITLE: - return (id3v1tag.title.length() > 0) || hasNext(index + 1); - - case ARTIST: - return (id3v1tag.artist.length() > 0) || hasNext(index + 1); - - case ALBUM: - return (id3v1tag.album.length() > 0) || hasNext(index + 1); - - case COMMENT: - return (id3v1tag.comment.length() > 0) || hasNext(index + 1); - - case YEAR: - return (id3v1tag.year.length() > 0) || hasNext(index + 1); - - case GENRE: - return (id3v1tag.genre >= (byte) 0) || hasNext(index + 1); - - case TRACK: - - if (id3v1tag instanceof ID3v11Tag) { - return (((ID3v11Tag) id3v1tag).track >= (byte) 0) || hasNext(index + 1); - } - - default: - return false; - } - } - - /** - * @param index - * @return - * @throws NoSuchElementException - */ - private Object next(int index) { - switch (lastIndex) { - case 0: - return (id3v1tag.title.length() > 0) ? id3v1tag.title : next(index + 1); - - case TITLE: - return (id3v1tag.artist.length() > 0) ? id3v1tag.artist : next(index + 1); - - case ARTIST: - return (id3v1tag.album.length() > 0) ? id3v1tag.album : next(index + 1); - - case ALBUM: - return (id3v1tag.comment.length() > 0) ? id3v1tag.comment : next(index + 1); - - case COMMENT: - return (id3v1tag.year.length() > 0) ? id3v1tag.year : next(index + 1); - - case YEAR: - return (id3v1tag.genre >= (byte) 0) ? id3v1tag.genre : next(index + 1); - - case GENRE: - return (id3v1tag instanceof ID3v11Tag && (((ID3v11Tag) id3v1tag).track >= (byte) 0)) ? ((ID3v11Tag) id3v1tag).track : null; - - default: - throw new NoSuchElementException("Iteration has no more elements."); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v1Tag.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v1Tag.java deleted file mode 100644 index 259b711..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v1Tag.java +++ /dev/null @@ -1,921 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: ID3v1Tag.java 1082 2013-01-06 09:38:14Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.reference.GenreTypes; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.*; -import java.util.regex.Matcher; - -/** - * Represents an ID3v1 tag. - * - * @author : Eric Farng - * @author : Paul Taylor - */ -public class ID3v1Tag extends AbstractID3v1Tag implements Tag { - //For writing output - protected static final String TYPE_COMMENT = "comment"; - protected static final int FIELD_COMMENT_LENGTH = 30; - protected static final int FIELD_COMMENT_POS = 97; - protected static final int BYTE_TO_UNSIGNED = 0xff; - protected static final int GENRE_UNDEFINED = 0xff; - private static final byte RELEASE = 1; - private static final byte MAJOR_VERSION = 0; - private static final byte REVISION = 0; - static EnumMap tagFieldToID3v1Field = new EnumMap(FieldKey.class); - - static { - tagFieldToID3v1Field.put(FieldKey.ARTIST, ID3v1FieldKey.ARTIST); - tagFieldToID3v1Field.put(FieldKey.ALBUM, ID3v1FieldKey.ALBUM); - tagFieldToID3v1Field.put(FieldKey.TITLE, ID3v1FieldKey.TITLE); - tagFieldToID3v1Field.put(FieldKey.TRACK, ID3v1FieldKey.TRACK); - tagFieldToID3v1Field.put(FieldKey.YEAR, ID3v1FieldKey.YEAR); - tagFieldToID3v1Field.put(FieldKey.GENRE, ID3v1FieldKey.GENRE); - tagFieldToID3v1Field.put(FieldKey.COMMENT, ID3v1FieldKey.COMMENT); - } - - /** - * - */ - protected String album = ""; - /** - * - */ - protected String artist = ""; - /** - * - */ - protected String comment = ""; - /** - * - */ - protected String title = ""; - /** - * - */ - protected String year = ""; - /** - * - */ - protected byte genre = (byte) -1; - - /** - * Creates a new ID3v1 datatype. - */ - public ID3v1Tag() { - - } - - public ID3v1Tag(ID3v1Tag copyObject) { - super(copyObject); - - this.album = copyObject.album; - this.artist = copyObject.artist; - this.comment = copyObject.comment; - this.title = copyObject.title; - this.year = copyObject.year; - this.genre = copyObject.genre; - } - - public ID3v1Tag(AbstractTag mp3tag) { - - if (mp3tag != null) { - ID3v11Tag convertedTag; - if (mp3tag instanceof ID3v1Tag) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - if (mp3tag instanceof ID3v11Tag) { - convertedTag = (ID3v11Tag) mp3tag; - } else { - convertedTag = new ID3v11Tag(mp3tag); - } - this.album = convertedTag.album; - this.artist = convertedTag.artist; - this.comment = convertedTag.comment; - this.title = convertedTag.title; - this.year = convertedTag.year; - this.genre = convertedTag.genre; - } - } - - /** - * Creates a new ID3v1 datatype. - * - * @param file - * @param loggingFilename - * @throws TagNotFoundException - * @throws IOException - */ - public ID3v1Tag(RandomAccessFile file, String loggingFilename) throws TagNotFoundException, IOException { - setLoggingFilename(loggingFilename); - FileChannel fc; - ByteBuffer byteBuffer; - - fc = file.getChannel(); - fc.position(file.length() - TAG_LENGTH); - byteBuffer = ByteBuffer.allocate(TAG_LENGTH); - fc.read(byteBuffer); - byteBuffer.flip(); - read(byteBuffer); - } - - /** - * Creates a new ID3v1 datatype. - * - * @param file - * @throws TagNotFoundException - * @throws IOException - * @deprecated use {@link #ID3v1Tag(RandomAccessFile, String)} instead - */ - public ID3v1Tag(RandomAccessFile file) throws TagNotFoundException, IOException { - this(file, ""); - } - - /** - * Retrieve the Release - */ - public byte getRelease() { - return RELEASE; - } - - /** - * Retrieve the Major Version - */ - public byte getMajorVersion() { - return MAJOR_VERSION; - } - - /** - * Retrieve the Revision - */ - public byte getRevision() { - return REVISION; - } - - public void addField(TagField field) { - //TODO - } - - /** - * Maps the generic key to the ogg key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - List list = new ArrayList(); - list.add(getFirst(genericKey.name())); - return list; - } - - public List getFields(String id) { - - if (FieldKey.ARTIST.name().equals(id)) { - return getArtist(); - } else if (FieldKey.ALBUM.name().equals(id)) { - return getAlbum(); - } else if (FieldKey.TITLE.name().equals(id)) { - return getTitle(); - } else if (FieldKey.GENRE.name().equals(id)) { - return getGenre(); - } else if (FieldKey.YEAR.name().equals(id)) { - return getYear(); - } else if (FieldKey.COMMENT.name().equals(id)) { - return getComment(); - } - return new ArrayList(); - } - - public int getFieldCount() { - return 6; - } - - public int getFieldCountIncludingSubValues() { - return getFieldCount(); - } - - protected List returnFieldToList(ID3v1TagField field) { - List fields = new ArrayList(); - fields.add(field); - return fields; - } - - /** - * Get Album - * - * @return album - */ - public String getFirstAlbum() { - return album; - } - - /** - * @return album within list or empty if does not exist - */ - public List getAlbum() { - if (getFirstAlbum().length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.ALBUM.name(), getFirstAlbum()); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Set Album - * - * @param album - */ - public void setAlbum(String album) { - if (album == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - this.album = ID3Tags.truncate(album, FIELD_ALBUM_LENGTH); - } - - /** - * Get Artist - * - * @return artist - */ - public String getFirstArtist() { - return artist; - } - - /** - * @return Artist within list or empty if does not exist - */ - public List getArtist() { - if (getFirstArtist().length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.ARTIST.name(), getFirstArtist()); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Set Artist - * - * @param artist - */ - public void setArtist(String artist) { - if (artist == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - this.artist = ID3Tags.truncate(artist, FIELD_ARTIST_LENGTH); - } - - /** - * @return comment within list or empty if does not exist - */ - public List getComment() { - if (getFirstComment().length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.COMMENT.name(), getFirstComment()); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Set Comment - * - * @param comment - * @throws IllegalArgumentException if comment null - */ - public void setComment(String comment) { - if (comment == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - this.comment = ID3Tags.truncate(comment, FIELD_COMMENT_LENGTH); - } - - /** - * Get Comment - * - * @return comment - */ - public String getFirstComment() { - return comment; - } - - /** - * Get Genre - * - * @return genre or empty string if not valid - */ - public String getFirstGenre() { - Integer genreId = genre & BYTE_TO_UNSIGNED; - String genreValue = GenreTypes.getInstanceOf().getValueForId(genreId); - if (genreValue == null) { - return ""; - } else { - return genreValue; - } - } - - /** - * Get Genre field - *

    - *

    Only a single genre is available in ID3v1 - * - * @return - */ - public List getGenre() { - if (getFirst(FieldKey.GENRE).length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.GENRE.name(), getFirst(FieldKey.GENRE)); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Sets the genreID, - *

    - *

    ID3v1 only supports genres defined in a predefined list - * so if unable to find value in list set 255, which seems to be the value - * winamp uses for undefined. - * - * @param genreVal - */ - public void setGenre(String genreVal) { - if (genreVal == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - Integer genreID = GenreTypes.getInstanceOf().getIdForValue(genreVal); - if (genreID != null) { - this.genre = genreID.byteValue(); - } else { - this.genre = (byte) GENRE_UNDEFINED; - } - } - - /** - * Get title - * - * @return Title - */ - public String getFirstTitle() { - return title; - } - - /** - * Get title field - *

    - *

    Only a single title is available in ID3v1 - * - * @return - */ - public List getTitle() { - if (getFirst(FieldKey.TITLE).length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.TITLE.name(), getFirst(FieldKey.TITLE)); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Set Title - * - * @param title - */ - public void setTitle(String title) { - if (title == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - this.title = ID3Tags.truncate(title, FIELD_TITLE_LENGTH); - } - - /** - * Get year - * - * @return year - */ - public String getFirstYear() { - return year; - } - - /** - * Get year field - *

    - *

    Only a single year is available in ID3v1 - * - * @return - */ - public List getYear() { - if (getFirst(FieldKey.YEAR).length() > 0) { - ID3v1TagField field = new ID3v1TagField(ID3v1FieldKey.YEAR.name(), getFirst(FieldKey.YEAR)); - return returnFieldToList(field); - } else { - return new ArrayList(); - } - } - - /** - * Set year - * - * @param year - */ - public void setYear(String year) { - this.year = ID3Tags.truncate(year, FIELD_YEAR_LENGTH); - } - - public String getFirstTrack() { - throw new UnsupportedOperationException("ID3v10 cannot store track numbers"); - } - - public List getTrack() { - throw new UnsupportedOperationException("ID3v10 cannot store track numbers"); - } - - public TagField getFirstField(String id) { - List results = null; - - if (FieldKey.ARTIST.name().equals(id)) { - results = getArtist(); - } else if (FieldKey.ALBUM.name().equals(id)) { - results = getAlbum(); - } else if (FieldKey.TITLE.name().equals(id)) { - results = getTitle(); - } else if (FieldKey.GENRE.name().equals(id)) { - results = getGenre(); - } else if (FieldKey.YEAR.name().equals(id)) { - results = getYear(); - } else if (FieldKey.COMMENT.name().equals(id)) { - results = getComment(); - } - - if (results != null) { - if (results.size() > 0) { - return results.get(0); - } - } - return null; - } - - public Iterator getFields() { - throw new UnsupportedOperationException("TODO:Not done yet"); - } - - public boolean hasCommonFields() { - //TODO - return true; - } - - public boolean hasField(FieldKey genericKey) { - return getFirst(genericKey).length() > 0; - } - - public boolean hasField(String id) { - try { - FieldKey key = FieldKey.valueOf(id.toUpperCase()); - return hasField(key); - } catch (java.lang.IllegalArgumentException iae) { - return false; - } - } - - public boolean isEmpty() { - return !(getFirst(FieldKey.TITLE).length() > 0 || - getFirstArtist().length() > 0 || - getFirstAlbum().length() > 0 || - getFirst(FieldKey.GENRE).length() > 0 || - getFirst(FieldKey.YEAR).length() > 0 || - getFirstComment().length() > 0); - } - - - public void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - setField(genericKey, value); - } - - public void setField(TagField field) { - FieldKey genericKey = FieldKey.valueOf(field.getId()); - switch (genericKey) { - case ARTIST: - setArtist(field.toString()); - break; - - case ALBUM: - setAlbum(field.toString()); - break; - - case TITLE: - setTitle(field.toString()); - break; - - case GENRE: - setGenre(field.toString()); - break; - - case YEAR: - setYear(field.toString()); - break; - - case COMMENT: - setComment(field.toString()); - break; - } - } - - /** - * @param encoding - * @return - */ - public boolean setEncoding(String encoding) { - return true; - } - - /** - * Create Tag Field using generic key - */ - public TagField createField(FieldKey genericKey, String value) { - if (genericKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - ID3v1FieldKey idv1FieldKey = tagFieldToID3v1Field.get(genericKey); - if (idv1FieldKey == null) { - throw new KeyNotFoundException(ErrorMessage.INVALID_FIELD_FOR_ID3V1TAG.getMsg(genericKey.name())); - } - return new ID3v1TagField(idv1FieldKey.name(), value); - } - - public String getEncoding() { - return "ISO-8859-1"; - } - - public TagField getFirstField(FieldKey genericKey) { - List l = getFields(genericKey); - return (l.size() != 0) ? l.get(0) : null; - } - - /** - * Returns a {@linkplain List list} of {@link TagField} objects whose "{@linkplain TagField#getId() id}" - * is the specified one.
    - * - * @param genericKey The generic field key - * @return A list of {@link TagField} objects with the given "id". - */ - public List getFields(FieldKey genericKey) { - switch (genericKey) { - case ARTIST: - return getArtist(); - - case ALBUM: - return getAlbum(); - - case TITLE: - return getTitle(); - - case GENRE: - return getGenre(); - - case YEAR: - return getYear(); - - case COMMENT: - return getComment(); - - default: - return new ArrayList(); - } - } - - - /** - * Retrieve the first value that exists for this key id - * - * @param genericKey - * @return - */ - public String getFirst(String genericKey) { - FieldKey matchingKey = FieldKey.valueOf(genericKey); - if (matchingKey != null) { - return getFirst(matchingKey); - } else { - return ""; - } - } - - - /** - * Retrieve the first value that exists for this generic key - * - * @param genericKey - * @return - */ - public String getFirst(FieldKey genericKey) { - switch (genericKey) { - case ARTIST: - return getFirstArtist(); - - case ALBUM: - return getFirstAlbum(); - - case TITLE: - return getFirstTitle(); - - case GENRE: - return getFirstGenre(); - - case YEAR: - return getFirstYear(); - - case COMMENT: - return getFirstComment(); - - default: - return ""; - } - } - - /** - * The m parameter is effectively ignored - * - * @param id - * @param n - * @param m - * @return - */ - public String getSubValue(FieldKey id, int n, int m) { - return getValue(id, n); - } - - public String getValue(FieldKey genericKey, int index) { - return getFirst(genericKey); - } - - /** - * Delete any instance of tag fields with this key - * - * @param genericKey - */ - public void deleteField(FieldKey genericKey) { - switch (genericKey) { - case ARTIST: - setArtist(""); - break; - - case ALBUM: - setAlbum(""); - break; - - case TITLE: - setTitle(""); - break; - - case GENRE: - setGenre(""); - break; - - case YEAR: - setYear(""); - break; - - case COMMENT: - setComment(""); - break; - } - } - - public void deleteField(String id) { - FieldKey key = FieldKey.valueOf(id); - if (key != null) { - deleteField(key); - } - } - - /** - * @param obj - * @return true if this and obj are equivalent - */ - public boolean equals(Object obj) { - if (!(obj instanceof ID3v1Tag)) { - return false; - } - ID3v1Tag object = (ID3v1Tag) obj; - if (!this.album.equals(object.album)) { - return false; - } - if (!this.artist.equals(object.artist)) { - return false; - } - if (!this.comment.equals(object.comment)) { - return false; - } - if (this.genre != object.genre) { - return false; - } - if (!this.title.equals(object.title)) { - return false; - } - return this.year.equals(object.year) && super.equals(obj); - } - - /** - * @return an iterator to iterate through the fields of the tag - */ - public Iterator iterator() { - return new ID3v1Iterator(this); - } - - - /** - * @param byteBuffer - * @throws TagNotFoundException - */ - public void read(ByteBuffer byteBuffer) throws TagNotFoundException { - if (!seek(byteBuffer)) { - throw new TagNotFoundException(getLoggingFilename() + ":" + "ID3v1 tag not found"); - } - logger.finer(getLoggingFilename() + ":" + "Reading v1 tag"); - //Do single file read of data to cut down on file reads - byte[] dataBuffer = new byte[TAG_LENGTH]; - byteBuffer.position(0); - byteBuffer.get(dataBuffer, 0, TAG_LENGTH); - title = Utils.getString(dataBuffer, FIELD_TITLE_POS, FIELD_TITLE_LENGTH, "ISO-8859-1").trim(); - Matcher m = AbstractID3v1Tag.endofStringPattern.matcher(title); - if (m.find()) { - title = title.substring(0, m.start()); - } - artist = Utils.getString(dataBuffer, FIELD_ARTIST_POS, FIELD_ARTIST_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(artist); - if (m.find()) { - artist = artist.substring(0, m.start()); - } - album = Utils.getString(dataBuffer, FIELD_ALBUM_POS, FIELD_ALBUM_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(album); - logger.finest(getLoggingFilename() + ":" + "Orig Album is:" + comment + ":"); - if (m.find()) { - album = album.substring(0, m.start()); - logger.finest(getLoggingFilename() + ":" + "Album is:" + album + ":"); - } - year = Utils.getString(dataBuffer, FIELD_YEAR_POS, FIELD_YEAR_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(year); - if (m.find()) { - year = year.substring(0, m.start()); - } - comment = Utils.getString(dataBuffer, FIELD_COMMENT_POS, FIELD_COMMENT_LENGTH, "ISO-8859-1").trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(comment); - logger.finest(getLoggingFilename() + ":" + "Orig Comment is:" + comment + ":"); - if (m.find()) { - comment = comment.substring(0, m.start()); - logger.finest(getLoggingFilename() + ":" + "Comment is:" + comment + ":"); - } - genre = dataBuffer[FIELD_GENRE_POS]; - - } - - /** - * Does a tag of this version exist within the byteBuffer - * - * @return whether tag exists within the byteBuffer - */ - public boolean seek(ByteBuffer byteBuffer) { - byte[] buffer = new byte[FIELD_TAGID_LENGTH]; - // read the TAG value - byteBuffer.get(buffer, 0, FIELD_TAGID_LENGTH); - return (Arrays.equals(buffer, TAG_ID)); - } - - /** - * Write this tag to the file, replacing any tag previously existing - * - * @param file - * @throws IOException - */ - public void write(RandomAccessFile file) throws IOException { - logger.config("Saving ID3v1 tag to file"); - byte[] buffer = new byte[TAG_LENGTH]; - int i; - String str; - delete(file); - file.seek(file.length()); - //Copy the TAGID into new buffer - System.arraycopy(TAG_ID, FIELD_TAGID_POS, buffer, FIELD_TAGID_POS, TAG_ID.length); - int offset = FIELD_TITLE_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveTitle()) { - str = ID3Tags.truncate(title, FIELD_TITLE_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_ARTIST_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveArtist()) { - str = ID3Tags.truncate(artist, FIELD_ARTIST_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_ALBUM_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveAlbum()) { - str = ID3Tags.truncate(album, FIELD_ALBUM_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_YEAR_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveYear()) { - str = ID3Tags.truncate(year, AbstractID3v1Tag.FIELD_YEAR_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_COMMENT_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveComment()) { - str = ID3Tags.truncate(comment, FIELD_COMMENT_LENGTH); - for (i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - } - offset = FIELD_GENRE_POS; - if (TagOptionSingleton.getInstance().isId3v1SaveGenre()) { - buffer[offset] = genre; - } - file.write(buffer); - logger.config("Saved ID3v1 tag to file"); - } - - /** - * Create structured representation of this item. - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier()); - //Header - MP3File.getStructureFormatter().addElement(TYPE_TITLE, this.title); - MP3File.getStructureFormatter().addElement(TYPE_ARTIST, this.artist); - MP3File.getStructureFormatter().addElement(TYPE_ALBUM, this.album); - MP3File.getStructureFormatter().addElement(TYPE_YEAR, this.year); - MP3File.getStructureFormatter().addElement(TYPE_COMMENT, this.comment); - MP3File.getStructureFormatter().addElement(TYPE_GENRE, this.genre); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG); - } - - public List getArtworkList() { - return Collections.emptyList(); - } - - public Artwork getFirstArtwork() { - return null; - } - - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - - public void setField(Artwork artwork) throws FieldDataInvalidException { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - - public void addField(Artwork artwork) throws FieldDataInvalidException { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v1TagField.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v1TagField.java deleted file mode 100644 index cbc50aa..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v1TagField.java +++ /dev/null @@ -1,205 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.TagTextField; - -import java.io.UnsupportedEncodingException; - -/** - * This class encapsulates the name and content of a tag entry in id3 fields - *
    - * - * @author @author Raphael Slinckx (KiKiDonK) - * @author Christian Laireiter (liree) - */ -public class ID3v1TagField implements TagTextField { - - /** - * If true, the id of the current encapsulated tag field is - * specified as a common field.
    - * Example is "ARTIST" which should be interpreted by any application as the - * artist of the media content.
    - * Will be set during construction with {@link #checkCommon()}. - */ - private boolean common; - - /** - * Stores the content of the tag field.
    - */ - private String content; - - /** - * Stores the id (name) of the tag field.
    - */ - private String id; - - /** - * Creates an instance. - * - * @param raw Raw byte data of the tagfield. - * @throws UnsupportedEncodingException If the data doesn't conform "UTF-8" specification. - */ - public ID3v1TagField(byte[] raw) throws UnsupportedEncodingException { - String field = new String(raw, "ISO-8859-1"); - - int i = field.indexOf("="); - if (i == -1) { - //Beware that ogg ID, must be capitalized and contain no space.. - this.id = "ERRONEOUS"; - this.content = field; - } else { - this.id = field.substring(0, i).toUpperCase(); - if (field.length() > i) { - this.content = field.substring(i + 1); - } else { - //We have "XXXXXX=" with nothing after the "=" - this.content = ""; - } - } - checkCommon(); - } - - /** - * Creates an instance. - * - * @param fieldId ID (name) of the field. - * @param fieldContent Content of the field. - */ - public ID3v1TagField(String fieldId, String fieldContent) { - this.id = fieldId.toUpperCase(); - this.content = fieldContent; - checkCommon(); - } - - /** - * This method examines the ID of the current field and modifies - * {@link #common}in order to reflect if the tag id is a commonly used one. - *
    - */ - private void checkCommon() { - this.common = id.equals(ID3v1FieldKey.TITLE.name()) || id.equals(ID3v1FieldKey.ALBUM.name()) || id.equals(ID3v1FieldKey.ARTIST.name()) || id.equals(ID3v1FieldKey.GENRE.name()) || id.equals(ID3v1FieldKey.YEAR.name()) || id.equals(ID3v1FieldKey.COMMENT.name()) || id.equals(ID3v1FieldKey.TRACK.name()); - } - - /** - * This method will copy all bytes of src to dst - * at the specified location. - * - * @param src bytes to copy. - * @param dst where to copy to. - * @param dstOffset at which position of dst the data should be - * copied. - */ - protected void copy(byte[] src, byte[] dst, int dstOffset) { - // for (int i = 0; i < src.length; i++) - // dst[i + dstOffset] = src[i]; - /* - * Heared that this method is optimized and does its job very near of - * the system. - */ - System.arraycopy(src, 0, dst, dstOffset, src.length); - } - - /** - * @see TagField#copyContent(TagField) - */ - public void copyContent(TagField field) { - if (field instanceof TagTextField) { - this.content = ((TagTextField) field).getContent(); - } - } - - /** - * @see TagTextField#getContent() - */ - public String getContent() { - return content; - } - - /** - * @see TagTextField#setContent(String) - */ - public void setContent(String s) { - this.content = s; - } - - /** - * @see TagTextField#getEncoding() - */ - public String getEncoding() { - return "ISO-8859-1"; - } - - /** - * @see TagTextField#setEncoding(String) - */ - public void setEncoding(String s) { - //Do nothing, encoding is always ISO-8859-1 for this tag - } - - /** - * @see TagField#getId() - */ - public String getId() { - return this.id; - } - - /** - * @see TagField#getRawContent() - */ - public byte[] getRawContent() throws UnsupportedEncodingException { - byte[] size = new byte[4]; - byte[] idBytes = this.id.getBytes("ISO-8859-1"); - byte[] contentBytes = Utils.getDefaultBytes(this.content, "ISO-8859-1"); - byte[] b = new byte[4 + idBytes.length + 1 + contentBytes.length]; - - int length = idBytes.length + 1 + contentBytes.length; - size[3] = (byte) ((length & 0xFF000000) >> 24); - size[2] = (byte) ((length & 0x00FF0000) >> 16); - size[1] = (byte) ((length & 0x0000FF00) >> 8); - size[0] = (byte) (length & 0x000000FF); - - int offset = 0; - copy(size, b, offset); - offset += 4; - copy(idBytes, b, offset); - offset += idBytes.length; - b[offset] = (byte) 0x3D; - offset++;// "=" - copy(contentBytes, b, offset); - - return b; - } - - /** - * @see TagField#isBinary() - */ - public boolean isBinary() { - return false; - } - - /** - * @see TagField#isBinary(boolean) - */ - public void isBinary(boolean b) { - //Do nothing, always false - } - - /** - * @see TagField#isCommon() - */ - public boolean isCommon() { - return common; - } - - /** - * @see TagField#isEmpty() - */ - public boolean isEmpty() { - return this.content.equals(""); - } - - public String toString() { - return getContent(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v22FieldKey.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v22FieldKey.java deleted file mode 100644 index bb8a9d4..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v22FieldKey.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.id3.framebody.*; - -/** - * List of known id3v22 metadata fields - *

    - *

    These provide a mapping from the generic key to the underlying ID3v22frames. For example most of the Musicbrainz - * fields are implemnted using a User Defined Text Info Frame, but with a different description key, so this - * enum provides the link between the two. - */ -public enum ID3v22FieldKey { - ALBUM(ID3v22Frames.FRAME_ID_V2_ALBUM, Id3FieldType.TEXT), - ALBUM_ARTIST(ID3v22Frames.FRAME_ID_V2_ACCOMPANIMENT, Id3FieldType.TEXT), - ALBUM_ARTIST_SORT(ID3v22Frames.FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - ALBUM_SORT(ID3v22Frames.FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - AMAZON_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.AMAZON_ASIN, Id3FieldType.TEXT), - ARTIST(ID3v22Frames.FRAME_ID_V2_ARTIST, Id3FieldType.TEXT), - ARTIST_SORT(ID3v22Frames.FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - BARCODE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.BARCODE, Id3FieldType.TEXT), - BPM(ID3v22Frames.FRAME_ID_V2_BPM, Id3FieldType.TEXT), - CATALOG_NO(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.CATALOG_NO, Id3FieldType.TEXT), - COMMENT(ID3v22Frames.FRAME_ID_V2_COMMENT, Id3FieldType.TEXT), - COMPOSER(ID3v22Frames.FRAME_ID_V2_COMPOSER, Id3FieldType.TEXT), - COMPOSER_SORT(ID3v22Frames.FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - CONDUCTOR(ID3v22Frames.FRAME_ID_V2_CONDUCTOR, Id3FieldType.TEXT), - COVER_ART(ID3v22Frames.FRAME_ID_V2_ATTACHED_PICTURE, Id3FieldType.BINARY), - CUSTOM1(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_CUSTOM1, Id3FieldType.TEXT), - CUSTOM2(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_CUSTOM2, Id3FieldType.TEXT), - CUSTOM3(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_CUSTOM3, Id3FieldType.TEXT), - CUSTOM4(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_CUSTOM4, Id3FieldType.TEXT), - CUSTOM5(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_CUSTOM5, Id3FieldType.TEXT), - DISC_NO(ID3v22Frames.FRAME_ID_V2_SET, Id3FieldType.TEXT), - DISC_SUBTITLE(ID3v22Frames.FRAME_ID_V2_SET_SUBTITLE, Id3FieldType.TEXT), - DISC_TOTAL(ID3v22Frames.FRAME_ID_V2_SET, Id3FieldType.TEXT), - ENCODER(ID3v22Frames.FRAME_ID_V2_ENCODEDBY, Id3FieldType.TEXT), - FBPM(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.FBPM, Id3FieldType.TEXT), - GENRE(ID3v22Frames.FRAME_ID_V2_GENRE, Id3FieldType.TEXT), - GROUPING(ID3v22Frames.FRAME_ID_V2_CONTENT_GROUP_DESC, Id3FieldType.TEXT), - ISRC(ID3v22Frames.FRAME_ID_V2_ISRC, Id3FieldType.TEXT), - IS_COMPILATION(ID3v22Frames.FRAME_ID_V2_IS_COMPILATION, Id3FieldType.TEXT), - KEY(ID3v22Frames.FRAME_ID_V2_INITIAL_KEY, Id3FieldType.TEXT), - LANGUAGE(ID3v22Frames.FRAME_ID_V2_LANGUAGE, Id3FieldType.TEXT), - LYRICIST(ID3v22Frames.FRAME_ID_V2_LYRICIST, Id3FieldType.TEXT), - LYRICS(ID3v22Frames.FRAME_ID_V2_UNSYNC_LYRICS, Id3FieldType.TEXT), - MEDIA(ID3v22Frames.FRAME_ID_V2_MEDIA_TYPE, Id3FieldType.TEXT), - MOOD(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD, Id3FieldType.TEXT), - MUSICBRAINZ_ARTISTID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ARTISTID, Id3FieldType.TEXT), - MUSICBRAINZ_DISC_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_DISCID, Id3FieldType.TEXT), - MUSICBRAINZ_ORIGINAL_RELEASEID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ORIGINAL_ALBUMID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASEARTISTID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_ARTISTID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASEID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUMID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_COUNTRY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_COUNTRY, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_GROUP_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_RELEASE_GROUPID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_STATUS(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_STATUS, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_TYPE, Id3FieldType.TEXT), - MUSICBRAINZ_TRACK_ID(ID3v22Frames.FRAME_ID_V2_UNIQUE_FILE_ID, FrameBodyUFID.UFID_MUSICBRAINZ, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORKID, Id3FieldType.TEXT), - MUSICIP_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICIP_ID, Id3FieldType.TEXT), - OCCASION(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_OCCASION, Id3FieldType.TEXT), - ORIGINAL_ALBUM(ID3v22Frames.FRAME_ID_V2_ORIG_TITLE, Id3FieldType.TEXT), - ORIGINAL_ARTIST(ID3v22Frames.FRAME_ID_V2_ORIGARTIST, Id3FieldType.TEXT), - ORIGINAL_LYRICIST(ID3v22Frames.FRAME_ID_V2_ORIG_LYRICIST, Id3FieldType.TEXT), - ORIGINAL_YEAR(ID3v22Frames.FRAME_ID_V2_TORY, Id3FieldType.TEXT), - QUALITY(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_QUALITY, Id3FieldType.TEXT), - RATING(ID3v22Frames.FRAME_ID_V2_POPULARIMETER, Id3FieldType.TEXT), - RECORD_LABEL(ID3v22Frames.FRAME_ID_V2_PUBLISHER, Id3FieldType.TEXT), - REMIXER(ID3v22Frames.FRAME_ID_V2_REMIXED, Id3FieldType.TEXT), - SCRIPT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.SCRIPT, Id3FieldType.TEXT), - SUBTITLE(ID3v22Frames.FRAME_ID_V2_TITLE_REFINEMENT, Id3FieldType.TEXT), - TAGS(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.TAGS, Id3FieldType.TEXT), - TEMPO(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_TEMPO, Id3FieldType.TEXT), - TITLE(ID3v22Frames.FRAME_ID_V2_TITLE, Id3FieldType.TEXT), - TITLE_SORT(ID3v22Frames.FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - TRACK(ID3v22Frames.FRAME_ID_V2_TRACK, Id3FieldType.TEXT), - TRACK_TOTAL(ID3v22Frames.FRAME_ID_V2_TRACK, Id3FieldType.TEXT), - URL_DISCOGS_ARTIST_SITE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, FrameBodyWXXX.URL_DISCOGS_ARTIST_SITE, Id3FieldType.TEXT), - URL_DISCOGS_RELEASE_SITE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, FrameBodyWXXX.URL_DISCOGS_RELEASE_SITE, Id3FieldType.TEXT), - URL_LYRICS_SITE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, FrameBodyWXXX.URL_LYRICS_SITE, Id3FieldType.TEXT), - URL_OFFICIAL_ARTIST_SITE(ID3v22Frames.FRAME_ID_V2_URL_ARTIST_WEB, Id3FieldType.TEXT), - URL_OFFICIAL_RELEASE_SITE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, FrameBodyWXXX.URL_OFFICIAL_RELEASE_SITE, Id3FieldType.TEXT), - URL_WIKIPEDIA_ARTIST_SITE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, FrameBodyWXXX.URL_WIKIPEDIA_ARTIST_SITE, Id3FieldType.TEXT), - URL_WIKIPEDIA_RELEASE_SITE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL, FrameBodyWXXX.URL_WIKIPEDIA_RELEASE_SITE, Id3FieldType.TEXT), - YEAR(ID3v22Frames.FRAME_ID_V2_TYER, Id3FieldType.TEXT), - ENGINEER(ID3v22Frames.FRAME_ID_V2_IPLS, FrameBodyTIPL.ENGINEER, Id3FieldType.TEXT), - PRODUCER(ID3v22Frames.FRAME_ID_V2_IPLS, FrameBodyTIPL.PRODUCER, Id3FieldType.TEXT), - MIXER(ID3v22Frames.FRAME_ID_V2_IPLS, FrameBodyTIPL.MIXER, Id3FieldType.TEXT), - DJMIXER(ID3v22Frames.FRAME_ID_V2_IPLS, FrameBodyTIPL.DJMIXER, Id3FieldType.TEXT), - ARRANGER(ID3v22Frames.FRAME_ID_V2_IPLS, FrameBodyTIPL.ARRANGER, Id3FieldType.TEXT), - ARTISTS(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS, Id3FieldType.TEXT), - ACOUSTID_FINGERPRINT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ACOUSTID_FINGERPRINT, Id3FieldType.TEXT), - ACOUSTID_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ACOUSTID_ID, Id3FieldType.TEXT), - COUNTRY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.COUNTRY, Id3FieldType.TEXT),; - - private String fieldName; - - private String frameId; - private String subId; - private Id3FieldType fieldType; - - /** - * For usual metadata fields that use a data field - * - * @param frameId the frame that will be used - * @param fieldType of data atom - */ - ID3v22FieldKey(String frameId, Id3FieldType fieldType) { - this.frameId = frameId; - this.fieldType = fieldType; - - this.fieldName = frameId; - } - - /** - * @param frameId the frame that will be used - * @param subId the additioanl key required within the frame to uniquely identify this key - * @param fieldType - */ - ID3v22FieldKey(String frameId, String subId, Id3FieldType fieldType) { - this.frameId = frameId; - this.subId = subId; - this.fieldType = fieldType; - - this.fieldName = frameId + ":" + subId; - } - - /** - * @return fieldtype - */ - public Id3FieldType getFieldType() { - return fieldType; - } - - /** - * This is the frame identifier used to write the field - * - * @return - */ - public String getFrameId() { - return frameId; - } - - /** - * This is the subfield used within the frame for this type of field - * - * @return subId - */ - public String getSubId() { - return subId; - } - - /** - * This is the value of the key that can uniquely identifer a key type - * - * @return - */ - public String getFieldName() { - return fieldName; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v22Frame.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v22Frame.java deleted file mode 100644 index f2ecd5a..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v22Frame.java +++ /dev/null @@ -1,454 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.tag.EmptyFrameException; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.InvalidFrameException; -import org.jaudiotagger.tag.InvalidFrameIdentifierException; -import org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import org.jaudiotagger.tag.id3.framebody.FrameBodyDeprecated; -import org.jaudiotagger.tag.id3.framebody.FrameBodyUnsupported; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Represents an ID3v2.2 frame. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3v22Frame.java 976 2011-06-08 10:05:34Z paultaylor $ - */ -public class ID3v22Frame extends AbstractID3v2Frame { - protected static final int FRAME_ID_SIZE = 3; - protected static final int FRAME_SIZE_SIZE = 3; - protected static final int FRAME_HEADER_SIZE = FRAME_ID_SIZE + FRAME_SIZE_SIZE; - private static Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{2}"); - - public ID3v22Frame() { - - } - - /** - * Creates a new ID3v22 Frame with given body - * - * @param body New body and frame is based on this - */ - public ID3v22Frame(AbstractID3v2FrameBody body) { - super(body); - } - - /** - * Creates a new ID3v22 Frame of type identifier. - *

    - * An empty body of the correct type will be automatically created. This constructor should be used when wish to - * create a new frame from scratch using user values - * - * @param identifier - */ - @SuppressWarnings("unchecked") - public ID3v22Frame(String identifier) { - - logger.config("Creating empty frame of type" + identifier); - String bodyIdentifier = identifier; - this.identifier = identifier; - - //If dealing with v22 identifier (Note this constructor is used by all three tag versions) - if (ID3Tags.isID3v22FrameIdentifier(bodyIdentifier)) { - //Does it have its own framebody (PIC,CRM) or are we using v23/v24 body (the normal case) - if (ID3Tags.forceFrameID22To23(bodyIdentifier) != null) { - //Do not convert - } else if (bodyIdentifier.equals("CRM")) { - //Do not convert. - //TODO we don't have a way of converting this to v23 which is why its not in the ForceMap - } - //TODO Improve messy fix for datetime - //TODO need to check in case v22 body does exist before using V23 body(e.g PIC) - else if ((bodyIdentifier.equals(ID3v22Frames.FRAME_ID_V2_TYER)) || (bodyIdentifier.equals(ID3v22Frames.FRAME_ID_V2_TIME))) { - bodyIdentifier = ID3v24Frames.FRAME_ID_YEAR; - } - // Have to check for v22 because most don't have own body they use v23 or v24 - // body to hold the data, the frame is identified by its identifier, the body identifier - // is just to create a body suitable for writing the data to - else if (ID3Tags.isID3v22FrameIdentifier(bodyIdentifier)) { - bodyIdentifier = ID3Tags.convertFrameID22To23(bodyIdentifier); - } - } - - // Use reflection to map id to frame body, which makes things much easier - // to keep things up to date. - try { - Class c = (Class) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + bodyIdentifier); - frameBody = c.newInstance(); - } catch (ClassNotFoundException cnfe) { - logger.log(Level.SEVERE, cnfe.getMessage(), cnfe); - frameBody = new FrameBodyUnsupported(identifier); - } - //Instantiate Interface/Abstract should not happen - catch (InstantiationException ie) { - logger.log(Level.SEVERE, ie.getMessage(), ie); - throw new RuntimeException(ie); - } - //Private Constructor shouild not happen - catch (IllegalAccessException iae) { - logger.log(Level.SEVERE, iae.getMessage(), iae); - throw new RuntimeException(iae); - } - frameBody.setHeader(this); - logger.config("Created empty frame of type" + this.identifier + "with frame body of" + bodyIdentifier); - - } - - /** - * Copy Constructor - *

    - * Creates a new v22 frame based on another v22 frame - * - * @param frame - */ - public ID3v22Frame(ID3v22Frame frame) { - super(frame); - logger.config("Creating frame from a frame of same version"); - } - - /** - * Creates a new ID3v22 Frame from another frame of a different tag version - * - * @param frame to construct the new frame from - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - public ID3v22Frame(AbstractID3v2Frame frame) throws InvalidFrameException { - logger.config("Creating frame from a frame of a different version"); - if (frame instanceof ID3v22Frame) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - - // If it is a v24 frame is it possible to convert it into a v23 frame, anmd then convert from that - if (frame instanceof ID3v24Frame) { - ID3v23Frame v23Frame = new ID3v23Frame(frame); - createV22FrameFromV23Frame(v23Frame); - } - //If it is a v23 frame is it possible to convert it into a v22 frame - else if (frame instanceof ID3v23Frame) { - createV22FrameFromV23Frame((ID3v23Frame) frame); - } - this.frameBody.setHeader(this); - logger.config("Created frame from a frame of a different version"); - } - - /** - * Creates a new ID3v22Frame datatype by reading from byteBuffer. - * - * @param byteBuffer to read from - * @param loggingFilename - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - public ID3v22Frame(ByteBuffer byteBuffer, String loggingFilename) throws InvalidFrameException, InvalidDataTypeException { - setLoggingFilename(loggingFilename); - read(byteBuffer); - } - - /** - * Creates a new ID3v23Frame datatype by reading from byteBuffer. - * - * @param byteBuffer to read from - * @throws org.jaudiotagger.tag.InvalidFrameException - * @deprecated use {@link #ID3v22Frame(ByteBuffer, String)} instead - */ - public ID3v22Frame(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException { - this(byteBuffer, ""); - } - - protected int getFrameIdSize() { - return FRAME_ID_SIZE; - } - - protected int getFrameSizeSize() { - return FRAME_SIZE_SIZE; - } - - protected int getFrameHeaderSize() { - return FRAME_HEADER_SIZE; - } - - /** - * Compare for equality - * To be deemed equal obj must be a IDv23Frame with the same identifier - * and the same flags. - * containing the same body,datatype list ectera. - * equals() method is made up from all the various components - * - * @param obj - * @return if true if this object is equivalent to obj - */ - public boolean equals(Object obj) { - if (this == obj) return true; - - if (!(obj instanceof ID3v22Frame)) { - return false; - } - ID3v22Frame that = (ID3v22Frame) obj; - - - return - EqualsUtil.areEqual(this.statusFlags, that.statusFlags) && - EqualsUtil.areEqual(this.encodingFlags, that.encodingFlags) && - super.equals(that); - - } - - private void createV22FrameFromV23Frame(ID3v23Frame frame) throws InvalidFrameException { - identifier = ID3Tags.convertFrameID23To22(frame.getIdentifier()); - if (identifier != null) { - logger.config("V2:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = (AbstractID3v2FrameBody) ID3Tags.copyObject(frame.getBody()); - } - // Is it a known v3 frame which needs forcing to v2 frame e.g. APIC - PIC - else if (ID3Tags.isID3v23FrameIdentifier(frame.getIdentifier())) { - identifier = ID3Tags.forceFrameID23To22(frame.getIdentifier()); - if (identifier != null) { - logger.config("V2:Force:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody()); - } - // No mechanism exists to convert it to a v22 frame - else { - throw new InvalidFrameException("Unable to convert v23 frame:" + frame.getIdentifier() + " to a v22 frame"); - } - } - //Deprecated frame for v23 - else if (frame.getBody() instanceof FrameBodyDeprecated) { - //Was it valid for this tag version, if so try and reconstruct - if (ID3Tags.isID3v22FrameIdentifier(frame.getIdentifier())) { - this.frameBody = frame.getBody(); - identifier = frame.getIdentifier(); - logger.config("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - } - //or was it still deprecated, if so leave as is - else { - this.frameBody = new FrameBodyDeprecated((FrameBodyDeprecated) frame.getBody()); - identifier = frame.getIdentifier(); - logger.config("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - } - } - // Unknown Frame e.g NCON - else { - this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody()); - identifier = frame.getIdentifier(); - logger.config("v2:UNKNOWN:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - } - } - - /** - * Return size of frame - * - * @return int size of frame - */ - public int getSize() { - return frameBody.getSize() + getFrameHeaderSize(); - } - - @Override - protected boolean isPadding(byte[] buffer) { - return (buffer[0] == '\0') && - (buffer[1] == '\0') && - (buffer[2] == '\0'); - } - - /** - * Read frame from file. - * Read the frame header then delegate reading of data to frame body. - * - * @param byteBuffer - */ - public void read(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException { - String identifier = readIdentifier(byteBuffer); - - byte[] buffer = new byte[getFrameSizeSize()]; - - // Is this a valid identifier? - if (!isValidID3v2FrameIdentifier(identifier)) { - logger.config("Invalid identifier:" + identifier); - byteBuffer.position(byteBuffer.position() - (getFrameIdSize() - 1)); - throw new InvalidFrameIdentifierException(getLoggingFilename() + ":" + identifier + ":is not a valid ID3v2.20 frame"); - } - //Read Frame Size (same size as Frame Id so reuse buffer) - byteBuffer.get(buffer, 0, getFrameSizeSize()); - frameSize = decodeSize(buffer); - if (frameSize < 0) { - throw new InvalidFrameException(identifier + " has invalid size of:" + frameSize); - } else if (frameSize == 0) { - //We dont process this frame or add to framemap becuase contains no useful information - logger.warning("Empty Frame:" + identifier); - throw new EmptyFrameException(identifier + " is empty frame"); - } else if (frameSize > byteBuffer.remaining()) { - logger.warning("Invalid Frame size larger than size before mp3 audio:" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame"); - } else { - logger.fine("Frame Size Is:" + frameSize); - //Convert v2.2 to v2.4 id just for reading the data - String id = ID3Tags.convertFrameID22To24(identifier); - if (id == null) { - //OK,it may be convertable to a v.3 id even though not valid v.4 - id = ID3Tags.convertFrameID22To23(identifier); - if (id == null) { - // Is it a valid v22 identifier so should be able to find a - // frame body for it. - if (ID3Tags.isID3v22FrameIdentifier(identifier)) { - id = identifier; - } - // Unknown so will be created as FrameBodyUnsupported - else { - id = UNSUPPORTED_ID; - } - } - } - logger.fine("Identifier was:" + identifier + " reading using:" + id); - - //Create Buffer that only contains the body of this frame rather than the remainder of tag - ByteBuffer frameBodyBuffer = byteBuffer.slice(); - frameBodyBuffer.limit(frameSize); - - try { - frameBody = readBody(id, frameBodyBuffer, frameSize); - } finally { - //Update position of main buffer, so no attempt is made to reread these bytes - byteBuffer.position(byteBuffer.position() + frameSize); - } - } - } - - /** - * Read Frame Size, which has to be decoded - * - * @param buffer - * @return - */ - private int decodeSize(byte[] buffer) { - BigInteger bi = new BigInteger(buffer); - int tmpSize = bi.intValue(); - if (tmpSize < 0) { - logger.warning("Invalid Frame Size of:" + tmpSize + "Decoded from bin:" + Integer.toBinaryString(tmpSize) + "Decoded from hex:" + Integer.toHexString(tmpSize)); - } - return tmpSize; - } - - - /** - * Write Frame raw data - * - * @throws IOException - */ - public void write(ByteArrayOutputStream tagBuffer) { - logger.config("Write Frame to Buffer" + getIdentifier()); - //This is where we will write header, move position to where we can - //write body - ByteBuffer headerBuffer = ByteBuffer.allocate(getFrameHeaderSize()); - - //Write Frame Body Data - ByteArrayOutputStream bodyOutputStream = new ByteArrayOutputStream(); - ((AbstractID3v2FrameBody) frameBody).write(bodyOutputStream); - - //Write Frame Header - //Write Frame ID must adjust can only be 3 bytes long - headerBuffer.put(Utils.getDefaultBytes(getIdentifier(), "ISO-8859-1"), 0, getFrameIdSize()); - encodeSize(headerBuffer, frameBody.getSize()); - - //Add header to the Byte Array Output Stream - try { - tagBuffer.write(headerBuffer.array()); - - //Add body to the Byte Array Output Stream - tagBuffer.write(bodyOutputStream.toByteArray()); - } catch (IOException ioe) { - //This could never happen coz not writing to file, so convert to RuntimeException - throw new RuntimeException(ioe); - } - } - - /** - * Write Frame Size (can now be accurately calculated, have to convert 4 byte int - * to 3 byte format. - * - * @param headerBuffer - * @param size - */ - private void encodeSize(ByteBuffer headerBuffer, int size) { - headerBuffer.put((byte) ((size & 0x00FF0000) >> 16)); - headerBuffer.put((byte) ((size & 0x0000FF00) >> 8)); - headerBuffer.put((byte) (size & 0x000000FF)); - logger.fine("Frame Size Is Actual:" + size + ":Encoded bin:" + Integer.toBinaryString(size) + ":Encoded Hex" + Integer.toHexString(size)); - } - - /** - * Does the frame identifier meet the syntax for a idv3v2 frame identifier. - * must start with a capital letter and only contain capital letters and numbers - * - * @param identifier - * @return - */ - public boolean isValidID3v2FrameIdentifier(String identifier) { - Matcher m = ID3v22Frame.validFrameIdentifier.matcher(identifier); - return m.matches(); - } - - /** - * Return String Representation of body - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FRAME, getIdentifier()); - MP3File.getStructureFormatter().addElement(TYPE_FRAME_SIZE, frameSize); - frameBody.createStructure(); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FRAME); - } - - /** - * @return true if considered a common frame - */ - public boolean isCommon() { - return ID3v22Frames.getInstanceOf().isCommon(getId()); - } - - /** - * @return true if considered a common frame - */ - public boolean isBinary() { - return ID3v22Frames.getInstanceOf().isBinary(getId()); - } - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - public void setEncoding(String encoding) { - Integer encodingId = TextEncoding.getInstanceOf().getIdForValue(encoding); - if (encoding != null) { - if (encodingId < 2) { - this.getBody().setTextEncoding(encodingId.byteValue()); - } - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v22Frames.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v22Frames.java deleted file mode 100644 index 8492fbf..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v22Frames.java +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Jaudiotagger Copyright (C)2004,2005 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.FieldKey; - -import java.util.EnumMap; -import java.util.Map; - -/** - * Defines ID3v22 frames and collections that categorise frames within an ID3v22 tag. - *

    - * You can include frames here that are not officially supported as long as they can be used within an - * ID3v22Tag - * - * @author Paul Taylor - * @version $Id: ID3v22Frames.java 1081 2013-01-04 20:09:36Z paultaylor $ - */ -public class ID3v22Frames extends ID3Frames { - //V2 Frames (only 3 chars) - public static final String FRAME_ID_V2_ACCOMPANIMENT = "TP2"; - public static final String FRAME_ID_V2_ALBUM = "TAL"; - public static final String FRAME_ID_V2_ARTIST = "TP1"; - public static final String FRAME_ID_V2_ATTACHED_PICTURE = "PIC"; - public static final String FRAME_ID_V2_AUDIO_ENCRYPTION = "CRA"; - public static final String FRAME_ID_V2_BPM = "TBP"; - public static final String FRAME_ID_V2_COMMENT = "COM"; - public static final String FRAME_ID_V2_COMPOSER = "TCM"; - public static final String FRAME_ID_V2_CONDUCTOR = "TPE"; - public static final String FRAME_ID_V2_CONTENT_GROUP_DESC = "TT1"; - public static final String FRAME_ID_V2_COPYRIGHTINFO = "TCR"; - public static final String FRAME_ID_V2_ENCODEDBY = "TEN"; - public static final String FRAME_ID_V2_ENCRYPTED_FRAME = "CRM"; - public static final String FRAME_ID_V2_EQUALISATION = "EQU"; - public static final String FRAME_ID_V2_EVENT_TIMING_CODES = "ETC"; - public static final String FRAME_ID_V2_FILE_TYPE = "TFT"; - public static final String FRAME_ID_V2_GENERAL_ENCAPS_OBJECT = "GEO"; - public static final String FRAME_ID_V2_GENRE = "TCO"; - public static final String FRAME_ID_V2_HW_SW_SETTINGS = "TSS"; - public static final String FRAME_ID_V2_INITIAL_KEY = "TKE"; - public static final String FRAME_ID_V2_IPLS = "IPL"; - public static final String FRAME_ID_V2_ISRC = "TRC"; - public static final String FRAME_ID_V2_LANGUAGE = "TLA"; - public static final String FRAME_ID_V2_LENGTH = "TLE"; - public static final String FRAME_ID_V2_LINKED_INFO = "LNK"; - public static final String FRAME_ID_V2_LYRICIST = "TXT"; - public static final String FRAME_ID_V2_MEDIA_TYPE = "TMT"; - public static final String FRAME_ID_V2_MPEG_LOCATION_LOOKUP_TABLE = "MLL"; - public static final String FRAME_ID_V2_MUSIC_CD_ID = "MCI"; - public static final String FRAME_ID_V2_ORIGARTIST = "TOA"; - public static final String FRAME_ID_V2_ORIG_FILENAME = "TOF"; - public static final String FRAME_ID_V2_ORIG_LYRICIST = "TOL"; - public static final String FRAME_ID_V2_ORIG_TITLE = "TOT"; - public static final String FRAME_ID_V2_PLAYLIST_DELAY = "TDY"; - public static final String FRAME_ID_V2_PLAY_COUNTER = "CNT"; - public static final String FRAME_ID_V2_POPULARIMETER = "POP"; - public static final String FRAME_ID_V2_PUBLISHER = "TPB"; - public static final String FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE = "BUF"; - public static final String FRAME_ID_V2_RELATIVE_VOLUME_ADJUSTMENT = "RVA"; - public static final String FRAME_ID_V2_REMIXED = "TP4"; - public static final String FRAME_ID_V2_REVERB = "REV"; - public static final String FRAME_ID_V2_SET = "TPA"; - public static final String FRAME_ID_V2_SET_SUBTITLE = "TPS"; //Note this is non-standard - public static final String FRAME_ID_V2_SYNC_LYRIC = "SLT"; - public static final String FRAME_ID_V2_SYNC_TEMPO = "STC"; - public static final String FRAME_ID_V2_TDAT = "TDA"; - public static final String FRAME_ID_V2_TIME = "TIM"; - public static final String FRAME_ID_V2_TITLE = "TT2"; - public static final String FRAME_ID_V2_TITLE_REFINEMENT = "TT3"; - public static final String FRAME_ID_V2_TORY = "TOR"; - public static final String FRAME_ID_V2_TRACK = "TRK"; - public static final String FRAME_ID_V2_TRDA = "TRD"; - public static final String FRAME_ID_V2_TSIZ = "TSI"; - public static final String FRAME_ID_V2_TYER = "TYE"; - public static final String FRAME_ID_V2_UNIQUE_FILE_ID = "UFI"; - public static final String FRAME_ID_V2_UNSYNC_LYRICS = "ULT"; - public static final String FRAME_ID_V2_URL_ARTIST_WEB = "WAR"; - public static final String FRAME_ID_V2_URL_COMMERCIAL = "WCM"; - public static final String FRAME_ID_V2_URL_COPYRIGHT = "WCP"; - public static final String FRAME_ID_V2_URL_FILE_WEB = "WAF"; - public static final String FRAME_ID_V2_URL_OFFICIAL_RADIO = "WRS"; - public static final String FRAME_ID_V2_URL_PAYMENT = "WPAY"; - public static final String FRAME_ID_V2_URL_PUBLISHERS = "WPB"; - public static final String FRAME_ID_V2_URL_SOURCE_WEB = "WAS"; - public static final String FRAME_ID_V2_USER_DEFINED_INFO = "TXX"; - public static final String FRAME_ID_V2_USER_DEFINED_URL = "WXX"; - - public static final String FRAME_ID_V2_IS_COMPILATION = "TCP"; - public static final String FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES = "TST"; - public static final String FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES = "TSP"; - public static final String FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES = "TSA"; - public static final String FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES = "TS2"; - public static final String FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES = "TSC"; - - private static ID3v22Frames id3v22Frames; - - /** - * Maps from Generic key to ID3 key - */ - protected EnumMap tagFieldToId3 = new EnumMap(FieldKey.class); - - /** - * Maps from ID3 key to Generic key - */ - protected EnumMap id3ToTagField = new EnumMap(ID3v22FieldKey.class); - - - private ID3v22Frames() { - // The defined v22 frames - supportedFrames.add(FRAME_ID_V2_ACCOMPANIMENT); - supportedFrames.add(FRAME_ID_V2_ALBUM); - supportedFrames.add(FRAME_ID_V2_ARTIST); - supportedFrames.add(FRAME_ID_V2_ATTACHED_PICTURE); - supportedFrames.add(FRAME_ID_V2_AUDIO_ENCRYPTION); - supportedFrames.add(FRAME_ID_V2_BPM); - supportedFrames.add(FRAME_ID_V2_COMMENT); - supportedFrames.add(FRAME_ID_V2_COMPOSER); - supportedFrames.add(FRAME_ID_V2_ENCRYPTED_FRAME); - supportedFrames.add(FRAME_ID_V2_CONDUCTOR); - supportedFrames.add(FRAME_ID_V2_CONTENT_GROUP_DESC); - supportedFrames.add(FRAME_ID_V2_COPYRIGHTINFO); - supportedFrames.add(FRAME_ID_V2_ENCODEDBY); - supportedFrames.add(FRAME_ID_V2_ENCRYPTED_FRAME); - supportedFrames.add(FRAME_ID_V2_EQUALISATION); - supportedFrames.add(FRAME_ID_V2_EVENT_TIMING_CODES); - supportedFrames.add(FRAME_ID_V2_FILE_TYPE); - supportedFrames.add(FRAME_ID_V2_GENERAL_ENCAPS_OBJECT); - supportedFrames.add(FRAME_ID_V2_GENRE); - supportedFrames.add(FRAME_ID_V2_HW_SW_SETTINGS); - supportedFrames.add(FRAME_ID_V2_INITIAL_KEY); - supportedFrames.add(FRAME_ID_V2_IPLS); - supportedFrames.add(FRAME_ID_V2_ISRC); - supportedFrames.add(FRAME_ID_V2_LANGUAGE); - supportedFrames.add(FRAME_ID_V2_LENGTH); - supportedFrames.add(FRAME_ID_V2_LINKED_INFO); - supportedFrames.add(FRAME_ID_V2_LYRICIST); - supportedFrames.add(FRAME_ID_V2_MEDIA_TYPE); - supportedFrames.add(FRAME_ID_V2_MPEG_LOCATION_LOOKUP_TABLE); - supportedFrames.add(FRAME_ID_V2_MUSIC_CD_ID); - supportedFrames.add(FRAME_ID_V2_ORIGARTIST); - supportedFrames.add(FRAME_ID_V2_ORIG_FILENAME); - supportedFrames.add(FRAME_ID_V2_ORIG_LYRICIST); - supportedFrames.add(FRAME_ID_V2_ORIG_TITLE); - supportedFrames.add(FRAME_ID_V2_PLAYLIST_DELAY); - supportedFrames.add(FRAME_ID_V2_PLAY_COUNTER); - supportedFrames.add(FRAME_ID_V2_POPULARIMETER); - supportedFrames.add(FRAME_ID_V2_PUBLISHER); - supportedFrames.add(FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE); - supportedFrames.add(FRAME_ID_V2_RELATIVE_VOLUME_ADJUSTMENT); - supportedFrames.add(FRAME_ID_V2_REMIXED); - supportedFrames.add(FRAME_ID_V2_REVERB); - supportedFrames.add(FRAME_ID_V2_SET); - supportedFrames.add(FRAME_ID_V2_SYNC_LYRIC); - supportedFrames.add(FRAME_ID_V2_SYNC_TEMPO); - supportedFrames.add(FRAME_ID_V2_TDAT); - supportedFrames.add(FRAME_ID_V2_TIME); - supportedFrames.add(FRAME_ID_V2_TITLE); - supportedFrames.add(FRAME_ID_V2_TITLE_REFINEMENT); - supportedFrames.add(FRAME_ID_V2_TORY); - supportedFrames.add(FRAME_ID_V2_TRACK); - supportedFrames.add(FRAME_ID_V2_TRDA); - supportedFrames.add(FRAME_ID_V2_TSIZ); - supportedFrames.add(FRAME_ID_V2_TYER); - supportedFrames.add(FRAME_ID_V2_UNIQUE_FILE_ID); - supportedFrames.add(FRAME_ID_V2_UNSYNC_LYRICS); - supportedFrames.add(FRAME_ID_V2_URL_ARTIST_WEB); - supportedFrames.add(FRAME_ID_V2_URL_COMMERCIAL); - supportedFrames.add(FRAME_ID_V2_URL_COPYRIGHT); - supportedFrames.add(FRAME_ID_V2_URL_FILE_WEB); - supportedFrames.add(FRAME_ID_V2_URL_OFFICIAL_RADIO); - supportedFrames.add(FRAME_ID_V2_URL_PAYMENT); - supportedFrames.add(FRAME_ID_V2_URL_PUBLISHERS); - supportedFrames.add(FRAME_ID_V2_URL_SOURCE_WEB); - supportedFrames.add(FRAME_ID_V2_USER_DEFINED_INFO); - supportedFrames.add(FRAME_ID_V2_USER_DEFINED_URL); - - //Extension - extensionFrames.add(FRAME_ID_V2_IS_COMPILATION); - extensionFrames.add(FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES); - - //Common - commonFrames.add(FRAME_ID_V2_ARTIST); - commonFrames.add(FRAME_ID_V2_ALBUM); - commonFrames.add(FRAME_ID_V2_TITLE); - commonFrames.add(FRAME_ID_V2_GENRE); - commonFrames.add(FRAME_ID_V2_TRACK); - commonFrames.add(FRAME_ID_V2_TYER); - commonFrames.add(FRAME_ID_V2_COMMENT); - - //Binary - binaryFrames.add(FRAME_ID_V2_ATTACHED_PICTURE); - binaryFrames.add(FRAME_ID_V2_AUDIO_ENCRYPTION); - binaryFrames.add(FRAME_ID_V2_ENCRYPTED_FRAME); - binaryFrames.add(FRAME_ID_V2_EQUALISATION); - binaryFrames.add(FRAME_ID_V2_EVENT_TIMING_CODES); - binaryFrames.add(FRAME_ID_V2_GENERAL_ENCAPS_OBJECT); - binaryFrames.add(FRAME_ID_V2_RELATIVE_VOLUME_ADJUSTMENT); - binaryFrames.add(FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE); - binaryFrames.add(FRAME_ID_V2_UNIQUE_FILE_ID); - - // Map frameid to a name - idToValue.put(FRAME_ID_V2_ACCOMPANIMENT, "Text: Band/Orchestra/Accompaniment"); - idToValue.put(FRAME_ID_V2_ALBUM, "Text: Album/Movie/Show title"); - idToValue.put(FRAME_ID_V2_ARTIST, "Text: Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group"); - idToValue.put(FRAME_ID_V2_ATTACHED_PICTURE, "Attached picture"); - idToValue.put(FRAME_ID_V2_AUDIO_ENCRYPTION, "Audio encryption"); - idToValue.put(FRAME_ID_V2_BPM, "Text: BPM (Beats Per Minute)"); - idToValue.put(FRAME_ID_V2_COMMENT, "Comments"); - idToValue.put(FRAME_ID_V2_COMPOSER, "Text: Composer"); - idToValue.put(FRAME_ID_V2_CONDUCTOR, "Text: Conductor/Performer refinement"); - idToValue.put(FRAME_ID_V2_CONTENT_GROUP_DESC, "Text: Content group description"); - idToValue.put(FRAME_ID_V2_COPYRIGHTINFO, "Text: Copyright message"); - idToValue.put(FRAME_ID_V2_ENCODEDBY, "Text: Encoded by"); - idToValue.put(FRAME_ID_V2_ENCRYPTED_FRAME, "Encrypted meta frame"); - idToValue.put(FRAME_ID_V2_EQUALISATION, "Equalization"); - idToValue.put(FRAME_ID_V2_EVENT_TIMING_CODES, "Event timing codes"); - idToValue.put(FRAME_ID_V2_FILE_TYPE, "Text: File type"); - idToValue.put(FRAME_ID_V2_GENERAL_ENCAPS_OBJECT, "General encapsulated datatype"); - idToValue.put(FRAME_ID_V2_GENRE, "Text: Content type"); - idToValue.put(FRAME_ID_V2_HW_SW_SETTINGS, "Text: Software/hardware and settings used for encoding"); - idToValue.put(FRAME_ID_V2_INITIAL_KEY, "Text: Initial key"); - idToValue.put(FRAME_ID_V2_IPLS, "Involved people list"); - idToValue.put(FRAME_ID_V2_ISRC, "Text: ISRC (International Standard Recording Code)"); - idToValue.put(FRAME_ID_V2_LANGUAGE, "Text: Language(s)"); - idToValue.put(FRAME_ID_V2_LENGTH, "Text: Length"); - idToValue.put(FRAME_ID_V2_LINKED_INFO, "Linked information"); - idToValue.put(FRAME_ID_V2_LYRICIST, "Text: Lyricist/text writer"); - idToValue.put(FRAME_ID_V2_MEDIA_TYPE, "Text: Media type"); - idToValue.put(FRAME_ID_V2_MPEG_LOCATION_LOOKUP_TABLE, "MPEG location lookup table"); - idToValue.put(FRAME_ID_V2_MUSIC_CD_ID, "Music CD Identifier"); - idToValue.put(FRAME_ID_V2_ORIGARTIST, "Text: Original artist(s)/performer(s)"); - idToValue.put(FRAME_ID_V2_ORIG_FILENAME, "Text: Original filename"); - idToValue.put(FRAME_ID_V2_ORIG_LYRICIST, "Text: Original Lyricist(s)/text writer(s)"); - idToValue.put(FRAME_ID_V2_ORIG_TITLE, "Text: Original album/Movie/Show title"); - idToValue.put(FRAME_ID_V2_PLAYLIST_DELAY, "Text: Playlist delay"); - idToValue.put(FRAME_ID_V2_PLAY_COUNTER, "Play counter"); - idToValue.put(FRAME_ID_V2_POPULARIMETER, "Popularimeter"); - idToValue.put(FRAME_ID_V2_PUBLISHER, "Text: Publisher"); - idToValue.put(FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE, "Recommended buffer size"); - idToValue.put(FRAME_ID_V2_RELATIVE_VOLUME_ADJUSTMENT, "Relative volume adjustment"); - idToValue.put(FRAME_ID_V2_REMIXED, "Text: Interpreted, remixed, or otherwise modified by"); - idToValue.put(FRAME_ID_V2_REVERB, "Reverb"); - idToValue.put(FRAME_ID_V2_SET, "Text: Part of a setField"); - idToValue.put(FRAME_ID_V2_SET_SUBTITLE, "Text: Set subtitle"); - idToValue.put(FRAME_ID_V2_SYNC_LYRIC, "Synchronized lyric/text"); - idToValue.put(FRAME_ID_V2_SYNC_TEMPO, "Synced tempo codes"); - idToValue.put(FRAME_ID_V2_TDAT, "Text: Date"); - idToValue.put(FRAME_ID_V2_TIME, "Text: Time"); - idToValue.put(FRAME_ID_V2_TITLE, "Text: Title/Songname/Content description"); - idToValue.put(FRAME_ID_V2_TITLE_REFINEMENT, "Text: Subtitle/Description refinement"); - idToValue.put(FRAME_ID_V2_TORY, "Text: Original release year"); - idToValue.put(FRAME_ID_V2_TRACK, "Text: Track number/Position in setField"); - idToValue.put(FRAME_ID_V2_TRDA, "Text: Recording dates"); - idToValue.put(FRAME_ID_V2_TSIZ, "Text: Size"); - idToValue.put(FRAME_ID_V2_TYER, "Text: Year"); - idToValue.put(FRAME_ID_V2_UNIQUE_FILE_ID, "Unique file identifier"); - idToValue.put(FRAME_ID_V2_UNSYNC_LYRICS, "Unsychronized lyric/text transcription"); - idToValue.put(FRAME_ID_V2_URL_ARTIST_WEB, "URL: Official artist/performer webpage"); - idToValue.put(FRAME_ID_V2_URL_COMMERCIAL, "URL: Commercial information"); - idToValue.put(FRAME_ID_V2_URL_COPYRIGHT, "URL: Copyright/Legal information"); - idToValue.put(FRAME_ID_V2_URL_FILE_WEB, "URL: Official audio file webpage"); - idToValue.put(FRAME_ID_V2_URL_OFFICIAL_RADIO, "URL: Official radio station"); - idToValue.put(FRAME_ID_V2_URL_PAYMENT, "URL: Official payment site"); - idToValue.put(FRAME_ID_V2_URL_PUBLISHERS, "URL: Publishers official webpage"); - idToValue.put(FRAME_ID_V2_URL_SOURCE_WEB, "URL: Official audio source webpage"); - idToValue.put(FRAME_ID_V2_USER_DEFINED_INFO, "User defined text information frame"); - idToValue.put(FRAME_ID_V2_USER_DEFINED_URL, "User defined URL link frame"); - - idToValue.put(FRAME_ID_V2_IS_COMPILATION, "Is Compilation"); - idToValue.put(FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES, "Text: title sort order"); - idToValue.put(FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES, "Text: artist sort order"); - idToValue.put(FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES, "Text: album sort order"); - idToValue.put(FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES, "Text:Album Artist Sort Order Frame"); - idToValue.put(FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES, "Text:Composer Sort Order Frame"); - - - createMaps(); - - multipleFrames.add(FRAME_ID_V2_ATTACHED_PICTURE); - multipleFrames.add(FRAME_ID_V2_UNIQUE_FILE_ID); - multipleFrames.add(FRAME_ID_V2_POPULARIMETER); - multipleFrames.add(FRAME_ID_V2_USER_DEFINED_INFO); - multipleFrames.add(FRAME_ID_V2_USER_DEFINED_URL); - multipleFrames.add(FRAME_ID_V2_COMMENT); - multipleFrames.add(FRAME_ID_V2_UNSYNC_LYRICS); - multipleFrames.add(FRAME_ID_V2_GENERAL_ENCAPS_OBJECT); - multipleFrames.add(FRAME_ID_V2_URL_ARTIST_WEB); - - //Mapping generic key to id3v22 key - tagFieldToId3.put(FieldKey.ALBUM, ID3v22FieldKey.ALBUM); - tagFieldToId3.put(FieldKey.ALBUM_ARTIST, ID3v22FieldKey.ALBUM_ARTIST); - tagFieldToId3.put(FieldKey.ALBUM_ARTIST_SORT, ID3v22FieldKey.ALBUM_ARTIST_SORT); - tagFieldToId3.put(FieldKey.ALBUM_SORT, ID3v22FieldKey.ALBUM_SORT); - tagFieldToId3.put(FieldKey.AMAZON_ID, ID3v22FieldKey.AMAZON_ID); - tagFieldToId3.put(FieldKey.ARTIST, ID3v22FieldKey.ARTIST); - tagFieldToId3.put(FieldKey.ARTIST_SORT, ID3v22FieldKey.ARTIST_SORT); - tagFieldToId3.put(FieldKey.BARCODE, ID3v22FieldKey.BARCODE); - tagFieldToId3.put(FieldKey.BPM, ID3v22FieldKey.BPM); - tagFieldToId3.put(FieldKey.CATALOG_NO, ID3v22FieldKey.CATALOG_NO); - tagFieldToId3.put(FieldKey.COMMENT, ID3v22FieldKey.COMMENT); - tagFieldToId3.put(FieldKey.COMPOSER, ID3v22FieldKey.COMPOSER); - tagFieldToId3.put(FieldKey.COMPOSER_SORT, ID3v22FieldKey.COMPOSER_SORT); - tagFieldToId3.put(FieldKey.CONDUCTOR, ID3v22FieldKey.CONDUCTOR); - tagFieldToId3.put(FieldKey.COVER_ART, ID3v22FieldKey.COVER_ART); - tagFieldToId3.put(FieldKey.CUSTOM1, ID3v22FieldKey.CUSTOM1); - tagFieldToId3.put(FieldKey.CUSTOM2, ID3v22FieldKey.CUSTOM2); - tagFieldToId3.put(FieldKey.CUSTOM3, ID3v22FieldKey.CUSTOM3); - tagFieldToId3.put(FieldKey.CUSTOM4, ID3v22FieldKey.CUSTOM4); - tagFieldToId3.put(FieldKey.CUSTOM5, ID3v22FieldKey.CUSTOM5); - tagFieldToId3.put(FieldKey.DISC_NO, ID3v22FieldKey.DISC_NO); - tagFieldToId3.put(FieldKey.DISC_SUBTITLE, ID3v22FieldKey.DISC_SUBTITLE); - tagFieldToId3.put(FieldKey.DISC_TOTAL, ID3v22FieldKey.DISC_NO); - tagFieldToId3.put(FieldKey.ENCODER, ID3v22FieldKey.ENCODER); - tagFieldToId3.put(FieldKey.FBPM, ID3v22FieldKey.FBPM); - tagFieldToId3.put(FieldKey.GENRE, ID3v22FieldKey.GENRE); - tagFieldToId3.put(FieldKey.GROUPING, ID3v22FieldKey.GROUPING); - tagFieldToId3.put(FieldKey.ISRC, ID3v22FieldKey.ISRC); - tagFieldToId3.put(FieldKey.IS_COMPILATION, ID3v22FieldKey.IS_COMPILATION); - tagFieldToId3.put(FieldKey.KEY, ID3v22FieldKey.KEY); - tagFieldToId3.put(FieldKey.LANGUAGE, ID3v22FieldKey.LANGUAGE); - tagFieldToId3.put(FieldKey.LYRICIST, ID3v22FieldKey.LYRICIST); - tagFieldToId3.put(FieldKey.LYRICS, ID3v22FieldKey.LYRICS); - tagFieldToId3.put(FieldKey.MEDIA, ID3v22FieldKey.MEDIA); - tagFieldToId3.put(FieldKey.MOOD, ID3v22FieldKey.MOOD); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_ARTISTID, ID3v22FieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_DISC_ID, ID3v22FieldKey.MUSICBRAINZ_DISC_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, ID3v22FieldKey.MUSICBRAINZ_ORIGINAL_RELEASEID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, ID3v22FieldKey.MUSICBRAINZ_RELEASEARTISTID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASEID, ID3v22FieldKey.MUSICBRAINZ_RELEASEID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, ID3v22FieldKey.MUSICBRAINZ_RELEASE_COUNTRY); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, ID3v22FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, ID3v22FieldKey.MUSICBRAINZ_RELEASE_STATUS); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, ID3v22FieldKey.MUSICBRAINZ_RELEASE_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_TRACK_ID, ID3v22FieldKey.MUSICBRAINZ_TRACK_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_ID); - tagFieldToId3.put(FieldKey.MUSICIP_ID, ID3v22FieldKey.MUSICIP_ID); - tagFieldToId3.put(FieldKey.OCCASION, ID3v22FieldKey.OCCASION); - tagFieldToId3.put(FieldKey.ORIGINAL_ALBUM, ID3v22FieldKey.ORIGINAL_ALBUM); - tagFieldToId3.put(FieldKey.ORIGINAL_ARTIST, ID3v22FieldKey.ORIGINAL_ARTIST); - tagFieldToId3.put(FieldKey.ORIGINAL_LYRICIST, ID3v22FieldKey.ORIGINAL_LYRICIST); - tagFieldToId3.put(FieldKey.ORIGINAL_YEAR, ID3v22FieldKey.ORIGINAL_YEAR); - tagFieldToId3.put(FieldKey.QUALITY, ID3v22FieldKey.QUALITY); - tagFieldToId3.put(FieldKey.RATING, ID3v22FieldKey.RATING); - tagFieldToId3.put(FieldKey.RECORD_LABEL, ID3v22FieldKey.RECORD_LABEL); - tagFieldToId3.put(FieldKey.REMIXER, ID3v22FieldKey.REMIXER); - tagFieldToId3.put(FieldKey.SCRIPT, ID3v22FieldKey.SCRIPT); - tagFieldToId3.put(FieldKey.SUBTITLE, ID3v22FieldKey.SUBTITLE); - tagFieldToId3.put(FieldKey.TAGS, ID3v22FieldKey.TAGS); - tagFieldToId3.put(FieldKey.TEMPO, ID3v22FieldKey.TEMPO); - tagFieldToId3.put(FieldKey.TITLE, ID3v22FieldKey.TITLE); - tagFieldToId3.put(FieldKey.TITLE_SORT, ID3v22FieldKey.TITLE_SORT); - tagFieldToId3.put(FieldKey.TRACK, ID3v22FieldKey.TRACK); - tagFieldToId3.put(FieldKey.TRACK_TOTAL, ID3v22FieldKey.TRACK_TOTAL); - tagFieldToId3.put(FieldKey.URL_DISCOGS_ARTIST_SITE, ID3v22FieldKey.URL_DISCOGS_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_DISCOGS_RELEASE_SITE, ID3v22FieldKey.URL_DISCOGS_RELEASE_SITE); - tagFieldToId3.put(FieldKey.URL_LYRICS_SITE, ID3v22FieldKey.URL_LYRICS_SITE); - tagFieldToId3.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, ID3v22FieldKey.URL_OFFICIAL_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, ID3v22FieldKey.URL_OFFICIAL_RELEASE_SITE); - tagFieldToId3.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, ID3v22FieldKey.URL_WIKIPEDIA_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, ID3v22FieldKey.URL_WIKIPEDIA_RELEASE_SITE); - tagFieldToId3.put(FieldKey.YEAR, ID3v22FieldKey.YEAR); - tagFieldToId3.put(FieldKey.ENGINEER, ID3v22FieldKey.ENGINEER); - tagFieldToId3.put(FieldKey.PRODUCER, ID3v22FieldKey.PRODUCER); - tagFieldToId3.put(FieldKey.MIXER, ID3v22FieldKey.MIXER); - tagFieldToId3.put(FieldKey.DJMIXER, ID3v22FieldKey.DJMIXER); - tagFieldToId3.put(FieldKey.ARRANGER, ID3v22FieldKey.ARRANGER); - tagFieldToId3.put(FieldKey.ARTISTS, ID3v22FieldKey.ARTISTS); - tagFieldToId3.put(FieldKey.ACOUSTID_FINGERPRINT, ID3v22FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToId3.put(FieldKey.ACOUSTID_ID, ID3v22FieldKey.ACOUSTID_ID); - tagFieldToId3.put(FieldKey.COUNTRY, ID3v22FieldKey.COUNTRY); - - for (Map.Entry next : tagFieldToId3.entrySet()) { - id3ToTagField.put(next.getValue(), next.getKey()); - } - } - - public static ID3v22Frames getInstanceOf() { - if (id3v22Frames == null) { - id3v22Frames = new ID3v22Frames(); - } - return id3v22Frames; - } - - /** - * @param genericKey - * @return id3 key for generic key - */ - public ID3v22FieldKey getId3KeyFromGenericKey(FieldKey genericKey) { - return tagFieldToId3.get(genericKey); - } - - /** - * Get generic key for ID3 field key - * - * @param fieldKey - * @return - */ - public FieldKey getGenericKeyFromId3(ID3v22FieldKey fieldKey) { - return id3ToTagField.get(fieldKey); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java deleted file mode 100644 index 979d6d1..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -/** - * Orders frame Ids so that the most important frames are writtne first - */ -public class ID3v22PreferredFrameOrderComparator implements Comparator { - private static ID3v22PreferredFrameOrderComparator comparator; - private static List frameIdsInPreferredOrder = new ArrayList(); - - static { - //these are the key ones we want at the top - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_UNIQUE_FILE_ID); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TITLE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ARTIST); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ALBUM); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TORY); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_GENRE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_COMPOSER); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_CONDUCTOR); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_CONTENT_GROUP_DESC); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TRACK); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TYER); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TDAT); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TIME); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_BPM); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ISRC); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TORY); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ACCOMPANIMENT); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TITLE_REFINEMENT); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_UNSYNC_LYRICS); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_URL); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_ARTIST_WEB); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_COMMERCIAL); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_COPYRIGHT); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_FILE_WEB); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_OFFICIAL_RADIO); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_PAYMENT); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_PUBLISHERS); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_URL_COMMERCIAL); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_LYRICIST); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_MEDIA_TYPE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_IPLS); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_LANGUAGE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_PLAYLIST_DELAY); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_PLAY_COUNTER); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_POPULARIMETER); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_PUBLISHER); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_IS_COMPILATION); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ALBUM_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ALBUM_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_COMPOSER_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_COMMENT); - - //Not so bothered about these - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TRDA); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_COPYRIGHTINFO); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ENCODEDBY); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_EQUALISATION); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_EVENT_TIMING_CODES); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_FILE_TYPE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_HW_SW_SETTINGS); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_INITIAL_KEY); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_LENGTH); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_LINKED_INFO); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_TSIZ); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_MPEG_LOCATION_LOOKUP_TABLE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ORIGARTIST); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ORIG_FILENAME); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ORIG_LYRICIST); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ORIG_TITLE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_RECOMMENDED_BUFFER_SIZE); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_REMIXED); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_REVERB); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_SET); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_SYNC_LYRIC); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_SYNC_TEMPO); - - //Want this near the end because can cause problems with unsyncing - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_ATTACHED_PICTURE); - - //Itunes doesnt seem to like these, and of little use so put right at end - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_MUSIC_CD_ID); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_AUDIO_ENCRYPTION); - frameIdsInPreferredOrder.add(ID3v22Frames.FRAME_ID_V2_GENERAL_ENCAPS_OBJECT); - } - - - private ID3v22PreferredFrameOrderComparator() { - - } - - public static ID3v22PreferredFrameOrderComparator getInstanceof() { - if (comparator == null) { - comparator = new ID3v22PreferredFrameOrderComparator(); - } - return comparator; - } - - /** - * @param frameId1 - * @param frameId2 - * @return - */ - public int compare(String frameId1, String frameId2) { - int frameId1Index = frameIdsInPreferredOrder.indexOf(frameId1); - int frameId2Index = frameIdsInPreferredOrder.indexOf(frameId2); - return frameId1Index - frameId2Index; - } - - public boolean equals(Object obj) { - return obj instanceof ID3v22PreferredFrameOrderComparator; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v22Tag.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v22Tag.java deleted file mode 100644 index da4c24e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v22Tag.java +++ /dev/null @@ -1,677 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.FileConstants; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.framebody.AbstractFrameBodyTextInfo; -import org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC; -import org.jaudiotagger.tag.id3.framebody.FrameBodyPIC; -import org.jaudiotagger.tag.id3.framebody.FrameBodyTDRC; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.logging.Level; - -/** - * Represents an ID3v2.2 tag. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3v22Tag.java 1082 2013-01-06 09:38:14Z paultaylor $ - */ -public class ID3v22Tag extends AbstractID3v2Tag { - - /** - * Bit mask to indicate tag is Unsychronization - */ - public static final int MASK_V22_UNSYNCHRONIZATION = FileConstants.BIT7; - /** - * Bit mask to indicate tag is compressed, although compression is not - * actually defined in v22 so just ignored - */ - public static final int MASK_V22_COMPRESSION = FileConstants.BIT6; - public static final byte RELEASE = 2; - public static final byte MAJOR_VERSION = 2; - public static final byte REVISION = 0; - protected static final String TYPE_COMPRESSION = "compression"; - protected static final String TYPE_UNSYNCHRONISATION = "unsyncronisation"; - /** - * The tag is compressed, although no compression scheme is defined in ID3v22 - */ - protected boolean compression = false; - /** - * If set all frames in the tag uses unsynchronisation - */ - protected boolean unsynchronization = false; - - /** - * Creates a new empty ID3v2_2 tag. - */ - public ID3v22Tag() { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - } - - /** - * Copy Constructor, creates a new ID3v2_2 Tag based on another ID3v2_2 Tag - * - * @param copyObject - */ - public ID3v22Tag(ID3v22Tag copyObject) { - //This doesnt do anything. - super(copyObject); - logger.config("Creating tag from another tag of same type"); - copyPrimitives(copyObject); - copyFrames(copyObject); - } - - /** - * Constructs a new tag based upon another tag of different version/type - * - * @param mp3tag - */ - public ID3v22Tag(AbstractTag mp3tag) { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - logger.config("Creating tag from a tag of a different version"); - //Default Superclass constructor does nothing - if (mp3tag != null) { - ID3v24Tag convertedTag; - //Should use the copy constructor instead - if ((!(mp3tag instanceof ID3v23Tag)) && (mp3tag instanceof ID3v22Tag)) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - //If v2.4 can getFields variables from this - else if (mp3tag instanceof ID3v24Tag) { - convertedTag = (ID3v24Tag) mp3tag; - } - //Any tag (e.g lyrics3 and idv1.1,idv2.3 can be converted to id32.4 so do that - //to simplify things - else { - convertedTag = new ID3v24Tag(mp3tag); - } - this.setLoggingFilename(convertedTag.getLoggingFilename()); - //Set the primitive types specific to v2_2. - copyPrimitives(convertedTag); - //Set v2.2 Frames - copyFrames(convertedTag); - logger.config("Created tag from a tag of a different version"); - } - } - - /** - * Creates a new ID3v2_2 datatype. - * - * @param buffer - * @param loggingFilename - * @throws TagException - */ - public ID3v22Tag(ByteBuffer buffer, String loggingFilename) throws TagException { - setLoggingFilename(loggingFilename); - this.read(buffer); - } - - /** - * Creates a new ID3v2_2 datatype. - * - * @param buffer - * @throws TagException - * @deprecated use {@link #ID3v22Tag(ByteBuffer, String)} instead - */ - public ID3v22Tag(ByteBuffer buffer) throws TagException { - this(buffer, ""); - } - - /** - * Retrieve the Release - */ - public byte getRelease() { - return RELEASE; - } - - /** - * Retrieve the Major Version - */ - public byte getMajorVersion() { - return MAJOR_VERSION; - } - - /** - * Retrieve the Revision - */ - public byte getRevision() { - return REVISION; - } - - /** - * Copy primitives applicable to v2.2 - */ - protected void copyPrimitives(AbstractID3v2Tag copyObj) { - logger.config("Copying primitives"); - super.copyPrimitives(copyObj); - - //Set the primitive types specific to v2_2. - if (copyObj instanceof ID3v22Tag) { - ID3v22Tag copyObject = (ID3v22Tag) copyObj; - this.compression = copyObject.compression; - this.unsynchronization = copyObject.unsynchronization; - } else if (copyObj instanceof ID3v23Tag) { - ID3v23Tag copyObject = (ID3v23Tag) copyObj; - this.compression = copyObject.compression; - this.unsynchronization = copyObject.unsynchronization; - } else if (copyObj instanceof ID3v24Tag) { - ID3v24Tag copyObject = (ID3v24Tag) copyObj; - this.compression = false; - this.unsynchronization = copyObject.unsynchronization; - } - } - - /** - * @return an indentifier of the tag type - */ - public String getIdentifier() { - return "ID3v2_2.20"; - } - - /** - * Return frame size based upon the sizes of the frames rather than the size - * including padding recorded in the tag header - * - * @return size - */ - public int getSize() { - int size = TAG_HEADER_LENGTH; - size += super.getSize(); - return size; - } - - - /** - * @param obj - * @return equality - */ - public boolean equals(Object obj) { - if (!(obj instanceof ID3v22Tag)) { - return false; - } - ID3v22Tag object = (ID3v22Tag) obj; - if (this.compression != object.compression) { - return false; - } - return this.unsynchronization == object.unsynchronization && super.equals(obj); - } - - - protected void addFrame(AbstractID3v2Frame frame) { - try { - //Special case to handle TDRC frame from V24 that needs breaking up into separate frame in V23 - if ((frame.getIdentifier().equals(ID3v24Frames.FRAME_ID_YEAR)) && (frame.getBody() instanceof FrameBodyTDRC)) { - translateFrame(frame); - } else if (frame instanceof ID3v22Frame) { - copyFrameIntoMap(frame.getIdentifier(), frame); - } else { - ID3v22Frame newFrame = new ID3v22Frame(frame); - copyFrameIntoMap(newFrame.getIdentifier(), newFrame); - } - } catch (InvalidFrameException ife) { - logger.log(Level.SEVERE, "Unable to convert frame:" + frame.getIdentifier()); - } - } - - - /** - * Read tag Header Flags - * - * @param byteBuffer - * @throws TagException - */ - private void readHeaderFlags(ByteBuffer byteBuffer) throws TagException { - //Flags - byte flags = byteBuffer.get(); - unsynchronization = (flags & MASK_V22_UNSYNCHRONIZATION) != 0; - compression = (flags & MASK_V22_COMPRESSION) != 0; - - if (unsynchronization) { - logger.config(ErrorMessage.ID3_TAG_UNSYNCHRONIZED.getMsg(getLoggingFilename())); - } - - if (compression) { - logger.config(ErrorMessage.ID3_TAG_COMPRESSED.getMsg(getLoggingFilename())); - } - - //Not allowable/Unknown Flags - if ((flags & FileConstants.BIT5) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT5)); - } - if ((flags & FileConstants.BIT4) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT4)); - } - if ((flags & FileConstants.BIT3) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT3)); - } - if ((flags & FileConstants.BIT2) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT2)); - } - if ((flags & FileConstants.BIT1) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT1)); - } - if ((flags & FileConstants.BIT0) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT3)); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void read(ByteBuffer byteBuffer) throws TagException { - int size; - if (!seek(byteBuffer)) { - throw new TagNotFoundException("ID3v2.20 tag not found"); - } - logger.config(getLoggingFilename() + ":" + "Reading tag from file"); - - //Read the flags - readHeaderFlags(byteBuffer); - - // Read the size - size = ID3SyncSafeInteger.bufferToValue(byteBuffer); - - //Slice Buffer, so position markers tally with size (i.e do not include tagheader) - ByteBuffer bufferWithoutHeader = byteBuffer.slice(); - - //We need to synchronize the buffer - if (unsynchronization) { - bufferWithoutHeader = ID3Unsynchronization.synchronize(bufferWithoutHeader); - } - readFrames(bufferWithoutHeader, size); - logger.config(getLoggingFilename() + ":" + "Loaded Frames,there are:" + frameMap.keySet().size()); - } - - /** - * Read frames from tag - * - * @param byteBuffer - * @param size - */ - protected void readFrames(ByteBuffer byteBuffer, int size) { - //Now start looking for frames - ID3v22Frame next; - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - //Read the size from the Tag Header - this.fileReadSize = size; - logger.finest(getLoggingFilename() + ":" + "Start of frame body at:" + byteBuffer.position() + ",frames sizes and padding is:" + size); - /* todo not done yet. Read the first Frame, there seems to be quite a - ** common case of extra data being between the tag header and the first - ** frame so should we allow for this when reading first frame, but not subsequent frames - */ - // Read the frames until got to upto the size as specified in header - while (byteBuffer.position() < size) { - try { - //Read Frame - logger.finest(getLoggingFilename() + ":" + "looking for next frame at:" + byteBuffer.position()); - next = new ID3v22Frame(byteBuffer, getLoggingFilename()); - String id = next.getIdentifier(); - loadFrameIntoMap(id, next); - } - //Found Padding, no more frames - catch (PaddingException ex) { - logger.config(getLoggingFilename() + ":Found padding starting at:" + byteBuffer.position()); - break; - } - //Found Empty Frame - catch (EmptyFrameException ex) { - logger.warning(getLoggingFilename() + ":" + "Empty Frame:" + ex.getMessage()); - this.emptyFrameBytes += ID3v22Frame.FRAME_HEADER_SIZE; - } catch (InvalidFrameIdentifierException ifie) { - logger.config(getLoggingFilename() + ":" + "Invalid Frame Identifier:" + ifie.getMessage()); - this.invalidFrames++; - //Dont try and find any more frames - break; - } - //Problem trying to find frame - catch (InvalidFrameException ife) { - logger.warning(getLoggingFilename() + ":" + "Invalid Frame:" + ife.getMessage()); - this.invalidFrames++; - //Dont try and find any more frames - break; - } - //Failed reading frame but may just have invalid data but correct length so lets carry on - //in case we can read the next frame - catch (InvalidDataTypeException idete) { - logger.warning(getLoggingFilename() + ":Corrupt Frame:" + idete.getMessage()); - this.invalidFrames++; - continue; - } - } - } - - /** - * This is used when we need to translate a single frame into multiple frames, - * currently required for TDRC frames. - * - * @param frame - */ - //TODO will overwrite any existing TYER or TIME frame, do we ever want multiples of these - protected void translateFrame(AbstractID3v2Frame frame) { - FrameBodyTDRC tmpBody = (FrameBodyTDRC) frame.getBody(); - ID3v22Frame newFrame; - if (tmpBody.getYear().length() != 0) { - //Create Year frame (v2.2 id,but uses v2.3 body) - newFrame = new ID3v22Frame(ID3v22Frames.FRAME_ID_V2_TYER); - ((AbstractFrameBodyTextInfo) newFrame.getBody()).setText(tmpBody.getYear()); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (tmpBody.getTime().length() != 0) { - //Create Time frame (v2.2 id,but uses v2.3 body) - newFrame = new ID3v22Frame(ID3v22Frames.FRAME_ID_V2_TIME); - ((AbstractFrameBodyTextInfo) newFrame.getBody()).setText(tmpBody.getTime()); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - } - - - /** - * Write the ID3 header to the ByteBuffer. - *

    - * - * @param padding - * @param size - * @return ByteBuffer - * @throws IOException - */ - private ByteBuffer writeHeaderToBuffer(int padding, int size) throws IOException { - compression = false; - - //Create Header Buffer - ByteBuffer headerBuffer = ByteBuffer.allocate(TAG_HEADER_LENGTH); - - //TAGID - headerBuffer.put(TAG_ID); - //Major Version - headerBuffer.put(getMajorVersion()); - //Minor Version - headerBuffer.put(getRevision()); - - //Flags - byte flags = (byte) 0; - if (unsynchronization) { - flags |= (byte) MASK_V22_UNSYNCHRONIZATION; - } - if (compression) { - flags |= (byte) MASK_V22_COMPRESSION; - } - - headerBuffer.put(flags); - - //Size As Recorded in Header, don't include the main header length - headerBuffer.put(ID3SyncSafeInteger.valueToBuffer(padding + size)); - headerBuffer.flip(); - return headerBuffer; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(File file, long audioStartLocation) throws IOException { - setLoggingFilename(file.getName()); - logger.config("Writing tag to file:" + getLoggingFilename()); - - // Write Body Buffer - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - - // Unsynchronize if option enabled and unsync required - unsynchronization = TagOptionSingleton.getInstance().isUnsyncTags() && ID3Unsynchronization.requiresUnsynchronization(bodyByteBuffer); - if (isUnsynchronization()) { - bodyByteBuffer = ID3Unsynchronization.unsynchronize(bodyByteBuffer); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizeafterunsynchronisation:" + bodyByteBuffer.length); - } - - int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) audioStartLocation); - int padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH); - logger.config(getLoggingFilename() + ":Current audiostart:" + audioStartLocation); - logger.config(getLoggingFilename() + ":Size including padding:" + sizeIncPadding); - logger.config(getLoggingFilename() + ":Padding:" + padding); - - ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length); - writeBufferToFile(file, headerBuffer, bodyByteBuffer, padding, sizeIncPadding, audioStartLocation); - } - - - /** - * {@inheritDoc} - */ - @Override - public void write(WritableByteChannel channel) throws IOException { - logger.config(getLoggingFilename() + ":Writing tag to channel"); - - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizebeforeunsynchronisation:" + bodyByteBuffer.length); - - //Unsynchronize if option enabled and unsync required - unsynchronization = TagOptionSingleton.getInstance().isUnsyncTags() && ID3Unsynchronization.requiresUnsynchronization(bodyByteBuffer); - if (isUnsynchronization()) { - bodyByteBuffer = ID3Unsynchronization.unsynchronize(bodyByteBuffer); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizeafterunsynchronisation:" + bodyByteBuffer.length); - } - ByteBuffer headerBuffer = writeHeaderToBuffer(0, bodyByteBuffer.length); - - channel.write(headerBuffer); - channel.write(ByteBuffer.wrap(bodyByteBuffer)); - } - - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier()); - - super.createStructureHeader(); - - //Header - MP3File.getStructureFormatter().openHeadingElement(TYPE_HEADER, ""); - MP3File.getStructureFormatter().addElement(TYPE_COMPRESSION, this.compression); - MP3File.getStructureFormatter().addElement(TYPE_UNSYNCHRONISATION, this.unsynchronization); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_HEADER); - //Body - super.createStructureBody(); - - MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG); - } - - /** - * @return is tag unsynchronized - */ - public boolean isUnsynchronization() { - return unsynchronization; - } - - /** - * @return is tag compressed - */ - public boolean isCompression() { - return compression; - } - - /** - * Create Frame - * - * @param id frameid - * @return - */ - public ID3v22Frame createFrame(String id) { - return new ID3v22Frame(id); - } - - - /** - * Create Frame for Id3 Key - *

    - * Only textual data supported at the moment, should only be used with frames that - * support a simple string argument. - * - * @param id3Key - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public TagField createField(ID3v22FieldKey id3Key, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (id3Key == null) { - throw new KeyNotFoundException(); - } - return super.doCreateTagField(new FrameAndSubId(id3Key.getFrameId(), id3Key.getSubId()), value); - } - - /** - * Retrieve the first value that exists for this id3v22key - * - * @param id3v22FieldKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public String getFirst(ID3v22FieldKey id3v22FieldKey) throws KeyNotFoundException { - if (id3v22FieldKey == null) { - throw new KeyNotFoundException(); - } - - FieldKey genericKey = ID3v22Frames.getInstanceOf().getGenericKeyFromId3(id3v22FieldKey); - if (genericKey != null) { - return super.getFirst(genericKey); - } else { - FrameAndSubId frameAndSubId = new FrameAndSubId(id3v22FieldKey.getFrameId(), id3v22FieldKey.getSubId()); - return super.doGetValueAtIndex(frameAndSubId, 0); - } - } - - /** - * Delete fields with this id3v22FieldKey - * - * @param id3v22FieldKey - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(ID3v22FieldKey id3v22FieldKey) throws KeyNotFoundException { - if (id3v22FieldKey == null) { - throw new KeyNotFoundException(); - } - super.doDeleteTagField(new FrameAndSubId(id3v22FieldKey.getFrameId(), id3v22FieldKey.getSubId())); - } - - /** - * Delete fields with this (frame) id - * - * @param id - */ - public void deleteField(String id) { - super.doDeleteTagField(new FrameAndSubId(id, null)); - } - - protected FrameAndSubId getFrameAndSubIdFromGenericKey(FieldKey genericKey) { - if (genericKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - ID3v22FieldKey id3v22FieldKey = ID3v22Frames.getInstanceOf().getId3KeyFromGenericKey(genericKey); - if (id3v22FieldKey == null) { - throw new KeyNotFoundException(genericKey.name()); - } - return new FrameAndSubId(id3v22FieldKey.getFrameId(), id3v22FieldKey.getSubId()); - } - - protected ID3Frames getID3Frames() { - return ID3v22Frames.getInstanceOf(); - } - - /** - * @return comparator used to order frames in preffrred order for writing to file - * so that most important frames are written first. - */ - public Comparator getPreferredFrameOrderComparator() { - return ID3v22PreferredFrameOrderComparator.getInstanceof(); - } - - /** - * {@inheritDoc} - */ - public List getArtworkList() { - List coverartList = getFields(FieldKey.COVER_ART); - List artworkList = new ArrayList(coverartList.size()); - - for (TagField next : coverartList) { - FrameBodyPIC coverArt = (FrameBodyPIC) ((AbstractID3v2Frame) next).getBody(); - Artwork artwork = ArtworkFactory.getNew(); - artwork.setMimeType(ImageFormats.getMimeTypeForFormat(coverArt.getFormatType())); - artwork.setPictureType(coverArt.getPictureType()); - if (coverArt.isImageUrl()) { - artwork.setLinked(true); - artwork.setImageUrl(coverArt.getImageUrl()); - } else { - artwork.setBinaryData(coverArt.getImageData()); - } - artworkList.add(artwork); - } - return artworkList; - } - - /** - * {@inheritDoc} - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - FrameBodyPIC body = (FrameBodyPIC) frame.getBody(); - if (!artwork.isLinked()) { - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, artwork.getBinaryData()); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, artwork.getPictureType()); - body.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, ImageFormats.getFormatForMimeType(artwork.getMimeType())); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } else { - try { - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, artwork.getImageUrl().getBytes("ISO-8859-1")); - } catch (UnsupportedEncodingException uoe) { - throw new RuntimeException(uoe.getMessage()); - } - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, artwork.getPictureType()); - body.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, FrameBodyAPIC.IMAGE_IS_URL); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } - } - - public TagField createArtworkField(byte[] data, String mimeType) { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - FrameBodyPIC body = (FrameBodyPIC) frame.getBody(); - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, data); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID); - body.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, ImageFormats.getFormatForMimeType(mimeType)); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v23FieldKey.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v23FieldKey.java deleted file mode 100644 index 81fff8f..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v23FieldKey.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.id3.framebody.*; - -/** - * List of known id3v23 metadata fields - *

    - *

    These provide a mapping from the generic key to the underlying ID3v23frames. For example most of the Musicbrainz - * fields are implemented using a User Defined Text Info Frame, but with a different description key, so this - * enum provides the link between the two. - */ -public enum ID3v23FieldKey { - ALBUM(ID3v23Frames.FRAME_ID_V3_ALBUM, Id3FieldType.TEXT), - ALBUM_ARTIST(ID3v23Frames.FRAME_ID_V3_ACCOMPANIMENT, Id3FieldType.TEXT), - ALBUM_ARTIST_SORT(ID3v23Frames.FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - ALBUM_SORT(ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - AMAZON_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.AMAZON_ASIN, Id3FieldType.TEXT), - ARTIST(ID3v23Frames.FRAME_ID_V3_ARTIST, Id3FieldType.TEXT), - ARTIST_SORT(ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - BARCODE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.BARCODE, Id3FieldType.TEXT), - BPM(ID3v23Frames.FRAME_ID_V3_BPM, Id3FieldType.TEXT), - CATALOG_NO(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.CATALOG_NO, Id3FieldType.TEXT), - COMMENT(ID3v23Frames.FRAME_ID_V3_COMMENT, Id3FieldType.TEXT), - COMPOSER(ID3v23Frames.FRAME_ID_V3_COMPOSER, Id3FieldType.TEXT), - COMPOSER_SORT(ID3v23Frames.FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - CONDUCTOR(ID3v23Frames.FRAME_ID_V3_CONDUCTOR, Id3FieldType.TEXT), - COVER_ART(ID3v23Frames.FRAME_ID_V3_ATTACHED_PICTURE, Id3FieldType.BINARY), - CUSTOM1(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_CUSTOM1, Id3FieldType.TEXT), - CUSTOM2(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_CUSTOM2, Id3FieldType.TEXT), - CUSTOM3(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_CUSTOM3, Id3FieldType.TEXT), - CUSTOM4(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_CUSTOM4, Id3FieldType.TEXT), - CUSTOM5(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_CUSTOM5, Id3FieldType.TEXT), - DISC_NO(ID3v23Frames.FRAME_ID_V3_SET, Id3FieldType.TEXT), - DISC_SUBTITLE(ID3v23Frames.FRAME_ID_V3_SET_SUBTITLE, Id3FieldType.TEXT), - DISC_TOTAL(ID3v23Frames.FRAME_ID_V3_SET, Id3FieldType.TEXT), - ENCODER(ID3v23Frames.FRAME_ID_V3_ENCODEDBY, Id3FieldType.TEXT), - FBPM(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.FBPM, Id3FieldType.TEXT), - GENRE(ID3v23Frames.FRAME_ID_V3_GENRE, Id3FieldType.TEXT), - GROUPING(ID3v23Frames.FRAME_ID_V3_CONTENT_GROUP_DESC, Id3FieldType.TEXT), - ISRC(ID3v23Frames.FRAME_ID_V3_ISRC, Id3FieldType.TEXT), - IS_COMPILATION(ID3v23Frames.FRAME_ID_V3_IS_COMPILATION, Id3FieldType.TEXT), - KEY(ID3v23Frames.FRAME_ID_V3_INITIAL_KEY, Id3FieldType.TEXT), - LANGUAGE(ID3v23Frames.FRAME_ID_V3_LANGUAGE, Id3FieldType.TEXT), - LYRICIST(ID3v23Frames.FRAME_ID_V3_LYRICIST, Id3FieldType.TEXT), - LYRICS(ID3v23Frames.FRAME_ID_V3_UNSYNC_LYRICS, Id3FieldType.TEXT), - MEDIA(ID3v23Frames.FRAME_ID_V3_MEDIA_TYPE, Id3FieldType.TEXT), - MOOD(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD, Id3FieldType.TEXT), - MUSICBRAINZ_ARTISTID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ARTISTID, Id3FieldType.TEXT), - MUSICBRAINZ_DISC_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_DISCID, Id3FieldType.TEXT), - MUSICBRAINZ_ORIGINAL_RELEASEID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ORIGINAL_ALBUMID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASEARTISTID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_ARTISTID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASEID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUMID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_COUNTRY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_COUNTRY, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_GROUP_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_RELEASE_GROUPID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_STATUS(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_STATUS, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_TYPE, Id3FieldType.TEXT), - MUSICBRAINZ_TRACK_ID(ID3v23Frames.FRAME_ID_V3_UNIQUE_FILE_ID, FrameBodyUFID.UFID_MUSICBRAINZ, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORKID, Id3FieldType.TEXT), - MUSICIP_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICIP_ID, Id3FieldType.TEXT), - OCCASION(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_OCCASION, Id3FieldType.TEXT), - ORIGINAL_ALBUM(ID3v23Frames.FRAME_ID_V3_ORIG_TITLE, Id3FieldType.TEXT), - ORIGINAL_ARTIST(ID3v23Frames.FRAME_ID_V3_ORIGARTIST, Id3FieldType.TEXT), - ORIGINAL_LYRICIST(ID3v23Frames.FRAME_ID_V3_ORIG_LYRICIST, Id3FieldType.TEXT), - ORIGINAL_YEAR(ID3v23Frames.FRAME_ID_V3_TORY, Id3FieldType.TEXT), - QUALITY(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_QUALITY, Id3FieldType.TEXT), - RATING(ID3v23Frames.FRAME_ID_V3_POPULARIMETER, Id3FieldType.TEXT), - RECORD_LABEL(ID3v23Frames.FRAME_ID_V3_PUBLISHER, Id3FieldType.TEXT), - REMIXER(ID3v23Frames.FRAME_ID_V3_REMIXED, Id3FieldType.TEXT), - SCRIPT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.SCRIPT, Id3FieldType.TEXT), - SUBTITLE(ID3v23Frames.FRAME_ID_V3_TITLE_REFINEMENT, Id3FieldType.TEXT), - TAGS(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.TAGS, Id3FieldType.TEXT), - TEMPO(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_TEMPO, Id3FieldType.TEXT), - TITLE(ID3v23Frames.FRAME_ID_V3_TITLE, Id3FieldType.TEXT), - TITLE_SORT(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - TRACK(ID3v23Frames.FRAME_ID_V3_TRACK, Id3FieldType.TEXT), - TRACK_TOTAL(ID3v23Frames.FRAME_ID_V3_TRACK, Id3FieldType.TEXT), - URL_DISCOGS_ARTIST_SITE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL, FrameBodyWXXX.URL_DISCOGS_ARTIST_SITE, Id3FieldType.TEXT), - URL_DISCOGS_RELEASE_SITE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL, FrameBodyWXXX.URL_DISCOGS_RELEASE_SITE, Id3FieldType.TEXT), - URL_LYRICS_SITE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL, FrameBodyWXXX.URL_LYRICS_SITE, Id3FieldType.TEXT), - URL_OFFICIAL_ARTIST_SITE(ID3v23Frames.FRAME_ID_V3_URL_ARTIST_WEB, Id3FieldType.TEXT), - URL_OFFICIAL_RELEASE_SITE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL, FrameBodyWXXX.URL_OFFICIAL_RELEASE_SITE, Id3FieldType.TEXT), - URL_WIKIPEDIA_ARTIST_SITE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL, FrameBodyWXXX.URL_WIKIPEDIA_ARTIST_SITE, Id3FieldType.TEXT), - URL_WIKIPEDIA_RELEASE_SITE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL, FrameBodyWXXX.URL_WIKIPEDIA_RELEASE_SITE, Id3FieldType.TEXT), - YEAR(ID3v23Frames.FRAME_ID_V3_TYER, Id3FieldType.TEXT), - ENGINEER(ID3v23Frames.FRAME_ID_V3_IPLS, FrameBodyTIPL.ENGINEER, Id3FieldType.TEXT), - PRODUCER(ID3v23Frames.FRAME_ID_V3_IPLS, FrameBodyTIPL.PRODUCER, Id3FieldType.TEXT), - MIXER(ID3v23Frames.FRAME_ID_V3_IPLS, FrameBodyTIPL.MIXER, Id3FieldType.TEXT), - DJMIXER(ID3v23Frames.FRAME_ID_V3_IPLS, FrameBodyTIPL.DJMIXER, Id3FieldType.TEXT), - ARRANGER(ID3v23Frames.FRAME_ID_V3_IPLS, FrameBodyTIPL.ARRANGER, Id3FieldType.TEXT), - ARTISTS(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS, Id3FieldType.TEXT), - ACOUSTID_FINGERPRINT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ACOUSTID_FINGERPRINT, Id3FieldType.TEXT), - ACOUSTID_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ACOUSTID_ID, Id3FieldType.TEXT), - COUNTRY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.COUNTRY, Id3FieldType.TEXT),; - private String fieldName; - - private String frameId; - private String subId; - private Id3FieldType fieldType; - - /** - * For usual metadata fields that use a data field - * - * @param frameId the frame that will be used - * @param fieldType of data atom - */ - ID3v23FieldKey(String frameId, Id3FieldType fieldType) { - this.frameId = frameId; - this.fieldType = fieldType; - - this.fieldName = frameId; - } - - /** - * @param frameId the frame that will be used - * @param subId the additional key required within the frame to uniquely identify this key - * @param fieldType - */ - ID3v23FieldKey(String frameId, String subId, Id3FieldType fieldType) { - this.frameId = frameId; - this.subId = subId; - this.fieldType = fieldType; - - this.fieldName = frameId + ":" + subId; - } - - /** - * @return fieldtype - */ - public Id3FieldType getFieldType() { - return fieldType; - } - - /** - * This is the frame identifier used to write the field - * - * @return - */ - public String getFrameId() { - return frameId; - } - - /** - * This is the subfield used within the frame for this type of field - * - * @return subId - */ - public String getSubId() { - return subId; - } - - /** - * This is the value of the key that can uniquely identifer a key type - * - * @return - */ - public String getFieldName() { - return fieldName; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v23Frame.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v23Frame.java deleted file mode 100644 index 40dfdba..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v23Frame.java +++ /dev/null @@ -1,722 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.FileConstants; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.Hex; -import org.jaudiotagger.tag.EmptyFrameException; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.InvalidFrameException; -import org.jaudiotagger.tag.InvalidFrameIdentifierException; -import org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import org.jaudiotagger.tag.id3.framebody.FrameBodyDeprecated; -import org.jaudiotagger.tag.id3.framebody.FrameBodyUnsupported; -import org.jaudiotagger.tag.id3.framebody.ID3v23FrameBody; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Represents an ID3v2.3 frame. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3v23Frame.java 976 2011-06-08 10:05:34Z paultaylor $ - */ -public class ID3v23Frame extends AbstractID3v2Frame { - protected static final int FRAME_ID_SIZE = 4; - protected static final int FRAME_FLAGS_SIZE = 2; - protected static final int FRAME_SIZE_SIZE = 4; - protected static final int FRAME_COMPRESSION_UNCOMPRESSED_SIZE = 4; - protected static final int FRAME_ENCRYPTION_INDICATOR_SIZE = 1; - protected static final int FRAME_GROUPING_INDICATOR_SIZE = 1; - protected static final int FRAME_HEADER_SIZE = FRAME_ID_SIZE + FRAME_SIZE_SIZE + FRAME_FLAGS_SIZE; - private static Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{3}"); - /** - * If the frame is encrypted then the encryption method is stored in this byte - */ - private int encryptionMethod; - - /** - * If the frame belongs in a group with other frames then the group identifier byte is stored - */ - private int groupIdentifier; - - /** - * Creates a new ID3v23 Frame - */ - public ID3v23Frame() { - } - - /** - * Creates a new ID3v23 Frame of type identifier. - *

    - *

    An empty body of the correct type will be automatically created. - * This constructor should be used when wish to create a new - * frame from scratch using user data. - * - * @param identifier - */ - public ID3v23Frame(String identifier) { - super(identifier); - statusFlags = new StatusFlags(); - encodingFlags = new EncodingFlags(); - } - - /** - * Copy Constructor - *

    - * Creates a new v23 frame based on another v23 frame - * - * @param frame - */ - public ID3v23Frame(ID3v23Frame frame) { - super(frame); - statusFlags = new StatusFlags(frame.getStatusFlags().getOriginalFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } - - /** - * Creates a new ID3v23Frame based on another frame of a different version. - * - * @param frame - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - public ID3v23Frame(AbstractID3v2Frame frame) throws InvalidFrameException { - logger.finer("Creating frame from a frame of a different version"); - if (frame instanceof ID3v23Frame) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - if (frame instanceof ID3v24Frame) { - statusFlags = new StatusFlags((ID3v24Frame.StatusFlags) frame.getStatusFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } - - if (frame instanceof ID3v24Frame) { - //Unknown Frame e.g NCON, also protects when known id but has unsupported frame body - if (frame.getBody() instanceof FrameBodyUnsupported) { - this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frame.getIdentifier(); - logger.config("UNKNOWN:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - return; - } - // Deprecated frame for v24 - else if (frame.getBody() instanceof FrameBodyDeprecated) { - //Was it valid for this tag version, if so try and reconstruct - if (ID3Tags.isID3v23FrameIdentifier(frame.getIdentifier())) { - this.frameBody = ((FrameBodyDeprecated) frame.getBody()).getOriginalFrameBody(); - this.frameBody.setHeader(this); - this.frameBody.setTextEncoding(ID3TextEncodingConversion.getTextEncoding(this, this.frameBody.getTextEncoding())); - identifier = frame.getIdentifier(); - logger.config("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - } - //or was it still deprecated, if so leave as is - else { - this.frameBody = new FrameBodyDeprecated((FrameBodyDeprecated) frame.getBody()); - this.frameBody.setHeader(this); - this.frameBody.setTextEncoding(ID3TextEncodingConversion.getTextEncoding(this, this.frameBody.getTextEncoding())); - - identifier = frame.getIdentifier(); - logger.config("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - return; - } - } else if (ID3Tags.isID3v24FrameIdentifier(frame.getIdentifier())) { - logger.finer("isID3v24FrameIdentifier"); - //Version between v4 and v3 - identifier = ID3Tags.convertFrameID24To23(frame.getIdentifier()); - if (identifier != null) { - logger.finer("V4:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = (AbstractTagFrameBody) ID3Tags.copyObject(frame.getBody()); - this.frameBody.setHeader(this); - this.frameBody.setTextEncoding(ID3TextEncodingConversion.getTextEncoding(this, this.frameBody.getTextEncoding())); - return; - } else { - //Is it a known v4 frame which needs forcing to v3 frame e.g. TDRC - TYER,TDAT - identifier = ID3Tags.forceFrameID24To23(frame.getIdentifier()); - if (identifier != null) { - logger.finer("V4:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody()); - this.frameBody.setHeader(this); - this.frameBody.setTextEncoding(ID3TextEncodingConversion.getTextEncoding(this, this.frameBody.getTextEncoding())); - return; - } - //It is a v24 frame that is not known and cannot be forced in v23 e.g TDRL,in which case - //we convert to a frameBody unsupported by writing contents as a byte array and feeding - //it into FrameBodyUnsupported - else { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ((AbstractID3v2FrameBody) frame.getBody()).write(baos); - - identifier = frame.getIdentifier(); - this.frameBody = new FrameBodyUnsupported(identifier, baos.toByteArray()); - this.frameBody.setHeader(this); - logger.finer("V4:Orig id is:" + frame.getIdentifier() + ":New Id Unsupported is:" + identifier); - return; - } - } - } - // Unable to find a suitable frameBody, this should not happen - else { - logger.severe("Orig id is:" + frame.getIdentifier() + "Unable to create Frame Body"); - throw new InvalidFrameException("Orig id is:" + frame.getIdentifier() + "Unable to create Frame Body"); - } - } else if (frame instanceof ID3v22Frame) { - if (ID3Tags.isID3v22FrameIdentifier(frame.getIdentifier())) { - identifier = ID3Tags.convertFrameID22To23(frame.getIdentifier()); - if (identifier != null) { - logger.config("V3:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = (AbstractTagFrameBody) ID3Tags.copyObject(frame.getBody()); - this.frameBody.setHeader(this); - return; - } - //Is it a known v2 frame which needs forcing to v23 frame e.g PIC - APIC - else if (ID3Tags.isID3v22FrameIdentifier(frame.getIdentifier())) { - //Force v2 to v3 - identifier = ID3Tags.forceFrameID22To23(frame.getIdentifier()); - if (identifier != null) { - logger.config("V22Orig id is:" + frame.getIdentifier() + "New id is:" + identifier); - this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody()); - this.frameBody.setHeader(this); - return; - } - //No mechanism exists to convert it to a v23 frame - else { - this.frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frame.getIdentifier(); - logger.config("Deprecated:V22:orig id id is:" + frame.getIdentifier() + ":New id is:" + identifier); - return; - } - } - } - // Unknown Frame e.g NCON - else { - this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frame.getIdentifier(); - logger.config("UNKNOWN:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - return; - } - } - - logger.warning("Frame is unknown version:" + frame.getClass()); - } - - /** - * Creates a new ID3v23Frame dataType by reading from byteBuffer. - * - * @param byteBuffer to read from - * @param loggingFilename - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - public ID3v23Frame(ByteBuffer byteBuffer, String loggingFilename) throws InvalidFrameException, InvalidDataTypeException { - setLoggingFilename(loggingFilename); - read(byteBuffer); - } - - /** - * Creates a new ID3v23Frame dataType by reading from byteBuffer. - * - * @param byteBuffer to read from - * @throws org.jaudiotagger.tag.InvalidFrameException - * @deprecated use {@link #ID3v23Frame(ByteBuffer, String)} instead - */ - public ID3v23Frame(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException { - this(byteBuffer, ""); - } - - protected int getFrameIdSize() { - return FRAME_ID_SIZE; - } - - protected int getFrameSizeSize() { - return FRAME_SIZE_SIZE; - } - - protected int getFrameHeaderSize() { - return FRAME_HEADER_SIZE; - } - - /** - * Return size of frame - * - * @return int frame size - */ - public int getSize() { - return frameBody.getSize() + ID3v23Frame.FRAME_HEADER_SIZE; - } - - /** - * Compare for equality - * To be deemed equal obj must be a IDv23Frame with the same identifier - * and the same flags. - * containing the same body,dataType list ectera. - * equals() method is made up from all the various components - * - * @param obj - * @return if true if this object is equivalent to obj - */ - public boolean equals(Object obj) { - if (this == obj) return true; - - if (!(obj instanceof ID3v23Frame)) { - return false; - } - ID3v23Frame that = (ID3v23Frame) obj; - - - return - EqualsUtil.areEqual(this.statusFlags, that.statusFlags) && - EqualsUtil.areEqual(this.encodingFlags, that.encodingFlags) && - super.equals(that); - - } - - - /** - * Read the frame from a byteBuffer - * - * @param byteBuffer buffer to read from - */ - public void read(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException { - String identifier = readIdentifier(byteBuffer); - if (!isValidID3v2FrameIdentifier(identifier)) { - logger.config(getLoggingFilename() + ":Invalid identifier:" + identifier); - byteBuffer.position(byteBuffer.position() - (getFrameIdSize() - 1)); - throw new InvalidFrameIdentifierException(getLoggingFilename() + ":" + identifier + ":is not a valid ID3v2.30 frame"); - } - //Read the size field (as Big Endian Int - byte buffers always initialised to Big Endian order) - frameSize = byteBuffer.getInt(); - if (frameSize < 0) { - logger.warning(getLoggingFilename() + ":Invalid Frame Size:" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame"); - } else if (frameSize == 0) { - logger.warning(getLoggingFilename() + ":Empty Frame Size:" + identifier); - //We don't process this frame or add to frameMap because contains no useful information - //Skip the two flag bytes so in correct position for subsequent frames - byteBuffer.get(); - byteBuffer.get(); - throw new EmptyFrameException(identifier + " is empty frame"); - } else if (frameSize > byteBuffer.remaining()) { - logger.warning(getLoggingFilename() + ":Invalid Frame size of " + frameSize + " larger than size of" + byteBuffer.remaining() + " before mp3 audio:" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame"); - } - - //Read the flag bytes - statusFlags = new StatusFlags(byteBuffer.get()); - encodingFlags = new EncodingFlags(byteBuffer.get()); - String id; - - //If this identifier is a valid v24 identifier or easily converted to v24 - id = ID3Tags.convertFrameID23To24(identifier); - - // Cant easily be converted to v24 but is it a valid v23 identifier - if (id == null) { - // It is a valid v23 identifier so should be able to find a - // frame body for it. - if (ID3Tags.isID3v23FrameIdentifier(identifier)) { - id = identifier; - } - // Unknown so will be created as FrameBodyUnsupported - else { - id = UNSUPPORTED_ID; - } - } - logger.fine(getLoggingFilename() + ":Identifier was:" + identifier + " reading using:" + id + "with frame size:" + frameSize); - - //Read extra bits appended to frame header for various encodings - //These are not included in header size but are included in frame size but won't be read when we actually - //try to read the frame body data - int extraHeaderBytesCount = 0; - int decompressedFrameSize = -1; - if (((EncodingFlags) encodingFlags).isCompression()) { - //Read the Decompressed Size - decompressedFrameSize = byteBuffer.getInt(); - extraHeaderBytesCount = FRAME_COMPRESSION_UNCOMPRESSED_SIZE; - logger.fine(getLoggingFilename() + ":Decompressed frame size is:" + decompressedFrameSize); - } - - if (((EncodingFlags) encodingFlags).isEncryption()) { - //Consume the encryption byte - extraHeaderBytesCount += FRAME_ENCRYPTION_INDICATOR_SIZE; - encryptionMethod = byteBuffer.get(); - } - - if (((EncodingFlags) encodingFlags).isGrouping()) { - //Read the Grouping byte, but do nothing with it - extraHeaderBytesCount += FRAME_GROUPING_INDICATOR_SIZE; - groupIdentifier = byteBuffer.get(); - } - - //Work out the real size of the frameBody data - int realFrameSize = frameSize - extraHeaderBytesCount; - - ByteBuffer frameBodyBuffer; - //Read the body data - try { - if (((EncodingFlags) encodingFlags).isCompression()) { - frameBodyBuffer = ID3Compression.uncompress(identifier, getLoggingFilename(), byteBuffer, decompressedFrameSize, realFrameSize); - frameBody = readBody(id, frameBodyBuffer, decompressedFrameSize); - } else if (((EncodingFlags) encodingFlags).isEncryption()) { - frameBodyBuffer = byteBuffer.slice(); - frameBodyBuffer.limit(realFrameSize); - frameBody = readEncryptedBody(identifier, byteBuffer, frameSize); - } else { - //Create Buffer that only contains the body of this frame rather than the remainder of tag - frameBodyBuffer = byteBuffer.slice(); - frameBodyBuffer.limit(realFrameSize); - frameBody = readBody(id, frameBodyBuffer, realFrameSize); - } - //TODO code seems to assume that if the frame created is not a v23FrameBody - //it should be deprecated, but what about if somehow a V24Frame has been put into a V23 Tag, shouldn't - //it then be created as FrameBodyUnsupported - if (!(frameBody instanceof ID3v23FrameBody)) { - logger.config(getLoggingFilename() + ":Converted frameBody with:" + identifier + " to deprecated frameBody"); - frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody) frameBody); - } - } finally { - //Update position of main buffer, so no attempt is made to reread these bytes - byteBuffer.position(byteBuffer.position() + realFrameSize); - } - } - - /** - * Write the frame to bufferOutputStream - * - * @throws IOException - */ - public void write(ByteArrayOutputStream tagBuffer) { - logger.config("Writing frame to buffer:" + getIdentifier()); - //This is where we will write header, move position to where we can - //write body - ByteBuffer headerBuffer = ByteBuffer.allocate(FRAME_HEADER_SIZE); - - //Write Frame Body Data - ByteArrayOutputStream bodyOutputStream = new ByteArrayOutputStream(); - ((AbstractID3v2FrameBody) frameBody).write(bodyOutputStream); - //Write Frame Header write Frame ID - if (getIdentifier().length() == 3) { - identifier = identifier + ' '; - } - headerBuffer.put(Utils.getDefaultBytes(getIdentifier(), "ISO-8859-1"), 0, FRAME_ID_SIZE); - //Write Frame Size - int size = frameBody.getSize(); - logger.fine("Frame Size Is:" + size); - headerBuffer.putInt(frameBody.getSize()); - - //Write the Flags - //Status Flags:leave as they were when we read - headerBuffer.put(statusFlags.getWriteFlags()); - - //Remove any non standard flags - ((EncodingFlags) encodingFlags).unsetNonStandardFlags(); - - //Unset Compression flag if previously set because we uncompress previously compressed frames on write. - ((EncodingFlags) encodingFlags).unsetCompression(); - headerBuffer.put(encodingFlags.getFlags()); - - try { - //Add header to the Byte Array Output Stream - tagBuffer.write(headerBuffer.array()); - - if (((EncodingFlags) encodingFlags).isEncryption()) { - tagBuffer.write(encryptionMethod); - } - - if (((EncodingFlags) encodingFlags).isGrouping()) { - tagBuffer.write(groupIdentifier); - } - - //Add body to the Byte Array Output Stream - tagBuffer.write(bodyOutputStream.toByteArray()); - } catch (IOException ioe) { - //This could never happen coz not writing to file, so convert to RuntimeException - throw new RuntimeException(ioe); - } - - - } - - public AbstractID3v2Frame.StatusFlags getStatusFlags() { - return statusFlags; - } - - public AbstractID3v2Frame.EncodingFlags getEncodingFlags() { - return encodingFlags; - } - - public int getEncryptionMethod() { - return encryptionMethod; - } - - public int getGroupIdentifier() { - return groupIdentifier; - } - - /** - * Does the frame identifier meet the syntax for a idv3v2 frame identifier. - * must start with a capital letter and only contain capital letters and numbers - * - * @param identifier to be checked - * @return whether the identifier is valid - */ - public boolean isValidID3v2FrameIdentifier(String identifier) { - Matcher m = ID3v23Frame.validFrameIdentifier.matcher(identifier); - return m.matches(); - } - - /** - * Return String Representation of body - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FRAME, getIdentifier()); - MP3File.getStructureFormatter().addElement(TYPE_FRAME_SIZE, frameSize); - statusFlags.createStructure(); - encodingFlags.createStructure(); - frameBody.createStructure(); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FRAME); - } - - /** - * @return true if considered a common frame - */ - public boolean isCommon() { - return ID3v23Frames.getInstanceOf().isCommon(getId()); - } - - /** - * @return true if considered a common frame - */ - public boolean isBinary() { - return ID3v23Frames.getInstanceOf().isBinary(getId()); - } - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - public void setEncoding(String encoding) { - Integer encodingId = TextEncoding.getInstanceOf().getIdForValue(encoding); - if (encoding != null) { - if (encodingId < 2) { - this.getBody().setTextEncoding(encodingId.byteValue()); - } - } - } - - /** - * This represents a frame headers Status Flags - * Make adjustments if necessary based on frame type and specification. - */ - class StatusFlags extends AbstractID3v2Frame.StatusFlags { - public static final String TYPE_TAGALTERPRESERVATION = "typeTagAlterPreservation"; - public static final String TYPE_FILEALTERPRESERVATION = "typeFileAlterPreservation"; - public static final String TYPE_READONLY = "typeReadOnly"; - - /** - * Discard frame if tag altered - */ - public static final int MASK_TAG_ALTER_PRESERVATION = FileConstants.BIT7; - - /** - * Discard frame if audio file part altered - */ - public static final int MASK_FILE_ALTER_PRESERVATION = FileConstants.BIT6; - - /** - * Frame tagged as read only - */ - public static final int MASK_READ_ONLY = FileConstants.BIT5; - - public StatusFlags() { - originalFlags = (byte) 0; - writeFlags = (byte) 0; - } - - StatusFlags(byte flags) { - originalFlags = flags; - writeFlags = flags; - modifyFlags(); - } - - - /** - * Use this constructor when convert a v24 frame - * - * @param statusFlags - */ - StatusFlags(ID3v24Frame.StatusFlags statusFlags) { - originalFlags = convertV4ToV3Flags(statusFlags.getOriginalFlags()); - writeFlags = originalFlags; - modifyFlags(); - } - - private byte convertV4ToV3Flags(byte v4Flag) { - byte v3Flag = (byte) 0; - if ((v4Flag & ID3v24Frame.StatusFlags.MASK_FILE_ALTER_PRESERVATION) != 0) { - v3Flag |= (byte) MASK_FILE_ALTER_PRESERVATION; - } - if ((v4Flag & ID3v24Frame.StatusFlags.MASK_TAG_ALTER_PRESERVATION) != 0) { - v3Flag |= (byte) MASK_TAG_ALTER_PRESERVATION; - } - return v3Flag; - } - - protected void modifyFlags() { - String str = getIdentifier(); - if (ID3v23Frames.getInstanceOf().isDiscardIfFileAltered(str)) { - writeFlags |= (byte) MASK_FILE_ALTER_PRESERVATION; - writeFlags &= (byte) ~MASK_TAG_ALTER_PRESERVATION; - } else { - writeFlags &= (byte) ~MASK_FILE_ALTER_PRESERVATION; - writeFlags &= (byte) ~MASK_TAG_ALTER_PRESERVATION; - } - } - - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FLAGS, ""); - MP3File.getStructureFormatter().addElement(TYPE_TAGALTERPRESERVATION, originalFlags & MASK_TAG_ALTER_PRESERVATION); - MP3File.getStructureFormatter().addElement(TYPE_FILEALTERPRESERVATION, originalFlags & MASK_FILE_ALTER_PRESERVATION); - MP3File.getStructureFormatter().addElement(TYPE_READONLY, originalFlags & MASK_READ_ONLY); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FLAGS); - } - } - - /** - * This represents a frame headers Encoding Flags - */ - class EncodingFlags extends AbstractID3v2Frame.EncodingFlags { - public static final String TYPE_COMPRESSION = "compression"; - public static final String TYPE_ENCRYPTION = "encryption"; - public static final String TYPE_GROUPIDENTITY = "groupidentity"; - - /** - * Frame is compressed - */ - public static final int MASK_COMPRESSION = FileConstants.BIT7; - - /** - * Frame is encrypted - */ - public static final int MASK_ENCRYPTION = FileConstants.BIT6; - - /** - * Frame is part of a group - */ - public static final int MASK_GROUPING_IDENTITY = FileConstants.BIT5; - - public EncodingFlags() { - super(); - } - - public EncodingFlags(byte flags) { - super(flags); - logEnabledFlags(); - } - - public void setCompression() { - flags |= MASK_COMPRESSION; - } - - public void setEncryption() { - flags |= MASK_ENCRYPTION; - } - - public void setGrouping() { - flags |= MASK_GROUPING_IDENTITY; - } - - public void unsetCompression() { - flags &= (byte) ~MASK_COMPRESSION; - } - - public void unsetEncryption() { - flags &= (byte) ~MASK_ENCRYPTION; - } - - public void unsetGrouping() { - flags &= (byte) ~MASK_GROUPING_IDENTITY; - } - - public boolean isNonStandardFlags() { - return ((flags & FileConstants.BIT4) > 0) || - ((flags & FileConstants.BIT3) > 0) || - ((flags & FileConstants.BIT2) > 0) || - ((flags & FileConstants.BIT1) > 0) || - ((flags & FileConstants.BIT0) > 0); - - } - - public void unsetNonStandardFlags() { - if (isNonStandardFlags()) { - logger.warning(getLoggingFilename() + ":" + getIdentifier() + ":Unsetting Unknown Encoding Flags:" + Hex.asHex(flags)); - flags &= (byte) ~FileConstants.BIT4; - flags &= (byte) ~FileConstants.BIT3; - flags &= (byte) ~FileConstants.BIT2; - flags &= (byte) ~FileConstants.BIT1; - flags &= (byte) ~FileConstants.BIT0; - } - } - - - public void logEnabledFlags() { - if (isNonStandardFlags()) { - logger.warning(getLoggingFilename() + ":" + identifier + ":Unknown Encoding Flags:" + Hex.asHex(flags)); - } - if (isCompression()) { - logger.warning(getLoggingFilename() + ":" + identifier + " is compressed"); - } - - if (isEncryption()) { - logger.warning(getLoggingFilename() + ":" + identifier + " is encrypted"); - } - - if (isGrouping()) { - logger.warning(getLoggingFilename() + ":" + identifier + " is grouped"); - } - } - - public boolean isCompression() { - return (flags & MASK_COMPRESSION) > 0; - } - - public boolean isEncryption() { - return (flags & MASK_ENCRYPTION) > 0; - } - - public boolean isGrouping() { - return (flags & MASK_GROUPING_IDENTITY) > 0; - } - - - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FLAGS, ""); - MP3File.getStructureFormatter().addElement(TYPE_COMPRESSION, flags & MASK_COMPRESSION); - MP3File.getStructureFormatter().addElement(TYPE_ENCRYPTION, flags & MASK_ENCRYPTION); - MP3File.getStructureFormatter().addElement(TYPE_GROUPIDENTITY, flags & MASK_GROUPING_IDENTITY); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FLAGS); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v23Frames.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v23Frames.java deleted file mode 100644 index 82d8cc1..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v23Frames.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Jaudiotagger Copyright (C)2004,2005 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.FieldKey; - -import java.util.EnumMap; -import java.util.Map; - -/** - * Defines ID3v23 frames and collections that categorise frames within an ID3v23 tag. - *

    - * You can include frames here that are not officially supported as long as they can be used within an - * ID3v23Tag - * - * @author Paul Taylor - * @version $Id: ID3v23Frames.java 1059 2012-07-04 12:18:35Z paultaylor $ - */ -public class ID3v23Frames extends ID3Frames { - /** - * Define all frames that are valid within ID3v23 - * Frame IDs begining with T are text frames, & with W are url frames - */ - public static final String FRAME_ID_V3_ACCOMPANIMENT = "TPE2"; - public static final String FRAME_ID_V3_ALBUM = "TALB"; - public static final String FRAME_ID_V3_ARTIST = "TPE1"; - public static final String FRAME_ID_V3_ATTACHED_PICTURE = "APIC"; - public static final String FRAME_ID_V3_AUDIO_ENCRYPTION = "AENC"; - public static final String FRAME_ID_V3_BPM = "TBPM"; - public static final String FRAME_ID_V3_COMMENT = "COMM"; - public static final String FRAME_ID_V3_COMMERCIAL_FRAME = "COMR"; - public static final String FRAME_ID_V3_COMPOSER = "TCOM"; - public static final String FRAME_ID_V3_CONDUCTOR = "TPE3"; - public static final String FRAME_ID_V3_CONTENT_GROUP_DESC = "TIT1"; - public static final String FRAME_ID_V3_COPYRIGHTINFO = "TCOP"; - public static final String FRAME_ID_V3_ENCODEDBY = "TENC"; - public static final String FRAME_ID_V3_ENCRYPTION = "ENCR"; - public static final String FRAME_ID_V3_EQUALISATION = "EQUA"; - public static final String FRAME_ID_V3_EVENT_TIMING_CODES = "ETCO"; - public static final String FRAME_ID_V3_FILE_OWNER = "TOWN"; - public static final String FRAME_ID_V3_FILE_TYPE = "TFLT"; - public static final String FRAME_ID_V3_GENERAL_ENCAPS_OBJECT = "GEOB"; - public static final String FRAME_ID_V3_GENRE = "TCON"; - public static final String FRAME_ID_V3_GROUP_ID_REG = "GRID"; - public static final String FRAME_ID_V3_HW_SW_SETTINGS = "TSSE"; - public static final String FRAME_ID_V3_INITIAL_KEY = "TKEY"; - public static final String FRAME_ID_V3_IPLS = "IPLS"; - public static final String FRAME_ID_V3_ISRC = "TSRC"; - public static final String FRAME_ID_V3_LANGUAGE = "TLAN"; - public static final String FRAME_ID_V3_LENGTH = "TLEN"; - public static final String FRAME_ID_V3_LINKED_INFO = "LINK"; - public static final String FRAME_ID_V3_LYRICIST = "TEXT"; - public static final String FRAME_ID_V3_MEDIA_TYPE = "TMED"; - public static final String FRAME_ID_V3_MPEG_LOCATION_LOOKUP_TABLE = "MLLT"; - public static final String FRAME_ID_V3_MUSIC_CD_ID = "MCDI"; - public static final String FRAME_ID_V3_ORIGARTIST = "TOPE"; - public static final String FRAME_ID_V3_ORIG_FILENAME = "TOFN"; - public static final String FRAME_ID_V3_ORIG_LYRICIST = "TOLY"; - public static final String FRAME_ID_V3_ORIG_TITLE = "TOAL"; - public static final String FRAME_ID_V3_OWNERSHIP = "OWNE"; - public static final String FRAME_ID_V3_PLAYLIST_DELAY = "TDLY"; - public static final String FRAME_ID_V3_PLAY_COUNTER = "PCNT"; - public static final String FRAME_ID_V3_POPULARIMETER = "POPM"; - public static final String FRAME_ID_V3_POSITION_SYNC = "POSS"; - public static final String FRAME_ID_V3_PRIVATE = "PRIV"; - public static final String FRAME_ID_V3_PUBLISHER = "TPUB"; - public static final String FRAME_ID_V3_RADIO_NAME = "TRSN"; - public static final String FRAME_ID_V3_RADIO_OWNER = "TRSO"; - public static final String FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE = "RBUF"; - public static final String FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT = "RVAD"; - public static final String FRAME_ID_V3_REMIXED = "TPE4"; - public static final String FRAME_ID_V3_REVERB = "RVRB"; - public static final String FRAME_ID_V3_SET = "TPOS"; - public static final String FRAME_ID_V3_SYNC_LYRIC = "SYLT"; - public static final String FRAME_ID_V3_SYNC_TEMPO = "SYTC"; - public static final String FRAME_ID_V3_TDAT = "TDAT"; - public static final String FRAME_ID_V3_TERMS_OF_USE = "USER"; - public static final String FRAME_ID_V3_TIME = "TIME"; - public static final String FRAME_ID_V3_TITLE = "TIT2"; - public static final String FRAME_ID_V3_TITLE_REFINEMENT = "TIT3"; - public static final String FRAME_ID_V3_TORY = "TORY"; - public static final String FRAME_ID_V3_TRACK = "TRCK"; - public static final String FRAME_ID_V3_TRDA = "TRDA"; - public static final String FRAME_ID_V3_TSIZ = "TSIZ"; - public static final String FRAME_ID_V3_TYER = "TYER"; - public static final String FRAME_ID_V3_UNIQUE_FILE_ID = "UFID"; - public static final String FRAME_ID_V3_UNSYNC_LYRICS = "USLT"; - public static final String FRAME_ID_V3_URL_ARTIST_WEB = "WOAR"; - public static final String FRAME_ID_V3_URL_COMMERCIAL = "WCOM"; - public static final String FRAME_ID_V3_URL_COPYRIGHT = "WCOP"; - public static final String FRAME_ID_V3_URL_FILE_WEB = "WOAF"; - public static final String FRAME_ID_V3_URL_OFFICIAL_RADIO = "WORS"; - public static final String FRAME_ID_V3_URL_PAYMENT = "WPAY"; - public static final String FRAME_ID_V3_URL_PUBLISHERS = "WPUB"; - public static final String FRAME_ID_V3_URL_SOURCE_WEB = "WOAS"; - public static final String FRAME_ID_V3_USER_DEFINED_INFO = "TXXX"; - public static final String FRAME_ID_V3_USER_DEFINED_URL = "WXXX"; - - public static final String FRAME_ID_V3_IS_COMPILATION = "TCMP"; - public static final String FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES = "TSOT"; - public static final String FRAME_ID_V3_ARTIST_SORT_ORDER_ITUNES = "TSOP"; - public static final String FRAME_ID_V3_ALBUM_SORT_ORDER_ITUNES = "TSOA"; - public static final String FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ = "XSOT"; - public static final String FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ = "XSOP"; - public static final String FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ = "XSOA"; - public static final String FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES = "TSO2"; - public static final String FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES = "TSOC"; - public static final String FRAME_ID_V3_SET_SUBTITLE = "TSST"; - - private static ID3v23Frames id3v23Frames; - - /** - * Maps from Generic key to ID3 key - */ - protected EnumMap tagFieldToId3 = new EnumMap(FieldKey.class); - - - /** - * Maps from ID3 key to Generic key - */ - protected EnumMap id3ToTagField = new EnumMap(ID3v23FieldKey.class); - - private ID3v23Frames() { - // The defined v23 frames, - supportedFrames.add(FRAME_ID_V3_ACCOMPANIMENT); - supportedFrames.add(FRAME_ID_V3_ALBUM); - supportedFrames.add(FRAME_ID_V3_ARTIST); - supportedFrames.add(FRAME_ID_V3_ATTACHED_PICTURE); - supportedFrames.add(FRAME_ID_V3_AUDIO_ENCRYPTION); - supportedFrames.add(FRAME_ID_V3_BPM); - supportedFrames.add(FRAME_ID_V3_COMMENT); - supportedFrames.add(FRAME_ID_V3_COMMERCIAL_FRAME); - supportedFrames.add(FRAME_ID_V3_COMPOSER); - supportedFrames.add(FRAME_ID_V3_CONDUCTOR); - supportedFrames.add(FRAME_ID_V3_CONTENT_GROUP_DESC); - supportedFrames.add(FRAME_ID_V3_COPYRIGHTINFO); - supportedFrames.add(FRAME_ID_V3_ENCODEDBY); - supportedFrames.add(FRAME_ID_V3_ENCRYPTION); - supportedFrames.add(FRAME_ID_V3_EQUALISATION); - supportedFrames.add(FRAME_ID_V3_EVENT_TIMING_CODES); - supportedFrames.add(FRAME_ID_V3_FILE_OWNER); - supportedFrames.add(FRAME_ID_V3_FILE_TYPE); - supportedFrames.add(FRAME_ID_V3_GENERAL_ENCAPS_OBJECT); - supportedFrames.add(FRAME_ID_V3_GENRE); - supportedFrames.add(FRAME_ID_V3_GROUP_ID_REG); - supportedFrames.add(FRAME_ID_V3_HW_SW_SETTINGS); - supportedFrames.add(FRAME_ID_V3_INITIAL_KEY); - supportedFrames.add(FRAME_ID_V3_IPLS); - supportedFrames.add(FRAME_ID_V3_ISRC); - supportedFrames.add(FRAME_ID_V3_LANGUAGE); - supportedFrames.add(FRAME_ID_V3_LENGTH); - supportedFrames.add(FRAME_ID_V3_LINKED_INFO); - supportedFrames.add(FRAME_ID_V3_LYRICIST); - supportedFrames.add(FRAME_ID_V3_MEDIA_TYPE); - supportedFrames.add(FRAME_ID_V3_MPEG_LOCATION_LOOKUP_TABLE); - supportedFrames.add(FRAME_ID_V3_MUSIC_CD_ID); - supportedFrames.add(FRAME_ID_V3_ORIGARTIST); - supportedFrames.add(FRAME_ID_V3_ORIG_FILENAME); - supportedFrames.add(FRAME_ID_V3_ORIG_LYRICIST); - supportedFrames.add(FRAME_ID_V3_ORIG_TITLE); - supportedFrames.add(FRAME_ID_V3_OWNERSHIP); - supportedFrames.add(FRAME_ID_V3_PLAYLIST_DELAY); - supportedFrames.add(FRAME_ID_V3_PLAY_COUNTER); - supportedFrames.add(FRAME_ID_V3_POPULARIMETER); - supportedFrames.add(FRAME_ID_V3_POSITION_SYNC); - supportedFrames.add(FRAME_ID_V3_PRIVATE); - supportedFrames.add(FRAME_ID_V3_PUBLISHER); - supportedFrames.add(FRAME_ID_V3_RADIO_NAME); - supportedFrames.add(FRAME_ID_V3_RADIO_OWNER); - supportedFrames.add(FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE); - supportedFrames.add(FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT); - supportedFrames.add(FRAME_ID_V3_REMIXED); - supportedFrames.add(FRAME_ID_V3_REVERB); - supportedFrames.add(FRAME_ID_V3_SET); - supportedFrames.add(FRAME_ID_V3_SET_SUBTITLE); - supportedFrames.add(FRAME_ID_V3_SYNC_LYRIC); - supportedFrames.add(FRAME_ID_V3_SYNC_TEMPO); - supportedFrames.add(FRAME_ID_V3_TDAT); - supportedFrames.add(FRAME_ID_V3_TERMS_OF_USE); - supportedFrames.add(FRAME_ID_V3_TIME); - supportedFrames.add(FRAME_ID_V3_TITLE); - supportedFrames.add(FRAME_ID_V3_TITLE_REFINEMENT); - supportedFrames.add(FRAME_ID_V3_TORY); - supportedFrames.add(FRAME_ID_V3_TRACK); - supportedFrames.add(FRAME_ID_V3_TRDA); - supportedFrames.add(FRAME_ID_V3_TSIZ); - supportedFrames.add(FRAME_ID_V3_TYER); - supportedFrames.add(FRAME_ID_V3_UNIQUE_FILE_ID); - supportedFrames.add(FRAME_ID_V3_UNSYNC_LYRICS); - supportedFrames.add(FRAME_ID_V3_URL_ARTIST_WEB); - supportedFrames.add(FRAME_ID_V3_URL_COMMERCIAL); - supportedFrames.add(FRAME_ID_V3_URL_COPYRIGHT); - supportedFrames.add(FRAME_ID_V3_URL_FILE_WEB); - supportedFrames.add(FRAME_ID_V3_URL_OFFICIAL_RADIO); - supportedFrames.add(FRAME_ID_V3_URL_PAYMENT); - supportedFrames.add(FRAME_ID_V3_URL_PUBLISHERS); - supportedFrames.add(FRAME_ID_V3_URL_SOURCE_WEB); - supportedFrames.add(FRAME_ID_V3_USER_DEFINED_INFO); - supportedFrames.add(FRAME_ID_V3_USER_DEFINED_URL); - - //Extension - extensionFrames.add(FRAME_ID_V3_IS_COMPILATION); - extensionFrames.add(FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V3_ARTIST_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V3_ALBUM_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ); - extensionFrames.add(FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ); - extensionFrames.add(FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ); - extensionFrames.add(FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES); - - //Common - commonFrames.add(FRAME_ID_V3_ARTIST); - commonFrames.add(FRAME_ID_V3_ALBUM); - commonFrames.add(FRAME_ID_V3_TITLE); - commonFrames.add(FRAME_ID_V3_GENRE); - commonFrames.add(FRAME_ID_V3_TRACK); - commonFrames.add(FRAME_ID_V3_TYER); - commonFrames.add(FRAME_ID_V3_COMMENT); - - //Binary - binaryFrames.add(FRAME_ID_V3_ATTACHED_PICTURE); - binaryFrames.add(FRAME_ID_V3_AUDIO_ENCRYPTION); - binaryFrames.add(FRAME_ID_V3_ENCRYPTION); - binaryFrames.add(FRAME_ID_V3_EQUALISATION); - binaryFrames.add(FRAME_ID_V3_EVENT_TIMING_CODES); - binaryFrames.add(FRAME_ID_V3_GENERAL_ENCAPS_OBJECT); - binaryFrames.add(FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT); - binaryFrames.add(FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE); - binaryFrames.add(FRAME_ID_V3_UNIQUE_FILE_ID); - - // Map frameid to a name - idToValue.put(FRAME_ID_V3_ACCOMPANIMENT, "Text: Band/Orchestra/Accompaniment"); - idToValue.put(FRAME_ID_V3_ALBUM, "Text: Album/Movie/Show title"); - idToValue.put(FRAME_ID_V3_ARTIST, "Text: Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group"); - idToValue.put(FRAME_ID_V3_ATTACHED_PICTURE, "Attached picture"); - idToValue.put(FRAME_ID_V3_AUDIO_ENCRYPTION, "Audio encryption"); - idToValue.put(FRAME_ID_V3_BPM, "Text: BPM (Beats Per Minute)"); - idToValue.put(FRAME_ID_V3_COMMENT, "Comments"); - idToValue.put(FRAME_ID_V3_COMMERCIAL_FRAME, ""); - idToValue.put(FRAME_ID_V3_COMPOSER, "Text: Composer"); - idToValue.put(FRAME_ID_V3_CONDUCTOR, "Text: Conductor/Performer refinement"); - idToValue.put(FRAME_ID_V3_CONTENT_GROUP_DESC, "Text: Content group description"); - idToValue.put(FRAME_ID_V3_COPYRIGHTINFO, "Text: Copyright message"); - idToValue.put(FRAME_ID_V3_ENCODEDBY, "Text: Encoded by"); - idToValue.put(FRAME_ID_V3_ENCRYPTION, "Encryption method registration"); - idToValue.put(FRAME_ID_V3_EQUALISATION, "Equalization"); - idToValue.put(FRAME_ID_V3_EVENT_TIMING_CODES, "Event timing codes"); - idToValue.put(FRAME_ID_V3_FILE_OWNER, ""); - idToValue.put(FRAME_ID_V3_FILE_TYPE, "Text: File type"); - idToValue.put(FRAME_ID_V3_GENERAL_ENCAPS_OBJECT, "General encapsulated datatype"); - idToValue.put(FRAME_ID_V3_GENRE, "Text: Content type"); - idToValue.put(FRAME_ID_V3_GROUP_ID_REG, ""); - idToValue.put(FRAME_ID_V3_HW_SW_SETTINGS, "Text: Software/hardware and settings used for encoding"); - idToValue.put(FRAME_ID_V3_INITIAL_KEY, "Text: Initial key"); - idToValue.put(FRAME_ID_V3_IPLS, "Involved people list"); - idToValue.put(FRAME_ID_V3_ISRC, "Text: ISRC (International Standard Recording Code)"); - idToValue.put(FRAME_ID_V3_LANGUAGE, "Text: Language(s)"); - idToValue.put(FRAME_ID_V3_LENGTH, "Text: Length"); - idToValue.put(FRAME_ID_V3_LINKED_INFO, "Linked information"); - idToValue.put(FRAME_ID_V3_LYRICIST, "Text: Lyricist/text writer"); - idToValue.put(FRAME_ID_V3_MEDIA_TYPE, "Text: Media type"); - idToValue.put(FRAME_ID_V3_MPEG_LOCATION_LOOKUP_TABLE, "MPEG location lookup table"); - idToValue.put(FRAME_ID_V3_MUSIC_CD_ID, "Music CD Identifier"); - idToValue.put(FRAME_ID_V3_ORIGARTIST, "Text: Original artist(s)/performer(s)"); - idToValue.put(FRAME_ID_V3_ORIG_FILENAME, "Text: Original filename"); - idToValue.put(FRAME_ID_V3_ORIG_LYRICIST, "Text: Original Lyricist(s)/text writer(s)"); - idToValue.put(FRAME_ID_V3_ORIG_TITLE, "Text: Original album/Movie/Show title"); - idToValue.put(FRAME_ID_V3_OWNERSHIP, ""); - idToValue.put(FRAME_ID_V3_PLAYLIST_DELAY, "Text: Playlist delay"); - idToValue.put(FRAME_ID_V3_PLAY_COUNTER, "Play counter"); - idToValue.put(FRAME_ID_V3_POPULARIMETER, "Popularimeter"); - idToValue.put(FRAME_ID_V3_POSITION_SYNC, "Position Sync"); - idToValue.put(FRAME_ID_V3_PRIVATE, "Private frame"); - idToValue.put(FRAME_ID_V3_PUBLISHER, "Text: Publisher"); - idToValue.put(FRAME_ID_V3_RADIO_NAME, ""); - idToValue.put(FRAME_ID_V3_RADIO_OWNER, ""); - idToValue.put(FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE, "Recommended buffer size"); - idToValue.put(FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT, "Relative volume adjustment"); - idToValue.put(FRAME_ID_V3_REMIXED, "Text: Interpreted, remixed, or otherwise modified by"); - idToValue.put(FRAME_ID_V3_REVERB, "Reverb"); - idToValue.put(FRAME_ID_V3_SET, "Text: Part of a setField"); - idToValue.put(FRAME_ID_V3_SET_SUBTITLE, "Text: SubTitle"); - idToValue.put(FRAME_ID_V3_SYNC_LYRIC, "Synchronized lyric/text"); - idToValue.put(FRAME_ID_V3_SYNC_TEMPO, "Synced tempo codes"); - idToValue.put(FRAME_ID_V3_TDAT, "Text: Date"); - idToValue.put(FRAME_ID_V3_TERMS_OF_USE, ""); - idToValue.put(FRAME_ID_V3_TIME, "Text: Time"); - idToValue.put(FRAME_ID_V3_TITLE, "Text: Title/Songname/Content description"); - idToValue.put(FRAME_ID_V3_TITLE_REFINEMENT, "Text: Subtitle/Description refinement"); - idToValue.put(FRAME_ID_V3_TORY, "Text: Original release year"); - idToValue.put(FRAME_ID_V3_TRACK, "Text: Track number/Position in setField"); - idToValue.put(FRAME_ID_V3_TRDA, "Text: Recording dates"); - idToValue.put(FRAME_ID_V3_TSIZ, "Text: Size"); - idToValue.put(FRAME_ID_V3_TYER, "Text: Year"); - idToValue.put(FRAME_ID_V3_UNIQUE_FILE_ID, "Unique file identifier"); - idToValue.put(FRAME_ID_V3_UNSYNC_LYRICS, "Unsychronized lyric/text transcription"); - idToValue.put(FRAME_ID_V3_URL_ARTIST_WEB, "URL: Official artist/performer webpage"); - idToValue.put(FRAME_ID_V3_URL_COMMERCIAL, "URL: Commercial information"); - idToValue.put(FRAME_ID_V3_URL_COPYRIGHT, "URL: Copyright/Legal information"); - idToValue.put(FRAME_ID_V3_URL_FILE_WEB, "URL: Official audio file webpage"); - idToValue.put(FRAME_ID_V3_URL_OFFICIAL_RADIO, "Official Radio"); - idToValue.put(FRAME_ID_V3_URL_PAYMENT, "URL: Payment"); - idToValue.put(FRAME_ID_V3_URL_PUBLISHERS, "URL: Publishers official webpage"); - idToValue.put(FRAME_ID_V3_URL_SOURCE_WEB, "URL: Official audio source webpage"); - idToValue.put(FRAME_ID_V3_USER_DEFINED_INFO, "User defined text information frame"); - idToValue.put(FRAME_ID_V3_USER_DEFINED_URL, "User defined URL link frame"); - idToValue.put(FRAME_ID_V3_IS_COMPILATION, "Is Compilation"); - idToValue.put(FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES, "Text: title sort order"); - idToValue.put(FRAME_ID_V3_ARTIST_SORT_ORDER_ITUNES, "Text: artist sort order"); - idToValue.put(FRAME_ID_V3_ALBUM_SORT_ORDER_ITUNES, "Text: album sort order"); - idToValue.put(FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ, "Text: title sort order"); - idToValue.put(FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ, "Text: artist sort order"); - idToValue.put(FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ, "Text: album sort order"); - idToValue.put(FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES, "Text:Album Artist Sort Order Frame"); - idToValue.put(FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES, "Text:Composer Sort Order Frame"); - - createMaps(); - - multipleFrames.add(FRAME_ID_V3_USER_DEFINED_INFO); - multipleFrames.add(FRAME_ID_V3_USER_DEFINED_URL); - multipleFrames.add(FRAME_ID_V3_ATTACHED_PICTURE); - multipleFrames.add(FRAME_ID_V3_PRIVATE); - multipleFrames.add(FRAME_ID_V3_COMMENT); - multipleFrames.add(FRAME_ID_V3_UNIQUE_FILE_ID); - multipleFrames.add(FRAME_ID_V3_UNSYNC_LYRICS); - multipleFrames.add(FRAME_ID_V3_POPULARIMETER); - multipleFrames.add(FRAME_ID_V3_GENERAL_ENCAPS_OBJECT); - multipleFrames.add(FRAME_ID_V3_URL_ARTIST_WEB); - - discardIfFileAlteredFrames.add(FRAME_ID_V3_EVENT_TIMING_CODES); - discardIfFileAlteredFrames.add(FRAME_ID_V3_EQUALISATION); - discardIfFileAlteredFrames.add(FRAME_ID_V3_MPEG_LOCATION_LOOKUP_TABLE); - discardIfFileAlteredFrames.add(FRAME_ID_V3_POSITION_SYNC); - discardIfFileAlteredFrames.add(FRAME_ID_V3_SYNC_LYRIC); - discardIfFileAlteredFrames.add(FRAME_ID_V3_SYNC_TEMPO); - discardIfFileAlteredFrames.add(FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT); - discardIfFileAlteredFrames.add(FRAME_ID_V3_EVENT_TIMING_CODES); - discardIfFileAlteredFrames.add(FRAME_ID_V3_ENCODEDBY); - discardIfFileAlteredFrames.add(FRAME_ID_V3_LENGTH); - discardIfFileAlteredFrames.add(FRAME_ID_V3_TSIZ); - - //Mapping from generic key - tagFieldToId3.put(FieldKey.ALBUM, ID3v23FieldKey.ALBUM); - tagFieldToId3.put(FieldKey.ALBUM_ARTIST, ID3v23FieldKey.ALBUM_ARTIST); - tagFieldToId3.put(FieldKey.ALBUM_ARTIST_SORT, ID3v23FieldKey.ALBUM_ARTIST_SORT); - tagFieldToId3.put(FieldKey.ALBUM_SORT, ID3v23FieldKey.ALBUM_SORT); - tagFieldToId3.put(FieldKey.AMAZON_ID, ID3v23FieldKey.AMAZON_ID); - tagFieldToId3.put(FieldKey.ARTIST, ID3v23FieldKey.ARTIST); - tagFieldToId3.put(FieldKey.ARTIST_SORT, ID3v23FieldKey.ARTIST_SORT); - tagFieldToId3.put(FieldKey.BARCODE, ID3v23FieldKey.BARCODE); - tagFieldToId3.put(FieldKey.BPM, ID3v23FieldKey.BPM); - tagFieldToId3.put(FieldKey.CATALOG_NO, ID3v23FieldKey.CATALOG_NO); - tagFieldToId3.put(FieldKey.COMMENT, ID3v23FieldKey.COMMENT); - tagFieldToId3.put(FieldKey.COMPOSER, ID3v23FieldKey.COMPOSER); - tagFieldToId3.put(FieldKey.COMPOSER_SORT, ID3v23FieldKey.COMPOSER_SORT); - tagFieldToId3.put(FieldKey.CONDUCTOR, ID3v23FieldKey.CONDUCTOR); - tagFieldToId3.put(FieldKey.COVER_ART, ID3v23FieldKey.COVER_ART); - tagFieldToId3.put(FieldKey.CUSTOM1, ID3v23FieldKey.CUSTOM1); - tagFieldToId3.put(FieldKey.CUSTOM2, ID3v23FieldKey.CUSTOM2); - tagFieldToId3.put(FieldKey.CUSTOM3, ID3v23FieldKey.CUSTOM3); - tagFieldToId3.put(FieldKey.CUSTOM4, ID3v23FieldKey.CUSTOM4); - tagFieldToId3.put(FieldKey.CUSTOM5, ID3v23FieldKey.CUSTOM5); - tagFieldToId3.put(FieldKey.DISC_NO, ID3v23FieldKey.DISC_NO); - tagFieldToId3.put(FieldKey.DISC_SUBTITLE, ID3v23FieldKey.DISC_SUBTITLE); - tagFieldToId3.put(FieldKey.DISC_TOTAL, ID3v23FieldKey.DISC_NO); - tagFieldToId3.put(FieldKey.ENCODER, ID3v23FieldKey.ENCODER); - tagFieldToId3.put(FieldKey.FBPM, ID3v23FieldKey.FBPM); - tagFieldToId3.put(FieldKey.GENRE, ID3v23FieldKey.GENRE); - tagFieldToId3.put(FieldKey.GROUPING, ID3v23FieldKey.GROUPING); - tagFieldToId3.put(FieldKey.ISRC, ID3v23FieldKey.ISRC); - tagFieldToId3.put(FieldKey.IS_COMPILATION, ID3v23FieldKey.IS_COMPILATION); - tagFieldToId3.put(FieldKey.KEY, ID3v23FieldKey.KEY); - tagFieldToId3.put(FieldKey.LANGUAGE, ID3v23FieldKey.LANGUAGE); - tagFieldToId3.put(FieldKey.LYRICIST, ID3v23FieldKey.LYRICIST); - tagFieldToId3.put(FieldKey.LYRICS, ID3v23FieldKey.LYRICS); - tagFieldToId3.put(FieldKey.MEDIA, ID3v23FieldKey.MEDIA); - tagFieldToId3.put(FieldKey.MOOD, ID3v23FieldKey.MOOD); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_ARTISTID, ID3v23FieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_DISC_ID, ID3v23FieldKey.MUSICBRAINZ_DISC_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, ID3v23FieldKey.MUSICBRAINZ_ORIGINAL_RELEASEID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, ID3v23FieldKey.MUSICBRAINZ_RELEASEARTISTID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASEID, ID3v23FieldKey.MUSICBRAINZ_RELEASEID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, ID3v23FieldKey.MUSICBRAINZ_RELEASE_COUNTRY); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, ID3v23FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, ID3v23FieldKey.MUSICBRAINZ_RELEASE_STATUS); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, ID3v23FieldKey.MUSICBRAINZ_RELEASE_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_TRACK_ID, ID3v23FieldKey.MUSICBRAINZ_TRACK_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_ID); - tagFieldToId3.put(FieldKey.MUSICIP_ID, ID3v23FieldKey.MUSICIP_ID); - tagFieldToId3.put(FieldKey.OCCASION, ID3v23FieldKey.OCCASION); - tagFieldToId3.put(FieldKey.ORIGINAL_ALBUM, ID3v23FieldKey.ORIGINAL_ALBUM); - tagFieldToId3.put(FieldKey.ORIGINAL_ARTIST, ID3v23FieldKey.ORIGINAL_ARTIST); - tagFieldToId3.put(FieldKey.ORIGINAL_LYRICIST, ID3v23FieldKey.ORIGINAL_LYRICIST); - tagFieldToId3.put(FieldKey.ORIGINAL_YEAR, ID3v23FieldKey.ORIGINAL_YEAR); - tagFieldToId3.put(FieldKey.QUALITY, ID3v23FieldKey.QUALITY); - tagFieldToId3.put(FieldKey.RATING, ID3v23FieldKey.RATING); - tagFieldToId3.put(FieldKey.RECORD_LABEL, ID3v23FieldKey.RECORD_LABEL); - tagFieldToId3.put(FieldKey.REMIXER, ID3v23FieldKey.REMIXER); - tagFieldToId3.put(FieldKey.SCRIPT, ID3v23FieldKey.SCRIPT); - tagFieldToId3.put(FieldKey.SUBTITLE, ID3v23FieldKey.SUBTITLE); - tagFieldToId3.put(FieldKey.TAGS, ID3v23FieldKey.TAGS); - tagFieldToId3.put(FieldKey.TEMPO, ID3v23FieldKey.TEMPO); - tagFieldToId3.put(FieldKey.TITLE, ID3v23FieldKey.TITLE); - tagFieldToId3.put(FieldKey.TITLE_SORT, ID3v23FieldKey.TITLE_SORT); - tagFieldToId3.put(FieldKey.TRACK, ID3v23FieldKey.TRACK); - tagFieldToId3.put(FieldKey.TRACK_TOTAL, ID3v23FieldKey.TRACK_TOTAL); - tagFieldToId3.put(FieldKey.URL_DISCOGS_ARTIST_SITE, ID3v23FieldKey.URL_DISCOGS_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_DISCOGS_RELEASE_SITE, ID3v23FieldKey.URL_DISCOGS_RELEASE_SITE); - tagFieldToId3.put(FieldKey.URL_LYRICS_SITE, ID3v23FieldKey.URL_LYRICS_SITE); - tagFieldToId3.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, ID3v23FieldKey.URL_OFFICIAL_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, ID3v23FieldKey.URL_OFFICIAL_RELEASE_SITE); - tagFieldToId3.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, ID3v23FieldKey.URL_WIKIPEDIA_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, ID3v23FieldKey.URL_WIKIPEDIA_RELEASE_SITE); - tagFieldToId3.put(FieldKey.YEAR, ID3v23FieldKey.YEAR); - tagFieldToId3.put(FieldKey.ENGINEER, ID3v23FieldKey.ENGINEER); - tagFieldToId3.put(FieldKey.PRODUCER, ID3v23FieldKey.PRODUCER); - tagFieldToId3.put(FieldKey.MIXER, ID3v23FieldKey.MIXER); - tagFieldToId3.put(FieldKey.DJMIXER, ID3v23FieldKey.DJMIXER); - tagFieldToId3.put(FieldKey.ARRANGER, ID3v23FieldKey.ARRANGER); - tagFieldToId3.put(FieldKey.ARTISTS, ID3v23FieldKey.ARTISTS); - tagFieldToId3.put(FieldKey.ACOUSTID_FINGERPRINT, ID3v23FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToId3.put(FieldKey.ACOUSTID_ID, ID3v23FieldKey.ACOUSTID_ID); - tagFieldToId3.put(FieldKey.COUNTRY, ID3v23FieldKey.COUNTRY); - - for (Map.Entry next : tagFieldToId3.entrySet()) { - id3ToTagField.put(next.getValue(), next.getKey()); - } - } - - public static ID3v23Frames getInstanceOf() { - if (id3v23Frames == null) { - id3v23Frames = new ID3v23Frames(); - } - return id3v23Frames; - } - - /** - * @param genericKey - * @return id3 key for generic key - */ - public ID3v23FieldKey getId3KeyFromGenericKey(FieldKey genericKey) { - return tagFieldToId3.get(genericKey); - } - - /** - * Get generic key for ID3 field key - * - * @param fieldKey - * @return - */ - public FieldKey getGenericKeyFromId3(ID3v23FieldKey fieldKey) { - return id3ToTagField.get(fieldKey); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java deleted file mode 100644 index d999839..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -/** - * Orders frame Ids so that the most important frames are writtne first - */ -public class ID3v23PreferredFrameOrderComparator implements Comparator { - private static ID3v23PreferredFrameOrderComparator comparator; - private static List frameIdsInPreferredOrder = new ArrayList(); - - static { - //these are the key ones we want at the top - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_UNIQUE_FILE_ID); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TITLE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ARTIST); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ALBUM); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TORY); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_GENRE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_COMPOSER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_CONDUCTOR); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_CONTENT_GROUP_DESC); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TRACK); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TYER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TDAT); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TIME); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_BPM); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ISRC); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TORY); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ACCOMPANIMENT); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TITLE_REFINEMENT); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_UNSYNC_LYRICS); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_URL); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_ARTIST_WEB); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_COMMERCIAL); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_COPYRIGHT); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_FILE_WEB); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_OFFICIAL_RADIO); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_PAYMENT); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_PUBLISHERS); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_URL_COMMERCIAL); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_LYRICIST); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_MEDIA_TYPE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_IPLS); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_LANGUAGE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_PLAYLIST_DELAY); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_PLAY_COUNTER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_POPULARIMETER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_PUBLISHER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_IS_COMPILATION); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ALBUM_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_COMPOSER_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_COMMENT); - - - //Not so bothered about these - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TRDA); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_COMMERCIAL_FRAME); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_COPYRIGHTINFO); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ENCODEDBY); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ENCRYPTION); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_EQUALISATION); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_EVENT_TIMING_CODES); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_FILE_OWNER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_FILE_TYPE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_GROUP_ID_REG); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_HW_SW_SETTINGS); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_INITIAL_KEY); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_LENGTH); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_LINKED_INFO); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TSIZ); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_MPEG_LOCATION_LOOKUP_TABLE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ORIGARTIST); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ORIG_FILENAME); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ORIG_LYRICIST); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ORIG_TITLE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_OWNERSHIP); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_POSITION_SYNC); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_RADIO_NAME); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_RADIO_OWNER); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_RECOMMENDED_BUFFER_SIZE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_REMIXED); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_REVERB); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_SET); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_SYNC_LYRIC); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_SYNC_TEMPO); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_TERMS_OF_USE); - - //Want this near the end because can cause problems with unsyncing - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_ATTACHED_PICTURE); - - //Itunes doesnt seem to like these, and of little use so put right at end - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_PRIVATE); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_MUSIC_CD_ID); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_AUDIO_ENCRYPTION); - frameIdsInPreferredOrder.add(ID3v23Frames.FRAME_ID_V3_GENERAL_ENCAPS_OBJECT); - } - - - private ID3v23PreferredFrameOrderComparator() { - - } - - public static ID3v23PreferredFrameOrderComparator getInstanceof() { - if (comparator == null) { - comparator = new ID3v23PreferredFrameOrderComparator(); - } - return comparator; - } - - /** - * @param frameId1 - * @param frameId2 - * @return - */ - public int compare(String frameId1, String frameId2) { - int frameId1Index = frameIdsInPreferredOrder.indexOf(frameId1); - int frameId2Index = frameIdsInPreferredOrder.indexOf(frameId2); - return frameId1Index - frameId2Index; - } - - public boolean equals(Object obj) { - return obj instanceof ID3v23PreferredFrameOrderComparator; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v23Tag.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v23Tag.java deleted file mode 100644 index 40dfe65..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v23Tag.java +++ /dev/null @@ -1,980 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.FileConstants; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.framebody.*; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import java.util.*; -import java.util.logging.Level; - -/** - * Represents an ID3v2.3 tag. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3v23Tag.java 1082 2013-01-06 09:38:14Z paultaylor $ - */ -public class ID3v23Tag extends AbstractID3v2Tag { - - /** - * ID3v2.3 Header bit mask - */ - public static final int MASK_V23_UNSYNCHRONIZATION = FileConstants.BIT7; - /** - * ID3v2.3 Header bit mask - */ - public static final int MASK_V23_EXTENDED_HEADER = FileConstants.BIT6; - /** - * ID3v2.3 Header bit mask - */ - public static final int MASK_V23_EXPERIMENTAL = FileConstants.BIT5; - /** - * ID3v2.3 Extended Header bit mask - */ - public static final int MASK_V23_CRC_DATA_PRESENT = FileConstants.BIT7; - /** - * ID3v2.3 RBUF frame bit mask - */ - public static final int MASK_V23_EMBEDDED_INFO_FLAG = FileConstants.BIT1; - public static final byte RELEASE = 2; - public static final byte MAJOR_VERSION = 3; - public static final byte REVISION = 0; - protected static final String TYPE_CRCDATA = "crcdata"; - protected static final String TYPE_EXPERIMENTAL = "experimental"; - protected static final String TYPE_EXTENDED = "extended"; - protected static final String TYPE_PADDINGSIZE = "paddingsize"; - protected static final String TYPE_UNSYNCHRONISATION = "unsyncronisation"; - protected static int TAG_EXT_HEADER_LENGTH = 10; - protected static int TAG_EXT_HEADER_CRC_LENGTH = 4; - protected static int FIELD_TAG_EXT_SIZE_LENGTH = 4; - protected static int TAG_EXT_HEADER_DATA_LENGTH = TAG_EXT_HEADER_LENGTH - FIELD_TAG_EXT_SIZE_LENGTH; - /** - * CRC Checksum calculated - */ - protected boolean crcDataFlag = false; - /** - * Experiemntal tag - */ - protected boolean experimental = false; - /** - * Contains extended header - */ - protected boolean extended = false; - /** - * All frames in the tag uses unsynchronisation - */ - protected boolean unsynchronization = false; - /** - * The tag is compressed - */ - protected boolean compression = false; - /** - * Crcdata Checksum in extended header - */ - private int crc32; - /** - * Tag padding - */ - private int paddingSize = 0; - - - /** - * Creates a new empty ID3v2_3 datatype. - */ - public ID3v23Tag() { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - } - - /** - * Copy Constructor, creates a new ID3v2_3 Tag based on another ID3v2_3 Tag - * - * @param copyObject - */ - public ID3v23Tag(ID3v23Tag copyObject) { - //This doesn't do anything. - super(copyObject); - logger.config("Creating tag from another tag of same type"); - copyPrimitives(copyObject); - copyFrames(copyObject); - - } - - /** - * Constructs a new tag based upon another tag of different version/type - * - * @param mp3tag - */ - public ID3v23Tag(AbstractTag mp3tag) { - logger.config("Creating tag from a tag of a different version"); - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - if (mp3tag != null) { - ID3v24Tag convertedTag; - //Should use simpler copy constructor - if (mp3tag instanceof ID3v23Tag) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - if (mp3tag instanceof ID3v24Tag) { - convertedTag = (ID3v24Tag) mp3tag; - } - //All tags types can be converted to v2.4 so do this to simplify things - else { - convertedTag = new ID3v24Tag(mp3tag); - } - this.setLoggingFilename(convertedTag.getLoggingFilename()); - //Copy Primitives - copyPrimitives(convertedTag); - //Copy Frames - copyFrames(convertedTag); - logger.config("Created tag from a tag of a different version"); - } - } - - - /** - * Creates a new ID3v2_3 datatype. - * - * @param buffer - * @param loggingFilename - * @throws TagException - */ - public ID3v23Tag(ByteBuffer buffer, String loggingFilename) throws TagException { - setLoggingFilename(loggingFilename); - this.read(buffer); - } - - /** - * Creates a new ID3v2_3 datatype. - * - * @param buffer - * @throws TagException - * @deprecated use {@link #ID3v23Tag(ByteBuffer, String)} instead - */ - public ID3v23Tag(ByteBuffer buffer) throws TagException { - this(buffer, ""); - } - - /** - * Retrieve the Release - */ - public byte getRelease() { - return RELEASE; - } - - /** - * Retrieve the Major Version - */ - public byte getMajorVersion() { - return MAJOR_VERSION; - } - - /** - * Retrieve the Revision - */ - public byte getRevision() { - return REVISION; - } - - /** - * @return Cyclic Redundancy Check 32 Value - */ - public int getCrc32() { - return crc32; - } - - /** - * Copy primitives applicable to v2.3 - */ - protected void copyPrimitives(AbstractID3v2Tag copyObj) { - logger.config("Copying primitives"); - super.copyPrimitives(copyObj); - - if (copyObj instanceof ID3v23Tag) { - ID3v23Tag copyObject = (ID3v23Tag) copyObj; - this.crcDataFlag = copyObject.crcDataFlag; - this.experimental = copyObject.experimental; - this.extended = copyObject.extended; - this.crc32 = copyObject.crc32; - this.paddingSize = copyObject.paddingSize; - } - } - - protected void addFrame(AbstractID3v2Frame frame) { - try { - //Special case to handle TDRC frame from V24 that needs breaking up into separate frame in V23 - if ((frame.getIdentifier().equals(ID3v24Frames.FRAME_ID_YEAR)) && (frame.getBody() instanceof FrameBodyTDRC)) { - translateFrame(frame); - } else if (frame instanceof ID3v23Frame) { - copyFrameIntoMap(frame.getIdentifier(), frame); - } else { - ID3v23Frame newFrame = new ID3v23Frame(frame); - copyFrameIntoMap(newFrame.getIdentifier(), newFrame); - } - } catch (InvalidFrameException ife) { - logger.log(Level.SEVERE, "Unable to convert frame:" + frame.getIdentifier()); - } - } - - /** - * This is used when we need to translate a single frame into multiple frames, - * currently required for v24 TDRC frames. - * - * @param frame - */ - //TODO will overwrite any existing TYER or TIME frame, do we ever want multiples of these - protected void translateFrame(AbstractID3v2Frame frame) { - FrameBodyTDRC tmpBody = (FrameBodyTDRC) frame.getBody(); - ID3v23Frame newFrame; - if (!tmpBody.getYear().equals("")) { - newFrame = new ID3v23Frame(ID3v23Frames.FRAME_ID_V3_TYER); - ((FrameBodyTYER) newFrame.getBody()).setText(tmpBody.getYear()); - logger.config("Adding Frame:" + newFrame.getIdentifier()); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (!tmpBody.getDate().equals("")) { - newFrame = new ID3v23Frame(ID3v23Frames.FRAME_ID_V3_TDAT); - ((FrameBodyTDAT) newFrame.getBody()).setText(tmpBody.getDate()); - ((FrameBodyTDAT) newFrame.getBody()).setMonthOnly(tmpBody.isMonthOnly()); - logger.config("Adding Frame:" + newFrame.getIdentifier()); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (!tmpBody.getTime().equals("")) { - newFrame = new ID3v23Frame(ID3v23Frames.FRAME_ID_V3_TIME); - ((FrameBodyTIME) newFrame.getBody()).setText(tmpBody.getTime()); - ((FrameBodyTIME) newFrame.getBody()).setHoursOnly(tmpBody.isHoursOnly()); - logger.config("Adding Frame:" + newFrame.getIdentifier()); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - } - - /** - * @return textual tag identifier - */ - public String getIdentifier() { - return "ID3v2.30"; - } - - /** - * Return frame size based upon the sizes of the tags rather than the physical - * no of bytes between start of ID3Tag and start of Audio Data. - *

    - * TODO this is incorrect, because of subclasses - * - * @return size of tag - */ - public int getSize() { - int size = TAG_HEADER_LENGTH; - if (extended) { - size += TAG_EXT_HEADER_LENGTH; - if (crcDataFlag) { - size += TAG_EXT_HEADER_CRC_LENGTH; - } - } - size += super.getSize(); - return size; - } - - /** - * Is Tag Equivalent to another tag - * - * @param obj - * @return true if tag is equivalent to another - */ - public boolean equals(Object obj) { - if (!(obj instanceof ID3v23Tag)) { - return false; - } - ID3v23Tag object = (ID3v23Tag) obj; - if (this.crc32 != object.crc32) { - return false; - } - if (this.crcDataFlag != object.crcDataFlag) { - return false; - } - if (this.experimental != object.experimental) { - return false; - } - if (this.extended != object.extended) { - return false; - } - return this.paddingSize == object.paddingSize && super.equals(obj); - } - - - /** - * Read header flags - *

    - *

    Log info messages for flags that have been set and log warnings when bits have been set for unknown flags

    - * - * @param buffer - * @throws TagException - */ - private void readHeaderFlags(ByteBuffer buffer) throws TagException { - //Allowable Flags - byte flags = buffer.get(); - unsynchronization = (flags & MASK_V23_UNSYNCHRONIZATION) != 0; - extended = (flags & MASK_V23_EXTENDED_HEADER) != 0; - experimental = (flags & MASK_V23_EXPERIMENTAL) != 0; - - //Not allowable/Unknown Flags - if ((flags & FileConstants.BIT4) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT4)); - } - - if ((flags & FileConstants.BIT3) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT3)); - } - - if ((flags & FileConstants.BIT2) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT2)); - } - - if ((flags & FileConstants.BIT1) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT1)); - } - - if ((flags & FileConstants.BIT0) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT0)); - } - - if (isUnsynchronization()) { - logger.config(ErrorMessage.ID3_TAG_UNSYNCHRONIZED.getMsg(getLoggingFilename())); - } - - if (extended) { - logger.config(ErrorMessage.ID3_TAG_EXTENDED.getMsg(getLoggingFilename())); - } - - if (experimental) { - logger.config(ErrorMessage.ID3_TAG_EXPERIMENTAL.getMsg(getLoggingFilename())); - } - } - - /** - * Read the optional extended header - * - * @param buffer - * @param size - */ - private void readExtendedHeader(ByteBuffer buffer, int size) { - // Int is 4 bytes. - int extendedHeaderSize = buffer.getInt(); - // Extended header without CRC Data - if (extendedHeaderSize == TAG_EXT_HEADER_DATA_LENGTH) { - //Flag should not be setField , if is log a warning - byte extFlag = buffer.get(); - crcDataFlag = (extFlag & MASK_V23_CRC_DATA_PRESENT) != 0; - if (crcDataFlag) { - logger.warning(ErrorMessage.ID3_TAG_CRC_FLAG_SET_INCORRECTLY.getMsg(getLoggingFilename())); - } - //2nd Flag Byte (not used) - buffer.get(); - - //Take padding and ext header size off the size to be read - paddingSize = buffer.getInt(); - if (paddingSize > 0) { - logger.config(ErrorMessage.ID3_TAG_PADDING_SIZE.getMsg(getLoggingFilename(), paddingSize)); - } - size = size - (paddingSize + TAG_EXT_HEADER_LENGTH); - } else if (extendedHeaderSize == TAG_EXT_HEADER_DATA_LENGTH + TAG_EXT_HEADER_CRC_LENGTH) { - logger.config(ErrorMessage.ID3_TAG_CRC.getMsg(getLoggingFilename())); - - //Flag should be setField, if nor just act as if it is - byte extFlag = buffer.get(); - crcDataFlag = (extFlag & MASK_V23_CRC_DATA_PRESENT) != 0; - if (!crcDataFlag) { - logger.warning(ErrorMessage.ID3_TAG_CRC_FLAG_SET_INCORRECTLY.getMsg(getLoggingFilename())); - } - //2nd Flag Byte (not used) - buffer.get(); - //Take padding size of size to be read - paddingSize = buffer.getInt(); - if (paddingSize > 0) { - logger.config(ErrorMessage.ID3_TAG_PADDING_SIZE.getMsg(getLoggingFilename(), paddingSize)); - } - size = size - (paddingSize + TAG_EXT_HEADER_LENGTH + TAG_EXT_HEADER_CRC_LENGTH); - //CRC Data - crc32 = buffer.getInt(); - logger.config(ErrorMessage.ID3_TAG_CRC_SIZE.getMsg(getLoggingFilename(), crc32)); - } - //Extended header size is only allowed to be six or ten bytes so this is invalid but instead - //of giving up lets guess its six bytes and carry on and see if we can read file ok - else { - logger.warning(ErrorMessage.ID3_EXTENDED_HEADER_SIZE_INVALID.getMsg(getLoggingFilename(), extendedHeaderSize)); - buffer.position(buffer.position() - FIELD_TAG_EXT_SIZE_LENGTH); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void read(ByteBuffer buffer) throws TagException { - int size; - if (!seek(buffer)) { - throw new TagNotFoundException(getIdentifier() + " tag not found"); - } - logger.config(getLoggingFilename() + ":" + "Reading ID3v23 tag"); - - readHeaderFlags(buffer); - - // Read the size, this is size of tag not including the tag header - size = ID3SyncSafeInteger.bufferToValue(buffer); - logger.config(ErrorMessage.ID_TAG_SIZE.getMsg(getLoggingFilename(), size)); - - //Extended Header - if (extended) { - readExtendedHeader(buffer, size); - } - - //Slice Buffer, so position markers tally with size (i.e do not include tagHeader) - ByteBuffer bufferWithoutHeader = buffer.slice(); - //We need to synchronize the buffer - if (isUnsynchronization()) { - bufferWithoutHeader = ID3Unsynchronization.synchronize(bufferWithoutHeader); - } - - readFrames(bufferWithoutHeader, size); - logger.config(getLoggingFilename() + ":Loaded Frames,there are:" + frameMap.keySet().size()); - - } - - - /** - * Read the frames - *

    - * Read from byteBuffer upto size - * - * @param byteBuffer - * @param size - */ - protected void readFrames(ByteBuffer byteBuffer, int size) { - //Now start looking for frames - ID3v23Frame next; - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - - //Read the size from the Tag Header - this.fileReadSize = size; - logger.finest(getLoggingFilename() + ":Start of frame body at:" + byteBuffer.position() + ",frames data size is:" + size); - - // Read the frames until got to up to the size as specified in header or until - // we hit an invalid frame identifier or padding - while (byteBuffer.position() < size) { - String id; - try { - //Read Frame - logger.finest(getLoggingFilename() + ":Looking for next frame at:" + byteBuffer.position()); - next = new ID3v23Frame(byteBuffer, getLoggingFilename()); - id = next.getIdentifier(); - loadFrameIntoMap(id, next); - } - //Found Padding, no more frames - catch (PaddingException ex) { - logger.config(getLoggingFilename() + ":Found padding starting at:" + byteBuffer.position()); - break; - } - //Found Empty Frame, log it - empty frames should not exist - catch (EmptyFrameException ex) { - logger.warning(getLoggingFilename() + ":Empty Frame:" + ex.getMessage()); - this.emptyFrameBytes += ID3v23Frame.FRAME_HEADER_SIZE; - } catch (InvalidFrameIdentifierException ifie) { - logger.warning(getLoggingFilename() + ":Invalid Frame Identifier:" + ifie.getMessage()); - this.invalidFrames++; - //Don't try and find any more frames - break; - } - //Problem trying to find frame, often just occurs because frameHeader includes padding - //and we have reached padding - catch (InvalidFrameException ife) { - logger.warning(getLoggingFilename() + ":Invalid Frame:" + ife.getMessage()); - this.invalidFrames++; - //Don't try and find any more frames - break; - } - //Failed reading frame but may just have invalid data but correct length so lets carry on - //in case we can read the next frame - catch (InvalidDataTypeException idete) { - logger.warning(getLoggingFilename() + ":Corrupt Frame:" + idete.getMessage()); - this.invalidFrames++; - continue; - } - } - } - - /** - * Write the ID3 header to the ByteBuffer. - *

    - * TODO Calculate the CYC Data Check - * TODO Reintroduce Extended Header - * - * @param padding is the size of the padding portion of the tag - * @param size is the size of the body data - * @return ByteBuffer - * @throws IOException - */ - private ByteBuffer writeHeaderToBuffer(int padding, int size) throws IOException { - // Flags,currently we never calculate the CRC - // and if we dont calculate them cant keep orig values. Tags are not - // experimental and we never createField extended header to keep things simple. - extended = false; - experimental = false; - crcDataFlag = false; - - // Create Header Buffer,allocate maximum possible size for the header - ByteBuffer headerBuffer = ByteBuffer. - allocate(TAG_HEADER_LENGTH + TAG_EXT_HEADER_LENGTH + TAG_EXT_HEADER_CRC_LENGTH); - - //TAGID - headerBuffer.put(TAG_ID); - - //Major Version - headerBuffer.put(getMajorVersion()); - - //Minor Version - headerBuffer.put(getRevision()); - - //Flags - byte flagsByte = 0; - if (isUnsynchronization()) { - flagsByte |= MASK_V23_UNSYNCHRONIZATION; - } - if (extended) { - flagsByte |= MASK_V23_EXTENDED_HEADER; - } - if (experimental) { - flagsByte |= MASK_V23_EXPERIMENTAL; - } - headerBuffer.put(flagsByte); - - //Additional Header Size,(for completeness we never actually write the extended header) - int additionalHeaderSize = 0; - if (extended) { - additionalHeaderSize += TAG_EXT_HEADER_LENGTH; - if (crcDataFlag) { - additionalHeaderSize += TAG_EXT_HEADER_CRC_LENGTH; - } - } - - //Size As Recorded in Header, don't include the main header length - headerBuffer.put(ID3SyncSafeInteger.valueToBuffer(padding + size + additionalHeaderSize)); - - //Write Extended Header - if (extended) { - byte extFlagsByte1 = 0; - byte extFlagsByte2 = 0; - - //Contains CRCData - if (crcDataFlag) { - headerBuffer.putInt(TAG_EXT_HEADER_DATA_LENGTH + TAG_EXT_HEADER_CRC_LENGTH); - extFlagsByte1 |= MASK_V23_CRC_DATA_PRESENT; - headerBuffer.put(extFlagsByte1); - headerBuffer.put(extFlagsByte2); - headerBuffer.putInt(paddingSize); - headerBuffer.putInt(crc32); - } - //Just extended Header - else { - headerBuffer.putInt(TAG_EXT_HEADER_DATA_LENGTH); - headerBuffer.put(extFlagsByte1); - headerBuffer.put(extFlagsByte2); - //Newly Calculated Padding As Recorded in Extended Header - headerBuffer.putInt(padding); - } - } - - headerBuffer.flip(); - return headerBuffer; - } - - - /** - * Write tag to file - *

    - * TODO:we currently never write the Extended header , but if we did the size calculation in this - * method would be slightly incorrect - * - * @param file The file to write to - * @throws IOException - */ - public void write(File file, long audioStartLocation) throws IOException { - setLoggingFilename(file.getName()); - logger.config("Writing tag to file:" + getLoggingFilename()); - - //Write Body Buffer - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizebeforeunsynchronisation:" + bodyByteBuffer.length); - - // Unsynchronize if option enabled and unsync required - unsynchronization = TagOptionSingleton.getInstance().isUnsyncTags() && ID3Unsynchronization.requiresUnsynchronization(bodyByteBuffer); - if (isUnsynchronization()) { - bodyByteBuffer = ID3Unsynchronization.unsynchronize(bodyByteBuffer); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizeafterunsynchronisation:" + bodyByteBuffer.length); - } - - int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) audioStartLocation); - int padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH); - logger.config(getLoggingFilename() + ":Current audiostart:" + audioStartLocation); - logger.config(getLoggingFilename() + ":Size including padding:" + sizeIncPadding); - logger.config(getLoggingFilename() + ":Padding:" + padding); - - ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length); - writeBufferToFile(file, headerBuffer, bodyByteBuffer, padding, sizeIncPadding, audioStartLocation); - } - - /** - * {@inheritDoc} - */ - @Override - public void write(WritableByteChannel channel) throws IOException { - logger.config(getLoggingFilename() + ":Writing tag to channel"); - - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizebeforeunsynchronisation:" + bodyByteBuffer.length); - - // Unsynchronize if option enabled and unsync required - unsynchronization = TagOptionSingleton.getInstance().isUnsyncTags() && ID3Unsynchronization.requiresUnsynchronization(bodyByteBuffer); - if (isUnsynchronization()) { - bodyByteBuffer = ID3Unsynchronization.unsynchronize(bodyByteBuffer); - logger.config(getLoggingFilename() + ":bodybytebuffer:sizeafterunsynchronisation:" + bodyByteBuffer.length); - } - ByteBuffer headerBuffer = writeHeaderToBuffer(0, bodyByteBuffer.length); - - channel.write(headerBuffer); - channel.write(ByteBuffer.wrap(bodyByteBuffer)); - } - - /** - * For representing the MP3File in an XML Format - */ - public void createStructure() { - - MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier()); - - super.createStructureHeader(); - - //Header - MP3File.getStructureFormatter().openHeadingElement(TYPE_HEADER, ""); - MP3File.getStructureFormatter().addElement(TYPE_UNSYNCHRONISATION, this.isUnsynchronization()); - MP3File.getStructureFormatter().addElement(TYPE_EXTENDED, this.extended); - MP3File.getStructureFormatter().addElement(TYPE_EXPERIMENTAL, this.experimental); - MP3File.getStructureFormatter().addElement(TYPE_CRCDATA, this.crc32); - MP3File.getStructureFormatter().addElement(TYPE_PADDINGSIZE, this.paddingSize); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_HEADER); - //Body - super.createStructureBody(); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG); - } - - /** - * @return is tag unsynchronized - */ - public boolean isUnsynchronization() { - return unsynchronization; - } - - public ID3v23Frame createFrame(String id) { - return new ID3v23Frame(id); - } - - - /** - * Create Frame for Id3 Key - *

    - * Only textual data supported at the moment, should only be used with frames that - * support a simple string argument. - * - * @param id3Key - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public TagField createField(ID3v23FieldKey id3Key, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (id3Key == null) { - throw new KeyNotFoundException(); - } - return super.doCreateTagField(new FrameAndSubId(id3Key.getFrameId(), id3Key.getSubId()), value); - } - - /** - * Retrieve the first value that exists for this id3v23key - * - * @param id3v23FieldKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public String getFirst(ID3v23FieldKey id3v23FieldKey) throws KeyNotFoundException { - if (id3v23FieldKey == null) { - throw new KeyNotFoundException(); - } - - FieldKey genericKey = ID3v23Frames.getInstanceOf().getGenericKeyFromId3(id3v23FieldKey); - if (genericKey != null) { - return super.getFirst(genericKey); - } else { - FrameAndSubId frameAndSubId = new FrameAndSubId(id3v23FieldKey.getFrameId(), id3v23FieldKey.getSubId()); - return super.doGetValueAtIndex(frameAndSubId, 0); - } - } - - /** - * Delete fields with this id3v23FieldKey - * - * @param id3v23FieldKey - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(ID3v23FieldKey id3v23FieldKey) throws KeyNotFoundException { - if (id3v23FieldKey == null) { - throw new KeyNotFoundException(); - } - super.doDeleteTagField(new FrameAndSubId(id3v23FieldKey.getFrameId(), id3v23FieldKey.getSubId())); - } - - /** - * Delete fields with this (frame) id - * - * @param id - */ - public void deleteField(String id) { - super.doDeleteTagField(new FrameAndSubId(id, null)); - } - - protected FrameAndSubId getFrameAndSubIdFromGenericKey(FieldKey genericKey) { - if (genericKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - ID3v23FieldKey id3v23FieldKey = ID3v23Frames.getInstanceOf().getId3KeyFromGenericKey(genericKey); - if (id3v23FieldKey == null) { - throw new KeyNotFoundException(genericKey.name()); - } - return new FrameAndSubId(id3v23FieldKey.getFrameId(), id3v23FieldKey.getSubId()); - } - - protected ID3Frames getID3Frames() { - return ID3v23Frames.getInstanceOf(); - } - - /** - * @return comparator used to order frames in preferred order for writing to file - * so that most important frames are written first. - */ - public Comparator getPreferredFrameOrderComparator() { - return ID3v23PreferredFrameOrderComparator.getInstanceof(); - } - - /** - * {@inheritDoc} - */ - public List getArtworkList() { - List coverartList = getFields(FieldKey.COVER_ART); - List artworkList = new ArrayList(coverartList.size()); - - for (TagField next : coverartList) { - FrameBodyAPIC coverArt = (FrameBodyAPIC) ((AbstractID3v2Frame) next).getBody(); - Artwork artwork = ArtworkFactory.getNew(); - artwork.setMimeType(coverArt.getMimeType()); - artwork.setPictureType(coverArt.getPictureType()); - if (coverArt.isImageUrl()) { - artwork.setLinked(true); - artwork.setImageUrl(coverArt.getImageUrl()); - } else { - artwork.setBinaryData(coverArt.getImageData()); - } - artworkList.add(artwork); - } - return artworkList; - } - - /** - * {@inheritDoc} - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - FrameBodyAPIC body = (FrameBodyAPIC) frame.getBody(); - if (!artwork.isLinked()) { - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, artwork.getBinaryData()); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, artwork.getPictureType()); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, artwork.getMimeType()); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } else { - try { - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, artwork.getImageUrl().getBytes("ISO-8859-1")); - } catch (UnsupportedEncodingException uoe) { - throw new RuntimeException(uoe.getMessage()); - } - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, artwork.getPictureType()); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, FrameBodyAPIC.IMAGE_IS_URL); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } - } - - /** - * Create Artwork - * - * @param data - * @param mimeType of the image - * @return - * @see PictureTypes - */ - public TagField createArtworkField(byte[] data, String mimeType) { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - FrameBodyAPIC body = (FrameBodyAPIC) frame.getBody(); - - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, data); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, mimeType); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } - - public int getPaddingSize() { - return paddingSize; - } - - /** - * Overridden to allow special handling for mapping YEAR to TYER and TDAT Frames - * - * @param genericKey is the generic key - * @param value to store - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - if (genericKey != FieldKey.YEAR) { - return super.createField(genericKey, value); - } - - if (value.length() < 4) { - throw new FieldDataInvalidException(); - } else if (value.length() == 4) { - AbstractID3v2Frame tyer = createFrame(ID3v23Frames.FRAME_ID_V3_TYER); - ((AbstractFrameBodyTextInfo) tyer.getBody()).setText(value.substring(0, 4)); - return tyer; - } else if (value.length() > 4) { - AbstractID3v2Frame tyer = createFrame(ID3v23Frames.FRAME_ID_V3_TYER); - ((AbstractFrameBodyTextInfo) tyer.getBody()).setText(value.substring(0, 4)); - - if (value.length() >= 10) { - //Have a full yyyy-mm-dd value that needs storing in two frames in ID3 - String month = value.substring(5, 7); - String day = value.substring(8, 10); - AbstractID3v2Frame tdat = createFrame(ID3v23Frames.FRAME_ID_V3_TDAT); - ((AbstractFrameBodyTextInfo) tdat.getBody()).setText(day + month); - - TyerTdatAggregatedFrame ag = new TyerTdatAggregatedFrame(); - ag.addFrame(tyer); - ag.addFrame(tdat); - return ag; - } else if (value.length() >= 7) { - //TDAT frame requires both month and day so if we only have the month we just have to make - //the day up - String month = value.substring(5, 7); - String day = "01"; - AbstractID3v2Frame tdat = createFrame(ID3v23Frames.FRAME_ID_V3_TDAT); - ((AbstractFrameBodyTextInfo) tdat.getBody()).setText(day + month); - - TyerTdatAggregatedFrame ag = new TyerTdatAggregatedFrame(); - ag.addFrame(tyer); - ag.addFrame(tdat); - return ag; - } else { - //We only have year data - return tyer; - } - } else { - return null; - } - } - - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - if (genericKey != FieldKey.YEAR) { - return super.getValue(genericKey, index); - } - - AggregatedFrame af = (AggregatedFrame) getFrame(TyerTdatAggregatedFrame.ID_TYER_TDAT); - if (af != null) { - return af.getContent(); - } else { - return super.getValue(genericKey, index); - } - } - - protected void loadFrameIntoSpecifiedMap(HashMap map, String frameId, AbstractID3v2Frame frame) { - if (!(frameId.equals(ID3v23Frames.FRAME_ID_V3_TYER)) && !(frameId.equals(ID3v23Frames.FRAME_ID_V3_TDAT))) { - super.loadFrameIntoSpecifiedMap(map, frameId, frame); - return; - } - - if (map.containsKey(frameId) || map.containsKey(TyerTdatAggregatedFrame.ID_TYER_TDAT)) { - //If we have multiple duplicate frames in a tag separate them with semicolons - if (this.duplicateFrameId.length() > 0) { - this.duplicateFrameId += ";"; - } - this.duplicateFrameId += frameId; - this.duplicateBytes += frame.getSize(); - } else if (frameId.equals(ID3v23Frames.FRAME_ID_V3_TYER)) { - if (map.containsKey(ID3v23Frames.FRAME_ID_V3_TDAT)) { - TyerTdatAggregatedFrame ag = new TyerTdatAggregatedFrame(); - ag.addFrame(frame); - ag.addFrame((AbstractID3v2Frame) map.get(ID3v23Frames.FRAME_ID_V3_TDAT)); - map.remove(ID3v23Frames.FRAME_ID_V3_TDAT); - map.put(TyerTdatAggregatedFrame.ID_TYER_TDAT, ag); - } else { - map.put(ID3v23Frames.FRAME_ID_V3_TYER, frame); - } - } else if (frameId.equals(ID3v23Frames.FRAME_ID_V3_TDAT)) { - if (map.containsKey(ID3v23Frames.FRAME_ID_V3_TYER)) { - TyerTdatAggregatedFrame ag = new TyerTdatAggregatedFrame(); - ag.addFrame((AbstractID3v2Frame) map.get(ID3v23Frames.FRAME_ID_V3_TYER)); - ag.addFrame(frame); - map.remove(ID3v23Frames.FRAME_ID_V3_TYER); - map.put(TyerTdatAggregatedFrame.ID_TYER_TDAT, ag); - } else { - map.put(ID3v23Frames.FRAME_ID_V3_TDAT, frame); - } - } - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v24FieldKey.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v24FieldKey.java deleted file mode 100644 index 8f15cc2..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v24FieldKey.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.id3.framebody.*; - -/** - * List of known id3v24 metadata fields - *

    - *

    These provide a mapping from the generic key to the underlying ID3v24frames. For example most of the Musicbrainz - * fields are implemented using a User Defined Text Info Frame, but with a different description key, so this - * enum provides the link between the two. - */ -public enum ID3v24FieldKey { - ALBUM(ID3v24Frames.FRAME_ID_ALBUM, Id3FieldType.TEXT), - ALBUM_ARTIST(ID3v24Frames.FRAME_ID_ACCOMPANIMENT, Id3FieldType.TEXT), - ALBUM_ARTIST_SORT(ID3v24Frames.FRAME_ID_ALBUM_ARTIST_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - ALBUM_SORT(ID3v24Frames.FRAME_ID_ALBUM_SORT_ORDER, Id3FieldType.TEXT), - AMAZON_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.AMAZON_ASIN, Id3FieldType.TEXT), - ARTIST(ID3v24Frames.FRAME_ID_ARTIST, Id3FieldType.TEXT), - ARTIST_SORT(ID3v24Frames.FRAME_ID_ARTIST_SORT_ORDER, Id3FieldType.TEXT), - BARCODE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.BARCODE, Id3FieldType.TEXT), - BPM(ID3v24Frames.FRAME_ID_BPM, Id3FieldType.TEXT), - CATALOG_NO(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.CATALOG_NO, Id3FieldType.TEXT), - COMMENT(ID3v24Frames.FRAME_ID_COMMENT, Id3FieldType.TEXT), - COMPOSER(ID3v24Frames.FRAME_ID_COMPOSER, Id3FieldType.TEXT), - COMPOSER_SORT(ID3v24Frames.FRAME_ID_COMPOSER_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - CONDUCTOR(ID3v24Frames.FRAME_ID_CONDUCTOR, Id3FieldType.TEXT), - COVER_ART(ID3v24Frames.FRAME_ID_ATTACHED_PICTURE, Id3FieldType.BINARY), - CUSTOM1(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_CUSTOM1, Id3FieldType.TEXT), - CUSTOM2(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_CUSTOM2, Id3FieldType.TEXT), - CUSTOM3(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_CUSTOM3, Id3FieldType.TEXT), - CUSTOM4(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_CUSTOM4, Id3FieldType.TEXT), - CUSTOM5(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_CUSTOM5, Id3FieldType.TEXT), - DISC_NO(ID3v24Frames.FRAME_ID_SET, Id3FieldType.TEXT), - DISC_SUBTITLE(ID3v24Frames.FRAME_ID_SET_SUBTITLE, Id3FieldType.TEXT), - DISC_TOTAL(ID3v24Frames.FRAME_ID_SET, Id3FieldType.TEXT), - ENCODER(ID3v24Frames.FRAME_ID_ENCODEDBY, Id3FieldType.TEXT), - FBPM(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.FBPM, Id3FieldType.TEXT), - GENRE(ID3v24Frames.FRAME_ID_GENRE, Id3FieldType.TEXT), - GROUPING(ID3v24Frames.FRAME_ID_CONTENT_GROUP_DESC, Id3FieldType.TEXT), - ISRC(ID3v24Frames.FRAME_ID_ISRC, Id3FieldType.TEXT), - IS_COMPILATION(ID3v24Frames.FRAME_ID_IS_COMPILATION, Id3FieldType.TEXT), - KEY(ID3v24Frames.FRAME_ID_INITIAL_KEY, Id3FieldType.TEXT), - LANGUAGE(ID3v24Frames.FRAME_ID_LANGUAGE, Id3FieldType.TEXT), - LYRICIST(ID3v24Frames.FRAME_ID_LYRICIST, Id3FieldType.TEXT), - LYRICS(ID3v24Frames.FRAME_ID_UNSYNC_LYRICS, Id3FieldType.TEXT), - MEDIA(ID3v24Frames.FRAME_ID_MEDIA_TYPE, Id3FieldType.TEXT), - MOOD(ID3v24Frames.FRAME_ID_MOOD, Id3FieldType.TEXT), - MUSICBRAINZ_ARTISTID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ARTISTID, Id3FieldType.TEXT), - MUSICBRAINZ_DISC_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_DISCID, Id3FieldType.TEXT), - MUSICBRAINZ_ORIGINAL_RELEASEID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ORIGINAL_ALBUMID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASEARTISTID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_ARTISTID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASEID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUMID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_COUNTRY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_COUNTRY, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_GROUP_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_RELEASE_GROUPID, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_STATUS(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_STATUS, Id3FieldType.TEXT), - MUSICBRAINZ_RELEASE_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_ALBUM_TYPE, Id3FieldType.TEXT), - MUSICBRAINZ_TRACK_ID(ID3v24Frames.FRAME_ID_UNIQUE_FILE_ID, FrameBodyUFID.UFID_MUSICBRAINZ, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORKID, Id3FieldType.TEXT), - MUSICIP_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICIP_ID, Id3FieldType.TEXT), - OCCASION(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_OCCASION, Id3FieldType.TEXT), - ORIGINAL_ALBUM(ID3v24Frames.FRAME_ID_ORIG_TITLE, Id3FieldType.TEXT), - ORIGINAL_ARTIST(ID3v24Frames.FRAME_ID_ORIGARTIST, Id3FieldType.TEXT), - ORIGINAL_LYRICIST(ID3v24Frames.FRAME_ID_ORIG_LYRICIST, Id3FieldType.TEXT), - ORIGINAL_YEAR(ID3v24Frames.FRAME_ID_ORIGINAL_RELEASE_TIME, Id3FieldType.TEXT), - QUALITY(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_QUALITY, Id3FieldType.TEXT), - RATING(ID3v24Frames.FRAME_ID_POPULARIMETER, Id3FieldType.TEXT), - RECORD_LABEL(ID3v24Frames.FRAME_ID_PUBLISHER, Id3FieldType.TEXT), - REMIXER(ID3v24Frames.FRAME_ID_REMIXED, Id3FieldType.TEXT), - SCRIPT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.SCRIPT, Id3FieldType.TEXT), - SUBTITLE(ID3v24Frames.FRAME_ID_TITLE_REFINEMENT, Id3FieldType.TEXT), - TAGS(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.TAGS, Id3FieldType.TEXT), - TEMPO(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_TEMPO, Id3FieldType.TEXT), - TITLE(ID3v24Frames.FRAME_ID_TITLE, Id3FieldType.TEXT), - TITLE_SORT(ID3v24Frames.FRAME_ID_TITLE_SORT_ORDER, Id3FieldType.TEXT), - TRACK(ID3v24Frames.FRAME_ID_TRACK, Id3FieldType.TEXT), - TRACK_TOTAL(ID3v24Frames.FRAME_ID_TRACK, Id3FieldType.TEXT), - URL_DISCOGS_ARTIST_SITE(ID3v24Frames.FRAME_ID_USER_DEFINED_URL, FrameBodyWXXX.URL_DISCOGS_ARTIST_SITE, Id3FieldType.TEXT), - URL_DISCOGS_RELEASE_SITE(ID3v24Frames.FRAME_ID_USER_DEFINED_URL, FrameBodyWXXX.URL_DISCOGS_RELEASE_SITE, Id3FieldType.TEXT), - URL_LYRICS_SITE(ID3v24Frames.FRAME_ID_USER_DEFINED_URL, FrameBodyWXXX.URL_LYRICS_SITE, Id3FieldType.TEXT), - URL_OFFICIAL_ARTIST_SITE(ID3v24Frames.FRAME_ID_URL_ARTIST_WEB, Id3FieldType.TEXT), - URL_OFFICIAL_RELEASE_SITE(ID3v24Frames.FRAME_ID_USER_DEFINED_URL, FrameBodyWXXX.URL_OFFICIAL_RELEASE_SITE, Id3FieldType.TEXT), - URL_WIKIPEDIA_ARTIST_SITE(ID3v24Frames.FRAME_ID_USER_DEFINED_URL, FrameBodyWXXX.URL_WIKIPEDIA_ARTIST_SITE, Id3FieldType.TEXT), - URL_WIKIPEDIA_RELEASE_SITE(ID3v24Frames.FRAME_ID_USER_DEFINED_URL, FrameBodyWXXX.URL_WIKIPEDIA_RELEASE_SITE, Id3FieldType.TEXT), - YEAR(ID3v24Frames.FRAME_ID_YEAR, Id3FieldType.TEXT), - ENGINEER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, FrameBodyTIPL.ENGINEER, Id3FieldType.TEXT), - PRODUCER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, FrameBodyTIPL.PRODUCER, Id3FieldType.TEXT), - MIXER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, FrameBodyTIPL.MIXER, Id3FieldType.TEXT), - DJMIXER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, FrameBodyTIPL.DJMIXER, Id3FieldType.TEXT), - ARRANGER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, FrameBodyTIPL.ARRANGER, Id3FieldType.TEXT), - ARTISTS(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS, Id3FieldType.TEXT), - ACOUSTID_FINGERPRINT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ACOUSTID_FINGERPRINT, Id3FieldType.TEXT), - ACOUSTID_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ACOUSTID_ID, Id3FieldType.TEXT), - COUNTRY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.COUNTRY, Id3FieldType.TEXT),; - - private String fieldName; - - private String frameId; - private String subId; - private Id3FieldType fieldType; - - /** - * For usual metadata fields that use a data field - * - * @param frameId the frame that will be used - * @param fieldType of data atom - */ - ID3v24FieldKey(String frameId, Id3FieldType fieldType) { - this.frameId = frameId; - this.fieldType = fieldType; - - this.fieldName = frameId; - } - - /** - * @param frameId the frame that will be used - * @param subId the additional key required within the frame to uniquely identify this key - * @param fieldType - */ - ID3v24FieldKey(String frameId, String subId, Id3FieldType fieldType) { - this.frameId = frameId; - this.subId = subId; - this.fieldType = fieldType; - - this.fieldName = frameId + ":" + subId; - } - - /** - * @return fieldtype - */ - public Id3FieldType getFieldType() { - return fieldType; - } - - /** - * This is the frame identifier used to write the field - * - * @return - */ - public String getFrameId() { - return frameId; - } - - /** - * This is the subfield used within the frame for this type of field - * - * @return subId - */ - public String getSubId() { - return subId; - } - - /** - * This is the value of the key that can uniquely identifer a key type - * - * @return - */ - public String getFieldName() { - return fieldName; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v24Frame.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v24Frame.java deleted file mode 100644 index 1d66ce2..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v24Frame.java +++ /dev/null @@ -1,964 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.FileConstants; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.logging.Hex; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.datatype.Lyrics3Line; -import org.jaudiotagger.tag.id3.framebody.*; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.lyrics3.*; -import org.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Iterator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Represents an ID3v2.4 frame. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3v24Frame.java 976 2011-06-08 10:05:34Z paultaylor $ - */ -public class ID3v24Frame extends AbstractID3v2Frame { - protected static final int FRAME_DATA_LENGTH_SIZE = 4; - protected static final int FRAME_ID_SIZE = 4; - protected static final int FRAME_FLAGS_SIZE = 2; - protected static final int FRAME_SIZE_SIZE = 4; - protected static final int FRAME_ENCRYPTION_INDICATOR_SIZE = 1; - protected static final int FRAME_GROUPING_INDICATOR_SIZE = 1; - protected static final int FRAME_HEADER_SIZE = FRAME_ID_SIZE + FRAME_SIZE_SIZE + FRAME_FLAGS_SIZE; - private static Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{3}"); - /** - * If the frame is encrypted then the encryption method is stored in this byte - */ - private int encryptionMethod; - - /** - * If the frame belongs in a group with other frames then the group identifier byte is stored - */ - private int groupIdentifier; - - public ID3v24Frame() { - } - - /** - * Creates a new ID3v2_4Frame of type identifier. An empty - * body of the correct type will be automatically created. - * This constructor should be used when wish to create a new - * frame from scratch using user input - * - * @param identifier defines the type of body to be created - */ - public ID3v24Frame(String identifier) { - //Super Constructor creates a frame with empty body of type specified - super(identifier); - statusFlags = new StatusFlags(); - encodingFlags = new EncodingFlags(); - - } - - /** - * Copy Constructor:Creates a new ID3v2_4Frame datatype based on another frame. - * - * @param frame - */ - public ID3v24Frame(ID3v24Frame frame) { - super(frame); - statusFlags = new StatusFlags(frame.getStatusFlags().getOriginalFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } - - /** - * Creates a new ID3v2_4Frame datatype based on another frame of different version - * Converts the framebody to the equivalent v24 framebody or to UnsupportedFrameBody if identifier - * is unknown. - * - * @param frame to construct a new frame from - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - public ID3v24Frame(AbstractID3v2Frame frame) throws InvalidFrameException { - //Should not be called - if ((frame instanceof ID3v24Frame)) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - //Flags - if (frame instanceof ID3v23Frame) { - statusFlags = new StatusFlags((ID3v23Frame.StatusFlags) frame.getStatusFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } else { - statusFlags = new StatusFlags(); - encodingFlags = new EncodingFlags(); - } - - // Convert Identifier. If the id was a known id for the original - // version we should be able to convert it to an v24 frame, although it may mean minor - // modification to the data. If it was not recognised originally it should remain - // unknown. - if (frame instanceof ID3v23Frame) { - createV24FrameFromV23Frame((ID3v23Frame) frame); - } else if (frame instanceof ID3v22Frame) { - ID3v23Frame v23Frame = new ID3v23Frame(frame); - createV24FrameFromV23Frame(v23Frame); - } - this.frameBody.setHeader(this); - } - - - /** - * Creates a new ID3v2_4Frame datatype based on Lyrics3. - * - * @param field - * @throws InvalidTagException - */ - public ID3v24Frame(Lyrics3v2Field field) throws InvalidTagException { - String id = field.getIdentifier(); - String value; - if (id.equals("IND")) { - throw new InvalidTagException("Cannot create ID3v2.40 frame from Lyrics3 indications field."); - } else if (id.equals("LYR")) { - FieldFrameBodyLYR lyric = (FieldFrameBodyLYR) field.getBody(); - Lyrics3Line line; - Iterator iterator = lyric.iterator(); - FrameBodySYLT sync; - FrameBodyUSLT unsync; - boolean hasTimeStamp = lyric.hasTimeStamp(); - // we'll create only one frame here. - // if there is any timestamp at all, we will create a sync'ed frame. - sync = new FrameBodySYLT((byte) 0, "ENG", (byte) 2, (byte) 1, "", new byte[0]); - unsync = new FrameBodyUSLT((byte) 0, "ENG", "", ""); - while (iterator.hasNext()) { - line = iterator.next(); - if (hasTimeStamp) { - // sync.addLyric(line); - } else { - unsync.addLyric(line); - } - } - if (hasTimeStamp) { - this.frameBody = sync; - this.frameBody.setHeader(this); - } else { - this.frameBody = unsync; - this.frameBody.setHeader(this); - } - } else if (id.equals("INF")) { - value = ((FieldFrameBodyINF) field.getBody()).getAdditionalInformation(); - this.frameBody = new FrameBodyCOMM((byte) 0, "ENG", "", value); - this.frameBody.setHeader(this); - } else if (id.equals("AUT")) { - value = ((FieldFrameBodyAUT) field.getBody()).getAuthor(); - this.frameBody = new FrameBodyTCOM((byte) 0, value); - this.frameBody.setHeader(this); - } else if (id.equals("EAL")) { - value = ((FieldFrameBodyEAL) field.getBody()).getAlbum(); - this.frameBody = new FrameBodyTALB((byte) 0, value); - this.frameBody.setHeader(this); - } else if (id.equals("EAR")) { - value = ((FieldFrameBodyEAR) field.getBody()).getArtist(); - this.frameBody = new FrameBodyTPE1((byte) 0, value); - this.frameBody.setHeader(this); - } else if (id.equals("ETT")) { - value = ((FieldFrameBodyETT) field.getBody()).getTitle(); - this.frameBody = new FrameBodyTIT2((byte) 0, value); - this.frameBody.setHeader(this); - } else if (id.equals("IMG")) { - throw new InvalidTagException("Cannot create ID3v2.40 frame from Lyrics3 image field."); - } else { - throw new InvalidTagException("Cannot caret ID3v2.40 frame from " + id + " Lyrics3 field"); - } - } - - /** - * Creates a new ID3v24Frame datatype by reading from byteBuffer. - * - * @param byteBuffer to read from - * @param loggingFilename - * @throws org.jaudiotagger.tag.InvalidFrameException - */ - public ID3v24Frame(ByteBuffer byteBuffer, String loggingFilename) throws InvalidFrameException, InvalidDataTypeException { - setLoggingFilename(loggingFilename); - read(byteBuffer); - } - - /** - * Creates a new ID3v24Frame datatype by reading from byteBuffer. - * - * @param byteBuffer to read from - * @throws org.jaudiotagger.tag.InvalidFrameException - * @deprecated use {@link #ID3v24Frame(ByteBuffer, String)} instead - */ - public ID3v24Frame(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException { - this(byteBuffer, ""); - } - - protected int getFrameIdSize() { - return FRAME_ID_SIZE; - } - - protected int getFrameSizeSize() { - return FRAME_SIZE_SIZE; - } - - protected int getFrameFlagsSize() { - return FRAME_FLAGS_SIZE; - } - - protected int getFrameHeaderSize() { - return FRAME_HEADER_SIZE; - } - - private void createV24FrameFromV23Frame(ID3v23Frame frame) throws InvalidFrameException { - // Is it a straight conversion e.g TALB - TALB - identifier = ID3Tags.convertFrameID23To24(frame.getIdentifier()); - logger.finer("Creating V24frame from v23:" + frame.getIdentifier() + ":" + identifier); - - - //We cant convert unsupported bodies properly - if (frame.getBody() instanceof FrameBodyUnsupported) { - this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frame.getIdentifier(); - logger.finer("V3:UnsupportedBody:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - }//Simple Copy - else if (identifier != null) { - //Special Case - if ((frame.getIdentifier().equals(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO)) && (((FrameBodyTXXX) frame.getBody()).getDescription().equals(FrameBodyTXXX.MOOD))) { - this.frameBody = new FrameBodyTMOO((FrameBodyTXXX) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frameBody.getIdentifier(); - } else { - logger.finer("V3:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = (AbstractTagFrameBody) ID3Tags.copyObject(frame.getBody()); - this.frameBody.setHeader(this); - } - } - // Is it a known v3 frame which needs forcing to v4 frame e.g. TYER - TDRC - else if (ID3Tags.isID3v23FrameIdentifier(frame.getIdentifier())) { - identifier = ID3Tags.forceFrameID23To24(frame.getIdentifier()); - if (identifier != null) { - logger.config("V3:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody()); - this.frameBody.setHeader(this); - } - // No mechanism exists to convert it to a v24 frame, e.g deprecated frame e.g TSIZ, so hold - // as a deprecated frame consisting of an array of bytes*/ - else { - this.frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frame.getIdentifier(); - logger.finer("V3:Deprecated:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - } - } - // Unknown Frame e.g NCON or TDRL (because TDRL unknown to V23) - else { - this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody()); - this.frameBody.setHeader(this); - identifier = frame.getIdentifier(); - logger.finer("V3:Unknown:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier); - } - } - - /** - * @param obj - * @return if obj is equivalent to this frame - */ - public boolean equals(Object obj) { - - if (this == obj) return true; - - if (!(obj instanceof ID3v24Frame)) { - return false; - } - ID3v24Frame that = (ID3v24Frame) obj; - - - return EqualsUtil.areEqual(this.statusFlags, that.statusFlags) && EqualsUtil.areEqual(this.encodingFlags, that.encodingFlags) && super.equals(that); - } - - - /** - * Return size of frame - * - * @return int frame size - */ - public int getSize() { - return frameBody.getSize() + ID3v24Frame.FRAME_HEADER_SIZE; - } - - /** - * If frame is greater than certain size it will be decoded differently if unsynchronized to if synchronized - * Frames with certain byte sequences should be unsynchronized but sometimes editors do not - * unsynchronize them so this method checks both cases and goes with the option that fits best with the data - * - * @param byteBuffer - * @throws InvalidFrameException - */ - private void checkIfFrameSizeThatIsNotSyncSafe(ByteBuffer byteBuffer) - throws InvalidFrameException { - if (frameSize > ID3SyncSafeInteger.MAX_SAFE_SIZE) { - //Set Just after size field this is where we want to be when we leave this if statement - int currentPosition = byteBuffer.position(); - - //Read as nonsync safe integer - byteBuffer.position(currentPosition - getFrameIdSize()); - int nonSyncSafeFrameSize = byteBuffer.getInt(); - - //Is the frame size syncsafe, should always be BUT some encoders such as Itunes do not do it properly - //so do an easy check now. - byteBuffer.position(currentPosition - getFrameIdSize()); - boolean isNotSyncSafe = ID3SyncSafeInteger.isBufferNotSyncSafe(byteBuffer); - - //not relative so need to move position - byteBuffer.position(currentPosition); - - if (isNotSyncSafe) { - logger.warning(getLoggingFilename() + ":" + "Frame size is NOT stored as a sync safe integer:" + identifier); - - //This will return a larger frame size so need to check against buffer size if too large then we are - //buggered , give up - if (nonSyncSafeFrameSize > (byteBuffer.remaining() - -getFrameFlagsSize())) { - logger.warning(getLoggingFilename() + ":" + "Invalid Frame size larger than size before mp3 audio:" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame"); - } else { - frameSize = nonSyncSafeFrameSize; - } - } else { - //appears to be sync safe but lets look at the bytes just after the reported end of this - //frame to see if find a valid frame header - - //Read the Frame Identifier - byte[] readAheadbuffer = new byte[getFrameIdSize()]; - byteBuffer.position(currentPosition + frameSize + getFrameFlagsSize()); - - if (byteBuffer.remaining() < getFrameIdSize()) { - //There is no padding or framedata we are at end so assume syncsafe - //reset position to just after framesize - byteBuffer.position(currentPosition); - } else { - byteBuffer.get(readAheadbuffer, 0, getFrameIdSize()); - - //reset position to just after framesize - byteBuffer.position(currentPosition); - - String readAheadIdentifier = new String(readAheadbuffer); - if (isValidID3v2FrameIdentifier(readAheadIdentifier)) { - //Everything ok, so continue - } else if (ID3SyncSafeInteger.isBufferEmpty(readAheadbuffer)) { - //no data found so assume entered padding in which case assume it is last - //frame and we are ok - } - //haven't found identifier so maybe not syncsafe or maybe there are no more frames, just padding - else { - //Ok lets try using a non-syncsafe integer - - //size returned will be larger so is it valid - if (nonSyncSafeFrameSize > byteBuffer.remaining() - getFrameFlagsSize()) { - //invalid so assume syncsafe - byteBuffer.position(currentPosition); - } else { - readAheadbuffer = new byte[getFrameIdSize()]; - byteBuffer.position(currentPosition + nonSyncSafeFrameSize + getFrameFlagsSize()); - - if (byteBuffer.remaining() >= getFrameIdSize()) { - byteBuffer.get(readAheadbuffer, 0, getFrameIdSize()); - readAheadIdentifier = new String(readAheadbuffer); - - //reset position to just after framesize - byteBuffer.position(currentPosition); - - //ok found a valid identifier using non-syncsafe so assume non-syncsafe size - //and continue - if (isValidID3v2FrameIdentifier(readAheadIdentifier)) { - frameSize = nonSyncSafeFrameSize; - logger.warning(getLoggingFilename() + ":" + "Assuming frame size is NOT stored as a sync safe integer:" + identifier); - } - //no data found so assume entered padding in which case assume it is last - //frame and we are ok whereas we didn't hit padding when using syncsafe integer - //or we wouldn't have got to this point. So assume syncsafe integer ended within - //the frame data whereas this has reached end of frames. - else if (ID3SyncSafeInteger.isBufferEmpty(readAheadbuffer)) { - frameSize = nonSyncSafeFrameSize; - logger.warning(getLoggingFilename() + ":" + "Assuming frame size is NOT stored as a sync safe integer:" + identifier); - } - //invalid so assume syncsafe as that is is the standard - else { - - } - } else { - //reset position to just after framesize - byteBuffer.position(currentPosition); - - //If the unsync framesize matches exactly the remaining bytes then assume it has the - //correct size for the last frame - if (byteBuffer.remaining() == 0) { - frameSize = nonSyncSafeFrameSize; - } - //Inconclusive stick with syncsafe - else { - } - } - } - } - } - } - } - } - - /** - * Read the frame size form the header, check okay , if not try to fix - * or just throw exception - * - * @param byteBuffer - * @throws InvalidFrameException - */ - private void getFrameSize(ByteBuffer byteBuffer) - throws InvalidFrameException { - //Read frame size as syncsafe integer - frameSize = ID3SyncSafeInteger.bufferToValue(byteBuffer); - - if (frameSize < 0) { - logger.warning(getLoggingFilename() + ":" + "Invalid Frame size:" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame"); - } else if (frameSize == 0) { - logger.warning(getLoggingFilename() + ":" + "Empty Frame:" + identifier); - //We dont process this frame or add to framemap becuase contains no useful information - //Skip the two flag bytes so in correct position for subsequent frames - byteBuffer.get(); - byteBuffer.get(); - throw new EmptyFrameException(identifier + " is empty frame"); - } else if (frameSize > (byteBuffer.remaining() - FRAME_FLAGS_SIZE)) { - logger.warning(getLoggingFilename() + ":" + "Invalid Frame size larger than size before mp3 audio:" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame"); - } - - checkIfFrameSizeThatIsNotSyncSafe(byteBuffer); - } - - /** - * Read the frame from the specified file. - * Read the frame header then delegate reading of data to frame body. - * - * @param byteBuffer to read the frame from - */ - public void read(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException { - String identifier = readIdentifier(byteBuffer); - - //Is this a valid identifier? - if (!isValidID3v2FrameIdentifier(identifier)) { - //If not valid move file pointer back to one byte after - //the original check so can try again. - logger.config(getLoggingFilename() + ":" + "Invalid identifier:" + identifier); - byteBuffer.position(byteBuffer.position() - (getFrameIdSize() - 1)); - throw new InvalidFrameIdentifierException(getLoggingFilename() + ":" + identifier + ":is not a valid ID3v2.30 frame"); - } - - //Get the frame size, adjusted as necessary - getFrameSize(byteBuffer); - - //Read the flag bytes - statusFlags = new StatusFlags(byteBuffer.get()); - encodingFlags = new EncodingFlags(byteBuffer.get()); - - //Read extra bits appended to frame header for various encodings - //These are not included in header size but are included in frame size but wont be read when we actually - //try to read the frame body data - int extraHeaderBytesCount = 0; - int dataLengthSize = -1; - if (((EncodingFlags) encodingFlags).isGrouping()) { - extraHeaderBytesCount = ID3v24Frame.FRAME_GROUPING_INDICATOR_SIZE; - groupIdentifier = byteBuffer.get(); - } - - if (((EncodingFlags) encodingFlags).isEncryption()) { - //Read the Encryption byte, but do nothing with it - extraHeaderBytesCount += ID3v24Frame.FRAME_ENCRYPTION_INDICATOR_SIZE; - encryptionMethod = byteBuffer.get(); - } - - if (((EncodingFlags) encodingFlags).isDataLengthIndicator()) { - //Read the sync safe size field - dataLengthSize = ID3SyncSafeInteger.bufferToValue(byteBuffer); - extraHeaderBytesCount += FRAME_DATA_LENGTH_SIZE; - logger.config(getLoggingFilename() + ":" + "Frame Size Is:" + frameSize + " Data Length Size:" + dataLengthSize); - } - - //Work out the real size of the frameBody data - int realFrameSize = frameSize - extraHeaderBytesCount; - - //Create Buffer that only contains the body of this frame rather than the remainder of tag - ByteBuffer frameBodyBuffer = byteBuffer.slice(); - frameBodyBuffer.limit(realFrameSize); - - //Do we need to synchronize the frame body - int syncSize = realFrameSize; - if (((EncodingFlags) encodingFlags).isUnsynchronised()) { - //We only want to synchronize the buffer up to the end of this frame (remember this - //buffer contains the remainder of this tag not just this frame), and we cannot just - //create a new buffer because when this method returns the position of the buffer is used - //to look for the next frame, so we need to modify the buffer. The action of synchronizing causes - //bytes to be dropped so the existing buffer is large enough to hold the modifications - frameBodyBuffer = ID3Unsynchronization.synchronize(frameBodyBuffer); - syncSize = frameBodyBuffer.limit(); - logger.config(getLoggingFilename() + ":" + "Frame Size After Syncing is:" + syncSize); - } - - //Read the body data - try { - if (((EncodingFlags) encodingFlags).isCompression()) { - frameBodyBuffer = ID3Compression.uncompress(identifier, getLoggingFilename(), byteBuffer, dataLengthSize, realFrameSize); - frameBody = readBody(identifier, frameBodyBuffer, dataLengthSize); - } else if (((EncodingFlags) encodingFlags).isEncryption()) { - frameBodyBuffer = byteBuffer.slice(); - frameBodyBuffer.limit(realFrameSize); - frameBody = readEncryptedBody(identifier, byteBuffer, frameSize); - } else { - frameBody = readBody(identifier, frameBodyBuffer, syncSize); - } - if (!(frameBody instanceof ID3v24FrameBody)) { - logger.config(getLoggingFilename() + ":" + "Converted frame body with:" + identifier + " to deprecated framebody"); - frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody) frameBody); - } - } finally { - //Update position of main buffer, so no attempt is made to reread these bytes - byteBuffer.position(byteBuffer.position() + realFrameSize); - } - } - - /** - * Write the frame. Writes the frame header but writing the data is delegated to the - * frame body. - * - * @throws IOException - */ - public void write(ByteArrayOutputStream tagBuffer) { - boolean unsynchronization; - - logger.config("Writing frame to file:" + getIdentifier()); - - //This is where we will write header, move position to where we can - //write bodybuffer - ByteBuffer headerBuffer = ByteBuffer.allocate(FRAME_HEADER_SIZE); - - //Write Frame Body Data to a new stream - ByteArrayOutputStream bodyOutputStream = new ByteArrayOutputStream(); - ((AbstractID3v2FrameBody) frameBody).write(bodyOutputStream); - - //Does it need unsynchronizing, and are we allowing unsychronizing - byte[] bodyBuffer = bodyOutputStream.toByteArray(); - unsynchronization = TagOptionSingleton.getInstance().isUnsyncTags() && ID3Unsynchronization.requiresUnsynchronization(bodyBuffer); - if (unsynchronization) { - bodyBuffer = ID3Unsynchronization.unsynchronize(bodyBuffer); - logger.config("bodybytebuffer:sizeafterunsynchronisation:" + bodyBuffer.length); - } - - //Write Frame Header - //Write Frame ID, the identifier must be 4 bytes bytes long it may not be - //because converted an unknown v2.2 id (only 3 bytes long) - if (getIdentifier().length() == 3) { - identifier = identifier + ' '; - } - headerBuffer.put(Utils.getDefaultBytes(getIdentifier(), "ISO-8859-1"), 0, FRAME_ID_SIZE); - - //Write Frame Size based on size of body buffer (if it has been unsynced then it size - //will have increased accordingly - int size = bodyBuffer.length; - logger.fine("Frame Size Is:" + size); - headerBuffer.put(ID3SyncSafeInteger.valueToBuffer(size)); - - //Write the Flags - //Status Flags:leave as they were when we read - headerBuffer.put(statusFlags.getWriteFlags()); - - //Remove any non standard flags - ((ID3v24Frame.EncodingFlags) encodingFlags).unsetNonStandardFlags(); - - //Encoding we only support unsynchronization - if (unsynchronization) { - ((ID3v24Frame.EncodingFlags) encodingFlags).setUnsynchronised(); - } else { - ((ID3v24Frame.EncodingFlags) encodingFlags).unsetUnsynchronised(); - } - //These are not currently supported on write - ((ID3v24Frame.EncodingFlags) encodingFlags).unsetCompression(); - ((ID3v24Frame.EncodingFlags) encodingFlags).unsetDataLengthIndicator(); - headerBuffer.put(encodingFlags.getFlags()); - - try { - //Add header to the Byte Array Output Stream - tagBuffer.write(headerBuffer.array()); - - if (((EncodingFlags) encodingFlags).isEncryption()) { - tagBuffer.write(encryptionMethod); - } - - if (((EncodingFlags) encodingFlags).isGrouping()) { - tagBuffer.write(groupIdentifier); - } - - //Add bodybuffer to the Byte Array Output Stream - tagBuffer.write(bodyBuffer); - } catch (IOException ioe) { - //This could never happen coz not writing to file, so convert to RuntimeException - throw new RuntimeException(ioe); - } - } - - /** - * Get Status Flags Object - */ - public AbstractID3v2Frame.StatusFlags getStatusFlags() { - return statusFlags; - } - - /** - * Get Encoding Flags Object - */ - public AbstractID3v2Frame.EncodingFlags getEncodingFlags() { - return encodingFlags; - } - - public int getEncryptionMethod() { - return encryptionMethod; - } - - public int getGroupIdentifier() { - return groupIdentifier; - } - - /** - * Does the frame identifier meet the syntax for a idv3v2 frame identifier. - * must start with a capital letter and only contain capital letters and numbers - * - * @param identifier to be checked - * @return whether the identifier is valid - */ - public boolean isValidID3v2FrameIdentifier(String identifier) { - Matcher m = ID3v24Frame.validFrameIdentifier.matcher(identifier); - return m.matches(); - } - - /** - * Return String Representation of body - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FRAME, getIdentifier()); - MP3File.getStructureFormatter().addElement(TYPE_FRAME_SIZE, frameSize); - statusFlags.createStructure(); - encodingFlags.createStructure(); - frameBody.createStructure(); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FRAME); - } - - /** - * @return true if considered a common frame - */ - public boolean isCommon() { - return ID3v24Frames.getInstanceOf().isCommon(getId()); - } - - /** - * @return true if considered a common frame - */ - public boolean isBinary() { - return ID3v24Frames.getInstanceOf().isBinary(getId()); - } - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - public void setEncoding(String encoding) { - Integer encodingId = TextEncoding.getInstanceOf().getIdForValue(encoding); - if (encoding != null) { - if (encodingId < 4) { - this.getBody().setTextEncoding(encodingId.byteValue()); - } - } - } - - /** - * Member Class This represents a frame headers Status Flags - * Make adjustments if necessary based on frame type and specification. - */ - class StatusFlags extends AbstractID3v2Frame.StatusFlags { - public static final String TYPE_TAGALTERPRESERVATION = "typeTagAlterPreservation"; - public static final String TYPE_FILEALTERPRESERVATION = "typeFileAlterPreservation"; - public static final String TYPE_READONLY = "typeReadOnly"; - - - /** - * Discard frame if tag altered - */ - public static final int MASK_TAG_ALTER_PRESERVATION = FileConstants.BIT6; - - /** - * Discard frame if audio part of file altered - */ - public static final int MASK_FILE_ALTER_PRESERVATION = FileConstants.BIT5; - - /** - * Frame tagged as read only - */ - public static final int MASK_READ_ONLY = FileConstants.BIT4; - - /** - * Use this when creating a frame from scratch - */ - StatusFlags() { - super(); - } - - /** - * Use this constructor when reading from file or from another v4 frame - * - * @param flags - */ - StatusFlags(byte flags) { - originalFlags = flags; - writeFlags = flags; - modifyFlags(); - } - - /** - * Use this constructor when convert a v23 frame - * - * @param statusFlags - */ - StatusFlags(ID3v23Frame.StatusFlags statusFlags) { - originalFlags = convertV3ToV4Flags(statusFlags.getOriginalFlags()); - writeFlags = originalFlags; - modifyFlags(); - } - - /** - * Convert V3 Flags to equivalent V4 Flags - * - * @param v3Flag - * @return - */ - private byte convertV3ToV4Flags(byte v3Flag) { - byte v4Flag = (byte) 0; - if ((v3Flag & ID3v23Frame.StatusFlags.MASK_FILE_ALTER_PRESERVATION) != 0) { - v4Flag |= (byte) MASK_FILE_ALTER_PRESERVATION; - } - if ((v3Flag & ID3v23Frame.StatusFlags.MASK_TAG_ALTER_PRESERVATION) != 0) { - v4Flag |= (byte) MASK_TAG_ALTER_PRESERVATION; - } - return v4Flag; - } - - /** - * Makes modifications to flags based on specification and frameid - */ - protected void modifyFlags() { - String str = getIdentifier(); - if (ID3v24Frames.getInstanceOf().isDiscardIfFileAltered(str)) { - writeFlags |= (byte) MASK_FILE_ALTER_PRESERVATION; - writeFlags &= (byte) ~MASK_TAG_ALTER_PRESERVATION; - } else { - writeFlags &= (byte) ~MASK_FILE_ALTER_PRESERVATION; - writeFlags &= (byte) ~MASK_TAG_ALTER_PRESERVATION; - } - } - - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FLAGS, ""); - MP3File.getStructureFormatter().addElement(TYPE_TAGALTERPRESERVATION, originalFlags & MASK_TAG_ALTER_PRESERVATION); - MP3File.getStructureFormatter().addElement(TYPE_FILEALTERPRESERVATION, originalFlags & MASK_FILE_ALTER_PRESERVATION); - MP3File.getStructureFormatter().addElement(TYPE_READONLY, originalFlags & MASK_READ_ONLY); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FLAGS); - } - - - } - - /** - * This represents a frame headers Encoding Flags - */ - class EncodingFlags extends AbstractID3v2Frame.EncodingFlags { - public static final String TYPE_COMPRESSION = "compression"; - public static final String TYPE_ENCRYPTION = "encryption"; - public static final String TYPE_GROUPIDENTITY = "groupidentity"; - public static final String TYPE_FRAMEUNSYNCHRONIZATION = "frameUnsynchronisation"; - public static final String TYPE_DATALENGTHINDICATOR = "dataLengthIndicator"; - - /** - * Frame is part of a group - */ - public static final int MASK_GROUPING_IDENTITY = FileConstants.BIT6; - - /** - * Frame is compressed - */ - public static final int MASK_COMPRESSION = FileConstants.BIT3; - - /** - * Frame is encrypted - */ - public static final int MASK_ENCRYPTION = FileConstants.BIT2; - - /** - * Unsynchronisation - */ - public static final int MASK_FRAME_UNSYNCHRONIZATION = FileConstants.BIT1; - - /** - * Length - */ - public static final int MASK_DATA_LENGTH_INDICATOR = FileConstants.BIT0; - - /** - * Use this when creating a frame from scratch - */ - EncodingFlags() { - super(); - } - - /** - * Use this when creating a frame from existing flags in another v4 frame - * - * @param flags - */ - EncodingFlags(byte flags) { - super(flags); - logEnabledFlags(); - } - - public void logEnabledFlags() { - if (isNonStandardFlags()) { - logger.warning(getLoggingFilename() + ":" + identifier + ":Unknown Encoding Flags:" + Hex.asHex(flags)); - } - if (isCompression()) { - logger.warning(ErrorMessage.MP3_FRAME_IS_COMPRESSED.getMsg(getLoggingFilename(), identifier)); - } - - if (isEncryption()) { - logger.warning(ErrorMessage.MP3_FRAME_IS_ENCRYPTED.getMsg(getLoggingFilename(), identifier)); - } - - if (isGrouping()) { - logger.config(ErrorMessage.MP3_FRAME_IS_GROUPED.getMsg(getLoggingFilename(), identifier)); - } - - if (isUnsynchronised()) { - logger.config(ErrorMessage.MP3_FRAME_IS_UNSYNCHRONISED.getMsg(getLoggingFilename(), identifier)); - } - - if (isDataLengthIndicator()) { - logger.config(ErrorMessage.MP3_FRAME_IS_DATA_LENGTH_INDICATOR.getMsg(getLoggingFilename(), identifier)); - } - } - - public byte getFlags() { - return flags; - } - - public boolean isCompression() { - return (flags & MASK_COMPRESSION) > 0; - } - - public boolean isEncryption() { - return (flags & MASK_ENCRYPTION) > 0; - } - - public boolean isGrouping() { - return (flags & MASK_GROUPING_IDENTITY) > 0; - } - - public boolean isUnsynchronised() { - return (flags & MASK_FRAME_UNSYNCHRONIZATION) > 0; - } - - public boolean isDataLengthIndicator() { - return (flags & MASK_DATA_LENGTH_INDICATOR) > 0; - } - - public void setCompression() { - flags |= MASK_COMPRESSION; - } - - public void setEncryption() { - flags |= MASK_ENCRYPTION; - } - - public void setGrouping() { - flags |= MASK_GROUPING_IDENTITY; - } - - public void setUnsynchronised() { - flags |= MASK_FRAME_UNSYNCHRONIZATION; - } - - public void setDataLengthIndicator() { - flags |= MASK_DATA_LENGTH_INDICATOR; - } - - public void unsetCompression() { - flags &= (byte) ~MASK_COMPRESSION; - } - - public void unsetEncryption() { - flags &= (byte) ~MASK_ENCRYPTION; - } - - public void unsetGrouping() { - flags &= (byte) ~MASK_GROUPING_IDENTITY; - } - - public void unsetUnsynchronised() { - flags &= (byte) ~MASK_FRAME_UNSYNCHRONIZATION; - } - - public void unsetDataLengthIndicator() { - flags &= (byte) ~MASK_DATA_LENGTH_INDICATOR; - } - - public boolean isNonStandardFlags() { - return ((flags & FileConstants.BIT7) > 0) || - ((flags & FileConstants.BIT5) > 0) || - ((flags & FileConstants.BIT4) > 0); - } - - public void unsetNonStandardFlags() { - if (isNonStandardFlags()) { - logger.warning(getLoggingFilename() + ":" + getIdentifier() + ":Unsetting Unknown Encoding Flags:" + Hex.asHex(flags)); - flags &= (byte) ~FileConstants.BIT7; - flags &= (byte) ~FileConstants.BIT5; - flags &= (byte) ~FileConstants.BIT4; - } - } - - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_FLAGS, ""); - MP3File.getStructureFormatter().addElement(TYPE_COMPRESSION, flags & MASK_COMPRESSION); - MP3File.getStructureFormatter().addElement(TYPE_ENCRYPTION, flags & MASK_ENCRYPTION); - MP3File.getStructureFormatter().addElement(TYPE_GROUPIDENTITY, flags & MASK_GROUPING_IDENTITY); - MP3File.getStructureFormatter().addElement(TYPE_FRAMEUNSYNCHRONIZATION, flags & MASK_FRAME_UNSYNCHRONIZATION); - MP3File.getStructureFormatter().addElement(TYPE_DATALENGTHINDICATOR, flags & MASK_DATA_LENGTH_INDICATOR); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_FLAGS); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v24Frames.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v24Frames.java deleted file mode 100644 index b69ff62..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v24Frames.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Jaudiotagger Copyright (C)2004,2005 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.tag.FieldKey; - -import java.util.EnumMap; -import java.util.Map; - -/** - * Defines ID3v24 frames and collections that categorise frames. - *

    - *

    You can include frames here that are not officially supported as long as they can be used within an - * ID3v24Tag - * - * @author Paul Taylor - * @version $Id: ID3v24Frames.java 1081 2013-01-04 20:09:36Z paultaylor $ - */ -public class ID3v24Frames extends ID3Frames { - /** - * Frame IDs beginning with T are text frames, & with W are url frames - */ - public static final String FRAME_ID_ACCOMPANIMENT = "TPE2"; - public static final String FRAME_ID_ALBUM = "TALB"; - public static final String FRAME_ID_ALBUM_SORT_ORDER = "TSOA"; - public static final String FRAME_ID_ARTIST = "TPE1"; - public static final String FRAME_ID_ATTACHED_PICTURE = "APIC"; - public static final String FRAME_ID_AUDIO_ENCRYPTION = "AENC"; - public static final String FRAME_ID_AUDIO_SEEK_POINT_INDEX = "ASPI"; - public static final String FRAME_ID_BPM = "TBPM"; - public static final String FRAME_ID_COMMENT = "COMM"; - public static final String FRAME_ID_COMMERCIAL_FRAME = "COMR"; - public static final String FRAME_ID_COMPOSER = "TCOM"; - public static final String FRAME_ID_CONDUCTOR = "TPE3"; - public static final String FRAME_ID_CONTENT_GROUP_DESC = "TIT1"; - public static final String FRAME_ID_COPYRIGHTINFO = "TCOP"; - public static final String FRAME_ID_ENCODEDBY = "TENC"; - public static final String FRAME_ID_ENCODING_TIME = "TDEN"; - public static final String FRAME_ID_ENCRYPTION = "ENCR"; - public static final String FRAME_ID_EQUALISATION2 = "EQU2"; - public static final String FRAME_ID_EVENT_TIMING_CODES = "ETCO"; - public static final String FRAME_ID_FILE_OWNER = "TOWN"; - public static final String FRAME_ID_FILE_TYPE = "TFLT"; - public static final String FRAME_ID_GENERAL_ENCAPS_OBJECT = "GEOB"; - public static final String FRAME_ID_GENRE = "TCON"; - public static final String FRAME_ID_GROUP_ID_REG = "GRID"; - public static final String FRAME_ID_HW_SW_SETTINGS = "TSSE"; - public static final String FRAME_ID_INITIAL_KEY = "TKEY"; - public static final String FRAME_ID_INVOLVED_PEOPLE = "TIPL"; - public static final String FRAME_ID_ISRC = "TSRC"; - public static final String FRAME_ID_LANGUAGE = "TLAN"; - public static final String FRAME_ID_LENGTH = "TLEN"; - public static final String FRAME_ID_LINKED_INFO = "LINK"; - public static final String FRAME_ID_LYRICIST = "TEXT"; - public static final String FRAME_ID_MEDIA_TYPE = "TMED"; - public static final String FRAME_ID_MOOD = "TMOO"; - public static final String FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE = "MLLT"; - public static final String FRAME_ID_MUSICIAN_CREDITS = "TMCL"; - public static final String FRAME_ID_MUSIC_CD_ID = "MCDI"; - public static final String FRAME_ID_ORIGARTIST = "TOPE"; - public static final String FRAME_ID_ORIGINAL_RELEASE_TIME = "TDOR"; - public static final String FRAME_ID_ORIG_FILENAME = "TOFN"; - public static final String FRAME_ID_ORIG_LYRICIST = "TOLY"; - public static final String FRAME_ID_ORIG_TITLE = "TOAL"; - public static final String FRAME_ID_OWNERSHIP = "OWNE"; - public static final String FRAME_ID_ARTIST_SORT_ORDER = "TSOP"; - public static final String FRAME_ID_PLAYLIST_DELAY = "TDLY"; - public static final String FRAME_ID_PLAY_COUNTER = "PCNT"; - public static final String FRAME_ID_POPULARIMETER = "POPM"; - public static final String FRAME_ID_POSITION_SYNC = "POSS"; - public static final String FRAME_ID_PRIVATE = "PRIV"; - public static final String FRAME_ID_PRODUCED_NOTICE = "TPRO"; - public static final String FRAME_ID_PUBLISHER = "TPUB"; - public static final String FRAME_ID_RADIO_NAME = "TRSN"; - public static final String FRAME_ID_RADIO_OWNER = "TRSO"; - public static final String FRAME_ID_RECOMMENDED_BUFFER_SIZE = "RBUF"; - public static final String FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2 = "RVA2"; - public static final String FRAME_ID_RELEASE_TIME = "TDRL"; - public static final String FRAME_ID_REMIXED = "TPE4"; - public static final String FRAME_ID_REVERB = "RVRB"; - public static final String FRAME_ID_SEEK = "SEEK"; - public static final String FRAME_ID_SET = "TPOS"; - public static final String FRAME_ID_SET_SUBTITLE = "TSST"; - public static final String FRAME_ID_SIGNATURE = "SIGN"; - public static final String FRAME_ID_SYNC_LYRIC = "SYLT"; - public static final String FRAME_ID_SYNC_TEMPO = "SYTC"; - public static final String FRAME_ID_TAGGING_TIME = "TDTG"; - public static final String FRAME_ID_TERMS_OF_USE = "USER"; - public static final String FRAME_ID_TITLE = "TIT2"; - public static final String FRAME_ID_TITLE_REFINEMENT = "TIT3"; - public static final String FRAME_ID_TITLE_SORT_ORDER = "TSOT"; - public static final String FRAME_ID_TRACK = "TRCK"; - public static final String FRAME_ID_UNIQUE_FILE_ID = "UFID"; - public static final String FRAME_ID_UNSYNC_LYRICS = "USLT"; - public static final String FRAME_ID_URL_ARTIST_WEB = "WOAR"; - public static final String FRAME_ID_URL_COMMERCIAL = "WCOM"; - public static final String FRAME_ID_URL_COPYRIGHT = "WCOP"; - public static final String FRAME_ID_URL_FILE_WEB = "WOAF"; - public static final String FRAME_ID_URL_OFFICIAL_RADIO = "WORS"; - public static final String FRAME_ID_URL_PAYMENT = "WPAY"; - public static final String FRAME_ID_URL_PUBLISHERS = "WPUB"; - public static final String FRAME_ID_URL_SOURCE_WEB = "WOAS"; - public static final String FRAME_ID_USER_DEFINED_INFO = "TXXX"; - public static final String FRAME_ID_USER_DEFINED_URL = "WXXX"; - public static final String FRAME_ID_YEAR = "TDRC"; - - public static final String FRAME_ID_ALBUM_ARTIST_SORT_ORDER_ITUNES = "TSO2"; - public static final String FRAME_ID_COMPOSER_SORT_ORDER_ITUNES = "TSOC"; - public static final String FRAME_ID_IS_COMPILATION = "TCMP"; - - //TODO this is temporary to provide backwards compatability - public static final String FRAME_ID_PERFORMER_SORT_OWNER = FRAME_ID_ARTIST_SORT_ORDER; - public static final String FRAME_ID_TITLE_SORT_OWNER = FRAME_ID_TITLE_SORT_ORDER; - private static ID3v24Frames id3v24Frames; - protected EnumMap tagFieldToId3 = new EnumMap(FieldKey.class); - /** - * Maps from ID3 key to Generic key - */ - protected EnumMap id3ToTagField = new EnumMap(ID3v24FieldKey.class); - - private ID3v24Frames() { - supportedFrames.add(FRAME_ID_ACCOMPANIMENT); - supportedFrames.add(FRAME_ID_ALBUM); - supportedFrames.add(FRAME_ID_ALBUM_SORT_ORDER); - supportedFrames.add(FRAME_ID_ARTIST); - supportedFrames.add(FRAME_ID_ATTACHED_PICTURE); - supportedFrames.add(FRAME_ID_AUDIO_ENCRYPTION); - supportedFrames.add(FRAME_ID_AUDIO_SEEK_POINT_INDEX); - supportedFrames.add(FRAME_ID_BPM); - supportedFrames.add(FRAME_ID_COMMENT); - supportedFrames.add(FRAME_ID_COMMERCIAL_FRAME); - supportedFrames.add(FRAME_ID_COMPOSER); - supportedFrames.add(FRAME_ID_CONDUCTOR); - supportedFrames.add(FRAME_ID_CONTENT_GROUP_DESC); - supportedFrames.add(FRAME_ID_COPYRIGHTINFO); - supportedFrames.add(FRAME_ID_ENCODEDBY); - supportedFrames.add(FRAME_ID_ENCODING_TIME); - supportedFrames.add(FRAME_ID_ENCRYPTION); - supportedFrames.add(FRAME_ID_EQUALISATION2); - supportedFrames.add(FRAME_ID_EVENT_TIMING_CODES); - supportedFrames.add(FRAME_ID_FILE_OWNER); - supportedFrames.add(FRAME_ID_FILE_TYPE); - supportedFrames.add(FRAME_ID_GENERAL_ENCAPS_OBJECT); - supportedFrames.add(FRAME_ID_GENRE); - supportedFrames.add(FRAME_ID_GROUP_ID_REG); - supportedFrames.add(FRAME_ID_HW_SW_SETTINGS); - supportedFrames.add(FRAME_ID_INITIAL_KEY); - supportedFrames.add(FRAME_ID_INVOLVED_PEOPLE); - supportedFrames.add(FRAME_ID_ISRC); - supportedFrames.add(FRAME_ID_LANGUAGE); - supportedFrames.add(FRAME_ID_LENGTH); - supportedFrames.add(FRAME_ID_LINKED_INFO); - supportedFrames.add(FRAME_ID_LYRICIST); - supportedFrames.add(FRAME_ID_MEDIA_TYPE); - supportedFrames.add(FRAME_ID_MOOD); - supportedFrames.add(FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE); - supportedFrames.add(FRAME_ID_MUSIC_CD_ID); - supportedFrames.add(FRAME_ID_ORIGARTIST); - supportedFrames.add(FRAME_ID_ORIGINAL_RELEASE_TIME); - supportedFrames.add(FRAME_ID_ORIG_FILENAME); - supportedFrames.add(FRAME_ID_ORIG_LYRICIST); - supportedFrames.add(FRAME_ID_ORIG_TITLE); - supportedFrames.add(FRAME_ID_OWNERSHIP); - supportedFrames.add(FRAME_ID_ARTIST_SORT_ORDER); - supportedFrames.add(FRAME_ID_PLAYLIST_DELAY); - supportedFrames.add(FRAME_ID_PLAY_COUNTER); - supportedFrames.add(FRAME_ID_POPULARIMETER); - supportedFrames.add(FRAME_ID_POSITION_SYNC); - supportedFrames.add(FRAME_ID_PRIVATE); - supportedFrames.add(FRAME_ID_PRODUCED_NOTICE); - supportedFrames.add(FRAME_ID_PUBLISHER); - supportedFrames.add(FRAME_ID_RADIO_NAME); - supportedFrames.add(FRAME_ID_RADIO_OWNER); - supportedFrames.add(FRAME_ID_RECOMMENDED_BUFFER_SIZE); - supportedFrames.add(FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2); - supportedFrames.add(FRAME_ID_RELEASE_TIME); - supportedFrames.add(FRAME_ID_REMIXED); - supportedFrames.add(FRAME_ID_REVERB); - supportedFrames.add(FRAME_ID_SEEK); - supportedFrames.add(FRAME_ID_SET); - supportedFrames.add(FRAME_ID_SET_SUBTITLE); - supportedFrames.add(FRAME_ID_SIGNATURE); - supportedFrames.add(FRAME_ID_SYNC_LYRIC); - supportedFrames.add(FRAME_ID_SYNC_TEMPO); - supportedFrames.add(FRAME_ID_TAGGING_TIME); - supportedFrames.add(FRAME_ID_TERMS_OF_USE); - supportedFrames.add(FRAME_ID_TITLE); - supportedFrames.add(FRAME_ID_TITLE_REFINEMENT); - supportedFrames.add(FRAME_ID_TITLE_SORT_ORDER); - supportedFrames.add(FRAME_ID_TRACK); - supportedFrames.add(FRAME_ID_UNIQUE_FILE_ID); - supportedFrames.add(FRAME_ID_UNSYNC_LYRICS); - supportedFrames.add(FRAME_ID_URL_ARTIST_WEB); - supportedFrames.add(FRAME_ID_URL_COMMERCIAL); - supportedFrames.add(FRAME_ID_URL_COPYRIGHT); - supportedFrames.add(FRAME_ID_URL_FILE_WEB); - supportedFrames.add(FRAME_ID_URL_OFFICIAL_RADIO); - supportedFrames.add(FRAME_ID_URL_PAYMENT); - supportedFrames.add(FRAME_ID_URL_PUBLISHERS); - supportedFrames.add(FRAME_ID_URL_SOURCE_WEB); - supportedFrames.add(FRAME_ID_USER_DEFINED_INFO); - supportedFrames.add(FRAME_ID_USER_DEFINED_URL); - supportedFrames.add(FRAME_ID_YEAR); - - //Extension - extensionFrames.add(FRAME_ID_IS_COMPILATION); - extensionFrames.add(FRAME_ID_ALBUM_ARTIST_SORT_ORDER_ITUNES); - extensionFrames.add(FRAME_ID_COMPOSER_SORT_ORDER_ITUNES); - - //Common - commonFrames.add(FRAME_ID_ARTIST); - commonFrames.add(FRAME_ID_ALBUM); - commonFrames.add(FRAME_ID_TITLE); - commonFrames.add(FRAME_ID_GENRE); - commonFrames.add(FRAME_ID_TRACK); - commonFrames.add(FRAME_ID_YEAR); - commonFrames.add(FRAME_ID_COMMENT); - - //Binary - binaryFrames.add(FRAME_ID_ATTACHED_PICTURE); - binaryFrames.add(FRAME_ID_AUDIO_ENCRYPTION); - binaryFrames.add(FRAME_ID_ENCRYPTION); - binaryFrames.add(FRAME_ID_EQUALISATION2); - binaryFrames.add(FRAME_ID_EVENT_TIMING_CODES); - binaryFrames.add(FRAME_ID_GENERAL_ENCAPS_OBJECT); - binaryFrames.add(FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2); - binaryFrames.add(FRAME_ID_RECOMMENDED_BUFFER_SIZE); - binaryFrames.add(FRAME_ID_UNIQUE_FILE_ID); - // Map frameid to a name - idToValue.put(FRAME_ID_ACCOMPANIMENT, "Text: Band/Orchestra/Accompaniment"); - idToValue.put(FRAME_ID_ALBUM, "Text: Album/Movie/Show title"); - idToValue.put(FRAME_ID_ALBUM_SORT_ORDER, "Album sort order"); - idToValue.put(FRAME_ID_ARTIST, "Text: Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group"); - idToValue.put(FRAME_ID_ATTACHED_PICTURE, "Attached picture"); - idToValue.put(FRAME_ID_AUDIO_ENCRYPTION, "Audio encryption"); - idToValue.put(FRAME_ID_AUDIO_SEEK_POINT_INDEX, "Audio seek point index"); - idToValue.put(FRAME_ID_BPM, "Text: BPM (Beats Per Minute)"); - idToValue.put(FRAME_ID_COMMENT, "Comments"); - idToValue.put(FRAME_ID_COMMERCIAL_FRAME, "Commercial Frame"); - idToValue.put(FRAME_ID_COMPOSER, "Text: Composer"); - idToValue.put(FRAME_ID_CONDUCTOR, "Text: Conductor/Performer refinement"); - idToValue.put(FRAME_ID_CONTENT_GROUP_DESC, "Text: Content group description"); - idToValue.put(FRAME_ID_COPYRIGHTINFO, "Text: Copyright message"); - idToValue.put(FRAME_ID_ENCODEDBY, "Text: Encoded by"); - idToValue.put(FRAME_ID_ENCODING_TIME, "Text: Encoding time"); - idToValue.put(FRAME_ID_ENCRYPTION, "Encryption method registration"); - idToValue.put(FRAME_ID_EQUALISATION2, "Equalization (2)"); - idToValue.put(FRAME_ID_EVENT_TIMING_CODES, "Event timing codes"); - idToValue.put(FRAME_ID_FILE_OWNER, "Text:File Owner"); - idToValue.put(FRAME_ID_FILE_TYPE, "Text: File type"); - idToValue.put(FRAME_ID_GENERAL_ENCAPS_OBJECT, "General encapsulated datatype"); - idToValue.put(FRAME_ID_GENRE, "Text: Content type"); - idToValue.put(FRAME_ID_GROUP_ID_REG, "Group ID Registration"); - idToValue.put(FRAME_ID_HW_SW_SETTINGS, "Text: Software/hardware and settings used for encoding"); - idToValue.put(FRAME_ID_INITIAL_KEY, "Text: Initial key"); - idToValue.put(FRAME_ID_INVOLVED_PEOPLE, "Involved people list"); - idToValue.put(FRAME_ID_ISRC, "Text: ISRC (International Standard Recording Code)"); - idToValue.put(FRAME_ID_LANGUAGE, "Text: Language(s)"); - idToValue.put(FRAME_ID_LENGTH, "Text: Length"); - idToValue.put(FRAME_ID_LINKED_INFO, "Linked information"); - idToValue.put(FRAME_ID_LYRICIST, "Text: Lyricist/text writer"); - idToValue.put(FRAME_ID_MEDIA_TYPE, "Text: Media type"); - idToValue.put(FRAME_ID_MOOD, "Text: Mood"); - idToValue.put(FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE, "MPEG location lookup table"); - idToValue.put(FRAME_ID_MUSIC_CD_ID, "Music CD Identifier"); - idToValue.put(FRAME_ID_ORIGARTIST, "Text: Original artist(s)/performer(s)"); - idToValue.put(FRAME_ID_ORIGINAL_RELEASE_TIME, "Text: Original release time"); - idToValue.put(FRAME_ID_ORIG_FILENAME, "Text: Original filename"); - idToValue.put(FRAME_ID_ORIG_LYRICIST, "Text: Original Lyricist(s)/text writer(s)"); - idToValue.put(FRAME_ID_ORIG_TITLE, "Text: Original album/Movie/Show title"); - idToValue.put(FRAME_ID_OWNERSHIP, "Ownership"); - idToValue.put(FRAME_ID_ARTIST_SORT_ORDER, "Performance Sort Order"); - idToValue.put(FRAME_ID_PLAYLIST_DELAY, "Text: Playlist delay"); - idToValue.put(FRAME_ID_PLAY_COUNTER, "Play counter"); - idToValue.put(FRAME_ID_POPULARIMETER, "Popularimeter"); - idToValue.put(FRAME_ID_POSITION_SYNC, "Position Sync"); - idToValue.put(FRAME_ID_PRIVATE, "Private frame"); - idToValue.put(FRAME_ID_PRODUCED_NOTICE, "Produced Notice"); - idToValue.put(FRAME_ID_PUBLISHER, "Text: Publisher"); - idToValue.put(FRAME_ID_RADIO_NAME, "Text: Radio Name"); - idToValue.put(FRAME_ID_RADIO_OWNER, "Text: Radio Owner"); - idToValue.put(FRAME_ID_RECOMMENDED_BUFFER_SIZE, "Recommended buffer size"); - idToValue.put(FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2, "Relative volume adjustment(2)"); - idToValue.put(FRAME_ID_RELEASE_TIME, "Release Time"); - idToValue.put(FRAME_ID_REMIXED, "Text: Interpreted, remixed, or otherwise modified by"); - idToValue.put(FRAME_ID_REVERB, "Reverb"); - idToValue.put(FRAME_ID_SEEK, "Seek"); - idToValue.put(FRAME_ID_SET, "Text: Part of a setField"); - idToValue.put(FRAME_ID_SET_SUBTITLE, "Text: Set subtitle"); - idToValue.put(FRAME_ID_SIGNATURE, "Signature"); - idToValue.put(FRAME_ID_SYNC_LYRIC, "Synchronized lyric/text"); - idToValue.put(FRAME_ID_SYNC_TEMPO, "Synced tempo codes"); - idToValue.put(FRAME_ID_TAGGING_TIME, "Text: Tagging time"); - idToValue.put(FRAME_ID_TERMS_OF_USE, "Terms of Use"); - idToValue.put(FRAME_ID_TITLE, "Text: title"); - idToValue.put(FRAME_ID_TITLE_REFINEMENT, "Text: Subtitle/Description refinement"); - idToValue.put(FRAME_ID_TITLE_SORT_ORDER, "Text: title sort order"); - idToValue.put(FRAME_ID_TRACK, "Text: Track number/Position in setField"); - idToValue.put(FRAME_ID_UNIQUE_FILE_ID, "Unique file identifier"); - idToValue.put(FRAME_ID_UNSYNC_LYRICS, "Unsychronized lyric/text transcription"); - idToValue.put(FRAME_ID_URL_ARTIST_WEB, "URL: Official artist/performer webpage"); - idToValue.put(FRAME_ID_URL_COMMERCIAL, "URL: Commercial information"); - idToValue.put(FRAME_ID_URL_COPYRIGHT, "URL: Copyright/Legal information"); - idToValue.put(FRAME_ID_URL_FILE_WEB, "URL: Official audio file webpage"); - idToValue.put(FRAME_ID_URL_OFFICIAL_RADIO, "URL: Official Radio website"); - idToValue.put(FRAME_ID_URL_PAYMENT, "URL: Payment for this recording "); - idToValue.put(FRAME_ID_URL_PUBLISHERS, "URL: Publishers official webpage"); - idToValue.put(FRAME_ID_URL_SOURCE_WEB, "URL: Official audio source webpage"); - idToValue.put(FRAME_ID_USER_DEFINED_INFO, "User defined text information frame"); - idToValue.put(FRAME_ID_USER_DEFINED_URL, "User defined URL link frame"); - idToValue.put(FRAME_ID_YEAR, "Text:Year"); - idToValue.put(FRAME_ID_IS_COMPILATION, "Is Compilation"); - idToValue.put(FRAME_ID_ALBUM_ARTIST_SORT_ORDER_ITUNES, "Text:Album Artist Sort Order Frame"); - idToValue.put(FRAME_ID_COMPOSER_SORT_ORDER_ITUNES, "Text:Composer Sort Order Frame"); - - - createMaps(); - - multipleFrames.add(FRAME_ID_USER_DEFINED_INFO); - multipleFrames.add(FRAME_ID_USER_DEFINED_URL); - multipleFrames.add(FRAME_ID_ATTACHED_PICTURE); - multipleFrames.add(FRAME_ID_PRIVATE); - multipleFrames.add(FRAME_ID_COMMENT); - multipleFrames.add(FRAME_ID_UNIQUE_FILE_ID); - multipleFrames.add(FRAME_ID_UNSYNC_LYRICS); - multipleFrames.add(FRAME_ID_POPULARIMETER); - multipleFrames.add(FRAME_ID_GENERAL_ENCAPS_OBJECT); - multipleFrames.add(FRAME_ID_URL_ARTIST_WEB); - - discardIfFileAlteredFrames.add(FRAME_ID_EVENT_TIMING_CODES); - discardIfFileAlteredFrames.add(FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE); - discardIfFileAlteredFrames.add(FRAME_ID_POSITION_SYNC); - discardIfFileAlteredFrames.add(FRAME_ID_SYNC_LYRIC); - discardIfFileAlteredFrames.add(FRAME_ID_SYNC_TEMPO); - discardIfFileAlteredFrames.add(FRAME_ID_EVENT_TIMING_CODES); - discardIfFileAlteredFrames.add(FRAME_ID_ENCODEDBY); - discardIfFileAlteredFrames.add(FRAME_ID_LENGTH); - - tagFieldToId3.put(FieldKey.ALBUM, ID3v24FieldKey.ALBUM); - tagFieldToId3.put(FieldKey.ALBUM_ARTIST, ID3v24FieldKey.ALBUM_ARTIST); - tagFieldToId3.put(FieldKey.ALBUM_ARTIST_SORT, ID3v24FieldKey.ALBUM_ARTIST_SORT); - tagFieldToId3.put(FieldKey.ALBUM_SORT, ID3v24FieldKey.ALBUM_SORT); - tagFieldToId3.put(FieldKey.AMAZON_ID, ID3v24FieldKey.AMAZON_ID); - tagFieldToId3.put(FieldKey.ARTIST, ID3v24FieldKey.ARTIST); - tagFieldToId3.put(FieldKey.ARTIST_SORT, ID3v24FieldKey.ARTIST_SORT); - tagFieldToId3.put(FieldKey.BARCODE, ID3v24FieldKey.BARCODE); - tagFieldToId3.put(FieldKey.BPM, ID3v24FieldKey.BPM); - tagFieldToId3.put(FieldKey.CATALOG_NO, ID3v24FieldKey.CATALOG_NO); - tagFieldToId3.put(FieldKey.COMMENT, ID3v24FieldKey.COMMENT); - tagFieldToId3.put(FieldKey.COMPOSER, ID3v24FieldKey.COMPOSER); - tagFieldToId3.put(FieldKey.COMPOSER_SORT, ID3v24FieldKey.COMPOSER_SORT); - tagFieldToId3.put(FieldKey.CONDUCTOR, ID3v24FieldKey.CONDUCTOR); - tagFieldToId3.put(FieldKey.COVER_ART, ID3v24FieldKey.COVER_ART); - tagFieldToId3.put(FieldKey.CUSTOM1, ID3v24FieldKey.CUSTOM1); - tagFieldToId3.put(FieldKey.CUSTOM2, ID3v24FieldKey.CUSTOM2); - tagFieldToId3.put(FieldKey.CUSTOM3, ID3v24FieldKey.CUSTOM3); - tagFieldToId3.put(FieldKey.CUSTOM4, ID3v24FieldKey.CUSTOM4); - tagFieldToId3.put(FieldKey.CUSTOM5, ID3v24FieldKey.CUSTOM5); - tagFieldToId3.put(FieldKey.DISC_NO, ID3v24FieldKey.DISC_NO); - tagFieldToId3.put(FieldKey.DISC_SUBTITLE, ID3v24FieldKey.DISC_SUBTITLE); - tagFieldToId3.put(FieldKey.DISC_TOTAL, ID3v24FieldKey.DISC_NO); - tagFieldToId3.put(FieldKey.ENCODER, ID3v24FieldKey.ENCODER); - tagFieldToId3.put(FieldKey.FBPM, ID3v24FieldKey.FBPM); - tagFieldToId3.put(FieldKey.GENRE, ID3v24FieldKey.GENRE); - tagFieldToId3.put(FieldKey.GROUPING, ID3v24FieldKey.GROUPING); - tagFieldToId3.put(FieldKey.ISRC, ID3v24FieldKey.ISRC); - tagFieldToId3.put(FieldKey.IS_COMPILATION, ID3v24FieldKey.IS_COMPILATION); - tagFieldToId3.put(FieldKey.KEY, ID3v24FieldKey.KEY); - tagFieldToId3.put(FieldKey.LANGUAGE, ID3v24FieldKey.LANGUAGE); - tagFieldToId3.put(FieldKey.LYRICIST, ID3v24FieldKey.LYRICIST); - tagFieldToId3.put(FieldKey.LYRICS, ID3v24FieldKey.LYRICS); - tagFieldToId3.put(FieldKey.MEDIA, ID3v24FieldKey.MEDIA); - tagFieldToId3.put(FieldKey.MOOD, ID3v24FieldKey.MOOD); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_ARTISTID, ID3v24FieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_DISC_ID, ID3v24FieldKey.MUSICBRAINZ_DISC_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, ID3v24FieldKey.MUSICBRAINZ_ORIGINAL_RELEASEID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, ID3v24FieldKey.MUSICBRAINZ_RELEASEARTISTID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASEID, ID3v24FieldKey.MUSICBRAINZ_RELEASEID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, ID3v24FieldKey.MUSICBRAINZ_RELEASE_COUNTRY); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, ID3v24FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, ID3v24FieldKey.MUSICBRAINZ_RELEASE_STATUS); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, ID3v24FieldKey.MUSICBRAINZ_RELEASE_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_TRACK_ID, ID3v24FieldKey.MUSICBRAINZ_TRACK_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_ID); - tagFieldToId3.put(FieldKey.MUSICIP_ID, ID3v24FieldKey.MUSICIP_ID); - tagFieldToId3.put(FieldKey.OCCASION, ID3v24FieldKey.OCCASION); - tagFieldToId3.put(FieldKey.ORIGINAL_ALBUM, ID3v24FieldKey.ORIGINAL_ALBUM); - tagFieldToId3.put(FieldKey.ORIGINAL_ARTIST, ID3v24FieldKey.ORIGINAL_ARTIST); - tagFieldToId3.put(FieldKey.ORIGINAL_LYRICIST, ID3v24FieldKey.ORIGINAL_LYRICIST); - tagFieldToId3.put(FieldKey.ORIGINAL_YEAR, ID3v24FieldKey.ORIGINAL_YEAR); - tagFieldToId3.put(FieldKey.QUALITY, ID3v24FieldKey.QUALITY); - tagFieldToId3.put(FieldKey.RATING, ID3v24FieldKey.RATING); - tagFieldToId3.put(FieldKey.RECORD_LABEL, ID3v24FieldKey.RECORD_LABEL); - tagFieldToId3.put(FieldKey.REMIXER, ID3v24FieldKey.REMIXER); - tagFieldToId3.put(FieldKey.SCRIPT, ID3v24FieldKey.SCRIPT); - tagFieldToId3.put(FieldKey.TAGS, ID3v24FieldKey.TAGS); - tagFieldToId3.put(FieldKey.TEMPO, ID3v24FieldKey.TEMPO); - tagFieldToId3.put(FieldKey.TITLE, ID3v24FieldKey.TITLE); - tagFieldToId3.put(FieldKey.TITLE_SORT, ID3v24FieldKey.TITLE_SORT); - tagFieldToId3.put(FieldKey.TRACK, ID3v24FieldKey.TRACK); - tagFieldToId3.put(FieldKey.TRACK_TOTAL, ID3v24FieldKey.TRACK_TOTAL); - tagFieldToId3.put(FieldKey.URL_DISCOGS_ARTIST_SITE, ID3v24FieldKey.URL_DISCOGS_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_DISCOGS_RELEASE_SITE, ID3v24FieldKey.URL_DISCOGS_RELEASE_SITE); - tagFieldToId3.put(FieldKey.URL_LYRICS_SITE, ID3v24FieldKey.URL_LYRICS_SITE); - tagFieldToId3.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, ID3v24FieldKey.URL_OFFICIAL_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, ID3v24FieldKey.URL_OFFICIAL_RELEASE_SITE); - tagFieldToId3.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, ID3v24FieldKey.URL_WIKIPEDIA_ARTIST_SITE); - tagFieldToId3.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, ID3v24FieldKey.URL_WIKIPEDIA_RELEASE_SITE); - tagFieldToId3.put(FieldKey.YEAR, ID3v24FieldKey.YEAR); - tagFieldToId3.put(FieldKey.ENGINEER, ID3v24FieldKey.ENGINEER); - tagFieldToId3.put(FieldKey.PRODUCER, ID3v24FieldKey.PRODUCER); - tagFieldToId3.put(FieldKey.MIXER, ID3v24FieldKey.MIXER); - tagFieldToId3.put(FieldKey.DJMIXER, ID3v24FieldKey.DJMIXER); - tagFieldToId3.put(FieldKey.ARRANGER, ID3v24FieldKey.ARRANGER); - tagFieldToId3.put(FieldKey.ARTISTS, ID3v24FieldKey.ARTISTS); - tagFieldToId3.put(FieldKey.ACOUSTID_FINGERPRINT, ID3v24FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToId3.put(FieldKey.ACOUSTID_ID, ID3v24FieldKey.ACOUSTID_ID); - tagFieldToId3.put(FieldKey.COUNTRY, ID3v24FieldKey.COUNTRY); - tagFieldToId3.put(FieldKey.SUBTITLE, ID3v24FieldKey.SUBTITLE); - - for (Map.Entry next : tagFieldToId3.entrySet()) { - id3ToTagField.put(next.getValue(), next.getKey()); - } - } - - public static ID3v24Frames getInstanceOf() { - if (id3v24Frames == null) { - id3v24Frames = new ID3v24Frames(); - } - return id3v24Frames; - } - - /** - * @param genericKey - * @return id3 key for generic key - */ - public ID3v24FieldKey getId3KeyFromGenericKey(FieldKey genericKey) { - return tagFieldToId3.get(genericKey); - } - - /** - * Get generic key for ID3 field key - * - * @param fieldKey - * @return - */ - public FieldKey getGenericKeyFromId3(ID3v24FieldKey fieldKey) { - return id3ToTagField.get(fieldKey); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java deleted file mode 100644 index 3bbce4d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -import static org.jaudiotagger.tag.id3.ID3v24Frames.*; - -/** - * Orders frame Ids so that the most important frames are writtne first - */ -public class ID3v24PreferredFrameOrderComparator implements Comparator { - private static ID3v24PreferredFrameOrderComparator comparator; - private static List frameIdsInPreferredOrder = new ArrayList(); - - static { - //these are the key ones we want at the top - frameIdsInPreferredOrder.add(FRAME_ID_UNIQUE_FILE_ID); - frameIdsInPreferredOrder.add(FRAME_ID_TITLE); - frameIdsInPreferredOrder.add(FRAME_ID_ARTIST); - frameIdsInPreferredOrder.add(FRAME_ID_ALBUM); - frameIdsInPreferredOrder.add(FRAME_ID_ALBUM_SORT_ORDER); - frameIdsInPreferredOrder.add(FRAME_ID_GENRE); - frameIdsInPreferredOrder.add(FRAME_ID_COMPOSER); - frameIdsInPreferredOrder.add(FRAME_ID_CONDUCTOR); - frameIdsInPreferredOrder.add(FRAME_ID_CONTENT_GROUP_DESC); - frameIdsInPreferredOrder.add(FRAME_ID_TRACK); - frameIdsInPreferredOrder.add(FRAME_ID_YEAR); - frameIdsInPreferredOrder.add(FRAME_ID_ACCOMPANIMENT); - frameIdsInPreferredOrder.add(FRAME_ID_BPM); - frameIdsInPreferredOrder.add(FRAME_ID_ISRC); - frameIdsInPreferredOrder.add(FRAME_ID_TITLE_SORT_ORDER); - frameIdsInPreferredOrder.add(FRAME_ID_TITLE_REFINEMENT); - frameIdsInPreferredOrder.add(FRAME_ID_UNSYNC_LYRICS); - frameIdsInPreferredOrder.add(FRAME_ID_USER_DEFINED_INFO); - frameIdsInPreferredOrder.add(FRAME_ID_USER_DEFINED_URL); - frameIdsInPreferredOrder.add(FRAME_ID_URL_ARTIST_WEB); - frameIdsInPreferredOrder.add(FRAME_ID_URL_COMMERCIAL); - frameIdsInPreferredOrder.add(FRAME_ID_URL_COPYRIGHT); - frameIdsInPreferredOrder.add(FRAME_ID_URL_FILE_WEB); - frameIdsInPreferredOrder.add(FRAME_ID_URL_OFFICIAL_RADIO); - frameIdsInPreferredOrder.add(FRAME_ID_URL_PAYMENT); - frameIdsInPreferredOrder.add(FRAME_ID_URL_PUBLISHERS); - frameIdsInPreferredOrder.add(FRAME_ID_URL_COMMERCIAL); - frameIdsInPreferredOrder.add(FRAME_ID_LYRICIST); - frameIdsInPreferredOrder.add(FRAME_ID_MEDIA_TYPE); - frameIdsInPreferredOrder.add(FRAME_ID_INVOLVED_PEOPLE); - frameIdsInPreferredOrder.add(FRAME_ID_LANGUAGE); - frameIdsInPreferredOrder.add(FRAME_ID_ARTIST_SORT_ORDER); - frameIdsInPreferredOrder.add(FRAME_ID_PLAYLIST_DELAY); - frameIdsInPreferredOrder.add(FRAME_ID_PLAY_COUNTER); - frameIdsInPreferredOrder.add(FRAME_ID_POPULARIMETER); - frameIdsInPreferredOrder.add(FRAME_ID_PUBLISHER); - frameIdsInPreferredOrder.add(FRAME_ID_ALBUM_ARTIST_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(FRAME_ID_COMPOSER_SORT_ORDER_ITUNES); - frameIdsInPreferredOrder.add(FRAME_ID_IS_COMPILATION); - frameIdsInPreferredOrder.add(FRAME_ID_COMMENT); - - //Not so bothered about these - frameIdsInPreferredOrder.add(FRAME_ID_AUDIO_SEEK_POINT_INDEX); - frameIdsInPreferredOrder.add(FRAME_ID_COMMERCIAL_FRAME); - frameIdsInPreferredOrder.add(FRAME_ID_COPYRIGHTINFO); - frameIdsInPreferredOrder.add(FRAME_ID_ENCODEDBY); - frameIdsInPreferredOrder.add(FRAME_ID_ENCODING_TIME); - frameIdsInPreferredOrder.add(FRAME_ID_ENCRYPTION); - frameIdsInPreferredOrder.add(FRAME_ID_EQUALISATION2); - frameIdsInPreferredOrder.add(FRAME_ID_EVENT_TIMING_CODES); - frameIdsInPreferredOrder.add(FRAME_ID_FILE_OWNER); - frameIdsInPreferredOrder.add(FRAME_ID_FILE_TYPE); - frameIdsInPreferredOrder.add(FRAME_ID_GROUP_ID_REG); - frameIdsInPreferredOrder.add(FRAME_ID_HW_SW_SETTINGS); - frameIdsInPreferredOrder.add(FRAME_ID_INITIAL_KEY); - frameIdsInPreferredOrder.add(FRAME_ID_LENGTH); - frameIdsInPreferredOrder.add(FRAME_ID_LINKED_INFO); - frameIdsInPreferredOrder.add(FRAME_ID_MOOD); - frameIdsInPreferredOrder.add(FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE); - frameIdsInPreferredOrder.add(FRAME_ID_MUSICIAN_CREDITS); - frameIdsInPreferredOrder.add(FRAME_ID_ORIGARTIST); - frameIdsInPreferredOrder.add(FRAME_ID_ORIGINAL_RELEASE_TIME); - frameIdsInPreferredOrder.add(FRAME_ID_ORIG_FILENAME); - frameIdsInPreferredOrder.add(FRAME_ID_ORIG_LYRICIST); - frameIdsInPreferredOrder.add(FRAME_ID_ORIG_TITLE); - frameIdsInPreferredOrder.add(FRAME_ID_OWNERSHIP); - frameIdsInPreferredOrder.add(FRAME_ID_POSITION_SYNC); - frameIdsInPreferredOrder.add(FRAME_ID_PRODUCED_NOTICE); - frameIdsInPreferredOrder.add(FRAME_ID_RADIO_NAME); - frameIdsInPreferredOrder.add(FRAME_ID_RADIO_OWNER); - frameIdsInPreferredOrder.add(FRAME_ID_RECOMMENDED_BUFFER_SIZE); - frameIdsInPreferredOrder.add(FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2); - frameIdsInPreferredOrder.add(FRAME_ID_RELEASE_TIME); - frameIdsInPreferredOrder.add(FRAME_ID_REMIXED); - frameIdsInPreferredOrder.add(FRAME_ID_REVERB); - frameIdsInPreferredOrder.add(FRAME_ID_SEEK); - frameIdsInPreferredOrder.add(FRAME_ID_SET); - frameIdsInPreferredOrder.add(FRAME_ID_SET_SUBTITLE); - frameIdsInPreferredOrder.add(FRAME_ID_SIGNATURE); - frameIdsInPreferredOrder.add(FRAME_ID_SYNC_LYRIC); - frameIdsInPreferredOrder.add(FRAME_ID_SYNC_TEMPO); - frameIdsInPreferredOrder.add(FRAME_ID_TAGGING_TIME); - frameIdsInPreferredOrder.add(FRAME_ID_TERMS_OF_USE); - - //Want this near the end because can cause problems with unsyncing - frameIdsInPreferredOrder.add(FRAME_ID_ATTACHED_PICTURE); - - //Itunes doesnt seem to like these, and of little use so put right at end - frameIdsInPreferredOrder.add(FRAME_ID_PRIVATE); - frameIdsInPreferredOrder.add(FRAME_ID_MUSIC_CD_ID); - frameIdsInPreferredOrder.add(FRAME_ID_AUDIO_ENCRYPTION); - frameIdsInPreferredOrder.add(FRAME_ID_GENERAL_ENCAPS_OBJECT); - - } - - private ID3v24PreferredFrameOrderComparator() { - - } - - public static ID3v24PreferredFrameOrderComparator getInstanceof() { - if (comparator == null) { - comparator = new ID3v24PreferredFrameOrderComparator(); - } - return comparator; - } - - - /** - * @param frameId1 - * @param frameId2 - * @return - */ - public int compare(String frameId1, String frameId2) { - int frameId1Index = frameIdsInPreferredOrder.indexOf(frameId1); - int frameId2Index = frameIdsInPreferredOrder.indexOf(frameId2); - return frameId1Index - frameId2Index; - } - - public boolean equals(Object obj) { - return obj instanceof ID3v24PreferredFrameOrderComparator; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v24Tag.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v24Tag.java deleted file mode 100644 index 74afc08..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v24Tag.java +++ /dev/null @@ -1,1149 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import org.jaudiotagger.FileConstants; -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.framebody.*; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.lyrics3.AbstractLyrics3; -import org.jaudiotagger.tag.lyrics3.Lyrics3v2; -import org.jaudiotagger.tag.lyrics3.Lyrics3v2Field; -import org.jaudiotagger.tag.reference.GenreTypes; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import java.util.*; -import java.util.logging.Level; - -/** - * Represents an ID3v2.4 tag. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: ID3v24Tag.java 1082 2013-01-06 09:38:14Z paultaylor $ - */ -public class ID3v24Tag extends AbstractID3v2Tag { - /** - * ID3v2.4 Header bit mask - */ - public static final int MASK_V24_UNSYNCHRONIZATION = FileConstants.BIT7; - /** - * ID3v2.4 Header bit mask - */ - public static final int MASK_V24_EXTENDED_HEADER = FileConstants.BIT6; - /** - * ID3v2.4 Header bit mask - */ - public static final int MASK_V24_EXPERIMENTAL = FileConstants.BIT5; - /** - * ID3v2.4 Header bit mask - */ - public static final int MASK_V24_FOOTER_PRESENT = FileConstants.BIT4; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_TAG_UPDATE = FileConstants.BIT6; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_CRC_DATA_PRESENT = FileConstants.BIT5; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_TAG_RESTRICTIONS = FileConstants.BIT4; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_TAG_SIZE_RESTRICTIONS = (byte) FileConstants.BIT7 | FileConstants.BIT6; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_TEXT_ENCODING_RESTRICTIONS = FileConstants.BIT5; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_TEXT_FIELD_SIZE_RESTRICTIONS = FileConstants.BIT4 | FileConstants.BIT3; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_IMAGE_ENCODING = FileConstants.BIT2; - /** - * ID3v2.4 Extended header bit mask - */ - public static final int MASK_V24_IMAGE_SIZE_RESTRICTIONS = FileConstants.BIT2 | FileConstants.BIT1; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_TAG_ALTER_PRESERVATION = FileConstants.BIT6; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_FILE_ALTER_PRESERVATION = FileConstants.BIT5; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_READ_ONLY = FileConstants.BIT4; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_GROUPING_IDENTITY = FileConstants.BIT6; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_COMPRESSION = FileConstants.BIT4; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_ENCRYPTION = FileConstants.BIT3; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_FRAME_UNSYNCHRONIZATION = FileConstants.BIT2; - /** - * ID3v2.4 Header Footer bit mask - */ - public static final int MASK_V24_DATA_LENGTH_INDICATOR = FileConstants.BIT1; - public static final byte RELEASE = 2; - public static final byte MAJOR_VERSION = 4; - public static final byte REVISION = 0; - protected static final String TYPE_FOOTER = "footer"; - protected static final String TYPE_IMAGEENCODINGRESTRICTION = "imageEncodingRestriction"; - protected static final String TYPE_IMAGESIZERESTRICTION = "imageSizeRestriction"; - protected static final String TYPE_TAGRESTRICTION = "tagRestriction"; - protected static final String TYPE_TAGSIZERESTRICTION = "tagSizeRestriction"; - protected static final String TYPE_TEXTENCODINGRESTRICTION = "textEncodingRestriction"; - protected static final String TYPE_TEXTFIELDSIZERESTRICTION = "textFieldSizeRestriction"; - protected static final String TYPE_UPDATETAG = "updateTag"; - protected static final String TYPE_CRCDATA = "crcdata"; - - /** - * ID3v2.4 Header Footer are the same as the header flags. WHY?!?! move the - * flags from thier position in 2.3?????????? - */ - protected static final String TYPE_EXPERIMENTAL = "experimental"; - protected static final String TYPE_EXTENDED = "extended"; - protected static final String TYPE_PADDINGSIZE = "paddingsize"; - protected static final String TYPE_UNSYNCHRONISATION = "unsyncronisation"; - protected static int TAG_EXT_HEADER_LENGTH = 6; - protected static int TAG_EXT_HEADER_UPDATE_LENGTH = 1; - protected static int TAG_EXT_HEADER_CRC_LENGTH = 6; - protected static int TAG_EXT_HEADER_RESTRICTION_LENGTH = 2; - protected static int TAG_EXT_HEADER_CRC_DATA_LENGTH = 5; - protected static int TAG_EXT_HEADER_RESTRICTION_DATA_LENGTH = 1; - protected static int TAG_EXT_NUMBER_BYTES_DATA_LENGTH = 1; - /** - * CRC Checksum calculated - */ - protected boolean crcDataFlag = false; - /** - * Experiemntal tag - */ - protected boolean experimental = false; - /** - * Contains extended header - */ - protected boolean extended = false; - /** - * All frames in the tag uses unsynchronisation - */ - protected boolean unsynchronization = false; - /** - * CRC Checksum - */ - protected int crcData = 0; - /** - * Contains a footer - */ - protected boolean footer = false; - /** - * Tag is an update - */ - protected boolean updateTag = false; - /** - * Tag has restrictions - */ - protected boolean tagRestriction = false; - /** - * If Set Image encoding restrictions - *

    - * 0 No restrictions - * 1 Images are encoded only with PNG [PNG] or JPEG [JFIF]. - */ - protected byte imageEncodingRestriction = 0; - /** - * If set Image size restrictions - *

    - * 00 No restrictions - * 01 All images are 256x256 pixels or smaller. - * 10 All images are 64x64 pixels or smaller. - * 11 All images are exactly 64x64 pixels, unless required - * otherwise. - */ - protected byte imageSizeRestriction = 0; - /** - * If set then Tag Size Restrictions - *

    - * 00 No more than 128 frames and 1 MB total tag size. - * 01 No more than 64 frames and 128 KB total tag size. - * 10 No more than 32 frames and 40 KB total tag size. - * 11 No more than 32 frames and 4 KB total tag size. - */ - protected byte tagSizeRestriction = 0; - /** - * If set Text encoding restrictions - *

    - * 0 No restrictions - * 1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or - * UTF-8 [UTF-8]. - */ - protected byte textEncodingRestriction = 0; - /** - * Tag padding - */ - protected int paddingSize = 0; - /** - * If set Text fields size restrictions - *

    - * 00 No restrictions - * 01 No string is longer than 1024 characters. - * 10 No string is longer than 128 characters. - * 11 No string is longer than 30 characters. - *

    - * Note that nothing is said about how many bytes is used to - * represent those characters, since it is encoding dependent. If a - * text frame consists of more than one string, the sum of the - * strungs is restricted as stated. - */ - protected byte textFieldSizeRestriction = 0; - - /** - * Creates a new empty ID3v2_4 datatype. - */ - public ID3v24Tag() { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - } - - /** - * Copy Constructor, creates a new ID3v2_4 Tag based on another ID3v2_4 Tag - * - * @param copyObject - */ - public ID3v24Tag(ID3v24Tag copyObject) { - logger.config("Creating tag from another tag of same type"); - copyPrimitives(copyObject); - copyFrames(copyObject); - } - - /** - * Creates a new ID3v2_4 datatype based on another (non 2.4) tag - * - * @param mp3tag - */ - public ID3v24Tag(AbstractTag mp3tag) { - logger.config("Creating tag from a tag of a different version"); - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - if (mp3tag != null) { - //Should use simpler copy constructor - if ((mp3tag instanceof ID3v24Tag)) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } - /* If we get a tag, we want to convert to id3v2_4 - * both id3v1 and lyrics3 convert to this type - * id3v1 needs to convert to id3v2_4 before converting to lyrics3 - */ - else if (mp3tag instanceof AbstractID3v2Tag) { - this.setLoggingFilename(((AbstractID3v2Tag) mp3tag).getLoggingFilename()); - copyPrimitives((AbstractID3v2Tag) mp3tag); - copyFrames((AbstractID3v2Tag) mp3tag); - } - //IDv1 - else if (mp3tag instanceof ID3v1Tag) { - // convert id3v1 tags. - ID3v1Tag id3tag = (ID3v1Tag) mp3tag; - ID3v24Frame newFrame; - AbstractID3v2FrameBody newBody; - if (id3tag.title.length() > 0) { - newBody = new FrameBodyTIT2((byte) 0, id3tag.title); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_TITLE); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (id3tag.artist.length() > 0) { - newBody = new FrameBodyTPE1((byte) 0, id3tag.artist); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_ARTIST); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (id3tag.album.length() > 0) { - newBody = new FrameBodyTALB((byte) 0, id3tag.album); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_ALBUM); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (id3tag.year.length() > 0) { - newBody = new FrameBodyTDRC((byte) 0, id3tag.year); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_YEAR); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (id3tag.comment.length() > 0) { - newBody = new FrameBodyCOMM((byte) 0, "ENG", "", id3tag.comment); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_COMMENT); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (((id3tag.genre & ID3v1Tag.BYTE_TO_UNSIGNED) >= 0) && ((id3tag.genre & ID3v1Tag.BYTE_TO_UNSIGNED) != ID3v1Tag.BYTE_TO_UNSIGNED)) { - Integer genreId = id3tag.genre & ID3v1Tag.BYTE_TO_UNSIGNED; - String genre = "(" + genreId + ") " + GenreTypes.getInstanceOf().getValueForId(genreId); - - newBody = new FrameBodyTCON((byte) 0, genre); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_GENRE); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - if (mp3tag instanceof ID3v11Tag) { - ID3v11Tag id3tag2 = (ID3v11Tag) mp3tag; - if (id3tag2.track > 0) { - newBody = new FrameBodyTRCK((byte) 0, Byte.toString(id3tag2.track)); - newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_TRACK); - newFrame.setBody(newBody); - frameMap.put(newFrame.getIdentifier(), newFrame); - } - } - } - //Lyrics 3 - else if (mp3tag instanceof AbstractLyrics3) { - //Put the conversion stuff in the individual frame code. - Lyrics3v2 lyric; - if (mp3tag instanceof Lyrics3v2) { - lyric = new Lyrics3v2((Lyrics3v2) mp3tag); - } else { - lyric = new Lyrics3v2(mp3tag); - } - Iterator iterator = lyric.iterator(); - Lyrics3v2Field field; - ID3v24Frame newFrame; - while (iterator.hasNext()) { - try { - field = iterator.next(); - newFrame = new ID3v24Frame(field); - frameMap.put(newFrame.getIdentifier(), newFrame); - } catch (InvalidTagException ex) { - logger.warning("Unable to convert Lyrics3 to v24 Frame:Frame Identifier"); - } - } - } - } - } - - - /** - * Creates a new ID3v2_4 datatype. - * - * @param buffer - * @param loggingFilename - * @throws TagException - */ - public ID3v24Tag(ByteBuffer buffer, String loggingFilename) throws TagException { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - setLoggingFilename(loggingFilename); - this.read(buffer); - } - - /** - * Creates a new ID3v2_4 datatype. - * - * @param buffer - * @throws TagException - * @deprecated use {@link #ID3v24Tag(ByteBuffer, String)} instead - */ - public ID3v24Tag(ByteBuffer buffer) throws TagException { - this(buffer, ""); - } - - /** - * Retrieve the Release - */ - public byte getRelease() { - return RELEASE; - } - - /** - * Retrieve the Major Version - */ - public byte getMajorVersion() { - return MAJOR_VERSION; - } - - /** - * Retrieve the Revision - */ - public byte getRevision() { - return REVISION; - } - - /** - * Copy primitives applicable to v2.4, this is used when cloning a v2.4 datatype - * and other objects such as v2.3 so need to check instanceof - */ - protected void copyPrimitives(AbstractID3v2Tag copyObj) { - logger.config("Copying primitives"); - super.copyPrimitives(copyObj); - - if (copyObj instanceof ID3v24Tag) { - ID3v24Tag copyObject = (ID3v24Tag) copyObj; - this.footer = copyObject.footer; - this.tagRestriction = copyObject.tagRestriction; - this.updateTag = copyObject.updateTag; - this.imageEncodingRestriction = copyObject.imageEncodingRestriction; - this.imageSizeRestriction = copyObject.imageSizeRestriction; - this.tagSizeRestriction = copyObject.tagSizeRestriction; - this.textEncodingRestriction = copyObject.textEncodingRestriction; - this.textFieldSizeRestriction = copyObject.textFieldSizeRestriction; - } - } - - protected void addFrame(AbstractID3v2Frame frame) { - try { - if (frame instanceof ID3v24Frame) { - copyFrameIntoMap(frame.getIdentifier(), frame); - } else { - ID3v24Frame newFrame = new ID3v24Frame(frame); - copyFrameIntoMap(newFrame.getIdentifier(), newFrame); - } - } catch (InvalidFrameException ife) { - logger.log(Level.SEVERE, "Unable to convert frame:" + frame.getIdentifier()); - } - } - - /* - * Copy frame into map, whilst accounting for multiple frames of same type which can occur even if there were - * not frames of the dame type in the original tag - * - * The frame already exists this shouldn't normally happen because frames - * that are allowed to be multiple don't call this method. Frames that - * aren't allowed to be multiple aren't added to hashMap in first place when - * originally added. - * - * We only want to allow one of the frames going forward but we try and merge - * all the information into the one frame. However there is a problem here that - * if we then take this, modify it and try to write back the original values - * we could lose some information although this info is probably invalid anyway. - * - * However converting some frames from tag of one version to another may - * mean that two different frames both get converted to one frame, this - * particularly applies to DateTime fields which were originally two fields - * in v2.3 but are one field in v2.4. - */ - @Override - protected void copyFrameIntoMap(String id, AbstractID3v2Frame newFrame) { - - if (frameMap.containsKey(newFrame.getIdentifier())) { - Object o = frameMap.get(newFrame.getIdentifier()); - if (o instanceof AbstractID3v2Frame) { - //Retrieve the frame with the same id we have already loaded into the map - AbstractID3v2Frame firstFrame = (AbstractID3v2Frame) frameMap.get(newFrame.getIdentifier()); - - - //Two different frames both converted to TDRCFrames, now if this is the case one of them - //may have actually have been created as a FrameUnsupportedBody because TDRC is only - //supported in ID3v24, but is often created in v23 tags as well together with the valid TYER - //frame OR it might be that we have two v23 frames that map to TDRC such as TYER,TIME or TDAT - if (newFrame.getBody() instanceof FrameBodyTDRC) { - if (firstFrame.getBody() instanceof FrameBodyTDRC) { - logger.finest("Modifying frame in map:" + newFrame.getIdentifier()); - FrameBodyTDRC body = (FrameBodyTDRC) firstFrame.getBody(); - FrameBodyTDRC newBody = (FrameBodyTDRC) newFrame.getBody(); - - //#304:Check for NullPointer, just ignore this frame - if (newBody.getOriginalID() == null) { - return; - } - //Just add the data to the frame - if (newBody.getOriginalID().equals(ID3v23Frames.FRAME_ID_V3_TYER)) { - body.setYear(newBody.getYear()); - } else if (newBody.getOriginalID().equals(ID3v23Frames.FRAME_ID_V3_TDAT)) { - body.setDate(newBody.getDate()); - body.setMonthOnly(newBody.isMonthOnly()); - } else if (newBody.getOriginalID().equals(ID3v23Frames.FRAME_ID_V3_TIME)) { - body.setTime(newBody.getTime()); - body.setHoursOnly(newBody.isHoursOnly()); - } - body.setObjectValue(DataTypes.OBJ_TEXT, body.getFormattedText()); - } - // The first frame was a TDRC frame that was not really allowed, this new frame was probably a - // valid frame such as TYER which has been converted to TDRC, replace the firstframe with this frame - else if (firstFrame.getBody() instanceof FrameBodyUnsupported) { - frameMap.put(newFrame.getIdentifier(), newFrame); - } else { - //we just lose this frame, weve already got one with the correct id. - //TODO may want to store this somewhere - logger.warning("Found duplicate TDRC frame in invalid situation,discarding:" + newFrame.getIdentifier()); - } - } else { - List list = new ArrayList(); - list.add(firstFrame); - list.add(newFrame); - frameMap.put(newFrame.getIdentifier(), list); - } - } else { - List list = (List) o; - list.add(newFrame); - } - } else { - frameMap.put(newFrame.getIdentifier(), newFrame); - } - } - - /** - * @return identifier - */ - public String getIdentifier() { - return "ID3v2.40"; - } - - /** - * Return tag size based upon the sizes of the frames rather than the physical - * no of bytes between start of ID3Tag and start of Audio Data. - * - * @return size - */ - public int getSize() { - int size = TAG_HEADER_LENGTH; - if (extended) { - size += TAG_EXT_HEADER_LENGTH; - if (updateTag) { - size += TAG_EXT_HEADER_UPDATE_LENGTH; - } - if (crcDataFlag) { - size += TAG_EXT_HEADER_CRC_LENGTH; - } - if (tagRestriction) { - size += TAG_EXT_HEADER_RESTRICTION_LENGTH; - } - } - size += super.getSize(); - logger.finer("Tag Size is" + size); - return size; - } - - /** - * @param obj - * @return equality - */ - public boolean equals(Object obj) { - if (!(obj instanceof ID3v24Tag)) { - return false; - } - ID3v24Tag object = (ID3v24Tag) obj; - if (this.footer != object.footer) { - return false; - } - if (this.imageEncodingRestriction != object.imageEncodingRestriction) { - return false; - } - if (this.imageSizeRestriction != object.imageSizeRestriction) { - return false; - } - if (this.tagRestriction != object.tagRestriction) { - return false; - } - if (this.tagSizeRestriction != object.tagSizeRestriction) { - return false; - } - if (this.textEncodingRestriction != object.textEncodingRestriction) { - return false; - } - if (this.textFieldSizeRestriction != object.textFieldSizeRestriction) { - return false; - } - return this.updateTag == object.updateTag && super.equals(obj); - } - - /** - * Read header flags - *

    - *

    Log info messages for falgs that have been set and log warnings when bits have been set for unknown flags

    - * - * @param byteBuffer - * @throws TagException - */ - private void readHeaderFlags(ByteBuffer byteBuffer) throws TagException { - //Flags - byte flags = byteBuffer.get(); - unsynchronization = (flags & MASK_V24_UNSYNCHRONIZATION) != 0; - extended = (flags & MASK_V24_EXTENDED_HEADER) != 0; - experimental = (flags & MASK_V24_EXPERIMENTAL) != 0; - footer = (flags & MASK_V24_FOOTER_PRESENT) != 0; - - //Not allowable/Unknown Flags - if ((flags & FileConstants.BIT3) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT3)); - } - - if ((flags & FileConstants.BIT2) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT2)); - } - - if ((flags & FileConstants.BIT1) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT1)); - } - - if ((flags & FileConstants.BIT0) != 0) { - logger.warning(ErrorMessage.ID3_INVALID_OR_UNKNOWN_FLAG_SET.getMsg(getLoggingFilename(), FileConstants.BIT0)); - } - - - if (isUnsynchronization()) { - logger.config(ErrorMessage.ID3_TAG_UNSYNCHRONIZED.getMsg(getLoggingFilename())); - } - - if (extended) { - logger.config(ErrorMessage.ID3_TAG_EXTENDED.getMsg(getLoggingFilename())); - } - - if (experimental) { - logger.config(ErrorMessage.ID3_TAG_EXPERIMENTAL.getMsg(getLoggingFilename())); - } - - if (footer) { - logger.warning(ErrorMessage.ID3_TAG_FOOTER.getMsg(getLoggingFilename())); - } - } - - /** - * Read the optional extended header - * - * @param byteBuffer - * @param size - * @throws org.jaudiotagger.tag.InvalidTagException - */ - private void readExtendedHeader(ByteBuffer byteBuffer, int size) throws InvalidTagException { - byte[] buffer; - - // int is 4 bytes. - int extendedHeaderSize = byteBuffer.getInt(); - - // the extended header must be at least 6 bytes - if (extendedHeaderSize <= TAG_EXT_HEADER_LENGTH) { - throw new InvalidTagException(ErrorMessage.ID3_EXTENDED_HEADER_SIZE_TOO_SMALL.getMsg(getLoggingFilename(), extendedHeaderSize)); - } - - //Number of bytes - byteBuffer.get(); - - // Read the extended flag bytes - byte extFlag = byteBuffer.get(); - updateTag = (extFlag & MASK_V24_TAG_UPDATE) != 0; - crcDataFlag = (extFlag & MASK_V24_CRC_DATA_PRESENT) != 0; - tagRestriction = (extFlag & MASK_V24_TAG_RESTRICTIONS) != 0; - - // read the length byte if the flag is set - // this tag should always be zero but just in case - // read this information. - if (updateTag) { - byteBuffer.get(); - } - - //CRC-32 - if (crcDataFlag) { - // the CRC has a variable length - byteBuffer.get(); - buffer = new byte[TAG_EXT_HEADER_CRC_DATA_LENGTH]; - byteBuffer.get(buffer, 0, TAG_EXT_HEADER_CRC_DATA_LENGTH); - crcData = 0; - for (int i = 0; i < TAG_EXT_HEADER_CRC_DATA_LENGTH; i++) { - crcData <<= 8; - crcData += buffer[i]; - } - } - - //Tag Restriction - if (tagRestriction) { - byteBuffer.get(); - buffer = new byte[1]; - byteBuffer.get(buffer, 0, 1); - tagSizeRestriction = (byte) ((buffer[0] & MASK_V24_TAG_SIZE_RESTRICTIONS) >> 6); - textEncodingRestriction = (byte) ((buffer[0] & MASK_V24_TEXT_ENCODING_RESTRICTIONS) >> 5); - textFieldSizeRestriction = (byte) ((buffer[0] & MASK_V24_TEXT_FIELD_SIZE_RESTRICTIONS) >> 3); - imageEncodingRestriction = (byte) ((buffer[0] & MASK_V24_IMAGE_ENCODING) >> 2); - imageSizeRestriction = (byte) (buffer[0] & MASK_V24_IMAGE_SIZE_RESTRICTIONS); - } - } - - - /** - * {@inheritDoc} - */ - @Override - public void read(ByteBuffer byteBuffer) throws TagException { - int size; - byte[] buffer; - if (!seek(byteBuffer)) { - throw new TagNotFoundException(getLoggingFilename() + ":" + getIdentifier() + " tag not found"); - } - logger.config(getLoggingFilename() + ":" + "Reading ID3v24 tag"); - readHeaderFlags(byteBuffer); - - // Read the size, this is size of tag apart from tag header - size = ID3SyncSafeInteger.bufferToValue(byteBuffer); - logger.config(getLoggingFilename() + ":" + "Reading tag from file size set in header is" + size); - - if (extended) { - readExtendedHeader(byteBuffer, size); - } - - //Note if there was an extended header the size value has padding taken - //off so we dont search it. - readFrames(byteBuffer, size); - } - - /** - * Read frames from tag - * - * @param byteBuffer - * @param size - */ - protected void readFrames(ByteBuffer byteBuffer, int size) { - logger.finest(getLoggingFilename() + ":" + "Start of frame body at" + byteBuffer.position()); - //Now start looking for frames - ID3v24Frame next; - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - //Read the size from the Tag Header - this.fileReadSize = size; - // Read the frames until got to upto the size as specified in header - logger.finest(getLoggingFilename() + ":" + "Start of frame body at:" + byteBuffer.position() + ",frames data size is:" + size); - while (byteBuffer.position() <= size) { - String id; - try { - //Read Frame - logger.finest(getLoggingFilename() + ":" + "looking for next frame at:" + byteBuffer.position()); - next = new ID3v24Frame(byteBuffer, getLoggingFilename()); - id = next.getIdentifier(); - loadFrameIntoMap(id, next); - } - //Found Padding, no more frames - catch (PaddingException ex) { - logger.config(getLoggingFilename() + ":Found padding starting at:" + byteBuffer.position()); - break; - } - //Found Empty Frame - catch (EmptyFrameException ex) { - logger.warning(getLoggingFilename() + ":" + "Empty Frame:" + ex.getMessage()); - this.emptyFrameBytes += TAG_HEADER_LENGTH; - } catch (InvalidFrameIdentifierException ifie) { - logger.config(getLoggingFilename() + ":" + "Invalid Frame Identifier:" + ifie.getMessage()); - this.invalidFrames++; - //Don't try and find any more frames - break; - } - //Problem trying to find frame - catch (InvalidFrameException ife) { - logger.warning(getLoggingFilename() + ":" + "Invalid Frame:" + ife.getMessage()); - this.invalidFrames++; - //Don't try and find any more frames - break; - } - //Failed reading frame but may just have invalid data but correct length so lets carry on - //in case we can read the next frame - catch (InvalidDataTypeException idete) { - logger.warning(getLoggingFilename() + ":Corrupt Frame:" + idete.getMessage()); - this.invalidFrames++; - continue; - } - } - } - - /** - * Write the ID3 header to the ByteBuffer. - *

    - * TODO Calculate the CYC Data Check - * TODO Reintroduce Extended Header - * - * @param padding is the size of the padding - * @param size is the size of the body data - * @return ByteBuffer - * @throws IOException - */ - private ByteBuffer writeHeaderToBuffer(int padding, int size) throws IOException { - //This would only be set if every frame in tag has been unsynchronized, I only unsychronize frames - //that need it, in any case I have been advised not to set it even then. - unsynchronization = false; - - // Flags,currently we never calculate the CRC - // and if we dont calculate them cant keep orig values. Tags are not - // experimental and we never create extended header to keep things simple. - extended = false; - experimental = false; - footer = false; - - // Create Header Buffer,allocate maximum possible size for the header - ByteBuffer headerBuffer = ByteBuffer.allocate(TAG_HEADER_LENGTH); - //TAGID - headerBuffer.put(TAG_ID); - - //Major Version - headerBuffer.put(getMajorVersion()); - - //Minor Version - headerBuffer.put(getRevision()); - - //Flags - byte flagsByte = 0; - if (isUnsynchronization()) { - flagsByte |= MASK_V24_UNSYNCHRONIZATION; - } - if (extended) { - flagsByte |= MASK_V24_EXTENDED_HEADER; - } - if (experimental) { - flagsByte |= MASK_V24_EXPERIMENTAL; - } - if (footer) { - flagsByte |= MASK_V24_FOOTER_PRESENT; - } - headerBuffer.put(flagsByte); - - //Size As Recorded in Header, don't include the main header length - //Additional Header Size,(for completeness we never actually write the extended header, or footer) - int additionalHeaderSize = 0; - if (extended) { - additionalHeaderSize += TAG_EXT_HEADER_LENGTH; - if (updateTag) { - additionalHeaderSize += TAG_EXT_HEADER_UPDATE_LENGTH; - } - if (crcDataFlag) { - additionalHeaderSize += TAG_EXT_HEADER_CRC_LENGTH; - } - if (tagRestriction) { - additionalHeaderSize += TAG_EXT_HEADER_RESTRICTION_LENGTH; - } - } - - //Size As Recorded in Header, don't include the main header length - headerBuffer.put(ID3SyncSafeInteger.valueToBuffer(padding + size + additionalHeaderSize)); - - //Write Extended Header - ByteBuffer extHeaderBuffer = null; - if (extended) { - //Write Extended Header Size - int extendedSize = TAG_EXT_HEADER_LENGTH; - if (updateTag) { - extendedSize += TAG_EXT_HEADER_UPDATE_LENGTH; - } - if (crcDataFlag) { - extendedSize += TAG_EXT_HEADER_CRC_LENGTH; - } - if (tagRestriction) { - extendedSize += TAG_EXT_HEADER_RESTRICTION_LENGTH; - } - extHeaderBuffer = ByteBuffer.allocate(extendedSize); - extHeaderBuffer.putInt(extendedSize); - //Write Number of flags Byte - extHeaderBuffer.put((byte) TAG_EXT_NUMBER_BYTES_DATA_LENGTH); - //Write Extended Flags - byte extFlag = 0; - if (updateTag) { - extFlag |= MASK_V24_TAG_UPDATE; - } - if (crcDataFlag) { - extFlag |= MASK_V24_CRC_DATA_PRESENT; - } - if (tagRestriction) { - extFlag |= MASK_V24_TAG_RESTRICTIONS; - } - extHeaderBuffer.put(extFlag); - //Write Update Data - if (updateTag) { - extHeaderBuffer.put((byte) 0); - } - //Write CRC Data - if (crcDataFlag) { - extHeaderBuffer.put((byte) TAG_EXT_HEADER_CRC_DATA_LENGTH); - extHeaderBuffer.put((byte) 0); - extHeaderBuffer.putInt(crcData); - } - //Write Tag Restriction - if (tagRestriction) { - extHeaderBuffer.put((byte) TAG_EXT_HEADER_RESTRICTION_DATA_LENGTH); - //todo not currently setting restrictions - extHeaderBuffer.put((byte) 0); - } - } - - if (extHeaderBuffer != null) { - extHeaderBuffer.flip(); - headerBuffer.put(extHeaderBuffer); - } - - headerBuffer.flip(); - return headerBuffer; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(File file, long audioStartLocation) throws IOException { - setLoggingFilename(file.getName()); - logger.config("Writing tag to file:" + getLoggingFilename()); - - //Write Body Buffer - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - - //Calculate Tag Size including Padding - int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) audioStartLocation); - - //Calculate padding bytes required - int padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH); - - ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length); - writeBufferToFile(file, headerBuffer, bodyByteBuffer, padding, sizeIncPadding, audioStartLocation); - } - - /** - * {@inheritDoc} - */ - @Override - public void write(WritableByteChannel channel) throws IOException { - logger.config("Writing tag to channel"); - - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - ByteBuffer headerBuffer = writeHeaderToBuffer(0, bodyByteBuffer.length); - - channel.write(headerBuffer); - channel.write(ByteBuffer.wrap(bodyByteBuffer)); - } - - /** - * Display the tag in an XMLFormat - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier()); - - super.createStructureHeader(); - - //Header - MP3File.getStructureFormatter().openHeadingElement(TYPE_HEADER, ""); - MP3File.getStructureFormatter().addElement(TYPE_UNSYNCHRONISATION, this.isUnsynchronization()); - MP3File.getStructureFormatter().addElement(TYPE_CRCDATA, this.crcData); - MP3File.getStructureFormatter().addElement(TYPE_EXPERIMENTAL, this.experimental); - MP3File.getStructureFormatter().addElement(TYPE_EXTENDED, this.extended); - MP3File.getStructureFormatter().addElement(TYPE_PADDINGSIZE, this.paddingSize); - MP3File.getStructureFormatter().addElement(TYPE_FOOTER, this.footer); - MP3File.getStructureFormatter().addElement(TYPE_IMAGEENCODINGRESTRICTION, this.paddingSize); - MP3File.getStructureFormatter().addElement(TYPE_IMAGESIZERESTRICTION, this.imageSizeRestriction); - MP3File.getStructureFormatter().addElement(TYPE_TAGRESTRICTION, this.tagRestriction); - MP3File.getStructureFormatter().addElement(TYPE_TAGSIZERESTRICTION, this.tagSizeRestriction); - MP3File.getStructureFormatter().addElement(TYPE_TEXTFIELDSIZERESTRICTION, this.textFieldSizeRestriction); - MP3File.getStructureFormatter().addElement(TYPE_TEXTENCODINGRESTRICTION, this.textEncodingRestriction); - MP3File.getStructureFormatter().addElement(TYPE_UPDATETAG, this.updateTag); - MP3File.getStructureFormatter().closeHeadingElement(TYPE_HEADER); - - //Body - super.createStructureBody(); - - MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG); - } - - /** - * Are all frame swithin this tag unsynchronized - *

    - *

    Because synchronization occurs at the frame level it is not normally desirable to unsynchronize all frames - * and hence this flag is not normally set. - * - * @return are all frames within the tag unsynchronized - */ - public boolean isUnsynchronization() { - return unsynchronization; - } - - /** - * Create a new frame with the specified frameid - * - * @param id - * @return - */ - public ID3v24Frame createFrame(String id) { - return new ID3v24Frame(id); - } - - - /** - * Create Frame for Id3 Key - *

    - * Only textual data supported at the moment, should only be used with frames that - * support a simple string argument. - * - * @param id3Key - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public TagField createField(ID3v24FieldKey id3Key, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (id3Key == null) { - throw new KeyNotFoundException(); - } - return super.doCreateTagField(new FrameAndSubId(id3Key.getFrameId(), id3Key.getSubId()), value); - } - - /** - * Retrieve the first value that exists for this id3v24key - * - * @param id3v24FieldKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public String getFirst(ID3v24FieldKey id3v24FieldKey) throws KeyNotFoundException { - if (id3v24FieldKey == null) { - throw new KeyNotFoundException(); - } - - FieldKey genericKey = ID3v24Frames.getInstanceOf().getGenericKeyFromId3(id3v24FieldKey); - if (genericKey != null) { - return super.getFirst(genericKey); - } else { - FrameAndSubId frameAndSubId = new FrameAndSubId(id3v24FieldKey.getFrameId(), id3v24FieldKey.getSubId()); - return super.doGetValueAtIndex(frameAndSubId, 0); - } - } - - - /** - * Delete fields with this id3v24FieldKey - * - * @param id3v24FieldKey - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(ID3v24FieldKey id3v24FieldKey) throws KeyNotFoundException { - if (id3v24FieldKey == null) { - throw new KeyNotFoundException(); - } - super.doDeleteTagField(new FrameAndSubId(id3v24FieldKey.getFrameId(), id3v24FieldKey.getSubId())); - } - - /** - * Delete fields with this (frame) id - * - * @param id - */ - public void deleteField(String id) { - super.doDeleteTagField(new FrameAndSubId(id, null)); - } - - protected FrameAndSubId getFrameAndSubIdFromGenericKey(FieldKey genericKey) { - if (genericKey == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - ID3v24FieldKey id3v24FieldKey = ID3v24Frames.getInstanceOf().getId3KeyFromGenericKey(genericKey); - if (id3v24FieldKey == null) { - throw new KeyNotFoundException(genericKey.name()); - } - return new FrameAndSubId(id3v24FieldKey.getFrameId(), id3v24FieldKey.getSubId()); - } - - protected ID3Frames getID3Frames() { - return ID3v24Frames.getInstanceOf(); - } - - /** - * @return comparator used to order frames in preferred order for writing to file - * so that most important frames are written first. - */ - public Comparator getPreferredFrameOrderComparator() { - return ID3v24PreferredFrameOrderComparator.getInstanceof(); - } - - public List getArtworkList() { - List coverartList = getFields(FieldKey.COVER_ART); - List artworkList = new ArrayList(coverartList.size()); - - for (TagField next : coverartList) { - FrameBodyAPIC coverArt = (FrameBodyAPIC) ((AbstractID3v2Frame) next).getBody(); - Artwork artwork = ArtworkFactory.getNew(); - artwork.setMimeType(coverArt.getMimeType()); - artwork.setPictureType(coverArt.getPictureType()); - if (coverArt.isImageUrl()) { - artwork.setLinked(true); - artwork.setImageUrl(coverArt.getImageUrl()); - } else { - artwork.setBinaryData(coverArt.getImageData()); - } - artworkList.add(artwork); - } - return artworkList; - } - - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - FrameBodyAPIC body = (FrameBodyAPIC) frame.getBody(); - if (!artwork.isLinked()) { - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, artwork.getBinaryData()); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, artwork.getPictureType()); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, artwork.getMimeType()); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } else { - try { - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, artwork.getImageUrl().getBytes("ISO-8859-1")); - } catch (UnsupportedEncodingException uoe) { - throw new RuntimeException(uoe.getMessage()); - } - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, artwork.getPictureType()); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, FrameBodyAPIC.IMAGE_IS_URL); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } - } - - /** - * Create Artwork - * - * @param data - * @param mimeType of the image - * @return - * @see PictureTypes - */ - public TagField createArtworkField(byte[] data, String mimeType) { - AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId()); - FrameBodyAPIC body = (FrameBodyAPIC) frame.getBody(); - body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, data); - body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID); - body.setObjectValue(DataTypes.OBJ_MIME_TYPE, mimeType); - body.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - return frame; - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/ID3v2ChapterFrames.java b/src/main/java/org/jaudiotagger/tag/id3/ID3v2ChapterFrames.java deleted file mode 100644 index f4b68d5..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/ID3v2ChapterFrames.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Horizon Wimba Copyright (C)2006 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can getFields a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3; - -import java.util.TreeSet; - -/** - * Defines ID3 Chapter frames and collections that categorise frames. - *

    - *

    For more details, please refer to the ID3 Chapter Frame specifications: - *

    - * - * @author Marc Gimpel, Horizon Wimba S.A. - * @version $Id: ID3v2ChapterFrames.java 830 2009-11-12 12:23:47Z paultaylor $ - */ -public class ID3v2ChapterFrames extends ID3Frames { - public static final String FRAME_ID_CHAPTER = "CHAP"; - public static final String FRAME_ID_TABLE_OF_CONTENT = "CTOC"; - - private static ID3v2ChapterFrames id3v2ChapterFrames; - - private ID3v2ChapterFrames() { - idToValue.put(FRAME_ID_CHAPTER, "Chapter"); - idToValue.put(FRAME_ID_TABLE_OF_CONTENT, "Table of content"); - createMaps(); - multipleFrames = new TreeSet(); - discardIfFileAlteredFrames = new TreeSet(); - } - - public static ID3v2ChapterFrames getInstanceOf() { - if (id3v2ChapterFrames == null) { - id3v2ChapterFrames = new ID3v2ChapterFrames(); - } - return id3v2ChapterFrames; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/Id3FieldType.java b/src/main/java/org/jaudiotagger/tag/id3/Id3FieldType.java deleted file mode 100644 index 5384a9b..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/Id3FieldType.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.jaudiotagger.tag.id3; - -/** - * Categorises id3 fields to aid in mapping to generic keys - */ -public enum Id3FieldType { - TEXT, - USER_DEFINED_TEXT, - BINARY -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java b/src/main/java/org/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java deleted file mode 100644 index 9871c66..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.jaudiotagger.tag.id3; - -import java.util.Iterator; - -/** - * For use in ID3 for mapping YEAR field to TYER and TDAT Frames - */ -public class TyerTdatAggregatedFrame extends AggregatedFrame { - public static final String ID_TYER_TDAT = ID3v23Frames.FRAME_ID_V3_TYER + ID3v23Frames.FRAME_ID_V3_TDAT; - - public String getContent() { - StringBuilder sb = new StringBuilder(); - - Iterator i = frames.iterator(); - AbstractID3v2Frame tyer = i.next(); - sb.append(tyer.getContent()); - AbstractID3v2Frame tdat = i.next(); - sb.append("-"); - sb.append(tdat.getContent().substring(2, 4)); - sb.append("-"); - sb.append(tdat.getContent().substring(0, 2)); - return sb.toString(); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java deleted file mode 100644 index 63b3e0d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java +++ /dev/null @@ -1,221 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractFrameBodyTextInfo.java 1040 2012-03-07 13:57:45Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.TextEncodedStringSizeTerminated; -import org.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.List; - -/** - * Abstract representation of a Text Frame - *

    - * The text information frames are often the most important frames, containing information like artist, album and - * more. There may only be one text information frame of its kind in an tag. In ID3v24 All text information frames - * supports multiple strings, stored as a null separated list, where null is represented by the termination code - * for the character encoding. All text frame identifiers begin with "T". Only text frame identifiers begin with "T", - * with the exception of the "TXXX" frame. All the text information frames have the following format: - *

    - * Text encoding $xx - * Information - *

    - * The list of valid text encodings increased from two in ID3v23 to four in ID3v24 - *

    - * iTunes incorrectly writes null terminators at the end of every String, even though it only writes one String. - *

    - * You can retrieve the first value without the null terminator using {@link #getFirstTextValue} - */ -public abstract class AbstractFrameBodyTextInfo extends AbstractID3v2FrameBody { - - /** - * Creates a new FrameBodyTextInformation datatype. The super.super - * Constructor sets up the Object list for the frame. - */ - protected AbstractFrameBodyTextInfo() { - super(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, ""); - } - - /** - * Copy Constructor - * - * @param body AbstractFrameBodyTextInformation - */ - protected AbstractFrameBodyTextInfo(AbstractFrameBodyTextInfo body) { - super(body); - } - - /** - * Creates a new FrameBodyTextInformation data type. This is used when user - * wants to create a new frame based on data in a user interface. - * - * @param textEncoding Specifies what encoding should be used to write - * text to file. - * @param text Specifies the text String. - */ - protected AbstractFrameBodyTextInfo(byte textEncoding, String text) { - super(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, text); - } - - /** - * Creates a new FrameBodyTextInformation data type from file. - *

    - *

    The super.super Constructor sets up the Object list for the frame. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - protected AbstractFrameBodyTextInfo(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public String getUserFriendlyValue() { - return getTextWithoutTrailingNulls(); - } - - /** - * Retrieve the complete text String as it is held internally. - *

    - * If multiple values are held these will be returned, needless trailing nulls will also be returned - * - * @return the text string - */ - public String getText() { - return (String) getObjectValue(DataTypes.OBJ_TEXT); - } - - /** - * Set the Full Text String. - *

    - *

    If this String contains null terminator characters these are parsed as value - * separators, allowing you to hold multiple strings within one text frame. This functionality is only - * officially support in ID3v24. - * - * @param text to set - */ - public void setText(String text) { - if (text == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - setObjectValue(DataTypes.OBJ_TEXT, text); - } - - /** - * Retrieve the complete text String but without any trailing nulls - *

    - * If multiple values are held these will be returned, needless trailing nulls will not be returned - * - * @return the text string - */ - public String getTextWithoutTrailingNulls() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueWithoutTrailingNull(); - } - - /** - * Get first value - * - * @return value at index 0 - */ - public String getFirstTextValue() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueAtIndex(0); - } - - /** - * Get text value at index - *

    - * When a multiple values are stored within a single text frame this method allows access to any of the - * individual values. - * - * @param index - * @return value at index - */ - public String getValueAtIndex(int index) { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueAtIndex(index); - } - - public List getValues() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValues(); - } - - /** - * Add additional value to value - * - * @param value at index - */ - public void addTextValue(String value) { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - text.addValue(value); - } - - /** - * @return number of text values, usually one - */ - public int getNumberOfValues() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getNumberOfValues(); - } - - /** - * Because Text frames have a text encoding we need to check the text - * String does not contain characters that cannot be encoded in - * current encoding before we write data. If there are change the text - * encoding. - */ - public void write(ByteArrayOutputStream tagBuffer) { - //Ensure valid for type - setTextEncoding(ID3TextEncodingConversion.getTextEncoding(getHeader(), getTextEncoding())); - - //Ensure valid for data - if (!((TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - super.write(tagBuffer); - } - - /** - * Setup the Object List. All text frames contain a text encoding - * and then a text string. - *

    - * TODO:would like to make final but cannot because overridden by FrameBodyTXXX - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new TextEncodedStringSizeTerminated(DataTypes.OBJ_TEXT, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java deleted file mode 100644 index 830bffd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractFrameBodyUrlLink.java 895 2010-04-15 15:21:45Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; - -/** - * Abstract super class of all URL Frames - */ -public abstract class AbstractFrameBodyUrlLink extends AbstractID3v2FrameBody { - - /** - * Creates a new FrameBodyUrlLink datatype. - */ - protected AbstractFrameBodyUrlLink() { - super(); - } - - /** - * Copy Constructor - * - * @param body - */ - protected AbstractFrameBodyUrlLink(AbstractFrameBodyUrlLink body) { - super(body); - } - - /** - * Creates a new FrameBodyUrlLink datatype., set up with data. - * - * @param urlLink - */ - public AbstractFrameBodyUrlLink(String urlLink) { - setObjectValue(DataTypes.OBJ_URLLINK, urlLink); - } - - /** - * Creates a new FrameBodyUrlLink datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - protected AbstractFrameBodyUrlLink(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public String getUserFriendlyValue() { - return getUrlLink(); - } - - /** - * Get URL Link - * - * @return the urllink - */ - public String getUrlLink() { - return (String) getObjectValue(DataTypes.OBJ_URLLINK); - } - - /** - * Set URL Link - * - * @param urlLink - */ - public void setUrlLink(String urlLink) { - if (urlLink == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - setObjectValue(DataTypes.OBJ_URLLINK, urlLink); - } - - /** - * If the description cannot be encoded using the current encoding change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - CharsetEncoder encoder = Charset.forName(TextEncoding.CHARSET_ISO_8859_1).newEncoder(); - String origUrl = getUrlLink(); - if (!encoder.canEncode(origUrl)) { - //ALL W Frames only support ISO-8859-1 for the url itself, if unable to encode let us assume - //the link just needs url encoding - setUrlLink(encodeURL(origUrl)); - - //We still cant convert so just set log error and set to blank to allow save to continue - if (!encoder.canEncode(getUrlLink())) { - logger.warning(ErrorMessage.MP3_UNABLE_TO_ENCODE_URL.getMsg(origUrl)); - setUrlLink(""); - } - //it was ok, just note the modification made - else { - logger.warning(ErrorMessage.MP3_URL_SAVED_ENCODED.getMsg(origUrl, getUrlLink())); - } - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringSizeTerminated(DataTypes.OBJ_URLLINK, this)); - } - - /** - * Encode url because may receive url already encoded or not, but we can only store as ISO8859-1 - * - * @param url - * @return - */ - private String encodeURL(String url) { - try { - final String[] splitURL = url.split("(? - * Version @version:$Id: AbstractID3v2FrameBody.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Abstract Superclass of all Frame Bodys - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.audio.mp3.MP3File; -import org.jaudiotagger.tag.InvalidDataTypeException; -import org.jaudiotagger.tag.InvalidFrameException; -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.AbstractDataType; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Contains the content for an ID3v2 frame, (the header is held directly within the frame - */ -public abstract class AbstractID3v2FrameBody extends AbstractTagFrameBody { - protected static final String TYPE_BODY = "body"; - - - /** - * Frame Body Size, originally this is size as indicated in frame header - * when we come to writing data we recalculate it. - */ - private int size; - - - /** - * Create Empty Body. Super Constructor sets up Object list - */ - protected AbstractID3v2FrameBody() { - } - - /** - * Create Body based on another body - * - * @param copyObject - */ - protected AbstractID3v2FrameBody(AbstractID3v2FrameBody copyObject) { - super(copyObject); - } - - /** - * Creates a new FrameBody dataType from file. The super - * Constructor sets up the Object list for the frame. - * - * @param byteBuffer from where to read the frame body from - * @param frameSize - * @throws org.jaudiotagger.tag.InvalidTagException - */ - protected AbstractID3v2FrameBody(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(); - setSize(frameSize); - this.read(byteBuffer); - - } - - /** - * Return the ID3v2 Frame Identifier, must be implemented by concrete subclasses - * - * @return the frame identifier - */ - public abstract String getIdentifier(); - - - /** - * Return size of frame body,if frameBody already exist will take this value from the frame header - * but it is always recalculated before writing any changes back to disk. - * - * @return size in bytes of this frame body - */ - public int getSize() { - return size; - } - - /** - * Set size based on size passed as parameter from frame header, - * done before read - * - * @param size - */ - public void setSize(int size) { - this.size = size; - } - - /** - * Set size based on size of the DataTypes making up the body,done after write - */ - public void setSize() { - size = 0; - for (AbstractDataType object : objectList) { - size += object.getSize(); - } - } - - /** - * Are two bodies equal - * - * @param obj - */ - public boolean equals(Object obj) { - return (obj instanceof AbstractID3v2FrameBody) && super.equals(obj); - } - - /** - * This reads a frame body from a ByteBuffer into the appropriate FrameBody class and update the position of the - * buffer to be just after the end of this frameBody - *

    - * The ByteBuffer represents the tag and its position should be at the start of this frameBody. The size as - * indicated in the header is passed to the frame constructor when reading from file. - * - * @param byteBuffer file to read - * @throws InvalidFrameException if unable to construct a frameBody from the ByteBuffer - */ - //TODO why don't we just slice byteBuffer, set limit to size and convert readByteArray to take a ByteBuffer - //then we wouldn't have to temporary allocate space for the buffer, using lots of needless memory - //and providing extra work for the garbage collector. - public void read(ByteBuffer byteBuffer) throws InvalidTagException { - int size = getSize(); - logger.config("Reading body for" + this.getIdentifier() + ":" + size); - - //Allocate a buffer to the size of the Frame Body and read from file - byte[] buffer = new byte[size]; - byteBuffer.get(buffer); - - //Offset into buffer, incremented by length of previous dataType - //this offset is only used internally to decide where to look for the next - //dataType within a frameBody, it does not decide where to look for the next frame body - int offset = 0; - - //Go through the ObjectList of the Frame reading the data into the - for (AbstractDataType object : objectList) - //correct dataType. - { - logger.finest("offset:" + offset); - - //The read has extended further than the defined frame size (ok to extend upto - //size because the next datatype may be of length 0.) - if (offset > (size)) { - logger.warning("Invalid Size for FrameBody"); - throw new InvalidFrameException("Invalid size for Frame Body"); - } - - //Try and load it with data from the Buffer - //if it fails frame is invalid - try { - object.readByteArray(buffer, offset); - } catch (InvalidDataTypeException e) { - logger.warning("Problem reading datatype within Frame Body:" + e.getMessage()); - throw e; - } - //Increment Offset to start of next datatype. - offset += object.getSize(); - } - } - - /** - * Write the contents of this datatype to the byte array - * - * @param tagBuffer - * @throws IOException on any I/O error - */ - public void write(ByteArrayOutputStream tagBuffer) - - { - logger.config("Writing frame body for" + this.getIdentifier() + ":Est Size:" + size); - //Write the various fields to file in order - for (AbstractDataType object : objectList) { - byte[] objectData = object.writeByteArray(); - if (objectData != null) { - try { - tagBuffer.write(objectData); - } catch (IOException ioe) { - //This could never happen coz not writing to file, so convert to RuntimeException - throw new RuntimeException(ioe); - } - } - } - setSize(); - logger.config("Written frame body for" + this.getIdentifier() + ":Real Size:" + size); - - } - - /** - * Return String Representation of Datatype * - */ - public void createStructure() { - MP3File.getStructureFormatter().openHeadingElement(TYPE_BODY, ""); - for (AbstractDataType nextObject : objectList) { - nextObject.createStructure(); - } - MP3File.getStructureFormatter().closeHeadingElement(TYPE_BODY); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyAENC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyAENC.java deleted file mode 100644 index d474f12..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyAENC.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Audio encryption Frame. - *

    - *

    - * This frame indicates if the actual audio stream is encrypted, and by - * whom. Since standardisation of such encrypion scheme is beyond this - * document, all "AENC" frames begin with a terminated string with a - * URL containing an email address, or a link to a location where an - * email address can be found, that belongs to the organisation - * responsible for this specific encrypted audio file. Questions - * regarding the encrypted audio should be sent to the email address - * specified. If a $00 is found directly after the 'Frame size' and the - * audiofile indeed is encrypted, the whole file may be considered - * useless. - *

    - * After the 'Owner identifier', a pointer to an unencrypted part of the - * audio can be specified. The 'Preview start' and 'Preview length' is - * described in frames. If no part is unencrypted, these fields should - * be left zeroed. After the 'preview length' field follows optionally a - * datablock required for decryption of the audio. There may be more - * than one "AENC" frames in a tag, but only one with the same 'Owner - * identifier'. - *

    - * - * - * - * - * - *
    <Header for 'Audio encryption', ID: "AENC">
    Owner identifier <text string> $00
    Preview start $xx xx
    Preview length $xx xx
    Encryption info <binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyAENC.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyAENC extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - - /** - * Creates a new FrameBodyAENC datatype. - */ - public FrameBodyAENC() { - this.setObjectValue(DataTypes.OBJ_OWNER, ""); - this.setObjectValue(DataTypes.OBJ_PREVIEW_START, (short) 0); - this.setObjectValue(DataTypes.OBJ_PREVIEW_LENGTH, (short) 0); - this.setObjectValue(DataTypes.OBJ_ENCRYPTION_INFO, new byte[0]); - } - - public FrameBodyAENC(FrameBodyAENC body) { - super(body); - } - - /** - * Creates a new FrameBodyAENC datatype. - * - * @param owner - * @param previewStart - * @param previewLength - * @param data - */ - public FrameBodyAENC(String owner, short previewStart, short previewLength, byte[] data) { - this.setObjectValue(DataTypes.OBJ_OWNER, owner); - this.setObjectValue(DataTypes.OBJ_PREVIEW_START, previewStart); - this.setObjectValue(DataTypes.OBJ_PREVIEW_LENGTH, previewLength); - this.setObjectValue(DataTypes.OBJ_ENCRYPTION_INFO, data); - } - - /** - * Creates a new FrameBodyAENC datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyAENC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_AUDIO_ENCRYPTION; - } - - /** - * @return owner - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * @param description - */ - public void getOwner(String description) { - setObjectValue(DataTypes.OBJ_OWNER, description); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_PREVIEW_START, this, 2)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_PREVIEW_LENGTH, this, 2)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_ENCRYPTION_INFO, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java deleted file mode 100644 index 3fcfdf0..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * Attached picture frame. - *

    - *

    - * This frame contains a picture directly related to the audio file. - * Image format is the MIME type and subtype for the image. In - * the event that the MIME media type name is omitted, "image/" will be - * implied. The "image/png" or "image/jpeg" picture format - * should be used when interoperability is wanted. Description is a - * short description of the picture, represented as a terminated - * textstring. The description has a maximum length of 64 characters, - * but may be empty. There may be several pictures attached to one file, - * each in their individual "APIC" frame, but only one with the same - * content descriptor. There may only be one picture with the picture - * type declared as picture type $01 and $02 respectively. There is the - * possibility to put only a link to the image file by using the 'MIME - * type' "-->" and having a complete URL instead of picture data. - * The use of linked files should however be used sparingly since there - * is the risk of separation of files. - *

    - * - * - * - * - * - * - *
    <Header for 'Attached picture', ID: "APIC">
    Text encoding $xx
    MIME type <text string> $00
    Picture type $xx
    Description <text string according to encoding> $00 (00)
    Picture data <binary data>

    - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Picture type:$00 Other
    $01 32x32 pixels 'file icon' (PNG only)
    $02 Other file icon
    $03 Cover (front)
    $04 Cover (back)
    $05 Leaflet page
    $06 Media (e.g. lable side of CD)
    $07 Lead artist/lead performer/soloist
    $08 Artist/performer
    $09 Conductor
    $0A Band/Orchestra
    $0B Composer
    $0C Lyricist/text writer
    $0D Recording Location
    $0E During recording
    $0F During performance
    $10 Movie/video screen capture
    $11 A bright coloured fish
    $12 Illustration
    $13 Band/artist logotype
    $14 Publisher/Studio logotype

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyAPIC.java 895 2010-04-15 15:21:45Z paultaylor $ - */ -public class FrameBodyAPIC extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - public static final String IMAGE_IS_URL = "-->"; - - /** - * Creates a new FrameBodyAPIC datatype. - */ - public FrameBodyAPIC() { - //Initilise default text encoding - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - } - - public FrameBodyAPIC(FrameBodyAPIC body) { - super(body); - } - - /** - * Conversion from v2 PIC to v3/v4 APIC - * - * @param body - */ - public FrameBodyAPIC(FrameBodyPIC body) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - this.setObjectValue(DataTypes.OBJ_MIME_TYPE, ImageFormats.getMimeTypeForFormat((String) body.getObjectValue(DataTypes.OBJ_IMAGE_FORMAT))); - this.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, body.getObjectValue(DataTypes.OBJ_PICTURE_TYPE)); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, body.getDescription()); - this.setObjectValue(DataTypes.OBJ_PICTURE_DATA, body.getObjectValue(DataTypes.OBJ_PICTURE_DATA)); - - } - - /** - * Creates a new FrameBodyAPIC datatype. - * - * @param textEncoding - * @param mimeType - * @param pictureType - * @param description - * @param data - */ - public FrameBodyAPIC(byte textEncoding, String mimeType, byte pictureType, String description, byte[] data) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setMimeType(mimeType); - this.setPictureType(pictureType); - this.setDescription(description); - this.setImageData(data); - } - - /** - * Creates a new FrameBodyAPIC datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyAPIC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public String getUserFriendlyValue() { - return getMimeType() + ":" + getDescription() + ":" + getImageData().length; - } - - /** - * Get a description of the image - * - * @return a description of the image - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set a description of the image - * - * @param description - */ - public void setDescription(String description) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * Get mimetype - * - * @return a description of the image - */ - public String getMimeType() { - return (String) getObjectValue(DataTypes.OBJ_MIME_TYPE); - } - - /** - * Set mimeType - * - * @param mimeType - */ - public void setMimeType(String mimeType) { - setObjectValue(DataTypes.OBJ_MIME_TYPE, mimeType); - } - - /** - * Get Image data - * - * @return - */ - public byte[] getImageData() { - return (byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA); - } - - /** - * Set imageData - * - * @param imageData - */ - public void setImageData(byte[] imageData) { - setObjectValue(DataTypes.OBJ_PICTURE_DATA, imageData); - } - - /** - * @return picturetype - */ - public int getPictureType() { - return ((Long) getObjectValue(DataTypes.OBJ_PICTURE_TYPE)).intValue(); - } - - /** - * Set Picture Type - * - * @param pictureType - */ - public void setPictureType(byte pictureType) { - setObjectValue(DataTypes.OBJ_PICTURE_TYPE, pictureType); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ATTACHED_PICTURE; - } - - - /** - * If the description cannot be encoded using current encoder, change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_MIME_TYPE, this)); - objectList.add(new NumberHashMap(DataTypes.OBJ_PICTURE_TYPE, this, PictureTypes.PICTURE_TYPE_FIELD_SIZE)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_PICTURE_DATA, this)); - } - - /** - * @return true if imagedata is held as a url rather than actually being imagedata - */ - public boolean isImageUrl() { - return getMimeType() != null && getMimeType().equals(IMAGE_IS_URL); - } - - /** - * @return the image url if there is otherwise return an empty String - */ - public String getImageUrl() { - if (isImageUrl()) { - return Utils.getString(((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)), 0, ((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)).length, TextEncoding.CHARSET_ISO_8859_1); - } else { - return ""; - } - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java deleted file mode 100644 index f686b5e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.datatype.NumberVariableLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Audio files with variable bit rates are intrinsically difficult to - * deal with in the case of seeking within the file. The ASPI frame - * makes seeking easier by providing a list a seek points within the - * audio file. The seek points are a fractional offset within the audio - * data, providing a starting point from which to find an appropriate - * point to start decoding. The presence of an ASPI frame requires the - * existence of a TLEN frame, indicating the duration of the file in - * milliseconds. There may only be one 'audio seek point index' frame in - * a tag. - *

    - *

    - * Indexed data start (S) $xx xx xx xx - * Indexed data length (L) $xx xx xx xx - * Number of index points (N) $xx xx - * Bits per index point (b) $xx - *

    - * Then for every index point the following data is included; - *

    - * Fraction at index (Fi) $xx (xx) - *

    - * 'Indexed data start' is a byte offset from the beginning of the file. - * 'Indexed data length' is the byte length of the audio data being - * indexed. 'Number of index points' is the number of index points, as - * the name implies. The recommended number is 100. 'Bits per index - * point' is 8 or 16, depending on the chosen precision. 8 bits works - * well for short files (less than 5 minutes of audio), while 16 bits is - * advantageous for long files. 'Fraction at index' is the numerator of - * the fraction representing a relative position in the data. The - * denominator is 2 to the power of b. - *

    - * Here are the algorithms to be used in the calculation. The known data - * must be the offset of the start of the indexed data (S), the offset - * of the end of the indexed data (E), the number of index points (N), - * the offset at index i (Oi). We calculate the fraction at index i - * (Fi). - *

    - * Oi is the offset of the frame whose start is soonest after the point - * for which the time offset is (i/N * duration). - *

    - * The frame data should be calculated as follows: - *

    - * Fi = Oi/L * 2^b (rounded down to the nearest integer) - *

    - * Offset calculation should be calculated as follows from data in the - * frame: - *

    - * Oi = (Fi/2^b)*L (rounded up to the nearest integer) - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyASPI.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyASPI extends AbstractID3v2FrameBody implements ID3v24FrameBody { - private static final int DATA_START_FIELD_SIZE = 4; - private static final int DATA_LENGTH_FIELD_SIZE = 4; - private static final int NO_OF_INDEX_POINTS_FIELD_SIZE = 2; - private static final int BITS_PER_INDEX_POINTS_FIELD_SIZE = 1; - private static final int FRACTION_AT_INDEX_MINIMUM_FIELD_SIZE = 1; - private static final String INDEXED_DATA_START = "IndexedDataStart"; - private static final String INDEXED_DATA_LENGTH = "IndexedDataLength"; - private static final String NUMBER_OF_INDEX_POINTS = "NumberOfIndexPoints"; - private static final String BITS_PER_INDEX_POINT = "BitsPerIndexPoint"; - private static final String FRACTION_AT_INDEX = "FractionAtIndex"; - - /** - * Creates a new FrameBodyASPI datatype. - */ - public FrameBodyASPI() { - } - - /** - * Creates a new FrameBodyASPI from another FrameBodyASPI - * - * @param copyObject - */ - public FrameBodyASPI(FrameBodyASPI copyObject) { - super(copyObject); - } - - /** - * Creates a new FrameBodyASPI datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyASPI(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_AUDIO_SEEK_POINT_INDEX; - } - - - protected void setupObjectList() { - objectList.add(new NumberFixedLength(INDEXED_DATA_START, this, DATA_START_FIELD_SIZE)); - objectList.add(new NumberFixedLength(INDEXED_DATA_LENGTH, this, DATA_LENGTH_FIELD_SIZE)); - objectList.add(new NumberFixedLength(NUMBER_OF_INDEX_POINTS, this, NO_OF_INDEX_POINTS_FIELD_SIZE)); - objectList.add(new NumberFixedLength(BITS_PER_INDEX_POINT, this, BITS_PER_INDEX_POINTS_FIELD_SIZE)); - objectList.add(new NumberVariableLength(FRACTION_AT_INDEX, this, FRACTION_AT_INDEX_MINIMUM_FIELD_SIZE)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java deleted file mode 100644 index 9502039..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Horizon Wimba Copyright (C)2006 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v2ChapterFrames; - -import java.nio.ByteBuffer; - -/** - * Chapter frame. - *

    - *

    - * The purpose of this frame is to describe a single chapter within an - * audio file. There may be more than one frame of this type in a tag - * but each must have an Element ID that is unique with respect to any - * other "CHAP" frame or "CTOC" frame in the tag. - *

    - * - * - * - * - * - * - * - * - *
    <ID3v2.3 or ID3v2.4 frame header, ID: "CHAP">  (10 bytes)
    Element ID<text string> $00
    Start time$xx xx xx xx
    End time$xx xx xx xx
    Start offset$xx xx xx xx
    End offset$xx xx xx xx
    <Optional embedded sub-frames>
    - *

    - * The Element ID uniquely identifies the frame. It is not intended to - * be human readable and should not be presented to the end user. - *

    - * The Start and End times are a count in milliseconds from the - * beginning of the file to the start and end of the chapter - * respectively. - *

    - * The Start offset is a zero-based count of bytes from the beginning - * of the file to the first byte of the first audio frame in the - * chapter. If these bytes are all set to 0xFF then the value should be - * ignored and the start time value should be utilized. - *

    - * The End offset is a zero-based count of bytes from the beginning of - * the file to the first byte of the audio frame following the end of - * the chapter. If these bytes are all set to 0xFF then the value should - * be ignored and the end time value should be utilized. - *

    - * There then follows a sequence of optional frames that are embedded - * within the "CHAP" frame and which describe the content of the chapter - * (e.g. a "TIT2" frame representing the chapter name) or provide - * related material such as URLs and images. These sub-frames are - * contained within the bounds of the "CHAP" frame as signalled by the - * size field in the "CHAP" frame header. If a parser does not recognise - * "CHAP" frames it can skip them using the size field in the frame - * header. When it does this it will skip any embedded sub-frames - * carried within the frame. - *

    - *

    - *

    For more details, please refer to the ID3 Chapter Frame specifications: - *

    - * - * @author Marc Gimpel, Horizon Wimba S.A. - * @version $Id: FrameBodyCHAP.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyCHAP extends AbstractID3v2FrameBody implements ID3v2ChapterFrameBody { - /** - * Creates a new FrameBodyCHAP datatype. - */ - public FrameBodyCHAP() { - } - - /** - * Creates a new FrameBodyCHAP datatype. - * - * @param body - */ - public FrameBodyCHAP(FrameBodyCHAP body) { - super(body); - } - - /** - * Creates a new FrameBodyCHAP datatype. - * - * @param elementId - * @param startTime - * @param endTime - * @param startOffset - * @param endOffset - */ - public FrameBodyCHAP(String elementId, int startTime, int endTime, int startOffset, int endOffset) { - this.setObjectValue(DataTypes.OBJ_ELEMENT_ID, elementId); - this.setObjectValue(DataTypes.OBJ_START_TIME, startTime); - this.setObjectValue(DataTypes.OBJ_END_TIME, endTime); - this.setObjectValue(DataTypes.OBJ_START_OFFSET, startOffset); - this.setObjectValue(DataTypes.OBJ_END_OFFSET, endOffset); - } - - /** - * Creates a new FrameBodyAENC datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyCHAP(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v2ChapterFrames.FRAME_ID_CHAPTER; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_ELEMENT_ID, this)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_START_TIME, this, 4)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_END_TIME, this, 4)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_START_OFFSET, this, 4)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_END_OFFSET, this, 4)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java deleted file mode 100644 index e9918ff..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.Languages; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.List; - -/** - * Comments frame. - *

    - *

    - * This frame is intended for any kind of full text information that does not fit in any other frame. It consists of a - * frame header followed by encoding, language and content descriptors and is ended with the actual comment as a - * text string. Newline characters are allowed in the comment text string. There may be more than one comment frame - * in each tag, but only one with the same language and* content descriptor. - *

    - *

    - * - * - * - * - * - *
    <Header for 'Comment', ID: "COMM">
    Text encoding $xx
    Language $xx xx xx
    Short content descrip.<text string according to encoding> $00 (00)
    The actual text <full text string according to encoding>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyCOMM.java 1030 2012-03-01 12:51:57Z paultaylor $ - */ -public class FrameBodyCOMM extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - //Most players only read comment with description of blank - public static final String DEFAULT = ""; - - //used by iTunes for volume normalization, although uses the COMMENT field not usually displayed as a comment - public static final String ITUNES_NORMALIZATION = "iTunNORM"; - public static final String MM_CUSTOM1 = "Songs-DB_Custom1"; - public static final String MM_CUSTOM2 = "Songs-DB_Custom2"; - public static final String MM_CUSTOM3 = "Songs-DB_Custom3"; - public static final String MM_CUSTOM4 = "Songs-DB_Custom4"; - public static final String MM_CUSTOM5 = "Songs-DB_Custom5"; - public static final String MM_OCCASION = "Songs-DB_Occasion"; - public static final String MM_QUALITY = "Songs-DB_Preference"; - public static final String MM_TEMPO = "Songs-DB_Tempo"; - //Various descriptions used by MediaMonkey, (note Media Monkey uses non-standard language field XXX) - private static final String MM_PREFIX = "Songs-DB"; - - /** - * Creates a new FrameBodyCOMM datatype. - */ - public FrameBodyCOMM() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_LANGUAGE, Languages.DEFAULT_ID); - setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - setObjectValue(DataTypes.OBJ_TEXT, ""); - } - - public FrameBodyCOMM(FrameBodyCOMM body) { - super(body); - } - - - /** - * Creates a new FrameBodyCOMM datatype. - * - * @param textEncoding - * @param language - * @param description - * @param text - */ - public FrameBodyCOMM(byte textEncoding, String language, String description, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - setObjectValue(DataTypes.OBJ_TEXT, text); - } - - /** - * Construct a Comment frame body from the buffer - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyCOMM(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public boolean isMediaMonkeyFrame() { - String desc = getDescription(); - if (desc != null && !(desc.length() == 0)) { - if (desc.startsWith(MM_PREFIX)) { - return true; - } - } - return false; - } - - public boolean isItunesFrame() { - String desc = getDescription(); - if (desc != null && !(desc.length() == 0)) { - if (desc.equals(ITUNES_NORMALIZATION)) { - return true; - } - } - return false; - } - - /** - * Get the description field, which describes the type of comment - * - * @return description field - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set the description field, which describes the type of comment - * - * @param description - */ - public void setDescription(String description) { - if (description == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_COMMENT; - } - - /** - * Get the language the comment is written in - * - * @return the language - */ - public String getLanguage() { - return (String) getObjectValue(DataTypes.OBJ_LANGUAGE); - } - - /** - * Sets the language the comment is written in - * - * @param language - */ - public void setLanguage(String language) { - //TODO not sure if this might break existing code - /*if(language==null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } */ - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - } - - /** - * Returns the the text field which holds the comment, adjusted to ensure does not return trailing null - * which is due to a iTunes bug. - * - * @return the text field - */ - public String getText() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueAtIndex(0); - } - - /** - * @param text - */ - public void setText(String text) { - if (text == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - setObjectValue(DataTypes.OBJ_TEXT, text); - } - - public String getUserFriendlyValue() { - return getText(); - } - - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringHashMap(DataTypes.OBJ_LANGUAGE, this, Languages.LANGUAGE_FIELD_SIZE)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new TextEncodedStringSizeTerminated(DataTypes.OBJ_TEXT, this)); - } - - /** - * Because COMM have a text encoding we need to check the text String does - * not contain characters that cannot be encoded in current encoding before - * we write data. If there are we change the encoding. - */ - public void write(ByteArrayOutputStream tagBuffer) { - //Ensure valid for type - setTextEncoding(ID3TextEncodingConversion.getTextEncoding(getHeader(), getTextEncoding())); - - //Ensure valid for data - if (!((AbstractString) getObject(DataTypes.OBJ_TEXT)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - super.write(tagBuffer); - } - - /** - * Retrieve the complete text String but without any trailing nulls - *

    - * If multiple values are held these will be returned, needless trailing nulls will not be returned - * - * @return the text string - */ - public String getTextWithoutTrailingNulls() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueWithoutTrailingNull(); - } - - /** - * Get first value - * - * @return value at index 0 - */ - public String getFirstTextValue() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueAtIndex(0); - } - - /** - * Get text value at index - *

    - * When a multiple values are stored within a single text frame this method allows access to any of the - * individual values. - * - * @param index - * @return value at index - */ - public String getValueAtIndex(int index) { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValueAtIndex(index); - } - - public List getValues() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValues(); - } - - /** - * Add additional value to value - * - * @param value at index - */ - public void addTextValue(String value) { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - text.addValue(value); - } - - /** - * @return number of text values, usually one - */ - public int getNumberOfValues() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getNumberOfValues(); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java deleted file mode 100644 index 29e64c3..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.ReceivedAsTypes; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * Commercial frame. - *

    - *

    - * This frame enables several competing offers in the same tag by - * bundling all needed information. That makes this frame rather complex - * but it's an easier solution than if one tries to achieve the same - * result with several frames. The frame begins, after the frame ID, - * size and encoding fields, with a price string field. A price is - * constructed by one three character currency code, encoded according - * to ISO-4217 alphabetic currency code, followed by a - * numerical value where "." is used as decimal seperator. In the price - * string several prices may be concatenated, seperated by a "/" - * character, but there may only be one currency of each type. - *

    - * The price string is followed by an 8 character date string in the - * format YYYYMMDD, describing for how long the price is valid. After - * that is a contact URL, with which the user can contact the seller, - * followed by a one byte 'received as' field. It describes how the - * audio is delivered when bought according to the following list: - *

    - * - * - * - * - * - * - * - * - * - *
    $00 Other
    $01 Standard CD album with other songs
    $02 Compressed audio on CD
    $03 File over the Internet
    $04 Stream over the Internet
    $05 As note sheets
    $06 As note sheets in a book with other sheets
    $07 Music on other media
    $08 Non-musical merchandise

    - * Next follows a terminated string with the name of the seller followed - * by a terminated string with a short description of the product. The - * last thing is the ability to include a company logotype. The first of - * them is the 'Picture MIME type' field containing information about - * which picture format is used. In the event that the MIME media type - * name is omitted, "image/" will be implied. Currently only "image/png" - * and "image/jpeg" are allowed. This format string is followed by the - * binary picture data. This two last fields may be omitted if no - * picture is to attach. - *

    - * - * - * - * - * - * - * - * - * - * - *
    <Header for 'Commercial frame', ID: "COMR">
    Text encoding $xx
    Price string <text string> $00
    Valid until <text string>
    Contact URL <text string> $00
    Received as $xx
    Name of seller<text string according to encoding> $00 (00)
    Description <text string according to encoding> $00 (00)
    Picture MIME type<string> $00
    Seller logo <binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyCOMR.java 867 2010-01-28 16:27:11Z paultaylor $ - */ -public class FrameBodyCOMR extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyCOMR datatype. - */ - public FrameBodyCOMR() { - // this.setObject("Text Encoding", new Byte((byte) 0)); - // this.setObject("Price String", ""); - // this.setObject("Valid Until", ""); - // this.setObject("Contact URL", ""); - // this.setObject("Recieved As", new Byte((byte) 0)); - // this.setObject("Name Of Seller", ""); - // this.setObject(ObjectTypes.OBJ_DESCRIPTION, ""); - // this.setObject("Picture MIME Type", ""); - // this.setObject("Seller Logo", new byte[0]); - } - - public FrameBodyCOMR(FrameBodyCOMR body) { - super(body); - } - - /** - * Creates a new FrameBodyCOMR datatype. - * - * @param textEncoding - * @param priceString - * @param validUntil - * @param contactUrl - * @param recievedAs - * @param nameOfSeller - * @param description - * @param mimeType - * @param sellerLogo - */ - public FrameBodyCOMR(byte textEncoding, String priceString, String validUntil, String contactUrl, byte recievedAs, String nameOfSeller, String description, String mimeType, byte[] sellerLogo) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setObjectValue(DataTypes.OBJ_PRICE_STRING, priceString); - this.setObjectValue(DataTypes.OBJ_VALID_UNTIL, validUntil); - this.setObjectValue(DataTypes.OBJ_CONTACT_URL, contactUrl); - this.setObjectValue(DataTypes.OBJ_RECIEVED_AS, recievedAs); - this.setObjectValue(DataTypes.OBJ_SELLER_NAME, nameOfSeller); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - this.setObjectValue(DataTypes.OBJ_MIME_TYPE, mimeType); - this.setObjectValue(DataTypes.OBJ_SELLER_LOGO, sellerLogo); - } - - /** - * Creates a new FrameBodyCOMR datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyCOMR(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_COMMERCIAL_FRAME; - } - - /** - * @return - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * @param description - */ - public void getOwner(String description) { - setObjectValue(DataTypes.OBJ_OWNER, description); - } - - /** - * If the seller or description cannot be encoded using current encoder, change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((AbstractString) getObject(DataTypes.OBJ_SELLER_NAME)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_PRICE_STRING, this)); - objectList.add(new StringDate(DataTypes.OBJ_VALID_UNTIL, this)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_CONTACT_URL, this)); - objectList.add(new NumberHashMap(DataTypes.OBJ_RECIEVED_AS, this, ReceivedAsTypes.RECEIVED_AS_FIELD_SIZE)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_SELLER_NAME, this)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_MIME_TYPE, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_SELLER_LOGO, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java deleted file mode 100644 index 2743c6f..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyCRM.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v22Frames; - -import java.nio.ByteBuffer; - -/** - * Encrypted meta frame - *

    - * This frame contains one or more encrypted frames. This enables - * protection of copyrighted information such as pictures and text, that - * people might want to pay extra for. Since standardisation of such an - * encryption scheme is beyond this document, all "CRM" frames begin with - * a terminated string with a URL [URL] containing an email address, or a - * link to a location where an email adress can be found, that belongs to - * the organisation responsible for this specific encrypted meta frame. - *

    - * Questions regarding the encrypted frame should be sent to the - * indicated email address. If a $00 is found directly after the 'Frame - * size', the whole frame should be ignored, and preferably be removed. - * The 'Owner identifier' is then followed by a short content description - * and explanation as to why it's encrypted. After the - * 'content/explanation' description, the actual encrypted block follows. - *

    - * When an ID3v2 decoder encounters a "CRM" frame, it should send the - * datablock to the 'plugin' with the corresponding 'owner identifier' - * and expect to receive either a datablock with one or several ID3v2 - * frames after each other or an error. There may be more than one "CRM" - * frames in a tag, but only one with the same 'owner identifier'. - *

    - * Encrypted meta frame "CRM" - * Frame size $xx xx xx - * Owner identifier $00 (00) - * Content/explanation $00 (00) - * Encrypted datablock - */ -public class FrameBodyCRM extends AbstractID3v2FrameBody implements ID3v22FrameBody { - /** - * Creates a new FrameBodyCRM datatype. - */ - public FrameBodyCRM() { - // this.setObject(ObjectTypes.OBJ_OWNER, ""); - // this.setObject(ObjectTypes.OBJ_DESCRIPTION, ""); - // this.setObject("Encrypted datablock", new byte[0]); - } - - public FrameBodyCRM(FrameBodyCRM body) { - super(body); - } - - /** - * Creates a new FrameBodyCRM datatype. - * - * @param owner - * @param description - * @param data - */ - public FrameBodyCRM(String owner, String description, byte[] data) { - this.setObjectValue(DataTypes.OBJ_OWNER, owner); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - this.setObjectValue(DataTypes.OBJ_ENCRYPTED_DATABLOCK, data); - } - - /** - * Creates a new FrameBodyCRM datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyCRM(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v22Frames.FRAME_ID_V2_ENCRYPTED_FRAME; - } - - /** - * @return - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * @param description - */ - public void getOwner(String description) { - setObjectValue(DataTypes.OBJ_OWNER, description); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_ENCRYPTED_DATABLOCK, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java deleted file mode 100644 index b382d3d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Horizon Wimba Copyright (C)2006 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v2ChapterFrames; - -import java.nio.ByteBuffer; - -/** - * Table of content frame. - *

    - *

    - * The purpose of "CTOC" frames is to allow a table of contents to be - * defined. In the simplest case, a single "CTOC" frame can be used to - * provide a flat (single-level) table of contents. However, multiple - * "CTOC" frames can also be used to define a hierarchical (multi-level) - * table of contents. - *

    - * There may be more than one frame of this type in a tag but each must - * have an Element ID that is unique with respect to any other "CTOC" or - * "CHAP" frame in the tag. - *

    - * Each "CTOC" frame represents one level or element of a table of contents - * by providing a list of Child Element IDs. These match the Element IDs of - * other "CHAP" and "CTOC" frames in the tag. - *

    - * - * - * - * - * - * - * - *
    <ID3v2.3 or ID3v2.4 frame header, ID: "CTOC">  (10 bytes)
    Element ID<text string> $00
    Flags%000000ab
    Entry count$xx  (8-bit unsigned int)
    <Child Element ID list>
    <Optional embedded sub-frames>
    - *

    - * The Element ID uniquely identifies the frame. It is not intended to - * be human readable and should not be presented to the end-user. - *

    - * Flag a - Top-level bit
    - * This is set to 1 to identify the top-level "CTOC" frame. This frame - * is the root of the Table of Contents tree and is not a child of any - * other "CTOC" frame. Only one "CTOC" frame in an ID3v2 tag can have - * this bit set to 1. In all other "CTOC" frames this bit shall be set - * to 0. - *

    - * Flag b - Ordered bit
    - * This should be set to 1 if the entries in the Child Element ID list - * are ordered or set to 0 if they not are ordered. This provides a hint - * as to whether the elements should be played as a continuous ordered - * sequence or played individually. - *

    - * The Entry count is the number of entries in the Child Element ID list - * that follows and must be greater than zero. Each entry in the list - * consists of: - *

    - * - * - *
    Child Element ID  <text string> $00
    - *

    - * The last entry in the child Element ID list is followed by a sequence - * of optional frames that are embedded within the "CTOC" frame and which - * describe this element of the table of contents (e.g. a "TIT2" frame - * representing the name of the element) or provide related material such - * as URLs and images. These sub-frames are contained within the bounds - * of the "CTOC" frame as signalled by the size field in the "CTOC" - * frame header. - *

    - * If a parser does not recognise "CTOC" frames it can skip them using - * the size field in the frame header. When it does this it will skip - * any embedded sub-frames carried within the frame. - *

    - *

    - *

    For more details, please refer to the ID3 Chapter Frame specifications: - *

    - * - * @author Marc Gimpel, Horizon Wimba S.A. - * @version $Id: FrameBodyCTOC.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyCTOC extends AbstractID3v2FrameBody implements ID3v2ChapterFrameBody { - /** - * Creates a new FrameBodyCTOC datatype. - */ - public FrameBodyCTOC() { - } - - /** - * Creates a new FrameBodyCTOC datatype. - * - * @param body - */ - public FrameBodyCTOC(FrameBodyCTOC body) { - super(body); - } - - /** - * Creates a new FrameBodyCTOC datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyCTOC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v2ChapterFrames.FRAME_ID_TABLE_OF_CONTENT; - } - - /** - * TODO:proper mapping - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java deleted file mode 100644 index 4cba53d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -/** - * Represents a frameBody for a frame identifier that is not defined for the tag version but was valid for a for an - * earlier tag version. - * The body consists of an array of bytes representing all the bytes in the body. - */ -public class FrameBodyDeprecated extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * The original frameBody is held so can be retrieved - * when converting a DeprecatedFrameBody back to a normal framebody - */ - private AbstractID3v2FrameBody originalFrameBody; - - - /** - * Creates a new FrameBodyDeprecated wrapper around the frameBody - * - * @param frameBody - */ - public FrameBodyDeprecated(AbstractID3v2FrameBody frameBody) { - this.originalFrameBody = frameBody; - } - - /** - * Copy constructor - * - * @param copyObject a copy is made of this - */ - public FrameBodyDeprecated(FrameBodyDeprecated copyObject) { - super(copyObject); - } - - - /** - * Return the frame identifier - * - * @return the identifier - */ - public String getIdentifier() { - return originalFrameBody.getIdentifier(); - } - - /** - * Delgate size to size of original frameBody, if frameBody already exist will take this value from the frame header - * but it is always recalculated before writing any changes back to disk. - * - * @return size in bytes of this frame body - */ - public int getSize() { - return originalFrameBody.getSize(); - } - - /** - * @param obj - * @return whether obj is equivalent to this object - */ - public boolean equals(Object obj) { - if (!(obj instanceof FrameBodyDeprecated)) { - return false; - } - - FrameBodyDeprecated object = (FrameBodyDeprecated) obj; - return this.getIdentifier().equals(object.getIdentifier()) && super.equals(obj); - } - - /** - * Return the original frameBody that was used to construct the DeprecatedFrameBody - * - * @return the original frameBody - */ - public AbstractID3v2FrameBody getOriginalFrameBody() { - return originalFrameBody; - } - - /** - * Because the contents of this frame are an array of bytes and could be large we just - * return the identifier. - * - * @return a string representation of this frame - */ - public String toString() { - return getIdentifier(); - } - - /** - * Setup the Object List. - *

    - * This is handled by the wrapped class - */ - protected void setupObjectList() { - - } - - public String getBriefDescription() { - //TODO When is this null, it seems it can be but Im not sure why - if (originalFrameBody != null) { - return originalFrameBody.getBriefDescription(); - } - return ""; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java deleted file mode 100644 index 5d576ec..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Encryption method registration frame. - *

    - *

    - * To identify with which method a frame has been encrypted the - * encryption method must be registered in the tag with this frame. The - * 'Owner identifier' is a null-terminated string with a URL - * containing an email address, or a link to a location where an email - * address can be found, that belongs to the organisation responsible - * for this specific encryption method. Questions regarding the - * encryption method should be sent to the indicated email address. The - * 'Method symbol' contains a value that is associated with this method - * throughout the whole tag. Values below $80 are reserved. The 'Method - * symbol' may optionally be followed by encryption specific data. There - * may be several "ENCR" frames in a tag but only one containing the - * same symbol and only one containing the same owner identifier. The - * method must be used somewhere in the tag. See section 3.3.1, flag j - * for more information. - *

    - * - * - * - * - *
    <Header for 'Encryption method registration', ID: "ENCR">
    Owner identifier<text string> $00
    Method symbol $xx
    Encryption data <binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyENCR.java 857 2009-12-03 11:21:11Z paultaylor $ - */ -public class FrameBodyENCR extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyENCR datatype. - */ - public FrameBodyENCR() { - this.setObjectValue(DataTypes.OBJ_OWNER, ""); - this.setObjectValue(DataTypes.OBJ_METHOD_SYMBOL, (byte) 0); - this.setObjectValue(DataTypes.OBJ_ENCRYPTION_INFO, new byte[0]); - } - - public FrameBodyENCR(FrameBodyENCR body) { - super(body); - } - - /** - * Creates a new FrameBodyENCR datatype. - * - * @param owner - * @param methodSymbol - * @param data - */ - public FrameBodyENCR(String owner, byte methodSymbol, byte[] data) { - this.setObjectValue(DataTypes.OBJ_OWNER, owner); - this.setObjectValue(DataTypes.OBJ_METHOD_SYMBOL, methodSymbol); - this.setObjectValue(DataTypes.OBJ_ENCRYPTION_INFO, data); - } - - /** - * Creates a new FrameBodyENCR datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyENCR(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ENCRYPTION; - } - - /** - * @return - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * @param owner - */ - public void setOwner(String owner) { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_METHOD_SYMBOL, this, 1)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_ENCRYPTION_INFO, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java deleted file mode 100644 index ac32760..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyEQU2.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - * Equalisation (2) - *

    - * This is another subjective, alignment frame. It allows the user to - * predefine an equalisation curve within the audio file. There may be - * more than one "EQU2" frame in each tag, but only one with the same - * identification string. - *

    - *

    - * Interpolation method $xx - * Identification $00 - *

    - * The 'interpolation method' describes which method is preferred when - * an interpolation between the adjustment point that follows. The - * following methods are currently defined: - *

    - * $00 Band - * No interpolation is made. A jump from one adjustment level to - * another occurs in the middle between two adjustment points. - * $01 Linear - * Interpolation between adjustment points is linear. - *

    - * The 'identification' string is used to identify the situation and/or - * device where this adjustment should apply. The following is then - * repeated for every adjustment point - *

    - * Frequency $xx xx - * Volume adjustment $xx xx - *

    - * The frequency is stored in units of 1/2 Hz, giving it a range from 0 - * to 32767 Hz. - *

    - * The volume adjustment is encoded as a fixed point decibel value, 16 - * bit signed integer representing (adjustment*512), giving +/- 64 dB - * with a precision of 0.001953125 dB. E.g. +2 dB is stored as $04 00 - * and -2 dB is $FC 00. - *

    - * Adjustment points should be ordered by frequency and one frequency - * should only be described once in the frame. - */ -public class FrameBodyEQU2 extends AbstractID3v2FrameBody implements ID3v24FrameBody { - /** - * Creates a new FrameBodyEQU2 datatype. - */ - public FrameBodyEQU2() { - - } - - public FrameBodyEQU2(FrameBodyEQU2 body) { - super(body); - } - - /** - * Creates a new FrameBodyEQU2 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyEQU2(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_EQUALISATION2; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java deleted file mode 100644 index 803ed0c..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -/** - * Equalisation frame. - *

    - *

    - * This is another subjective, alignment frame. It allows the user to - * predefine an equalisation curve within the audio file. There may only - * be one "EQUA" frame in each tag. - *

    - * - * - *
    <Header of 'Equalisation', ID: "EQUA">
    Adjustment bits$xx

    - * The 'adjustment bits' field defines the number of bits used for - * representation of the adjustment. This is normally $10 (16 bits) for - * MPEG 2 layer I, II and III and MPEG 2.5. This value may not be - * $00. - *

    - * This is followed by 2 bytes + ('adjustment bits' rounded up to the - * nearest byte) for every equalisation band in the following format, - * giving a frequency range of 0 - 32767Hz: - *

    - * - * - * - *
    Increment/decrement%x (MSB of the Frequency)
    Frequency (lower 15 bits)
    Adjustment$xx (xx ...)

    - * The increment/decrement bit is 1 for increment and 0 for decrement. - * The equalisation bands should be ordered increasingly with reference - * to frequency. All frequencies don't have to be declared. The - * equalisation curve in the reading software should be interpolated - * between the values in this frame. Three equal adjustments for three - * subsequent frequencies. A frequency should only be described once in - * the frame. - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyEQUA.java 905 2010-05-14 19:37:31Z paultaylor $ - */ -public class FrameBodyEQUA extends AbstractID3v2FrameBody implements ID3v23FrameBody { - /** - * Creates a new FrameBodyEQUA dataType. - */ - public FrameBodyEQUA() { - } - - public FrameBodyEQUA(FrameBodyEQUA body) { - super(body); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_EQUALISATION; - } - - /** - * TODO:proper mapping - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java deleted file mode 100644 index 74bdd54..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Event timing codes frame. - *

    - *

    - * This frame allows synchronisation with key events in a song or sound. - * The header is: - *

    - * - * - *
    <Header for 'Event timing codes', ID: "ETCO">
    Time stamp format$xx

    - * Where time stamp format is: - *

    - * $01 Absolute time, 32 bit sized, using MPEG frames as unit
    - * $02 Absolute time, 32 bit sized, using milliseconds as unit - *

    - * Abolute time means that every stamp contains the time from the - * beginning of the file. - *

    - * Followed by a list of key events in the following format: - *

    - * - * - *
    Type of event$xx
    Time stamp$xx (xx ...)

    - * The 'Time stamp' is set to zero if directly at the beginning of the - * sound or after the previous event. All events should be sorted in - * chronological order. The type of event is as follows: - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    $00 padding (has no meaning)
    $01 end of initial silence
    $02 intro start
    $03 mainpart start
    $04 outro start
    $05 outro end
    $06 verse start
    $07 refrain start
    $08 interlude start
    $09 theme start
    $0A variation start
    $0B key change
    $0C time change
    $0D momentary unwanted noise (Snap, Crackle & Pop)
    $0E sustained noise
    $0F sustained noise end
    $10 intro end
    $11 mainpart end
    $12 verse end
    $13 refrain end
    $14 theme end
    $15-$DFreserved for future use
    $E0-$EFnot predefined sync 0-F
    $F0-$FCreserved for future use
    $FD audio end (start of silence)
    $FE audio file ends
    $FFone more byte of events follows (all the following bytes with the value $FF have the same function)
    - *

    - * Terminating the start events such as "intro start" is not required. - * The 'Not predefined sync's ($E0-EF) are for user events. You might - * want to synchronise your music to something, like setting of an - * explosion on-stage, turning on your screensaver etc. - *

    - * There may only be one "ETCO" frame in each tag.

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyETCO.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyETCO extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyETCO datatype. - */ - public FrameBodyETCO() { - - } - - public FrameBodyETCO(FrameBodyETCO body) { - super(body); - } - - /** - * Creates a new FrameBodyETCO datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyETCO(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_EVENT_TIMING_CODES; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java deleted file mode 100644 index 82bfd48..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Jthink Copyright (C)2010 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; - -import java.nio.ByteBuffer; - -/** - * Encrypted frame. - *

    - *

    - * Container for an encrypted frame, we cannot decrypt encrypted frame but it may be possible - * for the calling application to decrypt the frame if they understand how it has been encrypted, - * information on this will be held within an ENCR frame - * - * @author : Paul Taylor - */ -public class FrameBodyEncrypted extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - private String identifier = null; - - /** - * Creates a new FrameBodyEncrypted dataType. - */ - public FrameBodyEncrypted(String identifier) { - this.identifier = identifier; - } - - public FrameBodyEncrypted(FrameBodyEncrypted body) { - super(body); - } - - /** - * Read from file - * - * @param identifier - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyEncrypted(String identifier, ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - this.identifier = identifier; - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return identifier; - } - - /** - * TODO:proper mapping - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java deleted file mode 100644 index 9254030..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * General encapsulated object frame. - *

    - *

    - * In this frame any type of file can be encapsulated. After the header, - * 'Frame size' and 'Encoding' follows 'MIME type' represented as - * as a terminated string encoded with ISO-8859-1. The - * filename is case sensitive and is encoded as 'Encoding'. Then follows - * a content description as terminated string, encoded as 'Encoding'. - * The last thing in the frame is the actual object. The first two - * strings may be omitted, leaving only their terminations. There may be more than one "GEOB" - * frame in each tag, but only one with the same content descriptor. - *

    - * - * - * - * - * - * - *
    <Header for 'General encapsulated object', ID: "GEOB">
    Text encoding $xx
    MIME type <text string> $00
    Filename <text string according to encoding> $00 (00)
    Content description $00 (00)
    Encapsulated object <binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyGEOB.java 836 2009-11-12 15:44:07Z paultaylor $ - */ -public class FrameBodyGEOB extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - - /** - * Creates a new FrameBodyGEOB datatype. - */ - public FrameBodyGEOB() { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - this.setObjectValue(DataTypes.OBJ_MIME_TYPE, ""); - this.setObjectValue(DataTypes.OBJ_FILENAME, ""); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - this.setObjectValue(DataTypes.OBJ_DATA, new byte[0]); - } - - public FrameBodyGEOB(FrameBodyGEOB body) { - super(body); - } - - /** - * Creates a new FrameBodyGEOB datatype. - * - * @param textEncoding - * @param mimeType - * @param filename - * @param description - * @param object - */ - public FrameBodyGEOB(byte textEncoding, String mimeType, String filename, String description, byte[] object) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setObjectValue(DataTypes.OBJ_MIME_TYPE, mimeType); - this.setObjectValue(DataTypes.OBJ_FILENAME, filename); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - this.setObjectValue(DataTypes.OBJ_DATA, object); - } - - /** - * Creates a new FrameBodyGEOB datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyGEOB(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return the description field - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * @param description - */ - public void setDescription(String description) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * @return - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_GENERAL_ENCAPS_OBJECT; - } - - - /** - * If the filename or description cannot be encoded using current encoder, change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((AbstractString) getObject(DataTypes.OBJ_FILENAME)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_MIME_TYPE, this)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_FILENAME, this)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java deleted file mode 100644 index 3170a3e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Group identification registration frame. - *

    - *

    - * This frame enables grouping of otherwise unrelated frames. This can - * be used when some frames are to be signed. To identify which frames - * belongs to a set of frames a group identifier must be registered in - * the tag with this frame. The 'Owner identifier' is a null-terminated - * string with a URL containing an email address, or a link to a - * location where an email address can be found, that belongs to the - * organisation responsible for this grouping. Questions regarding the - * grouping should be sent to the indicated email address. The 'Group - * symbol' contains a value that associates the frame with this group - * throughout the whole tag. Values below $80 are reserved. The 'Group - * symbol' may optionally be followed by some group specific data, e.g. - * a digital signature. There may be several "GRID" frames in a tag but - * only one containing the same symbol and only one containing the same - * owner identifier. The group symbol must be used somewhere in the tag. - * See section 3.3.1, flag j for more information. - *

    - * - * - * - * - *
    <Header for 'Group ID registration', ID: "GRID">
    Owner identifier <text string> $00
    Group symbol $xx
    Group dependent data <binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyGRID.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyGRID extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyGRID datatype. - */ - public FrameBodyGRID() { - // this.setObject(ObjectTypes.OBJ_OWNER, ""); - // this.setObject("Group Symbol", new Byte((byte) 0)); - // this.setObject("Group Dependent Data", new byte[0]); - } - - public FrameBodyGRID(FrameBodyGRID body) { - super(body); - } - - /** - * Creates a new FrameBodyGRID datatype. - * - * @param owner - * @param groupSymbol - * @param data - */ - public FrameBodyGRID(String owner, byte groupSymbol, byte[] data) { - this.setObjectValue(DataTypes.OBJ_OWNER, owner); - this.setObjectValue(DataTypes.OBJ_GROUP_SYMBOL, groupSymbol); - this.setObjectValue(DataTypes.OBJ_GROUP_DATA, data); - } - - /** - * Creates a new FrameBodyGRID datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyGRID(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return - */ - public byte getGroupSymbol() { - if (getObjectValue(DataTypes.OBJ_GROUP_SYMBOL) != null) { - return ((Long) getObjectValue(DataTypes.OBJ_GROUP_SYMBOL)).byteValue(); - } else { - return (byte) 0; - } - } - - /** - * @param textEncoding - */ - public void setGroupSymbol(byte textEncoding) { - setObjectValue(DataTypes.OBJ_GROUP_SYMBOL, textEncoding); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_GROUP_ID_REG; - } - - /** - * @return - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * @param owner - */ - public void setOwner(String owner) { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_GROUP_SYMBOL, this, 1)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_GROUP_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java deleted file mode 100644 index 46c9655..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.Pair; -import org.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v23Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.StringTokenizer; - -/** - * Involved People List ID3v22/v23 Only - *

    - * Since there might be a lot of people contributing to an audio file in various ways, such as musicians and technicians, - * the 'Text information frames' are often insufficient to list everyone involved in a project. - * The 'Involved people list' is a frame containing the names of those involved, and how they were involved. - * The body simply contains a terminated string with the involvement directly followed by a terminated string with - * the involvee followed by a new involvement and so on. There may only be one "IPLS" frame in each tag. - *

    - *

    - * Text encoding $xx - * People list strings - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyIPLS.java 923 2010-10-16 21:59:49Z paultaylor $ - */ -public class FrameBodyIPLS extends AbstractID3v2FrameBody implements ID3v23FrameBody { - /** - * Creates a new FrameBodyIPLS datatype. - */ - public FrameBodyIPLS() { - super(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - } - - public FrameBodyIPLS(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public FrameBodyIPLS(FrameBodyIPLS body) { - super(body); - } - - /** - * Creates a new FrameBodyIPLS data type. - * - * @param textEncoding - * @param text - */ - public FrameBodyIPLS(byte textEncoding, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setText(text); - } - - /** - * Convert from V4 to V3 Frame - * - * @param body - */ - public FrameBodyIPLS(FrameBodyTIPL body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - setText(body.getText()); - } - - /** - * The ID3v23 frame identifier - * - * @return the ID3v23 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_IPLS; - } - - public void addPair(String text) { - PairedTextEncodedStringNullTerminated.ValuePairs value = ((PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT)).getValue(); - StringTokenizer stz = new StringTokenizer(text, "\0"); - if (stz.hasMoreTokens()) { - value.add(stz.nextToken(), stz.nextToken()); - } - } - - /** - * Because have a text encoding we need to check the data values do not contain characters that cannot be encoded in - * current encoding before we write data. If they do change the encoding. - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * Consists of a text encoding , and then a series of null terminated Strings, there should be an even number - * of Strings as they are paired as involvement/involvee - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new PairedTextEncodedStringNullTerminated(DataTypes.OBJ_TEXT, this)); - } - - public PairedTextEncodedStringNullTerminated.ValuePairs getPairing() { - return (PairedTextEncodedStringNullTerminated.ValuePairs) getObject(DataTypes.OBJ_TEXT).getValue(); - } - - /** - * Get key at index - * - * @param index - * @return value at index - */ - public String getKeyAtIndex(int index) { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValue().getMapping().get(index).getKey(); - } - - /** - * Get value at index - * - * @param index - * @return value at index - */ - public String getValueAtIndex(int index) { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValue().getMapping().get(index).getValue(); - } - - /** - * @return number of text pairs - */ - public int getNumberOfPairs() { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValue().getNumberOfPairs(); - } - - public String getText() { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - StringBuilder sb = new StringBuilder(); - int count = 1; - for (Pair entry : text.getValue().getMapping()) { - sb.append(entry.getKey() + '\0' + entry.getValue()); - if (count != getNumberOfPairs()) { - sb.append('\0'); - } - count++; - } - return sb.toString(); - } - - /** - * Set the text, decoded as pairs of involvee - involvement - * - * @param text - */ - public void setText(String text) { - PairedTextEncodedStringNullTerminated.ValuePairs value = new PairedTextEncodedStringNullTerminated.ValuePairs(); - StringTokenizer stz = new StringTokenizer(text, "\0"); - while (stz.hasMoreTokens()) { - String key = stz.nextToken(); - if (stz.hasMoreTokens()) { - value.add(key, stz.nextToken()); - } - - } - setObjectValue(DataTypes.OBJ_TEXT, value); - } - - public String getUserFriendlyValue() { - return getText(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java deleted file mode 100644 index c9c7bbd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.StringFixedLength; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Linked information frame. - *

    - *

    - * To keep space waste as low as possible this frame may be used to link - * information from another ID3v2 tag that might reside in another audio - * file or alone in a binary file. It is recommended that this method is - * only used when the files are stored on a CD-ROM or other - * circumstances when the risk of file seperation is low. The frame - * contains a frame identifier, which is the frame that should be linked - * into this tag, a URL field, where a reference to the file where - * the frame is given, and additional ID data, if needed. Data should be - * retrieved from the first tag found in the file to which this link - * points. There may be more than one "LINK" frame in a tag, but only - * one with the same contents. A linked frame is to be considered as - * part of the tag and has the same restrictions as if it was a physical - * part of the tag (i.e. only one "RVRB" frame allowed, whether it's - * linked or not). - *

    - * - * - * - * - *
    <Header for 'Linked information', ID: "LINK">
    Frame identifier $xx xx xx
    URL <text string> $00
    ID and additional data<text string(s)>

    - *

    - * Frames that may be linked and need no additional data are "IPLS", - * "MCID", "ETCO", "MLLT", "SYTC", "RVAD", "EQUA", "RVRB", "RBUF", the - * text information frames and the URL link frames. - *

    - * The "TXXX", "APIC", "GEOB" and "AENC" frames may be linked with - * the content descriptor as additional ID data. - *

    - * The "COMM", "SYLT" and "USLT" frames may be linked with three bytes - * of language descriptor directly followed by a content descriptor as - * additional ID data. - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyLINK.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyLINK extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyLINK datatype. - */ - public FrameBodyLINK() { - // this.setObject("Frame Identifier", ""); - // this.setObject("URL", ""); - // this.setObject("ID and Additional Data", ""); - } - - public FrameBodyLINK(FrameBodyLINK body) { - super(body); - } - - /** - * Creates a new FrameBodyLINK datatype. - * - * @param frameIdentifier - * @param url - * @param additionalData - */ - public FrameBodyLINK(String frameIdentifier, String url, String additionalData) { - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, frameIdentifier); - this.setObjectValue(DataTypes.OBJ_URL, url); - this.setObjectValue(DataTypes.OBJ_ID, additionalData); - } - - /** - * Creates a new FrameBodyLINK datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyLINK(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return - */ - public String getAdditionalData() { - return (String) getObjectValue(DataTypes.OBJ_ID); - } - - /** - * @param additionalData - */ - public void getAdditionalData(String additionalData) { - setObjectValue(DataTypes.OBJ_ID, additionalData); - } - - /** - * @return - */ - public String getFrameIdentifier() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * @param frameIdentifier - */ - public void getFrameIdentifier(String frameIdentifier) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, frameIdentifier); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_LINKED_INFO; - } - - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringFixedLength(DataTypes.OBJ_DESCRIPTION, this, 4)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_URL, this)); - objectList.add(new StringSizeTerminated(DataTypes.OBJ_ID, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java deleted file mode 100644 index 4bca406..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Music CD identifier frame. - *

    - *

    - * This frame is intended for music that comes from a CD, so that the CD - * can be identified in databases such as the CDDB. The frame - * consists of a binary dump of the Table Of Contents, TOC, from the CD, - * which is a header of 4 bytes and then 8 bytes/track on the CD plus 8 - * bytes for the 'lead out' making a maximum of 804 bytes. The offset to - * the beginning of every track on the CD should be described with a - * four bytes absolute CD-frame address per track, and not with absolute - * time. This frame requires a present and valid "TRCK" frame, even if - * the CD's only got one track. There may only be one "MCDI" frame in - * each tag. - *

    - * - * - *
    <Header for 'Music CD identifier', ID: "MCDI">
    CD TOC<binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyMCDI.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyMCDI extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyMCDI datatype. - */ - public FrameBodyMCDI() { - this.setObjectValue(DataTypes.OBJ_DATA, new byte[0]); - } - - public FrameBodyMCDI(FrameBodyMCDI body) { - super(body); - } - - /** - * Creates a new FrameBodyMCDI datatype. - * - * @param cdTOC - */ - public FrameBodyMCDI(byte[] cdTOC) { - this.setObjectValue(DataTypes.OBJ_DATA, cdTOC); - } - - /** - * Creates a new FrameBodyMCDI datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyMCDI(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_MUSIC_CD_ID; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java deleted file mode 100644 index 1813729..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -/** - * MPEG location lookup table frame. - *

    - *

    - * To increase performance and accuracy of jumps within a MPEG - * audio file, frames with timecodes in different locations in the file - * might be useful. The ID3v2 frame includes references that the - * software can use to calculate positions in the file. After the frame - * header is a descriptor of how much the 'frame counter' should - * increase for every reference. If this value is two then the first - * reference points out the second frame, the 2nd reference the 4th - * frame, the 3rd reference the 6th frame etc. In a similar way the - * 'bytes between reference' and 'milliseconds between reference' points - * out bytes and milliseconds respectively. - *

    - * Each reference consists of two parts; a certain number of bits, as - * defined in 'bits for bytes deviation', that describes the difference - * between what is said in 'bytes between reference' and the reality and - * a certain number of bits, as defined in 'bits for milliseconds - * deviation', that describes the difference between what is said in - * 'milliseconds between reference' and the reality. The number of bits - * in every reference, i.e. 'bits for bytes deviation'+'bits for - * milliseconds deviation', must be a multiple of four. There may only - * be one "MLLT" frame in each tag. - *

    - * - * - * - * - * - * - *
    <Header for 'Location lookup table', ID: "MLLT">
    MPEG frames between reference$xx xx
    Bytes between reference$xx xx xx
    Milliseconds between reference$xx xx xx
    Bits for bytes deviation$xx
    Bits for milliseconds dev.$xx

    - * Then for every reference the following data is included; - *

    - * - * - *
    Deviation in bytes%xxx....
    Deviation in milliseconds%xxx....

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyMLLT.java 520 2008-01-01 15:16:38Z paultaylor $ - */ -public class FrameBodyMLLT extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyMLLT datatype. - */ - public FrameBodyMLLT() { - } - - public FrameBodyMLLT(FrameBodyMLLT body) { - super(body); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE; - } - - - /** - * TODO:proper mapping - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java deleted file mode 100644 index be588c6..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * Ownership frame. - *

    - *

    - * The ownership frame might be used as a reminder of a made transaction - * or, if signed, as proof. Note that the "USER" and "TOWN" frames are - * good to use in conjunction with this one. The frame begins, after the - * frame ID, size and encoding fields, with a 'price payed' field. The - * first three characters of this field contains the currency used for - * the transaction, encoded according to ISO-4217 alphabetic - * currency code. Concatenated to this is the actual price payed, as a - * numerical string using "." as the decimal separator. Next is an 8 - * character date string (YYYYMMDD) followed by a string with the name - * of the seller as the last field in the frame. There may only be one - * "OWNE" frame in a tag. - *

    - * - * - * - * - * - *
    <Header for 'Ownership frame', ID: "OWNE">
    Text encoding $xx
    Price payed <text string> $00
    Date of purch. <text string>
    Seller<text string according to encoding>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyOWNE.java 836 2009-11-12 15:44:07Z paultaylor $ - */ -public class FrameBodyOWNE extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyOWNE datatype. - */ - public FrameBodyOWNE() { - // this.setObject("Text Encoding", new Byte((byte) 0)); - // this.setObject("Price Paid", ""); - // this.setObject("Date Of Purchase", ""); - // this.setObject("Seller", ""); - } - - public FrameBodyOWNE(FrameBodyOWNE body) { - super(body); - } - - /** - * Creates a new FrameBodyOWNE datatype. - * - * @param textEncoding - * @param pricePaid - * @param dateOfPurchase - * @param seller - */ - public FrameBodyOWNE(byte textEncoding, String pricePaid, String dateOfPurchase, String seller) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setObjectValue(DataTypes.OBJ_PRICE_PAID, pricePaid); - this.setObjectValue(DataTypes.OBJ_PURCHASE_DATE, dateOfPurchase); - this.setObjectValue(DataTypes.OBJ_SELLER_NAME, seller); - } - - /** - * Creates a new FrameBodyOWNE datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyOWNE(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_OWNERSHIP; - } - - /** - * If the seller name cannot be encoded using current encoder, change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - //Ensure valid for type - setTextEncoding(ID3TextEncodingConversion.getTextEncoding(getHeader(), getTextEncoding())); - - //Ensure valid for data - if (!((AbstractString) getObject(DataTypes.OBJ_SELLER_NAME)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_PRICE_PAID, this)); - objectList.add(new StringDate(DataTypes.OBJ_PURCHASE_DATE, this)); - objectList.add(new TextEncodedStringSizeTerminated(DataTypes.OBJ_SELLER_NAME, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java deleted file mode 100644 index 94cbbd4..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberVariableLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Play counter frame. - *

    - *

    - * This is simply a counter of the number of times a file has been - * played. The value is increased by one every time the file begins to - * play. There may only be one "PCNT" frame in each tag. When the - * counter reaches all one's, one byte is inserted in front of the - * counter thus making the counter eight bits bigger. The counter must - * be at least 32-bits long to begin with. - *

    - * - * - *
    <Header for 'Play counter', ID: "PCNT">
    Counter $xx xx xx xx (xx ...)

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyPCNT.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyPCNT extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - private static final int COUNTER_MINIMUM_FIELD_SIZE = 4; - - /** - * Creates a new FrameBodyPCNT datatype. - */ - public FrameBodyPCNT() { - this.setObjectValue(DataTypes.OBJ_NUMBER, 0L); - } - - public FrameBodyPCNT(FrameBodyPCNT body) { - super(body); - } - - /** - * Creates a new FrameBodyPCNT datatype. - * - * @param counter - */ - public FrameBodyPCNT(long counter) { - this.setObjectValue(DataTypes.OBJ_NUMBER, counter); - } - - /** - * Creates a new FrameBodyPCNT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyPCNT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return the play count of this file - */ - public long getCounter() { - return ((Number) getObjectValue(DataTypes.OBJ_NUMBER)).longValue(); - } - - /** - * Set the play counter of this file - * - * @param counter - */ - public void setCounter(long counter) { - setObjectValue(DataTypes.OBJ_NUMBER, counter); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_PLAY_COUNTER; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberVariableLength(DataTypes.OBJ_NUMBER, this, COUNTER_MINIMUM_FIELD_SIZE)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java deleted file mode 100644 index 58eeca5..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java +++ /dev/null @@ -1,254 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyPIC.java 975 2011-06-08 09:27:24Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v22Frames; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * ID3v22 Attached Picture - *

    - *

    This frame contains a picture directly related to the audio file. - * Image format is preferably "PNG" [PNG] or "JPG" [JFIF]. Description - * is a short description of the picture, represented as a terminated - * textstring. The description has a maximum length of 64 characters, - * but may be empty. There may be several pictures attached to one file, - * each in their individual "PIC" frame, but only one with the same - * ontent descriptor. There may only be one picture with the picture - * type declared as picture type $01 and $02 respectively. There is a - * possibility to put only a link to the image file by using the 'image - * format' "-->" and having a complete URL [URL] instead of picture data. - * The use of linked files should however be used restrictively since - * there is the risk of separation of files. - *

    - * Attached picture "PIC" - * Frame size $xx xx xx - * Text encoding $xx - * Image format $xx xx xx - * Picture type $xx - * Description $00 (00) - * Picture data - *

    - *

    - * Picture type: $00 Other - * $01 32x32 pixels 'file icon' (PNG only) - * $02 Other file icon - * $03 Cover (front) - * $04 Cover (back) - * $05 Leaflet page - * $06 Media (e.g. lable side of CD) - * $07 Lead artist/lead performer/soloist - * $08 Artist/performer - * $09 Conductor - * $0A Band/Orchestra - * $0B Composer - * $0C Lyricist/text writer - * $0D Recording Location - * $0E During recording - * $0F During performance - * $10 Movie/video screen capture - * $11 A bright coloured fish - * $12 Illustration - * $13 Band/artist logotype - * $14 Publisher/Studio logotype - */ -public class FrameBodyPIC extends AbstractID3v2FrameBody implements ID3v22FrameBody { - public static final String IMAGE_IS_URL = "-->"; - - /** - * Creates a new FrameBodyPIC datatype. - */ - public FrameBodyPIC() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - } - - public FrameBodyPIC(FrameBodyPIC body) { - super(body); - } - - /** - * Creates a new FrameBodyPIC datatype. - * - * @param textEncoding - * @param imageFormat - * @param pictureType - * @param description - * @param data - */ - public FrameBodyPIC(byte textEncoding, String imageFormat, byte pictureType, String description, byte[] data) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, imageFormat); - this.setPictureType(pictureType); - this.setDescription(description); - this.setImageData(data); - } - - /** - * Conversion from v2 PIC to v3/v4 APIC - * - * @param body - */ - public FrameBodyPIC(FrameBodyAPIC body) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - this.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, ImageFormats.getFormatForMimeType((String) body.getObjectValue(DataTypes.OBJ_MIME_TYPE))); - this.setObjectValue(DataTypes.OBJ_PICTURE_DATA, body.getObjectValue(DataTypes.OBJ_PICTURE_DATA)); - this.setDescription(body.getDescription()); - this.setImageData(body.getImageData()); - } - - /** - * Creates a new FrameBodyPIC datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyPIC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * Get a description of the image - * - * @return a description of the image - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set a description of the image - * - * @param description of the image - */ - public void setDescription(String description) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * Get Image data - * - * @return - */ - public byte[] getImageData() { - return (byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA); - } - - /** - * Set imageData - * - * @param imageData - */ - public void setImageData(byte[] imageData) { - setObjectValue(DataTypes.OBJ_PICTURE_DATA, imageData); - } - - /** - * @return picturetype - */ - public int getPictureType() { - return ((Long) getObjectValue(DataTypes.OBJ_PICTURE_TYPE)).intValue(); - } - - /** - * Set Picture Type - * - * @param pictureType - */ - public void setPictureType(byte pictureType) { - setObjectValue(DataTypes.OBJ_PICTURE_TYPE, pictureType); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v22Frames.FRAME_ID_V2_ATTACHED_PICTURE; - } - - - /** - * If the description cannot be encoded using current encoder, change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * Get a description of the image - * - * @return a description of the image - */ - public String getFormatType() { - return (String) getObjectValue(DataTypes.OBJ_IMAGE_FORMAT); - } - - public boolean isImageUrl() { - return getFormatType() != null && getFormatType().equals(IMAGE_IS_URL); - } - - /** - * Get mimetype - * - * @return a description of the image - */ - public String getMimeType() { - return (String) getObjectValue(DataTypes.OBJ_MIME_TYPE); - } - - /** - * @return the image url if there is otherwise return an empty String - */ - public String getImageUrl() { - if (isImageUrl()) { - return Utils.getString(((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)), 0, ((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)).length, TextEncoding.CHARSET_ISO_8859_1); - } else { - return ""; - } - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringFixedLength(DataTypes.OBJ_IMAGE_FORMAT, this, 3)); - objectList.add(new NumberHashMap(DataTypes.OBJ_PICTURE_TYPE, this, PictureTypes.PICTURE_TYPE_FIELD_SIZE)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_PICTURE_DATA, this)); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java deleted file mode 100644 index 69d625e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.datatype.NumberVariableLength; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Popularimeter frame. - *

    - *

    - * The purpose of this frame is to specify how good an audio file is. - * Many interesting applications could be found to this frame such as a - * playlist that features better audiofiles more often than others or it - * could be used to profile a person's taste and find other 'good' files - * by comparing people's profiles. The frame is very simple. It contains - * the email address to the user, one rating byte and a four byte play - * counter, intended to be increased with one for every time the file is - * played. The email is a terminated string. The rating is 1-255 where - * 1 is worst and 255 is best. 0 is unknown. If no personal counter is - * wanted it may be omitted. When the counter reaches all one's, one - * byte is inserted in front of the counter thus making the counter - * eight bits bigger in the same away as the play counter ("PCNT"). - * There may be more than one "POPM" frame in each tag, but only one - * with the same email address. - *

    - * - * - * - * - *
    <Header for 'Popularimeter', ID: "POPM">
    Email to user<text string> $00
    Rating $xx
    Counter $xx xx xx xx (xx ...)

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyPOPM.java 938 2010-12-10 13:17:22Z paultaylor $ - * @todo : Counter should be optional, whereas we always expect it although allow a size of zero - * needs testing. - */ -public class FrameBodyPOPM extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - public static final String MEDIA_MONKEY_NO_EMAIL = "no@email"; - private static final int RATING_FIELD_SIZE = 1; - private static final int COUNTER_MINIMUM_FIELD_SIZE = 0; - - /** - * Creates a new FrameBodyPOPM datatype. - */ - public FrameBodyPOPM() { - this.setObjectValue(DataTypes.OBJ_EMAIL, ""); - this.setObjectValue(DataTypes.OBJ_RATING, (long) 0); - this.setObjectValue(DataTypes.OBJ_COUNTER, (long) 0); - } - - public FrameBodyPOPM(FrameBodyPOPM body) { - super(body); - } - - /** - * Creates a new FrameBodyPOPM datatype. - * - * @param emailToUser - * @param rating - * @param counter - */ - public FrameBodyPOPM(String emailToUser, long rating, long counter) { - this.setObjectValue(DataTypes.OBJ_EMAIL, emailToUser); - this.setObjectValue(DataTypes.OBJ_RATING, rating); - this.setObjectValue(DataTypes.OBJ_COUNTER, counter); - } - - /** - * Creates a new FrameBodyPOPM datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyPOPM(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return the memail of the user who rated this - */ - public String getEmailToUser() { - return (String) getObjectValue(DataTypes.OBJ_EMAIL); - } - - /** - * @param description - */ - public void setEmailToUser(String description) { - setObjectValue(DataTypes.OBJ_EMAIL, description); - } - - /** - * @return the rating given to this file - */ - public long getRating() { - return ((Number) getObjectValue(DataTypes.OBJ_RATING)).longValue(); - } - - /** - * Set the rating given to this file - * - * @param rating - */ - public void setRating(long rating) { - setObjectValue(DataTypes.OBJ_RATING, rating); - } - - /** - * @return the play count of this file - */ - public long getCounter() { - return ((Number) getObjectValue(DataTypes.OBJ_COUNTER)).longValue(); - } - - /** - * Set the play counter of this file - * - * @param counter - */ - public void setCounter(long counter) { - setObjectValue(DataTypes.OBJ_COUNTER, counter); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_POPULARIMETER; - } - - public String getUserFriendlyValue() { - return getEmailToUser() + ":" + getRating() + ":" + getCounter(); - } - - public void parseString(String data) { - try { - int value = Integer.parseInt(data); - setRating(value); - setEmailToUser(MEDIA_MONKEY_NO_EMAIL); - } catch (NumberFormatException nfe) { - - } - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_EMAIL, this)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_RATING, this, RATING_FIELD_SIZE)); - objectList.add(new NumberVariableLength(DataTypes.OBJ_COUNTER, this, COUNTER_MINIMUM_FIELD_SIZE)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java deleted file mode 100644 index 057d8ea..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.NumberVariableLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.EventTimingTimestampTypes; - -import java.nio.ByteBuffer; - -/** - * Position synchronisation frame. - *

    - *

    - * This frame delivers information to the listener of how far into the - * audio stream he picked up; in effect, it states the time offset of - * the first frame in the stream. The frame layout is: - *

    - * - * - * - *
    <Head for 'Position synchronisation', ID: "POSS">
    Time stamp format $xx
    Position $xx (xx ...)

    - *

    - * Where time stamp format is: - *

    - * $01 Absolute time, 32 bit sized, using MPEG frames as unit
    - * $02 Absolute time, 32 bit sized, using milliseconds as unit - *

    - * and position is where in the audio the listener starts to receive, - * i.e. the beginning of the next frame. If this frame is used in the - * beginning of a file the value is always 0. There may only be one - * "POSS" frame in each tag. - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyPOSS.java 867 2010-01-28 16:27:11Z paultaylor $ - */ -public class FrameBodyPOSS extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyPOSS datatype. - */ - public FrameBodyPOSS() { - // this.setObject(ObjectNumberHashMap.OBJ_TIME_STAMP_FORMAT, new Byte((byte) 0)); - // this.setObject("Position", new Long(0)); - } - - public FrameBodyPOSS(FrameBodyPOSS body) { - super(body); - } - - /** - * Creates a new FrameBodyPOSS datatype. - * - * @param timeStampFormat - * @param position - */ - public FrameBodyPOSS(byte timeStampFormat, long position) { - this.setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, timeStampFormat); - this.setObjectValue(DataTypes.OBJ_POSITION, position); - } - - /** - * Creates a new FrameBodyPOSS datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyPOSS(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_POSITION_SYNC; - } - - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TIME_STAMP_FORMAT, this, EventTimingTimestampTypes.TIMESTAMP_KEY_FIELD_SIZE)); - objectList.add(new NumberVariableLength(DataTypes.OBJ_POSITION, this, 1)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java deleted file mode 100644 index dddc10e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Private frame. - *

    - *

    - * This frame is used to contain information from a software producer - * that its program uses and does not fit into the other frames. The - * frame consists of an 'Owner identifier' string and the binary data. - * The 'Owner identifier' is a null-terminated string with a URL - * containing an email address, or a link to a location where an email - * address can be found, that belongs to the organisation responsible - * for the frame. Questions regarding the frame should be sent to the - * indicated email address. The tag may contain more than one "PRIV" - * frame but only with different contents. It is recommended to keep the - * number of "PRIV" frames as low as possible. - *

    - * - * - * - *
    <Header for 'Private frame', ID: "PRIV">
    Owner identifier<text string> $00
    The private data<binary data>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyPRIV.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyPRIV extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyPRIV datatype. - */ - public FrameBodyPRIV() { - this.setObjectValue(DataTypes.OBJ_OWNER, ""); - this.setObjectValue(DataTypes.OBJ_DATA, new byte[0]); - } - - public FrameBodyPRIV(FrameBodyPRIV body) { - super(body); - } - - /** - * Creates a new FrameBodyPRIV datatype. - * - * @param owner - * @param data - */ - public FrameBodyPRIV(String owner, byte[] data) { - this.setObjectValue(DataTypes.OBJ_OWNER, owner); - this.setObjectValue(DataTypes.OBJ_DATA, data); - } - - /** - * Creates a new FrameBodyPRIV datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyPRIV(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return - */ - public byte[] getData() { - return (byte[]) getObjectValue(DataTypes.OBJ_DATA); - } - - /** - * @param data - */ - public void setData(byte[] data) { - setObjectValue(DataTypes.OBJ_DATA, data); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_PRIVATE; - } - - /** - * @return - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * @param owner - */ - public void setOwner(String owner) { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java deleted file mode 100644 index 17fdeef..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyRBUF.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.BooleanByte; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - * Body of Recommended buffer size frame, generally used for streaming audio - */ -public class FrameBodyRBUF extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - private static int BUFFER_FIELD_SIZE = 3; - private static int EMBED_FLAG_BIT_POSITION = 1; - private static int OFFSET_FIELD_SIZE = 4; - - /** - * Creates a new FrameBodyRBUF datatype. - */ - public FrameBodyRBUF() { - this.setObjectValue(DataTypes.OBJ_BUFFER_SIZE, (byte) 0); - this.setObjectValue(DataTypes.OBJ_EMBED_FLAG, Boolean.FALSE); - this.setObjectValue(DataTypes.OBJ_OFFSET, (byte) 0); - } - - public FrameBodyRBUF(FrameBodyRBUF body) { - super(body); - } - - /** - * Creates a new FrameBodyRBUF datatype. - * - * @param bufferSize - * @param embeddedInfoFlag - * @param offsetToNextTag - */ - public FrameBodyRBUF(byte bufferSize, boolean embeddedInfoFlag, byte offsetToNextTag) { - this.setObjectValue(DataTypes.OBJ_BUFFER_SIZE, bufferSize); - this.setObjectValue(DataTypes.OBJ_EMBED_FLAG, embeddedInfoFlag); - this.setObjectValue(DataTypes.OBJ_OFFSET, offsetToNextTag); - } - - /** - * Creates a new FrameBodyRBUF datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyRBUF(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_RECOMMENDED_BUFFER_SIZE; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberFixedLength(DataTypes.OBJ_BUFFER_SIZE, this, BUFFER_FIELD_SIZE)); - objectList.add(new BooleanByte(DataTypes.OBJ_EMBED_FLAG, this, (byte) EMBED_FLAG_BIT_POSITION)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_OFFSET, this, OFFSET_FIELD_SIZE)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java deleted file mode 100644 index f9156af..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyRVA2.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Relative Volume Adjustment - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -public class FrameBodyRVA2 extends AbstractID3v2FrameBody implements ID3v24FrameBody { - - /** - * Creates a new FrameBodyRVA2 datatype. - */ - public FrameBodyRVA2() { - } - - public FrameBodyRVA2(FrameBodyRVA2 body) { - super(body); - } - - /** - * Convert from V3 to V4 Frame - * - * @param body - */ - public FrameBodyRVA2(FrameBodyRVAD body) { - setObjectValue(DataTypes.OBJ_DATA, body.getObjectValue(DataTypes.OBJ_DATA)); - } - - - /** - * Creates a new FrameBodyRVAD datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyRVA2(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2; - } - - /** - * Setup the Object List. A byte Array which will be read upto frame size - * bytes. - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java deleted file mode 100644 index f3e6f44..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Relative volume adjustment frame. - *

    - * Only partially implemented. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyRVAD.java 857 2009-12-03 11:21:11Z paultaylor $ - */ -public class FrameBodyRVAD extends AbstractID3v2FrameBody implements ID3v23FrameBody { - - /** - * Creates a new FrameBodyRVAD datatype. - */ - public FrameBodyRVAD() { - - } - - public FrameBodyRVAD(FrameBodyRVAD copyObject) { - super(copyObject); - - } - - - /** - * Convert from V4 to V3 Frame - * - * @param body - */ - public FrameBodyRVAD(FrameBodyRVA2 body) { - setObjectValue(DataTypes.OBJ_DATA, body.getObjectValue(DataTypes.OBJ_DATA)); - } - - /** - * Creates a new FrameBodyRVAD datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyRVAD(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_RELATIVE_VOLUME_ADJUSTMENT; - } - - /** - * Setup the Object List. A byte Array which will be read upto frame size - * bytes. - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java deleted file mode 100644 index 001bf87..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Reverb frame. - *

    - *

    - * Yet another subjective one. You may here adjust echoes of different - * kinds. Reverb left/right is the delay between every bounce in ms. - * Reverb bounces left/right is the number of bounces that should be - * made. $FF equals an infinite number of bounces. Feedback is the - * amount of volume that should be returned to the next echo bounce. $00 - * is 0%, $FF is 100%. If this value were $7F, there would be 50% volume - * reduction on the first bounce, 50% of that on the second and so on. - * Left to left means the sound from the left bounce to be played in the - * left speaker, while left to right means sound from the left bounce to - * be played in the right speaker. - *

    - * 'Premix left to right' is the amount of left sound to be mixed in the - * right before any reverb is applied, where $00 id 0% and $FF is 100%. - * 'Premix right to left' does the same thing, but right to left. - * Setting both premix to $FF would result in a mono output (if the - * reverb is applied symmetric). There may only be one "RVRB" frame in - * each tag. - *

    - * - * - * - * - * - * - * - * - * - * - * - *
    <Header for 'Reverb', ID: "RVRB">
    Reverb left (ms) $xx xx
    Reverb right (ms) $xx xx
    Reverb bounces, left $xx
    Reverb bounces, right $xx
    Reverb feedback, left to left $xx
    Reverb feedback, left to right $xx
    Reverb feedback, right to right $xx
    Reverb feedback, right to left $xx
    Premix left to right $xx
    Premix right to left $xx

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyRVRB.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyRVRB extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyRVRB datatype. - */ - public FrameBodyRVRB() { - // this.setObject("Reverb Left", new Short((short) 0)); - // this.setObject("Reverb Right", new Short((short) 0)); - // this.setObject("Reverb Bounces Left", new Byte((byte) 0)); - // this.setObject("Reverb Bounces Right", new Byte((byte) 0)); - // this.setObject("Reverb Feedback Left To Left", new Byte((byte) 0)); - // this.setObject("Reverb Feedback Left To Right", new Byte((byte) 0)); - // this.setObject("Reverb Feedback Right To Right", new Byte((byte) 0)); - // this.setObject("Reverb Feedback Right to Left", new Byte((byte) 0)); - // this.setObject("Premix Left To Right", new Byte((byte) 0)); - // this.setObject("Premix Right To Left", new Byte((byte) 0)); - } - - public FrameBodyRVRB(FrameBodyRVRB body) { - super(body); - } - - /** - * Creates a new FrameBodyRVRB datatype. - * - * @param reverbLeft - * @param reverbRight - * @param reverbBouncesLeft - * @param reverbBouncesRight - * @param reverbFeedbackLeftToLeft - * @param reverbFeedbackLeftToRight - * @param reverbFeedbackRightToRight - * @param reverbFeedbackRightToLeft - * @param premixLeftToRight - * @param premixRightToLeft - */ - public FrameBodyRVRB(short reverbLeft, short reverbRight, byte reverbBouncesLeft, byte reverbBouncesRight, byte reverbFeedbackLeftToLeft, byte reverbFeedbackLeftToRight, byte reverbFeedbackRightToRight, byte reverbFeedbackRightToLeft, byte premixLeftToRight, byte premixRightToLeft) { - this.setObjectValue(DataTypes.OBJ_REVERB_LEFT, reverbLeft); - this.setObjectValue(DataTypes.OBJ_REVERB_RIGHT, reverbRight); - this.setObjectValue(DataTypes.OBJ_REVERB_BOUNCE_LEFT, reverbBouncesLeft); - this.setObjectValue(DataTypes.OBJ_REVERB_BOUNCE_RIGHT, reverbBouncesRight); - this.setObjectValue(DataTypes.OBJ_REVERB_FEEDBACK_LEFT_TO_LEFT, reverbFeedbackLeftToLeft); - this.setObjectValue(DataTypes.OBJ_REVERB_FEEDBACK_LEFT_TO_RIGHT, reverbFeedbackLeftToRight); - this.setObjectValue(DataTypes.OBJ_REVERB_FEEDBACK_RIGHT_TO_RIGHT, reverbFeedbackRightToRight); - this.setObjectValue(DataTypes.OBJ_REVERB_FEEDBACK_RIGHT_TO_LEFT, reverbFeedbackRightToLeft); - this.setObjectValue(DataTypes.OBJ_PREMIX_LEFT_TO_RIGHT, premixLeftToRight); - this.setObjectValue(DataTypes.OBJ_PREMIX_RIGHT_TO_LEFT, premixRightToLeft); - } - - /** - * Creates a new FrameBodyRVRB datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyRVRB(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_REVERB; - } - - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_LEFT, this, 2)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_RIGHT, this, 2)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_BOUNCE_LEFT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_BOUNCE_RIGHT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_FEEDBACK_LEFT_TO_LEFT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_FEEDBACK_LEFT_TO_RIGHT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_FEEDBACK_RIGHT_TO_RIGHT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_REVERB_FEEDBACK_RIGHT_TO_LEFT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_PREMIX_LEFT_TO_RIGHT, this, 1)); - objectList.add(new NumberFixedLength(DataTypes.OBJ_PREMIX_RIGHT_TO_LEFT, this, 1)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java deleted file mode 100644 index d62fd64..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodySEEK.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodySEEK extends AbstractID3v2FrameBody implements ID3v24FrameBody { - /** - * Creates a new FrameBodySEEK datatype. - */ - public FrameBodySEEK() { - // this.setObject("Minimum Offset to Next Tag", new Integer(0)); - } - - /** - * Creates a new FrameBodySEEK datatype. - * - * @param minOffsetToNextTag - */ - public FrameBodySEEK(int minOffsetToNextTag) { - this.setObjectValue(DataTypes.OBJ_OFFSET, minOffsetToNextTag); - } - - public FrameBodySEEK(FrameBodySEEK body) { - super(body); - } - - /** - * Creates a new FrameBodySEEK datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodySEEK(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_AUDIO_SEEK_POINT_INDEX; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberFixedLength(DataTypes.OBJ_OFFSET, this, 4)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java deleted file mode 100644 index cf399f8..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodySIGN.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberFixedLength; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodySIGN extends AbstractID3v2FrameBody implements ID3v24FrameBody { - /** - * Creates a new FrameBodySIGN datatype. - */ - public FrameBodySIGN() { - // this.setObject("Group Symbol", new Byte((byte) 0)); - // this.setObject("Signature", new byte[0]); - } - - public FrameBodySIGN(FrameBodySIGN body) { - super(body); - } - - /** - * Creates a new FrameBodySIGN datatype. - * - * @param groupSymbol - * @param signature - */ - public FrameBodySIGN(byte groupSymbol, byte[] signature) { - this.setObjectValue(DataTypes.OBJ_GROUP_SYMBOL, groupSymbol); - this.setObjectValue(DataTypes.OBJ_SIGNATURE, signature); - } - - /** - * Creates a new FrameBodySIGN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodySIGN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return - */ - public byte getGroupSymbol() { - if (getObjectValue(DataTypes.OBJ_GROUP_SYMBOL) != null) { - return (Byte) getObjectValue(DataTypes.OBJ_GROUP_SYMBOL); - } else { - return (byte) 0; - } - } - - /** - * @param groupSymbol - */ - public void setGroupSymbol(byte groupSymbol) { - setObjectValue(DataTypes.OBJ_GROUP_SYMBOL, groupSymbol); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_SIGNATURE; - } - - /** - * @return - */ - public byte[] getSignature() { - return (byte[]) getObjectValue(DataTypes.OBJ_SIGNATURE); - } - - /** - * @param signature - */ - public void setSignature(byte[] signature) { - setObjectValue(DataTypes.OBJ_SIGNATURE, signature); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberFixedLength(DataTypes.OBJ_GROUP_SYMBOL, this, 1)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_SIGNATURE, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java deleted file mode 100644 index edc13d8..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.EventTimingTimestampTypes; -import org.jaudiotagger.tag.id3.valuepair.SynchronisedLyricsContentType; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.Languages; - -import java.nio.ByteBuffer; - -/** - * Synchronised lyrics/text frame. - *

    - *

    - * This is another way of incorporating the words, said or sung lyrics, - * in the audio file as text, this time, however, in sync with the - * audio. It might also be used to describing events e.g. occurring on a - * stage or on the screen in sync with the audio. The header includes a - * content descriptor, represented with as terminated textstring. If no - * descriptor is entered, 'Content descriptor' is $00 (00) only. - *

    - * - * - * - * - * - * - *
    <Header for 'Synchronised lyrics/text', ID: "SYLT">
    Text encoding$xx
    Language$xx xx xx
    Time stamp format$xx
    Content type$xx
    Content descriptor<text string according to encoding> $00 (00)

    - *

    - * - * - *
    Encoding:$00ISO-8859-1 character set is used => $00 is sync identifier.
    $01Unicode character set is used => $00 00 is sync identifier.

    - *

    - * - * - * - * - * - * - * - *
    Content type:$00is other
    $01is lyrics
    $02is text transcription
    $03is movement/part name (e.g. "Adagio")
    $04is events (e.g. "Don Quijote enters the stage")
    $05is chord (e.g. "Bb F Fsus")
    $06is trivia/'pop up' information

    - *

    - * Time stamp format is: - *

    - * $01 Absolute time, 32 bit sized, using MPEG frames as unit
    - * $02 Absolute time, 32 bit sized, using milliseconds as unit - *

    - * Abolute time means that every stamp contains the time from the - * beginning of the file. - *

    - * The text that follows the frame header differs from that of the - * unsynchronised lyrics/text transcription in one major way. Each - * syllable (or whatever size of text is considered to be convenient by - * the encoder) is a null terminated string followed by a time stamp - * denoting where in the sound file it belongs. Each sync thus has the - * following structure: - *

    - * - * - * - *
    Terminated text to be synced (typically a syllable)
    Sync identifier (terminator to above string)$00 (00)
    Time stamp$xx (xx ...)

    - *

    - * The 'time stamp' is set to zero or the whole sync is omitted if - * located directly at the beginning of the sound. All time stamps - * should be sorted in chronological order. The sync can be considered - * as a validator of the subsequent string. - *

    - * Newline ($0A) characters are allowed in all "SYLT" frames and should - * be used after every entry (name, event etc.) in a frame with the - * content type $03 - $04. - *

    - * A few considerations regarding whitespace characters: Whitespace - * separating words should mark the beginning of a new word, thus - * occurring in front of the first syllable of a new word. This is also - * valid for new line characters. A syllable followed by a comma should - * not be broken apart with a sync (both the syllable and the comma - * should be before the sync). - *

    - * An example: The "USLT" passage - *

    - * "Strangers in the night" $0A "Exchanging glances" - *

    would be "SYLT" encoded as: - *

    - * "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx - * " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx - * xx "glan" $00 xx xx "ces" $00 xx xx - *

    There may be more than one "SYLT" frame in each tag, but only one - * with the same language and content descriptor.

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodySYLT.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodySYLT extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodySYLT datatype. - */ - public FrameBodySYLT() { - - } - - /** - * Copy Constructor - * - * @param body - */ - public FrameBodySYLT(FrameBodySYLT body) { - super(body); - } - - /** - * Creates a new FrameBodySYLT datatype. - * - * @param textEncoding - * @param language - * @param timeStampFormat - * @param contentType - * @param description - * @param lyrics - */ - public FrameBodySYLT(int textEncoding, String language, int timeStampFormat, int contentType, String description, byte[] lyrics) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, timeStampFormat); - setObjectValue(DataTypes.OBJ_CONTENT_TYPE, contentType); - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - setObjectValue(DataTypes.OBJ_DATA, lyrics); - } - - /** - * Creates a new FrameBodySYLT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodySYLT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return language code - */ - public String getLanguage() { - return (String) getObjectValue(DataTypes.OBJ_LANGUAGE); - } - - /** - * @return timestamp format key - */ - public int getTimeStampFormat() { - return ((Number) getObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT)).intValue(); - } - - /** - * @return content type key - */ - public int getContentType() { - return ((Number) getObjectValue(DataTypes.OBJ_CONTENT_TYPE)).intValue(); - } - - /** - * @return description - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * @return frame identifier - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_SYNC_LYRIC; - } - - /** - * Get lyrics - *

    - * TODO:better format - * - * @return lyrics - */ - public byte[] getLyrics() { - return (byte[]) this.getObjectValue(DataTypes.OBJ_DATA); - } - - /** - * Set lyrics - *

    - * TODO:provide a more user friendly way of adding lyrics - * - * @param data - */ - public void setLyrics(byte[] data) { - this.setObjectValue(DataTypes.OBJ_DATA, data); - } - - /** - * Setup Object List - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringHashMap(DataTypes.OBJ_LANGUAGE, this, Languages.LANGUAGE_FIELD_SIZE)); - objectList.add(new NumberHashMap(DataTypes.OBJ_TIME_STAMP_FORMAT, this, EventTimingTimestampTypes.TIMESTAMP_KEY_FIELD_SIZE)); - objectList.add(new NumberHashMap(DataTypes.OBJ_CONTENT_TYPE, this, SynchronisedLyricsContentType.CONTENT_KEY_FIELD_SIZE)); - objectList.add(new StringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - - //TODO:This hold the actual lyrics - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java deleted file mode 100644 index 465d63e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.EventTimingTimestampTypes; - -import java.nio.ByteBuffer; - -/** - * Synchronised tempo codes frame. - *

    - *

    - * For a more accurate description of the tempo of a musical piece this - * frame might be used. After the header follows one byte describing - * which time stamp format should be used. Then follows one or more - * tempo codes. Each tempo code consists of one tempo part and one time - * part. The tempo is in BPM described with one or two bytes. If the - * first byte has the value $FF, one more byte follows, which is added - * to the first giving a range from 2 - 510 BPM, since $00 and $01 is - * reserved. $00 is used to describe a beat-free time period, which is - * not the same as a music-free time period. $01 is used to indicate one - * single beat-stroke followed by a beat-free period. - *

    - * The tempo descriptor is followed by a time stamp. Every time the - * tempo in the music changes, a tempo descriptor may indicate this for - * the player. All tempo descriptors should be sorted in chronological - * order. The first beat-stroke in a time-period is at the same time as - * the beat description occurs. There may only be one "SYTC" frame in - * each tag. - *

    - * - * - * - *
    <Header for 'Synchronised tempo codes', ID: "SYTC">
    Time stamp format$xx
    Tempo data <binary data>

    - * Where time stamp format is: - *

    - * $01 Absolute time, 32 bit sized, using MPEG frames as unit
    - * $02 Absolute time, 32 bit sized, using milliseconds as unit - *

    - * Abolute time means that every stamp contains the time from the - * beginning of the file. - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodySYTC.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodySYTC extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodySYTC datatype. - */ - public FrameBodySYTC() { - } - - /** - * @param timeStampFormat - * @param tempo - */ - public FrameBodySYTC(int timeStampFormat, byte[] tempo) { - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, timeStampFormat); - setObjectValue(DataTypes.OBJ_DATA, tempo); - } - - /** - * Creates a new FrameBody from buffer - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodySYTC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * Copy constructor - * - * @param body - */ - public FrameBodySYTC(FrameBodySYTC body) { - super(body); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_SYNC_TEMPO; - } - - - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TIME_STAMP_FORMAT, this, EventTimingTimestampTypes.TIMESTAMP_KEY_FIELD_SIZE)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java deleted file mode 100644 index 6c239f6..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Album/Movie/Show title Text information frame. - *

    The 'Album/Movie/Show title' frame is intended for the title of the recording(/source of sound) which the audio in the file is taken from. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTALB.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTALB extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTALB datatype. - */ - public FrameBodyTALB() { - } - - public FrameBodyTALB(FrameBodyTALB body) { - super(body); - } - - /** - * Creates a new FrameBodyTALB datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTALB(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTALB datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyTALB(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ALBUM; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java deleted file mode 100644 index f1937fe..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Beats Per Minute Text information frame. - *

    The 'BPM' frame contains the number of beats per minute in the mainpart of the audio. The BPM is an integer and represented as a numerical string. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTBPM.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTBPM extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTBPM datatype. - */ - public FrameBodyTBPM() { - } - - public FrameBodyTBPM(FrameBodyTBPM body) { - super(body); - } - - /** - * Creates a new FrameBodyTBPM datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTBPM(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTBPM datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTBPM(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_BPM; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java deleted file mode 100644 index c54e234..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - -/** - * Is part of a Compilation (iTunes frame) - *

    - *

    determines whether or not track is part of compilation - * - * @author : Paul Taylor - */ -public class FrameBodyTCMP extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - //TODO does iTunes have to have null terminator? - static String IS_COMPILATION = "1\u0000"; - - /** - * Creates a new FrameBodyTCMP datatype, with compilation enabled - *

    - * This is the preferred constructor to use because TCMP frames should not exist - * unless they are set to true - */ - public FrameBodyTCMP() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, IS_COMPILATION); - } - - public FrameBodyTCMP(FrameBodyTCMP body) { - super(body); - } - - /** - * Creates a new FrameBodyTCMP datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTCMP(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTIT1 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTCMP(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public boolean isCompilation() { - return this.getText().equals(IS_COMPILATION); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_IS_COMPILATION; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java deleted file mode 100644 index 455776c..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Composer Text information frame. - *

    The 'Composer(s)' frame is intended for the name of the composer(s). - * They are separated with the "/" character in ID3v23. - * Null separated as is the norm in ID3v24 - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTCOM.java 1028 2012-03-01 11:07:39Z paultaylor $ - */ -public class FrameBodyTCOM extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTCOM datatype. - */ - public FrameBodyTCOM() { - } - - public FrameBodyTCOM(FrameBodyTCOM body) { - super(body); - } - - /** - * Creates a new FrameBodyTCOM datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTCOM(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTCOM datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyTCOM(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_COMPOSER; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java deleted file mode 100644 index fd9608b..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Content type Text information frame. - *

    - *

    The 'Content type', which previously was - * stored as a one byte numeric value only, is now a numeric string. You - * may use one or several of the types as ID3v1.1 did or, since the - * category list would be impossible to maintain with accurate and up to - * date categories, define your own. - *

    - * ID3V23:References to the ID3v1 genres can be made by, as first byte, enter - * "(" followed by a number from the genres list (appendix A) and - * ended with a ")" character. This is optionally followed by a - * refinement, e.g. "(21)" or "(4)Eurodisco". Several references can be - * made in the same frame, e.g. "(51)(39)". If the refinement should - * begin with a "(" character it should be replaced with "((", e.g. "((I - * can figure out any genre)" or "(55)((I think...)". The following new - * content types is defined in ID3v2 and is implemented in the same way - * as the numeric content types, e.g. "(RX)". - *

    - * - * - *
    RXRemix
    CRCover

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - *

    - * ID3V24:The 'Content type', which ID3v1 was stored as a one byte numeric - * value only, is now a string. You may use one or several of the ID3v1 - * types as numerical strings, or, since the category list would be - * impossible to maintain with accurate and up to date categories, - * define your own. Example: "21" $00 "Eurodisco" $00 - *

    - * You may also use any of the following keywords: - *

    - * - * - *
    RXRemix
    CRCover

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTCON.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTCON extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTCON datatype. - */ - public FrameBodyTCON() { - } - - public FrameBodyTCON(FrameBodyTCON body) { - super(body); - } - - /** - * Creates a new FrameBodyTCON datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTCON(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTCON datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTCON(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_GENRE; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCOP.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCOP.java deleted file mode 100644 index 531c133..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTCOP.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Copyright message Text information frame. - *

    The 'Copyright message' frame, which must begin with a year and a space character (making five characters), is intended for the copyright holder of the original sound, not the audio file itself. The absence of this frame means only that the copyright information is unavailable or has been removed, and must not be interpreted to mean that the sound is public domain. Every time this field is displayed the field must be preceded with "Copyright ©". - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTCOP.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTCOP extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTCOP datatype. - */ - public FrameBodyTCOP() { - } - - public FrameBodyTCOP(FrameBodyTCOP body) { - super(body); - } - - /** - * Creates a new FrameBodyTCOP datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTCOP(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTCOP datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTCOP(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_COPYRIGHTINFO; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java deleted file mode 100644 index 8051e22..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Date Text information frame. - *

    The 'Date' frame is a numeric string in the DDMM format containing the date for the recording. This field is always four characters long. - *

    Deprecated in v2.4.0 - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTDAT.java 932 2010-11-26 13:13:15Z paultaylor $ - */ -public class FrameBodyTDAT extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - private boolean monthOnly; - - /** - * Creates a new FrameBodyTDAT datatype. - */ - public FrameBodyTDAT() { - } - - public FrameBodyTDAT(FrameBodyTDAT body) { - super(body); - } - - /** - * Creates a new FrameBodyTDAT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTDAT(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTDAT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTDAT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TDAT; - } - - public boolean isMonthOnly() { - return monthOnly; - } - - public void setMonthOnly(boolean monthOnly) { - this.monthOnly = monthOnly; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java deleted file mode 100644 index 218f71d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTDEN.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTDEN extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - /** - * Creates a new FrameBodyTDEN datatype. - */ - public FrameBodyTDEN() { - } - - public FrameBodyTDEN(FrameBodyTDEN body) { - super(body); - } - - /** - * Creates a new FrameBodyTDEN datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTDEN(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTDEN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTDEN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ENCODING_TIME; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java deleted file mode 100644 index b99a4c6..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Playlist delay Text information frame. - *

    The 'Playlist delay' defines the numbers of milliseconds of silence between every song in a playlist. The player should use the "ETC" frame, if present, to skip initial silence and silence at the end of the audio to match the 'Playlist delay' time. The time is represented as a numeric string. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTDLY.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTDLY extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTDLY datatype. - */ - public FrameBodyTDLY() { - } - - public FrameBodyTDLY(FrameBodyTDLY body) { - super(body); - } - - /** - * Creates a new FrameBodyTDLY datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTDLY(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTDLY datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTDLY(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_PLAYLIST_DELAY; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java deleted file mode 100644 index 0068833..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTDOR.java 869 2010-02-01 14:44:01Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - - -/** - *

    The 'Original release time' frame contains a timestamp describing - * when the original recording of the audio was released. Timestamp - * format is described in the ID3v2 structure document.

    - */ -public class FrameBodyTDOR extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - /** - * Creates a new FrameBodyTDOR datatype. - */ - public FrameBodyTDOR() { - } - - public FrameBodyTDOR(FrameBodyTDOR body) { - super(body); - } - - /** - * When converting v3 TDAT to v4 TDRC frame - * - * @param body - */ - public FrameBodyTDOR(FrameBodyTORY body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, body.getText()); - } - - /** - * Creates a new FrameBodyTDOR datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTDOR(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTDOR datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTDOR(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ORIGINAL_RELEASE_TIME; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java deleted file mode 100644 index de6d6b1..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java +++ /dev/null @@ -1,398 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTDRC.java 1055 2012-06-07 16:52:29Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v23Frames; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.logging.Level; - - -public class FrameBodyTDRC extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - private static final List formatters = new ArrayList(); - private static final int PRECISION_SECOND = 0; - private static final int PRECISION_MINUTE = 1; - private static final int PRECISION_HOUR = 2; - private static final int PRECISION_DAY = 3; - private static final int PRECISION_MONTH = 4; - private static final int PRECISION_YEAR = 5; - private static SimpleDateFormat formatYearIn, formatYearOut; - private static SimpleDateFormat formatDateIn, formatDateOut, formatMonthOut; - private static SimpleDateFormat formatTimeIn, formatTimeOut, formatHoursOut; - - static { - //This is allowable v24 format , we use UK Locale not because we are restricting to UK - //but because these formats are fixed in ID3 spec, and could possibly get unexpected results if library - //used with a default locale that has Date Format Symbols that interfere with the pattern - formatters.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.UK)); - formatters.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm", Locale.UK)); - formatters.add(new SimpleDateFormat("yyyy-MM-dd'T'HH", Locale.UK)); - formatters.add(new SimpleDateFormat("yyyy-MM-dd", Locale.UK)); - formatters.add(new SimpleDateFormat("yyyy-MM", Locale.UK)); - formatters.add(new SimpleDateFormat("yyyy", Locale.UK)); - - //These are formats used by v23 Frames - formatYearIn = new SimpleDateFormat("yyyy", Locale.UK); - formatDateIn = new SimpleDateFormat("ddMM", Locale.UK); - formatTimeIn = new SimpleDateFormat("HHmm", Locale.UK); - - //These are the separate components of the v24 format that the v23 formats map to - formatYearOut = new SimpleDateFormat("yyyy", Locale.UK); - formatDateOut = new SimpleDateFormat("-MM-dd", Locale.UK); - formatMonthOut = new SimpleDateFormat("-MM", Locale.UK); - formatTimeOut = new SimpleDateFormat("'T'HH:mm", Locale.UK); - formatHoursOut = new SimpleDateFormat("'T'HH", Locale.UK); - - } - - /** - * Used when converting from v3 tags , these fields should ALWAYS hold the v23 value - */ - private String originalID; - private String year = ""; - private String time = ""; - private String date = ""; - private boolean monthOnly = false; - private boolean hoursOnly = false; - - /** - * Creates a new FrameBodyTDRC datatype. - */ - public FrameBodyTDRC() { - super(); - } - - public FrameBodyTDRC(FrameBodyTDRC body) { - super(body); - } - - /** - * When converting v3 TYER to v4 TDRC frame - * - * @param body - */ - public FrameBodyTDRC(FrameBodyTYER body) { - originalID = ID3v23Frames.FRAME_ID_V3_TYER; - year = body.getText(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, getFormattedText()); - } - - /** - * When this has been generated as an amalgamation of v3 frames assumes - * the v3 frames match the the format in specification and convert them - * to their equivalent v4 format and return the generated String. - * i.e if the v3 frames contain a valid value this will return a valid - * v4 value, if not this won't. - */ - - /** - * When converting v3 TIME to v4 TDRC frame - * - * @param body - */ - public FrameBodyTDRC(FrameBodyTIME body) { - originalID = ID3v23Frames.FRAME_ID_V3_TIME; - time = body.getText(); - setHoursOnly(body.isHoursOnly()); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, getFormattedText()); - } - - /** - * When converting v3 TDAT to v4 TDRC frame - * - * @param body - */ - public FrameBodyTDRC(FrameBodyTDAT body) { - originalID = ID3v23Frames.FRAME_ID_V3_TDAT; - date = body.getText(); - setMonthOnly(body.isMonthOnly()); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, getFormattedText()); - } - - /** - * When converting v3 TDRA to v4 TDRC frame - * - * @param body - */ - public FrameBodyTDRC(FrameBodyTRDA body) { - originalID = ID3v23Frames.FRAME_ID_V3_TRDA; - date = body.getText(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, getFormattedText()); - } - - /** - * Creates a new FrameBodyTDRC dataType. - *

    - * Tries to decode the text to find the v24 date mask being used, and store the v3 components of the mask - * - * @param textEncoding - * @param text - */ - public FrameBodyTDRC(byte textEncoding, String text) { - super(textEncoding, text); - findMatchingMaskAndExtractV3Values(); - } - - - /** - * Creates a new FrameBodyTDRC datatype from File - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTDRC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - findMatchingMaskAndExtractV3Values(); - } - - /** - * Synchronized because SimpleDatFormat aren't thread safe - * - * @param formatDate - * @param parseDate - * @param text - * @return - */ - private static synchronized String formatAndParse(SimpleDateFormat formatDate, SimpleDateFormat parseDate, String text) { - try { - Date date = parseDate.parse(text); - String result = formatDate.format(date); - return result; - } catch (ParseException e) { - logger.warning("Unable to parse:" + text); - } - return ""; - } - - /** - * Format Date - *

    - * Synchronized because SimpleDateFormat is invalid - * - * @param d - * @return - */ - private static synchronized String formatDateAsYear(Date d) { - return formatYearIn.format(d); - } - - /** - * Format Date - *

    - * Synchronized because SimpleDateFormat is invalid - * - * @param d - * @return - */ - private static synchronized String formatDateAsDate(Date d) { - return formatDateIn.format(d); - } - - /** - * Format Date - *

    - * Synchronized because SimpleDateFormat is invalid - * - * @param d - * @return - */ - private static synchronized String formatDateAsTime(Date d) { - return formatTimeIn.format(d); - } - - /** - * Retrieve the original identifier - * - * @return - */ - public String getOriginalID() { - return originalID; - } - - public String getFormattedText() { - StringBuffer sb = new StringBuffer(); - if (originalID == null) { - return this.getText(); - } else { - if (year != null && !(year.equals(""))) { - sb.append(formatAndParse(formatYearOut, formatYearIn, year)); - } - if (!date.equals("")) { - if (isMonthOnly()) { - sb.append(formatAndParse(formatMonthOut, formatDateIn, date)); - } else { - sb.append(formatAndParse(formatDateOut, formatDateIn, date)); - } - } - if (!time.equals("")) { - if (isHoursOnly()) { - sb.append(formatAndParse(formatHoursOut, formatTimeIn, time)); - } else { - sb.append(formatAndParse(formatTimeOut, formatTimeIn, time)); - } - - } - return sb.toString(); - } - } - - public String getYear() { - return year; - } - - public void setYear(String year) { - logger.finest("Setting year to" + year); - this.year = year; - } - - public String getTime() { - return time; - } - - public void setTime(String time) { - logger.finest("Setting time to:" + time); - this.time = time; - } - - public String getDate() { - return date; - } - - public void setDate(String date) { - logger.finest("Setting date to:" + date); - this.date = date; - } - - private void findMatchingMaskAndExtractV3Values() { - //Find the date format of the text - for (int i = 0; i < formatters.size(); i++) { - try { - Date d; - synchronized (formatters.get(i)) { - d = formatters.get(i).parse(getText()); - } - //If able to parse a date from the text - if (d != null) { - extractID3v23Formats(d, i); - break; - } - } - //Dont display will occur for each failed format - catch (ParseException e) { - //Do nothing; - } catch (NumberFormatException nfe) { - //Do nothing except log warning because not really expecting this to happen - logger.log(Level.WARNING, "Date Formatter:" + formatters.get(i).toPattern() + "failed to parse:" + getText() + "with " + nfe.getMessage(), nfe); - } - } - } - - /** - * Extract the components ans store the v23 version of the various values - * - * @param dateRecord - * @param precision - */ - //TODO currently if user has entered Year and Month, we only store in v23, should we store month with - //first day - private void extractID3v23Formats(final Date dateRecord, final int precision) { - logger.fine("Precision is:" + precision + "for date:" + dateRecord.toString()); - Date d = dateRecord; - - //Precision Year - if (precision == PRECISION_YEAR) { - setYear(formatDateAsYear(d)); - } - //Precision Month - else if (precision == PRECISION_MONTH) { - setYear(formatDateAsYear(d)); - setDate(formatDateAsDate(d)); - monthOnly = true; - } - //Precision Day - else if (precision == PRECISION_DAY) { - setYear(formatDateAsYear(d)); - setDate(formatDateAsDate(d)); - } - //Precision Hour - else if (precision == PRECISION_HOUR) { - setYear(formatDateAsYear(d)); - setDate(formatDateAsDate(d)); - setTime(formatDateAsTime(d)); - hoursOnly = true; - - } - //Precision Minute - else if (precision == PRECISION_MINUTE) { - setYear(formatDateAsYear(d)); - setDate(formatDateAsDate(d)); - setTime(formatDateAsTime(d)); - } - //Precision Minute - else if (precision == PRECISION_SECOND) { - setYear(formatDateAsYear(d)); - setDate(formatDateAsDate(d)); - setTime(formatDateAsTime(d)); - } - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_YEAR; - } - - public boolean isMonthOnly() { - return monthOnly; - } - - public void setMonthOnly(boolean monthOnly) { - this.monthOnly = monthOnly; - } - - public boolean isHoursOnly() { - return hoursOnly; - } - - public void setHoursOnly(boolean hoursOnly) { - this.hoursOnly = hoursOnly; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java deleted file mode 100644 index acc5c29..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTDRL.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTDRL extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - /** - * Creates a new FrameBodyTDRL datatype. - */ - public FrameBodyTDRL() { - } - - public FrameBodyTDRL(FrameBodyTDRL body) { - super(body); - } - - /** - * Creates a new FrameBodyTDRL datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTDRL(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTDRL datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTDRL(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_RELEASE_TIME; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java deleted file mode 100644 index c9b2a12..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTDTG.java 869 2010-02-01 14:44:01Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - *

    The 'Tagging time' frame contains a timestamp describing then the - * audio was tagged. Timestamp format is described in the ID3v2 - * structure document

    - */ -public class FrameBodyTDTG extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - - /** - * Creates a new FrameBodyTDTG datatype. - */ - public FrameBodyTDTG() { - } - - public FrameBodyTDTG(FrameBodyTDTG body) { - super(body); - } - - /** - * Creates a new FrameBodyTDTG datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTDTG(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTDTG datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTDTG(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return the frame identifier - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_TAGGING_TIME; - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java deleted file mode 100644 index c35b458..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Encoded by Text information frame. - *

    The 'Encoded by' frame contains the name of the person or organisation that encoded the audio file. - * This field may contain a copyright message, if the audio file also is copyrighted by the encoder. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTENC.java 905 2010-05-14 19:37:31Z paultaylor $ - */ -public class FrameBodyTENC extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTENC dataType. - */ - public FrameBodyTENC() { - } - - public FrameBodyTENC(FrameBodyTENC body) { - super(body); - } - - /** - * Creates a new FrameBodyTENC dataType. - * - * @param textEncoding - * @param text - */ - public FrameBodyTENC(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTENC dataType. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTENC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ENCODEDBY; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java deleted file mode 100644 index 97e229e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Lyricist/Text writer Text information frame. - *

    The 'Lyricist(s)/Text writer(s)' frame is intended for the writer(s) of the text or lyrics in the recording. They are seperated with the "/" character. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTEXT.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTEXT extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTEXT datatype. - */ - public FrameBodyTEXT() { - } - - public FrameBodyTEXT(FrameBodyTEXT body) { - super(body); - } - - /** - * Creates a new FrameBodyTEXT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTEXT(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTEXT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTEXT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_LYRICIST; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java deleted file mode 100644 index 3ad2ceb..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * File type Text information frame. - *

    - *

    The 'File type' frame indicates which type of audio this tag defines. - * The following type and refinements are defined: - *

    - * - * - * - * - * - * - * - * - *
    MPG MPEG Audio
    /1 MPEG 1/2 layer I
    /2 MPEG 1/2 layer II
    /3 MPEG 1/2 layer III
    /2.5 MPEG 2.5
    /AAC Advanced audio compression
    VQFTransform-domain Weighted Interleave Vector Quantization
    PCM Pulse Code Modulated audio

    - * but other types may be used, not for these types though. This is used - * in a similar way to the predefined types in the "TMED" frame, but - * without parentheses. If this frame is not present audio type is - * assumed to be "MPG". - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTFLT.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTFLT extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTFLT datatype. - */ - public FrameBodyTFLT() { - } - - public FrameBodyTFLT(FrameBodyTFLT body) { - super(body); - } - - /** - * Creates a new FrameBodyTFLT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTFLT(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTFLT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTFLT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_FILE_TYPE; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java deleted file mode 100644 index d2fd4a8..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Time Text information frame. - *

    The 'Time' frame is a numeric string in the HHMM format containing the time for the recording. This field is always four characters long. - *

    Deprecated in v2.4.0 - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTIME.java 932 2010-11-26 13:13:15Z paultaylor $ - */ -public class FrameBodyTIME extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - private boolean hoursOnly; - - /** - * Creates a new FrameBodyTIME datatype. - */ - public FrameBodyTIME() { - } - - public FrameBodyTIME(FrameBodyTIME body) { - super(body); - } - - /** - * Creates a new FrameBodyTIME datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTIME(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTIME datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTIME(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TIME; - } - - public boolean isHoursOnly() { - return hoursOnly; - } - - public void setHoursOnly(boolean hoursOnly) { - this.hoursOnly = hoursOnly; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java deleted file mode 100644 index 264f36b..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTIPL.java 1028 2012-03-01 11:07:39Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * People List - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.Pair; -import org.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.StringTokenizer; - - -/** - * The 'Involved people list' is intended as a mapping between functions like producer and names. Every odd field is a - * function and every even is an name or a comma delimited list of names. - *

    - */ -public class FrameBodyTIPL extends AbstractID3v2FrameBody implements ID3v24FrameBody { - //Standard function names, taken from Picard Mapping - public static final String ENGINEER = "engineer"; - public static final String MIXER = "mix"; - public static final String DJMIXER = "DJ-mix"; - public static final String PRODUCER = "producer"; - public static final String ARRANGER = "arranger"; - - /** - * Creates a new FrameBodyTIPL datatype. - */ - public FrameBodyTIPL() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - } - - /** - * Creates a new FrameBodyTIPL data type. - * - * @param textEncoding - * @param text - */ - public FrameBodyTIPL(byte textEncoding, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setText(text); - } - - /** - * Creates a new FrameBodyTIPL data type. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTIPL(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * Convert from V3 to V4 Frame - * - * @param body - */ - public FrameBodyTIPL(FrameBodyIPLS body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - setObjectValue(DataTypes.OBJ_TEXT, body.getPairing()); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE; - } - - /** - * Parse text as a null separated pairing of name and function - * - * @param text - */ - public void addPair(String text) { - StringTokenizer stz = new StringTokenizer(text, "\0"); - if (stz.countTokens() == 2) { - addPair(stz.nextToken(), stz.nextToken()); - } - } - - /** - * Add pair - * - * @param function - * @param name - */ - public void addPair(String function, String name) { - PairedTextEncodedStringNullTerminated.ValuePairs value = ((PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT)).getValue(); - value.add(function, name); - - } - - /** - * Remove all Pairs - */ - public void resetPairs() { - PairedTextEncodedStringNullTerminated.ValuePairs value = ((PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT)).getValue(); - value.getMapping().clear(); - } - - /** - * Because have a text encoding we need to check the data values do not contain characters that cannot be encoded in - * current encoding before we write data. If they do change the encoding. - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * Consists of a text encoding , and then a series of null terminated Strings, there should be an even number - * of Strings as they are paired as involvement/involvee - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new PairedTextEncodedStringNullTerminated(DataTypes.OBJ_TEXT, this)); - } - - public PairedTextEncodedStringNullTerminated.ValuePairs getPairing() { - return (PairedTextEncodedStringNullTerminated.ValuePairs) getObject(DataTypes.OBJ_TEXT).getValue(); - } - - /** - * Get key at index - * - * @param index - * @return value at index - */ - public String getKeyAtIndex(int index) { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValue().getMapping().get(index).getKey(); - } - - /** - * Get value at index - * - * @param index - * @return value at index - */ - public String getValueAtIndex(int index) { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValue().getMapping().get(index).getValue(); - } - - /** - * @return number of text pairs - */ - public int getNumberOfPairs() { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - return text.getValue().getNumberOfPairs(); - } - - public String getText() { - PairedTextEncodedStringNullTerminated text = (PairedTextEncodedStringNullTerminated) getObject(DataTypes.OBJ_TEXT); - StringBuilder sb = new StringBuilder(); - int count = 1; - for (Pair entry : text.getValue().getMapping()) { - sb.append(entry.getKey() + '\0' + entry.getValue()); - if (count != getNumberOfPairs()) { - sb.append('\0'); - } - count++; - } - return sb.toString(); - } - - /** - * Set the text, decoded as pairs of involvee - involvement - * - * @param text - */ - public void setText(String text) { - PairedTextEncodedStringNullTerminated.ValuePairs value = new PairedTextEncodedStringNullTerminated.ValuePairs(); - StringTokenizer stz = new StringTokenizer(text, "\0"); - - while (stz.hasMoreTokens()) { - String key = stz.nextToken(); - if (stz.hasMoreTokens()) { - value.add(key, stz.nextToken()); - } - - } - setObjectValue(DataTypes.OBJ_TEXT, value); - } - - public String getUserFriendlyValue() { - return getText(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java deleted file mode 100644 index 21dbba1..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - * Content group description Text information frame. - *

    The 'Content group description' frame is used if the sound belongs to a larger category of sounds/music. - * For example, classical music is often sorted in different musical sections (e.g. "Piano Concerto", "Weather - Hurricane"). - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTIT1.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTIT1 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTIT1 datatype. - */ - public FrameBodyTIT1() { - } - - public FrameBodyTIT1(FrameBodyTIT1 body) { - super(body); - } - - /** - * Creates a new FrameBodyTIT1 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTIT1(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTIT1 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTIT1(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_CONTENT_GROUP_DESC; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java deleted file mode 100644 index 8e98fc3..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Title/Songname/Content description Text information frame. - *

    The 'Title/Songname/Content description' frame is the actual name of the piece (e.g. "Adagio", "Hurricane Donna"). - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTIT2.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTIT2 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTIT2 datatype. - */ - public FrameBodyTIT2() { - } - - public FrameBodyTIT2(FrameBodyTIT2 body) { - super(body); - } - - /** - * Creates a new FrameBodyTIT2 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTIT2(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTIT2 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTIT2(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_TITLE; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java deleted file mode 100644 index 84d8012..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Subtitle/Description refinement Text information frame. - *

    The 'Subtitle/Description refinement' frame is used for information directly related to the contents title (e.g. "Op. 16" or "Performed live at Wembley"). - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTIT3.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTIT3 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTIT3 datatype. - */ - public FrameBodyTIT3() { - } - - public FrameBodyTIT3(FrameBodyTIT3 body) { - super(body); - } - - /** - * Creates a new FrameBodyTIT3 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTIT3(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTIT3 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTIT3(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_TITLE_REFINEMENT; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java deleted file mode 100644 index b072e84..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.reference.MusicalKey; - -import java.nio.ByteBuffer; - -/** - * Initial key Text information frame. - *

    The 'Initial key' frame contains the musical key in which the sound starts. It is represented as a string with - * a maximum length of three characters. The ground keys are represented with "A","B","C","D","E", "F" and "G" and halfkeys represented - * with "b" and "#". Minor is represented as "m". Example "Cbm". Off key is represented with an "o" only. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTKEY.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTKEY extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTKEY datatype. - */ - public FrameBodyTKEY() { - } - - public FrameBodyTKEY(FrameBodyTKEY body) { - super(body); - } - - /** - * Creates a new FrameBodyTKEY datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTKEY(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTKEY datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTKEY(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_INITIAL_KEY; - } - - /** - * @return true if text value is valid musical key notation - */ - public boolean isValid() { - return MusicalKey.isValid(getFirstTextValue()); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.java deleted file mode 100644 index a4881cc..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.reference.Languages; - -import java.nio.ByteBuffer; - -/** - * Language(s) Text information frame. - *

    The 'Language(s)' frame should contain the languages of the text or lyrics spoken or sung in the audio. The language is represented with three characters according to ISO-639-2. If more than one language is used in the text their language codes should follow according to their usage. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - *

    - * TODO:Although rare TLAN can actually return multiple language codes, at the moment they are all returned as a single - * string via getText(), any additional parsing has to be done externally. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTLAN.java 1028 2012-03-01 11:07:39Z paultaylor $ - */ -public class FrameBodyTLAN extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - - /** - * Creates a new FrameBodyTLAN datatype. - */ - public FrameBodyTLAN() { - super(); - } - - public FrameBodyTLAN(FrameBodyTLAN body) { - super(body); - } - - /** - * Creates a new FrameBodyTLAN datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTLAN(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTLAN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTLAN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_LANGUAGE; - } - - /** - * @return true if text value is valid language code - */ - public boolean isValid() { - return Languages.getInstanceOf().getValueForId(getFirstTextValue()) != null; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java deleted file mode 100644 index e9c85bd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Length Text information frame. - *

    The 'Length' frame contains the length of the audiofile in milliseconds, represented as a numeric string. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTLEN.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTLEN extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTLEN datatype. - */ - public FrameBodyTLEN() { - } - - public FrameBodyTLEN(FrameBodyTLEN body) { - super(body); - } - - /** - * Creates a new FrameBodyTLEN datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTLEN(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTLEN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTLEN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_LENGTH; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java deleted file mode 100644 index f7b9705..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTMCL.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTMCL extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - /** - * Creates a new FrameBodyTMCL datatype. - */ - public FrameBodyTMCL() { - } - - public FrameBodyTMCL(FrameBodyTMCL body) { - super(body); - } - - /** - * Creates a new FrameBodyTMCL datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTMCL(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTMCL datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTMCL(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_MUSICIAN_CREDITS; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java deleted file mode 100644 index 95a58f0..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Length Text information frame. - *

    The 'Media type' frame describes from which media the sound - * originated. This may be a text string or a reference to the - * predefined media types found in the list below. References are made - * within "(" and ")" and are optionally followed by a text refinement, - * e.g. "(MC) with four channels". If a text refinement should begin - * with a "(" character it should be replaced with "((" in the same way - * as in the "TCO" frame. Predefined refinements is appended after the - * media type, e.g. "(CD/A)" or "(VID/PAL/VHS)". - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    DIG Other digital media
    /A
     
    Analog transfer from media
    ANAOther analog media
    /WACWax cylinder
    /8CA
     
    8-track tape cassette
    CDCD
    /AAnalog transfer from media
    /DDDDD
    /ADADD
    /AA
     
    AAD
    LDLaserdisc
    /A
     
    Analog transfer from media
    TTTurntable records
    /3333.33 rpm
    /4545 rpm
    /7171.29 rpm
    /7676.59 rpm
    /7878.26 rpm
    /80
     
    80 rpm
    MDMiniDisc
    /A
     
    Analog transfer from media
    DATDAT
    /AAnalog transfer from media
    /1standard, 48 kHz/16 bits, linear
    /2mode 2, 32 kHz/16 bits, linear
    /3mode 3, 32 kHz/12 bits, nonlinear, low speed
    /4mode 4, 32 kHz/12 bits, 4 channels
    /5mode 5, 44.1 kHz/16 bits, linear
    /6
     
    mode 6, 44.1 kHz/16 bits, 'wide track' play
    DCCDCC
    /A
     
    Analog transfer from media
    DVDDVD
    /A
     
    Analog transfer from media
    TVTelevision
    /PALPAL
    /NTSCNTSC
     /SECAM
     
    SECAM
    VIDVideo
    /PALPAL
    /NTSCNTSC
    /SECAMSECAM
    /VHSVHS
    /SVHSS-VHS
    /BETA
     
    BETAMAX
    RADRadio
    /FMFM
    /AMAM
    /LWLW
    /MW
     
    MW
    TELTelephone
    /I
     
    ISDN
    MCMC (normal cassette)
    /44.75 cm/s (normal speed for a two sided cassette)
    /99.5 cm/s
    /IType I cassette (ferric/normal)
    /IIType II cassette (chrome)
    /IIIType III cassette (ferric chrome)
    /IV
     
    Type IV cassette (metal)
    REEReel
    /99.5 cm/s
    /1919 cm/s
    /3838 cm/s
    /7676 cm/s
    /IType I cassette (ferric/normal)
    /IIType II cassette (chrome)
    /IIIType III cassette (ferric chrome)
    /IV
     
    Type IV cassette (metal)

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTMED.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTMED extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTMED datatype. - */ - public FrameBodyTMED() { - } - - public FrameBodyTMED(FrameBodyTMED body) { - super(body); - } - - /** - * Creates a new FrameBodyTMED datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTMED(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTMED datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTMED(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_MEDIA_TYPE; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java deleted file mode 100644 index c2b232a..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTMOO.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - - -public class FrameBodyTMOO extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - /** - * Creates a new FrameBodyTMOO datatype. - */ - public FrameBodyTMOO() { - } - - public FrameBodyTMOO(FrameBodyTMOO body) { - super(body); - } - - /** - * Creates a new FrameBodyTMOO datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTMOO(byte textEncoding, String text) { - super(textEncoding, text); - } - - public FrameBodyTMOO(FrameBodyTXXX body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - this.setObjectValue(DataTypes.OBJ_TEXT, body.getText()); - } - - /** - * Creates a new FrameBodyTMOO datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTMOO(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_MOOD; - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java deleted file mode 100644 index 30e7ed0..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Original album/movie/show title Text information frame. - *

    The 'Original album/movie/show title' frame is intended for the title of the original recording (or source of sound), if for example the music - * in the file should be a cover of a previously released song. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTOAL.java 921 2010-10-14 11:04:46Z paultaylor $ - */ -public class FrameBodyTOAL extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTOAL datatype. - */ - public FrameBodyTOAL() { - } - - public FrameBodyTOAL(FrameBodyTOAL body) { - super(body); - } - - /** - * Creates a new FrameBodyTOAL datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTOAL(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTOAL datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTOAL(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ORIG_TITLE; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java deleted file mode 100644 index fb2c68d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Original filename Text information frame. - *

    The 'Original filename' frame contains the preferred filename for the file, since some media doesn't allow the - * desired length of the filename. The filename is case sensitive and includes its suffix. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTOFN.java 947 2011-01-17 13:53:20Z paultaylor $ - */ -public class FrameBodyTOFN extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTOFN datatype. - */ - public FrameBodyTOFN() { - } - - public FrameBodyTOFN(FrameBodyTOFN body) { - super(body); - } - - /** - * Creates a new FrameBodyTOFN datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTOFN(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTOFN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTOFN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ORIG_FILENAME; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java deleted file mode 100644 index 38ffccd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Original lyricist(s)/text writer(s) Text information frame. - *

    The 'Original lyricist(s)/text writer(s)' frame is intended for the text writer(s) of the original recording, if for example the music in the file should be a cover of a previously released song. The text writers are seperated with the "/" character. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTOLY.java 921 2010-10-14 11:04:46Z paultaylor $ - */ -public class FrameBodyTOLY extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTOLY datatype. - */ - public FrameBodyTOLY() { - } - - public FrameBodyTOLY(FrameBodyTOLY body) { - super(body); - } - - /** - * Creates a new FrameBodyTOLY datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTOLY(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTOLY datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTOLY(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ORIG_LYRICIST; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java deleted file mode 100644 index 358b095..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Original artist(s)/performer(s) Text information frame. - *

    The 'Original artist(s)/performer(s)' frame is intended for the performer(s) of the original recording, if for - * example the music in the file should be a cover of a previously released song. The performers are separated with - * the "/" character. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTOPE.java 922 2010-10-14 13:31:09Z paultaylor $ - */ -public class FrameBodyTOPE extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTOPE datatype. - */ - public FrameBodyTOPE() { - } - - public FrameBodyTOPE(FrameBodyTOPE body) { - super(body); - } - - /** - * Creates a new FrameBodyTOPE datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTOPE(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTOPE datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTOPE(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ORIGARTIST; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java deleted file mode 100644 index de9f145..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v23Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - -/** - * Original release year Text information frame. - *

    The 'Original release year' frame is intended for the year when the original recording, if for example the music - * in the file should be a cover of a previously released song, was released. The field is formatted as in the "TYER" - * frame. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTORY.java 932 2010-11-26 13:13:15Z paultaylor $ - */ -public class FrameBodyTORY extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - private static final int NUMBER_OF_DIGITS_IN_YEAR = 4; - - /** - * Creates a new FrameBodyTORY datatype. - */ - public FrameBodyTORY() { - } - - public FrameBodyTORY(FrameBodyTORY body) { - super(body); - } - - /** - * Creates a new FrameBodyTORY datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTORY(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * When converting v4 TDOR to v3 TORY frame - * - * @param body - */ - public FrameBodyTORY(FrameBodyTDOR body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - String year = body.getText(); - if (body.getText().length() > NUMBER_OF_DIGITS_IN_YEAR) { - year = body.getText().substring(0, NUMBER_OF_DIGITS_IN_YEAR); - } - setObjectValue(DataTypes.OBJ_TEXT, year); - } - - /** - * Creates a new FrameBodyTORY datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTORY(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TORY; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java deleted file mode 100644 index b037c47..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * File owner/licensee Text information frame. - *

    The 'File owner/licensee' frame contains the name of the owner or licensee of the file and it's contents. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTOWN.java 947 2011-01-17 13:53:20Z paultaylor $ - */ -public class FrameBodyTOWN extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTOWN datatype. - */ - public FrameBodyTOWN() { - } - - public FrameBodyTOWN(FrameBodyTOWN body) { - super(body); - } - - /** - * Creates a new FrameBodyTOWN datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTOWN(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTOWN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTOWN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_FILE_OWNER; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java deleted file mode 100644 index d31f25f..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group Text information frame. - *

    The 'Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group' is used for the main artist(s). They are seperated with the "/" character. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTPE1.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTPE1 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTPE1 datatype. - */ - public FrameBodyTPE1() { - } - - public FrameBodyTPE1(FrameBodyTPE1 body) { - super(body); - } - - /** - * Creates a new FrameBodyTPE1 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTPE1(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTPE1 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTPE1(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ARTIST; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java deleted file mode 100644 index 885b973..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Band/Orchestra/Accompaniment Text information frame. - *

    The 'Band/Orchestra/Accompaniment' frame is used for additional information about the performers in the recording. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTPE2.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTPE2 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTPE2 datatype. - */ - public FrameBodyTPE2() { - } - - public FrameBodyTPE2(FrameBodyTPE2 body) { - super(body); - } - - /** - * Creates a new FrameBodyTPE2 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTPE2(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTPE2 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTPE2(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ACCOMPANIMENT; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java deleted file mode 100644 index eaa1f38..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Conductor Text information frame. - *

    The 'Conductor' frame is used for the name of the conductor. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTPE3.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTPE3 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTPE3 datatype. - */ - public FrameBodyTPE3() { - } - - public FrameBodyTPE3(FrameBodyTPE3 body) { - super(body); - } - - /** - * Creates a new FrameBodyTPE3 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTPE3(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTPE3 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTPE3(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_CONDUCTOR; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java deleted file mode 100644 index acb5788..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Interpreted, remixed, or otherwise modified by Text information frame. - *

    The 'Interpreted, remixed, or otherwise modified by' frame contains more information about the people behind a remix and similar interpretations of another existing piece. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTPE4.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTPE4 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTPE4 datatype. - */ - public FrameBodyTPE4() { - } - - public FrameBodyTPE4(FrameBodyTPE4 body) { - super(body); - } - - /** - * Creates a new FrameBodyTPE4 datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTPE4(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTPE4 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTPE4(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_REMIXED; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java deleted file mode 100644 index 45669f8..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.PartOfSet; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - -/** - * Part of a set Text information frame. - *

    - *

    The 'Part of a set' frame is a numeric string that describes which part of a set the audio came from. - * This frame is used if the source described in the "TALB" frame is divided into several mediums, e.g. a double CD. - * The value may be extended with a "/" character and a numeric string containing the total number of parts in the set. - * e.g. "1/2". - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTPOS.java 1051 2012-05-24 09:54:09Z paultaylor $ - */ -public class FrameBodyTPOS extends AbstractID3v2FrameBody implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTRCK datatype. - */ - public FrameBodyTPOS() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue()); - } - - public FrameBodyTPOS(FrameBodyTPOS body) { - super(body); - } - - /** - * Creates a new FrameBodyTRCK datatype, the value is parsed literally - * - * @param textEncoding - * @param text - */ - public FrameBodyTPOS(byte textEncoding, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } - - public FrameBodyTPOS(byte textEncoding, Integer discNo, Integer discTotal) { - super(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(discNo, discTotal)); - } - - - /** - * Creates a new FrameBodyTRCK datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTPOS(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_SET; - } - - public String getUserFriendlyValue() { - return String.valueOf(getDiscNo()); - } - - public String getText() { - return getObjectValue(DataTypes.OBJ_TEXT).toString(); - } - - public void setText(String text) { - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } - - public Integer getDiscNo() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getCount(); - } - - public void setDiscNo(String discNo) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setCount(discNo); - } - - public String getDiscNoAsText() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getCountAsText(); - } - - public void setDiscNo(Integer discNo) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setCount(discNo); - } - - public Integer getDiscTotal() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getTotal(); - } - - public void setDiscTotal(String discTotal) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setTotal(discTotal); - } - - public String getDiscTotalAsText() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getTotalAsText(); - } - - public void setDiscTotal(Integer discTotal) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setTotal(discTotal); - } - - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new PartOfSet(DataTypes.OBJ_TEXT, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java deleted file mode 100644 index a616bf3..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTPRO.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTPRO extends AbstractFrameBodyTextInfo implements ID3v24FrameBody { - /** - * Creates a new FrameBodyTPRO datatype. - */ - public FrameBodyTPRO() { - } - - public FrameBodyTPRO(FrameBodyTPRO body) { - super(body); - } - - /** - * Creates a new FrameBodyTPRO datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTPRO(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTPRO datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTPRO(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_PRODUCED_NOTICE; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java deleted file mode 100644 index 553c6dd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Publisher Text information frame. - *

    The 'Publisher' frame simply contains the name of the label or publisher. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTPUB.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTPUB extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTPUB datatype. - */ - public FrameBodyTPUB() { - } - - public FrameBodyTPUB(FrameBodyTPUB body) { - super(body); - } - - /** - * Creates a new FrameBodyTPUB datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTPUB(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTPUB datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTPUB(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_PUBLISHER; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java deleted file mode 100644 index 5666cdb..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.PartOfSet; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - -/** - * Track number/position in set Text Information frame. - *

    - *

    The 'Track number/Position in set' frame is a numeric string containing the order number of the audio-file on its original recording. - *

    - * This may be extended with a "/" character and a numeric string containing the total number of tracks/elements on the original recording. - * e.g. "4/9". - *

    - * Some applications like to prepend the track number with a zero to aid sorting, (i.e 02 comes before 10) - *

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTRCK.java 1051 2012-05-24 09:54:09Z paultaylor $ - */ -public class FrameBodyTRCK extends AbstractID3v2FrameBody implements ID3v23FrameBody, ID3v24FrameBody { - - /** - * Creates a new FrameBodyTRCK datatype. - */ - public FrameBodyTRCK() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue()); - } - - public FrameBodyTRCK(FrameBodyTRCK body) { - super(body); - } - - /** - * Creates a new FrameBodyTRCK datatype, the value is parsed literally - * - * @param textEncoding - * @param text - */ - public FrameBodyTRCK(byte textEncoding, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } - - public FrameBodyTRCK(byte textEncoding, Integer trackNo, Integer trackTotal) { - super(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(trackNo, trackTotal)); - } - - /** - * Creates a new FrameBodyTRCK datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTRCK(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public String getUserFriendlyValue() { - return String.valueOf(getTrackNo()); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_TRACK; - } - - public Integer getTrackNo() { - PartOfSet.PartOfSetValue value = (PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT); - return value.getCount(); - } - - public void setTrackNo(String trackNo) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setCount(trackNo); - } - - public String getTrackNoAsText() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getCountAsText(); - } - - public String getText() { - return getObjectValue(DataTypes.OBJ_TEXT).toString(); - } - - public void setText(String text) { - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } - - public void setTrackNo(Integer trackNo) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setCount(trackNo); - } - - public Integer getTrackTotal() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getTotal(); - } - - public void setTrackTotal(String trackTotal) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setTotal(trackTotal); - } - - public String getTrackTotalAsText() { - return ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).getTotalAsText(); - } - - public void setTrackTotal(Integer trackTotal) { - ((PartOfSet.PartOfSetValue) getObjectValue(DataTypes.OBJ_TEXT)).setTotal(trackTotal); - } - - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new PartOfSet(DataTypes.OBJ_TEXT, this)); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java deleted file mode 100644 index abe0b68..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Recording dates Text information frame. - *

    The 'Recording dates' frame is a intended to be used as complement to the "TYER", "TDAT" and "TIME" frames. E.g. "4th-7th June, 12th June" in combination with the "TYER" frame. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTRDA.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTRDA extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - /** - * Creates a new FrameBodyTRDA datatype. - */ - public FrameBodyTRDA() { - } - - public FrameBodyTRDA(FrameBodyTRDA body) { - super(body); - } - - /** - * Creates a new FrameBodyTRDA datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTRDA(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTRDA datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTRDA(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TRDA; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java deleted file mode 100644 index 6894187..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Internet radio station name Text information frame. - *

    The 'Internet radio station name' frame contains the name of the internet radio station from which the audio is streamed. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTRSN.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTRSN extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTRSN datatype. - */ - public FrameBodyTRSN() { - } - - public FrameBodyTRSN(FrameBodyTRSN body) { - super(body); - } - - /** - * Creates a new FrameBodyTRSN datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTRSN(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTRSN datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTRSN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_RADIO_NAME; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java deleted file mode 100644 index 0f2f2a3..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Internet radio station owner Text information frame. - *

    The 'Internet radio station owner' frame contains the name of the owner of the internet radio station from which the audio is streamed. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTRSO.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTRSO extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTRSO datatype. - */ - public FrameBodyTRSO() { - } - - public FrameBodyTRSO(FrameBodyTRSO body) { - super(body); - } - - /** - * Creates a new FrameBodyTRSO datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTRSO(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTRSO datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTRSO(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_RADIO_OWNER; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java deleted file mode 100644 index 7431d00..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Size Text information frame. - *

    The 'Size' frame contains the size of the audiofile in bytes, excluding the ID3v2 tag, represented as a numeric string. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTSIZ.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTSIZ extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - /** - * Creates a new FrameBodyTSIZ datatype. - */ - public FrameBodyTSIZ() { - } - - public FrameBodyTSIZ(FrameBodyTSIZ body) { - super(body); - } - - /** - * Creates a new FrameBodyTSIZ datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSIZ(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSIZ datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSIZ(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TSIZ; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java deleted file mode 100644 index 8043f33..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Album Artist Sort name ( iTunes Only) - */ -public class FrameBodyTSO2 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOA datatype. - */ - public FrameBodyTSO2() { - } - - public FrameBodyTSO2(FrameBodyTSO2 body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOA datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSO2(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOA datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSO2(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ALBUM_ARTIST_SORT_ORDER_ITUNES; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java deleted file mode 100644 index aaa24a1..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTSOA.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Album Sort name - */ -public class FrameBodyTSOA extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOA datatype. - */ - public FrameBodyTSOA() { - } - - public FrameBodyTSOA(FrameBodyTSOA body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOA datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSOA(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOA datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSOA(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ALBUM_SORT_ORDER; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java deleted file mode 100644 index 11bc677..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Composer Sort name (iTunes Only) - */ -public class FrameBodyTSOC extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOC datatype. - */ - public FrameBodyTSOC() { - } - - public FrameBodyTSOC(FrameBodyTSOC body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOA datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSOC(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOA datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSOC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_COMPOSER_SORT_ORDER_ITUNES; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java deleted file mode 100644 index a93cf04..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTSOP.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTSOP extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOP datatype. - */ - public FrameBodyTSOP() { - } - - public FrameBodyTSOP(FrameBodyTSOP body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOP datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSOP(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOP datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSOP(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ARTIST_SORT_ORDER; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java deleted file mode 100644 index 5f07214..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTSOT.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - * Title Sort name - */ -public class FrameBodyTSOT extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOT datatype. - */ - public FrameBodyTSOT() { - } - - public FrameBodyTSOT(FrameBodyTSOT body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSOT(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSOT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_TITLE_SORT_ORDER; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java deleted file mode 100644 index df2abcd..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTSRC.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTSRC extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyTSRC datatype. - */ - public FrameBodyTSRC() { - } - - public FrameBodyTSRC(FrameBodyTSRC body) { - super(body); - } - - /** - * Creates a new FrameBodyTSRC datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSRC(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSRC datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSRC(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_ISRC; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java deleted file mode 100644 index 9389ae5..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Software/Hardware and settings used for encoding Text information frame. - *

    The 'Software/Hardware and settings used for encoding' frame includes the used audio encoder and its settings when the file was encoded. Hardware refers to hardware encoders, not the computer on which a program was run. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTSSE.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTSSE extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTSSE datatype. - */ - public FrameBodyTSSE() { - } - - public FrameBodyTSSE(FrameBodyTSSE body) { - super(body); - } - - /** - * Creates a new FrameBodyTSSE datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSSE(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSSE datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTSSE(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_HW_SW_SETTINGS; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java deleted file mode 100644 index e485da0..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTSST.java 1059 2012-07-04 12:18:35Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -public class FrameBodyTSST extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyTSST datatype. - */ - public FrameBodyTSST() { - } - - public FrameBodyTSST(FrameBodyTSST body) { - super(body); - } - - /** - * Creates a new FrameBodyTSST datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTSST(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSST datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyTSST(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_SET_SUBTITLE; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java deleted file mode 100644 index d45b028..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyTXXX.java 1028 2012-03-01 11:07:39Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.NumberHashMap; -import org.jaudiotagger.tag.datatype.TextEncodedStringNullTerminated; -import org.jaudiotagger.tag.datatype.TextEncodedStringSizeTerminated; -import org.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - - -/** - * User defined text information frame - *

    - * This frame is intended for one-string text information concerning the - * audio file in a similar way to the other "T"-frames. The frame body - * consists of a description of the string, represented as a terminated - * string, followed by the actual string. There may be more than one - * "TXXX" frame in each tag, but only one with the same description. - *

    - *

    - * Text encoding $xx - * Description $00 (00) - * Value - */ -public class FrameBodyTXXX extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody { - //Used by Picard and Jaikoz - public static final String MUSICBRAINZ_ARTISTID = "MusicBrainz Artist Id"; - public static final String MUSICBRAINZ_ALBUM_ARTISTID = "MusicBrainz Album Artist Id"; - public static final String MUSICBRAINZ_ALBUMID = "MusicBrainz Album Id"; - public static final String MUSICBRAINZ_ORIGINAL_ALBUMID = "MusicBrainz Original Album Id"; - public static final String MUSICBRAINZ_RELEASE_GROUPID = "MusicBrainz Release Group Id"; - public static final String MUSICBRAINZ_DISCID = "MusicBrainz Disc Id"; - public static final String MUSICBRAINZ_ALBUM_TYPE = "MusicBrainz Album Type"; - public static final String MUSICBRAINZ_ALBUM_STATUS = "MusicBrainz Album Status"; - public static final String MUSICBRAINZ_ALBUM_COUNTRY = "MusicBrainz Album Release Country"; - public static final String MUSICBRAINZ_WORKID = "MusicBrainz Work Id"; - public static final String AMAZON_ASIN = "ASIN"; - public static final String MUSICIP_ID = "MusicIP PUID"; - public static final String BARCODE = "BARCODE"; - public static final String CATALOG_NO = "CATALOGNUMBER"; - public static final String MOOD = "MOOD"; //ID3 v23 only - public static final String TAGS = "TAGS"; - public static final String FBPM = "FBPM"; - public static final String SCRIPT = "Script"; - public static final String ARTISTS = "ARTISTS"; - public static final String ACOUSTID_FINGERPRINT = "Acoustid Fingerprint"; - public static final String ACOUSTID_ID = "Acoustid Id"; - public static final String COUNTRY = "Country"; - - //used by Foobar 20000 - public static final String ALBUM_ARTIST = "ALBUM ARTIST"; - public static final String PERFORMER = "PERFORMER"; - - /** - * Creates a new FrameBodyTXXX datatype. - */ - public FrameBodyTXXX() { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - this.setObjectValue(DataTypes.OBJ_TEXT, ""); - - } - - /** - * Convert from V4 TMOO Frame to V3 Frame - * - * @param body - */ - public FrameBodyTXXX(FrameBodyTMOO body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, MOOD); - this.setObjectValue(DataTypes.OBJ_TEXT, body.getText()); - } - - public FrameBodyTXXX(FrameBodyTXXX body) { - super(body); - } - - /** - * Creates a new FrameBodyTXXX datatype. - * - * @param textEncoding - * @param description - * @param text - */ - public FrameBodyTXXX(byte textEncoding, String description, String text) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - this.setObjectValue(DataTypes.OBJ_TEXT, text); - } - - /** - * Creates a new FrameBodyTXXX datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTXXX(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return the description field - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set the description field - * - * @param description - */ - public void setDescription(String description) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_USER_DEFINED_INFO; - } - - /** - * Because TXXX frames also have a text encoded description we need to check this as well. * - */ - public void write(ByteArrayOutputStream tagBuffer) { - //Ensure valid for type - setTextEncoding(ID3TextEncodingConversion.getTextEncoding(getHeader(), getTextEncoding())); - - //Ensure valid for description - if (!((TextEncodedStringNullTerminated) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - super.write(tagBuffer); - } - - /** - * This is different to other text Frames - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new TextEncodedStringSizeTerminated(DataTypes.OBJ_TEXT, this)); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java deleted file mode 100644 index 5728390..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.id3.ID3v23Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; - -/** - * Year Text information frame. - *

    The 'Year' frame is a numeric string with a year of the recording. This frames is always four characters long (until the year 10000). - *

    Deprecated in v2.4.0 - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyTYER.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyTYER extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - /** - * Creates a new FrameBodyTYER datatype. - */ - public FrameBodyTYER() { - } - - public FrameBodyTYER(FrameBodyTYER body) { - super(body); - } - - /** - * When converting v4 TDRC frame to v3 TYER - * - * @param body - */ - public FrameBodyTYER(FrameBodyTDRC body) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, body.getText()); - } - - /** - * Creates a new FrameBodyTYER datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyTYER(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTYER datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTYER(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TYER; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java deleted file mode 100644 index 2f6fe47..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyUFID.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Represents a Unique File ID for the file which relates - * to an external database. - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; -import org.jaudiotagger.tag.datatype.StringNullTerminated; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - * A UFID Framebody consists of an owner that identifies the server hosting the - * unique identifier database, and the unique identifier itself which can be up to 64 - * bytes in length. - */ -public class FrameBodyUFID extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - public static final String UFID_MUSICBRAINZ = "http://musicbrainz.org"; - public static final String UFID_ID3TEST = "http://www.id3.org/dummy/ufid.html"; - - /** - * Creates a new FrameBodyUFID datatype. - */ - public FrameBodyUFID() { - setOwner(""); - setUniqueIdentifier(new byte[0]); - } - - public FrameBodyUFID(FrameBodyUFID body) { - super(body); - } - - /** - * Creates a new FrameBodyUFID datatype. - * - * @param owner url of the database - * @param uniqueIdentifier unique identifier - */ - public FrameBodyUFID(String owner, byte[] uniqueIdentifier) { - setOwner(owner); - setUniqueIdentifier(uniqueIdentifier); - } - - /** - * Creates FrameBodyUFID datatype from buffer - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyUFID(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_UNIQUE_FILE_ID; - } - - /** - * @return the url of the the database that this ufid is stored in - */ - public String getOwner() { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * Set the owner of url of the the database that this ufid is stored in - * - * @param owner should be a valid url - */ - public void setOwner(String owner) { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * @return the unique identifier (within the owners domain) - */ - public byte[] getUniqueIdentifier() { - return (byte[]) getObjectValue(DataTypes.OBJ_DATA); - } - - /** - * Set the unique identifier (within the owners domain) - * - * @param uniqueIdentifier - */ - public void setUniqueIdentifier(byte[] uniqueIdentifier) { - setObjectValue(DataTypes.OBJ_DATA, uniqueIdentifier); - } - - protected void setupObjectList() { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUSER.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUSER.java deleted file mode 100644 index 5d5f134..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUSER.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.Languages; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * Terms of use frame. - *

    - *

    - * This frame contains a brief description of the terms of use and - * ownership of the file. More detailed information concerning the legal - * terms might be available through the "WCOP" frame. Newlines are - * allowed in the text. There may only be one "USER" frame in a tag. - *

    - * - * - * - * - *
    <Header for 'Terms of use frame', ID: "USER">
    Text encoding $xx
    Language $xx xx xx
    The actual text<text string according to encoding>

    - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyUSER.java 836 2009-11-12 15:44:07Z paultaylor $ - */ -public class FrameBodyUSER extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyUSER datatype. - */ - public FrameBodyUSER() { - // setObject("Text Encoding", new Byte((byte) 0)); - // setObject("Language", ""); - // setObject("Text", ""); - } - - public FrameBodyUSER(FrameBodyUSER body) { - super(body); - } - - /** - * Creates a new FrameBodyUSER datatype. - * - * @param textEncoding - * @param language - * @param text - */ - public FrameBodyUSER(byte textEncoding, String language, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - setObjectValue(DataTypes.OBJ_TEXT, text); - } - - - /** - * Create a new FrameBodyUser by reading from byte buffer - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyUSER(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_TERMS_OF_USE; - } - - /** - * @return lanaguage - */ - public String getLanguage() { - return (String) getObjectValue(DataTypes.OBJ_LANGUAGE); - } - - /** - * @param language - */ - public void setOwner(String language) { - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - } - - /** - * If the text cannot be encoded using current encoder, change the encoder - * - * @param tagBuffer - * @throws java.io.IOException - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((AbstractString) getObject(DataTypes.OBJ_TEXT)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringHashMap(DataTypes.OBJ_LANGUAGE, this, Languages.LANGUAGE_FIELD_SIZE)); - objectList.add(new StringSizeTerminated(DataTypes.OBJ_TEXT, this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java deleted file mode 100644 index 5dfeb69..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.reference.Languages; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -/** - * Unsychronised lyrics/text transcription frame. - *

    - *

    - * This frame contains the lyrics of the song or a text transcription of other vocal activities. The head includes an - * encoding descriptor and a content descriptor. The body consists of the actual text. The 'Content descriptor' is a - * terminated string. If no descriptor is entered, 'Content descriptor' is $00 (00) only. Newline characters are - * allowed in the text. There may be more than one 'Unsynchronised lyrics/text transcription' frame in each tag, but - * only one with the same language and content descriptor. - *

    - *

    - * - * - * - * - * - *
    <Header for 'Unsynchronised lyrics/text transcription', ID: "USLT">
    Text encoding $xx
    Language $xx xx xx
    Content descriptor<text string according to encoding> $00 (00)
    Lyrics/text <full text string according to encoding>

    - *

    - * You can retrieve the first value without the null terminator using {@link #getFirstTextValue} - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyUSLT.java 908 2010-08-04 18:43:30Z paultaylor $ - */ -public class FrameBodyUSLT extends AbstractID3v2FrameBody implements ID3v23FrameBody, ID3v24FrameBody { - /** - * Creates a new FrameBodyUSLT dataType. - */ - public FrameBodyUSLT() { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_LANGUAGE, ""); - setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - setObjectValue(DataTypes.OBJ_LYRICS, ""); - } - - /** - * Copy constructor - * - * @param body - */ - public FrameBodyUSLT(FrameBodyUSLT body) { - super(body); - } - - /** - * Creates a new FrameBodyUSLT datatype. - * - * @param textEncoding - * @param language - * @param description - * @param text - */ - public FrameBodyUSLT(byte textEncoding, String language, String description, String text) { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - setObjectValue(DataTypes.OBJ_LYRICS, text); - } - - /** - * Creates a new FrameBodyUSLT datatype, populated from buffer - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - * @throws InvalidTagException - */ - public FrameBodyUSLT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - public String getUserFriendlyValue() { - return getFirstTextValue(); - } - - /** - * Get a description field - * - * @return description - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set a description field - * - * @param description - */ - public void setDescription(String description) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_UNSYNC_LYRICS; - } - - /** - * Get the language field - * - * @return language - */ - public String getLanguage() { - return (String) getObjectValue(DataTypes.OBJ_LANGUAGE); - } - - /** - * Set the language field - * - * @param language - */ - public void setLanguage(String language) { - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - } - - /** - * Get the lyric field - * - * @return lyrics - */ - public String getLyric() { - return (String) getObjectValue(DataTypes.OBJ_LYRICS); - } - - /** - * Set the lyric field - * - * @param lyric - */ - public void setLyric(String lyric) { - setObjectValue(DataTypes.OBJ_LYRICS, lyric); - } - - /** - * Get first value - * - * @return value at index 0 - */ - public String getFirstTextValue() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_LYRICS); - return text.getValueAtIndex(0); - } - - /** - * Add additional lyric to the lyric field - * - * @param text - */ - public void addLyric(String text) { - setLyric(getLyric() + text); - } - - /** - * @param line - */ - public void addLyric(Lyrics3Line line) { - setLyric(getLyric() + line.writeString()); - } - - - public void write(ByteArrayOutputStream tagBuffer) { - - //Ensure valid for type - this.setTextEncoding(ID3TextEncodingConversion.getTextEncoding(getHeader(), getTextEncoding())); - - //Ensure valid for data - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - if (!((AbstractString) getObject(DataTypes.OBJ_LYRICS)).canBeEncoded()) { - this.setTextEncoding(ID3TextEncodingConversion.getUnicodeTextEncoding(getHeader())); - } - super.write(tagBuffer); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new StringHashMap(DataTypes.OBJ_LANGUAGE, this, Languages.LANGUAGE_FIELD_SIZE)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new TextEncodedStringSizeTerminated(DataTypes.OBJ_LYRICS, this)); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java deleted file mode 100644 index 0f7b327..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyUnsupported.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Frame that is not currently suported by this application - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import org.jaudiotagger.tag.datatype.DataTypes; - -import java.nio.ByteBuffer; - -/** - * Represents a framebody for a frame identifier jaudiotagger has not implemented a framebody for. - *

    - * This is likley to be because the FrameBody is not specified in the Specification but it may just be because the code - * has yet to be written, the library uses this framebody when it cant find an alternative. This is different to the - * ID3v2ExtensionFrameBody Interface which should be implemented by frame bodies that are non standard such as - * iTunes compilation frame (TCMP) but are commonly used. - */ -public class FrameBodyUnsupported extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody, ID3v22FrameBody { - /** - * Because used by any unknown frame identifier varies - */ - private String identifier = ""; - - /** - * @deprecated because no identifier set - */ - public FrameBodyUnsupported() { - - } - - /** - * Creates a new FrameBodyUnsupported - * - * @param identifier - */ - public FrameBodyUnsupported(String identifier) { - this.identifier = identifier; - } - - /** - * Create a new FrameBodyUnsupported - * - * @param identifier - * @param value - */ - public FrameBodyUnsupported(String identifier, byte[] value) { - this.identifier = identifier; - setObjectValue(DataTypes.OBJ_DATA, value); - } - - /** - * Creates a new FrameBodyUnsupported datatype. - * - * @param value - * @deprecated because no identifier set - */ - public FrameBodyUnsupported(byte[] value) { - setObjectValue(DataTypes.OBJ_DATA, value); - } - - /** - * Copy constructor - * - * @param copyObject a copy is made of this - */ - public FrameBodyUnsupported(FrameBodyUnsupported copyObject) { - super(copyObject); - this.identifier = copyObject.identifier; - - } - - /** - * Creates a new FrameBodyUnsupported datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidFrameException if unable to create framebody from buffer - * @throws org.jaudiotagger.tag.InvalidTagException - */ - public FrameBodyUnsupported(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * Return the frame identifier - * - * @return the identifier - */ - public String getIdentifier() { - return identifier; - } - - /** - * @param obj - * @return whether obj is equivalent to this object - */ - public boolean equals(Object obj) { - if (!(obj instanceof FrameBodyUnsupported)) { - return false; - } - - FrameBodyUnsupported object = (FrameBodyUnsupported) obj; - return this.identifier.equals(object.identifier) && super.equals(obj); - } - - - /** - * Because the contents of this frame are an array of bytes and could be large we just - * return the identifier. - * - * @return a string representation of this frame - */ - public String toString() { - return getIdentifier(); - } - - /** - * Setup the Object List. A byte Array which will be read upto frame size - * bytes. - */ - protected void setupObjectList() { - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java deleted file mode 100644 index 47f3086..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Commercial information URL link frames. - *

    The 'Commercial information' frame is a URL pointing at a webpage with information such as where the album can be - * bought. There may be more than one "WCOM" frame in a tag, but not with the same content. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWCOM.java 922 2010-10-14 13:31:09Z paultaylor $ - */ -public class FrameBodyWCOM extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWCOM datatype. - */ - public FrameBodyWCOM() { - } - - /** - * Creates a new FrameBodyWCOM datatype. - * - * @param urlLink - */ - public FrameBodyWCOM(String urlLink) { - super(urlLink); - } - - public FrameBodyWCOM(FrameBodyWCOM body) { - super(body); - } - - /** - * Creates a new FrameBodyWCOM datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWCOM(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_COMMERCIAL; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java deleted file mode 100644 index 311a7ae..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Copyright/Legal information URL link frames. - *

    The 'Copyright/Legal information' frame is a URL pointing at a webpage where the terms of use and ownership of the file is described. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWCOP.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyWCOP extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWCOP datatype. - */ - public FrameBodyWCOP() { - } - - /** - * Creates a new FrameBodyWCOP datatype. - * - * @param urlLink - */ - public FrameBodyWCOP(String urlLink) { - super(urlLink); - } - - public FrameBodyWCOP(FrameBodyWCOP body) { - super(body); - } - - /** - * Creates a new FrameBodyWCOP datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyWCOP(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_COPYRIGHT; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java deleted file mode 100644 index 4c94e95..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Official audio file webpage URL link frames. - *

    The 'Official audio file webpage' frame is a URL pointing at a file specific webpage. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWOAF.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyWOAF extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWOAF datatype. - */ - public FrameBodyWOAF() { - } - - /** - * Creates a new FrameBodyWOAF datatype. - * - * @param urlLink - */ - public FrameBodyWOAF(String urlLink) { - super(urlLink); - } - - public FrameBodyWOAF(FrameBodyWOAF body) { - super(body); - } - - /** - * Creates a new FrameBodyWOAF datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWOAF(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_FILE_WEB; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java deleted file mode 100644 index 720b7d3..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Official artist/performer webpage URL link frames. - *

    The 'Official artist/performer webpage' frame is a URL pointing at the artists official webpage. - * There may be more than one "WOAR" frame in a tag if the audio contains more than one performer, but not with - * the same content. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWOAR.java 1036 2012-03-05 17:25:24Z paultaylor $ - */ -public class FrameBodyWOAR extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWOAR datatype. - */ - public FrameBodyWOAR() { - } - - /** - * Creates a new FrameBodyWOAR datatype. - * - * @param urlLink - */ - public FrameBodyWOAR(String urlLink) { - super(urlLink); - } - - public FrameBodyWOAR(FrameBodyWOAR body) { - super(body); - } - - /** - * Creates a new FrameBodyWOAR datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWOAR(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_ARTIST_WEB; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java deleted file mode 100644 index 63ebcf3..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Official audio source webpage URL link frames. - *

    The 'Official audio source webpage' frame is a URL pointing at the official webpage for the source of the audio - * file, e.g. a movie. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWOAS.java 922 2010-10-14 13:31:09Z paultaylor $ - */ -public class FrameBodyWOAS extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWOAS datatype. - */ - public FrameBodyWOAS() { - } - - /** - * Creates a new FrameBodyWOAS datatype. - * - * @param urlLink - */ - public FrameBodyWOAS(String urlLink) { - super(urlLink); - } - - public FrameBodyWOAS(FrameBodyWOAS body) { - super(body); - } - - /** - * Creates a new FrameBodyWOAS datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWOAS(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_SOURCE_WEB; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java deleted file mode 100644 index 91a1d24..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Official internet radio station homepage URL link frames. - *

    The 'Official internet radio station homepage' contains a URL pointing at the homepage of the internet radio station. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWORS.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyWORS extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWORS datatype. - */ - public FrameBodyWORS() { - } - - /** - * Creates a new FrameBodyWORS datatype. - * - * @param urlLink - */ - public FrameBodyWORS(String urlLink) { - super(urlLink); - } - - public FrameBodyWORS(FrameBodyWORS body) { - super(body); - } - - /** - * Creates a new FrameBodyWORS datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWORS(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_OFFICIAL_RADIO; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java deleted file mode 100644 index dc6aa5d..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Payment URL link frames. - *

    The 'Payment' frame is a URL pointing at a webpage that will handle the process of paying for this file. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWPAY.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyWPAY extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWPAY datatype. - */ - public FrameBodyWPAY() { - } - - /** - * Creates a new FrameBodyWPAY datatype. - * - * @param urlLink - */ - public FrameBodyWPAY(String urlLink) { - super(urlLink); - } - - public FrameBodyWPAY(FrameBodyWPAY body) { - super(body); - } - - /** - * Creates a new FrameBodyWPAY datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWPAY(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_PAYMENT; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java deleted file mode 100644 index 8e97180..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * MusicTag Copyright (C)2003,2004 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Publishers official webpage URL link frames. - *

    The 'Publishers official webpage' frame is a URL pointing at the official wepage for the publisher. - *

    - *

    For more details, please refer to the ID3 specifications: - *

    - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id: FrameBodyWPUB.java 832 2009-11-12 13:25:38Z paultaylor $ - */ -public class FrameBodyWPUB extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - /** - * Creates a new FrameBodyWPUB datatype. - */ - public FrameBodyWPUB() { - } - - /** - * Creates a new FrameBodyWPUB datatype. - * - * @param urlLink - */ - public FrameBodyWPUB(String urlLink) { - super(urlLink); - } - - public FrameBodyWPUB(FrameBodyWPUB body) { - super(body); - } - - /** - * Creates a new FrameBodyWPUB datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws InvalidTagException - */ - public FrameBodyWPUB(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_URL_PUBLISHERS; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java deleted file mode 100644 index a3e5395..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FrameBodyWXXX.java 1030 2012-03-01 12:51:57Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Represents a user defined URL,must also privide a description - */ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.*; -import org.jaudiotagger.tag.id3.ID3v24Frames; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.List; - -/** - * Represents a user defined url - */ -public class FrameBodyWXXX extends AbstractFrameBodyUrlLink implements ID3v24FrameBody, ID3v23FrameBody { - - public static final String URL_DISCOGS_RELEASE_SITE = "DISCOGS_RELEASE"; - public static final String URL_WIKIPEDIA_RELEASE_SITE = "WIKIPEDIA_RELEASE"; - public static final String URL_OFFICIAL_RELEASE_SITE = "OFFICIAL_RELEASE"; - public static final String URL_DISCOGS_ARTIST_SITE = "DISCOGS_ARTIST"; - public static final String URL_WIKIPEDIA_ARTIST_SITE = "WIKIPEDIA_ARTIST"; - public static final String URL_LYRICS_SITE = "LYRICS_SITE"; - - /** - * Creates a new FrameBodyWXXX datatype. - */ - public FrameBodyWXXX() { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, ""); - this.setObjectValue(DataTypes.OBJ_URLLINK, ""); - } - - public FrameBodyWXXX(FrameBodyWXXX body) { - super(body); - } - - /** - * Creates a new FrameBodyWXXX datatype. - * - * @param textEncoding - * @param description - * @param urlLink - */ - public FrameBodyWXXX(byte textEncoding, String description, String urlLink) { - this.setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - this.setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - this.setObjectValue(DataTypes.OBJ_URLLINK, urlLink); - } - - /** - * Creates a new FrameBodyWXXX datatype by reading from file. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyWXXX(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * @return a description of the hyperlink - */ - public String getDescription() { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set a description of the hyperlink - * - * @param description - */ - public void setDescription(String description) { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v24Frames.FRAME_ID_USER_DEFINED_URL; - } - - /** - * If the description cannot be encoded using the current encoding change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) { - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) { - this.setTextEncoding(TextEncoding.UTF_16); - } - super.write(tagBuffer); - } - - /** - * This is different ot other URL Links - */ - protected void setupObjectList() { - objectList.add(new NumberHashMap(DataTypes.OBJ_TEXT_ENCODING, this, TextEncoding.TEXT_ENCODING_FIELD_SIZE)); - objectList.add(new TextEncodedStringNullTerminated(DataTypes.OBJ_DESCRIPTION, this)); - objectList.add(new StringSizeTerminated(DataTypes.OBJ_URLLINK, this)); - } - - /** - * Retrieve the complete text String but without any trailing nulls - *

    - * If multiple values are held these will be returned, needless trailing nulls will not be returned - * - * @return the text string - */ - public String getUrlLinkWithoutTrailingNulls() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_URLLINK); - return text.getValueWithoutTrailingNull(); - } - - /** - * Get first value - * - * @return value at index 0 - */ - public String getFirstUrlLink() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_URLLINK); - return text.getValueAtIndex(0); - } - - /** - * Get text value at index - *

    - * When a multiple values are stored within a single text frame this method allows access to any of the - * individual values. - * - * @param index - * @return value at index - */ - public String getUrlLinkAtIndex(int index) { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_URLLINK); - return text.getValueAtIndex(index); - } - - public List getUrlLinks() { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_URLLINK); - return text.getValues(); - } - - /** - * Add additional value to value - * - * @param value at index - */ - public void addUrlLink(String value) { - TextEncodedStringSizeTerminated text = (TextEncodedStringSizeTerminated) getObject(DataTypes.OBJ_URLLINK); - text.addValue(value); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java deleted file mode 100644 index 1e49e89..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Album Sort name, this is what MusicBrainz uses in ID3v23 because TSOA not supported. - *

    - * However iTunes uses TSOA even in ID3v23, so we have two possible options - */ -public class FrameBodyXSOA extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOT datatype. - */ - public FrameBodyXSOA() { - } - - public FrameBodyXSOA(FrameBodyXSOA body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyXSOA(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyXSOA(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_ALBUM_SORT_ORDER_MUSICBRAINZ; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java deleted file mode 100644 index d1a186f..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Artist Sort name, this is what MusicBrainz uses in ID3v23 because TSOP not supported. - *

    - * However iTunes uses TSOP even in ID3v23, so we have two possible options - */ -public class FrameBodyXSOP extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOT datatype. - */ - public FrameBodyXSOP() { - } - - public FrameBodyXSOP(FrameBodyXSOP body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyXSOP(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyXSOP(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_ARTIST_SORT_ORDER_MUSICBRAINZ; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java deleted file mode 100644 index c6eaeed..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.jaudiotagger.tag.id3.framebody; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Title Sort name, this is what MusicBrainz uses in ID3v23 because TSOT not supported. - *

    - * However iTunes uses TSOT even in ID3v23, so we have two possible options - */ -public class FrameBodyXSOT extends AbstractFrameBodyTextInfo implements ID3v23FrameBody { - /** - * Creates a new FrameBodyTSOT datatype. - */ - public FrameBodyXSOT() { - } - - public FrameBodyXSOT(FrameBodyXSOT body) { - super(body); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyXSOT(byte textEncoding, String text) { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTSOT datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyXSOT(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() { - return ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_MUSICBRAINZ; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java deleted file mode 100644 index 120dca8..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Jaudiotagger Copyright (C)2004,2005 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a framebody used in ID3v22Tags. - * - * @author Paul Taylor - * @version $Id: ID3v22FrameBody.java 243 2007-03-06 12:25:39Z paultaylor $ - */ -public interface ID3v22FrameBody { - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java deleted file mode 100644 index c6be928..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Jaudiotagger Copyright (C)2004,2005 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a framebody used in ID3v23Tags. - * - * @author Paul Taylor - * @version $Id: ID3v23FrameBody.java 520 2008-01-01 15:16:38Z paultaylor $ - */ -public interface ID3v23FrameBody { - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java deleted file mode 100644 index 03e1348..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Jaudiotagger Copyright (C)2004,2005 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a framebody used in ID3v24Tags. - * - * @author Paul Taylor - * @version $Id: ID3v24FrameBody.java 520 2008-01-01 15:16:38Z paultaylor $ - */ -public interface ID3v24FrameBody { - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java b/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java deleted file mode 100644 index ab8f87c..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Horizon Wimba Copyright (C)2006 - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -package org.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a frame used in ID3v2 Chapter Tags. - * - * @author Marc Gimpel, Horizon Wimba S.A. - * @version $Id: ID3v2ChapterFrameBody.java 177 2006-08-21 10:37:28Z mgimpel $ - */ -public interface ID3v2ChapterFrameBody { - -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/framebody/package.html b/src/main/java/org/jaudiotagger/tag/id3/framebody/package.html deleted file mode 100644 index a6cc088..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/framebody/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for ID3V2 frames. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/id3/package.html b/src/main/java/org/jaudiotagger/tag/id3/package.html deleted file mode 100644 index f000d5e..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for all flavors of ID3. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/id3/reference/ID3Rating.java b/src/main/java/org/jaudiotagger/tag/id3/reference/ID3Rating.java deleted file mode 100644 index 490696f..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/reference/ID3Rating.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.jaudiotagger.tag.id3.reference; - -import org.jaudiotagger.tag.reference.Tagger; - -/** - * Factory class that can be used to convert ratings to suit your preferred tagger/player - */ -//TODO Only the main ones done yet -public abstract class ID3Rating { - - public static ID3Rating getInstance(Tagger tagger) { - switch (tagger) { - case ITUNES: - return ITunesRating.getInstance(); - - case MEDIA_MONKEY: - return MediaMonkeyPlayerRating.getInstance(); - - case MEDIAPLAYER: - return MediaPlayerRating.getInstance(); - - default: - return MediaPlayerRating.getInstance(); - } - } - - public abstract int convertRatingFromFiveStarScale(int value); - - public abstract int convertRatingToFiveStarScale(int value); -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/reference/ITunesRating.java b/src/main/java/org/jaudiotagger/tag/id3/reference/ITunesRating.java deleted file mode 100644 index bc3955a..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/reference/ITunesRating.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.jaudiotagger.tag.id3.reference; - -/** - * Defines the how ratings are stored in iTunes (but iTunes doesn't actually store in the field) - *

    - * Rating=0 → POPM=0 - * Rating=1 → POPM=20 - * Rating=2 → POPM=40 - * Rating=3 → POPM=60 - * Rating=4 → POPM=80 - * Rating=5 → POPM=100 - */ -public class ITunesRating extends ID3Rating { - private static ID3Rating rating = null; - - private ITunesRating() { - } - - public static ID3Rating getInstance() { - if (rating == null) { - rating = new ITunesRating(); - } - return rating; - } - - public int convertRatingFromFiveStarScale(int value) { - if (value < 0 || value > 5) { - throw new IllegalArgumentException("convert Ratings from Five Star Scale accepts values from 0 to 5 not:" + value); - } - int newValue = 0; - - switch (value) { - case 0: - break; - - case 1: - newValue = 20; - break; - - case 2: - newValue = 40; - break; - - case 3: - newValue = 60; - break; - - case 4: - newValue = 80; - break; - - case 5: - newValue = 100; - break; - - } - return newValue; - } - - public int convertRatingToFiveStarScale(int value) { - int newValue = 0; - if (value <= 0) { - newValue = 0; - } else if (value <= 20) { - newValue = 1; - } else if (value <= 40) { - newValue = 2; - } else if (value <= 60) { - newValue = 3; - } else if (value <= 80) { - newValue = 4; - } else if (value <= 100) { - newValue = 5; - } else { - newValue = 5; - } - return newValue; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java b/src/main/java/org/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java deleted file mode 100644 index a8542aa..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.jaudiotagger.tag.id3.reference; - -/** - * Defines the how ratings are stored In Media Monkey for ID3 - *

    - * POPM=0 → Rating=0 - * POPM=1 → Rating=1 - * POPM=2-8 → Rating=0 - * POPM=9-18 → Rating=0.5 - * POPM=19-28 → Rating=1 (MM2.5:Rating=0.5 → POPM=28) (MM3.0:Rating=0.5 → POPM=26) - * POPM=29 → Rating=1.5 - * POPM=30-39 → Rating=0.5 - * POPM=40-49 → Rating=1 - * POPM=50-59 → Rating=1.5 (MM2.5:Rating=1 → POPM=53) (MM3.0:Rating=1 → POPM=51) - * POPM=60-69 → Rating=2 - * POPM=70-90 → Rating=1.5 - * POPM=91-113 → Rating=2 - * POPM=114-123 → Rating=2.5 - * POPM=124-133 → Rating=3 (MM2.5:Rating=2.5 → POPM=129) (MM3.0:Rating=2.5 → POPM=128) - * POPM=134-141 → Rating=2.5 - * POPM=142-167 → Rating=3 - * POPM=168-191 → Rating=3.5 - * POPM=192-218 → Rating=4 - * POPM=219-247 → Rating=4.5 - * POPM=248-255 → Rating=5 - *

    - *

    - * TODO Media Monkey includes half stars so essentially a 10 star scale but not used by anything else much - */ -public class MediaMonkeyPlayerRating extends ID3Rating { - private static ID3Rating rating = null; - - private MediaMonkeyPlayerRating() { - } - - public static ID3Rating getInstance() { - if (rating == null) { - rating = new MediaMonkeyPlayerRating(); - } - return rating; - } - - public int convertRatingFromFiveStarScale(int value) { - if (value < 0 || value > 5) { - throw new IllegalArgumentException("convert Ratings from Five Star Scale accepts values from 0 to 5 not:" + value); - } - int newValue = 0; - - switch (value) { - case 0: - break; - - case 1: - break; - - case 2: - newValue = 64; - break; - - case 3: - newValue = 128; - break; - - case 4: - newValue = 196; - break; - - case 5: - newValue = 255; - break; - - } - return newValue; - } - - public int convertRatingToFiveStarScale(int value) { - int newValue = 0; - if (value <= 0) { - newValue = 0; - } else if (value <= 1) { - newValue = 1; - } else if (value <= 8) { - newValue = 0; - } else if (value <= 18) { - newValue = 1; - } else if (value <= 28) { - newValue = 1; - } else if (value <= 28) { - newValue = 1; - } else if (value <= 28) { - newValue = 1; - } else if (value <= 28) { - newValue = 1; - } else if (value <= 29) { - newValue = 2; - } else if (value <= 39) { - newValue = 1; - } else if (value <= 49) { - newValue = 1; - } else if (value <= 113) { - newValue = 2; - } else if (value <= 167) { - newValue = 3; - } else if (value <= 218) { - newValue = 4; - } else { - newValue = 5; - } - return newValue; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/reference/MediaPlayerRating.java b/src/main/java/org/jaudiotagger/tag/id3/reference/MediaPlayerRating.java deleted file mode 100644 index 022e8dc..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/reference/MediaPlayerRating.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.jaudiotagger.tag.id3.reference; - -/** - * Defines the how ratings are stored In Windows Media Player for ID3 - *

    - * Rating=0 → POPM=0 - * Rating=1 → POPM=1 - * Rating=2 → POPM=64 - * Rating=3 → POPM=128 - * Rating=4 → POPM=196 - * Rating=5 → POPM=255 - */ -public class MediaPlayerRating extends ID3Rating { - private static ID3Rating rating = null; - - private MediaPlayerRating() { - } - - public static ID3Rating getInstance() { - if (rating == null) { - rating = new MediaPlayerRating(); - } - return rating; - } - - public int convertRatingFromFiveStarScale(int value) { - if (value < 0 || value > 5) { - throw new IllegalArgumentException("convert Ratings from Five Star Scale accepts values from 0 to 5 not:" + value); - } - int newValue = 0; - - switch (value) { - case 0: - break; - - case 1: - break; - - case 2: - newValue = 64; - break; - - case 3: - newValue = 128; - break; - - case 4: - newValue = 196; - break; - - case 5: - newValue = 255; - break; - - } - return newValue; - } - - public int convertRatingToFiveStarScale(int value) { - int newValue = 0; - if (value <= 0) { - newValue = 0; - } else if (value <= 1) { - newValue = 1; - } else if (value <= 64) { - newValue = 2; - } else if (value <= 128) { - newValue = 3; - } else if (value <= 196) { - newValue = 4; - } else { - newValue = 5; - } - return newValue; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/reference/package.html b/src/main/java/org/jaudiotagger/tag/id3/reference/package.html deleted file mode 100644 index a545c04..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/reference/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for various ID3 rating systems. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ChannelTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/ChannelTypes.java deleted file mode 100644 index 2c3a3cb..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ChannelTypes.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: ChannelTypes.java 339 2007-08-06 16:04:38Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License ainteger with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Channel type used by - */ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class ChannelTypes extends AbstractIntStringValuePair { - private static ChannelTypes channelTypes; - - private ChannelTypes() { - idToValue.put(0x00, "Other"); - idToValue.put(0x01, "Master volume"); - idToValue.put(0x02, "Front right"); - idToValue.put(0x03, "Front left"); - idToValue.put(0x04, "Back right"); - idToValue.put(0x05, "Back left"); - idToValue.put(0x06, "Front centre"); - idToValue.put(0x07, "Back centre"); - idToValue.put(0x08, "Subwoofer"); - - createMaps(); - } - - public static ChannelTypes getInstanceOf() { - if (channelTypes == null) { - channelTypes = new ChannelTypes(); - } - return channelTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java deleted file mode 100644 index 66fcc8b..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: EventTimingTimestampTypes.java 867 2010-01-28 16:27:11Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class EventTimingTimestampTypes extends AbstractIntStringValuePair { - - public static final int TIMESTAMP_KEY_FIELD_SIZE = 1; - private static EventTimingTimestampTypes eventTimingTimestampTypes; - - private EventTimingTimestampTypes() { - idToValue.put(1, "Absolute time using MPEG [MPEG] frames as unit"); - idToValue.put(2, "Absolute time using milliseconds as unit"); - - createMaps(); - } - - public static EventTimingTimestampTypes getInstanceOf() { - if (eventTimingTimestampTypes == null) { - eventTimingTimestampTypes = new EventTimingTimestampTypes(); - } - return eventTimingTimestampTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java deleted file mode 100644 index 728e171..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: EventTimingTypes.java 339 2007-08-06 16:04:38Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License ainteger with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class EventTimingTypes extends AbstractIntStringValuePair { - private static EventTimingTypes eventTimingTypes; - - private EventTimingTypes() { - idToValue.put(0x00, "Padding (has no meaning)"); - idToValue.put(0x01, "End of initial silence"); - idToValue.put(0x02, "Intro start"); - idToValue.put(0x03, "Main part start"); - idToValue.put(0x04, "Outro start"); - idToValue.put(0x05, "Outro end"); - idToValue.put(0x06, "Verse start"); - idToValue.put(0x07, "Refrain start"); - idToValue.put(0x08, "Interlude start"); - idToValue.put(0x09, "Theme start"); - idToValue.put(0x0A, "Variation start"); - idToValue.put(0x0B, "Key change"); - idToValue.put(0x0C, "Time change"); - idToValue.put(0x0D, "Momentary unwanted noise (Snap, Crackle & Pop)"); - idToValue.put(0x0E, "Sustained noise"); - idToValue.put(0x0F, "Sustained noise end"); - idToValue.put(0x10, "Intro end"); - idToValue.put(0x11, "Main part end"); - idToValue.put(0x12, "Verse end"); - idToValue.put(0x13, "Refrain end"); - idToValue.put(0x14, "Theme end"); - idToValue.put(0x15, "Profanity"); - idToValue.put(0x16, "Profanity end"); - idToValue.put(0xFD, "Audio end (start of silence)"); - idToValue.put(0xFE, "Audio file ends"); - - createMaps(); - } - - public static EventTimingTypes getInstanceOf() { - if (eventTimingTypes == null) { - eventTimingTypes = new EventTimingTypes(); - } - return eventTimingTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java deleted file mode 100644 index 83b8eb8..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.jaudiotagger.tag.id3.valuepair; - -/** - * ID3V2 Genre list - *

    - *

    These are additional genres added in the V2 Specification, they have a string key (RX,CV) rather than a - * numeric key

    - */ -public enum ID3V2ExtendedGenreTypes { - RX("Remix"), - CR("Cover"); - - private String description; - - ID3V2ExtendedGenreTypes(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ImageFormats.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/ImageFormats.java deleted file mode 100644 index 0b83912..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ImageFormats.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: ImageFormats.java 1085 2013-01-20 20:55:12Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * This class maps from v2.2 Image formats (PIC) to v2.3/v2.4 Mimetypes (APIC) and - * vice versa. - */ -package org.jaudiotagger.tag.id3.valuepair; - -import java.util.HashMap; -import java.util.Map; - -/** - * Represents common image formats support by ID3 and provides a mapping between the format field supported in ID3v22 and the - * mimetype field supported by ID3v23/ID3v24. - *

    - *

    - * Note only JPG and PNG are mentioned specifically in the ID3 v22 Spec but it only says 'Image Format is preferably - * PNG or JPG' , not mandatory. In the jaudiotagger library we also consider GIF as a portable format, and we recognise - * BMP,PDF and TIFF but do not consider these formats as portable. - */ -//TODO identifying PICT, bit more difficult because in certain formats has an empty 512byte header -public class ImageFormats { - public static final String V22_JPG_FORMAT = "JPG"; - public static final String V22_PNG_FORMAT = "PNG"; - public static final String V22_GIF_FORMAT = "GIF"; - public static final String V22_BMP_FORMAT = "BMP"; - public static final String V22_TIF_FORMAT = "TIF"; - public static final String V22_PDF_FORMAT = "PDF"; - public static final String V22_PIC_FORMAT = "PIC"; - - - public static final String MIME_TYPE_JPEG = "image/jpeg"; - public static final String MIME_TYPE_PNG = "image/png"; - public static final String MIME_TYPE_GIF = "image/gif"; - public static final String MIME_TYPE_BMP = "image/bmp"; - public static final String MIME_TYPE_TIFF = "image/tiff"; - public static final String MIME_TYPE_PDF = "image/pdf"; - public static final String MIME_TYPE_PICT = "image/x-pict"; - - /** - * Sometimes this is used for jpg instead :or have I made this up - */ - public static final String MIME_TYPE_JPG = "image/jpg"; - - private static Map imageFormatsToMimeType = new HashMap(); - private static Map imageMimeTypeToFormat = new HashMap(); - - static { - imageFormatsToMimeType.put(V22_JPG_FORMAT, MIME_TYPE_JPEG); - imageFormatsToMimeType.put(V22_PNG_FORMAT, MIME_TYPE_PNG); - imageFormatsToMimeType.put(V22_GIF_FORMAT, MIME_TYPE_GIF); - imageFormatsToMimeType.put(V22_BMP_FORMAT, MIME_TYPE_BMP); - imageFormatsToMimeType.put(V22_TIF_FORMAT, MIME_TYPE_TIFF); - imageFormatsToMimeType.put(V22_PDF_FORMAT, MIME_TYPE_PDF); - imageFormatsToMimeType.put(V22_PIC_FORMAT, MIME_TYPE_PICT); - - String value; - for (String key : imageFormatsToMimeType.keySet()) { - value = imageFormatsToMimeType.get(key); - imageMimeTypeToFormat.put(value, key); - } - - //The mapping isn't one-one lets add other mimetypes - imageMimeTypeToFormat.put(MIME_TYPE_JPG, V22_JPG_FORMAT); - } - - /** - * Get v2.3 mimetype from v2.2 format - * - * @param format - * @return - */ - public static String getMimeTypeForFormat(String format) { - return imageFormatsToMimeType.get(format); - } - - /** - * Get v2.2 format from v2.3 mimetype - * - * @param mimeType - * @return - */ - public static String getFormatForMimeType(String mimeType) { - return imageMimeTypeToFormat.get(mimeType); - } - - /** - * Is this binary data a png image - * - * @param data - * @return true if binary data matches expected header for a png - */ - public static boolean binaryDataIsPngFormat(byte[] data) { - //Read signature - if (data.length < 4) { - return false; - } - return (0x89 == (data[0] & 0xff)) && (0x50 == (data[1] & 0xff)) && (0x4E == (data[2] & 0xff)) && (0x47 == (data[3] & 0xff)); - } - - /** - * Is this binary data a jpg image - * - * @param data - * @return true if binary data matches expected header for a jpg - *

    - * Some details http://www.obrador.com/essentialjpeg/headerinfo.htm - */ - public static boolean binaryDataIsJpgFormat(byte[] data) { - if (data.length < 4) { - return false; - } - //Read signature - //Can be FF D8 FF E0 or FF D8 FF E1 - //FF D8 is SOI Marker, FFE0 or FFE1 is JFIF Marker - return (0xff == (data[0] & 0xff)) && (0xd8 == (data[1] & 0xff)) && (0xff == (data[2] & 0xff)) && (0xe0 <= (data[3] & 0xff)); - } - - /** - * Is this binary data a gif image - * - * @param data - * @return true if binary data matches expected header for a gif - */ - public static boolean binaryDataIsGifFormat(byte[] data) { - if (data.length < 3) { - return false; - } - //Read signature - return (0x47 == (data[0] & 0xff)) && (0x49 == (data[1] & 0xff)) && (0x46 == (data[2] & 0xff)); - } - - /** - * Is this binary data a bmp image - * - * @param data - * @return true if binary data matches expected header for a bmp - */ - public static boolean binaryDataIsBmpFormat(byte[] data) { - if (data.length < 2) { - return false; - } - //Read signature - return (0x42 == (data[0] & 0xff)) && (0x4d == (data[1] & 0xff)); - } - - /** - * Is this binary data a pdf image - *

    - * Details at http://en.wikipedia.org/wiki/Magic_number_%28programming%29 - * - * @param data - * @return true if binary data matches expected header for a pdf - */ - public static boolean binaryDataIsPdfFormat(byte[] data) { - if (data.length < 4) { - return false; - } - //Read signature - return (0x25 == (data[0] & 0xff)) && (0x50 == (data[1] & 0xff)) && (0x44 == (data[2] & 0xff)) && (0x46 == (data[3] & 0xff)); - } - - /** - * is this binary data a tiff image - *

    - * Details at http://en.wikipedia.org/wiki/Magic_number_%28programming%29 - * - * @param data - * @return true if binary data matches expected header for a tiff - */ - public static boolean binaryDataIsTiffFormat(byte[] data) { - if (data.length < 4) { - return false; - } - //Read signature Intel - return ( - ((0x49 == (data[0] & 0xff)) && (0x49 == (data[1] & 0xff)) && (0x2a == (data[2] & 0xff)) && (0x00 == (data[3] & 0xff))) - || - ((0x4d == (data[0] & 0xff)) && (0x4d == (data[1] & 0xff)) && (0x00 == (data[2] & 0xff)) && (0x2a == (data[3] & 0xff))) - ); - } - - /** - * @param data - * @return true if the image format is a portable format recognised across operating systems - */ - public static boolean isPortableFormat(byte[] data) { - return binaryDataIsPngFormat(data) || binaryDataIsJpgFormat(data) || binaryDataIsGifFormat(data); - } - - /** - * @param data - * @return correct mimetype for the image data represented by this byte data - */ - public static String getMimeTypeForBinarySignature(byte[] data) { - if (binaryDataIsPngFormat(data)) { - return MIME_TYPE_PNG; - } else if (binaryDataIsJpgFormat(data)) { - return MIME_TYPE_JPEG; - } else if (binaryDataIsGifFormat(data)) { - return MIME_TYPE_GIF; - } else if (binaryDataIsBmpFormat(data)) { - return MIME_TYPE_BMP; - } else if (binaryDataIsPdfFormat(data)) { - return MIME_TYPE_PDF; - } else if (binaryDataIsTiffFormat(data)) { - return MIME_TYPE_TIFF; - } else { - return null; - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java deleted file mode 100644 index ceb84f9..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: InterpolationTypes.java 339 2007-08-06 16:04:38Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class InterpolationTypes extends AbstractIntStringValuePair { - private static InterpolationTypes interpolationTypes; - - private InterpolationTypes() { - idToValue.put(0, "Band"); - idToValue.put(1, "Linear"); - createMaps(); - } - - public static InterpolationTypes getInstanceOf() { - if (interpolationTypes == null) { - interpolationTypes = new InterpolationTypes(); - } - return interpolationTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java deleted file mode 100644 index 2795e87..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: ReceivedAsTypes.java 867 2010-01-28 16:27:11Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License ainteger with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Used by Commercial Frame (COMR) - */ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -/** - * Defines how song was purchased used by the COMR frame - */ -public class ReceivedAsTypes extends AbstractIntStringValuePair { - //The number of bytes used to hold the text encoding field size - public static final int RECEIVED_AS_FIELD_SIZE = 1; - - private static ReceivedAsTypes receivedAsTypes; - - private ReceivedAsTypes() { - idToValue.put(0x00, "Other"); - idToValue.put(0x01, "Standard CD album with other songs"); - idToValue.put(0x02, "Compressed audio on CD"); - idToValue.put(0x03, "File over the Internet"); - idToValue.put(0x04, "Stream over the Internet"); - idToValue.put(0x05, "As note sheets"); - idToValue.put(0x06, "As note sheets in a book with other sheets"); - idToValue.put(0x07, "Music on other media"); - idToValue.put(0x08, "Non-musical merchandise"); - createMaps(); - } - - public static ReceivedAsTypes getInstanceOf() { - if (receivedAsTypes == null) { - receivedAsTypes = new ReceivedAsTypes(); - } - return receivedAsTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java deleted file mode 100644 index 51a4941..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -/** - * Content Type used by Sysnchronised Lyrics Frame (SYLT) - */ -public class SynchronisedLyricsContentType extends AbstractIntStringValuePair { - public static final int CONTENT_KEY_FIELD_SIZE = 1; - private static SynchronisedLyricsContentType eventTimingTypes; - - private SynchronisedLyricsContentType() { - idToValue.put(0x00, "other"); - idToValue.put(0x01, "lyrics"); - idToValue.put(0x02, "text transcription"); - idToValue.put(0x03, "movement/part name"); - idToValue.put(0x04, "events"); - idToValue.put(0x05, "chord"); - idToValue.put(0x06, "trivia"); - idToValue.put(0x07, "URLs to webpages"); - idToValue.put(0x08, "URLs to images"); - createMaps(); - } - - public static SynchronisedLyricsContentType getInstanceOf() { - if (SynchronisedLyricsContentType.eventTimingTypes == null) { - SynchronisedLyricsContentType.eventTimingTypes = new SynchronisedLyricsContentType(); - } - return SynchronisedLyricsContentType.eventTimingTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/TextEncoding.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/TextEncoding.java deleted file mode 100644 index 24f781f..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/TextEncoding.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: TextEncoding.java 960 2011-04-27 10:46:19Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Valid Text Encodings - */ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - - -/** - * Text Encoding supported by ID3v24, the id is recognised by ID3 - * whereas the value maps to a java java.nio.charset.Charset, all the - * charsets defined below are guaranteed on every Java platform. - *

    - * Note in ID3 UTF_16 can be implemented as either UTF16BE or UTF16LE with byte ordering - * marks, in JAudioTagger we always implement it as UTF16LE because only this order - * is understood in Windows, OSX seem to understand both. - */ -public class TextEncoding extends AbstractIntStringValuePair { - - //Supported Java charsets - public static final String CHARSET_ISO_8859_1 = "ISO-8859-1"; - public static final String CHARSET_UTF_16 = "UTF-16"; //Want to use x-UTF-16LE-BOM but not always available - public static final String CHARSET_UTF_16BE = "UTF-16BE"; - public static final String CHARSET_UTF_8 = "UTF-8"; - - //Need both depending on whether want to use BigEndian or Little Endian - public static final String CHARSET_UTF_16_LE_ENCODING_FORMAT = "UTF-16LE"; - public static final String CHARSET_UTF_16_BE_ENCODING_FORMAT = "UTF-16BE"; - - //Supported ID3 charset ids - public static final byte ISO_8859_1 = 0; - public static final byte UTF_16 = 1; //We use UTF-16 with LE byte-ordering and byte order mark buy default - //but can also use BOM with BE byte ordering - public static final byte UTF_16BE = 2; - public static final byte UTF_8 = 3; - - //The number of bytes used to hold the text encoding field size - public static final int TEXT_ENCODING_FIELD_SIZE = 1; - - private static TextEncoding textEncodings; - - private TextEncoding() { - idToValue.put((int) ISO_8859_1, CHARSET_ISO_8859_1); - idToValue.put((int) UTF_16, CHARSET_UTF_16); - idToValue.put((int) UTF_16BE, CHARSET_UTF_16BE); - idToValue.put((int) UTF_8, CHARSET_UTF_8); - - createMaps(); - - } - - public static TextEncoding getInstanceOf() { - if (textEncodings == null) { - textEncodings = new TextEncoding(); - } - return textEncodings; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java b/src/main/java/org/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java deleted file mode 100644 index 736d64c..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.jaudiotagger.tag.id3.valuepair; - -import org.jaudiotagger.tag.reference.GenreTypes; - -import java.util.Collections; -import java.util.List; - -/** - * ID3V2 Genre list - *

    - *

    Merging of Id3v2 genres and the extended ID3v2 genres

    - */ -public class V2GenreTypes { - private static V2GenreTypes v2GenresTypes; - - private V2GenreTypes() { - - } - - public static V2GenreTypes getInstanceOf() { - if (v2GenresTypes == null) { - v2GenresTypes = new V2GenreTypes(); - } - return v2GenresTypes; - } - - /** - * @return list of all valid v2 genres in alphabetical order - */ - public List getAlphabeticalValueList() { - List genres = GenreTypes.getInstanceOf().getAlphabeticalValueList(); - genres.add(ID3V2ExtendedGenreTypes.CR.getDescription()); - genres.add(ID3V2ExtendedGenreTypes.RX.getDescription()); - - //Sort - Collections.sort(genres); - return genres; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/id3/valuepair/package.html b/src/main/java/org/jaudiotagger/tag/id3/valuepair/package.html deleted file mode 100644 index bfe9eff..0000000 --- a/src/main/java/org/jaudiotagger/tag/id3/valuepair/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -ID3 types implemented as ID-value pairs. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/images/AndroidArtwork.java b/src/main/java/org/jaudiotagger/tag/images/AndroidArtwork.java deleted file mode 100644 index 0cede44..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/AndroidArtwork.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.jaudiotagger.tag.images; - -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; -import org.jaudiotagger.tag.reference.PictureTypes; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Represents artwork in a format independent way - */ -public class AndroidArtwork implements Artwork { - private byte[] binaryData; - private String mimeType = ""; - private String description = ""; - private boolean isLinked = false; - private String imageUrl = ""; - private int pictureType = -1; - private int width; - private int height; - - public AndroidArtwork() { - - } - - /** - * Create Artwork from File - * - * @param file - * @return - * @throws java.io.IOException - */ - public static AndroidArtwork createArtworkFromFile(File file) throws IOException { - AndroidArtwork artwork = new AndroidArtwork(); - artwork.setFromFile(file); - return artwork; - } - - /** - * @param url - * @return - * @throws IOException - */ - public static AndroidArtwork createLinkedArtworkFromURL(String url) throws IOException { - AndroidArtwork artwork = new AndroidArtwork(); - artwork.setLinkedFromURL(url); - return artwork; - } - - /** - * Create artwork from Flac block - * - * @param coverArt - * @return - */ - public static AndroidArtwork createArtworkFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) { - AndroidArtwork artwork = new AndroidArtwork(); - artwork.setFromMetadataBlockDataPicture(coverArt); - return artwork; - } - - public byte[] getBinaryData() { - return binaryData; - } - - public void setBinaryData(byte[] binaryData) { - this.binaryData = binaryData; - } - - public String getMimeType() { - return mimeType; - } - - public void setMimeType(String mimeType) { - this.mimeType = mimeType; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - /** - * Should be called when you wish to prime the artwork for saving - * - * @return - */ - public boolean setImageFromData() { - throw new UnsupportedOperationException(); - } - - public Object getImage() throws IOException { - throw new UnsupportedOperationException(); - } - - public boolean isLinked() { - return isLinked; - } - - public void setLinked(boolean linked) { - isLinked = linked; - } - - public String getImageUrl() { - return imageUrl; - } - - public void setImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } - - public int getPictureType() { - return pictureType; - } - - public void setPictureType(int pictureType) { - this.pictureType = pictureType; - } - - /** - * Create Artwork from File - * - * @param file - * @throws java.io.IOException - */ - public void setFromFile(File file) throws IOException { - RandomAccessFile imageFile = new RandomAccessFile(file, "r"); - byte[] imagedata = new byte[(int) imageFile.length()]; - imageFile.read(imagedata); - imageFile.close(); - - setBinaryData(imagedata); - setMimeType(ImageFormats.getMimeTypeForBinarySignature(imagedata)); - setDescription(""); - setPictureType(PictureTypes.DEFAULT_ID); - } - - /** - * Create Linked Artwork from URL - * - * @param url - * @throws java.io.IOException - */ - public void setLinkedFromURL(String url) throws IOException { - setLinked(true); - setImageUrl(url); - } - - /** - * Populate Artwork from MetadataBlockDataPicture as used by Flac and VorbisComment - * - * @param coverArt - */ - public void setFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) { - setMimeType(coverArt.getMimeType()); - setDescription(coverArt.getDescription()); - setPictureType(coverArt.getPictureType()); - if (coverArt.isImageUrl()) { - setLinked(coverArt.isImageUrl()); - setImageUrl(coverArt.getImageUrl()); - } else { - setBinaryData(coverArt.getImageData()); - } - setWidth(coverArt.getWidth()); - setHeight(coverArt.getHeight()); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/AndroidImageHandler.java b/src/main/java/org/jaudiotagger/tag/images/AndroidImageHandler.java deleted file mode 100644 index f174aee..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/AndroidImageHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.jaudiotagger.tag.images; - -import java.awt.image.BufferedImage; -import java.io.IOException; - -/** - * Image Handling to to use when running on Android - *

    - * TODO need to provide Android compatible implementations - */ -public class AndroidImageHandler implements ImageHandler { - private static AndroidImageHandler instance; - - private AndroidImageHandler() { - - } - - public static AndroidImageHandler getInstanceOf() { - if (instance == null) { - instance = new AndroidImageHandler(); - } - return instance; - } - - /** - * Resize the image until the total size require to store the image is less than maxsize - * - * @param artwork - * @param maxSize - * @throws IOException - */ - public void reduceQuality(Artwork artwork, int maxSize) throws IOException { - throw new UnsupportedOperationException(); - } - - /** - * Resize image using Java 2D - * - * @param artwork - * @param size - * @throws java.io.IOException - */ - public void makeSmaller(Artwork artwork, int size) throws IOException { - throw new UnsupportedOperationException(); - } - - public boolean isMimeTypeWritable(String mimeType) { - throw new UnsupportedOperationException(); - } - - /** - * Write buffered image as required format - * - * @param bi - * @param mimeType - * @return - * @throws IOException - */ - public byte[] writeImage(BufferedImage bi, String mimeType) throws IOException { - throw new UnsupportedOperationException(); - } - - /** - * @param bi - * @return - * @throws IOException - */ - public byte[] writeImageAsPng(BufferedImage bi) throws IOException { - throw new UnsupportedOperationException(); - } - - /** - * Show read formats - *

    - * On Windows supports png/jpeg/bmp/gif - */ - public void showReadFormats() { - throw new UnsupportedOperationException(); - } - - /** - * Show write formats - *

    - * On Windows supports png/jpeg/bmp - */ - public void showWriteFormats() { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/Artwork.java b/src/main/java/org/jaudiotagger/tag/images/Artwork.java deleted file mode 100644 index ae2be0d..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/Artwork.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.jaudiotagger.tag.images; - -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; - -import java.io.File; -import java.io.IOException; - -/** - * Represents artwork in a format independent way - */ -public interface Artwork { - byte[] getBinaryData(); - - - void setBinaryData(byte[] binaryData); - - String getMimeType(); - - void setMimeType(String mimeType); - - String getDescription(); - - void setDescription(String description); - - int getHeight(); - - void setHeight(int height); - - int getWidth(); - - void setWidth(int width); - - /** - * Should be called when you wish to prime the artwork for saving - * - * @return - */ - boolean setImageFromData(); - - Object getImage() throws IOException; - - boolean isLinked(); - - void setLinked(boolean linked); - - String getImageUrl(); - - void setImageUrl(String imageUrl); - - int getPictureType(); - - void setPictureType(int pictureType); - - /** - * Create Artwork from File - * - * @param file - * @throws IOException - */ - void setFromFile(File file) throws IOException; - - /** - * Populate Artwork from MetadataBlockDataPicture as used by Flac and VorbisComment - * - * @param coverArt - */ - void setFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt); -} diff --git a/src/main/java/org/jaudiotagger/tag/images/ArtworkFactory.java b/src/main/java/org/jaudiotagger/tag/images/ArtworkFactory.java deleted file mode 100644 index 2a54049..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/ArtworkFactory.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.jaudiotagger.tag.images; - -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.tag.TagOptionSingleton; - -import java.io.File; -import java.io.IOException; - -/** - * Get appropriate Artwork class - */ -public class ArtworkFactory { - - - public static Artwork getNew() { - //Normal - if (!TagOptionSingleton.getInstance().isAndroid()) { - return new StandardArtwork(); - } - //Android - else { - return new AndroidArtwork(); - } - } - - /** - * Create Artwork instance from A Flac Metadata Block - * - * @param coverArt - * @return - */ - public static Artwork createArtworkFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) { - //Normal - if (!TagOptionSingleton.getInstance().isAndroid()) { - return StandardArtwork.createArtworkFromMetadataBlockDataPicture(coverArt); - } - //Android - else { - return AndroidArtwork.createArtworkFromMetadataBlockDataPicture(coverArt); - } - } - - /** - * Create Artwork instance from an image file - * - * @param file - * @return - * @throws IOException - */ - public static Artwork createArtworkFromFile(File file) throws IOException { - //Normal - if (!TagOptionSingleton.getInstance().isAndroid()) { - return StandardArtwork.createArtworkFromFile(file); - } - //Android - else { - return AndroidArtwork.createArtworkFromFile(file); - } - } - - /** - * Create Artwork instance from an image file - * - * @param link - * @return - * @throws IOException - */ - public static Artwork createLinkedArtworkFromURL(String link) throws IOException { - //Normal - if (!TagOptionSingleton.getInstance().isAndroid()) { - return StandardArtwork.createLinkedArtworkFromURL(link); - } - //Android - else { - return AndroidArtwork.createLinkedArtworkFromURL(link); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/ImageHandler.java b/src/main/java/org/jaudiotagger/tag/images/ImageHandler.java deleted file mode 100644 index f2d93ec..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/ImageHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.jaudiotagger.tag.images; - -import java.awt.image.BufferedImage; -import java.io.IOException; - -/** - * Image Handler - */ -public interface ImageHandler { - void reduceQuality(Artwork artwork, int maxSize) throws IOException; - - void makeSmaller(Artwork artwork, int size) throws IOException; - - boolean isMimeTypeWritable(String mimeType); - - byte[] writeImage(BufferedImage bi, String mimeType) throws IOException; - - byte[] writeImageAsPng(BufferedImage bi) throws IOException; - - void showReadFormats(); - - void showWriteFormats(); -} diff --git a/src/main/java/org/jaudiotagger/tag/images/ImageHandlingFactory.java b/src/main/java/org/jaudiotagger/tag/images/ImageHandlingFactory.java deleted file mode 100644 index 9aa6422..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/ImageHandlingFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.jaudiotagger.tag.images; - -import org.jaudiotagger.tag.TagOptionSingleton; - -/** - * Provides a class for all Image handling, this is required because the image classes - * provided by standard java are different to those provided by Android - */ -public class ImageHandlingFactory { - private static StandardImageHandler standardImageHandler; - private static AndroidImageHandler androidImageHandler; - - public static ImageHandler getInstance() { - //Normal - if (!TagOptionSingleton.getInstance().isAndroid()) { - if (standardImageHandler == null) { - standardImageHandler = StandardImageHandler.getInstanceOf(); - } - return standardImageHandler; - } - //Android - else { - if (androidImageHandler == null) { - androidImageHandler = AndroidImageHandler.getInstanceOf(); - } - return androidImageHandler; - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/Images.java b/src/main/java/org/jaudiotagger/tag/images/Images.java deleted file mode 100644 index c47e0e3..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/Images.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.jaudiotagger.tag.images; - -import java.awt.image.BufferedImage; -import java.io.IOException; - -/** - * BufferedImage methods - *

    - * Not compatible with Android, delete from your source tree. - */ -public class Images { - public static BufferedImage getImage(Artwork artwork) throws IOException { - return (BufferedImage) artwork.getImage(); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/StandardArtwork.java b/src/main/java/org/jaudiotagger/tag/images/StandardArtwork.java deleted file mode 100644 index 7e852f4..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/StandardArtwork.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.jaudiotagger.tag.images; - -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; -import org.jaudiotagger.tag.reference.PictureTypes; - -import javax.imageio.ImageIO; -import javax.imageio.stream.ImageInputStream; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Represents artwork in a format independent way - */ -public class StandardArtwork implements Artwork { - private byte[] binaryData; - private String mimeType = ""; - private String description = ""; - private boolean isLinked = false; - private String imageUrl = ""; - private int pictureType = -1; - private int width; - private int height; - - public StandardArtwork() { - - } - - /** - * Create Artwork from File - * - * @param file - * @return - * @throws java.io.IOException - */ - public static StandardArtwork createArtworkFromFile(File file) throws IOException { - StandardArtwork artwork = new StandardArtwork(); - artwork.setFromFile(file); - return artwork; - } - - public static StandardArtwork createLinkedArtworkFromURL(String url) throws IOException { - StandardArtwork artwork = new StandardArtwork(); - artwork.setLinkedFromURL(url); - return artwork; - } - - /** - * Create artwork from Flac block - * - * @param coverArt - * @return - */ - public static StandardArtwork createArtworkFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) { - StandardArtwork artwork = new StandardArtwork(); - artwork.setFromMetadataBlockDataPicture(coverArt); - return artwork; - } - - public byte[] getBinaryData() { - return binaryData; - } - - public void setBinaryData(byte[] binaryData) { - this.binaryData = binaryData; - } - - public String getMimeType() { - return mimeType; - } - - public void setMimeType(String mimeType) { - this.mimeType = mimeType; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - /** - * Should be called when you wish to prime the artwork for saving - * - * @return - */ - public boolean setImageFromData() { - try { - BufferedImage image = (BufferedImage) getImage(); - setWidth(image.getWidth()); - setHeight(image.getHeight()); - } catch (IOException ioe) { - return false; - } - return true; - } - - public Object getImage() throws IOException { - ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(getBinaryData())); - BufferedImage bi = ImageIO.read(iis); - return bi; - } - - public boolean isLinked() { - return isLinked; - } - - public void setLinked(boolean linked) { - isLinked = linked; - } - - public String getImageUrl() { - return imageUrl; - } - - public void setImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } - - public int getPictureType() { - return pictureType; - } - - public void setPictureType(int pictureType) { - this.pictureType = pictureType; - } - - /** - * Create Artwork from File - * - * @param file - * @throws java.io.IOException - */ - public void setFromFile(File file) throws IOException { - RandomAccessFile imageFile = new RandomAccessFile(file, "r"); - byte[] imagedata = new byte[(int) imageFile.length()]; - imageFile.read(imagedata); - imageFile.close(); - - setBinaryData(imagedata); - setMimeType(ImageFormats.getMimeTypeForBinarySignature(imagedata)); - setDescription(""); - setPictureType(PictureTypes.DEFAULT_ID); - } - - /** - * Create Linked Artwork from URL - * - * @param url - * @throws java.io.IOException - */ - public void setLinkedFromURL(String url) throws IOException { - setLinked(true); - setImageUrl(url); - } - - /** - * Populate Artwork from MetadataBlockDataPicture as used by Flac and VorbisComment - * - * @param coverArt - */ - public void setFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) { - setMimeType(coverArt.getMimeType()); - setDescription(coverArt.getDescription()); - setPictureType(coverArt.getPictureType()); - if (coverArt.isImageUrl()) { - setLinked(coverArt.isImageUrl()); - setImageUrl(coverArt.getImageUrl()); - } else { - setBinaryData(coverArt.getImageData()); - } - setWidth(coverArt.getWidth()); - setHeight(coverArt.getHeight()); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/StandardImageHandler.java b/src/main/java/org/jaudiotagger/tag/images/StandardImageHandler.java deleted file mode 100644 index cdd37b8..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/StandardImageHandler.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.jaudiotagger.tag.images; - -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; - -import javax.imageio.ImageIO; -import javax.imageio.ImageWriter; -import java.awt.*; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Iterator; - -/** - * Image Handling used when running on standard JVM - */ -public class StandardImageHandler implements ImageHandler { - private static StandardImageHandler instance; - - private StandardImageHandler() { - - } - - public static StandardImageHandler getInstanceOf() { - if (instance == null) { - instance = new StandardImageHandler(); - } - return instance; - } - - /** - * Resize the image until the total size require to store the image is less than maxsize - * - * @param artwork - * @param maxSize - * @throws IOException - */ - public void reduceQuality(Artwork artwork, int maxSize) throws IOException { - while (artwork.getBinaryData().length > maxSize) { - Image srcImage = (Image) artwork.getImage(); - int w = srcImage.getWidth(null); - int newSize = w / 2; - makeSmaller(artwork, newSize); - } - } - - /** - * Resize image using Java 2D - * - * @param artwork - * @param size - * @throws java.io.IOException - */ - public void makeSmaller(Artwork artwork, int size) throws IOException { - Image srcImage = (Image) artwork.getImage(); - - int w = srcImage.getWidth(null); - int h = srcImage.getHeight(null); - - // Determine the scaling required to get desired result. - float scaleW = (float) size / (float) w; - float scaleH = (float) size / (float) h; - - //Create an image buffer in which to paint on, create as an opaque Rgb type image, it doesnt matter what type - //the original image is we want to convert to the best type for displaying on screen regardless - BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); - - // Set the scale. - AffineTransform tx = new AffineTransform(); - tx.scale(scaleW, scaleH); - - // Paint image. - Graphics2D g2d = bi.createGraphics(); - g2d.drawImage(srcImage, tx, null); - g2d.dispose(); - - - if (artwork.getMimeType() != null && isMimeTypeWritable(artwork.getMimeType())) { - artwork.setBinaryData(writeImage(bi, artwork.getMimeType())); - } else { - artwork.setBinaryData(writeImageAsPng(bi)); - } - } - - public boolean isMimeTypeWritable(String mimeType) { - Iterator writers = ImageIO.getImageWritersByMIMEType(mimeType); - return writers.hasNext(); - } - - /** - * Write buffered image as required format - * - * @param bi - * @param mimeType - * @return - * @throws IOException - */ - public byte[] writeImage(BufferedImage bi, String mimeType) throws IOException { - Iterator writers = ImageIO.getImageWritersByMIMEType(mimeType); - if (writers.hasNext()) { - ImageWriter writer = writers.next(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - writer.setOutput(ImageIO.createImageOutputStream(baos)); - writer.write(bi); - return baos.toByteArray(); - } - throw new IOException("Cannot write to this mimetype"); - } - - /** - * @param bi - * @return - * @throws IOException - */ - public byte[] writeImageAsPng(BufferedImage bi) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(bi, ImageFormats.MIME_TYPE_PNG, baos); - return baos.toByteArray(); - } - - /** - * Show read formats - *

    - * On Windows supports png/jpeg/bmp/gif - */ - public void showReadFormats() { - String[] formats = ImageIO.getReaderMIMETypes(); - for (String f : formats) { - System.out.println("r" + f); - } - } - - /** - * Show write formats - *

    - * On Windows supports png/jpeg/bmp - */ - public void showWriteFormats() { - String[] formats = ImageIO.getWriterMIMETypes(); - for (String f : formats) { - System.out.println(f); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/images/package.html b/src/main/java/org/jaudiotagger/tag/images/package.html deleted file mode 100644 index dffb445..0000000 --- a/src/main/java/org/jaudiotagger/tag/images/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Processing of images in audio metadata. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/AbstractLyrics3.java b/src/main/java/org/jaudiotagger/tag/lyrics3/AbstractLyrics3.java deleted file mode 100644 index 8192b88..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/AbstractLyrics3.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractLyrics3.java 625 2008-07-21 10:49:58Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.id3.AbstractTag; -import org.jaudiotagger.tag.id3.ID3v1Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - - -public abstract class AbstractLyrics3 extends AbstractTag { - public AbstractLyrics3() { - } - - public AbstractLyrics3(AbstractLyrics3 copyObject) { - super(copyObject); - } - - /** - * @param file - * @throws IOException - */ - public void delete(RandomAccessFile file) throws IOException { - long filePointer; - ID3v1Tag id3v1tag = new ID3v1Tag(); - - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java b/src/main/java/org/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java deleted file mode 100644 index 0f68b14..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: AbstractLyrics3v2FieldFrameBody.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.datatype.AbstractDataType; -import org.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.Iterator; - -public abstract class AbstractLyrics3v2FieldFrameBody extends AbstractTagFrameBody { - public AbstractLyrics3v2FieldFrameBody() { - } - - public AbstractLyrics3v2FieldFrameBody(AbstractLyrics3v2FieldFrameBody copyObject) { - super(copyObject); - } - - /** - * This is called by superclass when attempt to read data from file. - * - * @param file - * @return - * @throws InvalidTagException - * @throws IOException - */ - protected int readHeader(RandomAccessFile file) throws InvalidTagException, IOException { - int size; - byte[] buffer = new byte[5]; - - // read the 5 character size - file.read(buffer, 0, 5); - size = Integer.parseInt(new String(buffer, 0, 5)); - - if ((size == 0) && (!TagOptionSingleton.getInstance().isLyrics3KeepEmptyFieldIfRead())) { - throw new InvalidTagException("Lyircs3v2 Field has size of zero."); - } - - return size; - } - - /** - * This is called by superclass when attempt to write data from file. - * - * @param file - * @param size - * @throws IOException - */ - protected void writeHeader(RandomAccessFile file, int size) throws IOException { - String str; - int offset = 0; - byte[] buffer = new byte[5]; - - /** - * @todo change this to use pad String - */ - str = Integer.toString(getSize()); - - for (int i = 0; i < (5 - str.length()); i++) { - buffer[i] = (byte) '0'; - } - - offset += (5 - str.length()); - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - file.write(buffer); - } - - /** - * This reads a frame body from its file into the appropriate FrameBody class - * Read the data from the given file into this datatype. The file needs to - * have its file pointer in the correct location. The size as indicated in the - * header is passed to the frame constructor when reading from file. - * - * @param byteBuffer file to read - * @throws IOException on any I/O error - * @throws InvalidTagException if there is any error in the data format. - */ - public void read(ByteBuffer byteBuffer) throws InvalidTagException { - int size = getSize(); - //Allocate a buffer to the size of the Frame Body and read from file - byte[] buffer = new byte[size]; - byteBuffer.get(buffer); - //Offset into buffer, incremented by length of previous MP3Object - int offset = 0; - - //Go through the ObjectList of the Frame reading the data into the - //correct datatype. - AbstractDataType object; - Iterator iterator = objectList.listIterator(); - while (iterator.hasNext()) { - //The read has extended further than the defined frame size - if (offset > (size - 1)) { - throw new InvalidTagException("Invalid size for Frame Body"); - } - - //Get next Object and load it with data from the Buffer - object = iterator.next(); - object.readByteArray(buffer, offset); - //Increment Offset to start of next datatype. - offset += object.getSize(); - } - } - - /** - * Write the contents of this datatype to the file at the position it is - * currently at. - * - * @param file destination file - * @throws IOException on any I/O error - */ - public void write(RandomAccessFile file) throws IOException { - //Write the various fields to file in order - byte[] buffer; - AbstractDataType object; - Iterator iterator = objectList.listIterator(); - while (iterator.hasNext()) { - object = iterator.next(); - buffer = object.writeByteArray(); - file.write(buffer); - } - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java deleted file mode 100644 index 5c73f5a..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyAUT.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; - -import java.nio.ByteBuffer; - -public class FieldFrameBodyAUT extends AbstractLyrics3v2FieldFrameBody { - /** - * Creates a new FieldBodyAUT datatype. - */ - public FieldFrameBodyAUT() { - // this.setObject("Author", ""); - } - - public FieldFrameBodyAUT(FieldFrameBodyAUT body) { - super(body); - } - - /** - * Creates a new FieldBodyAUT datatype. - * - * @param author - */ - public FieldFrameBodyAUT(String author) { - this.setObjectValue("Author", author); - } - - /** - * Creates a new FieldBodyAUT datatype. - * - * @param byteBuffer - * @throws InvalidTagException - */ - public FieldFrameBodyAUT(ByteBuffer byteBuffer) throws InvalidTagException { - this.read(byteBuffer); - } - - /** - * @return - */ - public String getAuthor() { - return (String) getObjectValue("Author"); - } - - /** - * @param author - */ - public void setAuthor(String author) { - setObjectValue("Author", author); - } - - /** - * @return - */ - public String getIdentifier() { - return "AUT"; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringSizeTerminated("Author", this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java deleted file mode 100644 index d4a28cb..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyEAL.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; - -import java.nio.ByteBuffer; - - -public class FieldFrameBodyEAL extends AbstractLyrics3v2FieldFrameBody { - /** - * Creates a new FieldBodyEAL datatype. - */ - public FieldFrameBodyEAL() { - // this.setObject("Album", ""); - } - - public FieldFrameBodyEAL(FieldFrameBodyEAL body) { - super(body); - } - - /** - * Creates a new FieldBodyEAL datatype. - * - * @param album - */ - public FieldFrameBodyEAL(String album) { - this.setObjectValue("Album", album); - } - - /** - * Creates a new FieldBodyEAL datatype. - * - * @param byteBuffer - * @throws InvalidTagException - */ - public FieldFrameBodyEAL(ByteBuffer byteBuffer) throws InvalidTagException { - read(byteBuffer); - - } - - /** - * @return - */ - public String getAlbum() { - return (String) getObjectValue("Album"); - } - - /** - * @param album - */ - public void setAlbum(String album) { - setObjectValue("Album", album); - } - - /** - * @return - */ - public String getIdentifier() { - return "EAL"; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringSizeTerminated("Album", this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java deleted file mode 100644 index 07c30f0..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyEAR.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; - -import java.nio.ByteBuffer; - - -public class FieldFrameBodyEAR extends AbstractLyrics3v2FieldFrameBody { - /** - * Creates a new FieldBodyEAR datatype. - */ - public FieldFrameBodyEAR() { - // this.setObject("Artist", ""); - } - - public FieldFrameBodyEAR(FieldFrameBodyEAR body) { - super(body); - } - - /** - * Creates a new FieldBodyEAR datatype. - * - * @param artist - */ - public FieldFrameBodyEAR(String artist) { - this.setObjectValue("Artist", artist); - } - - /** - * Creates a new FieldBodyEAR datatype. - * - * @param byteBuffer - * @throws InvalidTagException - */ - public FieldFrameBodyEAR(ByteBuffer byteBuffer) throws InvalidTagException { - - this.read(byteBuffer); - - } - - /** - * @return - */ - public String getArtist() { - return (String) getObjectValue("Artist"); - } - - /** - * @param artist - */ - public void setArtist(String artist) { - setObjectValue("Artist", artist); - } - - /** - * @return - */ - public String getIdentifier() { - return "EAR"; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringSizeTerminated("Artist", this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java deleted file mode 100644 index 4434da0..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyETT.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; - -import java.nio.ByteBuffer; - - -public class FieldFrameBodyETT extends AbstractLyrics3v2FieldFrameBody { - /** - * Creates a new FieldBodyETT datatype. - */ - public FieldFrameBodyETT() { - // this.setObject("Title", ""); - } - - public FieldFrameBodyETT(FieldFrameBodyETT body) { - super(body); - } - - /** - * Creates a new FieldBodyETT datatype. - * - * @param title - */ - public FieldFrameBodyETT(String title) { - this.setObjectValue("Title", title); - } - - /** - * Creates a new FieldBodyETT datatype. - * - * @param byteBuffer - * @throws InvalidTagException - */ - public FieldFrameBodyETT(ByteBuffer byteBuffer) throws InvalidTagException { - this.read(byteBuffer); - } - - /** - * @return - */ - public String getIdentifier() { - return "ETT"; - } - - /** - * @return - */ - public String getTitle() { - return (String) getObjectValue("Title"); - } - - /** - * @param title - */ - public void setTitle(String title) { - setObjectValue("Title", title); - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringSizeTerminated("Title", this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java deleted file mode 100644 index a8e9a72..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java +++ /dev/null @@ -1,300 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyIMG.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ - -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.datatype.Lyrics3Image; - -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Iterator; - -public class FieldFrameBodyIMG extends AbstractLyrics3v2FieldFrameBody { - /** - * - */ - private ArrayList images = new ArrayList(); - - /** - * Creates a new FieldBodyIMG datatype. - */ - public FieldFrameBodyIMG() { - } - - public FieldFrameBodyIMG(FieldFrameBodyIMG copyObject) { - super(copyObject); - - Lyrics3Image old; - - for (int i = 0; i < copyObject.images.size(); i++) { - old = copyObject.images.get(i); - this.images.add(new Lyrics3Image(old)); - } - } - - /** - * Creates a new FieldBodyIMG datatype. - * - * @param imageString - */ - public FieldFrameBodyIMG(String imageString) { - readString(imageString); - } - - /** - * Creates a new FieldBodyIMG datatype. - * - * @param image - */ - public FieldFrameBodyIMG(Lyrics3Image image) { - images.add(image); - } - - /** - * Creates a new FieldBodyIMG datatype. - * - * @param byteBuffer - * @throws InvalidTagException - */ - public FieldFrameBodyIMG(ByteBuffer byteBuffer) throws InvalidTagException { - this.read(byteBuffer); - } - - /** - * @return - */ - public String getIdentifier() { - return "IMG"; - } - - /** - * @return - */ - public int getSize() { - int size = 0; - Lyrics3Image image; - - for (Object image1 : images) { - image = (Lyrics3Image) image1; - size += (image.getSize() + 2); // addField CRLF pair - } - - return size - 2; // cut off trailing crlf pair - } - - /** - * @param obj - * @return - */ - public boolean isSubsetOf(Object obj) { - if (!(obj instanceof FieldFrameBodyIMG)) { - return false; - } - - ArrayList superset = ((FieldFrameBodyIMG) obj).images; - - for (Object image : images) { - if (!superset.contains(image)) { - return false; - } - } - - return super.isSubsetOf(obj); - } - - /** - * @return - */ - public String getValue() { - return writeString(); - } - - /** - * @param value - */ - public void setValue(String value) { - readString(value); - } - - /** - * @param image - */ - public void addImage(Lyrics3Image image) { - images.add(image); - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof FieldFrameBodyIMG)) { - return false; - } - - FieldFrameBodyIMG object = (FieldFrameBodyIMG) obj; - - return this.images.equals(object.images) && super.equals(obj); - - } - - /** - * @return - */ - public Iterator iterator() { - return images.iterator(); - } - - - public void read(ByteBuffer byteBuffer) throws InvalidTagException { - String imageString; - - byte[] buffer = new byte[5]; - - // read the 5 character size - byteBuffer.get(buffer, 0, 5); - - int size = Integer.parseInt(new String(buffer, 0, 5)); - - if ((size == 0) && (!TagOptionSingleton.getInstance().isLyrics3KeepEmptyFieldIfRead())) { - throw new InvalidTagException("Lyircs3v2 Field has size of zero."); - } - - buffer = new byte[size]; - - // read the SIZE length description - byteBuffer.get(buffer); - imageString = new String(buffer); - readString(imageString); - } - - /** - * @return - */ - public String toString() { - String str = getIdentifier() + " : "; - - for (Object image : images) { - str += (image.toString() + " ; "); - } - - return str; - } - - /** - * @param file - * @throws java.io.IOException - */ - public void write(RandomAccessFile file) throws java.io.IOException { - int size; - int offset = 0; - byte[] buffer = new byte[5]; - String str; - - size = getSize(); - str = Integer.toString(size); - - for (int i = 0; i < (5 - str.length()); i++) { - buffer[i] = (byte) '0'; - } - - offset += (5 - str.length()); - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - offset += str.length(); - - file.write(buffer, 0, 5); - - if (size > 0) { - str = writeString(); - buffer = new byte[str.length()]; - - for (int i = 0; i < str.length(); i++) { - buffer[i] = (byte) str.charAt(i); - } - - file.write(buffer); - } - } - - /** - * @param imageString - */ - private void readString(String imageString) { - // now read each picture and put in the vector; - Lyrics3Image image; - String token; - int offset = 0; - int delim = imageString.indexOf(Lyrics3v2Fields.CRLF); - images = new ArrayList(); - - while (delim >= 0) { - token = imageString.substring(offset, delim); - image = new Lyrics3Image("Image", this); - image.setFilename(token); - images.add(image); - offset = delim + Lyrics3v2Fields.CRLF.length(); - delim = imageString.indexOf(Lyrics3v2Fields.CRLF, offset); - } - - if (offset < imageString.length()) { - token = imageString.substring(offset); - image = new Lyrics3Image("Image", this); - image.setFilename(token); - images.add(image); - } - } - - /** - * @return - */ - private String writeString() { - String str = ""; - Lyrics3Image image; - - for (Object image1 : images) { - image = (Lyrics3Image) image1; - str += (image.writeString() + Lyrics3v2Fields.CRLF); - } - - if (str.length() > 2) { - return str.substring(0, str.length() - 2); - } - - return str; - } - - - /** - * TODO - */ - protected void setupObjectList() { - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java deleted file mode 100644 index 3ebf667..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyIND.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.BooleanString; - -import java.nio.ByteBuffer; - - -public class FieldFrameBodyIND extends AbstractLyrics3v2FieldFrameBody { - /** - * Creates a new FieldBodyIND datatype. - */ - public FieldFrameBodyIND() { - // this.setObject("Lyrics Present", new Boolean(false)); - // this.setObject("Timestamp Present", new Boolean(false)); - } - - public FieldFrameBodyIND(FieldFrameBodyIND body) { - super(body); - } - - /** - * Creates a new FieldBodyIND datatype. - * - * @param lyricsPresent - * @param timeStampPresent - */ - public FieldFrameBodyIND(boolean lyricsPresent, boolean timeStampPresent) { - this.setObjectValue("Lyrics Present", lyricsPresent); - this.setObjectValue("Timestamp Present", timeStampPresent); - } - - /** - * Creates a new FieldBodyIND datatype. - * - * @param byteBuffer - * @throws InvalidTagException - */ - public FieldFrameBodyIND(ByteBuffer byteBuffer) throws InvalidTagException { - this.read(byteBuffer); - } - - /** - * @return - */ - public String getAuthor() { - return (String) getObjectValue("Author"); - } - - /** - * @param author - */ - public void setAuthor(String author) { - setObjectValue("Author", author); - } - - /** - * @return - */ - public String getIdentifier() { - return "IND"; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new BooleanString("Lyrics Present", this)); - objectList.add(new BooleanString("Timestamp Present", this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java deleted file mode 100644 index 848120a..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyINF.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.datatype.StringSizeTerminated; - -import java.nio.ByteBuffer; - -public class FieldFrameBodyINF extends AbstractLyrics3v2FieldFrameBody { - /** - * Creates a new FieldBodyINF datatype. - */ - public FieldFrameBodyINF() { - // this.setObject("Additional Information", ""); - } - - public FieldFrameBodyINF(FieldFrameBodyINF body) { - super(body); - } - - /** - * Creates a new FieldBodyINF datatype. - * - * @param additionalInformation - */ - public FieldFrameBodyINF(String additionalInformation) { - this.setObjectValue("Additional Information", additionalInformation); - } - - /** - * Creates a new FieldBodyINF datatype. - * - * @param byteBuffer - * @throws org.jaudiotagger.tag.InvalidTagException - */ - public FieldFrameBodyINF(ByteBuffer byteBuffer) throws InvalidTagException { - this.read(byteBuffer); - - } - - /** - * @return - */ - public String getAdditionalInformation() { - return (String) getObjectValue("Additional Information"); - } - - /** - * @param additionalInformation - */ - public void setAdditionalInformation(String additionalInformation) { - setObjectValue("Additional Information", additionalInformation); - } - - /** - * @return - */ - public String getIdentifier() { - return "INF"; - } - - /** - * - */ - protected void setupObjectList() { - objectList.add(new StringSizeTerminated("Additional Information", this)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java deleted file mode 100644 index 97e23af..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java +++ /dev/null @@ -1,369 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyLYR.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.datatype.ID3v2LyricLine; -import org.jaudiotagger.tag.datatype.Lyrics3Line; -import org.jaudiotagger.tag.datatype.Lyrics3TimeStamp; -import org.jaudiotagger.tag.id3.framebody.FrameBodySYLT; -import org.jaudiotagger.tag.id3.framebody.FrameBodyUSLT; - -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; - - -public class FieldFrameBodyLYR extends AbstractLyrics3v2FieldFrameBody { - /** - * - */ - private ArrayList lines = new ArrayList(); - - /** - * Creates a new FieldBodyLYR datatype. - */ - public FieldFrameBodyLYR() { - } - - public FieldFrameBodyLYR(FieldFrameBodyLYR copyObject) { - super(copyObject); - - Lyrics3Line old; - - for (int i = 0; i < copyObject.lines.size(); i++) { - old = copyObject.lines.get(i); - this.lines.add(new Lyrics3Line(old)); - } - } - - /** - * Creates a new FieldBodyLYR datatype. - * - * @param line - */ - public FieldFrameBodyLYR(String line) { - readString(line); - } - - /** - * Creates a new FieldBodyLYR datatype. - * - * @param sync - */ - public FieldFrameBodyLYR(FrameBodySYLT sync) { - addLyric(sync); - } - - /** - * Creates a new FieldBodyLYR datatype. - * - * @param unsync - */ - public FieldFrameBodyLYR(FrameBodyUSLT unsync) { - addLyric(unsync); - } - - /** - * Creates a new FieldBodyLYR datatype. - * - * @param byteBuffer - * @throws org.jaudiotagger.tag.InvalidTagException - */ - public FieldFrameBodyLYR(ByteBuffer byteBuffer) throws InvalidTagException { - - this.read(byteBuffer); - - } - - /** - * @return - */ - public String getIdentifier() { - return "LYR"; - } - - /** - * @return - */ - public String getLyric() { - return writeString(); - } - - /** - * @param str - */ - public void setLyric(String str) { - readString(str); - } - - /** - * @return - */ - public int getSize() { - int size = 0; - Lyrics3Line line; - - for (Object line1 : lines) { - line = (Lyrics3Line) line1; - size += (line.getSize() + 2); - } - - return size; - - //return size - 2; // cut off the last crlf pair - } - - /** - * @param obj - * @return - */ - public boolean isSubsetOf(Object obj) { - if (!(obj instanceof FieldFrameBodyLYR)) { - return false; - } - - ArrayList superset = ((FieldFrameBodyLYR) obj).lines; - - for (Object line : lines) { - if (!superset.contains(line)) { - return false; - } - } - - return super.isSubsetOf(obj); - } - - /** - * @param sync - */ - public void addLyric(FrameBodySYLT sync) { - // SYLT frames are made of individual lines - Iterator iterator = sync.iterator(); - Lyrics3Line newLine; - ID3v2LyricLine currentLine; - Lyrics3TimeStamp timeStamp; - HashMap lineMap = new HashMap(); - - while (iterator.hasNext()) { - currentLine = iterator.next(); - - // createField copy to use in new tag - currentLine = new ID3v2LyricLine(currentLine); - timeStamp = new Lyrics3TimeStamp("Time Stamp", this); - timeStamp.setTimeStamp(currentLine.getTimeStamp(), (byte) sync.getTimeStampFormat()); - - if (lineMap.containsKey(currentLine.getText())) { - newLine = lineMap.get(currentLine.getText()); - newLine.addTimeStamp(timeStamp); - } else { - newLine = new Lyrics3Line("Lyric Line", this); - newLine.setLyric(currentLine); - newLine.setTimeStamp(timeStamp); - lineMap.put(currentLine.getText(), newLine); - lines.add(newLine); - } - } - } - - /** - * @param unsync - */ - public void addLyric(FrameBodyUSLT unsync) { - // USLT frames are just long text string; - Lyrics3Line line = new Lyrics3Line("Lyric Line", this); - line.setLyric(unsync.getLyric()); - lines.add(line); - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof FieldFrameBodyLYR)) { - return false; - } - - FieldFrameBodyLYR object = (FieldFrameBodyLYR) obj; - - return this.lines.equals(object.lines) && super.equals(obj); - - } - - /** - * @return - */ - public boolean hasTimeStamp() { - boolean present = false; - - for (Object line : lines) { - if (((Lyrics3Line) line).hasTimeStamp()) { - present = true; - } - } - - return present; - } - - /** - * @return - */ - public Iterator iterator() { - return lines.iterator(); - } - - /** - * - * - * - */ - public void read(ByteBuffer byteBuffer) throws InvalidTagException { - String lineString; - - byte[] buffer = new byte[5]; - - // read the 5 character size - byteBuffer.get(buffer, 0, 5); - - int size = Integer.parseInt(new String(buffer, 0, 5)); - - if ((size == 0) && (!TagOptionSingleton.getInstance().isLyrics3KeepEmptyFieldIfRead())) { - throw new InvalidTagException("Lyircs3v2 Field has size of zero."); - } - - buffer = new byte[size]; - - // read the SIZE length description - byteBuffer.get(buffer); - lineString = new String(buffer); - readString(lineString); - } - - /** - * @return - */ - public String toString() { - String str = getIdentifier() + " : "; - - for (Object line : lines) { - str += line.toString(); - } - - return str; - } - - /** - * @param file - * @throws java.io.IOException - */ - public void write(RandomAccessFile file) throws java.io.IOException { - int size; - int offset = 0; - byte[] buffer = new byte[5]; - String str; - - size = getSize(); - str = Integer.toString(size); - - for (int i = 0; i < (5 - str.length()); i++) { - buffer[i] = (byte) '0'; - } - - offset += (5 - str.length()); - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - offset += str.length(); - file.write(buffer, 0, 5); - - if (size > 0) { - str = writeString(); - buffer = new byte[str.length()]; - - for (int i = 0; i < str.length(); i++) { - buffer[i] = (byte) str.charAt(i); - } - - file.write(buffer); - } - } - - /** - * @param lineString - */ - private void readString(String lineString) { - // now readString each line and put in the vector; - String token; - int offset = 0; - int delim = lineString.indexOf(Lyrics3v2Fields.CRLF); - lines = new ArrayList(); - - Lyrics3Line line; - - while (delim >= 0) { - token = lineString.substring(offset, delim); - line = new Lyrics3Line("Lyric Line", this); - line.setLyric(token); - lines.add(line); - offset = delim + Lyrics3v2Fields.CRLF.length(); - delim = lineString.indexOf(Lyrics3v2Fields.CRLF, offset); - } - - if (offset < lineString.length()) { - token = lineString.substring(offset); - line = new Lyrics3Line("Lyric Line", this); - line.setLyric(token); - lines.add(line); - } - } - - /** - * @return - */ - private String writeString() { - Lyrics3Line line; - String str = ""; - - for (Object line1 : lines) { - line = (Lyrics3Line) line1; - str += (line.writeString() + Lyrics3v2Fields.CRLF); - } - - return str; - - //return str.substring(0,str.length()-2); // cut off the last CRLF pair - } - - /** - * TODO - */ - protected void setupObjectList() { - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java b/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java deleted file mode 100644 index 4459f1d..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: FieldFrameBodyUnsupported.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - - -public class FieldFrameBodyUnsupported extends AbstractLyrics3v2FieldFrameBody { - /** - * - */ - private byte[] value = null; - - /** - * Creates a new FieldBodyUnsupported datatype. - */ - public FieldFrameBodyUnsupported() { - // this.value = new byte[0]; - } - - public FieldFrameBodyUnsupported(FieldFrameBodyUnsupported copyObject) { - super(copyObject); - this.value = copyObject.value.clone(); - } - - /** - * Creates a new FieldBodyUnsupported datatype. - * - * @param value - */ - public FieldFrameBodyUnsupported(byte[] value) { - this.value = value; - } - - /** - * Creates a new FieldBodyUnsupported datatype. - * - * @param byteBuffer - * @throws org.jaudiotagger.tag.InvalidTagException - */ - public FieldFrameBodyUnsupported(ByteBuffer byteBuffer) throws InvalidTagException { - - this.read(byteBuffer); - - } - - /** - * @return - */ - public String getIdentifier() { - return "ZZZ"; - } - - /** - * @param obj - * @return - */ - public boolean isSubsetOf(Object obj) { - if (!(obj instanceof FieldFrameBodyUnsupported)) { - return false; - } - - FieldFrameBodyUnsupported object = (FieldFrameBodyUnsupported) obj; - - String subset = new String(this.value); - String superset = new String(object.value); - - return superset.contains(subset) && super.isSubsetOf(obj); - - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof FieldFrameBodyUnsupported)) { - return false; - } - - FieldFrameBodyUnsupported object = (FieldFrameBodyUnsupported) obj; - - return java.util.Arrays.equals(this.value, object.value) && super.equals(obj); - - } - - /** - * @param byteBuffer - * @throws IOException - */ - public void read(ByteBuffer byteBuffer) throws InvalidTagException { - int size; - byte[] buffer = new byte[5]; - - // read the 5 character size - byteBuffer.get(buffer, 0, 5); - size = Integer.parseInt(new String(buffer, 0, 5)); - - value = new byte[size]; - - // read the SIZE length description - byteBuffer.get(value); - } - - /** - * @return - */ - public String toString() { - return getIdentifier() + " : " + (new String(value)); - } - - /** - * @param file - * @throws IOException - */ - public void write(RandomAccessFile file) throws IOException { - int offset = 0; - String str; - byte[] buffer = new byte[5]; - - str = Integer.toString(value.length); - - for (int i = 0; i < (5 - str.length()); i++) { - buffer[i] = (byte) '0'; - } - - offset += (5 - str.length()); - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - file.write(buffer); - - file.write(value); - } - - /** - * TODO - */ - protected void setupObjectList() { - - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v1.java b/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v1.java deleted file mode 100644 index f183454..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v1.java +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3v1.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ - -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.TagException; -import org.jaudiotagger.tag.TagNotFoundException; -import org.jaudiotagger.tag.id3.AbstractTag; -import org.jaudiotagger.tag.id3.ID3Tags; -import org.jaudiotagger.tag.id3.ID3v1Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.Iterator; - -public class Lyrics3v1 extends AbstractLyrics3 { - /** - * - */ - private String lyric = ""; - - /** - * Creates a new Lyrics3v1 datatype. - */ - public Lyrics3v1() { - } - - public Lyrics3v1(Lyrics3v1 copyObject) { - super(copyObject); - this.lyric = copyObject.lyric; - } - - public Lyrics3v1(AbstractTag mp3Tag) { - if (mp3Tag != null) { - Lyrics3v2 lyricTag; - - if (mp3Tag instanceof Lyrics3v1) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } else if (mp3Tag instanceof Lyrics3v2) { - lyricTag = (Lyrics3v2) mp3Tag; - } else { - lyricTag = new Lyrics3v2(mp3Tag); - } - - FieldFrameBodyLYR lyricField; - lyricField = (FieldFrameBodyLYR) lyricTag.getField("LYR").getBody(); - this.lyric = lyricField.getLyric(); - } - } - - /** - * Creates a new Lyrics3v1 datatype. - * - * @param file - * @param byteBuffer - * @throws TagNotFoundException - * @throws java.io.IOException - */ - public Lyrics3v1(ByteBuffer byteBuffer) throws TagNotFoundException, java.io.IOException { - try { - this.read(byteBuffer); - } catch (TagException e) { - e.printStackTrace(); - } - } - - /** - * @return - */ - public String getIdentifier() { - return "Lyrics3v1.00"; - } - - /** - * @return - */ - public String getLyric() { - return lyric; - } - - /** - * @param lyric - */ - public void setLyric(String lyric) { - this.lyric = ID3Tags.truncate(lyric, 5100); - } - - /** - * @return - */ - public int getSize() { - return "LYRICSBEGIN".length() + lyric.length() + "LYRICSEND".length(); - } - - /** - * @param obj - * @return - */ - public boolean isSubsetOf(Object obj) { - return (obj instanceof Lyrics3v1) && (((Lyrics3v1) obj).lyric.contains(this.lyric)); - - } - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof Lyrics3v1)) { - return false; - } - - Lyrics3v1 object = (Lyrics3v1) obj; - - return this.lyric.equals(object.lyric) && super.equals(obj); - - } - - /** - * @return - * @throws java.lang.UnsupportedOperationException - */ - public Iterator iterator() { - /** - * @todo Implement this org.jaudiotagger.tag.AbstractMP3Tag abstract method - */ - throw new java.lang.UnsupportedOperationException("Method iterator() not yet implemented."); - } - - /** - * TODO implement - * - * @param byteBuffer - * @return - * @throws IOException - */ - public boolean seek(ByteBuffer byteBuffer) { - return false; - } - - /** - * @param byteBuffer - * @throws TagNotFoundException - * @throws IOException - */ - public void read(ByteBuffer byteBuffer) throws TagException { - byte[] buffer = new byte[5100 + 9 + 11]; - String lyricBuffer; - - if (!seek(byteBuffer)) { - throw new TagNotFoundException("ID3v1 tag not found"); - } - - byteBuffer.get(buffer); - lyricBuffer = new String(buffer); - - lyric = lyricBuffer.substring(0, lyricBuffer.indexOf("LYRICSEND")); - } - - /** - * @param file - * @return - * @throws IOException - */ - public boolean seek(RandomAccessFile file) throws IOException { - byte[] buffer = new byte[5100 + 9 + 11]; - String lyricsEnd; - String lyricsStart; - long offset; - - // check right before the ID3 1.0 tag for the lyrics tag - file.seek(file.length() - 128 - 9); - file.read(buffer, 0, 9); - lyricsEnd = new String(buffer, 0, 9); - - if (lyricsEnd.equals("LYRICSEND")) { - offset = file.getFilePointer(); - } else { - // check the end of the file for a lyrics tag incase an ID3 - // tag wasn't placed after it. - file.seek(file.length() - 9); - file.read(buffer, 0, 9); - lyricsEnd = new String(buffer, 0, 9); - - if (lyricsEnd.equals("LYRICSEND")) { - offset = file.getFilePointer(); - } else { - return false; - } - } - - // the tag can at most only be 5100 bytes - offset -= (5100 + 9 + 11); - file.seek(offset); - file.read(buffer); - lyricsStart = new String(buffer); - - // search for the tag - int i = lyricsStart.indexOf("LYRICSBEGIN"); - - if (i == -1) { - return false; - } - - file.seek(offset + i + 11); - - return true; - } - - /** - * @return - */ - public String toString() { - String str = getIdentifier() + " " + this.getSize() + "\n"; - - return str + lyric; - } - - /** - * @param file - * @throws IOException - */ - public void write(RandomAccessFile file) throws IOException { - String str; - int offset; - byte[] buffer; - ID3v1Tag id3v1tag; - - id3v1tag = null; - - delete(file); - file.seek(file.length()); - - buffer = new byte[lyric.length() + 11 + 9]; - - str = "LYRICSBEGIN"; - - for (int i = 0; i < str.length(); i++) { - buffer[i] = (byte) str.charAt(i); - } - - offset = str.length(); - - str = ID3Tags.truncate(lyric, 5100); - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - offset += str.length(); - - str = "LYRICSEND"; - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - offset += str.length(); - - file.write(buffer, 0, offset); - - if (id3v1tag != null) { - id3v1tag.write(file); - } - } - -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java b/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java deleted file mode 100644 index e9724bb..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3v1Iterator.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public class Lyrics3v1Iterator implements Iterator { - /** - * - */ - private Lyrics3v1 tag = null; - - /** - * - */ - private int lastIndex = 0; - - /** - * - */ - private int removeIndex = 0; - - /** - * Creates a new Lyrics3v1Iterator datatype. - * - * @param lyrics3v1Tag - */ - public Lyrics3v1Iterator(Lyrics3v1 lyrics3v1Tag) { - tag = lyrics3v1Tag; - } - - /** - * @return - */ - public boolean hasNext() { - return !((tag.getLyric().indexOf('\n', lastIndex) < 0) && (lastIndex > tag.getLyric().length())); - } - - /** - * @return - * @throws NoSuchElementException - */ - public String next() { - int nextIndex = tag.getLyric().indexOf('\n', lastIndex); - - removeIndex = lastIndex; - - String line; - - if (lastIndex >= 0) { - if (nextIndex >= 0) { - line = tag.getLyric().substring(lastIndex, nextIndex); - } else { - line = tag.getLyric().substring(lastIndex); - } - - lastIndex = nextIndex; - } else { - throw new NoSuchElementException("Iteration has no more elements."); - } - - return line; - } - - /** - * - */ - public void remove() { - String lyric = tag.getLyric().substring(0, removeIndex) + tag.getLyric().substring(lastIndex); - tag.setLyric(lyric); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2.java b/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2.java deleted file mode 100644 index 0654f5a..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2.java +++ /dev/null @@ -1,469 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3v2.java 976 2011-06-08 10:05:34Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.TagException; -import org.jaudiotagger.tag.TagNotFoundException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.AbstractID3v2Frame; -import org.jaudiotagger.tag.id3.AbstractTag; -import org.jaudiotagger.tag.id3.ID3v1Tag; -import org.jaudiotagger.tag.id3.ID3v24Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Iterator; - -public class Lyrics3v2 extends AbstractLyrics3 { - /** - * - */ - private HashMap fieldMap = new HashMap(); - - /** - * Creates a new Lyrics3v2 datatype. - */ - public Lyrics3v2() { - } - - public Lyrics3v2(Lyrics3v2 copyObject) { - super(copyObject); - - Iterator iterator = copyObject.fieldMap.keySet().iterator(); - String oldIdentifier; - String newIdentifier; - Lyrics3v2Field newObject; - - while (iterator.hasNext()) { - oldIdentifier = iterator.next(); - newIdentifier = oldIdentifier; - newObject = new Lyrics3v2Field(copyObject.fieldMap.get(newIdentifier)); - fieldMap.put(newIdentifier, newObject); - } - } - - /** - * Creates a new Lyrics3v2 datatype. - * - * @param mp3tag - * @throws UnsupportedOperationException - */ - public Lyrics3v2(AbstractTag mp3tag) { - if (mp3tag != null) { - // upgrade the tag to lyrics3v2 - if (mp3tag instanceof Lyrics3v2) { - throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument"); - } else if (mp3tag instanceof Lyrics3v1) { - Lyrics3v1 lyricOld = (Lyrics3v1) mp3tag; - Lyrics3v2Field newField; - newField = new Lyrics3v2Field(new FieldFrameBodyLYR(lyricOld.getLyric())); - fieldMap.put(newField.getIdentifier(), newField); - } else { - Lyrics3v2Field newField; - Iterator iterator; - iterator = (new ID3v24Tag(mp3tag)).iterator(); - - while (iterator.hasNext()) { - try { - newField = new Lyrics3v2Field(iterator.next()); - - if (newField != null) { - fieldMap.put(newField.getIdentifier(), newField); - } - } catch (TagException ex) { - //invalid frame to createField lyrics3 field. ignore and keep going - } - } - } - } - } - - /** - * Creates a new Lyrics3v2 datatype. - * - * @param file - * @param byteBuffer - * @throws TagNotFoundException - * @throws IOException - */ - public Lyrics3v2(ByteBuffer byteBuffer) throws TagNotFoundException, IOException { - try { - this.read(byteBuffer); - } catch (TagException e) { - e.printStackTrace(); - } - } - - /** - * @param field - */ - public void setField(Lyrics3v2Field field) { - fieldMap.put(field.getIdentifier(), field); - } - - /** - * Gets the value of the frame identified by identifier - * - * @param identifier The three letter code - * @return The value associated with the identifier - */ - public Lyrics3v2Field getField(String identifier) { - return fieldMap.get(identifier); - } - - /** - * @return - */ - public int getFieldCount() { - return fieldMap.size(); - } - - /** - * @return - */ - public String getIdentifier() { - return "Lyrics3v2.00"; - } - - /** - * @return - */ - public int getSize() { - int size = 0; - Iterator iterator = fieldMap.values().iterator(); - Lyrics3v2Field field; - - while (iterator.hasNext()) { - field = iterator.next(); - size += field.getSize(); - } - - // include LYRICSBEGIN, but not 6 char size or LYRICSEND - return 11 + size; - } - - - /** - * @param obj - * @return - */ - public boolean equals(Object obj) { - if (!(obj instanceof Lyrics3v2)) { - return false; - } - - Lyrics3v2 object = (Lyrics3v2) obj; - - return this.fieldMap.equals(object.fieldMap) && super.equals(obj); - - } - - /** - * @param identifier - * @return - */ - public boolean hasField(String identifier) { - return fieldMap.containsKey(identifier); - } - - /** - * @return - */ - public Iterator iterator() { - return fieldMap.values().iterator(); - } - - - /** - * TODO implement - * - * @param byteBuffer - * @return - * @throws IOException - */ - public boolean seek(ByteBuffer byteBuffer) { - return false; - } - - - public void read(ByteBuffer byteBuffer) throws TagException { - long filePointer; - int lyricSize; - - if (seek(byteBuffer)) { - lyricSize = seekSize(byteBuffer); - } else { - throw new TagNotFoundException("Lyrics3v2.00 Tag Not Found"); - } - - // reset file pointer to the beginning of the tag; - seek(byteBuffer); - filePointer = byteBuffer.position(); - - fieldMap = new HashMap(); - - Lyrics3v2Field lyric; - - // read each of the fields - while ((byteBuffer.position()) < (lyricSize - 11)) { - try { - lyric = new Lyrics3v2Field(byteBuffer); - setField(lyric); - } catch (InvalidTagException ex) { - // keep reading until we're done - } - } - } - - /** - * @param identifier - */ - public void removeField(String identifier) { - fieldMap.remove(identifier); - } - - /** - * @param file - * @return - * @throws IOException - */ - public boolean seek(RandomAccessFile file) throws IOException { - byte[] buffer = new byte[11]; - String lyricEnd; - String lyricStart; - long filePointer; - long lyricSize; - - // check right before the ID3 1.0 tag for the lyrics tag - file.seek(file.length() - 128 - 9); - file.read(buffer, 0, 9); - lyricEnd = new String(buffer, 0, 9); - - if (lyricEnd.equals("LYRICS200")) { - filePointer = file.getFilePointer(); - } else { - // check the end of the file for a lyrics tag incase an ID3 - // tag wasn't placed after it. - file.seek(file.length() - 9); - file.read(buffer, 0, 9); - lyricEnd = new String(buffer, 0, 9); - - if (lyricEnd.equals("LYRICS200")) { - filePointer = file.getFilePointer(); - } else { - return false; - } - } - - // read the 6 bytes for the length of the tag - filePointer -= (9 + 6); - file.seek(filePointer); - file.read(buffer, 0, 6); - - lyricSize = Integer.parseInt(new String(buffer, 0, 6)); - - // read the lyrics begin tag if it exists. - file.seek(filePointer - lyricSize); - file.read(buffer, 0, 11); - lyricStart = new String(buffer, 0, 11); - - return lyricStart.equals("LYRICSBEGIN"); - } - - /** - * @return - */ - public String toString() { - Iterator iterator = fieldMap.values().iterator(); - Lyrics3v2Field field; - String str = getIdentifier() + " " + this.getSize() + "\n"; - - while (iterator.hasNext()) { - field = iterator.next(); - str += (field.toString() + "\n"); - } - - return str; - } - - /** - * @param identifier - */ - public void updateField(String identifier) { - Lyrics3v2Field lyrField; - - if (identifier.equals("IND")) { - boolean lyricsPresent = fieldMap.containsKey("LYR"); - boolean timeStampPresent = false; - - if (lyricsPresent) { - lyrField = fieldMap.get("LYR"); - - FieldFrameBodyLYR lyrBody = (FieldFrameBodyLYR) lyrField.getBody(); - timeStampPresent = lyrBody.hasTimeStamp(); - } - - lyrField = new Lyrics3v2Field(new FieldFrameBodyIND(lyricsPresent, timeStampPresent)); - setField(lyrField); - } - } - - /** - * @param file - * @throws IOException - */ - public void write(RandomAccessFile file) throws IOException { - int offset = 0; - - long size; - long filePointer; - byte[] buffer = new byte[6 + 9]; - - String str; - Lyrics3v2Field field; - Iterator iterator; - ID3v1Tag id3v1tag; - new ID3v1Tag(); - - id3v1tag = null; - - delete(file); - file.seek(file.length()); - - filePointer = file.getFilePointer(); - - str = "LYRICSBEGIN"; - - for (int i = 0; i < str.length(); i++) { - buffer[i] = (byte) str.charAt(i); - } - - file.write(buffer, 0, str.length()); - - // IND needs to go first. lets createField/update it and write it first. - updateField("IND"); - field = fieldMap.get("IND"); - field.write(file); - - iterator = fieldMap.values().iterator(); - - while (iterator.hasNext()) { - field = iterator.next(); - - String id = field.getIdentifier(); - boolean save = TagOptionSingleton.getInstance().getLyrics3SaveField(id); - - if ((!id.equals("IND")) && save) { - field.write(file); - } - } - - size = file.getFilePointer() - filePointer; - - if (this.getSize() != size) { - //logger.config("Lyrics3v2 size didn't match up while writing."); - //logger.config("this.getsize() = " + this.getSize()); - //logger.config("size (filePointer) = " + size); - } - - str = Long.toString(size); - - for (int i = 0; i < (6 - str.length()); i++) { - buffer[i] = (byte) '0'; - } - - offset += (6 - str.length()); - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - offset += str.length(); - - str = "LYRICS200"; - - for (int i = 0; i < str.length(); i++) { - buffer[i + offset] = (byte) str.charAt(i); - } - - offset += str.length(); - - file.write(buffer, 0, offset); - - if (id3v1tag != null) { - id3v1tag.write(file); - } - } - - /** - * TODO - * - * @param byteBuffer - * @return - */ - private int seekSize(ByteBuffer byteBuffer) { - /* - byte[] buffer = new byte[11]; - String lyricEnd = ""; - long filePointer = 0; - - // check right before the ID3 1.0 tag for the lyrics tag - file.seek(file.length() - 128 - 9); - file.read(buffer, 0, 9); - lyricEnd = new String(buffer, 0, 9); - - if (lyricEnd.equals("LYRICS200")) - { - filePointer = file.getFilePointer(); - } - else - { - // check the end of the file for a lyrics tag incase an ID3 - // tag wasn't placed after it. - file.seek(file.length() - 9); - file.read(buffer, 0, 9); - lyricEnd = new String(buffer, 0, 9); - - if (lyricEnd.equals("LYRICS200")) - { - filePointer = file.getFilePointer(); - } - else - { - return -1; - } - } - - // read the 6 bytes for the length of the tag - filePointer -= (9 + 6); - file.seek(filePointer); - file.read(buffer, 0, 6); - - return Integer.parseInt(new String(buffer, 0, 6)); - */ - return -1; - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java b/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java deleted file mode 100644 index 225f4b6..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - *

    - * Version @version:$Id: Lyrics3v2Field.java 836 2009-11-12 15:44:07Z paultaylor $ - *

    - * MusicTag Copyright (C)2003,2004 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ - -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.InvalidTagException; -import org.jaudiotagger.tag.TagException; -import org.jaudiotagger.tag.TagOptionSingleton; -import org.jaudiotagger.tag.id3.AbstractID3v2Frame; -import org.jaudiotagger.tag.id3.AbstractTagFrame; -import org.jaudiotagger.tag.id3.framebody.AbstractFrameBodyTextInfo; -import org.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import org.jaudiotagger.tag.id3.framebody.FrameBodySYLT; -import org.jaudiotagger.tag.id3.framebody.FrameBodyUSLT; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - - -public class Lyrics3v2Field extends AbstractTagFrame { - /** - * Creates a new Lyrics3v2Field datatype. - */ - public Lyrics3v2Field() { - } - - public Lyrics3v2Field(Lyrics3v2Field copyObject) { - super(copyObject); - } - - /** - * Creates a new Lyrics3v2Field datatype. - * - * @param body - */ - public Lyrics3v2Field(AbstractLyrics3v2FieldFrameBody body) { - this.frameBody = body; - } - - /** - * Creates a new Lyrics3v2Field datatype. - * - * @param frame - * @throws TagException - */ - public Lyrics3v2Field(AbstractID3v2Frame frame) throws TagException { - AbstractFrameBodyTextInfo textFrame; - String text; - String frameIdentifier = frame.getIdentifier(); - if (frameIdentifier.startsWith("USLT")) { - frameBody = new FieldFrameBodyLYR(""); - ((FieldFrameBodyLYR) frameBody).addLyric((FrameBodyUSLT) frame.getBody()); - } else if (frameIdentifier.startsWith("SYLT")) { - frameBody = new FieldFrameBodyLYR(""); - ((FieldFrameBodyLYR) frameBody).addLyric((FrameBodySYLT) frame.getBody()); - } else if (frameIdentifier.startsWith("COMM")) { - text = ((FrameBodyCOMM) frame.getBody()).getText(); - frameBody = new FieldFrameBodyINF(text); - } else if (frameIdentifier.equals("TCOM")) { - textFrame = (AbstractFrameBodyTextInfo) frame.getBody(); - frameBody = new FieldFrameBodyAUT(""); - if ((textFrame != null) && (textFrame.getText().length() > 0)) { - frameBody = new FieldFrameBodyAUT(textFrame.getText()); - } - } else if (frameIdentifier.equals("TALB")) { - textFrame = (AbstractFrameBodyTextInfo) frame.getBody(); - if ((textFrame != null) && (textFrame.getText().length() > 0)) { - frameBody = new FieldFrameBodyEAL(textFrame.getText()); - } - } else if (frameIdentifier.equals("TPE1")) { - textFrame = (AbstractFrameBodyTextInfo) frame.getBody(); - if ((textFrame != null) && (textFrame.getText().length() > 0)) { - frameBody = new FieldFrameBodyEAR(textFrame.getText()); - } - } else if (frameIdentifier.equals("TIT2")) { - textFrame = (AbstractFrameBodyTextInfo) frame.getBody(); - if ((textFrame != null) && (textFrame.getText().length() > 0)) { - frameBody = new FieldFrameBodyETT(textFrame.getText()); - } - } else { - throw new TagException("Cannot createField Lyrics3v2 field from given ID3v2 frame"); - } - } - - /** - * Creates a new Lyrics3v2Field datatype. - * - * @param file - * @param byteBuffer - * @throws InvalidTagException - */ - public Lyrics3v2Field(ByteBuffer byteBuffer) throws InvalidTagException { - this.read(byteBuffer); - } - - /** - * @return - */ - public String getIdentifier() { - if (frameBody == null) { - return ""; - } - return frameBody.getIdentifier(); - } - - /** - * @return - */ - public int getSize() { - return frameBody.getSize() + 5 + getIdentifier().length(); - } - - /** - * @param byteBuffer - * @throws InvalidTagException - * @throws IOException - */ - public void read(ByteBuffer byteBuffer) throws InvalidTagException { - byte[] buffer = new byte[6]; - // lets scan for a non-zero byte; - long filePointer; - byte b; - do { - b = byteBuffer.get(); - } - while (b == 0); - byteBuffer.position(byteBuffer.position() - 1); - // read the 3 character ID - byteBuffer.get(buffer, 0, 3); - String identifier = new String(buffer, 0, 3); - // is this a valid identifier? - if (!Lyrics3v2Fields.isLyrics3v2FieldIdentifier(identifier)) { - throw new InvalidTagException(identifier + " is not a valid ID3v2.4 frame"); - } - frameBody = readBody(identifier, byteBuffer); - } - - /** - * @return - */ - public String toString() { - if (frameBody == null) { - return ""; - } - return frameBody.toString(); - } - - /** - * @param file - * @throws IOException - */ - public void write(RandomAccessFile file) throws IOException { - if ((frameBody.getSize() > 0) || TagOptionSingleton.getInstance().isLyrics3SaveEmptyField()) { - byte[] buffer = new byte[3]; - String str = getIdentifier(); - for (int i = 0; i < str.length(); i++) { - buffer[i] = (byte) str.charAt(i); - } - file.write(buffer, 0, str.length()); - //body.write(file); - } - } - - /** - * Read a Lyrics3 Field from a file. - * - * @param identifier - * @param byteBuffer - * @return - * @throws InvalidTagException - */ - private AbstractLyrics3v2FieldFrameBody readBody(String identifier, ByteBuffer byteBuffer) throws InvalidTagException { - AbstractLyrics3v2FieldFrameBody newBody; - if (identifier.equals(Lyrics3v2Fields.FIELD_V2_AUTHOR)) { - newBody = new FieldFrameBodyAUT(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_ALBUM)) { - newBody = new FieldFrameBodyEAL(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_ARTIST)) { - newBody = new FieldFrameBodyEAR(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_TRACK)) { - newBody = new FieldFrameBodyETT(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_IMAGE)) { - newBody = new FieldFrameBodyIMG(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_INDICATIONS)) { - newBody = new FieldFrameBodyIND(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_ADDITIONAL_MULTI_LINE_TEXT)) { - newBody = new FieldFrameBodyINF(byteBuffer); - } else if (identifier.equals(Lyrics3v2Fields.FIELD_V2_LYRICS_MULTI_LINE_TEXT)) { - newBody = new FieldFrameBodyLYR(byteBuffer); - } else { - newBody = new FieldFrameBodyUnsupported(byteBuffer); - } - return newBody; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java b/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java deleted file mode 100644 index b48e16f..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: Lyrics3v2Fields.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.lyrics3; - -import org.jaudiotagger.tag.datatype.AbstractStringStringValuePair; - -public class Lyrics3v2Fields extends AbstractStringStringValuePair { - - public static final String FIELD_V2_INDICATIONS = "IND"; - public static final String FIELD_V2_LYRICS_MULTI_LINE_TEXT = "LYR"; - public static final String FIELD_V2_ADDITIONAL_MULTI_LINE_TEXT = "INF"; - public static final String FIELD_V2_AUTHOR = "AUT"; - public static final String FIELD_V2_ALBUM = "EAL"; - public static final String FIELD_V2_ARTIST = "EAR"; - public static final String FIELD_V2_TRACK = "ETT"; - public static final String FIELD_V2_IMAGE = "IMG"; - /** - * CRLF int set - */ - private static final byte[] crlfByte = {13, 10}; - /** - * CRLF int set - */ - public static final String CRLF = new String(crlfByte); - private static Lyrics3v2Fields lyrics3Fields; - private Lyrics3v2Fields() { - idToValue.put(FIELD_V2_INDICATIONS, "Indications field"); - idToValue.put(FIELD_V2_LYRICS_MULTI_LINE_TEXT, "Lyrics multi line text"); - idToValue.put(FIELD_V2_ADDITIONAL_MULTI_LINE_TEXT, "Additional information multi line text"); - idToValue.put(FIELD_V2_AUTHOR, "Lyrics/Music Author name"); - idToValue.put(FIELD_V2_ALBUM, "Extended Album name"); - idToValue.put(FIELD_V2_ARTIST, "Extended Artist name"); - idToValue.put(FIELD_V2_TRACK, "Extended Track Title"); - idToValue.put(FIELD_V2_IMAGE, "Link to an image files"); - createMaps(); - } - - public static Lyrics3v2Fields getInstanceOf() { - if (lyrics3Fields == null) { - lyrics3Fields = new Lyrics3v2Fields(); - } - return lyrics3Fields; - } - - /** - * Returns true if the identifier is a valid Lyrics3v2 frame identifier - * - * @param identifier string to test - * @return true if the identifier is a valid Lyrics3v2 frame identifier - */ - public static boolean isLyrics3v2FieldIdentifier(String identifier) { - return identifier.length() >= 3 && getInstanceOf().getIdToValueMap().containsKey(identifier.substring(0, 3)); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/lyrics3/package.html b/src/main/java/org/jaudiotagger/tag/lyrics3/package.html deleted file mode 100644 index 838644b..0000000 --- a/src/main/java/org/jaudiotagger/tag/lyrics3/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Implementation of ID3 frames that follow the lyrics3 pattern, not restricted to lyrics. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/mp4/Mp4FieldKey.java b/src/main/java/org/jaudiotagger/tag/mp4/Mp4FieldKey.java deleted file mode 100644 index 6ba2e70..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/Mp4FieldKey.java +++ /dev/null @@ -1,318 +0,0 @@ -package org.jaudiotagger.tag.mp4; - -import org.jaudiotagger.tag.mp4.field.Mp4FieldType; -import org.jaudiotagger.tag.mp4.field.Mp4TagReverseDnsField; -import org.jaudiotagger.tag.reference.Tagger; - -import static org.jaudiotagger.tag.mp4.field.Mp4FieldType.*; - -/** - * Starting list of known mp4 metadata fields that follow the Parent,Data or ---,issuer,name,data - * convention. Atoms that contain metadata in other formats are not listed here because they need to be processed - * specially. - *

    - *

    - *

    Simple metaitems use the parent atom id as their identifier whereas reverse dns (----) atoms use - * the reversedns,issuer and name fields as their identifier. When the atom is non-0standard but follws the rules - * we list it here with an additional Tagger field to indicate where the field was originally designed. - *

    - * From: - * http://www.hydrogenaudio.org/forums/index.php?showtopic=29120&st=0&p=251686&#entry251686 - * http://wiki.musicbrainz.org/PicardQt/TagMapping - * http://atomicparsley.sourceforge.net/mpeg-4files.html - *

    - *

    - */ -public enum Mp4FieldKey { - ACOUSTID_FINGERPRINT("com.apple.iTunes", "Acoustid Fingerprint", TEXT, Tagger.PICARD), - ACOUSTID_FINGERPRINT_OLD("com.apple.iTunes", "AcoustId Fingerprint", TEXT, Tagger.PICARD), - ACOUSTID_ID("com.apple.iTunes", "Acoustid Id", TEXT, Tagger.PICARD), - ALBUM("©alb", Mp4TagFieldSubType.TEXT, TEXT), - ALBUM_ARTIST("aART", Mp4TagFieldSubType.TEXT, TEXT), - ALBUM_ARTIST_SORT("soaa", Mp4TagFieldSubType.TEXT, TEXT), - ALBUM_SORT("soal", Mp4TagFieldSubType.TEXT, TEXT), - ARTIST_SORT("soar", Mp4TagFieldSubType.TEXT, TEXT), - ARTIST("©ART", Mp4TagFieldSubType.TEXT, TEXT), - ARTWORK("covr", Mp4TagFieldSubType.ARTWORK, COVERART_JPEG), - ASIN("com.apple.iTunes", "ASIN", TEXT, Tagger.PICARD), - BPM("tmpo", Mp4TagFieldSubType.BYTE, INTEGER, 2), - CATEGORY("catg", Mp4TagFieldSubType.TEXT, TEXT), - CDDB_1("com.apple.iTunes", "iTunes_CDDB_1", TEXT), - CDDB_IDS("com.apple.iTunes", "iTunes_CDDB_IDs", TEXT), - CDDB_TRACKNUMBER("com.apple.iTunes", "iTunes_CDDB_TrackNumber", TEXT), - COMMENT("©cmt", Mp4TagFieldSubType.TEXT, TEXT), - COMPILATION("cpil", Mp4TagFieldSubType.BYTE, INTEGER, 1), - COMPOSER("©wrt", Mp4TagFieldSubType.TEXT, TEXT), - COMPOSER_SORT("soco", Mp4TagFieldSubType.TEXT, TEXT), - COPYRIGHT("cprt", Mp4TagFieldSubType.TEXT, TEXT), - COUNTRY("com.apple.iTunes", "Country", TEXT, Tagger.PICARD), - DAY("©day", Mp4TagFieldSubType.TEXT, TEXT), - DESCRIPTION("desc", Mp4TagFieldSubType.TEXT, TEXT), - DISCNUMBER("disk", Mp4TagFieldSubType.DISC_NO, IMPLICIT), - DISC_SUBTITLE("com.apple.iTunes", "DISCSUBTITLE", TEXT, Tagger.PICARD), - ENCODER("©too", Mp4TagFieldSubType.TEXT, TEXT), - FBPM("com.apple.iTunes", "fBPM", TEXT, Tagger.JAIKOZ), - GENRE("gnre", Mp4TagFieldSubType.GENRE, IMPLICIT), - GENRE_CUSTOM("©gen", Mp4TagFieldSubType.TEXT, TEXT), - GROUPING("©grp", Mp4TagFieldSubType.TEXT, TEXT), - ITUNES_NORM("com.apple.iTunes", "iTunNORM", TEXT), - ITUNES_SMPB("com.apple.iTunes", "iTunSMPB", TEXT), - KEY("com.apple.iTunes", "KEY", TEXT, Tagger.JAIKOZ), - KEYWORD("keyw", Mp4TagFieldSubType.TEXT, TEXT), - LANGUAGE("com.apple.iTunes", "LANGUAGE", TEXT, Tagger.JAIKOZ), - LYRICS("©lyr", Mp4TagFieldSubType.TEXT, TEXT), - MUSICBRAINZ_ALBUMARTISTID("com.apple.iTunes", "MusicBrainz Album Artist Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_ALBUMID("com.apple.iTunes", "MusicBrainz Album Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_ALBUM_STATUS("com.apple.iTunes", "MusicBrainz Album Status", TEXT, Tagger.PICARD), - MUSICBRAINZ_ALBUM_TYPE("com.apple.iTunes", "MusicBrainz Album Type", TEXT, Tagger.PICARD), - MUSICBRAINZ_ARTISTID("com.apple.iTunes", "MusicBrainz Artist Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_DISCID("com.apple.iTunes", "MusicBrainz Disc Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_ORIGINALALBUMID("com.apple.iTunes", "MusicBrainz Original Album Id", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_RELEASE_GROUPID("com.apple.iTunes", "MusicBrainz Release Group Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_TRACKID("com.apple.iTunes", "MusicBrainz Track Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_WORKID("com.apple.iTunes", "MusicBrainz Work Id", TEXT, Tagger.PICARD), - MUSICIP_PUID("com.apple.iTunes", "MusicIP PUID", TEXT, Tagger.PICARD), - PART_OF_GAPLESS_ALBUM("pgap", Mp4TagFieldSubType.BYTE, INTEGER), - PURCHASE_DATE("purd", Mp4TagFieldSubType.TEXT, TEXT), - RATING("rtng", Mp4TagFieldSubType.BYTE, INTEGER, 1), //AFAIK Cant be setField in itunes, but if setField to explicit itunes will show as explicit - RELEASECOUNTRY("com.apple.iTunes", "MusicBrainz Album Release Country", TEXT, Tagger.PICARD), - SHOW("tvsh", Mp4TagFieldSubType.TEXT, TEXT), //tv show but also used just as show - SHOW_SORT("sosn", Mp4TagFieldSubType.TEXT, TEXT), - SUBTITLE("com.apple.iTunes", "SUBTITLE", TEXT, Tagger.PICARD), - TITLE("©nam", Mp4TagFieldSubType.TEXT, TEXT), - TITLE_SORT("sonm", Mp4TagFieldSubType.TEXT, TEXT), - TRACK("trkn", Mp4TagFieldSubType.TRACK_NO, IMPLICIT), - - //AFAIK These arent actually used by Audio Only files, but there is nothing to prevent them being used - CONTENT_TYPE("stik", Mp4TagFieldSubType.BYTE, INTEGER, 1), - TOOL("tool", Mp4TagFieldSubType.BYTE, INTEGER, 4), - PODCAST_KEYWORD("keyw", Mp4TagFieldSubType.TEXT, TEXT), - PODCAST_URL("purl", Mp4TagFieldSubType.NUMBER, IMPLICIT), //TODO Actually seems to store text but is marked as numeric! - EPISODE_GLOBAL_ID("egid", Mp4TagFieldSubType.NUMBER, IMPLICIT), //TODO Actually seems to store text but is marked as numeric! - TV_NETWORK("tvnn", Mp4TagFieldSubType.TEXT, TEXT), - TV_EPISODE_NUMBER("tven", Mp4TagFieldSubType.TEXT, TEXT), - TV_SEASON("tvsn", Mp4TagFieldSubType.BYTE, INTEGER, 1), - TV_EPISODE("tves", Mp4TagFieldSubType.BYTE, INTEGER, 1), - - //These seem to be used in DRM Files, of type byte , we need to know the byte length to allow them to be written - //back correctly on saving them, we don't provides options to modify them as may break drm - AP_ID("apID", Mp4TagFieldSubType.UNKNOWN, TEXT), - AT_ID("atID", Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - CN_ID("cnID", Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - PL_ID("plID", Mp4TagFieldSubType.UNKNOWN, INTEGER, 8), - GE_ID("geID", Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - SF_ID("sfID", Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - AK_ID("akID", Mp4TagFieldSubType.UNKNOWN, INTEGER, 1), - - //Media Monkey3 beta - LYRICIST_MM3BETA("lyrc", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CONDUCTOR_MM3BETA("cond", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - ISRC_MMBETA("isrc", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - MOOD_MM3BETA("mood", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - SCORE("rate", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), //As in mark out of 100 - ORIGINAL_ARTIST("oart", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - ORIGINAL_ALBUM_TITLE("otit", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - ORIGINAL_LYRICIST("olyr", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - INVOLVED_PEOPLE("peop", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - TEMPO("empo", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - OCCASION("occa", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - QUALITY("qual", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CUSTOM_1("cus1", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CUSTOM_2("cus2", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CUSTOM_3("cus3", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CUSTOM_4("cus4", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CUSTOM_5("cus5", Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - - //Media Monkey 3.0.6 Onwards - MM_PUBLISHER("com.apple.iTunes", "ORGANIZATION", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_ARTIST("com.apple.iTunes", "ORIGINAL ARTIST", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_ALBUM_TITLE("com.apple.iTunes", "ORIGINAL ALBUM", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_LYRICIST("com.apple.iTunes", "ORIGINAL LYRICIST", TEXT, Tagger.MEDIA_MONKEY), - MM_INVOLVED_PEOPLE("com.apple.iTunes", "INVOLVED PEOPLE", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_YEAR("com.apple.iTunes", "ORIGINAL YEAR", TEXT, Tagger.MEDIA_MONKEY), - MM_TEMPO("com.apple.iTunes", "TEMPO", TEXT, Tagger.MEDIA_MONKEY), - MM_OCCASION("com.apple.iTunes", "OCCASION", TEXT, Tagger.MEDIA_MONKEY), - MM_QUALITY("com.apple.iTunes", "QUALITY", TEXT, Tagger.MEDIA_MONKEY), - MM_CUSTOM_1("com.apple.iTunes", "CUSTOM1", TEXT, Tagger.MEDIA_MONKEY), - MM_CUSTOM_2("com.apple.iTunes", "CUSTOM2", TEXT, Tagger.MEDIA_MONKEY), - MM_CUSTOM_3("com.apple.iTunes", "CUSTOM3", TEXT, Tagger.MEDIA_MONKEY), - MM_CUSTOM_4("com.apple.iTunes", "CUSTOM4", TEXT, Tagger.MEDIA_MONKEY), - MM_CUSTOM_5("com.apple.iTunes", "CUSTOM5", TEXT, Tagger.MEDIA_MONKEY), - - //Picard Qt - LYRICIST("com.apple.iTunes", "LYRICIST", TEXT, Tagger.PICARD), - CONDUCTOR("com.apple.iTunes", "CONDUCTOR", TEXT, Tagger.PICARD), - REMIXER("com.apple.iTunes", "REMIXER", TEXT, Tagger.PICARD), - ENGINEER("com.apple.iTunes", "ENGINEER", TEXT, Tagger.PICARD), - PRODUCER("com.apple.iTunes", "PRODUCER", TEXT, Tagger.PICARD), - DJMIXER("com.apple.iTunes", "DJMIXER", TEXT, Tagger.PICARD), - MIXER("com.apple.iTunes", "MIXER", TEXT, Tagger.PICARD), - ARRANGER("com.apple.iTunes", "ARRANGER", TEXT, Tagger.PICARD), - MOOD("com.apple.iTunes", "MOOD", TEXT, Tagger.PICARD), - ISRC("com.apple.iTunes", "ISRC", TEXT, Tagger.PICARD), - MEDIA("com.apple.iTunes", "MEDIA", TEXT, Tagger.PICARD), - LABEL("com.apple.iTunes", "LABEL", TEXT, Tagger.PICARD), - CATALOGNO("com.apple.iTunes", "CATALOGNUMBER", TEXT, Tagger.PICARD), - BARCODE("com.apple.iTunes", "BARCODE", TEXT, Tagger.PICARD), - - //Jaikoz - URL_LYRICS_SITE("com.apple.iTunes", "URL_LYRICS_SITE", TEXT, Tagger.JAIKOZ), - URL_OFFICIAL_RELEASE_SITE("com.apple.iTunes", "URL_OFFICIAL_RELEASE_SITE", TEXT, Tagger.JAIKOZ), - URL_DISCOGS_RELEASE_SITE("com.apple.iTunes", "URL_DISCOGS_RELEASE_SITE", TEXT, Tagger.JAIKOZ), - URL_WIKIPEDIA_RELEASE_SITE("com.apple.iTunes", "URL_WIKIPEDIA_RELEASE_SITE", TEXT, Tagger.JAIKOZ), - URL_OFFICIAL_ARTIST_SITE("com.apple.iTunes", "URL_OFFICIAL_ARTIST_SITE", TEXT, Tagger.JAIKOZ), - URL_DISCOGS_ARTIST_SITE("com.apple.iTunes", "URL_DISCOGS_ARTIST_SITE", TEXT, Tagger.JAIKOZ), - URL_WIKIPEDIA_ARTIST_SITE("com.apple.iTunes", "URL_WIKIPEDIA_ARTIST_SITE", TEXT, Tagger.JAIKOZ), - SCRIPT("com.apple.iTunes", "SCRIPT", TEXT, Tagger.JAIKOZ), - TAGS("com.apple.iTunes", "TAGS", TEXT, Tagger.JAIKOZ), - ARTISTS("com.apple.iTunes", "ARTISTS", TEXT, Tagger.JAIKOZ), - - //Winamp - WINAMP_PUBLISHER("com.nullsoft.winamp", "publisher", TEXT, Tagger.WINAMP), - - //Unknown - KEYS("keys", Mp4TagFieldSubType.TEXT, TEXT),; - private Tagger tagger; - private String fieldName; - private Mp4TagFieldSubType subclassType; - private String issuer; - private String identifier; - private Mp4FieldType fieldType; - private int fieldLength; - - /** - * For usual metadata fields that use a data field - * - * @param fieldName - * @param fieldType of data atom - */ - Mp4FieldKey(String fieldName, Mp4TagFieldSubType subclassType, Mp4FieldType fieldType) { - this.fieldName = fieldName; - this.subclassType = subclassType; - this.fieldType = fieldType; - } - - /** - * For usual metadata fields that use a data field, but not recognised as standard field - * - * @param fieldName - * @param fieldType of data atom - * @param tagger - */ - Mp4FieldKey(String fieldName, Mp4TagFieldSubType subclassType, Mp4FieldType fieldType, Tagger tagger) { - this.fieldName = fieldName; - this.subclassType = subclassType; - this.fieldType = fieldType; - this.tagger = tagger; - } - - /** - * For usual metadata fields that use a data field where the field length is fixed - * such as Byte fields - * - * @param fieldName - * @param fieldType - * @param fieldLength - */ - Mp4FieldKey(String fieldName, Mp4TagFieldSubType subclassType, Mp4FieldType fieldType, int fieldLength) { - this.fieldName = fieldName; - this.subclassType = subclassType; - this.fieldType = fieldType; - this.fieldLength = fieldLength; - } - - /** - * For reverse dns fields that use an internal fieldname of '----' and have additional issuer - * and identifier fields, we use all three seperated by a ':' ) to give us a unique key - * - * @param issuer - * @param identifier - * @param fieldType of data atom - */ - Mp4FieldKey(String issuer, String identifier, Mp4FieldType fieldType) { - - this.issuer = issuer; - this.identifier = identifier; - this.fieldName = Mp4TagReverseDnsField.IDENTIFIER + ":" + issuer + ":" + identifier; - this.subclassType = Mp4TagFieldSubType.REVERSE_DNS; - this.fieldType = fieldType; - } - - /** - * For reverse dns fields that use an internal fieldname of '----' and have additional issuer - * and identifier fields, we use all three seperated by a ':' ) to give us a unique key - * For non-standard fields - * - * @param issuer - * @param identifier - * @param fieldType of data atom - * @param tagger - */ - Mp4FieldKey(String issuer, String identifier, Mp4FieldType fieldType, Tagger tagger) { - - this.issuer = issuer; - this.identifier = identifier; - this.fieldName = Mp4TagReverseDnsField.IDENTIFIER + ":" + issuer + ":" + identifier; - this.subclassType = Mp4TagFieldSubType.REVERSE_DNS; - this.fieldType = fieldType; - this.tagger = tagger; - } - - /** - * This is the value of the fieldname that is actually used to write mp4 - * - * @return - */ - public String getFieldName() { - return fieldName; - } - - /** - * @return fieldtype - */ - public Mp4FieldType getFieldType() { - return fieldType; - } - - /** - * @return subclassType - */ - public Mp4TagFieldSubType getSubClassFieldType() { - return subclassType; - } - - /** - * @return true if this is a reverse dns key - */ - public boolean isReverseDnsType() { - return identifier.startsWith(Mp4TagReverseDnsField.IDENTIFIER); - } - - /** - * @return issuer (Reverse Dns Fields Only) - */ - public String getIssuer() { - return issuer; - } - - /** - * @return identifier (Reverse Dns Fields Only) - */ - public String getIdentifier() { - return identifier; - } - - /** - * @return field length (currently only used by byte fields) - */ - public int getFieldLength() { - return fieldLength; - } - - public Tagger getTagger() { - if (tagger != null) { - return tagger; - } - return Tagger.ITUNES; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java b/src/main/java/org/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java deleted file mode 100644 index 2bd27cc..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.jaudiotagger.tag.mp4; - -import org.jaudiotagger.tag.reference.Tagger; - -/** - * This a list of mp4boxes identifiers that break various rules, but should be documented nonetheless, they will - * be created by applications other than iTunes, as we regard iTunes as the defacto standard for Mp4 files (but - * certainly not any other format such as mp3 !). - */ -public enum Mp4NonStandardFieldKey { - AAPR("AApr", "MM3 Album Art Attributes", Tagger.MEDIA_MONKEY), - ALFN("Alfn", "MM3 Album Art Unknown", Tagger.MEDIA_MONKEY), - AMIM("AMIM", "MM3 Album Art MimeType", Tagger.MEDIA_MONKEY), - ADCP("Adcp", "MM3 Album Art Description", Tagger.MEDIA_MONKEY), - APTY("Apty", "MM3 Album Art ID3 Picture Type", Tagger.MEDIA_MONKEY); - - private String fieldName; - private String description; - private Tagger tagger; - - Mp4NonStandardFieldKey(String fieldName, String description, Tagger tagger) { - this.fieldName = fieldName; - this.description = description; - this.tagger = tagger; - - } - - /** - * This is the value of the fieldname that is actually used to write mp4 - * - * @return - */ - public String getFieldName() { - return fieldName; - } - - /** - * @return description, human redable description of the atom - */ - public String getDescription() { - return description; - } - - /** - * @return tagger that defined (and probably craeted) instance of field - */ - public Tagger geTagger() { - return tagger; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/Mp4Tag.java b/src/main/java/org/jaudiotagger/tag/mp4/Mp4Tag.java deleted file mode 100644 index 7b86eae..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/Mp4Tag.java +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphael Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4; - -import org.jaudiotagger.audio.generic.AbstractTag; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.mp4.field.*; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; - -import static org.jaudiotagger.tag.mp4.Mp4FieldKey.*; - -/** - * A Logical representation of Mp4Tag, i.e the meta information stored in an Mp4 file underneath the - * moov.udt.meta.ilst atom. - */ -public class Mp4Tag extends AbstractTag { - - private static final EnumMap tagFieldToMp4Field = new EnumMap(FieldKey.class); - - //Mapping from generic key to mp4 key - static { - tagFieldToMp4Field.put(FieldKey.ALBUM, Mp4FieldKey.ALBUM); - tagFieldToMp4Field.put(FieldKey.ALBUM_ARTIST, Mp4FieldKey.ALBUM_ARTIST); - tagFieldToMp4Field.put(FieldKey.ALBUM_ARTIST_SORT, Mp4FieldKey.ALBUM_ARTIST_SORT); - tagFieldToMp4Field.put(FieldKey.ALBUM_SORT, Mp4FieldKey.ALBUM_SORT); - tagFieldToMp4Field.put(FieldKey.AMAZON_ID, Mp4FieldKey.ASIN); - tagFieldToMp4Field.put(FieldKey.ARTIST, Mp4FieldKey.ARTIST); - tagFieldToMp4Field.put(FieldKey.ARTIST_SORT, Mp4FieldKey.ARTIST_SORT); - tagFieldToMp4Field.put(FieldKey.ARTISTS, Mp4FieldKey.ARTISTS); - tagFieldToMp4Field.put(FieldKey.BARCODE, Mp4FieldKey.BARCODE); - tagFieldToMp4Field.put(FieldKey.BPM, Mp4FieldKey.BPM); - tagFieldToMp4Field.put(FieldKey.CATALOG_NO, Mp4FieldKey.CATALOGNO); - tagFieldToMp4Field.put(FieldKey.COMMENT, Mp4FieldKey.COMMENT); - tagFieldToMp4Field.put(FieldKey.COMPOSER, Mp4FieldKey.COMPOSER); - tagFieldToMp4Field.put(FieldKey.COMPOSER_SORT, Mp4FieldKey.COMPOSER_SORT); - tagFieldToMp4Field.put(FieldKey.CONDUCTOR, Mp4FieldKey.CONDUCTOR); - tagFieldToMp4Field.put(FieldKey.COVER_ART, Mp4FieldKey.ARTWORK); - tagFieldToMp4Field.put(FieldKey.CUSTOM1, Mp4FieldKey.MM_CUSTOM_1); - tagFieldToMp4Field.put(FieldKey.CUSTOM2, Mp4FieldKey.MM_CUSTOM_2); - tagFieldToMp4Field.put(FieldKey.CUSTOM3, Mp4FieldKey.MM_CUSTOM_3); - tagFieldToMp4Field.put(FieldKey.CUSTOM4, Mp4FieldKey.MM_CUSTOM_4); - tagFieldToMp4Field.put(FieldKey.CUSTOM5, Mp4FieldKey.MM_CUSTOM_5); - tagFieldToMp4Field.put(FieldKey.DISC_NO, Mp4FieldKey.DISCNUMBER); - tagFieldToMp4Field.put(FieldKey.DISC_SUBTITLE, Mp4FieldKey.DISC_SUBTITLE); - tagFieldToMp4Field.put(FieldKey.DISC_TOTAL, Mp4FieldKey.DISCNUMBER); - tagFieldToMp4Field.put(FieldKey.ENCODER, Mp4FieldKey.ENCODER); - tagFieldToMp4Field.put(FieldKey.FBPM, Mp4FieldKey.FBPM); - tagFieldToMp4Field.put(FieldKey.GENRE, Mp4FieldKey.GENRE); - tagFieldToMp4Field.put(FieldKey.GROUPING, Mp4FieldKey.GROUPING); - tagFieldToMp4Field.put(FieldKey.ISRC, Mp4FieldKey.ISRC); - tagFieldToMp4Field.put(FieldKey.IS_COMPILATION, Mp4FieldKey.COMPILATION); - tagFieldToMp4Field.put(FieldKey.KEY, Mp4FieldKey.KEY); - tagFieldToMp4Field.put(FieldKey.LANGUAGE, Mp4FieldKey.LANGUAGE); - tagFieldToMp4Field.put(FieldKey.LYRICIST, Mp4FieldKey.LYRICIST); - tagFieldToMp4Field.put(FieldKey.LYRICS, Mp4FieldKey.LYRICS); - tagFieldToMp4Field.put(FieldKey.MEDIA, Mp4FieldKey.MEDIA); - tagFieldToMp4Field.put(FieldKey.MOOD, Mp4FieldKey.MOOD); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_ARTISTID, Mp4FieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_DISC_ID, Mp4FieldKey.MUSICBRAINZ_DISCID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, Mp4FieldKey.MUSICBRAINZ_ORIGINALALBUMID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, Mp4FieldKey.MUSICBRAINZ_ALBUMARTISTID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASEID, Mp4FieldKey.MUSICBRAINZ_ALBUMID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, Mp4FieldKey.RELEASECOUNTRY); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, Mp4FieldKey.MUSICBRAINZ_RELEASE_GROUPID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, Mp4FieldKey.MUSICBRAINZ_ALBUM_STATUS); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, Mp4FieldKey.MUSICBRAINZ_ALBUM_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_TRACK_ID, Mp4FieldKey.MUSICBRAINZ_TRACKID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_ID, Mp4FieldKey.MUSICBRAINZ_WORKID); - tagFieldToMp4Field.put(FieldKey.MUSICIP_ID, Mp4FieldKey.MUSICIP_PUID); - tagFieldToMp4Field.put(FieldKey.OCCASION, Mp4FieldKey.MM_OCCASION); - tagFieldToMp4Field.put(FieldKey.ORIGINAL_ALBUM, Mp4FieldKey.MM_ORIGINAL_ALBUM_TITLE); - tagFieldToMp4Field.put(FieldKey.ORIGINAL_ARTIST, Mp4FieldKey.MM_ORIGINAL_ARTIST); - tagFieldToMp4Field.put(FieldKey.ORIGINAL_LYRICIST, Mp4FieldKey.MM_ORIGINAL_LYRICIST); - tagFieldToMp4Field.put(FieldKey.ORIGINAL_YEAR, Mp4FieldKey.MM_ORIGINAL_YEAR); - tagFieldToMp4Field.put(FieldKey.QUALITY, Mp4FieldKey.MM_QUALITY); - tagFieldToMp4Field.put(FieldKey.RATING, Mp4FieldKey.SCORE); - tagFieldToMp4Field.put(FieldKey.RECORD_LABEL, Mp4FieldKey.LABEL); - tagFieldToMp4Field.put(FieldKey.REMIXER, Mp4FieldKey.REMIXER); - tagFieldToMp4Field.put(FieldKey.SCRIPT, Mp4FieldKey.SCRIPT); - tagFieldToMp4Field.put(FieldKey.SUBTITLE, Mp4FieldKey.SUBTITLE); - tagFieldToMp4Field.put(FieldKey.TAGS, Mp4FieldKey.TAGS); - tagFieldToMp4Field.put(FieldKey.TEMPO, Mp4FieldKey.TEMPO); - tagFieldToMp4Field.put(FieldKey.TITLE, Mp4FieldKey.TITLE); - tagFieldToMp4Field.put(FieldKey.TITLE_SORT, Mp4FieldKey.TITLE_SORT); - tagFieldToMp4Field.put(FieldKey.TRACK, Mp4FieldKey.TRACK); - tagFieldToMp4Field.put(FieldKey.TRACK_TOTAL, Mp4FieldKey.TRACK); - tagFieldToMp4Field.put(FieldKey.URL_DISCOGS_ARTIST_SITE, Mp4FieldKey.URL_DISCOGS_ARTIST_SITE); - tagFieldToMp4Field.put(FieldKey.URL_DISCOGS_RELEASE_SITE, Mp4FieldKey.URL_DISCOGS_RELEASE_SITE); - tagFieldToMp4Field.put(FieldKey.URL_LYRICS_SITE, Mp4FieldKey.URL_LYRICS_SITE); - tagFieldToMp4Field.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, Mp4FieldKey.URL_OFFICIAL_ARTIST_SITE); - tagFieldToMp4Field.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, Mp4FieldKey.URL_OFFICIAL_RELEASE_SITE); - tagFieldToMp4Field.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, Mp4FieldKey.URL_WIKIPEDIA_ARTIST_SITE); - tagFieldToMp4Field.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, Mp4FieldKey.URL_WIKIPEDIA_RELEASE_SITE); - tagFieldToMp4Field.put(FieldKey.YEAR, Mp4FieldKey.DAY); - tagFieldToMp4Field.put(FieldKey.ENGINEER, Mp4FieldKey.ENGINEER); - tagFieldToMp4Field.put(FieldKey.PRODUCER, Mp4FieldKey.PRODUCER); - tagFieldToMp4Field.put(FieldKey.DJMIXER, Mp4FieldKey.DJMIXER); - tagFieldToMp4Field.put(FieldKey.MIXER, Mp4FieldKey.MIXER); - tagFieldToMp4Field.put(FieldKey.ARRANGER, Mp4FieldKey.ARRANGER); - tagFieldToMp4Field.put(FieldKey.ACOUSTID_FINGERPRINT, Mp4FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToMp4Field.put(FieldKey.ACOUSTID_ID, Mp4FieldKey.ACOUSTID_ID); - tagFieldToMp4Field.put(FieldKey.COUNTRY, Mp4FieldKey.COUNTRY); - } - - /** - * Create genre field - *

    - *

    If the content can be parsed to one of the known values use the genre field otherwise - * use the custom field. - * - * @param content - * @return - */ - @SuppressWarnings({"JavaDoc"}) - private TagField createGenreField(String content) { - if (content == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - - //Always write as text - if (TagOptionSingleton.getInstance().isWriteMp4GenresAsText()) { - return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), content); - } - - if (Mp4GenreField.isValidGenre(content)) { - return new Mp4GenreField(content); - } else { - return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), content); - } - } - - protected boolean isAllowedEncoding(String enc) { - return enc.equals(Mp4BoxHeader.CHARSET_UTF_8); - } - - public String toString() { - return "Mpeg4 " + super.toString(); - } - - /** - * @param genericKey - * @return - */ - public boolean hasField(FieldKey genericKey) { - return getFields(genericKey).size() != 0; - } - - /** - * @param mp4FieldKey - * @return - */ - public boolean hasField(Mp4FieldKey mp4FieldKey) { - return getFields(mp4FieldKey.getFieldName()).size() != 0; - } - - /** - * Maps the generic key to the mp4 key and return the list of values for this field - * - * @param genericKey - */ - @SuppressWarnings({"JavaDoc"}) - public List getFields(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - Mp4FieldKey mp4FieldKey = tagFieldToMp4Field.get(genericKey); - List list = getFields(mp4FieldKey.getFieldName()); - List filteredList = new ArrayList(); - - if (genericKey == FieldKey.GENRE) { - if (list.size() == 0) { - list = getFields(GENRE_CUSTOM.getFieldName()); - } - return list; - } else if (genericKey == FieldKey.TRACK) { - for (TagField next : list) { - Mp4TrackField trackField = (Mp4TrackField) next; - if (trackField.getTrackNo() > 0) { - filteredList.add(next); - } - } - return filteredList; - } else if (genericKey == FieldKey.TRACK_TOTAL) { - for (TagField next : list) { - Mp4TrackField trackField = (Mp4TrackField) next; - if (trackField.getTrackTotal() > 0) { - filteredList.add(next); - } - } - return filteredList; - } else if (genericKey == FieldKey.DISC_NO) { - for (TagField next : list) { - Mp4DiscNoField discNoField = (Mp4DiscNoField) next; - if (discNoField.getDiscNo() > 0) { - filteredList.add(next); - } - } - return filteredList; - } else if (genericKey == FieldKey.DISC_TOTAL) { - for (TagField next : list) { - Mp4DiscNoField discNoField = (Mp4DiscNoField) next; - if (discNoField.getDiscTotal() > 0) { - filteredList.add(next); - } - } - return filteredList; - } else { - return list; - } - } - - /** - * Maps the generic key to the specific key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - List values = new ArrayList(); - List fields = getFields(genericKey); - for (TagField tagfield : fields) { - if (genericKey == FieldKey.TRACK) { - values.add(((Mp4TrackField) tagfield).getTrackNo().toString()); - } else if (genericKey == FieldKey.TRACK_TOTAL) { - values.add(((Mp4TrackField) tagfield).getTrackTotal().toString()); - } else if (genericKey == FieldKey.DISC_NO) { - values.add(((Mp4DiscNoField) tagfield).getDiscNo().toString()); - } else if (genericKey == FieldKey.DISC_TOTAL) { - values.add(((Mp4DiscNoField) tagfield).getDiscTotal().toString()); - } else { - values.add(tagfield.toString()); - } - } - return values; - } - - /** - * Retrieve the values that exists for this mp4keyId (this is the internalid actually used) - *

    - * - * @param mp4FieldKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public List get(Mp4FieldKey mp4FieldKey) throws KeyNotFoundException { - if (mp4FieldKey == null) { - throw new KeyNotFoundException(); - } - return super.getFields(mp4FieldKey.getFieldName()); - } - - /** - * Retrieve the indexed value that exists for this generic key - * - * @param genericKey - * @return - */ - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException { - List fields = getFields(genericKey); - if (fields.size() > index) { - TagField field = fields.get(index); - if (genericKey == FieldKey.TRACK) { - return ((Mp4TrackField) field).getTrackNo().toString(); - } else if (genericKey == FieldKey.DISC_NO) { - return ((Mp4DiscNoField) field).getDiscNo().toString(); - } else if (genericKey == FieldKey.TRACK_TOTAL) { - return ((Mp4TrackField) field).getTrackTotal().toString(); - } else if (genericKey == FieldKey.DISC_TOTAL) { - return ((Mp4DiscNoField) field).getDiscTotal().toString(); - } else { - return field.toString(); - } - } - return ""; - } - - /** - * Retrieve the first value that exists for this mp4key - * - * @param mp4Key - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public String getFirst(Mp4FieldKey mp4Key) throws KeyNotFoundException { - if (mp4Key == null) { - throw new KeyNotFoundException(); - } - return super.getFirst(mp4Key.getFieldName()); - } - - public Mp4TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException { - List fields = getFields(genericKey); - if (fields.size() == 0) { - return null; - } - return (Mp4TagField) fields.get(0); - } - - public Mp4TagField getFirstField(Mp4FieldKey mp4Key) throws KeyNotFoundException { - if (mp4Key == null) { - throw new KeyNotFoundException(); - } - return (Mp4TagField) super.getFirstField(mp4Key.getFieldName()); - } - - /** - * Delete fields with this generic key - * - * @param genericKey - */ - public void deleteField(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - String mp4FieldName = tagFieldToMp4Field.get(genericKey).getFieldName(); - if (genericKey == FieldKey.TRACK) { - String trackTotal = this.getFirst(FieldKey.TRACK_TOTAL); - if (trackTotal.length() == 0) { - super.deleteField(mp4FieldName); - return; - } else { - Mp4TrackField field = (Mp4TrackField) this.getFirstField(FieldKey.TRACK_TOTAL); - field.setTrackNo(0); - return; - } - } else if (genericKey == FieldKey.TRACK_TOTAL) { - String track = this.getFirst(FieldKey.TRACK); - if (track.length() == 0) { - super.deleteField(mp4FieldName); - return; - } else { - Mp4TrackField field = (Mp4TrackField) this.getFirstField(FieldKey.TRACK); - field.setTrackTotal(0); - return; - } - } else if (genericKey == FieldKey.DISC_NO) { - String discTotal = this.getFirst(FieldKey.DISC_TOTAL); - if (discTotal.length() == 0) { - super.deleteField(mp4FieldName); - return; - } else { - Mp4DiscNoField field = (Mp4DiscNoField) this.getFirstField(FieldKey.DISC_TOTAL); - field.setDiscNo(0); - return; - } - } else if (genericKey == FieldKey.DISC_TOTAL) { - String discno = this.getFirst(FieldKey.DISC_NO); - if (discno.length() == 0) { - super.deleteField(mp4FieldName); - return; - } else { - Mp4DiscNoField field = (Mp4DiscNoField) this.getFirstField(FieldKey.DISC_NO); - field.setDiscTotal(0); - return; - } - } else { - super.deleteField(mp4FieldName); - } - } - - /** - * Delete fields with this mp4key - * - * @param mp4Key - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(Mp4FieldKey mp4Key) throws KeyNotFoundException { - if (mp4Key == null) { - throw new KeyNotFoundException(); - } - super.deleteField(mp4Key.getFieldName()); - } - - /** - * Create artwork field - * - * @param data raw image data - * @return - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public TagField createArtworkField(byte[] data) { - return new Mp4TagCoverField(data); - } - - /** - * Create artwork field - * - * @return - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - return new Mp4TagCoverField(artwork.getBinaryData()); - } - - /** - * Create new field and add it to the tag, with special handling for trackNo, discNo fields as we dont want multiple - * fields to be created for these fields - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if ( - (genericKey == FieldKey.TRACK) || - (genericKey == FieldKey.TRACK_TOTAL) || - (genericKey == FieldKey.DISC_NO) || - (genericKey == FieldKey.DISC_TOTAL) - ) { - setField(genericKey, value); - } else { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - } - - /** - * Create Tag Field using generic key - *

    - * This should use the correct subclass for the key - * - * @param genericKey - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (value == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - if (genericKey == null) { - throw new KeyNotFoundException(); - } - - //Special handling for these number fields - if ( - (genericKey == FieldKey.TRACK) || - (genericKey == FieldKey.TRACK_TOTAL) || - (genericKey == FieldKey.DISC_NO) || - (genericKey == FieldKey.DISC_TOTAL) - ) { - try { - int number = Integer.parseInt(value); - if (genericKey == FieldKey.TRACK) { - return new Mp4TrackField(number); - } else if (genericKey == FieldKey.TRACK_TOTAL) { - return new Mp4TrackField(0, number); - } else if (genericKey == FieldKey.DISC_NO) { - return new Mp4DiscNoField(number); - } else if (genericKey == FieldKey.DISC_TOTAL) { - return new Mp4DiscNoField(0, number); - } - } catch (NumberFormatException nfe) { - //If not number we want to convert to an expected exception (which is not a RuntimeException) - //so can be handled properly by calling program - throw new FieldDataInvalidException("Value " + value + " is not a number as required", nfe); - } - } - - //Default for all other fields - return createField(tagFieldToMp4Field.get(genericKey), value); - } - - /** - * Set field, special handling for track and disc because they hold two fields - * - * @param field - */ - @Override - public void setField(TagField field) { - if (field == null) { - return; - } - - if (field.getId().equals(TRACK.getFieldName())) { - List list = fields.get(field.getId()); - if (list == null || list.size() == 0) { - super.setField(field); - } else { - Mp4TrackField existingTrackField = (Mp4TrackField) list.get(0); - Mp4TrackField newTrackField = (Mp4TrackField) field; - Short trackNo = existingTrackField.getTrackNo(); - Short trackTotal = existingTrackField.getTrackTotal(); - if (newTrackField.getTrackNo() > 0) { - trackNo = newTrackField.getTrackNo(); - } - if (newTrackField.getTrackTotal() > 0) { - trackTotal = newTrackField.getTrackTotal(); - } - - Mp4TrackField mergedTrackField = new Mp4TrackField(trackNo, trackTotal); - super.setField(mergedTrackField); - } - } else if (field.getId().equals(DISCNUMBER.getFieldName())) { - List list = fields.get(field.getId()); - if (list == null || list.size() == 0) { - super.setField(field); - } else { - Mp4DiscNoField existingDiscNoField = (Mp4DiscNoField) list.get(0); - Mp4DiscNoField newDiscNoField = (Mp4DiscNoField) field; - Short discNo = existingDiscNoField.getDiscNo(); - Short discTotal = existingDiscNoField.getDiscTotal(); - if (newDiscNoField.getDiscNo() > 0) { - discNo = newDiscNoField.getDiscNo(); - } - if (newDiscNoField.getDiscTotal() > 0) { - discTotal = newDiscNoField.getDiscTotal(); - } - - Mp4DiscNoField mergedDiscNoField = new Mp4DiscNoField(discNo, discTotal); - super.setField(mergedDiscNoField); - } - } else { - super.setField(field); - } - } - - /** - * Create Tag Field using mp4 key - *

    - * Uses the correct subclass for the key - * - * @param mp4FieldKey - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public TagField createField(Mp4FieldKey mp4FieldKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (value == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - if (mp4FieldKey == null) { - throw new KeyNotFoundException(); - } - - //This is boolean stored as 1, but calling program might setField as 'true' so we handle this - //case internally - if (mp4FieldKey == Mp4FieldKey.COMPILATION) { - if (value.equals("true")) { - value = Mp4TagByteField.TRUE_VALUE; - } - return new Mp4TagByteField(mp4FieldKey, value, mp4FieldKey.getFieldLength()); - } else if (mp4FieldKey == Mp4FieldKey.GENRE) { - return createGenreField(value); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.DISC_NO) { - return new Mp4DiscNoField(value); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.TRACK_NO) { - return new Mp4TrackField(value); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.BYTE) { - return new Mp4TagByteField(mp4FieldKey, value, mp4FieldKey.getFieldLength()); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.NUMBER) { - return new Mp4TagTextNumberField(mp4FieldKey.getFieldName(), value); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.REVERSE_DNS) { - return new Mp4TagReverseDnsField(mp4FieldKey, value); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.ARTWORK) { - throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg()); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.TEXT) { - return new Mp4TagTextField(mp4FieldKey.getFieldName(), value); - } else if (mp4FieldKey.getSubClassFieldType() == Mp4TagFieldSubType.UNKNOWN) { - throw new UnsupportedOperationException(ErrorMessage.DO_NOT_KNOW_HOW_TO_CREATE_THIS_ATOM_TYPE.getMsg(mp4FieldKey.getFieldName())); - } else { - throw new UnsupportedOperationException(ErrorMessage.DO_NOT_KNOW_HOW_TO_CREATE_THIS_ATOM_TYPE.getMsg(mp4FieldKey.getFieldName())); - } - } - - public List getArtworkList() { - List coverartList = get(Mp4FieldKey.ARTWORK); - List artworkList = new ArrayList(coverartList.size()); - - for (TagField next : coverartList) { - Mp4TagCoverField mp4CoverArt = (Mp4TagCoverField) next; - Artwork artwork = ArtworkFactory.getNew(); - artwork.setBinaryData(mp4CoverArt.getData()); - artwork.setMimeType(Mp4TagCoverField.getMimeTypeForImageType(mp4CoverArt.getFieldType())); - artworkList.add(artwork); - } - return artworkList; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagCreator.java b/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagCreator.java deleted file mode 100644 index aa30c60..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagCreator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4; - -import org.jaudiotagger.audio.generic.AbstractTagCreator; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.Mp4AtomIdentifier; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.FieldKey; -import org.jaudiotagger.tag.KeyNotFoundException; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.mp4.field.Mp4TagCoverField; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.Iterator; - -/** - * Create raw content of mp4 tag data, concerns itself with atoms upto the ilst atom - *

    - *

    This level is was selected because the ilst atom can be recreated without reference to existing mp4 fields - * but fields above this level are dependent upon other information that is not held in the tag. - *

    - *

    - * |--- ftyp
    - * |--- moov
    - * |......|
    - * |......|----- mvdh
    - * |......|----- trak
    - * |......|----- udta
    - * |..............|
    - * |..............|-- meta
    - * |....................|
    - * |....................|-- hdlr
    - * |....................|-- ilst
    - * |....................|.. ..|
    - * |....................|.....|---- @nam (Optional for each metadatafield)
    - * |....................|.....|.......|-- data
    - * |....................|.....|....... ecetera
    - * |....................|.....|---- ---- (Optional for reverse dns field)
    - * |....................|.............|-- mean
    - * |....................|.............|-- name
    - * |....................|.............|-- data
    - * |....................|................ ecetere
    - * |....................|-- free
    - * |--- free
    - * |--- mdat
    - * 
    - */ -public class Mp4TagCreator extends AbstractTagCreator { - /** - * Convert tagdata to rawdata ready for writing to file - * - * @param tag - * @param padding TODO padding parameter currently ignored - * @return - * @throws UnsupportedEncodingException - */ - public ByteBuffer convert(Tag tag, int padding) throws UnsupportedEncodingException { - try { - //Add metadata raw content - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Iterator it = tag.getFields(); - boolean processedArtwork = false; - while (it.hasNext()) { - TagField frame = it.next(); - //To ensure order is maintained dont process artwork until iterator hits it. - if (frame instanceof Mp4TagCoverField) { - if (processedArtwork) { - //ignore - } else { - processedArtwork = true; - - //Because each artwork image is held within the tag as a separate field, but when - //they are written they are all held under a single covr box we need to do some checks - //and special processing here if we have any artwork image (this code only necessary - //if we have more than 1 but do it anyway even if only have 1 image) - ByteArrayOutputStream covrDataBaos = new ByteArrayOutputStream(); - - try { - for (TagField artwork : tag.getFields(FieldKey.COVER_ART)) { - covrDataBaos.write(((Mp4TagField) artwork).getRawContentDataOnly()); - } - } catch (KeyNotFoundException knfe) { - //This cannot happen - throw new RuntimeException("Unable to find COVERART Key"); - } - - //Now create the parent Data - byte[] data = covrDataBaos.toByteArray(); - baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + data.length)); - baos.write(Utils.getDefaultBytes(Mp4FieldKey.ARTWORK.getFieldName(), "ISO-8859-1")); - baos.write(data); - } - } else { - baos.write(frame.getRawContent()); - } - } - - //Wrap into ilst box - ByteArrayOutputStream ilst = new ByteArrayOutputStream(); - ilst.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size())); - ilst.write(Utils.getDefaultBytes(Mp4AtomIdentifier.ILST.getFieldName(), "ISO-8859-1")); - ilst.write(baos.toByteArray()); - - //Put into ByteBuffer - ByteBuffer buf = ByteBuffer.wrap(ilst.toByteArray()); - buf.rewind(); - return buf; - } catch (IOException ioe) { - //Should never happen as not writing to file at this point - throw new RuntimeException(ioe); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagField.java b/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagField.java deleted file mode 100644 index f62337a..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagField.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import org.jaudiotagger.tag.mp4.field.Mp4FieldType; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * This abstract class represents a link between piece of data, and how it is stored as an mp4 atom - *

    - * Note there isnt a one to one correspondance between a tag field and a box because some fields are represented - * by multiple boxes, for example many of the MusicBrainz fields use the '----' box, which in turn uses one of mean, - * name and data box. So an instance of a tag field maps to one item of data such as 'Title', but it may have to read - * multiple boxes to do this. - *

    - * There are various subclasses that represent different types of fields - */ -public abstract class Mp4TagField implements TagField { - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.mp4"); - - - protected String id; - - //Just used by reverese dns class, so it knows the size of its aprent so it can detect end correctly - protected Mp4BoxHeader parentHeader; - - protected Mp4TagField(String id) { - this.id = id; - } - - /** - * Used by subclasses that canot identify their id until after they have been built such as ReverseDnsField - * - * @param data - * @throws UnsupportedEncodingException - */ - protected Mp4TagField(ByteBuffer data) throws UnsupportedEncodingException { - build(data); - } - - /** - * Used by reverese dns when reading from file, so can identify when there is a data atom - * - * @param parentHeader - * @param data - * @throws UnsupportedEncodingException - */ - protected Mp4TagField(Mp4BoxHeader parentHeader, ByteBuffer data) throws UnsupportedEncodingException { - this.parentHeader = parentHeader; - build(data); - } - - protected Mp4TagField(String id, ByteBuffer data) throws UnsupportedEncodingException { - this(id); - build(data); - } - - /** - * @return field identifier - */ - public String getId() { - return id; - } - - public void isBinary(boolean b) { - /* One cannot choose if an arbitrary block can be binary or not */ - } - - public boolean isCommon() { - return id.equals(Mp4FieldKey.ARTIST.getFieldName()) || id.equals(Mp4FieldKey.ALBUM.getFieldName()) || id.equals(Mp4FieldKey.TITLE.getFieldName()) || id.equals(Mp4FieldKey.TRACK.getFieldName()) || id.equals(Mp4FieldKey.DAY.getFieldName()) || id.equals(Mp4FieldKey.COMMENT.getFieldName()) || id.equals(Mp4FieldKey.GENRE.getFieldName()); - } - - /** - * @return field identifier as it will be held within the file - */ - protected byte[] getIdBytes() { - return Utils.getDefaultBytes(getId(), "ISO-8859-1"); - } - - /** - * @return the data as it is held on file - * @throws UnsupportedEncodingException - */ - protected abstract byte[] getDataBytes() throws UnsupportedEncodingException; - - - /** - * @return the field type of this field - */ - public abstract Mp4FieldType getFieldType(); - - /** - * Processes the data and sets the position of the data buffer to just after the end of this fields data - * ready for processing next field. - * - * @param data - * @throws UnsupportedEncodingException - */ - protected abstract void build(ByteBuffer data) throws UnsupportedEncodingException; - - /** - * Convert back to raw content, includes parent and data atom as views as one thing externally - * - * @return - * @throws UnsupportedEncodingException - */ - public byte[] getRawContent() throws UnsupportedEncodingException { - logger.fine("Getting Raw data for:" + getId()); - try { - //Create Data Box - byte[] databox = getRawContentDataOnly(); - - //Wrap in Parent box - ByteArrayOutputStream outerbaos = new ByteArrayOutputStream(); - outerbaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + databox.length)); - outerbaos.write(Utils.getDefaultBytes(getId(), "ISO-8859-1")); - outerbaos.write(databox); - return outerbaos.toByteArray(); - } catch (IOException ioe) { - //This should never happen as were not actually writing to/from a file - throw new RuntimeException(ioe); - } - } - - /** - * Get raw content for the data component only - * - * @return - * @throws UnsupportedEncodingException - */ - public byte[] getRawContentDataOnly() throws UnsupportedEncodingException { - logger.fine("Getting Raw data for:" + getId()); - try { - //Create Data Box - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] data = getDataBytes(); - baos.write(Utils.getSizeBEInt32(Mp4DataBox.DATA_HEADER_LENGTH + data.length)); - baos.write(Utils.getDefaultBytes(Mp4DataBox.IDENTIFIER, "ISO-8859-1")); - baos.write(new byte[]{0}); - baos.write(new byte[]{0, 0, (byte) getFieldType().getFileClassId()}); - baos.write(new byte[]{0, 0, 0, 0}); - baos.write(data); - return baos.toByteArray(); - } catch (IOException ioe) { - //This should never happen as were not actually writing to/from a file - throw new RuntimeException(ioe); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java b/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java deleted file mode 100644 index dea026e..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.jaudiotagger.tag.mp4; - -/** - * Defines the available types of Mp4TagField, this simplifies Mp4 code because when we add a new Mp4FieldKey we can - * define the correct type instead of having to add additional code to Mp4tag.createField method - */ -public enum Mp4TagFieldSubType { - TEXT, - BYTE, - NUMBER, - REVERSE_DNS, - GENRE, - DISC_NO, - TRACK_NO, - ARTWORK, - UNKNOWN -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java b/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java deleted file mode 100644 index e6aae5e..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.jaudiotagger.tag.mp4.atom; - - -/** - * List of valid values for the Content Type (Stik) atom - *

    - *

    These are held as a byte field, normally only used for purcahed items, audio files use a stik of one - */ -public enum Mp4ContentTypeValue { - MOVIE("Movie", 0), - NORMAL("Normal", 1), - AUDIO_BOOK("AudioBook", 2), - BOOKMARK("Whacked Bookmark", 5), - MUSIC_VIDEO("Music Video", 6), - SHORT_FILM("Short Film", 9), - TV_SHOW("TV Show", 10), - BOOKLET("Booklet", 11); - - private String description; - private int id; - - - /** - * @param description of value - * @param id used internally - */ - Mp4ContentTypeValue(String description, int id) { - this.description = description; - this.id = id; - } - - /** - * Return id used in the file - * - * @return id - */ - public int getId() { - return id; - } - - /** - * @return the id as a string (convenience method for use with mp4.createtagField() - */ - public String getIdAsString() { - return String.valueOf(id); - } - - /** - * This is the value of the fieldname that is actually used to write mp4 - * - * @return - */ - public String getDescription() { - return description; - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4DataBox.java b/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4DataBox.java deleted file mode 100644 index 34facb4..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4DataBox.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.jaudiotagger.tag.mp4.atom; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.AbstractMp4Box; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.mp4.field.Mp4FieldType; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -/** - * This box is used within both normal metadat boxes and ---- boxes to hold the actual data. - *

    - *

    Format is as follows: - * :length (4 bytes) - * :name 'Data' (4 bytes) - * :atom version (1 byte) - * :atom type flags (3 bytes) - * :locale field (4 bytes) //Currently always zero - * :data - */ -public class Mp4DataBox extends AbstractMp4Box { - public static final String IDENTIFIER = "data"; - - public static final int VERSION_LENGTH = 1; - public static final int TYPE_LENGTH = 3; - public static final int NULL_LENGTH = 4; - public static final int PRE_DATA_LENGTH = VERSION_LENGTH + TYPE_LENGTH + NULL_LENGTH; - public static final int DATA_HEADER_LENGTH = Mp4BoxHeader.HEADER_LENGTH + PRE_DATA_LENGTH; - - public static final int TYPE_POS = VERSION_LENGTH; - - //For use externally - public static final int TYPE_POS_INCLUDING_HEADER = Mp4BoxHeader.HEADER_LENGTH + TYPE_POS; - public static final int NUMBER_LENGTH = 2; - private int type; - private String content; - //Holds the numbers decoded - private List numbers; - - //Holds bytedata for byte fields as is not clear for multibyte fields exactly these should be wrttien - private byte[] bytedata; - - /** - * @param header parentHeader info - * @param dataBuffer data of box (doesnt include parentHeader data) - */ - public Mp4DataBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - //Double check - if (!header.getId().equals(IDENTIFIER)) { - throw new RuntimeException("Unable to process data box because identifier is:" + header.getId()); - } - - //Make slice so operations here don't effect position of main buffer - this.dataBuffer = dataBuffer.slice(); - - //Type - type = Utils.getIntBE(this.dataBuffer, Mp4DataBox.TYPE_POS, Mp4DataBox.TYPE_POS + Mp4DataBox.TYPE_LENGTH - 1); - - if (type == Mp4FieldType.TEXT.getFileClassId()) { - content = Utils.getString(this.dataBuffer, PRE_DATA_LENGTH, header.getDataLength() - PRE_DATA_LENGTH, header.getEncoding()); - } else if (type == Mp4FieldType.IMPLICIT.getFileClassId()) { - numbers = new ArrayList(); - - for (int i = 0; i < ((header.getDataLength() - PRE_DATA_LENGTH) / NUMBER_LENGTH); i++) { - short number = Utils.getShortBE(this.dataBuffer, PRE_DATA_LENGTH + (i * NUMBER_LENGTH), PRE_DATA_LENGTH + (i * NUMBER_LENGTH) + (NUMBER_LENGTH - 1)); - numbers.add(number); - } - - //Make String representation (separate values with slash) - StringBuffer sb = new StringBuffer(); - ListIterator iterator = numbers.listIterator(); - while (iterator.hasNext()) { - sb.append(iterator.next()); - if (iterator.hasNext()) { - sb.append("/"); - } - } - content = sb.toString(); - } else if (type == Mp4FieldType.INTEGER.getFileClassId()) { - //TODO byte data length seems to be 1 for pgap and cpil but 2 for tmpo ? - //Create String representation for display - content = Utils.getIntBE(this.dataBuffer, PRE_DATA_LENGTH, header.getDataLength() - 1) + ""; - - //But store data for safer writing back to file - bytedata = new byte[header.getDataLength() - PRE_DATA_LENGTH]; - int pos = dataBuffer.position(); - dataBuffer.position(pos + PRE_DATA_LENGTH); - dataBuffer.get(bytedata); - dataBuffer.position(pos); - - //Songbird uses this type for trkn atom (normally implicit type) is used so just added this code so can be used - //by the Mp4TrackField atom - numbers = new ArrayList(); - for (int i = 0; i < ((header.getDataLength() - PRE_DATA_LENGTH) / NUMBER_LENGTH); i++) { - short number = Utils.getShortBE(this.dataBuffer, PRE_DATA_LENGTH + (i * NUMBER_LENGTH), PRE_DATA_LENGTH + (i * NUMBER_LENGTH) + (NUMBER_LENGTH - 1)); - numbers.add(number); - } - - } else if (type == Mp4FieldType.COVERART_JPEG.getFileClassId()) { - content = Utils.getString(this.dataBuffer, PRE_DATA_LENGTH, header.getDataLength() - PRE_DATA_LENGTH, header.getEncoding()); - } - } - - public String getContent() { - return content; - } - - public int getType() { - - return type; - } - - /** - * Return numbers, only valid for numeric fields - * - * @return numbers - */ - //TODO this is only applicable for numeric databoxes, should we subclass dont know type until start - //constructing and we also have Mp4tagTextNumericField class as well - public List getNumbers() { - return numbers; - } - - /** - * Return raw byte data only vaid for byte fields - * - * @return byte data - */ - public byte[] getByteData() { - return bytedata; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java b/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java deleted file mode 100644 index e894bfb..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.jaudiotagger.tag.mp4.atom; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.AbstractMp4Box; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; - -import java.nio.ByteBuffer; - -/** - * This box is used within ---- boxes to hold the issuer - */ -public class Mp4MeanBox extends AbstractMp4Box { - public static final String IDENTIFIER = "mean"; - //TODO Are these misnamed, are these version flag bytes or just null bytes - public static final int VERSION_LENGTH = 1; - public static final int FLAGS_LENGTH = 3; - public static final int PRE_DATA_LENGTH = VERSION_LENGTH + FLAGS_LENGTH; - private String issuer; - - /** - * @param header parentHeader info - * @param dataBuffer data of box (doesnt include parentHeader data) - */ - public Mp4MeanBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - - //Double check - if (!header.getId().equals(IDENTIFIER)) { - throw new RuntimeException("Unable to process data box because identifier is:" + header.getId()); - } - - //Make slice so operations here don't effect position of main buffer - this.dataBuffer = dataBuffer.slice(); - - //issuer - this.issuer = Utils.getString(this.dataBuffer, PRE_DATA_LENGTH, header.getDataLength() - PRE_DATA_LENGTH, header.getEncoding()); - - } - - public String getIssuer() { - return issuer; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4NameBox.java b/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4NameBox.java deleted file mode 100644 index 258fab5..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4NameBox.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jaudiotagger.tag.mp4.atom; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.AbstractMp4Box; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; - -import java.nio.ByteBuffer; - -/** - * This box is used within ---- boxes to hold the data name/descriptor - */ -public class Mp4NameBox extends AbstractMp4Box { - public static final String IDENTIFIER = "name"; - //TODO Are these misnamed, are these version flag bytes or just null bytes - public static final int VERSION_LENGTH = 1; - public static final int FLAGS_LENGTH = 3; - public static final int PRE_DATA_LENGTH = VERSION_LENGTH + FLAGS_LENGTH; - private String name; - - /** - * @param header parentHeader info - * @param dataBuffer data of box (doesnt include parentHeader data) - */ - public Mp4NameBox(Mp4BoxHeader header, ByteBuffer dataBuffer) { - this.header = header; - - //Double check - if (!header.getId().equals(IDENTIFIER)) { - throw new RuntimeException("Unable to process name box because identifier is:" + header.getId()); - } - - //Make slice so operations here don't effect position of main buffer - this.dataBuffer = dataBuffer.slice(); - - //issuer - this.name = Utils.getString(this.dataBuffer, PRE_DATA_LENGTH, header.getDataLength() - PRE_DATA_LENGTH, header.getEncoding()); - } - - public String getName() { - return name; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java b/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java deleted file mode 100644 index f81d75a..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.jaudiotagger.tag.mp4.atom; - -/** - * List of valid values for the Rating (rtng) atom - *

    - * These are held as a byte field - *

    - * TODO:Is this only used in video - */ -public enum Mp4RatingValue { - CLEAN("Clean", 2), - EXPLICIT("Explicit", 4); - - private String description; - private int id; - - - /** - * @param description of value - * @param id used internally - */ - Mp4RatingValue(String description, int id) { - this.description = description; - this.id = id; - } - - /** - * Return id used in the file - * - * @return id - */ - public int getId() { - return id; - } - - /** - * This is the value of the fieldname that is actually used to write mp4 - * - * @return - */ - public String getDescription() { - return description; - } - - -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/atom/package.html b/src/main/java/org/jaudiotagger/tag/mp4/atom/package.html deleted file mode 100644 index 9ca42ae..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/atom/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes dealing with atoms (boxes) embedded in top-level MP4 atoms. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java deleted file mode 100644 index 261f4a1..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.FieldDataInvalidException; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.ArrayList; - -/** - * Represents the Disc No field - *

    - *

    Contains some reserved fields that we currently ignore - *

    - * Reserved:2 bytes - * Disc Number:2 bytes - * Total no of Discs:2 bytes - *

    - */ -public class Mp4DiscNoField extends Mp4TagTextNumberField { - private static final int NONE_VALUE_INDEX = 0; - private static final int DISC_NO_INDEX = 1; - private static final int DISC_TOTAL_INDEX = 2; - - /** - * Create new Disc Field parsing the String for the discno/total - * - * @param discValue - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public Mp4DiscNoField(String discValue) throws FieldDataInvalidException { - super(Mp4FieldKey.DISCNUMBER.getFieldName(), discValue); - - numbers = new ArrayList(); - numbers.add(new Short("0")); - - String values[] = discValue.split("/"); - switch (values.length) { - case 1: - - try { - numbers.add(Short.parseShort(values[0])); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + values[0] + " is invalid for field:" + id); - } - numbers.add(new Short("0")); - break; - - case 2: - try { - numbers.add(Short.parseShort(values[0])); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + values[0] + " is invalid for field:" + id); - } - try { - numbers.add(Short.parseShort(values[1])); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + values[1] + " is invalid for field:" + id); - } - break; - - default: - throw new FieldDataInvalidException("Value is invalid for field:" + id); - } - } - - - /** - * Create new Disc No field with only discNo - * - * @param discNo - */ - public Mp4DiscNoField(int discNo) { - super(Mp4FieldKey.DISCNUMBER.getFieldName(), String.valueOf(discNo)); - numbers = new ArrayList(); - numbers.add(new Short("0")); - numbers.add((short) discNo); - numbers.add(new Short("0")); - } - - /** - * Create new Disc No Field with Disc No and total number of discs - * - * @param discNo - * @param total - */ - public Mp4DiscNoField(int discNo, int total) { - super(Mp4FieldKey.DISCNUMBER.getFieldName(), String.valueOf(discNo)); - numbers = new ArrayList(); - numbers.add(new Short("0")); - numbers.add((short) discNo); - numbers.add((short) total); - } - - public Mp4DiscNoField(String id, ByteBuffer data) throws UnsupportedEncodingException { - super(id, data); - } - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Data actually contains a 'Data' Box so process data using this - Mp4BoxHeader header = new Mp4BoxHeader(data); - Mp4DataBox databox = new Mp4DataBox(header, data); - dataSize = header.getDataLength(); - numbers = databox.getNumbers(); - - //Disc number always hold four values, we can discard the first one and last one, the second one is the disc no - //and the third is the total no of discs so only use if not zero - StringBuffer sb = new StringBuffer(); - if ((numbers.size() > DISC_NO_INDEX) && (numbers.get(DISC_NO_INDEX) > 0)) { - sb.append(numbers.get(DISC_NO_INDEX)); - } - if ((numbers.size() > DISC_TOTAL_INDEX) && (numbers.get(DISC_TOTAL_INDEX) > 0)) { - sb.append("/").append(numbers.get(DISC_TOTAL_INDEX)); - } - content = sb.toString(); - } - - /** - * @return - */ - public Short getDiscNo() { - return numbers.get(DISC_NO_INDEX); - } - - /** - * Set Disc No - * - * @param discNo - */ - public void setDiscNo(int discNo) { - numbers.set(DISC_NO_INDEX, (short) discNo); - } - - /** - * @return - */ - public Short getDiscTotal() { - if (numbers.size() <= DISC_TOTAL_INDEX) { - return 0; - } - return numbers.get(DISC_TOTAL_INDEX); - } - - /** - * Set total number of discs - * - * @param discTotal - */ - public void setDiscTotal(int discTotal) { - numbers.set(DISC_TOTAL_INDEX, (short) discTotal); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4FieldType.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4FieldType.java deleted file mode 100644 index c6275f5..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4FieldType.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import java.util.EnumSet; -import java.util.HashMap; - -/** - * Describes the possible types of data held within a Databox - */ -public enum Mp4FieldType { - IMPLICIT(0x0), //used for specialized formats such as TrackNo or DiscNo - TEXT(0x1), //UTF-8 - TEXT_UTF16BE(0x02), - TEXT_JAPANESE(0x03), - HTML(0x06), - XML(0x07), - GUID(0x08), - ISRC(0x09), - MI3P(0x0a), - COVERART_GIF(0x0c), - COVERART_JPEG(0x0d), - COVERART_PNG(0x0e), - URL(0x0f), - DURATION(0x10), - DATETIME(0x11), - GENRES(0x12), - INTEGER(0x15), //Formally known as byte - RIAAPA(0x18), - UPC(0x19), - COVERART_BMP(0x1B),; - - - private final static HashMap fileClassIdFiedTypeMap; - private static EnumSet coverArtTypes; - - static { - fileClassIdFiedTypeMap = new HashMap(Mp4FieldType.values().length); - for (Mp4FieldType curr : Mp4FieldType.values()) { - fileClassIdFiedTypeMap.put(curr.fileClassId, curr); - } - } - - static { - coverArtTypes = EnumSet.of(COVERART_GIF, COVERART_JPEG, COVERART_PNG, COVERART_BMP); - } - - private int fileClassId; - - Mp4FieldType(int fileClassId) { - this.fileClassId = fileClassId; - } - - /** - * @param fieldClassId - * @return the Mp4FieldType that this fieldClassId maps to - */ - public static Mp4FieldType getFieldType(int fieldClassId) { - return fileClassIdFiedTypeMap.get(fieldClassId); - } - - /** - * @param mp4FieldType - * @return true if this type is for identifying a image format to be used in cover art - */ - public static boolean isCoverArtType(Mp4FieldType mp4FieldType) { - return coverArtTypes.contains(mp4FieldType); - } - - public int getFileClassId() { - return fileClassId; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4GenreField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4GenreField.java deleted file mode 100644 index f304b21..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4GenreField.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import org.jaudiotagger.tag.reference.GenreTypes; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.ArrayList; - -/** - * Represents the Genre field , when user has selected from the set list of genres - *

    - *

    This class allows you to retrieve either the internal genreid, or the display value - */ -public class Mp4GenreField extends Mp4TagTextNumberField { - public Mp4GenreField(String id, ByteBuffer data) throws UnsupportedEncodingException { - super(id, data); - } - - /** - * Construct genre, if cant find match just default to first genre - * - * @param genreId key into ID3v1 list (offset by one) or String value in ID3list - */ - public Mp4GenreField(String genreId) { - super(Mp4FieldKey.GENRE.getFieldName(), genreId); - - //Is it an id - try { - short genreVal = Short.parseShort(genreId); - if ((genreVal - 1) <= GenreTypes.getMaxStandardGenreId()) { - numbers = new ArrayList(); - numbers.add(genreVal); - return; - } - //Default - numbers = new ArrayList(); - numbers.add((short) (1)); - return; - } catch (NumberFormatException nfe) { - //Do Nothing test as String instead - } - - //Is it the String value ? - Integer id3GenreId = GenreTypes.getInstanceOf().getIdForValue(genreId); - if (id3GenreId != null) { - if (id3GenreId <= GenreTypes.getMaxStandardGenreId()) { - numbers = new ArrayList(); - numbers.add((short) (id3GenreId + 1)); - return; - } - } - numbers = new ArrayList(); - numbers.add((short) (1)); - } - - /** - * Precheck to see if the value is a valid genre or whether you should use a custom genre. - * - * @param genreId - * @return - */ - public static boolean isValidGenre(String genreId) { - //Is it an id (within old id3 range) - try { - short genreVal = Short.parseShort(genreId); - if ((genreVal - 1) <= GenreTypes.getMaxStandardGenreId()) { - return true; - } - } catch (NumberFormatException nfe) { - //Do Nothing test as String instead - } - - //Is it the String value ? - Integer id3GenreId = GenreTypes.getInstanceOf().getIdForValue(genreId); - if (id3GenreId != null) { - if (id3GenreId <= GenreTypes.getMaxStandardGenreId()) { - return true; - } - } - return false; - } - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Data actually contains a 'Data' Box so process data using this - Mp4BoxHeader header = new Mp4BoxHeader(data); - Mp4DataBox databox = new Mp4DataBox(header, data); - dataSize = header.getDataLength(); - numbers = databox.getNumbers(); - - if (numbers.size() > 0) { - int genreId = numbers.get(0); - //Get value, we have to adjust index by one because iTunes labels from one instead of zero - content = GenreTypes.getInstanceOf().getValueForId(genreId - 1); - //Some apps set genre to invalid value, we dont disguise this by setting content to empty string we leave - //as null so apps can handle if they wish, but we do display a warning to make them aware. - if (content == null) { - logger.warning(ErrorMessage.MP4_GENRE_OUT_OF_RANGE.getMsg(genreId)); - } - } else { - logger.warning(ErrorMessage.MP4_NO_GENREID_FOR_GENRE.getMsg(header.getDataLength())); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.java deleted file mode 100644 index 6ac267d..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.mp4.Mp4TagField; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Represents binary data - *

    - *

    Subclassed by cover art field, - * TODO unaware of any other binary fields at the moment - */ -public class Mp4TagBinaryField extends Mp4TagField { - protected int dataSize; - protected byte[] dataBytes; - protected boolean isBinary = false; - - /** - * Construct an empty Binary Field - * - * @param id - */ - public Mp4TagBinaryField(String id) { - super(id); - } - - /** - * Construct new binary field with binarydata provided - * - * @param id - * @param data - * @throws UnsupportedEncodingException - */ - public Mp4TagBinaryField(String id, byte[] data) { - super(id); - this.dataBytes = data; - } - - /** - * Construct binary field from rawdata of audio file - * - * @param id - * @param raw - * @throws UnsupportedEncodingException - */ - public Mp4TagBinaryField(String id, ByteBuffer raw) throws UnsupportedEncodingException { - super(id, raw); - } - - public Mp4FieldType getFieldType() { - //TODO dont know what value this should be do we actually have any binary fields other - //than cover art - return Mp4FieldType.IMPLICIT; - } - - /** - * Used when creating raw content - * - * @return - * @throws UnsupportedEncodingException - */ - protected byte[] getDataBytes() throws UnsupportedEncodingException { - return dataBytes; - } - - protected void build(ByteBuffer raw) { - Mp4BoxHeader header = new Mp4BoxHeader(raw); - dataSize = header.getDataLength(); - - //Skip the version and length fields - raw.position(raw.position() + Mp4DataBox.PRE_DATA_LENGTH); - - //Read the raw data into byte array - this.dataBytes = new byte[dataSize - Mp4DataBox.PRE_DATA_LENGTH]; - for (int i = 0; i < dataBytes.length; i++) { - this.dataBytes[i] = raw.get(); - } - - //After returning buffers position will be after the end of this atom - } - - public boolean isBinary() { - return isBinary; - } - - public boolean isEmpty() { - return this.dataBytes.length == 0; - } - - public int getDataSize() { - return dataSize; - - } - - public byte[] getData() { - return this.dataBytes; - } - - public void setData(byte[] d) { - this.dataBytes = d; - } - - public void copyContent(TagField field) { - if (field instanceof Mp4TagBinaryField) { - this.dataBytes = ((Mp4TagBinaryField) field).getData(); - this.isBinary = field.isBinary(); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagByteField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagByteField.java deleted file mode 100644 index b82c577..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagByteField.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.FieldDataInvalidException; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Represents a single byte as a number - *

    - *

    Usually single byte fields are used as a boolean field, but not always so we dont do this conversion - */ -public class Mp4TagByteField extends Mp4TagTextField { - public static String TRUE_VALUE = "1"; //when using this field to hold a boolean - - //Holds the actual size of the data content as held in the databoxitem, this is required when creating new - //items because we cant accurately work out the size by looking at the content because sometimes field must be longer - //than is actually required to hold the value - //e.g byte data length seems to be 1 for pgap and cpil but 2 for tmpo, so we stored the dataSize - //when we loaded the value so if greater than 1 we pad the value. - private int realDataLength; - - //Preserved from data from file - private byte[] bytedata; - - /** - * Create new field - *

    - * Assume length of 1 which is correct for most but not all byte fields - * - * @param id - * @param value is a String representation of a number - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public Mp4TagByteField(Mp4FieldKey id, String value) throws FieldDataInvalidException { - this(id, value, 1); - } - - /** - * Create new field with known length - * - * @param id - * @param value is a String representation of a number - * @param realDataLength - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public Mp4TagByteField(Mp4FieldKey id, String value, int realDataLength) throws FieldDataInvalidException { - super(id.getFieldName(), value); - this.realDataLength = realDataLength; - //Check that can actually be stored numercially, otherwise will have big problems - //when try and save the field - try { - Long.parseLong(value); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + value + " is invalid for field:" + id); - } - } - - /** - * Construct from rawdata from audio file - * - * @param id - * @param raw - * @throws UnsupportedEncodingException - */ - public Mp4TagByteField(String id, ByteBuffer raw) throws UnsupportedEncodingException { - super(id, raw); - } - - public Mp4FieldType getFieldType() { - return Mp4FieldType.INTEGER; - } - - /** - * Return raw data bytes - *

    - * TODO this code should be done better so generalised to any length - * - * @return - * @throws UnsupportedEncodingException - */ - protected byte[] getDataBytes() throws UnsupportedEncodingException { - - //Write original data - if (bytedata != null) { - return bytedata; - } - - //new field, lets hope the realDataLength is correct - switch (realDataLength) { - case 2: { - //Save as two bytes - Short shortValue = new Short(content); - byte rawData[] = Utils.getSizeBEInt16(shortValue); - return rawData; - } - case 1: { - //Save as 1 bytes - Short shortValue = new Short(content); - byte rawData[] = new byte[1]; - rawData[0] = shortValue.byteValue(); - return rawData; - } - case 4: { - //Assume could be int - Integer intValue = new Integer(content); - byte rawData[] = Utils.getSizeBEInt32(intValue); - return rawData; - } - default: { - //TODO - throw new RuntimeException(id + ":" + realDataLength + ":" + "Dont know how to write byte fields of this length"); - } - } - - } - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Data actually contains a 'Data' Box so process data using this - Mp4BoxHeader header = new Mp4BoxHeader(data); - Mp4DataBox databox = new Mp4DataBox(header, data); - dataSize = header.getDataLength(); - //Needed for subsequent write - realDataLength = dataSize - Mp4DataBox.PRE_DATA_LENGTH; - bytedata = databox.getByteData(); - content = databox.getContent(); - - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java deleted file mode 100644 index 6796794..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.id3.valuepair.ImageFormats; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import org.jaudiotagger.tag.mp4.atom.Mp4NameBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Represents Cover Art - *

    - *

    Note:Within this library we have a seperate TagCoverField for every image stored, however this does not map - * very directly to how they are physically stored within a file, because all are stored under a single covr atom, so - * a more complex conversion has to be done then for other fields when writing multiple images back to file. - */ -public class Mp4TagCoverField extends Mp4TagBinaryField { - - //Type - private Mp4FieldType imageType; - - //Contains the size of each atom including header, required because may only have data atom or - //may have data and name atom - private int dataAndHeaderSize; - - /** - * Empty CoverArt Field - */ - public Mp4TagCoverField() { - super(Mp4FieldKey.ARTWORK.getFieldName()); - } - - /** - * Construct CoverField by reading data from audio file - * - * @param raw - * @param imageType - * @throws UnsupportedEncodingException - */ - public Mp4TagCoverField(ByteBuffer raw, Mp4FieldType imageType) throws UnsupportedEncodingException { - super(Mp4FieldKey.ARTWORK.getFieldName(), raw); - this.imageType = imageType; - if (!Mp4FieldType.isCoverArtType(imageType)) { - logger.warning(ErrorMessage.MP4_IMAGE_FORMAT_IS_NOT_TO_EXPECTED_TYPE.getMsg(imageType)); - } - } - - /** - * Construct new cover art with binarydata provided - *

    - *

    - * Identifies the imageType by looking at the data - * - * @param data - * @throws UnsupportedEncodingException - */ - public Mp4TagCoverField(byte[] data) { - super(Mp4FieldKey.ARTWORK.getFieldName(), data); - - //Read signature - if (ImageFormats.binaryDataIsPngFormat(data)) { - imageType = Mp4FieldType.COVERART_PNG; - } else if (ImageFormats.binaryDataIsJpgFormat(data)) { - imageType = Mp4FieldType.COVERART_JPEG; - } else if (ImageFormats.binaryDataIsGifFormat(data)) { - imageType = Mp4FieldType.COVERART_GIF; - } else if (ImageFormats.binaryDataIsBmpFormat(data)) { - imageType = Mp4FieldType.COVERART_BMP; - } else { - logger.warning(ErrorMessage.GENERAL_UNIDENITIFED_IMAGE_FORMAT.getMsg()); - imageType = Mp4FieldType.COVERART_PNG; - } - } - - /** - * @param imageType - * @return the corresponding mimetype - */ - public static String getMimeTypeForImageType(Mp4FieldType imageType) { - if (imageType == Mp4FieldType.COVERART_PNG) { - return ImageFormats.MIME_TYPE_PNG; - } else if (imageType == Mp4FieldType.COVERART_JPEG) { - return ImageFormats.MIME_TYPE_JPEG; - } else if (imageType == Mp4FieldType.COVERART_GIF) { - return ImageFormats.MIME_TYPE_GIF; - } else if (imageType == Mp4FieldType.COVERART_BMP) { - return ImageFormats.MIME_TYPE_BMP; - } else { - return null; - } - } - - /** - * @return data and header size - */ - public int getDataAndHeaderSize() { - return dataAndHeaderSize; - } - - /** - * Return field type, for artwork this also identifies the imagetype - * - * @return field type - */ - public Mp4FieldType getFieldType() { - return imageType; - } - - public boolean isBinary() { - return true; - } - - public String toString() { - return imageType + ":" + dataBytes.length + "bytes"; - } - - protected void build(ByteBuffer raw) { - Mp4BoxHeader header = new Mp4BoxHeader(raw); - dataSize = header.getDataLength(); - dataAndHeaderSize = header.getLength(); - - //Skip the version and length fields - raw.position(raw.position() + Mp4DataBox.PRE_DATA_LENGTH); - - //Read the raw data into byte array - this.dataBytes = new byte[dataSize - Mp4DataBox.PRE_DATA_LENGTH]; - raw.get(dataBytes, 0, dataBytes.length); - - //Is there room for another atom (remember actually passed all the data so unless Covr is last atom - //there will be room even though more likely to be for the text top level atom) - int positionAfterDataAtom = raw.position(); - if (raw.position() + Mp4BoxHeader.HEADER_LENGTH <= raw.limit()) { - //Is there a following name field (not the norm) - Mp4BoxHeader nameHeader = new Mp4BoxHeader(raw); - if (nameHeader.getId().equals(Mp4NameBox.IDENTIFIER)) { - dataSize += nameHeader.getDataLength(); - dataAndHeaderSize += nameHeader.getLength(); - } else { - raw.position(positionAfterDataAtom); - } - } - - //After returning buffers position will be after the end of this atom - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java deleted file mode 100644 index fc311c1..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.mp4.Mp4TagField; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Represents raw binary data - *

    - *

    We use this when we find an atom under the ilst atom that we do not recognise , that does not - * follow standard conventions in order to save the data without modification so it can be safetly - * written back to file - */ -public class Mp4TagRawBinaryField extends Mp4TagField { - protected int dataSize; - protected byte[] dataBytes; - - - /** - * Construct binary field from rawdata of audio file - * - * @param header - * @param raw - * @throws java.io.UnsupportedEncodingException - */ - public Mp4TagRawBinaryField(Mp4BoxHeader header, ByteBuffer raw) throws UnsupportedEncodingException { - super(header.getId()); - dataSize = header.getDataLength(); - build(raw); - } - - public Mp4FieldType getFieldType() { - return Mp4FieldType.IMPLICIT; - } - - /** - * Used when creating raw content - * - * @return - * @throws java.io.UnsupportedEncodingException - */ - protected byte[] getDataBytes() throws UnsupportedEncodingException { - return dataBytes; - } - - - /** - * Build from data - *

    - *

    After returning buffers position will be after the end of this atom - * - * @param raw - */ - protected void build(ByteBuffer raw) { - //Read the raw data into byte array - this.dataBytes = new byte[dataSize]; - for (int i = 0; i < dataBytes.length; i++) { - this.dataBytes[i] = raw.get(); - } - } - - public boolean isBinary() { - return true; - } - - public boolean isEmpty() { - return this.dataBytes.length == 0; - } - - public int getDataSize() { - return dataSize; - - } - - public byte[] getData() { - return this.dataBytes; - } - - public void setData(byte[] d) { - this.dataBytes = d; - } - - public void copyContent(TagField field) { - throw new UnsupportedOperationException("not done"); - } - - public byte[] getRawContent() throws UnsupportedEncodingException { - logger.fine("Getting Raw data for:" + getId()); - try { - ByteArrayOutputStream outerbaos = new ByteArrayOutputStream(); - outerbaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + dataSize)); - outerbaos.write(Utils.getDefaultBytes(getId(), "ISO-8859-1")); - outerbaos.write(dataBytes); - System.out.println("SIZE" + outerbaos.size()); - return outerbaos.toByteArray(); - } catch (IOException ioe) { - //This should never happen as were not actually writing to/from a file - throw new RuntimeException(ioe); - } - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java deleted file mode 100644 index f04b152..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java +++ /dev/null @@ -1,257 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.TagTextField; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.Mp4TagField; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import org.jaudiotagger.tag.mp4.atom.Mp4MeanBox; -import org.jaudiotagger.tag.mp4.atom.Mp4NameBox; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Represents reverse dns field, used for custom information - *

    - *

    Originally only used by Itunes for information that was iTunes specific but now used in a wide range of uses, - * for example Musicbrainz uses it for many of its fields. - *

    - * These fields have a more complex setup - * Box ---- shows this is a reverse dns metadata field - * Box mean the issuer in the form of reverse DNS domain (e.g com.apple.iTunes) - * Box name descriptor identifying the type of contents - * Box data contents - *

    - * The raw data passed starts from the mean box - */ -public class Mp4TagReverseDnsField extends Mp4TagField implements TagTextField { - public static final String IDENTIFIER = "----"; - - protected int dataSize; - //Data Content, - //TODO assuming always text at the moment - protected String content; - //Issuer - private String issuer; - //Descriptor - private String descriptor; - - /** - * Construct from existing file data - * - * @param parentHeader - * @param data - * @throws UnsupportedEncodingException - */ - public Mp4TagReverseDnsField(Mp4BoxHeader parentHeader, ByteBuffer data) throws UnsupportedEncodingException { - super(parentHeader, data); - } - - /** - * Newly created Reverse Dns field - * - * @param id - * @param content - */ - public Mp4TagReverseDnsField(Mp4FieldKey id, String content) { - super(id.getFieldName()); - this.issuer = id.getIssuer(); - this.descriptor = id.getIdentifier(); - this.content = content; - } - - /** - * Newly created Reverse Dns field bypassing the Mp4TagField enum for creation of temporary reverse dns fields - * - * @param fieldName - * @param issuer - * @param identifier - * @param content - */ - public Mp4TagReverseDnsField(final String fieldName, final String issuer, final String identifier, final String content) { - super(fieldName); - this.issuer = issuer; - this.descriptor = identifier; - this.content = content; - } - - public Mp4FieldType getFieldType() { - //TODO always assuming text at moment but may not always be the case (though dont have any concrete - //examples) - return Mp4FieldType.TEXT; - } - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Read mean box, set the issuer and skip over data - Mp4BoxHeader meanBoxHeader = new Mp4BoxHeader(data); - Mp4MeanBox meanBox = new Mp4MeanBox(meanBoxHeader, data); - setIssuer(meanBox.getIssuer()); - data.position(data.position() + meanBoxHeader.getDataLength()); - - //Read name box, identify what type of field it is - Mp4BoxHeader nameBoxHeader = new Mp4BoxHeader(data); - Mp4NameBox nameBox = new Mp4NameBox(nameBoxHeader, data); - setDescriptor(nameBox.getName()); - data.position(data.position() + nameBoxHeader.getDataLength()); - - //Issue 198:There is not actually a data atom there cannot cant be because no room for one - if (parentHeader.getDataLength() == meanBoxHeader.getLength() + nameBoxHeader.getLength()) { - id = IDENTIFIER + ":" + issuer + ":" + descriptor; - setContent(""); - logger.warning(ErrorMessage.MP4_REVERSE_DNS_FIELD_HAS_NO_DATA.getMsg(id)); - } - //Usual Case - else { - //Read data box, identify the data - Mp4BoxHeader dataBoxHeader = new Mp4BoxHeader(data); - Mp4DataBox dataBox = new Mp4DataBox(dataBoxHeader, data); - setContent(dataBox.getContent()); - data.position(data.position() + dataBoxHeader.getDataLength()); - - //Now calculate the id which in order to be unique needs to use all htree values - id = IDENTIFIER + ":" + issuer + ":" + descriptor; - } - } - - - public void copyContent(TagField field) { - if (field instanceof Mp4TagReverseDnsField) { - this.issuer = ((Mp4TagReverseDnsField) field).getIssuer(); - this.descriptor = ((Mp4TagReverseDnsField) field).getDescriptor(); - this.content = ((Mp4TagReverseDnsField) field).getContent(); - } - } - - /** - * @return content - */ - public String getContent() { - return content; - } - - public void setContent(String s) { - this.content = s; - } - - protected byte[] getDataBytes() throws UnsupportedEncodingException { - return content.getBytes(getEncoding()); - } - - public String getEncoding() { - return Mp4BoxHeader.CHARSET_UTF_8; - } - - public void setEncoding(String s) { - /* Not allowed */ - } - - /** - * Convert back to raw content, includes ----,mean,name and data atom as views as one thing externally - * - * @return - * @throws UnsupportedEncodingException - */ - public byte[] getRawContent() throws UnsupportedEncodingException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - //Create Meanbox data - byte[] issuerRawData = issuer.getBytes(getEncoding()); - baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4MeanBox.PRE_DATA_LENGTH + issuerRawData.length)); - baos.write(Utils.getDefaultBytes(Mp4MeanBox.IDENTIFIER, "ISO-8859-1")); - baos.write(new byte[]{0, 0, 0, 0}); - baos.write(issuerRawData); - - //Create Namebox data - byte[] nameRawData = descriptor.getBytes(getEncoding()); - baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4NameBox.PRE_DATA_LENGTH + nameRawData.length)); - baos.write(Utils.getDefaultBytes(Mp4NameBox.IDENTIFIER, "ISO-8859-1")); - baos.write(new byte[]{0, 0, 0, 0}); - baos.write(nameRawData); - - //Create DataBox data if we have data only - if (content.length() > 0) { - baos.write(getRawContentDataOnly()); - } - //Now wrap with reversedns box - ByteArrayOutputStream outerbaos = new ByteArrayOutputStream(); - outerbaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size())); - outerbaos.write(Utils.getDefaultBytes(IDENTIFIER, "ISO-8859-1")); - outerbaos.write(baos.toByteArray()); - return outerbaos.toByteArray(); - - } catch (IOException ioe) { - //This should never happen as were not actually writing to/from a file - throw new RuntimeException(ioe); - } - } - - public byte[] getRawContentDataOnly() throws UnsupportedEncodingException { - logger.fine("Getting Raw data for:" + getId()); - try { - //Create DataBox data - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] dataRawData = content.getBytes(getEncoding()); - baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4DataBox.PRE_DATA_LENGTH + dataRawData.length)); - baos.write(Utils.getDefaultBytes(Mp4DataBox.IDENTIFIER, "ISO-8859-1")); - baos.write(new byte[]{0}); - baos.write(new byte[]{0, 0, (byte) getFieldType().getFileClassId()}); - baos.write(new byte[]{0, 0, 0, 0}); - baos.write(dataRawData); - return baos.toByteArray(); - } catch (IOException ioe) { - //This should never happen as were not actually writing to/from a file - throw new RuntimeException(ioe); - } - } - - public boolean isBinary() { - return false; - } - - public boolean isEmpty() { - return this.content.trim().equals(""); - } - - public String toString() { - return content; - } - - /** - * @return the issuer - */ - public String getIssuer() { - return issuer; - } - - /** - * Set the issuer, usually reverse dns of the Companies domain - * - * @param issuer - */ - public void setIssuer(String issuer) { - this.issuer = issuer; - } - - /** - * @return the descriptor - */ - public String getDescriptor() { - return descriptor; - } - - /** - * Set the descriptor for the data (what type of data it is) - * - * @param descriptor - */ - public void setDescriptor(String descriptor) { - this.descriptor = descriptor; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagTextField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagTextField.java deleted file mode 100644 index 724d05e..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagTextField.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.TagTextField; -import org.jaudiotagger.tag.mp4.Mp4TagField; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; - -/** - * Represents a single text field - *

    - *

    Mp4 metadata normally held as follows: - *

    - * MP4Box Parent contains
    - *      :length (includes length of data child)  (4 bytes)
    - *      :name         (4 bytes)
    - *      :child with
    - *          :length          (4 bytes)
    - *          :name 'Data'     (4 bytes)
    - *          :atom version    (1 byte)
    - *          :atom type flags (3 bytes)
    - *          :null field      (4 bytes)
    - *          :data
    - * 
    - *

    - *

    Note:This class is initilized with the child data atom only, the parent data has already been processed, this may - * change as it seems that code should probably be enscapulated into this. Whereas the raw content returned by the - * getRawContent() contais the byte data for parent and child. - */ -public class Mp4TagTextField extends Mp4TagField implements TagTextField { - protected int dataSize; - protected String content; - - /** - * Construct from File - * - * @param id parent id - * @param data atom data - * @throws UnsupportedEncodingException - */ - public Mp4TagTextField(String id, ByteBuffer data) throws UnsupportedEncodingException { - super(id, data); - } - - /** - * Construct new Field - * - * @param id parent id - * @param content data atom data - */ - public Mp4TagTextField(String id, String content) { - super(id); - this.content = content; - } - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Data actually contains a 'Data' Box so process data using this - Mp4BoxHeader header = new Mp4BoxHeader(data); - Mp4DataBox databox = new Mp4DataBox(header, data); - dataSize = header.getDataLength(); - content = databox.getContent(); - } - - public void copyContent(TagField field) { - if (field instanceof Mp4TagTextField) { - this.content = ((Mp4TagTextField) field).getContent(); - } - } - - public String getContent() { - return content; - } - - public void setContent(String s) { - this.content = s; - } - - protected byte[] getDataBytes() throws UnsupportedEncodingException { - return content.getBytes(getEncoding()); - } - - public Mp4FieldType getFieldType() { - return Mp4FieldType.TEXT; - } - - public String getEncoding() { - return Mp4BoxHeader.CHARSET_UTF_8; - } - - public void setEncoding(String s) { - /* Not allowed */ - } - - public boolean isBinary() { - return false; - } - - public boolean isEmpty() { - return this.content.trim().equals(""); - } - - public String toString() { - return content; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java deleted file mode 100644 index 9376edf..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.List; - -/** - * Represents simple text field that contains an array of number, - *

    - *

    But reads the data content as an array of 16 bit unsigned numbers - */ -public class Mp4TagTextNumberField extends Mp4TagTextField { - public static final int NUMBER_LENGTH = 2; - - //Holds the numbers decoded - protected List numbers; - - /** - * Create a new number, already parsed in subclasses - * - * @param id - * @param numberArray - */ - public Mp4TagTextNumberField(String id, String numberArray) { - super(id, numberArray); - } - - public Mp4TagTextNumberField(String id, ByteBuffer data) throws UnsupportedEncodingException { - super(id, data); - } - - /** - * Recreate the raw data content from the list of numbers - * - * @return - */ - protected byte[] getDataBytes() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (Short number : numbers) { - try { - baos.write(Utils.getSizeBEInt16(number)); - } catch (IOException e) { - //This should never happen because we are not writing to file at this point. - throw new RuntimeException(e); - } - } - return baos.toByteArray(); - } - - public void copyContent(TagField field) { - if (field instanceof Mp4TagTextNumberField) { - this.content = ((Mp4TagTextNumberField) field).getContent(); - this.numbers = ((Mp4TagTextNumberField) field).getNumbers(); - } - } - - /** - * @return type numeric - */ - public Mp4FieldType getFieldType() { - return Mp4FieldType.IMPLICIT; - } - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Data actually contains a 'Data' Box so process data using this - Mp4BoxHeader header = new Mp4BoxHeader(data); - Mp4DataBox databox = new Mp4DataBox(header, data); - dataSize = header.getDataLength(); - content = databox.getContent(); - numbers = databox.getNumbers(); - } - - /** - * @return the individual numbers making up this field - */ - public List getNumbers() { - return numbers; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TrackField.java b/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TrackField.java deleted file mode 100644 index 4b140b9..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/Mp4TrackField.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.jaudiotagger.tag.mp4.field; - -import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import org.jaudiotagger.tag.FieldDataInvalidException; -import org.jaudiotagger.tag.mp4.Mp4FieldKey; -import org.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.ArrayList; - -/** - * Represents the Track No field - *

    - *

    There are a number of reserved fields making matters more complicated - * Reserved:2 bytes - * Track Number:2 bytes - * No of Tracks:2 bytes (or zero if not known) - * PlayListTitleReserved: 1 byte - * playtitlenameReserved:0 bytes - *

    - */ -public class Mp4TrackField extends Mp4TagTextNumberField { - private static final int NONE_VALUE_INDEX = 0; - private static final int TRACK_NO_INDEX = 1; - private static final int TRACK_TOTAL_INDEX = 2; - private static final int NONE_END_VALUE_INDEX = 3; - - /** - * Create new Track Field parsing the String for the trackno/total - * - * @param trackValue - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public Mp4TrackField(String trackValue) throws FieldDataInvalidException { - super(Mp4FieldKey.TRACK.getFieldName(), trackValue); - - numbers = new ArrayList(); - numbers.add(new Short("0")); - - String values[] = trackValue.split("/"); - switch (values.length) { - case 1: - try { - numbers.add(Short.parseShort(values[0])); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + values[0] + " is invalid for field:" + id); - } - numbers.add(new Short("0")); - numbers.add(new Short("0")); - break; - - case 2: - try { - numbers.add(Short.parseShort(values[0])); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + values[0] + " is invalid for field:" + id); - } - try { - numbers.add(Short.parseShort(values[1])); - } catch (NumberFormatException nfe) { - throw new FieldDataInvalidException("Value of:" + values[1] + " is invalid for field:" + id); - } - numbers.add(new Short("0")); - break; - - default: - throw new FieldDataInvalidException("Value is invalid for field:" + id); - } - } - - - /** - * Create new Track Field with only track No - * - * @param trackNo - */ - public Mp4TrackField(int trackNo) { - - super(Mp4FieldKey.TRACK.getFieldName(), String.valueOf(trackNo)); - numbers = new ArrayList(); - numbers.add(new Short("0")); - numbers.add((short) trackNo); - numbers.add(new Short("0")); - numbers.add(new Short("0")); - } - - /** - * Create new Track Field with track No and total tracks - * - * @param trackNo - * @param total - */ - public Mp4TrackField(int trackNo, int total) { - super(Mp4FieldKey.TRACK.getFieldName(), String.valueOf(trackNo)); - numbers = new ArrayList(); - numbers.add(new Short("0")); - numbers.add((short) trackNo); - numbers.add((short) total); - numbers.add(new Short("0")); - } - - /** - * Construct from filedata - * - * @param id - * @param data - * @throws UnsupportedEncodingException - */ - public Mp4TrackField(String id, ByteBuffer data) throws UnsupportedEncodingException { - super(id, data); - } - - - protected void build(ByteBuffer data) throws UnsupportedEncodingException { - //Data actually contains a 'Data' Box so process data using this - Mp4BoxHeader header = new Mp4BoxHeader(data); - Mp4DataBox databox = new Mp4DataBox(header, data); - dataSize = header.getDataLength(); - numbers = databox.getNumbers(); - //Track number always hold three values, we can discard the first one, the second one is the track no - //and the third is the total no of tracks so only use if not zero - StringBuffer sb = new StringBuffer(); - if (numbers != null) { - if ((numbers.size() > TRACK_NO_INDEX) && (numbers.get(TRACK_NO_INDEX) > 0)) { - sb.append(numbers.get(TRACK_NO_INDEX)); - } - if ((numbers.size() > TRACK_TOTAL_INDEX) && (numbers.get(TRACK_TOTAL_INDEX) > 0)) { - sb.append("/").append(numbers.get(TRACK_TOTAL_INDEX)); - } - } - content = sb.toString(); - } - - /** - * @return - */ - public Short getTrackNo() { - return numbers.get(TRACK_NO_INDEX); - } - - /** - * Set Track No - * - * @param trackNo - */ - public void setTrackNo(int trackNo) { - numbers.set(TRACK_NO_INDEX, (short) trackNo); - } - - /** - * @return - */ - public Short getTrackTotal() { - if (numbers.size() <= TRACK_TOTAL_INDEX) { - return 0; - } - return numbers.get(TRACK_TOTAL_INDEX); - } - - /** - * Set total number of tracks - * - * @param trackTotal - */ - public void setTrackTotal(int trackTotal) { - numbers.set(TRACK_TOTAL_INDEX, (short) trackTotal); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/mp4/field/package.html b/src/main/java/org/jaudiotagger/tag/mp4/field/package.html deleted file mode 100644 index 63a4937..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/field/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes handling fields of the MP4 moov.udt.meta.ilst atom. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/mp4/package.html b/src/main/java/org/jaudiotagger/tag/mp4/package.html deleted file mode 100644 index ba27f2b..0000000 --- a/src/main/java/org/jaudiotagger/tag/mp4/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Classes for the MP4 metadata (moov.udt.meta.ilst) atom. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/options/PadNumberOption.java b/src/main/java/org/jaudiotagger/tag/options/PadNumberOption.java deleted file mode 100644 index dc6928b..0000000 --- a/src/main/java/org/jaudiotagger/tag/options/PadNumberOption.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.jaudiotagger.tag.options; - -/** - * Number of padding zeroes digits 1- 9, numbers larger than nine will be padded accordingly based on the value. - *

    - * i.e - * If set to PAD_ONE_ZERO, 9 -> 09 , 99 -> 99 , 999 ->999 - * If set to PAD_TWO_ZERO, 9 -> 009 , 99 -> 099 , 999 ->999 - * If set to PAD_THREE_ZERO, 9 -> 0009 , 99 -> 0099 , 999 ->0999 - */ -public enum PadNumberOption { - PAD_ONE_ZERO, - PAD_TWO_ZERO, - PAD_THREE_ZERO, - -} diff --git a/src/main/java/org/jaudiotagger/tag/options/package.html b/src/main/java/org/jaudiotagger/tag/options/package.html deleted file mode 100644 index 1269a2a..0000000 --- a/src/main/java/org/jaudiotagger/tag/options/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Holds a few option definitions. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/package.html b/src/main/java/org/jaudiotagger/tag/package.html deleted file mode 100644 index f228770..0000000 --- a/src/main/java/org/jaudiotagger/tag/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Generic classes and interfaces for metadata blocks, broadly called tags. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/reference/GenreTypes.java b/src/main/java/org/jaudiotagger/tag/reference/GenreTypes.java deleted file mode 100644 index c0e33b2..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/GenreTypes.java +++ /dev/null @@ -1,224 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: GenreTypes.java 848 2009-11-14 07:46:43Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License ainteger with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.tag.reference; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Genre list - *

    - *

    This is the IDv1 list with additional values as defined by Winamp, this list is also used in Mp4 - * files, note iTunes doesn't understand genres above MAX_STANDARD_GENRE_ID, Winamp does

    - */ -public class GenreTypes extends AbstractIntStringValuePair { - private static int MAX_STANDARD_GENRE_ID = 125; - private static GenreTypes genreTypes; - //This maps the lowercase version to the id, so applications can map from the lowercase value to the id - private Map nameToIdMap; - - private GenreTypes() { - idToValue.put(0, "Blues"); - idToValue.put(1, "Classic Rock"); - idToValue.put(2, "Country"); - idToValue.put(3, "Dance"); - idToValue.put(4, "Disco"); - idToValue.put(5, "Funk"); - idToValue.put(6, "Grunge"); - idToValue.put(7, "Hip-Hop"); - idToValue.put(8, "Jazz"); - idToValue.put(9, "Metal"); - idToValue.put(10, "New Age"); - idToValue.put(11, "Oldies"); - idToValue.put(12, "Other"); - idToValue.put(13, "Pop"); - idToValue.put(14, "R&B"); - idToValue.put(15, "Rap"); - idToValue.put(16, "Reggae"); - idToValue.put(17, "Rock"); - idToValue.put(18, "Techno"); - idToValue.put(19, "Industrial"); - idToValue.put(20, "Alternative"); - idToValue.put(21, "Ska"); - idToValue.put(22, "Death Metal"); - idToValue.put(23, "Pranks"); - idToValue.put(24, "Soundtrack"); - idToValue.put(25, "Euro-Techno"); - idToValue.put(26, "Ambient"); - idToValue.put(27, "Trip-Hop"); - idToValue.put(28, "Vocal"); - idToValue.put(29, "Jazz+Funk"); - idToValue.put(30, "Fusion"); - idToValue.put(31, "Trance"); - idToValue.put(32, "Classical"); - idToValue.put(33, "Instrumental"); - idToValue.put(34, "Acid"); - idToValue.put(35, "House"); - idToValue.put(36, "Game"); - idToValue.put(37, "Sound Clip"); - idToValue.put(38, "Gospel"); - idToValue.put(39, "Noise"); - idToValue.put(40, "AlternRock"); - idToValue.put(41, "Bass"); - idToValue.put(42, "Soul"); - idToValue.put(43, "Punk"); - idToValue.put(44, "Space"); - idToValue.put(45, "Meditative"); - idToValue.put(46, "Instrumental Pop"); - idToValue.put(47, "Instrumental Rock"); - idToValue.put(48, "Ethnic"); - idToValue.put(49, "Gothic"); - idToValue.put(50, "Darkwave"); - idToValue.put(51, "Techno-Industrial"); - idToValue.put(52, "Electronic"); - idToValue.put(53, "Pop-Folk"); - idToValue.put(54, "Eurodance"); - idToValue.put(55, "Dream"); - idToValue.put(56, "Southern Rock"); - idToValue.put(57, "Comedy"); - idToValue.put(58, "Cult"); - idToValue.put(59, "Gangsta"); - idToValue.put(60, "Top 40"); - idToValue.put(61, "Christian Rap"); - idToValue.put(62, "Pop/Funk"); - idToValue.put(63, "Jungle"); - idToValue.put(64, "Native American"); - idToValue.put(65, "Cabaret"); - idToValue.put(66, "New Wave"); - idToValue.put(67, "Psychadelic"); - idToValue.put(68, "Rave"); - idToValue.put(69, "Showtunes"); - idToValue.put(70, "Trailer"); - idToValue.put(71, "Lo-Fi"); - idToValue.put(72, "Tribal"); - idToValue.put(73, "Acid Punk"); - idToValue.put(74, "Acid Jazz"); - idToValue.put(75, "Polka"); - idToValue.put(76, "Retro"); - idToValue.put(77, "Musical"); - idToValue.put(78, "Rock & Roll"); - idToValue.put(79, "Hard Rock"); - idToValue.put(80, "Folk"); - idToValue.put(81, "Folk-Rock"); - idToValue.put(82, "National Folk"); - idToValue.put(83, "Swing"); - idToValue.put(84, "Fast Fusion"); - idToValue.put(85, "Bebob"); - idToValue.put(86, "Latin"); - idToValue.put(87, "Revival"); - idToValue.put(88, "Celtic"); - idToValue.put(89, "Bluegrass"); - idToValue.put(90, "Avantgarde"); - idToValue.put(91, "Gothic Rock"); - idToValue.put(92, "Progressive Rock"); - idToValue.put(93, "Psychedelic Rock"); - idToValue.put(94, "Symphonic Rock"); - idToValue.put(95, "Slow Rock"); - idToValue.put(96, "Big Band"); - idToValue.put(97, "Chorus"); - idToValue.put(98, "Easy Listening"); - idToValue.put(99, "Acoustic"); - idToValue.put(100, "Humour"); - idToValue.put(101, "Speech"); - idToValue.put(102, "Chanson"); - idToValue.put(103, "Opera"); - idToValue.put(104, "Chamber Music"); - idToValue.put(105, "Sonata"); - idToValue.put(106, "Symphony"); - idToValue.put(107, "Booty Bass"); - idToValue.put(108, "Primus"); - idToValue.put(109, "Porn Groove"); - idToValue.put(110, "Satire"); - idToValue.put(111, "Slow Jam"); - idToValue.put(112, "Club"); - idToValue.put(113, "Tango"); - idToValue.put(114, "Samba"); - idToValue.put(115, "Folklore"); - idToValue.put(116, "Ballad"); - idToValue.put(117, "Power Ballad"); - idToValue.put(118, "Rhythmic Soul"); - idToValue.put(119, "Freestyle"); - idToValue.put(120, "Duet"); - idToValue.put(121, "Punk Rock"); - idToValue.put(122, "Drum Solo"); - idToValue.put(123, "Acapella"); - idToValue.put(124, "Euro-House"); - idToValue.put(125, "Dance Hall"); - idToValue.put(126, "Goa"); - idToValue.put(127, "Drum & Bass"); - idToValue.put(128, "Club-House"); - idToValue.put(129, "Hardcore"); - idToValue.put(130, "Terror"); - idToValue.put(131, "Indie"); - idToValue.put(132, "BritPop"); - idToValue.put(133, "Negerpunk"); - idToValue.put(134, "Polsk Punk"); - idToValue.put(135, "Beat"); - idToValue.put(136, "Christian Gangsta Rap"); - idToValue.put(137, "Heavy Metal"); - idToValue.put(138, "Black Metal"); - idToValue.put(139, "Crossover"); - idToValue.put(140, "Contemporary Christian"); - idToValue.put(141, "Christian Rock"); - idToValue.put(142, "Merengue"); - idToValue.put(143, "Salsa"); - idToValue.put(144, "Thrash Metal"); - idToValue.put(145, "Anime"); - idToValue.put(146, "JPop"); - idToValue.put(147, "SynthPop"); - - createMaps(); - - //We now need to map from lowercase version to Id - nameToIdMap = new LinkedHashMap(idToValue.size()); - for (Map.Entry entry : idToValue.entrySet()) { - nameToIdMap.put(entry.getValue().toLowerCase(), entry.getKey()); - } - } - - /** - * @return the maximum genreId that is part of the official Standard, genres above this were added by - * Winamp later. - */ - public static int getMaxStandardGenreId() { - return MAX_STANDARD_GENRE_ID; - } - - public static GenreTypes getInstanceOf() { - if (genreTypes == null) { - genreTypes = new GenreTypes(); - } - return genreTypes; - } - - /** - * Get Id for name, match is not case sensitive - * - * @param name - * @return - */ - public Integer getIdForName(String name) { - return nameToIdMap.get(name.toLowerCase()); - } -} diff --git a/src/main/java/org/jaudiotagger/tag/reference/ID3V2Version.java b/src/main/java/org/jaudiotagger/tag/reference/ID3V2Version.java deleted file mode 100644 index dfc5e84..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/ID3V2Version.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.jaudiotagger.tag.reference; - -/** - * Defines ID3V2 Versions - */ -public enum ID3V2Version { - ID3_V22, - ID3_V23, - ID3_V24,; -} diff --git a/src/main/java/org/jaudiotagger/tag/reference/ISOCountry.java b/src/main/java/org/jaudiotagger/tag/reference/ISOCountry.java deleted file mode 100644 index b7053e9..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/ISOCountry.java +++ /dev/null @@ -1,329 +0,0 @@ -package org.jaudiotagger.tag.reference; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * Represents the ISO 3166-1 Country List with ISO 3166-1-alpha-2 code - *

    - * Contains an enum of countries, their two letter code and description - * with additional method to allow an enum to be found by its two letter code or its description. - * More details at http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm#c - */ -public class ISOCountry { - private static Map codeMap; - private static Map descriptionMap; - - static { - codeMap = new HashMap(); - for (Country country : Country.values()) { - codeMap.put(country.code, country); - } - - descriptionMap = new HashMap(); - for (Country country : Country.values()) { - descriptionMap.put(country.description, country); - } - - } - - /** - * @param code - * @return enum with this two letter code - */ - public static Country getCountryByCode(String code) { - return codeMap.get(code); - } - - /** - * @param description - * @return enum with this description - */ - public static Country getCountryByDescription(String description) { - return descriptionMap.get(description); - } - - public static String[] getDescriptionsAsArray() { - List descriptions = new ArrayList(); - for (Country country : Country.values()) { - descriptions.add(country.description); - } - return descriptions.toArray(new String[0]); - } - - /** - * List of valid Iso Country, shows 2 letter abbreviation and country human readable name - */ - public enum Country { - AFGHANISTAN(" AF", "Afghanistan"), - ALAND_ISLANDS("AX", "Åland Islands"), - ALBANIA("AL", "Albania"), - ALGERIA("DZ", "Algeria"), - AMERICAN_SAMOA("AS", "American Samoa"), - ANDORRA("AD", "Andorra"), - ANGOLA("AO", "Angola"), - ANGUILLA("AI", "Anguilla"), - ANTARCTICA("AQ", "Antarctica"), - ANTIGUA_AND_BARBUDA("AG", "Antigua and Barbuda"), - ARGENTINA("AR", "Argentina"), - ARMENIA("AM", "Armenia"), - ARUBA("AW", "Aruba"), - AUSTRALIA("AU", "Australia"), - AUSTRIA("AT", "Austria"), - AZERBAIJAN("AZ", "Azerbaijan"), - BAHAMAS("BS", "Bahamas"), - BAHRAIN("BH", "Bahrain"), - BANGLADESH("BD", "Bangladesh"), - BARBADOS("BB", "Barbados"), - BELARUS("BY", "Belarus"), - BELGIUM("BE", "Belgium"), - BELIZE("BZ", "Belize"), - BENIN("BJ", "Benin"), - BERMUDA("BM", "Bermuda"), - BHUTAN("BT", "Bhutan"), - BOLIVIA("BO", "Bolivia"), - BOSNIA_AND_HERZEGOVINA("BA", "Bosnia and herzegovina"), - BOTSWANA("BW", "Botswana"), - BOUVET_ISLAND("BV", "Bouvet_Island"), - BRAZIL("BR", "Brazil"), - BRITISH_INDIAN_OCEAN_TERRITORY("IO", "British Indian Ocean Territory"), - BRUNEI_DARUSSALAM("BN", "Brunei Darussalam"), - BULGARIA("BG", "Bulgaria"), - BURKINA_FASO("BF", "Burkina Faso"), - BURUNDI("BI", "Burundi"), - CAMBODIA("KH", "Cambodia"), - CAMEROON("CM", "Cameroon"), - CANADA("CA", "Canada"), - CAPE_VERDE("CV", "Cape Verde"), - CAYMAN_ISLANDS("KY", "Cayman Islands"), - CENTRAL_AFRICAN_REPUBLIC("CF", "Central African Republic"), - CHAD("TD", "Chad"), - CHILE("CL", "Chile"), - CHINA("CN", "China"), - CHRISTMAS_ISLAND("CX", "Christmas Island"), - COCOS_KEELING_ISLANDS("CC", "Cocos Keeling Islands"), - COLOMBIA("CO", "Colombia"), - COMOROS("KM", "Comoros"), - CONGO("CG", "Congo"), - THE_DEMOCRATIC_REPUBLIC_OF_CONGO("CD", "The Democratic Republic Of Congo"), - COOK_ISLANDS("CK", "Cook Islands"), - COSTA_RICA("CR", "Costa Rica"), - COTE_D_IVOIRE("CI", "Ivory Coast"), - CROATIA("HR", "Croatia"), - CUBA("CU", "Cuba"), - CYPRUS("CY", "Cyprus"), - CZECH_REPUBLIC("CZ", "Czech Republic"), - DENMARK("DK", "Denmark"), - DJIBOUTI("DJ", "Djibouti"), - DOMINICA("DM", "Dominica"), - DOMINICAN_REPUBLIC("DO", "Dominican Republic"), - ECUADOR("EC", "Ecuador"), - EGYPT("EG", "Egypt"), - EL_SALVADOR("SV", "El Salvador"), - EQUATORIAL_GUINEA("GQ", "Equatorial Guinea"), - ERITREA("ER", "Eritrea"), - ESTONIA("EE", "Estonia"), - ETHIOPIA("ET", "Ethiopia"), - FALKLAND_ISLANDS("FK", "Falkland Islands"), - FAROE_ISLANDS("FO", "Faroe Islands"), - FIJI("FJ", "Fiji"), - FINLAND("FI", "Finland"), - FRANCE("FR", "France"), - FRENCH_GUIANA("GF", "French Guiana"), - FRENCH_POLYNESIA("PF", "French Polynesia"), - FRENCH_SOUTHERN_TERRITORIES("TF", "French Southern Territories"), - GABON("GA", "Gabon"), - GAMBIA("GM", "Gambia"), - GEORGIA("GE", "Georgia"), - GERMANY("DE", "Germany"), - GHANA("GH", "Ghana"), - GIBRALTAR("GI", "Gibraltar"), - GREECE("GR", "Greece"), - GREENLAND("GL", "Greenland"), - GRENADA("GD", "Grenada"), - GUADELOUPE("GP", "Guadeloupe"), - GUAM("GU", "Guam"), - GUATEMALA("GT", "Guatemala"), - GUERNSEY("GG", "Guernsey"), - GUINEA("GN", "Guinea"), - GUINEA_BISSAU("GW", "Guinea_Bissau"), - GUYANA("GY", "Guyana"), - HAITI("HT", "Haiti"), - HEARD_ISLAND_AND_MCDONALD_ISLANDS("HM", "Heard Island and Mcdonald Islands"), - HONDURAS("HN", "Honduras"), - HONG_KONG("HK", "Hong Kong"), - HUNGARY("HU", "Hungary"), - ICELAND("IS", "Iceland"), - INDIA("IN", "India"), - INDONESIA("ID", "Indonesia"), - IRAN("IR", "Iran"), - IRAQ("IQ", "Iraq"), - IRELAND("IE", "Ireland"), - ISLE_OF_MAN("IM", "Isle Of Man"), - ISRAEL("IL", "Israel"), - ITALY("IT", "Italy"), - JAMAICA("JM", "Jamaica"), - JAPAN("JP", "Japan"), - JERSEY("JE", "Jersey"), - JORDAN("JO", "Jordan"), - KAZAKHSTAN("KZ", "Kazakhstan"), - KENYA("KE", "Kenya"), - KIRIBATI("KI", "Kiribati"), - KOREA_NORTH("KP", "North Korea"), - KOREA_SOUTH("KR", "South Korea"), - KUWAIT("KW", "Kuwait"), - KYRGYZSTAN("KG", "Kyrgyzstan"), - LAO_PEOPLES_DEMOCRATIC_REPUBLIC("LA", "Lao"), - LATVIA("LV", "Latvia"), - LEBANON("LB", "Lebanon"), - LESOTHO("LS", "Lesotho"), - LIBERIA("LR", "Liberia"), - LIBYAN_ARAB_JAMAHIRIYA("LY", "Libyan Arab Jamahiriya"), - LIECHTENSTEIN("LI", "Liechtenstein"), - LITHUANIA("LT", "Lithuania"), - LUXEMBOURG("LU", "Luxembourg"), - MACAO("MO", "Macao"), - MACEDONIA("MK", "Macedonia"), - MADAGASCAR("MG", "Madagascar"), - MALAWI("MW", "Malawi"), - MALAYSIA("MY", "Malaysia"), - MALDIVES("MV", "Maldives"), - MALI("ML", "Mali"), - MALTA("MT", "Malta"), - MARSHALL_ISLANDS("MH", "Marshall Islands"), - MARTINIQUE("MQ", "Martinique"), - MAURITANIA("MR", "Mauritania"), - MAURITIUS("MU", "Mauritius"), - MAYOTTE("YT", "Mayotte"), - MEXICO("MX", "Mexico"), - MICRONESIA("FM", "Micronesia"), - MOLDOVA("MD", "Moldova"), - MONACO("MC", "Monaco"), - MONGOLIA("MN", "Mongolia"), - MONTENEGRO("ME", "Montenegro"), - MONTSERRAT("MS", "Montserrat"), - MOROCCO("MA", "Morocco"), - MOZAMBIQUE("MZ", "Mozambique"), - MYANMAR("MM", "Myanmar"), - NAMIBIA("NA", "Namibia"), - NAURU("NR", "Nauru"), - NEPAL("NP", "Nepal"), - NETHERLANDS("NL", "Netherlands"), - NETHERLANDS_ANTILLES("AN", "Netherlands Antilles"), - NEW_CALEDONIA("NC", "New Caledonia"), - NEW_ZEALAND("NZ", "New Zealand"), - NICARAGUA("NI", "Nicaragua"), - NIGER("NE", "Niger"), - NIGERIA("NG", "Nigeria"), - NIUE("NU", "Niue"), - NORFOLK_ISLAND("NF", "Norfolk Island"), - NORTHERN_MARIANA_ISLANDS("MP", "Northern Mariana Islands"), - NORWAY("NO", "Norway"), - OMAN("OM", "Oman"), - PAKISTAN("PK", "Pakistan"), - PALAU("PW", "Palau"), - PALESTINIAN_TERRITORY_OCCUPIED("PS", "Palestinian Territory Occupied"), - PANAMA("PA", "Panama"), - PAPUA_NEW_GUINEA("PG", "Papua New Guinea"), - PARAGUAY("PY", "Paraguay"), - PERU("PE", "Peru"), - PHILIPPINES("PH", "Philippines"), - PITCAIRN("PN", "Pitcairn"), - POLAND("PL", "Poland"), - PORTUGAL("PT", "Portugal"), - PUERTO_RICO("PR", "Puerto Rico"), - QATAR("QA", "Qatar"), - REUNION("RE", "Union"), - ROMANIA("RO", "Romania"), - RUSSIAN_FEDERATION("RU", "Russia"), - RWANDA("RW", "Rwanda"), - SAINT_BARTHOLEMY("BL", "Lemy"), - SAINT_HELENA("SH", "St Helena"), - SAINT_KITTS_AND_NEVIS("KN", "St Kitts and Nevis"), - SAINT_LUCIA("LC", "St Lucia"), - SAINT_MARTIN("MF", "St Martin"), - SAINT_PIERRE_AND_MIQUELON("PM", "St Pierre and Miquelon"), - SAINT_VINCENT_AND_THE_GRENADINES("VC", "St Vincent and the Grenadines"), - SAMOA("WS", "Samoa"), - SAN_MARINO("SM", "San_Marino"), - SAO_TOME_AND_PRINCIPE("ST", "Sao Tome and Principe"), - SAUDI_ARABIA("SA", "Saudi Arabia"), - SENEGAL("SN", "Senegal"), - SERBIA("RS", "Serbia"), - SEYCHELLES("SC", "Seychelles"), - SIERRA_LEONE("SL", "Sierra Leone"), - SINGAPORE("SG", "Singapore"), - SLOVAKIA("SK", "Slovakia"), - SLOVENIA("SI", "Slovenia"), - SOLOMON_ISLANDS("SB", "Solomon Islands"), - SOMALIA("SO", "Somalia"), - SOUTH_AFRICA("ZA", "South Africa"), - SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_Islands("GS", "South Georgia and the South Sandwich Islands"), - SPAIN("ES", "Spain"), - SRI_LANKA("LK", "Sri Lanka"), - SUDAN("SD", "Sudan"), - SURINAME("SR", "Suriname"), - SVALBARD_AND_JAN_MAYEN("SJ", "Svalbard and Jan Mayen"), - SWAZILAND("SZ", "Swaziland"), - SWEDEN("SE", "Sweden"), - SWITZERLAND("CH", "Switzerland"), - SYRIA("SY", "Syria"), - TAIWAN("TW", "Taiwan"), - TAJIKISTAN("TJ", "Tajikistan"), - TANZANIA("TZ", "Tanzania"), - THAILAND("TH", "Thailand"), - TIMOR_LESTE("TL", "Timor Leste"), - TOGO("TG", "Togo"), - TOKELAU("TK", "Tokelau"), - TONGA("TO", "Tonga"), - TRINIDAD_AND_TOBAGO("TT", "Trinidad and Tobago"), - TUNISIA("TN", "Tunisia"), - TURKEY("TR", "Turkey"), - TURKMENISTAN("TM", "Turkmenistan"), - TURKS_AND_CAICOS_ISLANDS("TC", "Turks and Caicos Islands"), - TUVALU("TV", "Tuvalu"), - UGANDA("UG", "Uganda"), - UKRAINE("UA", "Ukraine"), - UNITED_ARAB_EMIRATES("AE", "United Arab Emirates"), - UNITED_KINGDOM("GB", "United Kingdom"), - UNITED_STATES("US", "United States"), - UNITED_STATES_MINOR_OUTLYING_ISLANDS("UM", "United States Minor Outlying Islands"), - URUGUAY("UY", "Uruguay"), - UZBEKISTAN("UZ", "Uzbekistan"), - VANUATU("VU", "Vanuatu"), - VATICAN_CITY("VA", "Vatican City"), - VENEZUELA("VE", "Venezuela"), - VIETNAM("VN", "Vietnam"), - VIRGIN_ISLANDS_BRITISH("VG", "British Virgin Islands"), - VIRGIN_ISLANDS_US("VI", "US Virgin Islands"), - WALLIS_AND_FUTUNA("WF", "Wallis and Futuna"), - WESTERN_SAHARA("EH", "Western Sahara"), - YEMEN("YE", "Yemen"), - ZAMBIA("ZM", "Zambia"), - ZIMBABWE("ZW", "Zimbabwe"); - - - private String code; - private String description; - - Country(String code, String description) { - this.code = code; - this.description = description; - } - - public String getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public String toString() { - return getDescription(); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/reference/ISOScript.java b/src/main/java/org/jaudiotagger/tag/reference/ISOScript.java deleted file mode 100644 index 27cf894..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/ISOScript.java +++ /dev/null @@ -1,207 +0,0 @@ -package org.jaudiotagger.tag.reference; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * Represents the ISO Script - *

    - * Contains an enum of script, their four letter code and description - * with additional method to allow an enum to be found by its four letter code or its description. - */ -public class ISOScript { - private static Map codeMap; - private static Map descriptionMap; - - static { - codeMap = new HashMap(); - for (Script script : Script.values()) { - codeMap.put(script.code, script); - } - - descriptionMap = new HashMap(); - for (Script script : Script.values()) { - descriptionMap.put(script.description, script); - } - - } - - /** - * @param code - * @return enum with this two letter code - */ - public static Script getScriptByCode(String code) { - return codeMap.get(code); - } - - /** - * @param description - * @return enum with this description - */ - public static Script getScriptByDescription(String description) { - return descriptionMap.get(description); - } - - public static String[] getDescriptionsAsArray() { - List descriptions = new ArrayList(); - for (Script script : Script.values()) { - descriptions.add(script.description); - } - return descriptions.toArray(new String[0]); - } - - /** - * List of valid Iso Scripts, shows 4 letter abbreviation and script human readable name - */ - public enum Script { - ARABIC("Arab", "Arabic"), - IMPERIAL_ARAMAIC("Armi", "Imperial Aramaic"), - ARMENIAN("Armn", "Armenian"), - AVESTAN("Avst", "Avestan"), - BALINESE("Bali", "Balinese"), - BATAK("Batk", "Batak"), - BENGALI("Beng", "Bengali"), - BLISSYMBOLS("Blis", "Blissymbols"), - BOPOMOFO("Bopo", "Bopomofo"), - BRAHMI("Brah", "Brahmi"), - BRAILLE("Brai", "Braille"), - BUGINESE("Bugi", "Buginese"), - BUHID("Buhd", "Buhid"), - CHAKMA("Cakm", "Chakma"), - CANADIAN_SYLLABICS("Cans", "Canadian Syllabics"), - CARIAN("Cari", "Carian"), - CHAM("Cham", "Cham"), - CHEROKEE("Cher", "Cherokee"), - CIRTH("Cirt", "Cirth"), - COPTIC("Copt", "Coptic"), - CYPRIOT("Cprt", "Cypriot"), - CYRILLIC("Cyrl", "Cyrillic"), - CYRILLIC_OLD_CHURCH_SLAVONIC_VARIANT("Cyrs", "Cyrillic (Old Church Slavonic variant)"), - DEVANAGARI("Deva", "Devanagari"), - DESERET("Dsrt", "Deseret"), - EGYPTIAN_DEMOTIC("Egyd", "Egyptian demotic"), - EGYPTIAN_HIERATIC("Egyh", "Egyptian hieratic"), - EGYPTIAN_HIEROGLYPHS("Egyp", "Egyptian hieroglyphs"), - ETHIOPIC("Ethi", "Ethiopic"), - KHUTSURI("Geok", "Khutsuri"), - GEORGIAN("Geor", "Georgian"), - GLAGOLITIC("Glag", "Glagolitic"), - GOTHIC("Goth", "Gothic"), - GREEK("Grek", "Greek"), - GUJARATI("Gujr", "Gujarati"), - GURMUKHI("Guru", "Gurmukhi"), - HANGUL("Hang", "Hangul"), - HAN_HANJA("Hani", "Han (Hanzi, Kanji, Hanja)"), - HANUNOO("Hano", "Hanunoo"), - HAN_SIMPLIFIED("Hans", "Han (Simplified variant)"), - HAN_TRADITIONAL("Hant", "Han (Traditional variant)"), - HEBREW("Hebr", "Hebrew"), - HIRAGANA("Hira", "Hiragana"), - PAHAWH_HMONG("Hmng", "Pahawh Hmong"), - HIRAGANA_KATAKANA("Hrkt", "Hiragana + Katakana"), - OLD_HUNGARIAN("Hung", "Old Hungarian"), - INDUS("Inds", "Indus"), - OLD_ITALIC("Ital", "Old Italic"), - JAVANESE("Java", "Javanese"), - JAPANESE("Jpan", "Japanese"), - KAYAH_LI("Kali", "Kayah Li"), - KATAKANA("Kana", "Katakana"), - KHAROSHTHI("Khar", "Kharoshthi"), - KHMER("Khmr", "Khmer"), - KANNADA("Knda", "Kannada"), - KOREAN("Kore", "Korean"), - KAITHI("Kthi", "Kaithi"), - LANNA("Lana", "Lanna"), - LAO("Laoo", "Lao"), - LATIN_FRAKTUR_VARIANT("Latf", "Latin (Fraktur variant)"), - LATIN_GAELIC_VARIANT("Latg", "Latin (Gaelic variant)"), - LATIN("Latn", "Latin"), - LEPCHA("Lepc", "Lepcha"), - LIMBU("Limb", "Limbu"), - LINEAR_A("Lina", "Linear A"), - LINEAR_B("Linb", "Linear B"), - LYCIAN("Lyci", "Lycian"), - LYDIAN("Lydi", "Lydian"), - MANDAEAN("Mand", "Mandaean"), - MANICHAEAN("Mani", "Manichaean"), - MAYAN_HIEROGLYPHS("Maya", "Mayan hieroglyphs"), - MEROITIC("Mero", "Meroitic"), - MALAYALAM("Mlym", "Malayalam"), - MONGOLIAN("Mong", "Mongolian"), - MOON("Moon", "Moon"), - MEITEI_MAYEK("Mtei", "Meitei Mayek"), - MYANMAR("Mymr", "Myanmar"), - NKO("Nkoo", "N'ko"), - OGHAM("Ogam", "Ogham"), - OL_CHIKI("Olck", "Ol Chiki"), - ORKHON("Orkh", "Orkhon"), - ORIYA("Orya", "Oriya"), - OSMANYA("Osma", "Osmanya"), - OLD_PERMIC("Perm", "Old Permic"), - PHAGS_PA("Phag", "Phags-pa"), - INSCRIPTIONAL_PAHLAVI("Phli", "Inscriptional Pahlavi"), - PSALTER_PAHLAVI("Phlp", "Psalter Pahlavi"), - BOOK_PAHLAVI("Phlv", "Book Pahlavi"), - PHOENICIAN("Phnx", "Phoenician"), - POLLARD_PHONETIC("Plrd", "Pollard Phonetic"), - INSCRIPTIONAL_PARTHIAN("Prti", "Inscriptional Parthian"), - REJANG("Rjng", "Rejang"), - RONGORONGO("Roro", "Rongorongo"), - RUNIC("Runr", "Runic"), - SAMARITAN("Samr", "Samaritan"), - SARATI("Sara", "Sarati"), - SAURASHTRA("Saur", "Saurashtra"), - SIGNWRITING("Sgnw", "SignWriting"), - SHAVIAN("Shaw", "Shavian"), - SINHALA("Sinh", "Sinhala"), - SUNDANESE("Sund", "Sundanese"), - SYLOTI_NAGRI("Sylo", "Syloti Nagri"), - SYRIAC("Syrc", "Syriac"), - SYRIAC_ESTRANGELO_VARIANT("Syre", "Syriac (Estrangelo variant)"), - SYRIAC_WESTERN_VARIANT("Syrj", "Syriac (Western variant)"), - SYRIAC_EASTERN_VARIANT("Syrn", "Syriac (Eastern variant)"), - TAGBANWA("Tagb", "Tagbanwa"), - TAI_LE("Tale", "Tai Le"), - TAI_LUE("Talu", "Tai Lue"), - TAMIL("Taml", "Tamil"), - TAI_VIET("Tavt", "Tai Viet"), - TELUGU("Telu", "Telugu"), - TENGWAR("Teng", "Tengwar"), - TIFINAGH("Tfng", "Tifinagh"), - TAGALOG("Tglg", "Tagalog"), - THAANA("Thaa", "Thaana"), - THAI("Thai", "Thai"), - TIBETAN("Tibt", "Tibetan"), - UGARITIC("Ugar", "Ugaritic"), - VAI("Vaii", "Vai"), - VISIBLE_SPEECH("Visp", "Visible Speech"), - OLD_PERSIAN("Xpeo", "Old Persian"), - CUNEIFORM_SUMERO_AKKADIAN("Xsux", "Cuneiform, Sumero-Akkadian"), - YI("Yiii", "Yi"), - MATHEMATICAL_NOTATION("Zmth", "Mathematical notation"), - SYMBOLS("Zsym", "Symbols"),; - - private String code; - private String description; - - Script(String code, String description) { - this.code = code; - this.description = description; - } - - public String getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public String toString() { - return getDescription(); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/reference/Languages.java b/src/main/java/org/jaudiotagger/tag/reference/Languages.java deleted file mode 100644 index 786338a..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/Languages.java +++ /dev/null @@ -1,518 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: Languages.java 942 2010-12-17 20:13:07Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Valid Languages for ID Tags - */ -package org.jaudiotagger.tag.reference; - -import org.jaudiotagger.tag.datatype.AbstractStringStringValuePair; - -public class Languages extends AbstractStringStringValuePair { - public static final String DEFAULT_ID = "eng"; - public static final String MEDIA_MONKEY_ID = "XXX"; - public static final String WINAMP_ID = "\0\0\0"; - - public static final String DEFAULT_VALUE = "English"; - - //The number of bytes used to hold the language field size - public static final int LANGUAGE_FIELD_SIZE = 3; - - private static Languages languageTypes; - - - private Languages() { - idToValue.put("aar", "Afar"); - idToValue.put("abk", "Abkhazian"); - idToValue.put("ace", "Achinese"); - idToValue.put("ach", "Acoli"); - idToValue.put("ada", "Adangme"); - idToValue.put("afa", "Afro-Asiatic"); - idToValue.put("afh", "Afrihili"); - idToValue.put("afr", "Afrikaans"); - idToValue.put("aka", "Akan"); - idToValue.put("akk", "Akkadian"); - idToValue.put("alb", "Albanian"); - idToValue.put("ale", "Aleut"); - idToValue.put("alg", "Algonquian languages"); - idToValue.put("amh", "Amharic"); - idToValue.put("ang", "Old English,(ca.450-1100)"); - idToValue.put("apa", "Apache languages"); - idToValue.put("ara", "Arabic"); - idToValue.put("arc", "Aramaic"); - idToValue.put("arm", "Armenian"); - idToValue.put("arn", "Araucanian"); - idToValue.put("arp", "Arapaho"); - idToValue.put("art", "Artificial"); - idToValue.put("arw", "Arawak"); - idToValue.put("asm", "Assamese"); - idToValue.put("ast", "Asturian; Bable"); - idToValue.put("ath", "Athapascan languages"); - idToValue.put("aus", "Australian languages"); - idToValue.put("ava", "Avaric"); - idToValue.put("ave", "Avestan"); - idToValue.put("awa", "Awadhi"); - idToValue.put("aym", "Aymara"); - idToValue.put("aze", "Azerbaijani"); - idToValue.put("bad", "Banda"); - idToValue.put("bai", "Bamileke languages"); - idToValue.put("bak", "Bashkir"); - idToValue.put("bal", "Baluchi"); - idToValue.put("bam", "Bambara"); - idToValue.put("ban", "Balinese"); - idToValue.put("baq", "Basque"); - idToValue.put("bas", "Basa"); - idToValue.put("bat", "Baltic"); - idToValue.put("bej", "Beja"); - idToValue.put("bel", "Belarusian"); - idToValue.put("bem", "Bemba"); - idToValue.put("ben", "Bengali"); - idToValue.put("ber", "Berber"); - idToValue.put("bho", "Bhojpuri"); - idToValue.put("bih", "Bihari"); - idToValue.put("bik", "Bikol"); - idToValue.put("bin", "Bini"); - idToValue.put("bis", "Bislama"); - idToValue.put("bla", "Siksika"); - idToValue.put("bnt", "Bantu"); - idToValue.put("bod", "Tibetan"); - idToValue.put("bos", "Bosnian"); - idToValue.put("bra", "Braj"); - idToValue.put("bre", "Breton"); - idToValue.put("btk", "Batak (Indonesia)"); - idToValue.put("bua", "Buriat"); - idToValue.put("bug", "Buginese"); - idToValue.put("bul", "Bulgarian"); - idToValue.put("bur", "Burmese"); - idToValue.put("cad", "Caddo"); - idToValue.put("cai", "Central American Indian"); - idToValue.put("car", "Carib"); - idToValue.put("cat", "Catalan"); - idToValue.put("cau", "Caucasian"); - idToValue.put("ceb", "Cebuano"); - idToValue.put("cel", "Celtic"); - idToValue.put("ces", "Czech"); - idToValue.put("cha", "Chamorro"); - idToValue.put("chb", "Chibcha"); - idToValue.put("che", "Chechen"); - idToValue.put("chg", "Chagatai"); - idToValue.put("chi", "Chinese"); - idToValue.put("chk", "Chuukese"); - idToValue.put("chm", "Mari"); - idToValue.put("chn", "Chinook jargon"); - idToValue.put("cho", "Choctaw"); - idToValue.put("chp", "Chipewyan"); - idToValue.put("chr", "Cherokee"); - idToValue.put("chu", "Church Slavic"); - idToValue.put("chv", "Chuvash"); - idToValue.put("chy", "Cheyenne"); - idToValue.put("cmc", "Chamic languages"); - idToValue.put("cop", "Coptic"); - idToValue.put("cor", "Cornish"); - idToValue.put("cos", "Corsican"); - idToValue.put("cpe", "Creoles and pidgins, English based"); - idToValue.put("cpf", "Creoles and pidgins, French based"); - idToValue.put("cpp", "Creoles and pidgins"); - idToValue.put("cre", "Cree"); - idToValue.put("crp", "Creoles and pidgins"); - idToValue.put("cus", "Cushitic"); - idToValue.put("cym", "Welsh"); - idToValue.put("cze", "Czech"); - idToValue.put("dak", "Dakota"); - idToValue.put("dan", "Danish"); - idToValue.put("day", "Dayak"); - idToValue.put("del", "Delaware"); - idToValue.put("den", "Slave (Athapascan)"); - idToValue.put("deu", "German"); - idToValue.put("dgr", "Dogrib"); - idToValue.put("din", "Dinka"); - idToValue.put("div", "Divehi"); - idToValue.put("doi", "Dogri"); - idToValue.put("dra", "Dravidian"); - idToValue.put("dua", "Duala"); - idToValue.put("dum", "Dutch, Middle (ca.1050-1350)"); - idToValue.put("dut", "Dutch"); - idToValue.put("dyu", "Dyula"); - idToValue.put("dzo", "Dzongkha"); - idToValue.put("efi", "Efik"); - idToValue.put("egy", "Egyptian (Ancient)"); - idToValue.put("eka", "Ekajuk"); - idToValue.put("ell", "Greek, Modern (1453-)"); - idToValue.put("elx", "Elamite"); - idToValue.put("eng", "English"); - idToValue.put("enm", "English, Middle (1100-1500)"); - idToValue.put("epo", "Esperanto"); - idToValue.put("est", "Estonian"); - idToValue.put("eus", "Basque"); - idToValue.put("ewe", "Ewe"); - idToValue.put("ewo", "Ewondo"); - idToValue.put("fan", "Fang"); - idToValue.put("fao", "Faroese"); - idToValue.put("fas", "Persian"); - idToValue.put("fat", "Fanti"); - idToValue.put("fij", "Fijian"); - idToValue.put("fin", "Finnish"); - idToValue.put("fiu", "Finno-Ugrian"); - idToValue.put("fon", "Fon"); - idToValue.put("fra", "French"); - idToValue.put("frm", "French, Middle (ca.1400-1800)"); - idToValue.put("fro", "French, Old (842-ca.1400)"); - idToValue.put("fry", "Frisian"); - idToValue.put("ful", "Fulah"); - idToValue.put("fur", "Friulian"); - idToValue.put("gaa", "Ga"); - idToValue.put("gay", "Gayo"); - idToValue.put("gba", "Gbaya"); - idToValue.put("gem", "Germanic"); - idToValue.put("geo", "Georgian"); - idToValue.put("ger", "German"); - idToValue.put("gez", "Geez"); - idToValue.put("gil", "Gilbertese"); - idToValue.put("gla", "Gaelic; Scottish Gaelic"); - idToValue.put("gle", "Irish"); - idToValue.put("glg", "Gallegan"); - idToValue.put("glv", "Manx"); - idToValue.put("gmh", "German, Middle High (ca.1050-1500)"); - idToValue.put("goh", "German, Old High (ca.750-1050)"); - idToValue.put("gon", "Gondi"); - idToValue.put("gor", "Gorontalo"); - idToValue.put("got", "Gothic"); - idToValue.put("grb", "Grebo"); - idToValue.put("grc", "Greek, Ancient (to 1453)"); - idToValue.put("gre", "Greek, Modern (1453-)"); - idToValue.put("grn", "Guarani"); - idToValue.put("guj", "Gujarati"); - idToValue.put("gwi", "Gwich´in"); - idToValue.put("hai", "Haida"); - idToValue.put("hau", "Hausa"); - idToValue.put("haw", "Hawaiian"); - idToValue.put("heb", "Hebrew"); - idToValue.put("her", "Herero"); - idToValue.put("hil", "Hiligaynon"); - idToValue.put("him", "Himachali"); - idToValue.put("hin", "Hindi"); - idToValue.put("hit", "Hittite"); - idToValue.put("hmn", "Hmong"); - idToValue.put("hmo", "Hiri Motu"); - idToValue.put("hrv", "Croatian"); - idToValue.put("hun", "Hungarian"); - idToValue.put("hup", "Hupa"); - idToValue.put("hye", "Armenian"); - idToValue.put("iba", "Iban"); - idToValue.put("ibo", "Igbo"); - idToValue.put("ice", "Icelandic"); - idToValue.put("ido", "Ido"); - idToValue.put("ijo", "Ijo"); - idToValue.put("iku", "Inuktitut"); - idToValue.put("ile", "Interlingue"); - idToValue.put("ilo", "Iloko"); - idToValue.put("ina", "Interlingua"); - idToValue.put("inc", "Indic"); - idToValue.put("ind", "Indonesian"); - idToValue.put("ine", "Indo-European"); - idToValue.put("ipk", "Inupiaq"); - idToValue.put("ira", "Iranian (Other)"); - idToValue.put("iro", "Iroquoian languages"); - idToValue.put("isl", "Icelandic"); - idToValue.put("ita", "Italian"); - idToValue.put("jav", "Javanese"); - idToValue.put("jpn", "Japanese"); - idToValue.put("jpr", "Judeo-Persian"); - idToValue.put("jrb", "Judeo-Arabic"); - idToValue.put("kaa", "Kara-Kalpak"); - idToValue.put("kab", "Kabyle"); - idToValue.put("kac", "Kachin"); - idToValue.put("kal", "Kalaallisut"); - idToValue.put("kam", "Kamba"); - idToValue.put("kan", "Kannada"); - idToValue.put("kar", "Karen"); - idToValue.put("kas", "Kashmiri"); - idToValue.put("kat", "Georgian"); - idToValue.put("kau", "Kanuri"); - idToValue.put("kaw", "Kawi"); - idToValue.put("kaz", "Kazakh"); - idToValue.put("kha", "Khasi"); - idToValue.put("khi", "Khoisan"); - idToValue.put("khm", "Khmer"); - idToValue.put("kho", "Khotanese"); - idToValue.put("kik", "Kikuyu; Gikuyu"); - idToValue.put("kin", "Kinyarwanda"); - idToValue.put("kir", "Kirghiz"); - idToValue.put("kmb", "Kimbundu"); - idToValue.put("kok", "Konkani"); - idToValue.put("kom", "Komi"); - idToValue.put("kon", "Kongo"); - idToValue.put("kor", "Korean"); - idToValue.put("kos", "Kosraean"); - idToValue.put("kpe", "Kpelle"); - idToValue.put("kro", "Kru"); - idToValue.put("kru", "Kurukh"); - idToValue.put("kua", "Kuanyama; Kwanyama"); - idToValue.put("kum", "Kumyk"); - idToValue.put("kur", "Kurdish"); - idToValue.put("kut", "Kutenai"); - idToValue.put("lad", "Ladino"); - idToValue.put("lah", "Lahnda"); - idToValue.put("lam", "Lamba"); - idToValue.put("lao", "Lao"); - idToValue.put("lat", "Latin"); - idToValue.put("lav", "Latvian"); - idToValue.put("lez", "Lezghian"); - idToValue.put("lin", "Lingala"); - idToValue.put("lit", "Lithuanian"); - idToValue.put("lol", "Mongo"); - idToValue.put("loz", "Lozi"); - idToValue.put("ltz", "Luxembourgish; Letzeburgesch"); - idToValue.put("lua", "Luba-Lulua"); - idToValue.put("lub", "Luba-Katanga"); - idToValue.put("lug", "Ganda"); - idToValue.put("lui", "Luiseno"); - idToValue.put("lun", "Lunda"); - idToValue.put("luo", "Luo (Kenya and Tanzania)"); - idToValue.put("lus", "lushai"); - idToValue.put("mac", "Macedonian"); - idToValue.put("mad", "Madurese"); - idToValue.put("mag", "Magahi"); - idToValue.put("mah", "Marshallese"); - idToValue.put("mai", "Maithili"); - idToValue.put("mak", "Makasar"); - idToValue.put("mal", "Malayalam"); - idToValue.put("man", "Mandingo"); - idToValue.put("mao", "Maori"); - idToValue.put("map", "Austronesian"); - idToValue.put("mar", "Marathi"); - idToValue.put("mas", "Masai"); - idToValue.put("may", "Malay"); - idToValue.put("mdr", "Mandar"); - idToValue.put("men", "Mende"); - idToValue.put("mga", "Irish, Middle (900-1200)"); - idToValue.put("mic", "Micmac"); - idToValue.put("min", "Minangkabau"); - idToValue.put("mis", "Miscellaneous languages"); - idToValue.put("mkd", "Macedonian"); - idToValue.put("mkh", "Mon-Khmer"); - idToValue.put("mlg", "Malagasy"); - idToValue.put("mlt", "Maltese"); - idToValue.put("mnc", "Manchu"); - idToValue.put("mni", "Manipuri"); - idToValue.put("mno", "Manobo languages"); - idToValue.put("moh", "Mohawk"); - idToValue.put("mol", "Moldavian"); - idToValue.put("mon", "Mongolian"); - idToValue.put("mos", "Mossi"); - idToValue.put("mri", "Maori"); - idToValue.put("msa", "Malay"); - idToValue.put("mul", "Multiple languages"); - idToValue.put("mun", "Munda languages"); - idToValue.put("mus", "Creek"); - idToValue.put("mwr", "Marwari"); - idToValue.put("mya", "Burmese"); - idToValue.put("myn", "Mayan languages"); - idToValue.put("nah", "Nahuatl"); - idToValue.put("nai", "North American Indian"); - idToValue.put("nau", "Nauru"); - idToValue.put("nav", "Navajo; Navaho"); - idToValue.put("nbl", "South Ndebele"); - idToValue.put("nde", "North Ndebele"); - idToValue.put("ndo", "Ndonga"); - idToValue.put("nds", "Low German; Low Saxon"); - idToValue.put("nep", "Nepali"); - idToValue.put("new", "Newari"); - idToValue.put("nia", "Nias"); - idToValue.put("nic", "Niger-Kordofanian"); - idToValue.put("niu", "Niuean"); - idToValue.put("nld", "Dutch"); - idToValue.put("nno", "Norwegian Nynorsk"); - idToValue.put("nob", "Norwegian Bokmål"); - idToValue.put("non", "Norse, Old"); - idToValue.put("nor", "Norwegian"); - idToValue.put("nso", "Sotho, Northern"); - idToValue.put("nub", "Nubian languages"); - idToValue.put("nya", "Chichewa; Chewa; Nyanja"); - idToValue.put("nym", "Nyamwezi"); - idToValue.put("nyn", "Nyankole"); - idToValue.put("nyo", "Nyoro"); - idToValue.put("nzi", "Nzima"); - idToValue.put("oci", "Occitan (post 1500); Provençal"); - idToValue.put("oji", "Ojibwa"); - idToValue.put("ori", "Oriya"); - idToValue.put("orm", "Oromo"); - idToValue.put("osa", "Osage"); - idToValue.put("oss", "Ossetian; Ossetic"); - idToValue.put("ota", "Turkish, Ottoman (1500-1928)"); - idToValue.put("oto", "Otomian languages"); - idToValue.put("paa", "Papuan"); - idToValue.put("pag", "Pangasinan"); - idToValue.put("pal", "Pahlavi"); - idToValue.put("pam", "Pampanga"); - idToValue.put("pan", "Panjabi"); - idToValue.put("pap", "Papiamento"); - idToValue.put("pau", "Palauan"); - idToValue.put("peo", "Persian, Old (ca.600-400 B.C.)"); - idToValue.put("per", "Persian"); - idToValue.put("per", "Persian"); - idToValue.put("phi", "Philippine"); - idToValue.put("phn", "Phoenician"); - idToValue.put("pli", "Pali"); - idToValue.put("pol", "Polish"); - idToValue.put("pon", "Pohnpeian"); - idToValue.put("por", "Portuguese"); - idToValue.put("pra", "Prakrit languages"); - idToValue.put("pro", "Provençal, Old (to 1500)"); - idToValue.put("pus", "Pushto"); - idToValue.put("que", "Quechua"); - idToValue.put("raj", "Rajasthani"); - idToValue.put("rap", "Rapanui"); - idToValue.put("rar", "Rarotongan"); - idToValue.put("roa", "Romance"); - idToValue.put("roh", "Raeto-Romance"); - idToValue.put("rom", "Romany"); - idToValue.put("ron", "Romanian"); - idToValue.put("rum", "Romanian"); - idToValue.put("run", "Rundi"); - idToValue.put("rus", "Russian"); - idToValue.put("sad", "Sandawe"); - idToValue.put("sag", "Sango"); - idToValue.put("sah", "Yakut"); - idToValue.put("sai", "South American Indian"); - idToValue.put("sal", "Salishan languages"); - idToValue.put("sam", "Samaritan Aramaic"); - idToValue.put("san", "Sanskrit"); - idToValue.put("sas", "Sasak"); - idToValue.put("sat", "Santali"); - idToValue.put("scc", "Serbian"); - idToValue.put("sco", "Scots"); - idToValue.put("scr", "Croatian"); - idToValue.put("sel", "Selkup"); - idToValue.put("sem", "Semitic"); - idToValue.put("sga", "Irish, Old (to 900)"); - idToValue.put("sgn", "Sign languages"); - idToValue.put("shn", "Shan"); - idToValue.put("sid", "Sidamo"); - idToValue.put("sin", "Sinhales"); - idToValue.put("sio", "Siouan languages"); - idToValue.put("sit", "Sino-Tibetan"); - idToValue.put("sla", "Slavic"); - idToValue.put("slk", "Slovak"); - idToValue.put("slo", "Slovak"); - idToValue.put("slv", "Slovenian"); - idToValue.put("sma", "Southern Sami"); - idToValue.put("sme", "Northern Sami"); - idToValue.put("smi", "Sami languages"); - idToValue.put("smj", "Lule Sami"); - idToValue.put("smn", "Inari Sami"); - idToValue.put("smo", "Samoan"); - idToValue.put("sms", "Skolt Sami"); - idToValue.put("sna", "Shona"); - idToValue.put("snd", "Sindhi"); - idToValue.put("snk", "Soninke"); - idToValue.put("sog", "Sogdian"); - idToValue.put("som", "Somali"); - idToValue.put("son", "Songhai"); - idToValue.put("sot", "Sotho, Southern"); - idToValue.put("spa", "Spanish; Castilia"); - idToValue.put("sqi", "Albanian"); - idToValue.put("srd", "Sardinian"); - idToValue.put("srp", "Serbian"); - idToValue.put("srr", "Serer"); - idToValue.put("ssa", "Nilo-Saharan"); - idToValue.put("sus", "Susu"); - idToValue.put("sux", "Sumerian"); - idToValue.put("swa", "Swahili"); - idToValue.put("swe", "Swedish"); - idToValue.put("syr", "Syriac"); - idToValue.put("tah", "Tahitian"); - idToValue.put("tai", "Tai"); - idToValue.put("tam", "Tamil"); - idToValue.put("tat", "Tatar"); - idToValue.put("tel", "Telugu"); - idToValue.put("tem", "Timne"); - idToValue.put("ter", "Tereno"); - idToValue.put("tet", "Tetum"); - idToValue.put("tgk", "Tajik"); - idToValue.put("tgl", "Tagalog"); - idToValue.put("tha", "Thai"); - idToValue.put("tib", "Tibetan"); - idToValue.put("tig", "Tigre"); - idToValue.put("tir", "Tigrinya"); - idToValue.put("tiv", "Tiv"); - idToValue.put("tkl", "Tokelau"); - idToValue.put("tli", "Tlingit"); - idToValue.put("tmh", "Tamashek"); - idToValue.put("tog", "Tonga (Nyasa)"); - idToValue.put("ton", "Tonga (Tonga Islands)"); - idToValue.put("tpi", "Tok Pisin"); - idToValue.put("tsi", "Tsimshian"); - idToValue.put("tsn", "Tswana"); - idToValue.put("tso", "Tsonga"); - idToValue.put("tuk", "Turkmen"); - idToValue.put("tum", "Tumbuka"); - idToValue.put("tup", "Tupi"); - idToValue.put("tur", "Turkish"); - idToValue.put("tut", "Altaic"); - idToValue.put("tvl", "Tuvalu"); - idToValue.put("twi", "Twi"); - idToValue.put("tyv", "Tuvinian"); - idToValue.put("uga", "Ugaritic"); - idToValue.put("uig", "Uighur"); - idToValue.put("ukr", "Ukrainian"); - idToValue.put("umb", "Umbundu"); - idToValue.put("und", "Undetermined"); - idToValue.put("urd", "Urdu"); - idToValue.put("uzb", "Uzbek"); - idToValue.put("vai", "Vai"); - idToValue.put("ven", "Venda"); - idToValue.put("vie", "Vietnamese"); - idToValue.put("vol", "Volapük"); - idToValue.put("vot", "Votic"); - idToValue.put("wak", "Wakashan languages"); - idToValue.put("wal", "Walamo"); - idToValue.put("war", "Waray"); - idToValue.put("was", "Washo"); - idToValue.put("wel", "Welsh"); - idToValue.put("wen", "Sorbian languages"); - idToValue.put("wln", "Walloon"); - idToValue.put("wol", "Wolof"); - idToValue.put("xho", "Xhosa"); - idToValue.put("yao", "Yao"); - idToValue.put("yap", "Yapese"); - idToValue.put("yid", "Yiddish"); - idToValue.put("yor", "Yoruba"); - idToValue.put("ypk", "Yupik languages"); - idToValue.put("zap", "Zapotec"); - idToValue.put("zen", "Zenaga"); - idToValue.put("zha", "Zhuang; Chuang"); - idToValue.put("zho", "Chinese"); - idToValue.put("znd", "Zande"); - idToValue.put("zul", "Zulu"); - idToValue.put("zun", "Zuni"); - idToValue.put("\0\0\0", "Winamp Format"); //Not Part of Spec but commonly used by some applications - idToValue.put("XXX", "Media Monkey Format"); //Not Part of Spec but commonly used by some applications - - - createMaps(); - } - - public static Languages getInstanceOf() { - if (languageTypes == null) { - languageTypes = new Languages(); - } - return languageTypes; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/reference/MusicalKey.java b/src/main/java/org/jaudiotagger/tag/reference/MusicalKey.java deleted file mode 100644 index 1cb0170..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/MusicalKey.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.jaudiotagger.tag.reference; - -import java.util.EnumSet; -import java.util.HashMap; - -/** - * Musical key used by the Key tagFieldKey - *

    - * It is not enforced but can be used to verify the Musical key according to the ID3 specification of the TKEY field - */ -public enum MusicalKey { - NOTE_A("A"), - NOTE_B("B"), - NOTE_C("C"), - NOTE_D("D"), - NOTE_E("E"), - NOTE_F("F"), - NOTE_G("G"), - FLAT("b"), - SHARP("#"), - MINOR("m"), - OFF_KEY("o"); - - private static final int MAX_KEY_LENGTH = 3; - private final static HashMap groundKeyMap; - private final static HashMap halfKeyMap; - - static { - EnumSet groundKey = EnumSet.of(NOTE_A, NOTE_B, NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G); - groundKeyMap = new HashMap(MusicalKey.values().length); - for (MusicalKey curr : groundKey) { - groundKeyMap.put(curr.getValue(), curr); - } - EnumSet halfKey = EnumSet.of(FLAT, SHARP, MINOR); - halfKeyMap = new HashMap(MusicalKey.values().length); - for (MusicalKey curr : halfKey) { - halfKeyMap.put(curr.getValue(), curr); - } - } - - private String value; - MusicalKey(String value) { - this.value = value; - } - - public static boolean isValid(String musicalKey) { - if (musicalKey == null || musicalKey.length() > MAX_KEY_LENGTH || musicalKey.length() == 0) { - return false; - } - - - if (musicalKey.length() == 1) { - if (musicalKey.equals(OFF_KEY.getValue())) { - return true; - } - } - - if (!groundKeyMap.containsKey(musicalKey.substring(0, 1))) { - return false; - } - - if (musicalKey.length() == 2 || musicalKey.length() == 3) { - if (!halfKeyMap.containsKey(musicalKey.substring(1, 2))) { - return false; - } - } - - if (musicalKey.length() == 3) { - if (!musicalKey.substring(2, 3).equals(MINOR.getValue())) { - return false; - } - } - return true; - } - - public String getValue() { - return value; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/reference/PictureTypes.java b/src/main/java/org/jaudiotagger/tag/reference/PictureTypes.java deleted file mode 100644 index e88deaf..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/PictureTypes.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: PictureTypes.java 775 2008-12-22 13:46:26Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - * Valid Picture Types in ID3 - */ -package org.jaudiotagger.tag.reference; - -import org.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -/** - * Pictures types for Attached Pictures - *

    - *

    Note this list is used by APIC and PIC frames within ID3v2. It is also used by Flac format Picture blocks - * and WMA Picture fields. - */ -public class PictureTypes extends AbstractIntStringValuePair { - public static final int PICTURE_TYPE_FIELD_SIZE = 1; - public static final String DEFAULT_VALUE = "Cover (front)"; - public static final Integer DEFAULT_ID = 3; - private static PictureTypes pictureTypes; - private PictureTypes() { - idToValue.put(0, "Other"); - idToValue.put(1, "32x32 pixels 'file icon' (PNG only)"); - idToValue.put(2, "Other file icon"); - idToValue.put(3, "Cover (front)"); - idToValue.put(4, "Cover (back)"); - idToValue.put(5, "Leaflet page"); - idToValue.put(6, "Media (e.g. label side of CD)"); - idToValue.put(7, "Lead artist/lead performer/soloist"); - idToValue.put(8, "Artist/performer"); - idToValue.put(9, "Conductor"); - idToValue.put(10, "Band/Orchestra"); - idToValue.put(11, "Composer"); - idToValue.put(12, "Lyricist/text writer"); - idToValue.put(13, "Recording Location"); - idToValue.put(14, "During recording"); - idToValue.put(15, "During performance"); - idToValue.put(16, "Movie/video screen capture"); - idToValue.put(17, "A bright coloured fish"); - idToValue.put(18, "Illustration"); - idToValue.put(19, "Band/artist logotype"); - idToValue.put(20, "Publisher/Studio logotype"); - - createMaps(); - } - - public static PictureTypes getInstanceOf() { - if (pictureTypes == null) { - pictureTypes = new PictureTypes(); - } - return pictureTypes; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/reference/Tagger.java b/src/main/java/org/jaudiotagger/tag/reference/Tagger.java deleted file mode 100644 index cf2dd43..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/Tagger.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.jaudiotagger.tag.reference; - -/** - * An enumeration of popular tagger applications - *

    - *

    This is not meant to be a definitive list but is first attempt to document a list of taggers in order - * for us to link nonstandard fields, and link nonstandard tagging to them - */ -public enum Tagger { - ITUNES(0, "iTunes"), - MEDIAPLAYER(1, "Windows Media Player"), - WINAMP(2, "Winamp"), - MP3TAG(3, "Mp3 Tag"), - MEDIA_MONKEY(4, "Media Monkey"), - TAG_AND_RENAME(5, "Tag and Rename"), - PICARD(6, "Picard"), - JAIKOZ(7, "Jaikoz"), - TAGSCANNER(8, "Tagscanner"), - XIPH(9, "Xiph"), //standards body rather than tagger xiph.org - FOOBAR2000(10, "Foobar2000"), - BEATUNES(11, "Beatunes"), - SONGBIRD(12, "Songbird"), - JRIVER(13, "JRiver"), - GODFATHER(14, "The Godfather"); - - private int compatability; - private String desc; - - Tagger(int compatability, String desc) { - this.compatability = compatability; - this.desc = desc; - } - - public String toString() { - return desc; - } - -} diff --git a/src/main/java/org/jaudiotagger/tag/reference/package.html b/src/main/java/org/jaudiotagger/tag/reference/package.html deleted file mode 100644 index 5446b65..0000000 --- a/src/main/java/org/jaudiotagger/tag/reference/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Controlled vocabulary support. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.java b/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.java deleted file mode 100644 index f2f493a..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.vorbiscomment; - -import org.jaudiotagger.audio.generic.AbstractTagCreator; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.TagField; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.Iterator; - -/** - * Create the raw packet data for a Vorbis Comment Tag - */ -public class VorbisCommentCreator extends AbstractTagCreator { - /** - * Convert tagdata to rawdata ready for writing to file - * - * @param tag - * @param padding - * @return - * @throws UnsupportedEncodingException - */ - //TODO padding parameter currently ignored - public ByteBuffer convert(Tag tag, int padding) throws UnsupportedEncodingException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - //Vendor - String vendorString = ((VorbisCommentTag) tag).getVendor(); - int vendorLength = Utils.getUTF8Bytes(vendorString).length; - baos.write(Utils.getSizeLEInt32(vendorLength)); - baos.write(Utils.getUTF8Bytes(vendorString)); - - //User Comment List - int listLength = tag.getFieldCount() - 1; //Remove Vendor from count - baos.write(Utils.getSizeLEInt32(listLength)); - - //Add metadata raw content - Iterator it = tag.getFields(); - while (it.hasNext()) { - TagField frame = it.next(); - if (frame.getId().equals(VorbisCommentFieldKey.VENDOR.getFieldName())) { - //this is always stored above so ignore - } else { - baos.write(frame.getRawContent()); - } - } - - //Put into ByteBuffer - ByteBuffer buf = ByteBuffer.wrap(baos.toByteArray()); - buf.rewind(); - return buf; - } catch (IOException ioe) { - //Should never happen as not writing to file at this point - throw new RuntimeException(ioe); - } - } -} diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java b/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java deleted file mode 100644 index 2063d2a..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.jaudiotagger.tag.vorbiscomment; - -import org.jaudiotagger.tag.reference.Tagger; - -import java.util.EnumSet; - -/** - * Vorbis Comment Field Names - *

    - *

    - *

    - * This partial list is derived fom the following sources: - *

      - *
    • http://xiph.org/vorbis/doc/v-comment.html
    • - *
    • http://wiki.musicbrainz.org/PicardQt/TagMapping
    • - *
    • http://legroom.net/2009/05/09/ogg-vorbis-and-flac-comment-field-recommendations
    • - *
    - */ -public enum VorbisCommentFieldKey { - ALBUM("ALBUM", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - ALBUMARTIST("ALBUMARTIST", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - ALBUM_ARTIST("ALBUM_ARTIST", EnumSet.of(Tagger.MEDIA_MONKEY)), - ALBUMARTISTSORT("ALBUMARTISTSORT", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - ALBUMSORT("ALBUMSORT", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - ARTIST("ARTIST", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - ARTISTS("ARTISTS", EnumSet.of(Tagger.JAIKOZ)), - ARTISTSORT("ARTISTSORT", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - ASIN("ASIN", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - BARCODE("BARCODE", EnumSet.of(Tagger.JAIKOZ)), - BPM("BPM", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - CATALOGNUMBER("CATALOGNUMBER", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - COMMENT("COMMENT", EnumSet.of(Tagger.PICARD)), - COMPILATION("COMPILATION", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - COMPOSER("COMPOSER", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - COMPOSERSORT("COMPOSERSORT", EnumSet.of(Tagger.JAIKOZ)), - CONDUCTOR("CONDUCTOR", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - CONTACT("CONTACT", EnumSet.of(Tagger.XIPH)), - COPYRIGHT("COPYRIGHT", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - COVERART("COVERART", EnumSet.of(Tagger.JAIKOZ)), - COVERARTMIME("COVERARTMIME", EnumSet.of(Tagger.JAIKOZ)), - CUSTOM1("CUSTOM1", EnumSet.of(Tagger.MEDIA_MONKEY)), - CUSTOM2("CUSTOM2", EnumSet.of(Tagger.MEDIA_MONKEY)), - CUSTOM3("CUSTOM3", EnumSet.of(Tagger.MEDIA_MONKEY)), - CUSTOM4("CUSTOM4", EnumSet.of(Tagger.MEDIA_MONKEY)), - CUSTOM5("CUSTOM5", EnumSet.of(Tagger.MEDIA_MONKEY)), - DATE("DATE", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - DESCRIPTION("DESCRIPTION", EnumSet.of(Tagger.XIPH)), - DISCNUMBER("DISCNUMBER", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - DISCSUBTITLE("DISCSUBTITLE", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - DISCTOTAL("DISCTOTAL", EnumSet.of(Tagger.XIPH, Tagger.PICARD)), - ENCODEDBY("ENCODEDBY", EnumSet.of(Tagger.PICARD)), - ENCODER("ENCODER"), - ENSEMBLE("ENSEMBLE", EnumSet.of(Tagger.MEDIA_MONKEY)), //Uses this for ALBUM_ARTIST - FBPM("FBPM", EnumSet.of(Tagger.BEATUNES)), - GENRE("GENRE", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - GROUPING("GROUPING", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - ISRC("ISRC", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - KEY("KEY"), - LABEL("LABEL", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - LANGUAGE("LANGUAGE"), - LICENSE("LICENSE", EnumSet.of(Tagger.XIPH)), - LOCATION("LOCATION", EnumSet.of(Tagger.XIPH)), - LYRICIST("LYRICIST", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - LYRICS("LYRICS", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MEDIA("MEDIA", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - METADATA_BLOCK_PICTURE("METADATA_BLOCK_PICTURE", EnumSet.of(Tagger.XIPH)), - MOOD("MOOD", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_ALBUMARTISTID("MUSICBRAINZ_ALBUMARTISTID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_ALBUMID("MUSICBRAINZ_ALBUMID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_ALBUMSTATUS("MUSICBRAINZ_ALBUMSTATUS", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_ALBUMTYPE("MUSICBRAINZ_ALBUMTYPE", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_ARTISTID("MUSICBRAINZ_ARTISTID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_DISCID("MUSICBRAINZ_DISCID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_ORIGINAL_ALBUMID("MUSICBRAINZ_ORIGINALALBUMID", EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_RELEASEGROUPID("MUSICBRAINZ_RELEASEGROUPID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_TRACKID("MUSICBRAINZ_TRACKID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICBRAINZ_WORKID("MUSICBRAINZ_WORKID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - MUSICIP_PUID("MUSICIP_PUID", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - OCCASION("OCCASION", EnumSet.of(Tagger.MEDIA_MONKEY)), - ORGANIZATION("ORGANIZATION", EnumSet.of(Tagger.XIPH)), // Name of the organization producing the track (i.e. the 'record label') - ORIGINAL_ALBUM("ORIGINAL ALBUM", EnumSet.of(Tagger.JAIKOZ, Tagger.MEDIA_MONKEY)), - ORIGINAL_ARTIST("ORIGINAL ARTIST", EnumSet.of(Tagger.JAIKOZ, Tagger.MEDIA_MONKEY)), - ORIGINAL_LYRICIST("ORIGINAL LYRICIST", EnumSet.of(Tagger.MEDIA_MONKEY)), - ORIGINAL_YEAR("ORIGINAL YEAR", EnumSet.of(Tagger.JAIKOZ, Tagger.MEDIA_MONKEY)), - PERFORMER("PERFORMER", EnumSet.of(Tagger.XIPH, Tagger.PICARD)), - PRODUCTNUMBER("PRODUCTNUMBER", EnumSet.of(Tagger.XIPH)), - QUALITY("QUALITY", EnumSet.of(Tagger.MEDIA_MONKEY)), - RATING("RATING", EnumSet.of(Tagger.MEDIA_MONKEY)), - RELEASECOUNTRY("RELEASECOUNTRY", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - REMIXER("REMIXER", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - SCRIPT("SCRIPT", EnumSet.of(Tagger.JAIKOZ)), - SOURCEMEDIA("SOURCEMEDIA", EnumSet.of(Tagger.XIPH)), - SUBTITLE("SUBTITLE", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - TAGS("TAGS", EnumSet.of(Tagger.JAIKOZ)), - TEMPO("TEMPO", EnumSet.of(Tagger.MEDIA_MONKEY)), - TITLE("TITLE", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - TITLESORT("TITLESORT", EnumSet.of(Tagger.PICARD, Tagger.JAIKOZ)), - TRACKNUMBER("TRACKNUMBER", EnumSet.of(Tagger.XIPH, Tagger.PICARD, Tagger.JAIKOZ)), - TRACKTOTAL("TRACKTOTAL", EnumSet.of(Tagger.XIPH, Tagger.PICARD)), - URL_DISCOGS_ARTIST_SITE("URL_DISCOGS_ARTIST_SITE", EnumSet.of(Tagger.JAIKOZ)), - URL_DISCOGS_RELEASE_SITE("URL_DISCOGS_RELEASE_SITE", EnumSet.of(Tagger.JAIKOZ)), - URL_LYRICS_SITE("URL_LYRICS_SITE", EnumSet.of(Tagger.JAIKOZ)), - URL_OFFICIAL_ARTIST_SITE("URL_OFFICIAL_ARTIST_SITE", EnumSet.of(Tagger.JAIKOZ)), - URL_OFFICIAL_RELEASE_SITE("URL_OFFICIAL_RELEASE_SITE", EnumSet.of(Tagger.JAIKOZ)), - URL_WIKIPEDIA_ARTIST_SITE("URL_WIKIPEDIA_ARTIST_SITE", EnumSet.of(Tagger.JAIKOZ)), - URL_WIKIPEDIA_RELEASE_SITE("URL_WIKIPEDIA_RELEASE_SITE", EnumSet.of(Tagger.JAIKOZ)), - VENDOR("VENDOR"), - VERSION("VERSION", EnumSet.of(Tagger.XIPH)),// The version field may be used to differentiate multiple versions of the same track title in a single collection. (e.g. remix info) - - ENGINEER("ENGINEER", EnumSet.of(Tagger.PICARD)), - PRODUCER("PRODUCER", EnumSet.of(Tagger.PICARD)), - DJMIXER("DJMIXER", EnumSet.of(Tagger.PICARD)), - MIXER("MIXER", EnumSet.of(Tagger.PICARD)), - ARRANGER("ARRANGER", EnumSet.of(Tagger.PICARD)), - ACOUSTID_FINGERPRINT("ACOUSTID_FINGERPRINT", EnumSet.of(Tagger.PICARD)), - ACOUSTID_ID("ACOUSTID_ID", EnumSet.of(Tagger.PICARD)), - COUNTRY("COUNTRY", EnumSet.of(Tagger.PICARD)),; - - - private String fieldName; - private EnumSet taggers; - - VorbisCommentFieldKey(String fieldName) { - this.fieldName = fieldName; - } - - VorbisCommentFieldKey(String fieldName, EnumSet taggers) { - this.fieldName = fieldName; - this.taggers = taggers; - } - - public String getFieldName() { - return fieldName; - } - - /** - * List of taggers using this field, concentrates primarily on the original tagger to start using a field. - * Tagger.XIPH means the field is either part of the Vorbis Standard or a Vorbis proposed extension to the - * standard - * - * @return - */ - public EnumSet getTaggers() { - return taggers; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java b/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java deleted file mode 100644 index 4c1bf7e..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * Copyright (c) 2004-2005 Christian Laireiter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.vorbiscomment; - -import org.jaudiotagger.audio.exceptions.CannotReadException; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.ogg.util.VorbisHeader; -import org.jaudiotagger.logging.ErrorMessage; - -import java.io.IOException; -import java.util.logging.Logger; - -/** - * Create the VorbisCommentTag by reading from the raw packet data - *

    - *

    This is in the same format whether encoded with Ogg or Flac - * except the framing bit is only present when used within Ogg Vorbis - *

    - *

    - * From the http://xiph.org/vorbis/doc/Vorbis_I_spec.html#vorbis-spec-comment
    - * Read decodes the packet data using the following algorithm:
    - *  [vendor_length] = read an unsigned integer of 32 bits
    - *  [vendor_string] = read a UTF-8 vector as [vendor_length] octets
    - *  [user_comment_list_length] = read an unsigned integer of 32 bits
    - *  iterate [user_comment_list_length] times {
    - *      5) [length] = read an unsigned integer of 32 bits
    - *      6) this iteration's user comment = read a UTF-8 vector as [length] octets
    - *    }
    - *  [framing_bit] = read a single bit as boolean
    - *  if ( [framing_bit] unset or end-of-packet ) then ERROR
    - *  done.
    - * 
    - */ -public class VorbisCommentReader { - public static final int FIELD_VENDOR_LENGTH_POS = 0; - public static final int FIELD_VENDOR_STRING_POS = 4; - public static final int FIELD_VENDOR_LENGTH_LENGTH = 4; - public static final int FIELD_USER_COMMENT_LIST_LENGTH = 4; - public static final int FIELD_COMMENT_LENGTH_LENGTH = 4; - /** - * max comment length that jaudiotagger can handle, this isnt the maximum column length allowed but we dont - * dont allow comments larger than this because of problem with allocating memory (10MB shoudl be fine for all apps) - */ - private static final int JAUDIOTAGGER_MAX_COMMENT_LENGTH = 10000000; - // Logger Object - public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.vorbiscomment.VorbisCommentReader"); - - public VorbisCommentReader() { - - } - - /** - * @param rawdata - * @param isFramingBit - * @return logical representation of VorbisCommentTag - * @throws IOException - * @throws CannotReadException - */ - public VorbisCommentTag read(byte[] rawdata, boolean isFramingBit) throws IOException, CannotReadException { - - VorbisCommentTag tag = new VorbisCommentTag(); - - byte[] b = new byte[FIELD_VENDOR_LENGTH_LENGTH]; - System.arraycopy(rawdata, FIELD_VENDOR_LENGTH_POS, b, FIELD_VENDOR_LENGTH_POS, FIELD_VENDOR_LENGTH_LENGTH); - int pos = FIELD_VENDOR_LENGTH_LENGTH; - int vendorStringLength = Utils.getIntLE(b); - - b = new byte[vendorStringLength]; - System.arraycopy(rawdata, pos, b, 0, vendorStringLength); - pos += vendorStringLength; - tag.setVendor(new String(b, VorbisHeader.CHARSET_UTF_8)); - logger.config("Vendor is:" + tag.getVendor()); - - b = new byte[FIELD_USER_COMMENT_LIST_LENGTH]; - System.arraycopy(rawdata, pos, b, 0, FIELD_USER_COMMENT_LIST_LENGTH); - pos += FIELD_USER_COMMENT_LIST_LENGTH; - - int userComments = Utils.getIntLE(b); - logger.config("Number of user comments:" + userComments); - - for (int i = 0; i < userComments; i++) { - b = new byte[FIELD_COMMENT_LENGTH_LENGTH]; - System.arraycopy(rawdata, pos, b, 0, FIELD_COMMENT_LENGTH_LENGTH); - pos += FIELD_COMMENT_LENGTH_LENGTH; - - int commentLength = Utils.getIntLE(b); - logger.config("Next Comment Length:" + commentLength); - - if (commentLength > JAUDIOTAGGER_MAX_COMMENT_LENGTH) { - logger.warning(ErrorMessage.VORBIS_COMMENT_LENGTH_TOO_LARGE.getMsg(commentLength)); - break; - } else if (commentLength > rawdata.length) { - logger.warning(ErrorMessage.VORBIS_COMMENT_LENGTH_LARGE_THAN_HEADER.getMsg(commentLength, rawdata.length)); - break; - } else { - b = new byte[commentLength]; - System.arraycopy(rawdata, pos, b, 0, commentLength); - pos += commentLength; - - VorbisCommentTagField fieldComment = new VorbisCommentTagField(b); - logger.config("Adding:" + fieldComment.getId()); - tag.addField(fieldComment); - } - } - - //Check framing bit, only exists when vorbisComment used within OggVorbis - if (isFramingBit) { - if ((rawdata[pos] & 0x01) != 1) { - throw new CannotReadException(ErrorMessage.OGG_VORBIS_NO_FRAMING_BIT.getMsg((rawdata[pos] & 0x01))); - } - } - return tag; - } -} - diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java b/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java deleted file mode 100644 index 8dcb82d..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Rapha�l Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.vorbiscomment; - -import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import org.jaudiotagger.audio.generic.AbstractTag; -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.ogg.util.VorbisHeader; -import org.jaudiotagger.logging.ErrorMessage; -import org.jaudiotagger.tag.*; -import org.jaudiotagger.tag.id3.valuepair.TextEncoding; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import org.jaudiotagger.tag.vorbiscomment.util.Base64Coder; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; - -import static org.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey.VENDOR; - -/** - * This is the logical representation of Vorbis Comment Data - */ -public class VorbisCommentTag extends AbstractTag { - //This is the vendor string that will be written if no other is supplied. Should be the name of the software - //that actually encoded the file in the first place. - public static final String DEFAULT_VENDOR = "jaudiotagger"; - private static EnumMap tagFieldToOggField = new EnumMap(FieldKey.class); - - static { - tagFieldToOggField.put(FieldKey.ALBUM, VorbisCommentFieldKey.ALBUM); - tagFieldToOggField.put(FieldKey.ALBUM_ARTIST, VorbisCommentFieldKey.ALBUMARTIST); - tagFieldToOggField.put(FieldKey.ALBUM_ARTIST_SORT, VorbisCommentFieldKey.ALBUMARTISTSORT); - tagFieldToOggField.put(FieldKey.ALBUM_SORT, VorbisCommentFieldKey.ALBUMSORT); - tagFieldToOggField.put(FieldKey.ARTIST, VorbisCommentFieldKey.ARTIST); - tagFieldToOggField.put(FieldKey.ARTISTS, VorbisCommentFieldKey.ARTISTS); - tagFieldToOggField.put(FieldKey.AMAZON_ID, VorbisCommentFieldKey.ASIN); - tagFieldToOggField.put(FieldKey.ARTIST_SORT, VorbisCommentFieldKey.ARTISTSORT); - tagFieldToOggField.put(FieldKey.BARCODE, VorbisCommentFieldKey.BARCODE); - tagFieldToOggField.put(FieldKey.BPM, VorbisCommentFieldKey.BPM); - tagFieldToOggField.put(FieldKey.CATALOG_NO, VorbisCommentFieldKey.CATALOGNUMBER); - tagFieldToOggField.put(FieldKey.COMMENT, VorbisCommentFieldKey.COMMENT); - tagFieldToOggField.put(FieldKey.COMPOSER, VorbisCommentFieldKey.COMPOSER); - tagFieldToOggField.put(FieldKey.COMPOSER_SORT, VorbisCommentFieldKey.COMPOSERSORT); - tagFieldToOggField.put(FieldKey.CONDUCTOR, VorbisCommentFieldKey.CONDUCTOR); - tagFieldToOggField.put(FieldKey.COVER_ART, VorbisCommentFieldKey.METADATA_BLOCK_PICTURE); - tagFieldToOggField.put(FieldKey.CUSTOM1, VorbisCommentFieldKey.CUSTOM1); - tagFieldToOggField.put(FieldKey.CUSTOM2, VorbisCommentFieldKey.CUSTOM2); - tagFieldToOggField.put(FieldKey.CUSTOM3, VorbisCommentFieldKey.CUSTOM3); - tagFieldToOggField.put(FieldKey.CUSTOM4, VorbisCommentFieldKey.CUSTOM4); - tagFieldToOggField.put(FieldKey.CUSTOM5, VorbisCommentFieldKey.CUSTOM5); - tagFieldToOggField.put(FieldKey.DISC_NO, VorbisCommentFieldKey.DISCNUMBER); - tagFieldToOggField.put(FieldKey.DISC_SUBTITLE, VorbisCommentFieldKey.DISCSUBTITLE); - tagFieldToOggField.put(FieldKey.DISC_TOTAL, VorbisCommentFieldKey.DISCTOTAL); - tagFieldToOggField.put(FieldKey.ENCODER, VorbisCommentFieldKey.VENDOR); //Known as vendor in VorbisComment - tagFieldToOggField.put(FieldKey.FBPM, VorbisCommentFieldKey.FBPM); - tagFieldToOggField.put(FieldKey.GENRE, VorbisCommentFieldKey.GENRE); - tagFieldToOggField.put(FieldKey.GROUPING, VorbisCommentFieldKey.GROUPING); - tagFieldToOggField.put(FieldKey.ISRC, VorbisCommentFieldKey.ISRC); - tagFieldToOggField.put(FieldKey.IS_COMPILATION, VorbisCommentFieldKey.COMPILATION); - tagFieldToOggField.put(FieldKey.KEY, VorbisCommentFieldKey.KEY); - tagFieldToOggField.put(FieldKey.LANGUAGE, VorbisCommentFieldKey.LANGUAGE); - tagFieldToOggField.put(FieldKey.LYRICIST, VorbisCommentFieldKey.LYRICIST); - tagFieldToOggField.put(FieldKey.LYRICS, VorbisCommentFieldKey.LYRICS); - tagFieldToOggField.put(FieldKey.MEDIA, VorbisCommentFieldKey.MEDIA); - tagFieldToOggField.put(FieldKey.MOOD, VorbisCommentFieldKey.MOOD); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_ARTISTID, VorbisCommentFieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_DISC_ID, VorbisCommentFieldKey.MUSICBRAINZ_DISCID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMARTISTID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, VorbisCommentFieldKey.MUSICBRAINZ_ORIGINAL_ALBUMID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASEID, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, VorbisCommentFieldKey.MUSICBRAINZ_RELEASEGROUPID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, VorbisCommentFieldKey.RELEASECOUNTRY); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMSTATUS); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMTYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_TRACK_ID, VorbisCommentFieldKey.MUSICBRAINZ_TRACKID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORKID); - tagFieldToOggField.put(FieldKey.OCCASION, VorbisCommentFieldKey.OCCASION); - tagFieldToOggField.put(FieldKey.ORIGINAL_ALBUM, VorbisCommentFieldKey.ORIGINAL_ALBUM); - tagFieldToOggField.put(FieldKey.ORIGINAL_ARTIST, VorbisCommentFieldKey.ORIGINAL_ARTIST); - tagFieldToOggField.put(FieldKey.ORIGINAL_LYRICIST, VorbisCommentFieldKey.ORIGINAL_LYRICIST); - tagFieldToOggField.put(FieldKey.ORIGINAL_YEAR, VorbisCommentFieldKey.ORIGINAL_YEAR); - tagFieldToOggField.put(FieldKey.MUSICIP_ID, VorbisCommentFieldKey.MUSICIP_PUID); - tagFieldToOggField.put(FieldKey.QUALITY, VorbisCommentFieldKey.QUALITY); - tagFieldToOggField.put(FieldKey.RATING, VorbisCommentFieldKey.RATING); - tagFieldToOggField.put(FieldKey.RECORD_LABEL, VorbisCommentFieldKey.LABEL); - tagFieldToOggField.put(FieldKey.REMIXER, VorbisCommentFieldKey.REMIXER); - tagFieldToOggField.put(FieldKey.TAGS, VorbisCommentFieldKey.TAGS); - tagFieldToOggField.put(FieldKey.SCRIPT, VorbisCommentFieldKey.SCRIPT); - tagFieldToOggField.put(FieldKey.SUBTITLE, VorbisCommentFieldKey.SUBTITLE); - tagFieldToOggField.put(FieldKey.TEMPO, VorbisCommentFieldKey.TEMPO); - tagFieldToOggField.put(FieldKey.TITLE, VorbisCommentFieldKey.TITLE); - tagFieldToOggField.put(FieldKey.TITLE_SORT, VorbisCommentFieldKey.TITLESORT); - tagFieldToOggField.put(FieldKey.TRACK, VorbisCommentFieldKey.TRACKNUMBER); - tagFieldToOggField.put(FieldKey.TRACK_TOTAL, VorbisCommentFieldKey.TRACKTOTAL); - tagFieldToOggField.put(FieldKey.URL_DISCOGS_ARTIST_SITE, VorbisCommentFieldKey.URL_DISCOGS_ARTIST_SITE); - tagFieldToOggField.put(FieldKey.URL_DISCOGS_RELEASE_SITE, VorbisCommentFieldKey.URL_DISCOGS_RELEASE_SITE); - tagFieldToOggField.put(FieldKey.URL_LYRICS_SITE, VorbisCommentFieldKey.URL_LYRICS_SITE); - tagFieldToOggField.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, VorbisCommentFieldKey.URL_OFFICIAL_ARTIST_SITE); - tagFieldToOggField.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, VorbisCommentFieldKey.URL_OFFICIAL_RELEASE_SITE); - tagFieldToOggField.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, VorbisCommentFieldKey.URL_WIKIPEDIA_ARTIST_SITE); - tagFieldToOggField.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, VorbisCommentFieldKey.URL_WIKIPEDIA_RELEASE_SITE); - tagFieldToOggField.put(FieldKey.YEAR, VorbisCommentFieldKey.DATE); - - tagFieldToOggField.put(FieldKey.ENGINEER, VorbisCommentFieldKey.ENGINEER); - tagFieldToOggField.put(FieldKey.PRODUCER, VorbisCommentFieldKey.PRODUCER); - tagFieldToOggField.put(FieldKey.DJMIXER, VorbisCommentFieldKey.DJMIXER); - tagFieldToOggField.put(FieldKey.MIXER, VorbisCommentFieldKey.MIXER); - tagFieldToOggField.put(FieldKey.ARRANGER, VorbisCommentFieldKey.ARRANGER); - tagFieldToOggField.put(FieldKey.ACOUSTID_FINGERPRINT, VorbisCommentFieldKey.ACOUSTID_FINGERPRINT); - tagFieldToOggField.put(FieldKey.ACOUSTID_ID, VorbisCommentFieldKey.ACOUSTID_ID); - tagFieldToOggField.put(FieldKey.COUNTRY, VorbisCommentFieldKey.COUNTRY); - } - - /** - * Only used within Package, hidden because it doesnt set Vendor - * which should be done when created by end user - */ - VorbisCommentTag() { - - } - - /** - * Use to construct a new tag properly initialized - * - * @return - */ - public static VorbisCommentTag createNewTag() { - VorbisCommentTag tag = new VorbisCommentTag(); - tag.setVendor(DEFAULT_VENDOR); - return tag; - } - - /** - * @return the vendor, generically known as the encoder - */ - public String getVendor() { - return getFirst(VENDOR.getFieldName()); - } - - /** - * Set the vendor, known as the encoder generally - *

    - * We dont want this to be blank, when written to file this field is written to a different location - * to all other fields but user of library can just reat it as another field - * - * @param vendor - */ - public void setVendor(String vendor) { - if (vendor == null) { - vendor = DEFAULT_VENDOR; - } - super.setField(new VorbisCommentTagField(VENDOR.getFieldName(), vendor)); - } - - protected boolean isAllowedEncoding(String enc) { - return enc.equals(VorbisHeader.CHARSET_UTF_8); - } - - public String toString() { - return "OGG " + super.toString(); - } - - /** - * Create Tag Field using generic key - */ - @Override - public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - return createField(tagFieldToOggField.get(genericKey), value); - } - - /** - * Create Tag Field using ogg key - * - * @param vorbisCommentFieldKey - * @param value - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - * @throws org.jaudiotagger.tag.FieldDataInvalidException - */ - public TagField createField(VorbisCommentFieldKey vorbisCommentFieldKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - if (value == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - if (vorbisCommentFieldKey == null) { - throw new KeyNotFoundException(); - } - - return new VorbisCommentTagField(vorbisCommentFieldKey.getFieldName(), value); - } - - /** - * Create Tag Field using ogg key - *

    - * This method is provided to allow you to create key of any value because VorbisComment allows - * arbitary keys. - * - * @param vorbisCommentFieldKey - * @param value - * @return - */ - public TagField createField(String vorbisCommentFieldKey, String value) { - if (value == null) { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - return new VorbisCommentTagField(vorbisCommentFieldKey, value); - } - - /** - * Maps the generic key to the ogg key and return the list of values for this field - * - * @param genericKey - */ - public List getFields(FieldKey genericKey) throws KeyNotFoundException { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - if (vorbisCommentFieldKey == null) { - throw new KeyNotFoundException(); - } - return super.getFields(vorbisCommentFieldKey.getFieldName()); - } - - - /** - * Maps the generic key to the ogg key and return the list of values for this field as strings - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - public List getAll(FieldKey genericKey) throws KeyNotFoundException { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - if (vorbisCommentFieldKey == null) { - throw new KeyNotFoundException(); - } - return super.getAll(vorbisCommentFieldKey.getFieldName()); - } - - /** - * Retrieve the first value that exists for this vorbis comment key - * - * @param vorbisCommentKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public List get(VorbisCommentFieldKey vorbisCommentKey) throws KeyNotFoundException { - if (vorbisCommentKey == null) { - throw new KeyNotFoundException(); - } - return super.getFields(vorbisCommentKey.getFieldName()); - } - - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - if (vorbisCommentFieldKey == null) { - throw new KeyNotFoundException(); - } - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - - /** - * Retrieve the first value that exists for this vorbis comment key - * - * @param vorbisCommentKey - * @return - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public String getFirst(VorbisCommentFieldKey vorbisCommentKey) throws KeyNotFoundException { - if (vorbisCommentKey == null) { - throw new KeyNotFoundException(); - } - return super.getFirst(vorbisCommentKey.getFieldName()); - } - - /** - * @param genericKey - * @return - */ - public boolean hasField(FieldKey genericKey) { - VorbisCommentFieldKey vorbisFieldKey = tagFieldToOggField.get(genericKey); - return getFields(vorbisFieldKey.getFieldName()).size() != 0; - } - - /** - * @param vorbisFieldKey - * @return - */ - public boolean hasField(VorbisCommentFieldKey vorbisFieldKey) { - return getFields(vorbisFieldKey.getFieldName()).size() != 0; - } - - /** - * Delete fields with this generic key - * - * @param genericKey - */ - public void deleteField(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - deleteField(vorbisCommentFieldKey); - } - - /** - * Delete fields with this vorbisCommentFieldKey - * - * @param vorbisCommentFieldKey - * @throws org.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(VorbisCommentFieldKey vorbisCommentFieldKey) throws KeyNotFoundException { - if (vorbisCommentFieldKey == null) { - throw new KeyNotFoundException(); - } - super.deleteField(vorbisCommentFieldKey.getFieldName()); - } - - - /** - * Retrieve artwork raw data when using the deprecated COVERART format - * - * @return - */ - public byte[] getArtworkBinaryData() { - String base64data = this.getFirst(VorbisCommentFieldKey.COVERART); - byte[] rawdata = Base64Coder.decode(base64data.toCharArray()); - return rawdata; - } - - /** - * Retrieve artwork mimeType when using deprecated COVERART format - * - * @return mimetype - */ - public String getArtworkMimeType() { - return this.getFirst(VorbisCommentFieldKey.COVERARTMIME); - } - - /** - * Is this tag empty - *

    - *

    Overridden because check for size of one because there is always a vendor tag unless just - * created an empty vorbis tag as part of flac tag in which case size could be zero - * - * @see org.jaudiotagger.tag.Tag#isEmpty() - */ - public boolean isEmpty() { - return fields.size() <= 1; - } - - /** - * Add Field - *

    - *

    Overidden because there can only be one vendor set - * - * @param field - */ - public void addField(TagField field) { - if (field.getId().equals(VorbisCommentFieldKey.VENDOR.getFieldName())) { - super.setField(field); - } else { - super.addField(field); - } - } - - public TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException { - if (genericKey == null) { - throw new KeyNotFoundException(); - } - return getFirstField(tagFieldToOggField.get(genericKey).getFieldName()); - } - - /** - * @return list of artwork images - */ - public List getArtworkList() { - List artworkList = new ArrayList(1); - - //Read Old Format - if (getArtworkBinaryData() != null & getArtworkBinaryData().length > 0) { - Artwork artwork = ArtworkFactory.getNew(); - artwork.setMimeType(getArtworkMimeType()); - artwork.setBinaryData(getArtworkBinaryData()); - artworkList.add(artwork); - } - - //New Format (Supports Multiple Images) - List metadataBlockPics = this.get(VorbisCommentFieldKey.METADATA_BLOCK_PICTURE); - for (TagField tagField : metadataBlockPics) { - - try { - byte[] imageBinaryData = Base64Coder.decode(((TagTextField) tagField).getContent()); - MetadataBlockDataPicture coverArt = new MetadataBlockDataPicture(ByteBuffer.wrap(imageBinaryData)); - Artwork artwork = ArtworkFactory.createArtworkFromMetadataBlockDataPicture(coverArt); - artworkList.add(artwork); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } catch (InvalidFrameException ife) { - throw new RuntimeException(ife); - } - } - return artworkList; - } - - - /** - * Create MetadataBlockPicture field, this is the preferred way of storing artwork in VorbisComment tag now but - * has to be base encoded to be stored in VorbisComment - * - * @return MetadataBlockDataPicture - */ - private MetadataBlockDataPicture createMetadataBlockDataPicture(Artwork artwork) throws FieldDataInvalidException { - if (artwork.isLinked()) { - return new MetadataBlockDataPicture( - Utils.getDefaultBytes(artwork.getImageUrl(), TextEncoding.CHARSET_ISO_8859_1), - artwork.getPictureType(), - MetadataBlockDataPicture.IMAGE_IS_URL, - "", - 0, - 0, - 0, - 0); - } else { - if (!artwork.setImageFromData()) { - throw new FieldDataInvalidException("Unable to create MetadataBlockDataPicture from buffered"); - } - return new MetadataBlockDataPicture(artwork.getBinaryData(), - artwork.getPictureType(), - artwork.getMimeType(), - artwork.getDescription(), - artwork.getWidth(), - artwork.getHeight(), - 0, - 0); - } - } - - /** - * Create Artwork field - * - * @param artwork - * @return - * @throws FieldDataInvalidException - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException { - try { - char[] testdata = Base64Coder.encode(createMetadataBlockDataPicture(artwork).getRawContent()); - String base64image = new String(testdata); - TagField imageTagField = createField(VorbisCommentFieldKey.METADATA_BLOCK_PICTURE, base64image); - return imageTagField; - } catch (UnsupportedEncodingException uee) { - throw new RuntimeException(uee); - } - } - - /** - * Create and set artwork field - * - * @return - */ - @Override - public void setField(Artwork artwork) throws FieldDataInvalidException { - //Set field - this.setField(createField(artwork)); - - //If worked okay above then that should be first artwork and if we still had old coverart format - //that should be removed - if (this.getFirst(VorbisCommentFieldKey.COVERART).length() > 0) { - this.deleteField(VorbisCommentFieldKey.COVERART); - this.deleteField(VorbisCommentFieldKey.COVERARTMIME); - } - } - - /** - * Add artwork field - * - * @param artwork - * @throws FieldDataInvalidException - */ - public void addField(Artwork artwork) throws FieldDataInvalidException { - this.addField(createField(artwork)); - } - - /** - * Create artwork field using the non-standard COVERART tag - *

    - *

    - * Actually create two fields , the data field and the mimetype. Its is not recommended that you use this - * method anymore. - * - * @param data raw image data - * @param mimeType mimeType of data - *

    - * @return - */ - @Deprecated - public void setArtworkField(byte[] data, String mimeType) { - char[] testdata = Base64Coder.encode(data); - String base64image = new String(testdata); - VorbisCommentTagField dataField = new VorbisCommentTagField(VorbisCommentFieldKey.COVERART.getFieldName(), base64image); - VorbisCommentTagField mimeField = new VorbisCommentTagField(VorbisCommentFieldKey.COVERARTMIME.getFieldName(), mimeType); - - setField(dataField); - setField(mimeField); - - } - - /** - * Create and set field with name of vorbisCommentkey - * - * @param vorbisCommentKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void setField(String vorbisCommentKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(vorbisCommentKey, value); - setField(tagfield); - } - - /** - * Create and add field with name of vorbisCommentkey - * - * @param vorbisCommentKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void addField(String vorbisCommentKey, String value) throws KeyNotFoundException, FieldDataInvalidException { - TagField tagfield = createField(vorbisCommentKey, value); - addField(tagfield); - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException { - //New Method - this.deleteField(VorbisCommentFieldKey.METADATA_BLOCK_PICTURE); - - //Old Method - this.deleteField(VorbisCommentFieldKey.COVERART); - this.deleteField(VorbisCommentFieldKey.COVERARTMIME); - } -} - diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java b/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java deleted file mode 100644 index f723525..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Entagged Audio Tag library - * Copyright (c) 2003-2005 Raphaël Slinckx - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.jaudiotagger.tag.vorbiscomment; - -import org.jaudiotagger.audio.generic.Utils; -import org.jaudiotagger.audio.ogg.util.VorbisHeader; -import org.jaudiotagger.tag.TagField; -import org.jaudiotagger.tag.TagTextField; - -import java.io.UnsupportedEncodingException; - -import static org.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey.*; - -/** - * This class represents the name and content of a tag entry in ogg-files. - *
    - * - * @author @author Raphael Slinckx (KiKiDonK) - * @author Christian Laireiter (liree) - */ -public class VorbisCommentTagField implements TagTextField { - - /** - * If id is invalid - */ - private static final String ERRONEOUS_ID = "ERRONEOUS"; - /** - * If true, the id of the current encapsulated tag field is - * specified as a common field.
    - * Example is "ARTIST" which should be interpreted by any application as the - * artist of the media content.
    - * Will be set during construction with {@link #checkCommon()}. - */ - private boolean common; - /** - * Stores the content of the tag field.
    - */ - private String content; - /** - * Stores the id (name) of the tag field.
    - */ - private String id; - - /** - * Creates an instance. - * - * @param raw Raw byte data of the tagfield. - * @throws UnsupportedEncodingException If the data doesn't conform "UTF-8" specification. - */ - public VorbisCommentTagField(byte[] raw) throws UnsupportedEncodingException { - String field = new String(raw, "UTF-8"); - int i = field.indexOf("="); - if (i == -1) { - //Beware that ogg ID, must be capitalized and contain no space.. - this.id = ERRONEOUS_ID; - this.content = field; - } else { - this.id = field.substring(0, i).toUpperCase(); - if (field.length() > i) { - this.content = field.substring(i + 1); - } else { - //We have "XXXXXX=" with nothing after the "=" - this.content = ""; - } - } - checkCommon(); - } - - /** - * Creates an instance. - * - * @param fieldId ID (name) of the field. - * @param fieldContent Content of the field. - */ - public VorbisCommentTagField(String fieldId, String fieldContent) { - this.id = fieldId.toUpperCase(); - this.content = fieldContent; - checkCommon(); - } - - /** - * This method examines the ID of the current field and modifies - * {@link #common}in order to reflect if the tag id is a commonly used one. - *
    - */ - private void checkCommon() { - this.common = id.equals(TITLE.getFieldName()) || id.equals(ALBUM.getFieldName()) || id.equals(ARTIST.getFieldName()) - || id.equals(GENRE.getFieldName()) || id.equals(TRACKNUMBER.getFieldName()) || id.equals(DATE.getFieldName()) - || id.equals(DESCRIPTION.getFieldName()) || id.equals(COMMENT.getFieldName()); - - } - - /** - * This method will copy all bytes of src to dst - * at the specified location. - * - * @param src bytes to copy. - * @param dst where to copy to. - * @param dstOffset at which position of dst the data should be - * copied. - */ - protected void copy(byte[] src, byte[] dst, int dstOffset) { - // for (int i = 0; i < src.length; i++) - // dst[i + dstOffset] = src[i]; - /* - * Heared that this method is optimized and does its job very near of - * the system. - */ - System.arraycopy(src, 0, dst, dstOffset, src.length); - } - - /** - * @see TagField#copyContent(TagField) - */ - public void copyContent(TagField field) { - if (field instanceof TagTextField) { - this.content = ((TagTextField) field).getContent(); - } - } - - /** - * This method will try to return the byte representation of the given - * string after it has been converted to the given encoding.
    - * - * @param s The string whose converted bytes should be returned. - * @param encoding The encoding type to which the string should be converted. - * @return If encoding is supported the byte data of the - * given string is returned in that encoding. - * @throws UnsupportedEncodingException If the requested encoding is not available. - */ - protected byte[] getBytes(String s, String encoding) throws UnsupportedEncodingException { - return s.getBytes(encoding); - } - - /** - * @see TagTextField#getContent() - */ - public String getContent() { - return content; - } - - /** - * @see TagTextField#setContent(String) - */ - public void setContent(String s) { - this.content = s; - } - - /** - * @see TagTextField#getEncoding() - */ - public String getEncoding() { - return VorbisHeader.CHARSET_UTF_8; - } - - /** - * @see TagTextField#setEncoding(String) - */ - public void setEncoding(String s) { - if (s == null || !s.equalsIgnoreCase("UTF-8")) { - throw new UnsupportedOperationException("The encoding of OggTagFields cannot be " + "changed.(specified to be UTF-8)"); - } - } - - /** - * @see TagField#getId() - */ - public String getId() { - return this.id; - } - - /** - * @see TagField#getRawContent() - */ - public byte[] getRawContent() throws UnsupportedEncodingException { - byte[] size = new byte[VorbisCommentReader.FIELD_COMMENT_LENGTH_LENGTH]; - byte[] idBytes = Utils.getDefaultBytes(this.id, "ISO-8859-1"); - byte[] contentBytes = getBytes(this.content, "UTF-8"); - byte[] b = new byte[4 + idBytes.length + 1 + contentBytes.length]; - - int length = idBytes.length + 1 + contentBytes.length; - size[3] = (byte) ((length & 0xFF000000) >> 24); - size[2] = (byte) ((length & 0x00FF0000) >> 16); - size[1] = (byte) ((length & 0x0000FF00) >> 8); - size[0] = (byte) (length & 0x000000FF); - - int offset = 0; - copy(size, b, offset); - offset += 4; - copy(idBytes, b, offset); - offset += idBytes.length; - b[offset] = (byte) 0x3D; - offset++;// "=" - copy(contentBytes, b, offset); - - return b; - } - - /** - * @see TagField#isBinary() - */ - public boolean isBinary() { - return false; - } - - /** - * @see TagField#isBinary(boolean) - */ - public void isBinary(boolean b) { - if (b) { - // Only throw if binary = true requested. - throw new UnsupportedOperationException("OggTagFields cannot be changed to binary.\n" + "binary data should be stored elsewhere" + " according to Vorbis_I_spec."); - } - } - - /** - * @see TagField#isCommon() - */ - public boolean isCommon() { - return common; - } - - /** - * @see TagField#isEmpty() - */ - public boolean isEmpty() { - return this.content.equals(""); - } - - public String toString() { - return getContent(); - } -} \ No newline at end of file diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/package.html b/src/main/java/org/jaudiotagger/tag/vorbiscomment/package.html deleted file mode 100644 index 676f7cf..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Code dealing with the Vorbis metadata (called "Comment") tag. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java b/src/main/java/org/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java deleted file mode 100644 index 454155e..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.jaudiotagger.tag.vorbiscomment.util; - -import org.jaudiotagger.audio.generic.Utils; - -/** - * Base64Coder - */ -public class Base64Coder { - // Mapping table from 6-bit nibbles to Base64 characters. - private static final char[] map1 = new char[64]; - // Mapping table from Base64 characters to 6-bit nibbles. - private static final byte[] map2 = new byte[128]; - - static { - int i = 0; - for (char c = 'A'; c <= 'Z'; c++) { - map1[i++] = c; - } - for (char c = 'a'; c <= 'z'; c++) { - map1[i++] = c; - } - for (char c = '0'; c <= '9'; c++) { - map1[i++] = c; - } - map1[i++] = '+'; - map1[i++] = '/'; - } - - static { - for (int i = 0; i < map2.length; i++) { - map2[i] = -1; - } - for (int i = 0; i < 64; i++) { - map2[map1[i]] = (byte) i; - } - } - - /** - * Encodes a string into Base64 format. - * No blanks or line breaks are inserted. - * - * @param s a String to be encoded. - * @return A String with the Base64 encoded data. - */ - public static String encode(final String s) { - return new String(encode(Utils.getDefaultBytes(s, "ISO-8859-1"))); - } - - /** - * Encodes a byte array into Base64 format. - * No blanks or line breaks are inserted. - * - * @param in an array containing the data bytes to be encoded. - * @return A character array with the Base64 encoded data. - */ - public static char[] encode(final byte[] in) { - final int iLen = in.length; - final int oDataLen = (iLen * 4 + 2) / 3; // output length without padding - final int oLen = ((iLen + 2) / 3) * 4; // output length including padding - final char[] out = new char[oLen]; - int ip = 0; - int op = 0; - while (ip < iLen) { - final int i0 = in[ip++] & 0xff; - final int i1 = ip < iLen ? in[ip++] & 0xff : 0; - final int i2 = ip < iLen ? in[ip++] & 0xff : 0; - final int o0 = i0 >>> 2; - final int o1 = ((i0 & 3) << 4) | (i1 >>> 4); - final int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); - final int o3 = i2 & 0x3F; - out[op++] = map1[o0]; - out[op++] = map1[o1]; - out[op] = op < oDataLen ? map1[o2] : '='; - op++; - out[op] = op < oDataLen ? map1[o3] : '='; - op++; - } - return out; - } - - /** - * Decodes a Base64 string. - * - * @param s a Base64 String to be decoded. - * @return An array containing the decoded data bytes. - * @throws IllegalArgumentException if the input is not valid Base64 encoded data. - */ - public static byte[] decode(final String s) { - return decode(s.toCharArray()); - } - - /** - * Decodes Base64 data. - * No blanks or line breaks are allowed within the Base64 encoded data. - * - * @param in a character array containing the Base64 encoded data. - * @return An array containing the decoded data bytes. - * @throws IllegalArgumentException if the input is not valid Base64 encoded data. - */ - public static byte[] decode(final char[] in) { - int iLen = in.length; - if (iLen % 4 != 0) { - throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); - } - while (iLen > 0 && in[iLen - 1] == '=') { - iLen--; - } - final int oLen = (iLen * 3) / 4; - final byte[] out = new byte[oLen]; - int ip = 0; - int op = 0; - while (ip < iLen) { - final int i0 = in[ip++]; - final int i1 = in[ip++]; - final int i2 = ip < iLen ? in[ip++] : 'A'; - final int i3 = ip < iLen ? in[ip++] : 'A'; - if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - final int b0 = map2[i0]; - final int b1 = map2[i1]; - final int b2 = map2[i2]; - final int b3 = map2[i3]; - if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - final int o0 = (b0 << 2) | (b1 >>> 4); - final int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); - final int o2 = ((b2 & 3) << 6) | b3; - out[op++] = (byte) o0; - if (op < oLen) { - out[op++] = (byte) o1; - } - if (op < oLen) { - out[op++] = (byte) o2; - } - } - return out; - } -} diff --git a/src/main/java/org/jaudiotagger/tag/vorbiscomment/util/package.html b/src/main/java/org/jaudiotagger/tag/vorbiscomment/util/package.html deleted file mode 100644 index 726ec4a..0000000 --- a/src/main/java/org/jaudiotagger/tag/vorbiscomment/util/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Utility code supporting the Vorbis metadata (called "Comment") tag. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/test/ExtractID3TagFromFile.java b/src/main/java/org/jaudiotagger/test/ExtractID3TagFromFile.java deleted file mode 100644 index 141d907..0000000 --- a/src/main/java/org/jaudiotagger/test/ExtractID3TagFromFile.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.jaudiotagger.test; - -import org.jaudiotagger.audio.mp3.MP3File; - -import java.io.File; - -/** - * Simple class that will attempt to recusively read all files within a directory, flags - * errors that occur. - */ -public class ExtractID3TagFromFile { - - public static final String IDENT = "$Id: ExtractID3TagFromFile.java 836 2009-11-12 15:44:07Z paultaylor $"; - - public static void main(final String[] args) { - ExtractID3TagFromFile test = new ExtractID3TagFromFile(); - - if (args.length != 2) { - System.err.println("usage ExtractID3TagFromFile Filename FilenameOut"); - System.err.println(" You must enter the file to extract the tag from and where to extract to"); - System.exit(1); - } - - File file = new File(args[0]); - File outFile = new File(args[1]); - if (!file.isFile()) { - System.err.println("usage ExtractID3TagFromFile Filename FilenameOut"); - System.err.println(" File " + args[0] + " could not be found"); - System.exit(1); - } - - try { - final MP3File tmpMP3 = new MP3File(file); - tmpMP3.extractID3v2TagDataIntoFile(outFile); - } catch (Exception e) { - System.err.println("Unable to extract tag"); - System.exit(1); - } - } - - final class MP3FileFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter { - - /** - * allows Directories - */ - private final boolean allowDirectories; - - /** - * Create a default MP3FileFilter. The allowDirectories field will - * default to false. - */ - public MP3FileFilter() { - this(false); - } - - /** - * Create an MP3FileFilter. If allowDirectories is true, then this filter - * will accept directories as well as mp3 files. If it is false then - * only mp3 files will be accepted. - * - * @param allowDirectories whether or not to accept directories - */ - private MP3FileFilter(final boolean allowDirectories) { - this.allowDirectories = allowDirectories; - } - - /** - * Determines whether or not the file is an mp3 file. If the file is - * a directory, whether or not is accepted depends upon the - * allowDirectories flag passed to the constructor. - * - * @param file the file to test - * @return true if this file or directory should be accepted - */ - public final boolean accept(final File file) { - return (((file.getName()).toLowerCase().endsWith(".mp3")) || (file.isDirectory() && (this.allowDirectories))); - } - - /** - * Returns the Name of the Filter for use in the Chooser Dialog - * - * @return The Description of the Filter - */ - public final String getDescription() { - return ".mp3 Files"; - } - } - -} diff --git a/src/main/java/org/jaudiotagger/test/MergeID3AndMP3Files.java b/src/main/java/org/jaudiotagger/test/MergeID3AndMP3Files.java deleted file mode 100644 index 834cbd8..0000000 --- a/src/main/java/org/jaudiotagger/test/MergeID3AndMP3Files.java +++ /dev/null @@ -1,210 +0,0 @@ -package org.jaudiotagger.test; - -import java.io.*; -import java.text.DateFormat; -import java.util.Date; - -/** - * Simple class that will attempt to recusively read all files within a directory ending in .mp3 (but - * only actually expected to contain id3 tags), merge them with a given mp3 and write them to the provided - * output folder (which must already exist) - */ -public class MergeID3AndMP3Files { - - private static int count = 0; - private static int failed = 0; - - public static void main(final String[] args) { - MergeID3AndMP3Files test = new MergeID3AndMP3Files(); - - if (args.length == 0) { - System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); - System.err.println(" You must enter the from dir,outputdir and the mp3file to append"); - System.exit(1); - } else if (args.length != 3) { - System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); - System.err.println(" Only three parameters accepted"); - System.exit(1); - } - File rootDir = new File(args[0]); - if (!rootDir.isDirectory()) { - System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); - System.err.println(" Directory " + args[0] + " could not be found"); - System.exit(1); - } - - - File toDir = new File(args[1]); - if (!rootDir.isDirectory()) { - System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); - System.err.println(" Directory " + args[1] + " could not be found"); - System.exit(1); - } - - File mp3File = new File(args[2]); - if (!mp3File.isFile()) { - System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); - System.err.println(" Mp3File " + args[2] + " could not be found"); - System.exit(1); - } - - Date start = new Date(); - System.out.println("Started to merge from:" + rootDir.getPath() + " at " + DateFormat.getTimeInstance().format(start)); - test.scanSingleDir(rootDir, toDir, mp3File); - Date finish = new Date(); - System.out.println("Finished to merge from:" + rootDir.getPath() + DateFormat.getTimeInstance().format(finish)); - System.out.println("Attempted to merge:" + MergeID3AndMP3Files.count); - System.out.println("Successful to merge:" + (MergeID3AndMP3Files.count - MergeID3AndMP3Files.failed)); - System.out.println("Failed to merge:" + MergeID3AndMP3Files.failed); - - } - - public static File copyAudioToTmp(File toDir, File tagFile, File mp3File) { - File outputFile = new File(toDir.getPath(), tagFile.getName()); - boolean result = append(tagFile, mp3File, outputFile); - return outputFile; - } - - private static boolean append(File fromFile1, File fromFile2, File toFile) { - try { - FileInputStream in = new FileInputStream(fromFile1); - FileInputStream in2 = new FileInputStream(fromFile2); - - toFile.getParentFile().mkdirs(); - FileOutputStream out = new FileOutputStream(toFile); - BufferedInputStream inBuffer = new BufferedInputStream(in); - BufferedInputStream inBuffer2 = new BufferedInputStream(in2); - BufferedOutputStream outBuffer = new BufferedOutputStream(out); - - int theByte; - - while ((theByte = inBuffer.read()) > -1) { - outBuffer.write(theByte); - } - - while ((theByte = inBuffer2.read()) > -1) { - outBuffer.write(theByte); - } - - outBuffer.close(); - inBuffer.close(); - inBuffer2.close(); - out.close(); - in.close(); - in2.close(); - - // cleanupif files are not the same length - if ((fromFile1.length() + fromFile2.length()) != toFile.length()) { - toFile.delete(); - - return false; - } - - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - /** - * Recursive function to scan directory - * - * @param fromDir - * @param toDir - * @param mp3File - */ - private void scanSingleDir(final File fromDir, final File toDir, final File mp3File) { - - final File[] audioFiles = fromDir.listFiles(new MergeID3AndMP3Files.MP3FileFilter()); - if (audioFiles.length > 0) { - for (File audioFile : audioFiles) { - MergeID3AndMP3Files.count++; - - try { - copyAudioToTmp(toDir, audioFile, mp3File); - } catch (Throwable t) { - System.err.println("Unable to merge record:" + MergeID3AndMP3Files.count + ":" + mp3File.getPath()); - MergeID3AndMP3Files.failed++; - t.printStackTrace(); - } - } - } - - final File[] audioFileDirs = fromDir.listFiles(new MergeID3AndMP3Files.DirFilter()); - if (audioFileDirs.length > 0) { - for (File audioFileDir : audioFileDirs) { - scanSingleDir(audioFileDir, new File(toDir, audioFileDir.getName()), mp3File); - } - } - } - - final class MP3FileFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter { - - /** - * allows Directories - */ - private final boolean allowDirectories; - - /** - * Create a default MP3FileFilter. The allowDirectories field will - * default to false. - */ - public MP3FileFilter() { - this(false); - } - - /** - * Create an MP3FileFilter. If allowDirectories is true, then this filter - * will accept directories as well as mp3 files. If it is false then - * only mp3 files will be accepted. - * - * @param allowDirectories whether or not to accept directories - */ - private MP3FileFilter(final boolean allowDirectories) { - this.allowDirectories = allowDirectories; - } - - /** - * Determines whether or not the file is an mp3 file. If the file is - * a directory, whether or not is accepted depends upon the - * allowDirectories flag passed to the constructor. - * - * @param file the file to test - * @return true if this file or directory should be accepted - */ - public final boolean accept(final File file) { - return (((file.getName()).toLowerCase().endsWith(".mp3")) || (file.isDirectory() && (this.allowDirectories))); - } - - /** - * Returns the Name of the Filter for use in the Chooser Dialog - * - * @return The Description of the Filter - */ - public final String getDescription() { - return ".mp3 Files"; - } - } - - public final class DirFilter implements java.io.FileFilter { - public static final String IDENT = "$Id: MergeID3AndMP3Files.java 836 2009-11-12 15:44:07Z paultaylor $"; - - - public DirFilter() { - - } - - /** - * Determines whether or not the file is an mp3 file. If the file is - * a directory, whether or not is accepted depends upon the - * allowDirectories flag passed to the constructor. - * - * @param file the file to test - * @return true if this file or directory should be accepted - */ - public final boolean accept(final File file) { - return file.isDirectory(); - } - } -} diff --git a/src/main/java/org/jaudiotagger/test/TestAudioTagger.java b/src/main/java/org/jaudiotagger/test/TestAudioTagger.java deleted file mode 100644 index d4208ba..0000000 --- a/src/main/java/org/jaudiotagger/test/TestAudioTagger.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @author : Paul Taylor - *

    - * Version @version:$Id: TestAudioTagger.java 832 2009-11-12 13:25:38Z paultaylor $ - *

    - * Jaudiotagger Copyright (C)2004,2005 - *

    - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - *

    - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - *

    - * You should have received a copy of the GNU Lesser General Public License along with this library; if not, - * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - *

    - * Description: - */ -package org.jaudiotagger.test; - -import org.jaudiotagger.audio.AudioFileFilter; -import org.jaudiotagger.audio.AudioFileIO; - -import java.io.File; -import java.text.DateFormat; -import java.util.Date; - -/** - * Simple class that will attempt to recusively read all files within a directory, flags - * errors that occur. - */ -public class TestAudioTagger { - - private static int count = 0; - private static int failed = 0; - - public static void main(final String[] args) { - TestAudioTagger test = new TestAudioTagger(); - - if (args.length == 0) { - System.err.println("usage TestAudioTagger Dirname"); - System.err.println(" You must enter the root directory"); - System.exit(1); - } else if (args.length > 1) { - System.err.println("usage TestAudioTagger Dirname"); - System.err.println(" Only one parameter accepted"); - System.exit(1); - } - File rootDir = new File(args[0]); - if (!rootDir.isDirectory()) { - System.err.println("usage TestAudioTagger Dirname"); - System.err.println(" Directory " + args[0] + " could not be found"); - System.exit(1); - } - Date start = new Date(); - System.out.println("Started to read from:" + rootDir.getPath() + " at " + DateFormat.getTimeInstance().format(start)); - test.scanSingleDir(rootDir); - Date finish = new Date(); - System.out.println("Started to read from:" + rootDir.getPath() + " at " + DateFormat.getTimeInstance().format(start)); - System.out.println("Finished to read from:" + rootDir.getPath() + DateFormat.getTimeInstance().format(finish)); - System.out.println("Attempted to read:" + count); - System.out.println("Successful to read:" + (count - failed)); - System.out.println("Failed to read:" + failed); - - } - - /** - * Recursive function to scan directory - * - * @param dir - */ - private void scanSingleDir(final File dir) { - - final File[] audioFiles = dir.listFiles(new AudioFileFilter(false)); - if (audioFiles.length > 0) { - for (File audioFile : audioFiles) { - count++; - try { - AudioFileIO.read(audioFile); - } catch (Throwable t) { - System.err.println("Unable to read record:" + count + ":" + audioFile.getPath()); - failed++; - t.printStackTrace(); - } - } - } - - final File[] audioFileDirs = dir.listFiles(new DirFilter()); - if (audioFileDirs.length > 0) { - for (File audioFileDir : audioFileDirs) { - scanSingleDir(audioFileDir); - } - } - } - - - public final class DirFilter implements java.io.FileFilter { - public static final String IDENT = "$Id: TestAudioTagger.java 832 2009-11-12 13:25:38Z paultaylor $"; - - - public DirFilter() { - - } - - /** - * Determines whether or not the file is an mp3 file. If the file is - * a directory, whether or not is accepted depends upon the - * allowDirectories flag passed to the constructor. - * - * @param file the file to test - * @return true if this file or directory should be accepted - */ - public final boolean accept(final java.io.File file) { - return file.isDirectory(); - } - } -} diff --git a/src/main/java/org/jaudiotagger/test/package.html b/src/main/java/org/jaudiotagger/test/package.html deleted file mode 100644 index 1728750..0000000 --- a/src/main/java/org/jaudiotagger/test/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Tests that can be run from the command line. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/utils/EqualsUtil.java b/src/main/java/org/jaudiotagger/utils/EqualsUtil.java deleted file mode 100644 index 54caa33..0000000 --- a/src/main/java/org/jaudiotagger/utils/EqualsUtil.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.jaudiotagger.utils; - - -/** - * Collected methods which allow easy implementation of equals. - *

    - * Example use case in a class called Car: - *

    - * public boolean equals(Object aThat){
    - * if ( this == aThat ) return true;
    - * if ( !(aThat instanceof Car) ) return false;
    - * Car that = (Car)aThat;
    - * return
    - * EqualsUtil.areEqual(this.fName, that.fName) &&
    - * EqualsUtil.areEqual(this.fNumDoors, that.fNumDoors) &&
    - * EqualsUtil.areEqual(this.fGasMileage, that.fGasMileage) &&
    - * EqualsUtil.areEqual(this.fColor, that.fColor) &&
    - * Arrays.equals(this.fMaintenanceChecks, that.fMaintenanceChecks); //array!
    - * }
    - * 
    - *

    - * Arrays are not handled by this class. - * This is because the Arrays.equals methods should be used for - * array fields. - */ -public final class EqualsUtil { - - static public boolean areEqual(boolean aThis, boolean aThat) { - //System.out.println("boolean"); - return aThis == aThat; - } - - static public boolean areEqual(char aThis, char aThat) { - //System.out.println("char"); - return aThis == aThat; - } - - static public boolean areEqual(long aThis, long aThat) { - /* - * Implementation Note - * Note that byte, short, and int are handled by this method, through - * implicit conversion. - */ - //System.out.println("long"); - return aThis == aThat; - } - - static public boolean areEqual(float aThis, float aThat) { - //System.out.println("float"); - return Float.floatToIntBits(aThis) == Float.floatToIntBits(aThat); - } - - static public boolean areEqual(double aThis, double aThat) { - //System.out.println("double"); - return Double.doubleToLongBits(aThis) == Double.doubleToLongBits(aThat); - } - - /** - * Possibly-null object field. - *

    - * Includes type-safe enumerations and collections, but does not include - * arrays. See class comment. - */ - static public boolean areEqual(Object aThis, Object aThat) { - //System.out.println("Object"); - return aThis == null ? aThat == null : aThis.equals(aThat); - } -} - - diff --git a/src/main/java/org/jaudiotagger/utils/package.html b/src/main/java/org/jaudiotagger/utils/package.html deleted file mode 100644 index 7851c96..0000000 --- a/src/main/java/org/jaudiotagger/utils/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Some utility code. - -
    - - - - - - - diff --git a/src/main/java/org/jaudiotagger/utils/tree/DefaultMutableTreeNode.java b/src/main/java/org/jaudiotagger/utils/tree/DefaultMutableTreeNode.java deleted file mode 100644 index 7aa4762..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/DefaultMutableTreeNode.java +++ /dev/null @@ -1,1490 +0,0 @@ -/* - * @(#)DefaultMutableTreeNode.java 1.25 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; -// ISSUE: this class depends on nothing in AWT -- move to java.util? - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.*; - - -/** - * A DefaultMutableTreeNode is a general-purpose node in a tree data - * structure. - * For examples of using default mutable tree nodes, see - * How to Use Trees - * in The Java Tutorial. - *

    - *

    - *

    - * A tree node may have at most one parent and 0 or more children. - * DefaultMutableTreeNode provides operations for examining and modifying a - * node's parent and children and also operations for examining the tree that - * the node is a part of. A node's tree is the set of all nodes that can be - * reached by starting at the node and following all the possible links to - * parents and children. A node with no parent is the root of its tree; a - * node with no children is a leaf. A tree may consist of many subtrees, - * each node acting as the root for its own subtree. - *

    - * This class provides enumerations for efficiently traversing a tree or - * subtree in various orders or for following the path between two nodes. - * A DefaultMutableTreeNode may also hold a reference to a user object, the - * use of which is left to the user. Asking a DefaultMutableTreeNode for its - * string representation with toString() returns the string - * representation of its user object. - *

    - * This is not a thread safe class.If you intend to use - * a DefaultMutableTreeNode (or a tree of TreeNodes) in more than one thread, you - * need to do your own synchronizing. A good convention to adopt is - * synchronizing on the root node of a tree. - *

    - * While DefaultMutableTreeNode implements the MutableTreeNode interface and - * will allow you to add in any implementation of MutableTreeNode not all - * of the methods in DefaultMutableTreeNode will be applicable to all - * MutableTreeNodes implementations. Especially with some of the enumerations - * that are provided, using some of these methods assumes the - * DefaultMutableTreeNode contains only DefaultMutableNode instances. All - * of the TreeNode/MutableTreeNode methods will behave as defined no - * matter what implementations are added. - *

    - *

    - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @author Rob Davis - * @version 1.25 03/23/10 - * @see MutableTreeNode - */ -public class DefaultMutableTreeNode extends Object implements Cloneable, - MutableTreeNode, Serializable { - - /** - * An enumeration that is always empty. This is used when an enumeration - * of a leaf node's children is requested. - */ - static public final Enumeration EMPTY_ENUMERATION - = new Enumeration() { - public boolean hasMoreElements() { - return false; - } - - public TreeNode nextElement() { - throw new NoSuchElementException("No more elements"); - } - }; - - /** - * this node's parent, or null if this node has no parent - */ - protected MutableTreeNode parent; - - /** - * array of children, may be null if this node has no children - */ - protected Vector children; - - /** - * optional user object - */ - transient protected Object userObject; - - /** - * true if the node is able to have children - */ - protected boolean allowsChildren; - - - /** - * Creates a tree node that has no parent and no children, but which - * allows children. - */ - public DefaultMutableTreeNode() { - this(null); - } - - /** - * Creates a tree node with no parent, no children, but which allows - * children, and initializes it with the specified user object. - * - * @param userObject an Object provided by the user that constitutes - * the node's data - */ - public DefaultMutableTreeNode(Object userObject) { - this(userObject, true); - } - - /** - * Creates a tree node with no parent, no children, initialized with - * the specified user object, and that allows children only if - * specified. - * - * @param userObject an Object provided by the user that constitutes - * the node's data - * @param allowsChildren if true, the node is allowed to have child - * nodes -- otherwise, it is always a leaf node - */ - public DefaultMutableTreeNode(Object userObject, boolean allowsChildren) { - super(); - parent = null; - this.allowsChildren = allowsChildren; - this.userObject = userObject; - } - - - // - // Primitives - // - - /** - * Removes newChild from its present parent (if it has a - * parent), sets the child's parent to this node, and then adds the child - * to this node's child array at index childIndex. - * newChild must not be null and must not be an ancestor of - * this node. - * - * @param newChild the MutableTreeNode to insert under this node - * @param childIndex the index in this node's child array - * where this node is to be inserted - * @throws ArrayIndexOutOfBoundsException if childIndex is out of bounds - * @throws IllegalArgumentException if newChild is null or is an - * ancestor of this node - * @throws IllegalStateException if this node does not allow - * children - * @see #isNodeDescendant - */ - public void insert(MutableTreeNode newChild, int childIndex) { - if (!allowsChildren) { - throw new IllegalStateException("node does not allow children"); - } else if (newChild == null) { - throw new IllegalArgumentException("new child is null"); - } else if (isNodeAncestor(newChild)) { - throw new IllegalArgumentException("new child is an ancestor"); - } - - MutableTreeNode oldParent = (MutableTreeNode) newChild.getParent(); - - if (oldParent != null) { - oldParent.remove(newChild); - } - newChild.setParent(this); - if (children == null) { - children = new Vector(); - } - children.insertElementAt(newChild, childIndex); - } - - /** - * Removes the child at the specified index from this node's children - * and sets that node's parent to null. The child node to remove - * must be a MutableTreeNode. - * - * @param childIndex the index in this node's child array - * of the child to remove - * @throws ArrayIndexOutOfBoundsException if childIndex is out of bounds - */ - public void remove(int childIndex) { - MutableTreeNode child = (MutableTreeNode) getChildAt(childIndex); - children.removeElementAt(childIndex); - child.setParent(null); - } - - /** - * Returns this node's parent or null if this node has no parent. - * - * @return this node's parent TreeNode, or null if this node has no parent - */ - public TreeNode getParent() { - return parent; - } - - /** - * Sets this node's parent to newParent but does not - * change the parent's child array. This method is called from - * insert() and remove() to - * reassign a child's parent, it should not be messaged from anywhere - * else. - * - * @param newParent this node's new parent - */ - public void setParent(MutableTreeNode newParent) { - parent = newParent; - } - - /** - * Returns the child at the specified index in this node's child array. - * - * @param index an index into this node's child array - * @return the TreeNode in this node's child array at the specified index - * @throws ArrayIndexOutOfBoundsException if index - * is out of bounds - */ - public TreeNode getChildAt(int index) { - if (children == null) { - throw new ArrayIndexOutOfBoundsException("node has no children"); - } - return (TreeNode) children.elementAt(index); - } - - /** - * Returns the number of children of this node. - * - * @return an int giving the number of children of this node - */ - public int getChildCount() { - if (children == null) { - return 0; - } else { - return children.size(); - } - } - - /** - * Returns the index of the specified child in this node's child array. - * If the specified node is not a child of this node, returns - * -1. This method performs a linear search and is O(n) - * where n is the number of children. - * - * @param aChild the TreeNode to search for among this node's children - * @return an int giving the index of the node in this node's child - * array, or -1 if the specified node is a not - * a child of this node - * @throws IllegalArgumentException if aChild - * is null - */ - public int getIndex(TreeNode aChild) { - if (aChild == null) { - throw new IllegalArgumentException("argument is null"); - } - - if (!isNodeChild(aChild)) { - return -1; - } - return children.indexOf(aChild); // linear search - } - - /** - * Creates and returns a forward-order enumeration of this node's - * children. Modifying this node's child array invalidates any child - * enumerations created before the modification. - * - * @return an Enumeration of this node's children - */ - public Enumeration children() { - if (children == null) { - return EMPTY_ENUMERATION; - } else { - return children.elements(); - } - } - - /** - * Returns true if this node is allowed to have children. - * - * @return true if this node allows children, else false - */ - public boolean getAllowsChildren() { - return allowsChildren; - } - - /** - * Determines whether or not this node is allowed to have children. - * If allows is false, all of this node's children are - * removed. - *

    - * Note: By default, a node allows children. - * - * @param allows true if this node is allowed to have children - */ - public void setAllowsChildren(boolean allows) { - if (allows != allowsChildren) { - allowsChildren = allows; - if (!allowsChildren) { - removeAllChildren(); - } - } - } - - /** - * Returns this node's user object. - * - * @return the Object stored at this node by the user - * @see #setUserObject - * @see #toString - */ - public Object getUserObject() { - return userObject; - } - - /** - * Sets the user object for this node to userObject. - * - * @param userObject the Object that constitutes this node's - * user-specified data - * @see #getUserObject - * @see #toString - */ - public void setUserObject(Object userObject) { - this.userObject = userObject; - } - - - // - // Derived methods - // - - /** - * Removes the subtree rooted at this node from the tree, giving this - * node a null parent. Does nothing if this node is the root of its - * tree. - */ - public void removeFromParent() { - MutableTreeNode parent = (MutableTreeNode) getParent(); - if (parent != null) { - parent.remove(this); - } - } - - /** - * Removes aChild from this node's child array, giving it a - * null parent. - * - * @param aChild a child of this node to remove - * @throws IllegalArgumentException if aChild - * is null or is not a child of this node - */ - public void remove(MutableTreeNode aChild) { - if (aChild == null) { - throw new IllegalArgumentException("argument is null"); - } - - if (!isNodeChild(aChild)) { - throw new IllegalArgumentException("argument is not a child"); - } - remove(getIndex(aChild)); // linear search - } - - /** - * Removes all of this node's children, setting their parents to null. - * If this node has no children, this method does nothing. - */ - public void removeAllChildren() { - for (int i = getChildCount() - 1; i >= 0; i--) { - remove(i); - } - } - - /** - * Removes newChild from its parent and makes it a child of - * this node by adding it to the end of this node's child array. - * - * @param newChild node to add as a child of this node - * @throws IllegalArgumentException if newChild - * is null - * @throws IllegalStateException if this node does not allow - * children - * @see #insert - */ - public void add(MutableTreeNode newChild) { - if (newChild != null && newChild.getParent() == this) - insert(newChild, getChildCount() - 1); - else - insert(newChild, getChildCount()); - } - - - // - // Tree Queries - // - - /** - * Returns true if anotherNode is an ancestor of this node - * -- if it is this node, this node's parent, or an ancestor of this - * node's parent. (Note that a node is considered an ancestor of itself.) - * If anotherNode is null, this method returns false. This - * operation is at worst O(h) where h is the distance from the root to - * this node. - * - * @param anotherNode node to test as an ancestor of this node - * @return true if this node is a descendant of anotherNode - * @see #isNodeDescendant - * @see #getSharedAncestor - */ - public boolean isNodeAncestor(TreeNode anotherNode) { - if (anotherNode == null) { - return false; - } - - TreeNode ancestor = this; - - do { - if (ancestor == anotherNode) { - return true; - } - } while ((ancestor = ancestor.getParent()) != null); - - return false; - } - - /** - * Returns true if anotherNode is a descendant of this node - * -- if it is this node, one of this node's children, or a descendant of - * one of this node's children. Note that a node is considered a - * descendant of itself. If anotherNode is null, returns - * false. This operation is at worst O(h) where h is the distance from the - * root to anotherNode. - * - * @param anotherNode node to test as descendant of this node - * @return true if this node is an ancestor of anotherNode - * @see #isNodeAncestor - * @see #getSharedAncestor - */ - public boolean isNodeDescendant(DefaultMutableTreeNode anotherNode) { - if (anotherNode == null) - return false; - - return anotherNode.isNodeAncestor(this); - } - - /** - * Returns the nearest common ancestor to this node and aNode. - * Returns null, if no such ancestor exists -- if this node and - * aNode are in different trees or if aNode is - * null. A node is considered an ancestor of itself. - * - * @param aNode node to find common ancestor with - * @return nearest ancestor common to this node and aNode, - * or null if none - * @see #isNodeAncestor - * @see #isNodeDescendant - */ - public TreeNode getSharedAncestor(DefaultMutableTreeNode aNode) { - if (aNode == this) { - return this; - } else if (aNode == null) { - return null; - } - - int level1, level2, diff; - TreeNode node1, node2; - - level1 = getLevel(); - level2 = aNode.getLevel(); - - if (level2 > level1) { - diff = level2 - level1; - node1 = aNode; - node2 = this; - } else { - diff = level1 - level2; - node1 = this; - node2 = aNode; - } - - // Go up the tree until the nodes are at the same level - while (diff > 0) { - node1 = node1.getParent(); - diff--; - } - - // Move up the tree until we find a common ancestor. Since we know - // that both nodes are at the same level, we won't cross paths - // unknowingly (if there is a common ancestor, both nodes hit it in - // the same iteration). - - do { - if (node1 == node2) { - return node1; - } - node1 = node1.getParent(); - node2 = node2.getParent(); - } while (node1 != null);// only need to check one -- they're at the - // same level so if one is null, the other is - - if (node1 != null || node2 != null) { - throw new Error("nodes should be null"); - } - - return null; - } - - - /** - * Returns true if and only if aNode is in the same tree - * as this node. Returns false if aNode is null. - * - * @return true if aNode is in the same tree as this node; - * false if aNode is null - * @see #getSharedAncestor - * @see #getRoot - */ - public boolean isNodeRelated(DefaultMutableTreeNode aNode) { - return (aNode != null) && (getRoot() == aNode.getRoot()); - } - - - /** - * Returns the depth of the tree rooted at this node -- the longest - * distance from this node to a leaf. If this node has no children, - * returns 0. This operation is much more expensive than - * getLevel() because it must effectively traverse the entire - * tree rooted at this node. - * - * @return the depth of the tree whose root is this node - * @see #getLevel - */ - public int getDepth() { - Object last = null; - Enumeration enum_ = breadthFirstEnumeration(); - - while (enum_.hasMoreElements()) { - last = enum_.nextElement(); - } - - if (last == null) { - throw new Error("nodes should be null"); - } - - return ((DefaultMutableTreeNode) last).getLevel() - getLevel(); - } - - - /** - * Returns the number of levels above this node -- the distance from - * the root to this node. If this node is the root, returns 0. - * - * @return the number of levels above this node - * @see #getDepth - */ - public int getLevel() { - TreeNode ancestor; - int levels = 0; - - ancestor = this; - while ((ancestor = ancestor.getParent()) != null) { - levels++; - } - - return levels; - } - - - /** - * Returns the path from the root, to get to this node. The last - * element in the path is this node. - * - * @return an array of TreeNode objects giving the path, where the - * first element in the path is the root and the last - * element is this node. - */ - public TreeNode[] getPath() { - return getPathToRoot(this, 0); - } - - /** - * Builds the parents of node up to and including the root node, - * where the original node is the last element in the returned array. - * The length of the returned array gives the node's depth in the - * tree. - * - * @param aNode the TreeNode to get the path for - * @param depth an int giving the number of steps already taken towards - * the root (on recursive calls), used to size the returned array - * @return an array of TreeNodes giving the path from the root to the - * specified node - */ - protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) { - TreeNode[] retNodes; - - /* Check for null, in case someone passed in a null node, or - they passed in an element that isn't rooted at root. */ - if (aNode == null) { - if (depth == 0) - return null; - else - retNodes = new TreeNode[depth]; - } else { - depth++; - retNodes = getPathToRoot(aNode.getParent(), depth); - retNodes[retNodes.length - depth] = aNode; - } - return retNodes; - } - - /** - * Returns the user object path, from the root, to get to this node. - * If some of the TreeNodes in the path have null user objects, the - * returned path will contain nulls. - */ - public Object[] getUserObjectPath() { - TreeNode[] realPath = getPath(); - Object[] retPath = new Object[realPath.length]; - - for (int counter = 0; counter < realPath.length; counter++) - retPath[counter] = ((DefaultMutableTreeNode) realPath[counter]) - .getUserObject(); - return retPath; - } - - /** - * Returns the root of the tree that contains this node. The root is - * the ancestor with a null parent. - * - * @return the root of the tree that contains this node - * @see #isNodeAncestor - */ - public TreeNode getRoot() { - TreeNode ancestor = this; - TreeNode previous; - - do { - previous = ancestor; - ancestor = ancestor.getParent(); - } while (ancestor != null); - - return previous; - } - - - /** - * Returns true if this node is the root of the tree. The root is - * the only node in the tree with a null parent; every tree has exactly - * one root. - * - * @return true if this node is the root of its tree - */ - public boolean isRoot() { - return getParent() == null; - } - - - /** - * Returns the node that follows this node in a preorder traversal of this - * node's tree. Returns null if this node is the last node of the - * traversal. This is an inefficient way to traverse the entire tree; use - * an enumeration, instead. - * - * @return the node that follows this node in a preorder traversal, or - * null if this node is last - * @see #preorderEnumeration - */ - public DefaultMutableTreeNode getNextNode() { - if (getChildCount() == 0) { - // No children, so look for nextSibling - DefaultMutableTreeNode nextSibling = getNextSibling(); - - if (nextSibling == null) { - DefaultMutableTreeNode aNode = (DefaultMutableTreeNode) getParent(); - - do { - if (aNode == null) { - return null; - } - - nextSibling = aNode.getNextSibling(); - if (nextSibling != null) { - return nextSibling; - } - - aNode = (DefaultMutableTreeNode) aNode.getParent(); - } while (true); - } else { - return nextSibling; - } - } else { - return (DefaultMutableTreeNode) getChildAt(0); - } - } - - - /** - * Returns the node that precedes this node in a preorder traversal of - * this node's tree. Returns null if this node is the - * first node of the traversal -- the root of the tree. - * This is an inefficient way to - * traverse the entire tree; use an enumeration, instead. - * - * @return the node that precedes this node in a preorder traversal, or - * null if this node is the first - * @see #preorderEnumeration - */ - public DefaultMutableTreeNode getPreviousNode() { - DefaultMutableTreeNode previousSibling; - DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent(); - - if (myParent == null) { - return null; - } - - previousSibling = getPreviousSibling(); - - if (previousSibling != null) { - if (previousSibling.getChildCount() == 0) - return previousSibling; - else - return previousSibling.getLastLeaf(); - } else { - return myParent; - } - } - - /** - * Creates and returns an enumeration that traverses the subtree rooted at - * this node in preorder. The first node returned by the enumeration's - * nextElement() method is this node.

    - *

    - * Modifying the tree by inserting, removing, or moving a node invalidates - * any enumerations created before the modification. - * - * @return an enumeration for traversing the tree in preorder - * @see #postorderEnumeration - */ - public Enumeration preorderEnumeration() { - return new PreorderEnumeration(this); - } - - /** - * Creates and returns an enumeration that traverses the subtree rooted at - * this node in postorder. The first node returned by the enumeration's - * nextElement() method is the leftmost leaf. This is the - * same as a depth-first traversal.

    - *

    - * Modifying the tree by inserting, removing, or moving a node invalidates - * any enumerations created before the modification. - * - * @return an enumeration for traversing the tree in postorder - * @see #depthFirstEnumeration - * @see #preorderEnumeration - */ - public Enumeration postorderEnumeration() { - return new PostorderEnumeration(this); - } - - /** - * Creates and returns an enumeration that traverses the subtree rooted at - * this node in breadth-first order. The first node returned by the - * enumeration's nextElement() method is this node.

    - *

    - * Modifying the tree by inserting, removing, or moving a node invalidates - * any enumerations created before the modification. - * - * @return an enumeration for traversing the tree in breadth-first order - * @see #depthFirstEnumeration - */ - public Enumeration breadthFirstEnumeration() { - return new BreadthFirstEnumeration(this); - } - - /** - * Creates and returns an enumeration that traverses the subtree rooted at - * this node in depth-first order. The first node returned by the - * enumeration's nextElement() method is the leftmost leaf. - * This is the same as a postorder traversal.

    - *

    - * Modifying the tree by inserting, removing, or moving a node invalidates - * any enumerations created before the modification. - * - * @return an enumeration for traversing the tree in depth-first order - * @see #breadthFirstEnumeration - * @see #postorderEnumeration - */ - public Enumeration depthFirstEnumeration() { - return postorderEnumeration(); - } - - /** - * Creates and returns an enumeration that follows the path from - * ancestor to this node. The enumeration's - * nextElement() method first returns ancestor, - * then the child of ancestor that is an ancestor of this - * node, and so on, and finally returns this node. Creation of the - * enumeration is O(m) where m is the number of nodes between this node - * and ancestor, inclusive. Each nextElement() - * message is O(1).

    - *

    - * Modifying the tree by inserting, removing, or moving a node invalidates - * any enumerations created before the modification. - * - * @return an enumeration for following the path from an ancestor of - * this node to this one - * @throws IllegalArgumentException if ancestor is - * not an ancestor of this node - * @see #isNodeAncestor - * @see #isNodeDescendant - */ - public Enumeration pathFromAncestorEnumeration(TreeNode ancestor) { - return new PathBetweenNodesEnumeration(ancestor, this); - } - - - // - // Child Queries - // - - /** - * Returns true if aNode is a child of this node. If - * aNode is null, this method returns false. - * - * @return true if aNode is a child of this node; false if - * aNode is null - */ - public boolean isNodeChild(TreeNode aNode) { - boolean retval; - - if (aNode == null) { - retval = false; - } else { - if (getChildCount() == 0) { - retval = false; - } else { - retval = (aNode.getParent() == this); - } - } - - return retval; - } - - - /** - * Returns this node's first child. If this node has no children, - * throws NoSuchElementException. - * - * @return the first child of this node - * @throws NoSuchElementException if this node has no children - */ - public TreeNode getFirstChild() { - if (getChildCount() == 0) { - throw new NoSuchElementException("node has no children"); - } - return getChildAt(0); - } - - - /** - * Returns this node's last child. If this node has no children, - * throws NoSuchElementException. - * - * @return the last child of this node - * @throws NoSuchElementException if this node has no children - */ - public TreeNode getLastChild() { - if (getChildCount() == 0) { - throw new NoSuchElementException("node has no children"); - } - return getChildAt(getChildCount() - 1); - } - - - /** - * Returns the child in this node's child array that immediately - * follows aChild, which must be a child of this node. If - * aChild is the last child, returns null. This method - * performs a linear search of this node's children for - * aChild and is O(n) where n is the number of children; to - * traverse the entire array of children, use an enumeration instead. - * - * @return the child of this node that immediately follows - * aChild - * @throws IllegalArgumentException if aChild is - * null or is not a child of this node - * @see #children - */ - public TreeNode getChildAfter(TreeNode aChild) { - if (aChild == null) { - throw new IllegalArgumentException("argument is null"); - } - - int index = getIndex(aChild); // linear search - - if (index == -1) { - throw new IllegalArgumentException("node is not a child"); - } - - if (index < getChildCount() - 1) { - return getChildAt(index + 1); - } else { - return null; - } - } - - - /** - * Returns the child in this node's child array that immediately - * precedes aChild, which must be a child of this node. If - * aChild is the first child, returns null. This method - * performs a linear search of this node's children for aChild - * and is O(n) where n is the number of children. - * - * @return the child of this node that immediately precedes - * aChild - * @throws IllegalArgumentException if aChild is null - * or is not a child of this node - */ - public TreeNode getChildBefore(TreeNode aChild) { - if (aChild == null) { - throw new IllegalArgumentException("argument is null"); - } - - int index = getIndex(aChild); // linear search - - if (index == -1) { - throw new IllegalArgumentException("argument is not a child"); - } - - if (index > 0) { - return getChildAt(index - 1); - } else { - return null; - } - } - - - // - // Sibling Queries - // - - - /** - * Returns true if anotherNode is a sibling of (has the - * same parent as) this node. A node is its own sibling. If - * anotherNode is null, returns false. - * - * @param anotherNode node to test as sibling of this node - * @return true if anotherNode is a sibling of this node - */ - public boolean isNodeSibling(TreeNode anotherNode) { - boolean retval; - - if (anotherNode == null) { - retval = false; - } else if (anotherNode == this) { - retval = true; - } else { - TreeNode myParent = getParent(); - retval = (myParent != null && myParent == anotherNode.getParent()); - - if (retval && !((DefaultMutableTreeNode) getParent()) - .isNodeChild(anotherNode)) { - throw new Error("sibling has different parent"); - } - } - - return retval; - } - - - /** - * Returns the number of siblings of this node. A node is its own sibling - * (if it has no parent or no siblings, this method returns - * 1). - * - * @return the number of siblings of this node - */ - public int getSiblingCount() { - TreeNode myParent = getParent(); - - if (myParent == null) { - return 1; - } else { - return myParent.getChildCount(); - } - } - - - /** - * Returns the next sibling of this node in the parent's children array. - * Returns null if this node has no parent or is the parent's last child. - * This method performs a linear search that is O(n) where n is the number - * of children; to traverse the entire array, use the parent's child - * enumeration instead. - * - * @return the sibling of this node that immediately follows this node - * @see #children - */ - public DefaultMutableTreeNode getNextSibling() { - DefaultMutableTreeNode retval; - - DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent(); - - if (myParent == null) { - retval = null; - } else { - retval = (DefaultMutableTreeNode) myParent.getChildAfter(this); // linear search - } - - if (retval != null && !isNodeSibling(retval)) { - throw new Error("child of parent is not a sibling"); - } - - return retval; - } - - - /** - * Returns the previous sibling of this node in the parent's children - * array. Returns null if this node has no parent or is the parent's - * first child. This method performs a linear search that is O(n) where n - * is the number of children. - * - * @return the sibling of this node that immediately precedes this node - */ - public DefaultMutableTreeNode getPreviousSibling() { - DefaultMutableTreeNode retval; - - DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent(); - - if (myParent == null) { - retval = null; - } else { - retval = (DefaultMutableTreeNode) myParent.getChildBefore(this); // linear search - } - - if (retval != null && !isNodeSibling(retval)) { - throw new Error("child of parent is not a sibling"); - } - - return retval; - } - - - // - // Leaf Queries - // - - /** - * Returns true if this node has no children. To distinguish between - * nodes that have no children and nodes that cannot have - * children (e.g. to distinguish files from empty directories), use this - * method in conjunction with getAllowsChildren - * - * @return true if this node has no children - * @see #getAllowsChildren - */ - public boolean isLeaf() { - return (getChildCount() == 0); - } - - - /** - * Finds and returns the first leaf that is a descendant of this node -- - * either this node or its first child's first leaf. - * Returns this node if it is a leaf. - * - * @return the first leaf in the subtree rooted at this node - * @see #isLeaf - * @see #isNodeDescendant - */ - public DefaultMutableTreeNode getFirstLeaf() { - DefaultMutableTreeNode node = this; - - while (!node.isLeaf()) { - node = (DefaultMutableTreeNode) node.getFirstChild(); - } - - return node; - } - - - /** - * Finds and returns the last leaf that is a descendant of this node -- - * either this node or its last child's last leaf. - * Returns this node if it is a leaf. - * - * @return the last leaf in the subtree rooted at this node - * @see #isLeaf - * @see #isNodeDescendant - */ - public DefaultMutableTreeNode getLastLeaf() { - DefaultMutableTreeNode node = this; - - while (!node.isLeaf()) { - node = (DefaultMutableTreeNode) node.getLastChild(); - } - - return node; - } - - - /** - * Returns the leaf after this node or null if this node is the - * last leaf in the tree. - *

    - * In this implementation of the MutableNode interface, - * this operation is very inefficient. In order to determine the - * next node, this method first performs a linear search in the - * parent's child-list in order to find the current node. - *

    - * That implementation makes the operation suitable for short - * traversals from a known position. But to traverse all of the - * leaves in the tree, you should use depthFirstEnumeration - * to enumerate the nodes in the tree and use isLeaf - * on each node to determine which are leaves. - * - * @return returns the next leaf past this node - * @see #depthFirstEnumeration - * @see #isLeaf - */ - public DefaultMutableTreeNode getNextLeaf() { - DefaultMutableTreeNode nextSibling; - DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent(); - - if (myParent == null) - return null; - - nextSibling = getNextSibling(); // linear search - - if (nextSibling != null) - return nextSibling.getFirstLeaf(); - - return myParent.getNextLeaf(); // tail recursion - } - - - /** - * Returns the leaf before this node or null if this node is the - * first leaf in the tree. - *

    - * In this implementation of the MutableNode interface, - * this operation is very inefficient. In order to determine the - * previous node, this method first performs a linear search in the - * parent's child-list in order to find the current node. - *

    - * That implementation makes the operation suitable for short - * traversals from a known position. But to traverse all of the - * leaves in the tree, you should use depthFirstEnumeration - * to enumerate the nodes in the tree and use isLeaf - * on each node to determine which are leaves. - * - * @return returns the leaf before this node - * @see #depthFirstEnumeration - * @see #isLeaf - */ - public DefaultMutableTreeNode getPreviousLeaf() { - DefaultMutableTreeNode previousSibling; - DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent(); - - if (myParent == null) - return null; - - previousSibling = getPreviousSibling(); // linear search - - if (previousSibling != null) - return previousSibling.getLastLeaf(); - - return myParent.getPreviousLeaf(); // tail recursion - } - - - /** - * Returns the total number of leaves that are descendants of this node. - * If this node is a leaf, returns 1. This method is O(n) - * where n is the number of descendants of this node. - * - * @return the number of leaves beneath this node - * @see #isNodeAncestor - */ - public int getLeafCount() { - int count = 0; - - TreeNode node; - Enumeration enum_ = breadthFirstEnumeration(); // order matters not - - while (enum_.hasMoreElements()) { - node = (TreeNode) enum_.nextElement(); - if (node.isLeaf()) { - count++; - } - } - - if (count < 1) { - throw new Error("tree has zero leaves"); - } - - return count; - } - - - // - // Overrides - // - - /** - * Returns the result of sending toString() to this node's - * user object, or null if this node has no user object. - * - * @see #getUserObject - */ - public String toString() { - if (userObject == null) { - return null; - } else { - return userObject.toString(); - } - } - - /** - * Overridden to make clone public. Returns a shallow copy of this node; - * the new node has no parent or children and has a reference to the same - * user object, if any. - * - * @return a copy of this node - */ - public Object clone() { - DefaultMutableTreeNode newNode = null; - - try { - newNode = (DefaultMutableTreeNode) super.clone(); - - // shallow copy -- the new node has no parent or children - newNode.children = null; - newNode.parent = null; - - } catch (CloneNotSupportedException e) { - // Won't happen because we implement Cloneable - throw new Error(e.toString()); - } - - return newNode; - } - - - // Serialization support. - private void writeObject(ObjectOutputStream s) throws IOException { - Object[] tValues; - - s.defaultWriteObject(); - // Save the userObject, if its Serializable. - if (userObject != null && userObject instanceof Serializable) { - tValues = new Object[2]; - tValues[0] = "userObject"; - tValues[1] = userObject; - } else - tValues = new Object[0]; - s.writeObject(tValues); - } - - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - Object[] tValues; - - s.defaultReadObject(); - - tValues = (Object[]) s.readObject(); - - if (tValues.length > 0 && tValues[0].equals("userObject")) - userObject = tValues[1]; - } - - final class PreorderEnumeration implements Enumeration { - protected Stack stack; - - public PreorderEnumeration(TreeNode rootNode) { - super(); - Vector v = new Vector(1); - v.addElement(rootNode); // PENDING: don't really need a vector - stack = new Stack(); - stack.push(v.elements()); - } - - public boolean hasMoreElements() { - return (!stack.empty() && - ((Enumeration) stack.peek()).hasMoreElements()); - } - - public TreeNode nextElement() { - Enumeration enumer = (Enumeration) stack.peek(); - TreeNode node = (TreeNode) enumer.nextElement(); - Enumeration children = node.children(); - - if (!enumer.hasMoreElements()) { - stack.pop(); - } - if (children.hasMoreElements()) { - stack.push(children); - } - return node; - } - - } // End of class PreorderEnumeration - - - final class PostorderEnumeration implements Enumeration { - protected TreeNode root; - protected Enumeration children; - protected Enumeration subtree; - - public PostorderEnumeration(TreeNode rootNode) { - super(); - root = rootNode; - children = root.children(); - subtree = EMPTY_ENUMERATION; - } - - public boolean hasMoreElements() { - return root != null; - } - - public TreeNode nextElement() { - TreeNode retval; - - if (subtree.hasMoreElements()) { - retval = subtree.nextElement(); - } else if (children.hasMoreElements()) { - subtree = new PostorderEnumeration( - children.nextElement()); - retval = subtree.nextElement(); - } else { - retval = root; - root = null; - } - - return retval; - } - - } // End of class PostorderEnumeration - - - final class BreadthFirstEnumeration implements Enumeration { - protected Queue queue; - - public BreadthFirstEnumeration(TreeNode rootNode) { - super(); - Vector v = new Vector(1); - v.addElement(rootNode); // PENDING: don't really need a vector - queue = new Queue(); - queue.enqueue(v.elements()); - } - - public boolean hasMoreElements() { - return (!queue.isEmpty() && - ((Enumeration) queue.firstObject()).hasMoreElements()); - } - - public TreeNode nextElement() { - Enumeration enumer = (Enumeration) queue.firstObject(); - TreeNode node = (TreeNode) enumer.nextElement(); - Enumeration children = node.children(); - - if (!enumer.hasMoreElements()) { - queue.dequeue(); - } - if (children.hasMoreElements()) { - queue.enqueue(children); - } - return node; - } - - - // A simple queue with a linked list data structure. - final class Queue { - QNode head; // null if empty - QNode tail; - - public void enqueue(Object anObject) { - if (head == null) { - head = tail = new QNode(anObject, null); - } else { - tail.next = new QNode(anObject, null); - tail = tail.next; - } - } - - public Object dequeue() { - if (head == null) { - throw new NoSuchElementException("No more elements"); - } - - Object retval = head.object; - QNode oldHead = head; - head = head.next; - if (head == null) { - tail = null; - } else { - oldHead.next = null; - } - return retval; - } - - public Object firstObject() { - if (head == null) { - throw new NoSuchElementException("No more elements"); - } - - return head.object; - } - - public boolean isEmpty() { - return head == null; - } - - final class QNode { - public Object object; - public QNode next; // null if end - - public QNode(Object object, QNode next) { - this.object = object; - this.next = next; - } - } - - } // End of class Queue - - } // End of class BreadthFirstEnumeration - - - final class PathBetweenNodesEnumeration implements Enumeration { - protected Stack stack; - - public PathBetweenNodesEnumeration(TreeNode ancestor, - TreeNode descendant) { - super(); - - if (ancestor == null || descendant == null) { - throw new IllegalArgumentException("argument is null"); - } - - TreeNode current; - - stack = new Stack(); - stack.push(descendant); - - current = descendant; - while (current != ancestor) { - current = current.getParent(); - if (current == null && descendant != ancestor) { - throw new IllegalArgumentException("node " + ancestor + - " is not an ancestor of " + descendant); - } - stack.push(current); - } - } - - public boolean hasMoreElements() { - return stack.size() > 0; - } - - public TreeNode nextElement() { - try { - return stack.pop(); - } catch (EmptyStackException e) { - throw new NoSuchElementException("No more elements"); - } - } - - } // End of class PathBetweenNodesEnumeration - - -} // End of class DefaultMutableTreeNode diff --git a/src/main/java/org/jaudiotagger/utils/tree/DefaultTreeModel.java b/src/main/java/org/jaudiotagger/utils/tree/DefaultTreeModel.java deleted file mode 100644 index 6dea25c..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/DefaultTreeModel.java +++ /dev/null @@ -1,662 +0,0 @@ -/* - * @(#)DefaultTreeModel.java 1.58 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.EventListener; -import java.util.Vector; - - -/** - * A simple tree data model that uses TreeNodes. - * For further information and examples that use DefaultTreeModel, - * see How to Use Trees - * in The Java Tutorial. - *

    - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @author Rob Davis - * @author Ray Ryan - * @author Scott Violet - * @version 1.58 03/23/10 - */ -public class DefaultTreeModel implements Serializable, TreeModel { - /** - * Root of the tree. - */ - protected TreeNode root; - /** - * Listeners. - */ - protected EventListenerList listenerList = new EventListenerList(); - /** - * Determines how the isLeaf method figures - * out if a node is a leaf node. If true, a node is a leaf - * node if it does not allow children. (If it allows - * children, it is not a leaf node, even if no children - * are present.) That lets you distinguish between folder - * nodes and file nodes in a file system, for example. - *

    - * If this value is false, then any node which has no - * children is a leaf node, and any node may acquire - * children. - * - * @see TreeNode#getAllowsChildren - * @see TreeModel#isLeaf - * @see #setAsksAllowsChildren - */ - protected boolean asksAllowsChildren; - - - /** - * Creates a tree in which any node can have children. - * - * @param root a TreeNode object that is the root of the tree - * @see #DefaultTreeModel(TreeNode, boolean) - */ - public DefaultTreeModel(TreeNode root) { - this(root, false); - } - - /** - * Creates a tree specifying whether any node can have children, - * or whether only certain nodes can have children. - * - * @param root a TreeNode object that is the root of the tree - * @param asksAllowsChildren a boolean, false if any node can - * have children, true if each node is asked to see if - * it can have children - * @see #asksAllowsChildren - */ - public DefaultTreeModel(TreeNode root, boolean asksAllowsChildren) { - super(); - this.root = root; - this.asksAllowsChildren = asksAllowsChildren; - } - - /** - * Sets whether or not to test leafness by asking getAllowsChildren() - * or isLeaf() to the TreeNodes. If newvalue is true, getAllowsChildren() - * is messaged, otherwise isLeaf() is messaged. - */ - public void setAsksAllowsChildren(boolean newValue) { - asksAllowsChildren = newValue; - } - - /** - * Tells how leaf nodes are determined. - * - * @return true if only nodes which do not allow children are - * leaf nodes, false if nodes which have no children - * (even if allowed) are leaf nodes - * @see #asksAllowsChildren - */ - public boolean asksAllowsChildren() { - return asksAllowsChildren; - } - - /** - * Returns the root of the tree. Returns null only if the tree has - * no nodes. - * - * @return the root of the tree - */ - public Object getRoot() { - return root; - } - - /** - * Sets the root to root. A null root implies - * the tree is to display nothing, and is legal. - */ - public void setRoot(TreeNode root) { - Object oldRoot = this.root; - this.root = root; - if (root == null && oldRoot != null) { - fireTreeStructureChanged(this, null); - } else { - nodeStructureChanged(root); - } - } - - /** - * Returns the index of child in parent. - * If either the parent or child is null, returns -1. - * - * @param parent a note in the tree, obtained from this data source - * @param child the node we are interested in - * @return the index of the child in the parent, or -1 - * if either the parent or the child is null - */ - public int getIndexOfChild(Object parent, Object child) { - if (parent == null || child == null) - return -1; - return ((TreeNode) parent).getIndex((TreeNode) child); - } - - /** - * Returns the child of parent at index index in the parent's - * child array. parent must be a node previously obtained from - * this data source. This should not return null if index - * is a valid index for parent (that is index >= 0 && - * index < getChildCount(parent)). - * - * @param parent a node in the tree, obtained from this data source - * @return the child of parent at index index - */ - public Object getChild(Object parent, int index) { - return ((TreeNode) parent).getChildAt(index); - } - - /** - * Returns the number of children of parent. Returns 0 if the node - * is a leaf or if it has no children. parent must be a node - * previously obtained from this data source. - * - * @param parent a node in the tree, obtained from this data source - * @return the number of children of the node parent - */ - public int getChildCount(Object parent) { - return ((TreeNode) parent).getChildCount(); - } - - /** - * Returns whether the specified node is a leaf node. - * The way the test is performed depends on the - * askAllowsChildren setting. - * - * @param node the node to check - * @return true if the node is a leaf node - * @see #asksAllowsChildren - * @see TreeModel#isLeaf - */ - public boolean isLeaf(Object node) { - if (asksAllowsChildren) - return !((TreeNode) node).getAllowsChildren(); - return ((TreeNode) node).isLeaf(); - } - - /** - * Invoke this method if you've modified the {@code TreeNode}s upon which - * this model depends. The model will notify all of its listeners that the - * model has changed. - */ - public void reload() { - reload(root); - } - - /** - * This sets the user object of the TreeNode identified by path - * and posts a node changed. If you use custom user objects in - * the TreeModel you're going to need to subclass this and - * set the user object of the changed node to something meaningful. - */ - public void valueForPathChanged(TreePath path, Object newValue) { - MutableTreeNode aNode = (MutableTreeNode) path.getLastPathComponent(); - - aNode.setUserObject(newValue); - nodeChanged(aNode); - } - - /** - * Invoked this to insert newChild at location index in parents children. - * This will then message nodesWereInserted to create the appropriate - * event. This is the preferred way to add children as it will create - * the appropriate event. - */ - public void insertNodeInto(MutableTreeNode newChild, - MutableTreeNode parent, int index) { - parent.insert(newChild, index); - - int[] newIndexs = new int[1]; - - newIndexs[0] = index; - nodesWereInserted(parent, newIndexs); - } - - /** - * Message this to remove node from its parent. This will message - * nodesWereRemoved to create the appropriate event. This is the - * preferred way to remove a node as it handles the event creation - * for you. - */ - public void removeNodeFromParent(MutableTreeNode node) { - MutableTreeNode parent = (MutableTreeNode) node.getParent(); - - if (parent == null) - throw new IllegalArgumentException("node does not have a parent."); - - int[] childIndex = new int[1]; - Object[] removedArray = new Object[1]; - - childIndex[0] = parent.getIndex(node); - parent.remove(childIndex[0]); - removedArray[0] = node; - nodesWereRemoved(parent, childIndex, removedArray); - } - - /** - * Invoke this method after you've changed how node is to be - * represented in the tree. - */ - public void nodeChanged(TreeNode node) { - if (listenerList != null && node != null) { - TreeNode parent = node.getParent(); - - if (parent != null) { - int anIndex = parent.getIndex(node); - if (anIndex != -1) { - int[] cIndexs = new int[1]; - - cIndexs[0] = anIndex; - nodesChanged(parent, cIndexs); - } - } else if (node == getRoot()) { - nodesChanged(node, null); - } - } - } - - /** - * Invoke this method if you've modified the {@code TreeNode}s upon which - * this model depends. The model will notify all of its listeners that the - * model has changed below the given node. - * - * @param node the node below which the model has changed - */ - public void reload(TreeNode node) { - if (node != null) { - fireTreeStructureChanged(this, getPathToRoot(node), null, null); - } - } - - /** - * Invoke this method after you've inserted some TreeNodes into - * node. childIndices should be the index of the new elements and - * must be sorted in ascending order. - */ - public void nodesWereInserted(TreeNode node, int[] childIndices) { - if (listenerList != null && node != null && childIndices != null - && childIndices.length > 0) { - int cCount = childIndices.length; - Object[] newChildren = new Object[cCount]; - - for (int counter = 0; counter < cCount; counter++) - newChildren[counter] = node.getChildAt(childIndices[counter]); - fireTreeNodesInserted(this, getPathToRoot(node), childIndices, - newChildren); - } - } - - /** - * Invoke this method after you've removed some TreeNodes from - * node. childIndices should be the index of the removed elements and - * must be sorted in ascending order. And removedChildren should be - * the array of the children objects that were removed. - */ - public void nodesWereRemoved(TreeNode node, int[] childIndices, - Object[] removedChildren) { - if (node != null && childIndices != null) { - fireTreeNodesRemoved(this, getPathToRoot(node), childIndices, - removedChildren); - } - } - - /** - * Invoke this method after you've changed how the children identified by - * childIndicies are to be represented in the tree. - */ - public void nodesChanged(TreeNode node, int[] childIndices) { - if (node != null) { - if (childIndices != null) { - int cCount = childIndices.length; - - if (cCount > 0) { - Object[] cChildren = new Object[cCount]; - - for (int counter = 0; counter < cCount; counter++) - cChildren[counter] = node.getChildAt - (childIndices[counter]); - fireTreeNodesChanged(this, getPathToRoot(node), - childIndices, cChildren); - } - } else if (node == getRoot()) { - fireTreeNodesChanged(this, getPathToRoot(node), null, null); - } - } - } - - /** - * Invoke this method if you've totally changed the children of - * node and its childrens children... This will post a - * treeStructureChanged event. - */ - public void nodeStructureChanged(TreeNode node) { - if (node != null) { - fireTreeStructureChanged(this, getPathToRoot(node), null, null); - } - } - - /** - * Builds the parents of node up to and including the root node, - * where the original node is the last element in the returned array. - * The length of the returned array gives the node's depth in the - * tree. - * - * @param aNode the TreeNode to get the path for - */ - public TreeNode[] getPathToRoot(TreeNode aNode) { - return getPathToRoot(aNode, 0); - } - - /** - * Builds the parents of node up to and including the root node, - * where the original node is the last element in the returned array. - * The length of the returned array gives the node's depth in the - * tree. - * - * @param aNode the TreeNode to get the path for - * @param depth an int giving the number of steps already taken towards - * the root (on recursive calls), used to size the returned array - * @return an array of TreeNodes giving the path from the root to the - * specified node - */ - protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) { - TreeNode[] retNodes; - // This method recurses, traversing towards the root in order - // size the array. On the way back, it fills in the nodes, - // starting from the root and working back to the original node. - - /* Check for null, in case someone passed in a null node, or - they passed in an element that isn't rooted at root. */ - if (aNode == null) { - if (depth == 0) - return null; - else - retNodes = new TreeNode[depth]; - } else { - depth++; - if (aNode == root) - retNodes = new TreeNode[depth]; - else - retNodes = getPathToRoot(aNode.getParent(), depth); - retNodes[retNodes.length - depth] = aNode; - } - return retNodes; - } - - // - // Events - // - - /** - * Adds a listener for the TreeModelEvent posted after the tree changes. - * - * @param l the listener to add - * @see #removeTreeModelListener - */ - public void addTreeModelListener(TreeModelListener l) { - listenerList.add(TreeModelListener.class, l); - } - - /** - * Removes a listener previously added with addTreeModelListener(). - * - * @param l the listener to remove - * @see #addTreeModelListener - */ - public void removeTreeModelListener(TreeModelListener l) { - listenerList.remove(TreeModelListener.class, l); - } - - /** - * Returns an array of all the tree model listeners - * registered on this model. - * - * @return all of this model's TreeModelListeners - * or an empty - * array if no tree model listeners are currently registered - * @see #addTreeModelListener - * @see #removeTreeModelListener - * @since 1.4 - */ - public TreeModelListener[] getTreeModelListeners() { - return listenerList.getListeners( - TreeModelListener.class); - } - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created using the parameters passed into - * the fire method. - * - * @param source the node being changed - * @param path the path to the root node - * @param childIndices the indices of the changed elements - * @param children the changed elements - * @see EventListenerList - */ - protected void fireTreeNodesChanged(Object source, Object[] path, - int[] childIndices, - Object[] children) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - TreeModelEvent e = null; - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == TreeModelListener.class) { - // Lazily create the event: - if (e == null) - e = new TreeModelEvent(source, path, - childIndices, children); - ((TreeModelListener) listeners[i + 1]).treeNodesChanged(e); - } - } - } - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created using the parameters passed into - * the fire method. - * - * @param source the node where new elements are being inserted - * @param path the path to the root node - * @param childIndices the indices of the new elements - * @param children the new elements - * @see EventListenerList - */ - protected void fireTreeNodesInserted(Object source, Object[] path, - int[] childIndices, - Object[] children) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - TreeModelEvent e = null; - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == TreeModelListener.class) { - // Lazily create the event: - if (e == null) - e = new TreeModelEvent(source, path, - childIndices, children); - ((TreeModelListener) listeners[i + 1]).treeNodesInserted(e); - } - } - } - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created using the parameters passed into - * the fire method. - * - * @param source the node where elements are being removed - * @param path the path to the root node - * @param childIndices the indices of the removed elements - * @param children the removed elements - * @see EventListenerList - */ - protected void fireTreeNodesRemoved(Object source, Object[] path, - int[] childIndices, - Object[] children) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - TreeModelEvent e = null; - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == TreeModelListener.class) { - // Lazily create the event: - if (e == null) - e = new TreeModelEvent(source, path, - childIndices, children); - ((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e); - } - } - } - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created using the parameters passed into - * the fire method. - * - * @param source the node where the tree model has changed - * @param path the path to the root node - * @param childIndices the indices of the affected elements - * @param children the affected elements - * @see EventListenerList - */ - protected void fireTreeStructureChanged(Object source, Object[] path, - int[] childIndices, - Object[] children) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - TreeModelEvent e = null; - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == TreeModelListener.class) { - // Lazily create the event: - if (e == null) - e = new TreeModelEvent(source, path, - childIndices, children); - ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e); - } - } - } - - /* - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created using the parameters passed into - * the fire method. - * - * @param source the node where the tree model has changed - * @param path the path to the root node - * @see EventListenerList - */ - private void fireTreeStructureChanged(Object source, TreePath path) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - TreeModelEvent e = null; - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == TreeModelListener.class) { - // Lazily create the event: - if (e == null) - e = new TreeModelEvent(source, path); - ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e); - } - } - } - - /** - * Returns an array of all the objects currently registered - * as FooListeners - * upon this model. - * FooListeners are registered using the - * addFooListener method. - *

    - *

    - *

    - * You can specify the listenerType argument - * with a class literal, - * such as - * FooListener.class. - * For example, you can query a - * DefaultTreeModel m - * for its tree model listeners with the following code: - *

    - *

    TreeModelListener[] tmls = (TreeModelListener[])(m.getListeners(TreeModelListener.class));
    - * - * If no such listeners exist, this method returns an empty array. - * - * @param listenerType the type of listeners requested; this parameter - * should specify an interface that descends from - * java.util.EventListener - * @return an array of all objects registered as - * FooListeners on this component, - * or an empty array if no such - * listeners have been added - * @throws ClassCastException if listenerType - * doesn't specify a class or interface that implements - * java.util.EventListener - * @see #getTreeModelListeners - * @since 1.3 - */ - public T[] getListeners(Class listenerType) { - return listenerList.getListeners(listenerType); - } - - // Serialization support. - private void writeObject(ObjectOutputStream s) throws IOException { - Vector values = new Vector(); - - s.defaultWriteObject(); - // Save the root, if its Serializable. - if (root != null && root instanceof Serializable) { - values.addElement("root"); - values.addElement(root); - } - s.writeObject(values); - } - - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); - - Vector values = (Vector) s.readObject(); - int indexCounter = 0; - int maxCounter = values.size(); - - if (indexCounter < maxCounter && values.elementAt(indexCounter). - equals("root")) { - root = (TreeNode) values.elementAt(++indexCounter); - indexCounter++; - } - } - - -} // End of class DefaultTreeModel - - diff --git a/src/main/java/org/jaudiotagger/utils/tree/EventListenerList.java b/src/main/java/org/jaudiotagger/utils/tree/EventListenerList.java deleted file mode 100644 index fb1adff..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/EventListenerList.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * @(#)EventListenerList.java 1.38 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ -package org.jaudiotagger.utils.tree; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.reflect.Array; -import java.util.EventListener; - -/** - * A class that holds a list of EventListeners. A single instance - * can be used to hold all listeners (of all types) for the instance - * using the list. It is the responsiblity of the class using the - * EventListenerList to provide type-safe API (preferably conforming - * to the JavaBeans spec) and methods which dispatch event notification - * methods to appropriate Event Listeners on the list. - *

    - * The main benefits that this class provides are that it is relatively - * cheap in the case of no listeners, and it provides serialization for - * event-listener lists in a single place, as well as a degree of MT safety - * (when used correctly). - *

    - * Usage example: - * Say one is defining a class that sends out FooEvents, and one wants - * to allow users of the class to register FooListeners and receive - * notification when FooEvents occur. The following should be added - * to the class definition: - *

    - * EventListenerList listenerList = new EventListenerList();
    - * FooEvent fooEvent = null;
    - *
    - * public void addFooListener(FooListener l) {
    - *     listenerList.add(FooListener.class, l);
    - * }
    - *
    - * public void removeFooListener(FooListener l) {
    - *     listenerList.remove(FooListener.class, l);
    - * }
    - *
    - *
    - * // Notify all listeners that have registered interest for
    - * // notification on this event type.  The event instance
    - * // is lazily created using the parameters passed into
    - * // the fire method.
    - *
    - * protected void fireFooXXX() {
    - *     // Guaranteed to return a non-null array
    - *     Object[] listeners = listenerList.getListenerList();
    - *     // Process the listeners last to first, notifying
    - *     // those that are interested in this event
    - *     for (int i = listeners.length-2; i>=0; i-=2) {
    - *         if (listeners[i]==FooListener.class) {
    - *             // Lazily create the event:
    - *             if (fooEvent == null)
    - *                 fooEvent = new FooEvent(this);
    - *             ((FooListener)listeners[i+1]).fooXXX(fooEvent);
    - *         }
    - *     }
    - * }
    - * 
    - * foo should be changed to the appropriate name, and fireFooXxx to the - * appropriate method name. One fire method should exist for each - * notification method in the FooListener interface. - *

    - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @author Georges Saab - * @author Hans Muller - * @author James Gosling - * @version 1.38 03/23/10 - */ -public class EventListenerList implements Serializable { - /* A null array to be shared by all empty listener lists*/ - private final static Object[] NULL_ARRAY = new Object[0]; - /* The list of ListenerType - Listener pairs */ - protected transient Object[] listenerList = NULL_ARRAY; - - /** - * Passes back the event listener list as an array - * of ListenerType-listener pairs. Note that for - * performance reasons, this implementation passes back - * the actual data structure in which the listener data - * is stored internally! - * This method is guaranteed to pass back a non-null - * array, so that no null-checking is required in - * fire methods. A zero-length array of Object should - * be returned if there are currently no listeners. - *

    - * WARNING!!! Absolutely NO modification of - * the data contained in this array should be made -- if - * any such manipulation is necessary, it should be done - * on a copy of the array returned rather than the array - * itself. - */ - public Object[] getListenerList() { - return listenerList; - } - - /** - * Return an array of all the listeners of the given type. - * - * @return all of the listeners of the specified type. - * @throws ClassCastException if the supplied class - * is not assignable to EventListener - * @since 1.3 - */ - public T[] getListeners(Class t) { - Object[] lList = listenerList; - int n = getListenerCount(lList, t); - T[] result = (T[]) Array.newInstance(t, n); - int j = 0; - for (int i = lList.length - 2; i >= 0; i -= 2) { - if (lList[i] == t) { - result[j++] = (T) lList[i + 1]; - } - } - return result; - } - - /** - * Returns the total number of listeners for this listener list. - */ - public int getListenerCount() { - return listenerList.length / 2; - } - - /** - * Returns the total number of listeners of the supplied type - * for this listener list. - */ - public int getListenerCount(Class t) { - Object[] lList = listenerList; - return getListenerCount(lList, t); - } - - private int getListenerCount(Object[] list, Class t) { - int count = 0; - for (int i = 0; i < list.length; i += 2) { - if (t == list[i]) - count++; - } - return count; - } - - /** - * Adds the listener as a listener of the specified type. - * - * @param t the type of the listener to be added - * @param l the listener to be added - */ - public synchronized void add(Class t, T l) { - if (l == null) { - // In an ideal world, we would do an assertion here - // to help developers know they are probably doing - // something wrong - return; - } - if (!t.isInstance(l)) { - throw new IllegalArgumentException("Listener " + l + - " is not of type " + t); - } - if (listenerList == NULL_ARRAY) { - // if this is the first listener added, - // initialize the lists - listenerList = new Object[]{t, l}; - } else { - // Otherwise copy the array and add the new listener - int i = listenerList.length; - Object[] tmp = new Object[i + 2]; - System.arraycopy(listenerList, 0, tmp, 0, i); - - tmp[i] = t; - tmp[i + 1] = l; - - listenerList = tmp; - } - } - - /** - * Removes the listener as a listener of the specified type. - * - * @param t the type of the listener to be removed - * @param l the listener to be removed - */ - public synchronized void remove(Class t, T l) { - if (l == null) { - // In an ideal world, we would do an assertion here - // to help developers know they are probably doing - // something wrong - return; - } - if (!t.isInstance(l)) { - throw new IllegalArgumentException("Listener " + l + - " is not of type " + t); - } - // Is l on the list? - int index = -1; - for (int i = listenerList.length - 2; i >= 0; i -= 2) { - if ((listenerList[i] == t) && (listenerList[i + 1].equals(l) == true)) { - index = i; - break; - } - } - - // If so, remove it - if (index != -1) { - Object[] tmp = new Object[listenerList.length - 2]; - // Copy the list up to index - System.arraycopy(listenerList, 0, tmp, 0, index); - // Copy from two past the index, up to - // the end of tmp (which is two elements - // shorter than the old list) - if (index < tmp.length) - System.arraycopy(listenerList, index + 2, tmp, index, - tmp.length - index); - // set the listener array to the new array or null - listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp; - } - } - - // Serialization support. - private void writeObject(ObjectOutputStream s) throws IOException { - Object[] lList = listenerList; - s.defaultWriteObject(); - - // Save the non-null event listeners: - for (int i = 0; i < lList.length; i += 2) { - Class t = (Class) lList[i]; - EventListener l = (EventListener) lList[i + 1]; - if ((l != null) && (l instanceof Serializable)) { - s.writeObject(t.getName()); - s.writeObject(l); - } - } - - s.writeObject(null); - } - - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - listenerList = NULL_ARRAY; - s.defaultReadObject(); - Object listenerTypeOrNull; - - while (null != (listenerTypeOrNull = s.readObject())) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - EventListener l = (EventListener) s.readObject(); - add((Class) Class.forName((String) listenerTypeOrNull, true, cl), l); - } - } - - /** - * Returns a string representation of the EventListenerList. - */ - public String toString() { - Object[] lList = listenerList; - String s = "EventListenerList: "; - s += lList.length / 2 + " listeners: "; - for (int i = 0; i <= lList.length - 2; i += 2) { - s += " type " + ((Class) lList[i]).getName(); - s += " listener " + lList[i + 1]; - } - return s; - } -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/MutableTreeNode.java b/src/main/java/org/jaudiotagger/utils/tree/MutableTreeNode.java deleted file mode 100644 index e91cd77..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/MutableTreeNode.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * @(#)MutableTreeNode.java 1.13 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; - -/** - * Defines the requirements for a tree node object that can change -- - * by adding or removing child nodes, or by changing the contents - * of a user object stored in the node. - * - * @author Rob Davis - * @author Scott Violet - * @version 1.13 03/23/10 - * @see DefaultMutableTreeNode - * @see javax.swing.JTree - */ - -public interface MutableTreeNode extends TreeNode { - /** - * Adds child to the receiver at index. - * child will be messaged with setParent. - */ - void insert(MutableTreeNode child, int index); - - /** - * Removes the child at index from the receiver. - */ - void remove(int index); - - /** - * Removes node from the receiver. setParent - * will be messaged on node. - */ - void remove(MutableTreeNode node); - - /** - * Resets the user object of the receiver to object. - */ - void setUserObject(Object object); - - /** - * Removes the receiver from its parent. - */ - void removeFromParent(); - - /** - * Sets the parent of the receiver to newParent. - */ - void setParent(MutableTreeNode newParent); -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/TreeModel.java b/src/main/java/org/jaudiotagger/utils/tree/TreeModel.java deleted file mode 100644 index b61c9eb..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/TreeModel.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * @(#)TreeModel.java 1.27 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ -package org.jaudiotagger.utils.tree; - - -/** - * The model used by JTree. - *

    - * JTree and its related classes make extensive use of - * TreePaths for indentifying nodes in the TreeModel. - * If a TreeModel returns the same object, as compared by - * equals, at two different indices under the same parent - * than the resulting TreePath objects will be considered equal - * as well. Some implementations may assume that if two - * TreePaths are equal, they identify the same node. If this - * condition is not met, painting problems and other oddities may result. - * In other words, if getChild for a given parent returns - * the same Object (as determined by equals) problems may - * result, and it is recommended you avoid doing this. - *

    - * Similarly JTree and its related classes place - * TreePaths in Maps. As such if - * a node is requested twice, the return values must be equal - * (using the equals method) and have the same - * hashCode. - *

    - * For further information on tree models, - * including an example of a custom implementation, - * see How to Use Trees - * in The Java Tutorial. - * - * @author Rob Davis - * @author Ray Ryan - * @version 1.27 03/23/10 - * @see TreePath - */ -public interface TreeModel { - - /** - * Returns the root of the tree. Returns null - * only if the tree has no nodes. - * - * @return the root of the tree - */ - Object getRoot(); - - - /** - * Returns the child of parent at index index - * in the parent's - * child array. parent must be a node previously obtained - * from this data source. This should not return null - * if index - * is a valid index for parent (that is index >= 0 && - * index < getChildCount(parent)). - * - * @param parent a node in the tree, obtained from this data source - * @return the child of parent at index index - */ - Object getChild(Object parent, int index); - - - /** - * Returns the number of children of parent. - * Returns 0 if the node - * is a leaf or if it has no children. parent must be a node - * previously obtained from this data source. - * - * @param parent a node in the tree, obtained from this data source - * @return the number of children of the node parent - */ - int getChildCount(Object parent); - - - /** - * Returns true if node is a leaf. - * It is possible for this method to return false - * even if node has no children. - * A directory in a filesystem, for example, - * may contain no files; the node representing - * the directory is not a leaf, but it also has no children. - * - * @param node a node in the tree, obtained from this data source - * @return true if node is a leaf - */ - boolean isLeaf(Object node); - - /** - * Messaged when the user has altered the value for the item identified - * by path to newValue. - * If newValue signifies a truly new value - * the model should post a treeNodesChanged event. - * - * @param path path to the node that the user has altered - * @param newValue the new value from the TreeCellEditor - */ - void valueForPathChanged(TreePath path, Object newValue); - - /** - * Returns the index of child in parent. If either parent - * or child is null, returns -1. - * If either parent or child don't - * belong to this tree model, returns -1. - * - * @param parent a node in the tree, obtained from this data source - * @param child the node we are interested in - * @return the index of the child in the parent, or -1 if either - * child or parent are null - * or don't belong to this tree model - */ - int getIndexOfChild(Object parent, Object child); - -// -// Change Events -// - - /** - * Adds a listener for the TreeModelEvent - * posted after the tree changes. - * - * @param l the listener to add - * @see #removeTreeModelListener - */ - void addTreeModelListener(TreeModelListener l); - - /** - * Removes a listener previously added with - * addTreeModelListener. - * - * @param l the listener to remove - * @see #addTreeModelListener - */ - void removeTreeModelListener(TreeModelListener l); - -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/TreeModelEvent.java b/src/main/java/org/jaudiotagger/utils/tree/TreeModelEvent.java deleted file mode 100644 index eebe32f..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/TreeModelEvent.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * @(#)TreeModelEvent.java 1.35 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; - -import java.util.EventObject; - - -/** - * Encapsulates information describing changes to a tree model, and - * used to notify tree model listeners of the change. - * For more information and examples see - * How to Write a Tree Model Listener, - * a section in The Java Tutorial. - *

    - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @author Rob Davis - * @author Ray Ryan - * @author Scott Violet - * @version 1.35 03/23/10 - */ -public class TreeModelEvent extends EventObject { - /** - * Path to the parent of the nodes that have changed. - */ - protected TreePath path; - /** - * Indices identifying the position of where the children were. - */ - protected int[] childIndices; - /** - * Children that have been removed. - */ - protected Object[] children; - - /** - * Used to create an event when nodes have been changed, inserted, or - * removed, identifying the path to the parent of the modified items as - * an array of Objects. All of the modified objects are siblings which are - * direct descendents (not grandchildren) of the specified parent. - * The positions at which the inserts, deletes, or changes occurred are - * specified by an array of int. The indexes in that array - * must be in order, from lowest to highest. - *

    - * For changes, the indexes in the model correspond exactly to the indexes - * of items currently displayed in the UI. As a result, it is not really - * critical if the indexes are not in their exact order. But after multiple - * inserts or deletes, the items currently in the UI no longer correspond - * to the items in the model. It is therefore critical to specify the - * indexes properly for inserts and deletes. - *

    - * For inserts, the indexes represent the final state of the tree, - * after the inserts have occurred. Since the indexes must be specified in - * order, the most natural processing methodology is to do the inserts - * starting at the lowest index and working towards the highest. Accumulate - * a Vector of Integer objects that specify the - * insert-locations as you go, then convert the Vector to an - * array of int to create the event. When the postition-index - * equals zero, the node is inserted at the beginning of the list. When the - * position index equals the size of the list, the node is "inserted" at - * (appended to) the end of the list. - *

    - * For deletes, the indexes represent the initial state of the tree, - * before the deletes have occurred. Since the indexes must be specified in - * order, the most natural processing methodology is to use a delete-counter. - * Start by initializing the counter to zero and start work through the - * list from lowest to higest. Every time you do a delete, add the current - * value of the delete-counter to the index-position where the delete occurred, - * and append the result to a Vector of delete-locations, using - * addElement(). Then increment the delete-counter. The index - * positions stored in the Vector therefore reflect the effects of all previous - * deletes, so they represent each object's position in the initial tree. - * (You could also start at the highest index and working back towards the - * lowest, accumulating a Vector of delete-locations as you go using the - * insertElementAt(Integer, 0).) However you produce the Vector - * of initial-positions, you then need to convert the Vector of Integer - * objects to an array of int to create the event. - *

    - * Notes:

      - *
    • Like the insertNodeInto method in the - * DefaultTreeModel class, insertElementAt - * appends to the Vector when the index matches the size - * of the vector. So you can use insertElementAt(Integer, 0) - * even when the vector is empty. - *
        To create a node changed event for the root node, specify the parent - * and the child indices as null. - *
      - * - * @param source the Object responsible for generating the event (typically - * the creator of the event object passes this - * for its value) - * @param path an array of Object identifying the path to the - * parent of the modified item(s), where the first element - * of the array is the Object stored at the root node and - * the last element is the Object stored at the parent node - * @param childIndices an array of int that specifies the - * index values of the removed items. The indices must be - * in sorted order, from lowest to highest - * @param children an array of Object containing the inserted, removed, or - * changed objects - * @see TreePath - */ - public TreeModelEvent(Object source, Object[] path, int[] childIndices, - Object[] children) { - this(source, new TreePath(path), childIndices, children); - } - - /** - * Used to create an event when nodes have been changed, inserted, or - * removed, identifying the path to the parent of the modified items as - * a TreePath object. For more information on how to specify the indexes - * and objects, see - * TreeModelEvent(Object,Object[],int[],Object[]). - * - * @param source the Object responsible for generating the event (typically - * the creator of the event object passes this - * for its value) - * @param path a TreePath object that identifies the path to the - * parent of the modified item(s) - * @param childIndices an array of int that specifies the - * index values of the modified items - * @param children an array of Object containing the inserted, removed, or - * changed objects - * @see #TreeModelEvent(Object, Object[], int[], Object[]) - */ - public TreeModelEvent(Object source, TreePath path, int[] childIndices, - Object[] children) { - super(source); - this.path = path; - this.childIndices = childIndices; - this.children = children; - } - - /** - * Used to create an event when the node structure has changed in some way, - * identifying the path to the root of a modified subtree as an array of - * Objects. A structure change event might involve nodes swapping position, - * for example, or it might encapsulate multiple inserts and deletes in the - * subtree stemming from the node, where the changes may have taken place at - * different levels of the subtree. - *
      - * Note:
      - * JTree collapses all nodes under the specified node, so that only its - * immediate children are visible. - *
      - * - * @param source the Object responsible for generating the event (typically - * the creator of the event object passes this - * for its value) - * @param path an array of Object identifying the path to the root of the - * modified subtree, where the first element of the array is - * the object stored at the root node and the last element - * is the object stored at the changed node - * @see TreePath - */ - public TreeModelEvent(Object source, Object[] path) { - this(source, new TreePath(path)); - } - - /** - * Used to create an event when the node structure has changed in some way, - * identifying the path to the root of the modified subtree as a TreePath - * object. For more information on this event specification, see - * TreeModelEvent(Object,Object[]). - * - * @param source the Object responsible for generating the event (typically - * the creator of the event object passes this - * for its value) - * @param path a TreePath object that identifies the path to the - * change. In the DefaultTreeModel, - * this object contains an array of user-data objects, - * but a subclass of TreePath could use some totally - * different mechanism -- for example, a node ID number - * @see #TreeModelEvent(Object, Object[]) - */ - public TreeModelEvent(Object source, TreePath path) { - super(source); - this.path = path; - this.childIndices = new int[0]; - } - - /** - * For all events, except treeStructureChanged, - * returns the parent of the changed nodes. - * For treeStructureChanged events, returns the ancestor of the - * structure that has changed. This and - * getChildIndices are used to get a list of the effected - * nodes. - *

      - * The one exception to this is a treeNodesChanged event that is to - * identify the root, in which case this will return the root - * and getChildIndices will return null. - * - * @return the TreePath used in identifying the changed nodes. - * @see TreePath#getLastPathComponent - */ - public TreePath getTreePath() { - return path; - } - - /** - * Convenience method to get the array of objects from the TreePath - * instance that this event wraps. - * - * @return an array of Objects, where the first Object is the one - * stored at the root and the last object is the one - * stored at the node identified by the path - */ - public Object[] getPath() { - if (path != null) - return path.getPath(); - return null; - } - - /** - * Returns the objects that are children of the node identified by - * getPath at the locations specified by - * getChildIndices. If this is a removal event the - * returned objects are no longer children of the parent node. - * - * @return an array of Object containing the children specified by - * the event - * @see #getPath - * @see #getChildIndices - */ - public Object[] getChildren() { - if (children != null) { - int cCount = children.length; - Object[] retChildren = new Object[cCount]; - - System.arraycopy(children, 0, retChildren, 0, cCount); - return retChildren; - } - return null; - } - - /** - * Returns the values of the child indexes. If this is a removal event - * the indexes point to locations in the initial list where items - * were removed. If it is an insert, the indices point to locations - * in the final list where the items were added. For node changes, - * the indices point to the locations of the modified nodes. - * - * @return an array of int containing index locations for - * the children specified by the event - */ - public int[] getChildIndices() { - if (childIndices != null) { - int cCount = childIndices.length; - int[] retArray = new int[cCount]; - - System.arraycopy(childIndices, 0, retArray, 0, cCount); - return retArray; - } - return null; - } - - /** - * Returns a string that displays and identifies this object's - * properties. - * - * @return a String representation of this object - */ - public String toString() { - StringBuffer retBuffer = new StringBuffer(); - - retBuffer.append(getClass().getName() + " " + - Integer.toString(hashCode())); - if (path != null) - retBuffer.append(" path " + path); - if (childIndices != null) { - retBuffer.append(" indices [ "); - for (int counter = 0; counter < childIndices.length; counter++) - retBuffer.append(Integer.toString(childIndices[counter]) + " "); - retBuffer.append("]"); - } - if (children != null) { - retBuffer.append(" children [ "); - for (int counter = 0; counter < children.length; counter++) - retBuffer.append(children[counter] + " "); - retBuffer.append("]"); - } - return retBuffer.toString(); - } -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/TreeModelListener.java b/src/main/java/org/jaudiotagger/utils/tree/TreeModelListener.java deleted file mode 100644 index 9c182c9..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/TreeModelListener.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * @(#)TreeModelListener.java 1.19 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; - -import java.util.EventListener; - -/** - * Defines the interface for an object that listens - * to changes in a TreeModel. - * For further information and examples see - * How to Write a Tree Model Listener, - * a section in The Java Tutorial. - * - * @author Rob Davis - * @author Ray Ryan - * @version 1.19 03/23/10 - */ -public interface TreeModelListener extends EventListener { - - /** - *

      Invoked after a node (or a set of siblings) has changed in some - * way. The node(s) have not changed locations in the tree or - * altered their children arrays, but other attributes have - * changed and may affect presentation. Example: the name of a - * file has changed, but it is in the same location in the file - * system.

      - *

      To indicate the root has changed, childIndices and children - * will be null.

      - *

      - *

      Use e.getPath() - * to get the parent of the changed node(s). - * e.getChildIndices() - * returns the index(es) of the changed node(s).

      - */ - void treeNodesChanged(TreeModelEvent e); - - /** - *

      Invoked after nodes have been inserted into the tree.

      - *

      - *

      Use e.getPath() - * to get the parent of the new node(s). - * e.getChildIndices() - * returns the index(es) of the new node(s) - * in ascending order.

      - */ - void treeNodesInserted(TreeModelEvent e); - - /** - *

      Invoked after nodes have been removed from the tree. Note that - * if a subtree is removed from the tree, this method may only be - * invoked once for the root of the removed subtree, not once for - * each individual set of siblings removed.

      - *

      - *

      Use e.getPath() - * to get the former parent of the deleted node(s). - * e.getChildIndices() - * returns, in ascending order, the index(es) - * the node(s) had before being deleted.

      - */ - void treeNodesRemoved(TreeModelEvent e); - - /** - *

      Invoked after the tree has drastically changed structure from a - * given node down. If the path returned by e.getPath() is of length - * one and the first element does not identify the current root node - * the first element should become the new root of the tree.

      - *

      - *

      Use e.getPath() - * to get the path to the node. - * e.getChildIndices() - * returns null.

      - */ - void treeStructureChanged(TreeModelEvent e); - -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/TreeNode.java b/src/main/java/org/jaudiotagger/utils/tree/TreeNode.java deleted file mode 100644 index 13ac6f6..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/TreeNode.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * @(#)TreeNode.java 1.26 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; - -import java.util.Enumeration; - -/** - * Defines the requirements for an object that can be used as a - * tree node in a JTree. - *

      - * Implementations of TreeNode that override equals - * will typically need to override hashCode as well. Refer - * to {@link javax.swing.tree.TreeModel} for more information. - *

      - * For further information and examples of using tree nodes, - * see How to Use Tree Nodes - * in The Java Tutorial. - * - * @author Rob Davis - * @author Scott Violet - * @version 1.26 03/23/10 - */ - -public interface TreeNode { - /** - * Returns the child TreeNode at index - * childIndex. - */ - TreeNode getChildAt(int childIndex); - - /** - * Returns the number of children TreeNodes the receiver - * contains. - */ - int getChildCount(); - - /** - * Returns the parent TreeNode of the receiver. - */ - TreeNode getParent(); - - /** - * Returns the index of node in the receivers children. - * If the receiver does not contain node, -1 will be - * returned. - */ - int getIndex(TreeNode node); - - /** - * Returns true if the receiver allows children. - */ - boolean getAllowsChildren(); - - /** - * Returns true if the receiver is a leaf. - */ - boolean isLeaf(); - - /** - * Returns the children of the receiver as an Enumeration. - */ - Enumeration children(); -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/TreePath.java b/src/main/java/org/jaudiotagger/utils/tree/TreePath.java deleted file mode 100644 index c9b9896..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/TreePath.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * @(#)TreePath.java 1.32 10/03/23 - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -package org.jaudiotagger.utils.tree; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.Vector; - -/** - * Represents a path to a node. A TreePath is an array of Objects that are - * vended from a TreeModel. The elements of the array are ordered such - * that the root is always the first element (index 0) of the array. - * TreePath is Serializable, but if any - * components of the path are not serializable, it will not be written - * out. - *

      - * For further information and examples of using tree paths, - * see How to Use Trees - * in The Java Tutorial. - *

      - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @author Scott Violet - * @author Philip Milne - * @version 1.32 03/23/10 - */ -public class TreePath extends Object implements Serializable { - /** - * Path representing the parent, null if lastPathComponent represents - * the root. - */ - private TreePath parentPath; - /** - * Last path component. - */ - transient private Object lastPathComponent; - - /** - * Constructs a path from an array of Objects, uniquely identifying - * the path from the root of the tree to a specific node, as returned - * by the tree's data model. - *

      - * The model is free to return an array of any Objects it needs to - * represent the path. The DefaultTreeModel returns an array of - * TreeNode objects. The first TreeNode in the path is the root of the - * tree, the last TreeNode is the node identified by the path. - * - * @param path an array of Objects representing the path to a node - */ - public TreePath(Object[] path) { - if (path == null || path.length == 0) - throw new IllegalArgumentException("path in TreePath must be non null and not empty."); - lastPathComponent = path[path.length - 1]; - if (path.length > 1) - parentPath = new TreePath(path, path.length - 1); - } - - /** - * Constructs a TreePath containing only a single element. This is - * usually used to construct a TreePath for the the root of the TreeModel. - *

      - * - * @param singlePath an Object representing the path to a node - * @see #TreePath(Object[]) - */ - public TreePath(Object singlePath) { - if (singlePath == null) - throw new IllegalArgumentException("path in TreePath must be non null."); - lastPathComponent = singlePath; - parentPath = null; - } - - /** - * Constructs a new TreePath, which is the path identified by - * parent ending in lastElement. - */ - protected TreePath(TreePath parent, Object lastElement) { - if (lastElement == null) - throw new IllegalArgumentException("path in TreePath must be non null."); - parentPath = parent; - lastPathComponent = lastElement; - } - - /** - * Constructs a new TreePath with the identified path components of - * length length. - */ - protected TreePath(Object[] path, int length) { - lastPathComponent = path[length - 1]; - if (length > 1) - parentPath = new TreePath(path, length - 1); - } - - /** - * Primarily provided for subclasses - * that represent paths in a different manner. - * If a subclass uses this constructor, it should also override - * the getPath, - * getPathCount, and - * getPathComponent methods, - * and possibly the equals method. - */ - protected TreePath() { - } - - /** - * Returns an ordered array of Objects containing the components of this - * TreePath. The first element (index 0) is the root. - * - * @return an array of Objects representing the TreePath - * @see #TreePath(Object[]) - */ - public Object[] getPath() { - int i = getPathCount(); - Object[] result = new Object[i--]; - - for (TreePath path = this; path != null; path = path.parentPath) { - result[i--] = path.lastPathComponent; - } - return result; - } - - /** - * Returns the last component of this path. For a path returned by - * DefaultTreeModel this will return an instance of TreeNode. - * - * @return the Object at the end of the path - * @see #TreePath(Object[]) - */ - public Object getLastPathComponent() { - return lastPathComponent; - } - - /** - * Returns the number of elements in the path. - * - * @return an int giving a count of items the path - */ - public int getPathCount() { - int result = 0; - for (TreePath path = this; path != null; path = path.parentPath) { - result++; - } - return result; - } - - /** - * Returns the path component at the specified index. - * - * @param element an int specifying an element in the path, where - * 0 is the first element in the path - * @return the Object at that index location - * @throws IllegalArgumentException if the index is beyond the length - * of the path - * @see #TreePath(Object[]) - */ - public Object getPathComponent(int element) { - int pathLength = getPathCount(); - - if (element < 0 || element >= pathLength) - throw new IllegalArgumentException("Index " + element + " is out of the specified range"); - - TreePath path = this; - - for (int i = pathLength - 1; i != element; i--) { - path = path.parentPath; - } - return path.lastPathComponent; - } - - /** - * Tests two TreePaths for equality by checking each element of the - * paths for equality. Two paths are considered equal if they are of - * the same length, and contain - * the same elements (.equals). - * - * @param o the Object to compare - */ - public boolean equals(Object o) { - if (o == this) - return true; - if (o instanceof TreePath) { - TreePath oTreePath = (TreePath) o; - - if (getPathCount() != oTreePath.getPathCount()) - return false; - for (TreePath path = this; path != null; path = path.parentPath) { - if (!(path.lastPathComponent.equals - (oTreePath.lastPathComponent))) { - return false; - } - oTreePath = oTreePath.parentPath; - } - return true; - } - return false; - } - - /** - * Returns the hashCode for the object. The hash code of a TreePath - * is defined to be the hash code of the last component in the path. - * - * @return the hashCode for the object - */ - public int hashCode() { - return lastPathComponent.hashCode(); - } - - /** - * Returns true if aTreePath is a - * descendant of this - * TreePath. A TreePath P1 is a descendant of a TreePath P2 - * if P1 contains all of the components that make up - * P2's path. - * For example, if this object has the path [a, b], - * and aTreePath has the path [a, b, c], - * then aTreePath is a descendant of this object. - * However, if aTreePath has the path [a], - * then it is not a descendant of this object. By this definition - * a TreePath is always considered a descendant of itself. That is, - * aTreePath.isDescendant(aTreePath) returns true. - * - * @return true if aTreePath is a descendant of this path - */ - public boolean isDescendant(TreePath aTreePath) { - if (aTreePath == this) - return true; - - if (aTreePath != null) { - int pathLength = getPathCount(); - int oPathLength = aTreePath.getPathCount(); - - if (oPathLength < pathLength) - // Can't be a descendant, has fewer components in the path. - return false; - while (oPathLength-- > pathLength) - aTreePath = aTreePath.getParentPath(); - return equals(aTreePath); - } - return false; - } - - /** - * Returns a new path containing all the elements of this object - * plus child. child will be the last element - * of the newly created TreePath. - * This will throw a NullPointerException - * if child is null. - */ - public TreePath pathByAddingChild(Object child) { - if (child == null) - throw new NullPointerException("Null child not allowed"); - - return new TreePath(this, child); - } - - /** - * Returns a path containing all the elements of this object, except - * the last path component. - */ - public TreePath getParentPath() { - return parentPath; - } - - /** - * Returns a string that displays and identifies this - * object's properties. - * - * @return a String representation of this object - */ - public String toString() { - StringBuffer tempSpot = new StringBuffer("["); - - for (int counter = 0, maxCounter = getPathCount(); counter < maxCounter; - counter++) { - if (counter > 0) - tempSpot.append(", "); - tempSpot.append(getPathComponent(counter)); - } - tempSpot.append("]"); - return tempSpot.toString(); - } - - // Serialization support. - private void writeObject(ObjectOutputStream s) throws IOException { - s.defaultWriteObject(); - - Vector values = new Vector(); - boolean writePath = true; - - if (lastPathComponent != null && - (lastPathComponent instanceof Serializable)) { - values.addElement("lastPathComponent"); - values.addElement(lastPathComponent); - } - s.writeObject(values); - } - - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); - - Vector values = (Vector) s.readObject(); - int indexCounter = 0; - int maxCounter = values.size(); - - if (indexCounter < maxCounter && values.elementAt(indexCounter). - equals("lastPathComponent")) { - lastPathComponent = values.elementAt(++indexCounter); - indexCounter++; - } - } -} diff --git a/src/main/java/org/jaudiotagger/utils/tree/package.html b/src/main/java/org/jaudiotagger/utils/tree/package.html deleted file mode 100644 index 4fb0ba5..0000000 --- a/src/main/java/org/jaudiotagger/utils/tree/package.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - -Customization of JTree behavior. - -
      - - - - - - -