From d9d285936bdcad9b14762318b52823f9e66d5b47 Mon Sep 17 00:00:00 2001 From: shabinder Date: Mon, 19 Apr 2021 16:20:26 +0530 Subject: [PATCH] use jaudiotagger as a LIB --- buildSrc/buildSrc/src/main/kotlin/Versions.kt | 1 + common/dependency-injection/build.gradle.kts | 4 +- jaudiotagger/.gitignore | 1 - jaudiotagger/build.gradle.kts | 8 - .../com/mp3/jaudiotagger/FileConstants.java | 61 - .../mp3/jaudiotagger/StandardCharsets.java | 68 - .../com/mp3/jaudiotagger/audio/AudioFile.java | 476 --- .../jaudiotagger/audio/AudioFileFilter.java | 87 - .../mp3/jaudiotagger/audio/AudioFileIO.java | 502 --- .../mp3/jaudiotagger/audio/AudioHeader.java | 113 - .../audio/SupportedFileFormat.java | 41 - .../audio/aiff/AiffAudioHeader.java | 233 -- .../audio/aiff/AiffFileHeader.java | 93 - .../audio/aiff/AiffFileReader.java | 27 - .../audio/aiff/AiffFileWriter.java | 50 - .../audio/aiff/AiffInfoReader.java | 161 - .../audio/aiff/AiffTagFieldKey.java | 21 - .../audio/aiff/AiffTagReader.java | 138 - .../audio/aiff/AiffTagWriter.java | 403 --- .../mp3/jaudiotagger/audio/aiff/AiffType.java | 23 - .../mp3/jaudiotagger/audio/aiff/AiffUtil.java | 59 - .../jaudiotagger/audio/aiff/ExtDouble.java | 83 - .../audio/aiff/chunk/AiffChunkReader.java | 33 - .../audio/aiff/chunk/AiffChunkSummary.java | 67 - .../audio/aiff/chunk/AiffChunkType.java | 61 - .../audio/aiff/chunk/AiffCompressionType.java | 91 - .../audio/aiff/chunk/AnnotationChunk.java | 35 - .../audio/aiff/chunk/ApplicationChunk.java | 62 - .../audio/aiff/chunk/AuthorChunk.java | 32 - .../audio/aiff/chunk/CommentsChunk.java | 97 - .../audio/aiff/chunk/CommonChunk.java | 107 - .../audio/aiff/chunk/CopyrightChunk.java | 39 - .../audio/aiff/chunk/FormatVersionChunk.java | 67 - .../audio/aiff/chunk/ID3Chunk.java | 97 - .../audio/aiff/chunk/NameChunk.java | 32 - .../audio/aiff/chunk/SoundChunk.java | 36 - .../audio/aiff/chunk/TextChunk.java | 44 - .../jaudiotagger/audio/asf/AsfFileReader.java | 278 -- .../jaudiotagger/audio/asf/AsfFileWriter.java | 144 - .../audio/asf/data/AsfExtendedHeader.java | 71 - .../audio/asf/data/AsfHeader.java | 223 -- .../audio/asf/data/AudioStreamChunk.java | 318 -- .../jaudiotagger/audio/asf/data/Chunk.java | 183 - .../audio/asf/data/ChunkContainer.java | 191 - .../audio/asf/data/ContainerType.java | 284 -- .../audio/asf/data/ContentBranding.java | 224 -- .../audio/asf/data/ContentDescription.java | 254 -- .../audio/asf/data/EncodingChunk.java | 91 - .../audio/asf/data/EncryptionChunk.java | 159 - .../audio/asf/data/FileHeader.java | 238 -- .../mp3/jaudiotagger/audio/asf/data/GUID.java | 520 --- .../audio/asf/data/GUIDFormatException.java | 26 - .../audio/asf/data/LanguageList.java | 125 - .../audio/asf/data/MetadataContainer.java | 477 --- .../asf/data/MetadataContainerFactory.java | 97 - .../audio/asf/data/MetadataDescriptor.java | 940 ----- .../data/StreamBitratePropertiesChunk.java | 112 - .../audio/asf/data/StreamChunk.java | 192 - .../audio/asf/data/VideoStreamChunk.java | 140 - .../audio/asf/io/AsfExtHeaderModifier.java | 140 - .../audio/asf/io/AsfExtHeaderReader.java | 72 - .../audio/asf/io/AsfHeaderReader.java | 236 -- .../audio/asf/io/AsfStreamer.java | 185 - .../audio/asf/io/ChunkContainerReader.java | 231 -- .../audio/asf/io/ChunkHeaderReader.java | 93 - .../audio/asf/io/ChunkModifier.java | 39 - .../audio/asf/io/ChunkReader.java | 50 - .../audio/asf/io/ChunkRemover.java | 72 - .../audio/asf/io/ContentBrandingReader.java | 74 - .../asf/io/ContentDescriptionReader.java | 134 - .../audio/asf/io/CountingInputStream.java | 118 - .../audio/asf/io/CountingOutputstream.java | 96 - .../audio/asf/io/EncodingChunkReader.java | 105 - .../audio/asf/io/EncryptionChunkReader.java | 132 - .../audio/asf/io/FileHeaderReader.java | 96 - .../audio/asf/io/FullRequestInputStream.java | 86 - .../audio/asf/io/LanguageListReader.java | 65 - .../audio/asf/io/MetadataReader.java | 154 - .../audio/asf/io/ModificationResult.java | 94 - .../asf/io/RandomAccessFileInputstream.java | 73 - .../asf/io/RandomAccessFileOutputStream.java | 49 - .../asf/io/StreamBitratePropertiesReader.java | 91 - .../audio/asf/io/StreamChunkReader.java | 191 - .../audio/asf/io/WriteableChunk.java | 49 - .../audio/asf/io/WriteableChunkModifer.java | 84 - .../asf/util/ChunkPositionComparator.java | 47 - .../audio/asf/util/TagConverter.java | 204 -- .../jaudiotagger/audio/asf/util/Utils.java | 536 --- .../mp3/jaudiotagger/audio/dsf/DsdChunk.java | 98 - .../com/mp3/jaudiotagger/audio/dsf/Dsf.java | 32 - .../jaudiotagger/audio/dsf/DsfChunkType.java | 54 - .../jaudiotagger/audio/dsf/DsfFileReader.java | 119 - .../jaudiotagger/audio/dsf/DsfFileWriter.java | 151 - .../mp3/jaudiotagger/audio/dsf/FmtChunk.java | 86 - .../mp3/jaudiotagger/audio/dsf/ID3Chunk.java | 37 - .../audio/exceptions/CannotReadException.java | 62 - .../exceptions/CannotReadVideoException.java | 42 - .../exceptions/CannotWriteException.java | 73 - .../InvalidAudioFrameException.java | 20 - .../exceptions/InvalidBoxHeaderException.java | 12 - .../audio/exceptions/ModifyVetoException.java | 77 - .../NoReadPermissionsException.java | 60 - .../NoWritePermissionsException.java | 42 - .../audio/exceptions/NullBoxIdException.java | 13 - .../exceptions/ReadOnlyFileException.java | 55 - .../UnableToCreateFileException.java | 15 - .../UnableToModifyFileException.java | 15 - .../UnableToRenameFileException.java | 15 - .../audio/flac/FlacAudioHeader.java | 18 - .../audio/flac/FlacFileReader.java | 44 - .../audio/flac/FlacFileWriter.java | 50 - .../audio/flac/FlacInfoReader.java | 132 - .../audio/flac/FlacStreamReader.java | 102 - .../audio/flac/FlacTagCreator.java | 122 - .../audio/flac/FlacTagReader.java | 129 - .../audio/flac/FlacTagWriter.java | 491 --- .../audio/flac/metadatablock/BlockType.java | 32 - .../flac/metadatablock/MetadataBlock.java | 53 - .../flac/metadatablock/MetadataBlockData.java | 37 - .../MetadataBlockDataApplication.java | 54 - .../MetadataBlockDataCueSheet.java | 53 - .../MetadataBlockDataPadding.java | 51 - .../MetadataBlockDataPicture.java | 369 -- .../MetadataBlockDataSeekTable.java | 57 - .../MetadataBlockDataStreamInfo.java | 230 -- .../metadatablock/MetadataBlockHeader.java | 160 - .../audio/generic/AbstractTag.java | 482 --- .../audio/generic/AbstractTagCreator.java | 53 - .../generic/AudioFileModificationAdapter.java | 78 - .../AudioFileModificationListener.java | 94 - .../audio/generic/AudioFileReader.java | 137 - .../audio/generic/AudioFileReader2.java | 83 - .../audio/generic/AudioFileWriter.java | 637 ---- .../audio/generic/AudioFileWriter2.java | 102 - .../audio/generic/GenericAudioHeader.java | 410 --- .../audio/generic/GenericTag.java | 256 -- .../audio/generic/ModificationHandler.java | 142 - .../jaudiotagger/audio/generic/TagWriter.java | 28 - .../mp3/jaudiotagger/audio/generic/Utils.java | 507 --- .../com/mp3/jaudiotagger/audio/iff/Chunk.java | 39 - .../jaudiotagger/audio/iff/ChunkHeader.java | 132 - .../jaudiotagger/audio/iff/ChunkSummary.java | 68 - .../audio/iff/IffHeaderChunk.java | 54 - .../audio/mp3/ByteArrayMP3AudioHeader.java | 108 - .../mp3/jaudiotagger/audio/mp3/LameFrame.java | 92 - .../audio/mp3/MP3AudioHeader.java | 871 ----- .../mp3/jaudiotagger/audio/mp3/MP3File.java | 1152 ------ .../jaudiotagger/audio/mp3/MP3FileReader.java | 59 - .../jaudiotagger/audio/mp3/MP3FileWriter.java | 57 - .../audio/mp3/MPEGFrameHeader.java | 888 ----- .../mp3/jaudiotagger/audio/mp3/VbriFrame.java | 189 - .../mp3/jaudiotagger/audio/mp3/XingFrame.java | 267 -- .../jaudiotagger/audio/mp4/EncoderType.java | 24 - .../audio/mp4/Mp4AtomIdentifier.java | 195 -- .../jaudiotagger/audio/mp4/Mp4AtomTree.java | 514 --- .../audio/mp4/Mp4AudioHeader.java | 65 - .../jaudiotagger/audio/mp4/Mp4FileReader.java | 48 - .../jaudiotagger/audio/mp4/Mp4FileWriter.java | 49 - .../jaudiotagger/audio/mp4/Mp4InfoReader.java | 357 -- .../jaudiotagger/audio/mp4/Mp4TagReader.java | 319 -- .../jaudiotagger/audio/mp4/Mp4TagWriter.java | 1263 ------- .../audio/mp4/atom/AbstractMp4Box.java | 30 - .../audio/mp4/atom/Mp4AlacBox.java | 133 - .../audio/mp4/atom/Mp4BoxHeader.java | 385 -- .../audio/mp4/atom/Mp4DrmsBox.java | 50 - .../audio/mp4/atom/Mp4EsdsBox.java | 342 -- .../audio/mp4/atom/Mp4FreeBox.java | 49 - .../audio/mp4/atom/Mp4FtypBox.java | 155 - .../audio/mp4/atom/Mp4HdlrBox.java | 177 - .../audio/mp4/atom/Mp4MdhdBox.java | 72 - .../audio/mp4/atom/Mp4MetaBox.java | 55 - .../audio/mp4/atom/Mp4Mp4aBox.java | 78 - .../audio/mp4/atom/Mp4MvhdBox.java | 88 - .../audio/mp4/atom/Mp4StcoBox.java | 237 -- .../audio/mp4/atom/Mp4StsdBox.java | 41 - .../audio/mp4/atom/NullPadding.java | 18 - .../jaudiotagger/audio/ogg/OggFileReader.java | 141 - .../jaudiotagger/audio/ogg/OggFileWriter.java | 52 - .../audio/ogg/OggVorbisCommentTagCreator.java | 66 - .../audio/ogg/OggVorbisTagReader.java | 659 ---- .../audio/ogg/OggVorbisTagWriter.java | 716 ---- .../jaudiotagger/audio/ogg/VorbisVersion.java | 25 - .../audio/ogg/util/OggCRCFactory.java | 104 - .../audio/ogg/util/OggInfoReader.java | 161 - .../audio/ogg/util/OggPageHeader.java | 410 --- .../audio/ogg/util/VorbisHeader.java | 22 - .../ogg/util/VorbisIdentificationHeader.java | 163 - .../audio/ogg/util/VorbisPacketType.java | 26 - .../audio/ogg/util/VorbisSetupHeader.java | 44 - .../jaudiotagger/audio/real/RealChunk.java | 80 - .../audio/real/RealFileReader.java | 90 - .../mp3/jaudiotagger/audio/real/RealTag.java | 21 - .../jaudiotagger/audio/wav/WavChunkType.java | 61 - .../jaudiotagger/audio/wav/WavFileReader.java | 60 - .../jaudiotagger/audio/wav/WavFileWriter.java | 40 - .../jaudiotagger/audio/wav/WavInfoReader.java | 177 - .../jaudiotagger/audio/wav/WavOptions.java | 38 - .../jaudiotagger/audio/wav/WavRIFFHeader.java | 58 - .../audio/wav/WavSaveOptions.java | 31 - .../jaudiotagger/audio/wav/WavSaveOrder.java | 14 - .../jaudiotagger/audio/wav/WavSubFormat.java | 53 - .../jaudiotagger/audio/wav/WavTagReader.java | 201 -- .../jaudiotagger/audio/wav/WavTagWriter.java | 924 ----- .../audio/wav/chunk/WavChunkSummary.java | 116 - .../audio/wav/chunk/WavFactChunk.java | 59 - .../audio/wav/chunk/WavFormatChunk.java | 113 - .../audio/wav/chunk/WavId3Chunk.java | 99 - .../audio/wav/chunk/WavInfoChunk.java | 93 - .../audio/wav/chunk/WavInfoIdentifier.java | 100 - .../audio/wav/chunk/WavListChunk.java | 77 - .../logging/AbstractTagDisplayFormatter.java | 111 - .../jaudiotagger/logging/ErrorMessage.java | 144 - .../logging/FileSystemMessage.java | 23 - .../com/mp3/jaudiotagger/logging/Hex.java | 51 - .../logging/PlainTextTagDisplayFormatter.java | 99 - .../logging/XMLTagDisplayFormatter.java | 199 -- .../jaudiotagger/tag/EmptyFrameException.java | 68 - .../tag/FieldDataInvalidException.java | 48 - .../com/mp3/jaudiotagger/tag/FieldKey.java | 166 - .../tag/InvalidDataTypeException.java | 61 - .../tag/InvalidFrameException.java | 69 - .../tag/InvalidFrameIdentifierException.java | 70 - .../jaudiotagger/tag/InvalidTagException.java | 73 - .../tag/KeyNotFoundException.java | 47 - .../jaudiotagger/tag/PaddingException.java | 65 - .../java/com/mp3/jaudiotagger/tag/Tag.java | 338 -- .../mp3/jaudiotagger/tag/TagException.java | 70 - .../com/mp3/jaudiotagger/tag/TagField.java | 114 - .../tag/TagNotFoundException.java | 74 - .../jaudiotagger/tag/TagOptionSingleton.java | 1359 -------- .../mp3/jaudiotagger/tag/TagTextField.java | 60 - .../mp3/jaudiotagger/tag/aiff/AiffTag.java | 412 --- .../tag/aiff/AiffTagFieldKey.java | 20 - .../tag/asf/AbstractAsfTagImageField.java | 60 - .../mp3/jaudiotagger/tag/asf/AsfFieldKey.java | 391 --- .../com/mp3/jaudiotagger/tag/asf/AsfTag.java | 792 ----- .../tag/asf/AsfTagBannerField.java | 64 - .../tag/asf/AsfTagCoverField.java | 226 -- .../mp3/jaudiotagger/tag/asf/AsfTagField.java | 157 - .../jaudiotagger/tag/asf/AsfTagTextField.java | 88 - .../tag/datatype/AbstractDataType.java | 413 --- .../tag/datatype/AbstractDataTypeList.java | 149 - .../datatype/AbstractIntStringValuePair.java | 66 - .../tag/datatype/AbstractString.java | 191 - .../AbstractStringStringValuePair.java | 69 - .../tag/datatype/AbstractValuePair.java | 65 - .../tag/datatype/BooleanByte.java | 147 - .../tag/datatype/BooleanString.java | 103 - .../tag/datatype/ByteArraySizeTerminated.java | 119 - .../jaudiotagger/tag/datatype/DataTypes.java | 170 - .../tag/datatype/EventTimingCode.java | 151 - .../tag/datatype/EventTimingCodeList.java | 48 - .../tag/datatype/HashMapInterface.java | 49 - .../tag/datatype/ID3v2LyricLine.java | 170 - .../tag/datatype/Lyrics3Image.java | 272 -- .../tag/datatype/Lyrics3Line.java | 228 -- .../tag/datatype/Lyrics3TimeStamp.java | 238 -- ...ltipleTextEncodedStringNullTerminated.java | 221 -- .../tag/datatype/NumberFixedLength.java | 187 - .../tag/datatype/NumberHashMap.java | 271 -- .../tag/datatype/NumberVariableLength.java | 246 -- .../mp3/jaudiotagger/tag/datatype/Pair.java | 43 - ...PairedTextEncodedStringNullTerminated.java | 300 -- .../jaudiotagger/tag/datatype/PartOfSet.java | 524 --- .../jaudiotagger/tag/datatype/StringDate.java | 81 - .../tag/datatype/StringDateTime.java | 81 - .../tag/datatype/StringFixedLength.java | 229 -- .../tag/datatype/StringHashMap.java | 226 -- .../tag/datatype/StringNullTerminated.java | 64 - .../tag/datatype/StringSizeTerminated.java | 71 - .../tag/datatype/SynchronisedTempoCode.java | 151 - .../datatype/SynchronisedTempoCodeList.java | 48 - .../jaudiotagger/tag/datatype/TCONString.java | 166 - .../jaudiotagger/tag/datatype/TempoCode.java | 121 - .../TextEncodedStringNullTerminated.java | 264 -- .../TextEncodedStringSizeTerminated.java | 361 -- .../mp3/jaudiotagger/tag/flac/FlacTag.java | 631 ---- .../jaudiotagger/tag/id3/AbstractID3Tag.java | 108 - .../tag/id3/AbstractID3v1Tag.java | 157 - .../tag/id3/AbstractID3v2Frame.java | 655 ---- .../tag/id3/AbstractID3v2Tag.java | 3094 ----------------- .../mp3/jaudiotagger/tag/id3/AbstractTag.java | 94 - .../tag/id3/AbstractTagFrame.java | 138 - .../tag/id3/AbstractTagFrameBody.java | 342 -- .../jaudiotagger/tag/id3/AbstractTagItem.java | 104 - .../jaudiotagger/tag/id3/AggregatedFrame.java | 117 - .../jaudiotagger/tag/id3/ID3Compression.java | 66 - .../mp3/jaudiotagger/tag/id3/ID3Frames.java | 290 -- .../tag/id3/ID3SyncSafeInteger.java | 128 - .../com/mp3/jaudiotagger/tag/id3/ID3Tags.java | 471 --- .../tag/id3/ID3TextEncodingConversion.java | 121 - .../tag/id3/ID3Unsynchronization.java | 239 -- .../mp3/jaudiotagger/tag/id3/ID3v11Tag.java | 631 ---- .../jaudiotagger/tag/id3/ID3v1FieldKey.java | 15 - .../jaudiotagger/tag/id3/ID3v1Iterator.java | 209 -- .../mp3/jaudiotagger/tag/id3/ID3v1Tag.java | 1101 ------ .../jaudiotagger/tag/id3/ID3v1TagField.java | 209 -- .../jaudiotagger/tag/id3/ID3v22FieldKey.java | 242 -- .../mp3/jaudiotagger/tag/id3/ID3v22Frame.java | 525 --- .../jaudiotagger/tag/id3/ID3v22Frames.java | 505 --- .../ID3v22PreferredFrameOrderComparator.java | 147 - .../mp3/jaudiotagger/tag/id3/ID3v22Tag.java | 908 ----- .../jaudiotagger/tag/id3/ID3v23FieldKey.java | 243 -- .../mp3/jaudiotagger/tag/id3/ID3v23Frame.java | 880 ----- .../jaudiotagger/tag/id3/ID3v23Frames.java | 556 --- .../ID3v23PreferredFrameOrderComparator.java | 161 - .../mp3/jaudiotagger/tag/id3/ID3v23Tag.java | 1372 -------- .../jaudiotagger/tag/id3/ID3v24FieldKey.java | 243 -- .../mp3/jaudiotagger/tag/id3/ID3v24Frame.java | 1162 ------- .../jaudiotagger/tag/id3/ID3v24Frames.java | 554 --- .../ID3v24PreferredFrameOrderComparator.java | 165 - .../mp3/jaudiotagger/tag/id3/ID3v24Tag.java | 1492 -------- .../tag/id3/ID3v2ChapterFrames.java | 55 - .../jaudiotagger/tag/id3/Id3FieldType.java | 11 - .../tag/id3/Id3SupportingTag.java | 11 - .../tag/id3/TyerTdatAggregatedFrame.java | 40 - .../AbstractFrameBodyNumberTotal.java | 167 - .../id3/framebody/AbstractFrameBodyPairs.java | 229 -- .../framebody/AbstractFrameBodyTextInfo.java | 240 -- .../framebody/AbstractFrameBodyUrlLink.java | 174 - .../id3/framebody/AbstractID3v2FrameBody.java | 236 -- .../tag/id3/framebody/FrameBodyAENC.java | 149 - .../tag/id3/framebody/FrameBodyAPIC.java | 313 -- .../tag/id3/framebody/FrameBodyASPI.java | 139 - .../tag/id3/framebody/FrameBodyCHAP.java | 151 - .../tag/id3/framebody/FrameBodyCOMM.java | 333 -- .../tag/id3/framebody/FrameBodyCOMR.java | 207 -- .../tag/id3/framebody/FrameBodyCRM.java | 142 - .../tag/id3/framebody/FrameBodyCTOC.java | 145 - .../id3/framebody/FrameBodyDeprecated.java | 112 - .../tag/id3/framebody/FrameBodyENCR.java | 139 - .../tag/id3/framebody/FrameBodyEQU2.java | 118 - .../tag/id3/framebody/FrameBodyEQUA.java | 95 - .../tag/id3/framebody/FrameBodyETCO.java | 347 -- .../tag/id3/framebody/FrameBodyEncrypted.java | 81 - .../tag/id3/framebody/FrameBodyGEOB.java | 158 - .../tag/id3/framebody/FrameBodyGRID.java | 164 - .../tag/id3/framebody/FrameBodyGRP1.java | 79 - .../tag/id3/framebody/FrameBodyIPLS.java | 120 - .../tag/id3/framebody/FrameBodyLINK.java | 168 - .../tag/id3/framebody/FrameBodyMCDI.java | 107 - .../tag/id3/framebody/FrameBodyMLLT.java | 102 - .../tag/id3/framebody/FrameBodyMVIN.java | 83 - .../tag/id3/framebody/FrameBodyMVNM.java | 83 - .../tag/id3/framebody/FrameBodyOWNE.java | 141 - .../tag/id3/framebody/FrameBodyPCNT.java | 123 - .../tag/id3/framebody/FrameBodyPIC.java | 278 -- .../tag/id3/framebody/FrameBodyPOPM.java | 193 - .../tag/id3/framebody/FrameBodyPOSS.java | 118 - .../tag/id3/framebody/FrameBodyPRIV.java | 144 - .../tag/id3/framebody/FrameBodyRBUF.java | 104 - .../tag/id3/framebody/FrameBodyRVA2.java | 91 - .../tag/id3/framebody/FrameBodyRVAD.java | 91 - .../tag/id3/framebody/FrameBodyRVRB.java | 160 - .../tag/id3/framebody/FrameBodySEEK.java | 88 - .../tag/id3/framebody/FrameBodySIGN.java | 133 - .../tag/id3/framebody/FrameBodySYLT.java | 247 -- .../tag/id3/framebody/FrameBodySYTC.java | 269 -- .../tag/id3/framebody/FrameBodyTALB.java | 83 - .../tag/id3/framebody/FrameBodyTBPM.java | 83 - .../tag/id3/framebody/FrameBodyTCMP.java | 76 - .../tag/id3/framebody/FrameBodyTCOM.java | 86 - .../tag/id3/framebody/FrameBodyTCON.java | 352 -- .../tag/id3/framebody/FrameBodyTCOP.java | 83 - .../tag/id3/framebody/FrameBodyTDAT.java | 102 - .../tag/id3/framebody/FrameBodyTDEN.java | 79 - .../tag/id3/framebody/FrameBodyTDLY.java | 82 - .../tag/id3/framebody/FrameBodyTDOR.java | 96 - .../tag/id3/framebody/FrameBodyTDRC.java | 452 --- .../tag/id3/framebody/FrameBodyTDRL.java | 78 - .../tag/id3/framebody/FrameBodyTDTG.java | 85 - .../tag/id3/framebody/FrameBodyTENC.java | 84 - .../tag/id3/framebody/FrameBodyTEXT.java | 84 - .../tag/id3/framebody/FrameBodyTFLT.java | 99 - .../tag/id3/framebody/FrameBodyTIME.java | 94 - .../tag/id3/framebody/FrameBodyTIPL.java | 123 - .../tag/id3/framebody/FrameBodyTIT1.java | 84 - .../tag/id3/framebody/FrameBodyTIT2.java | 82 - .../tag/id3/framebody/FrameBodyTIT3.java | 82 - .../tag/id3/framebody/FrameBodyTKEY.java | 95 - .../tag/id3/framebody/FrameBodyTLAN.java | 97 - .../tag/id3/framebody/FrameBodyTLEN.java | 82 - .../tag/id3/framebody/FrameBodyTMCL.java | 111 - .../tag/id3/framebody/FrameBodyTMED.java | 159 - .../tag/id3/framebody/FrameBodyTMOO.java | 89 - .../tag/id3/framebody/FrameBodyTOAL.java | 83 - .../tag/id3/framebody/FrameBodyTOFN.java | 83 - .../tag/id3/framebody/FrameBodyTOLY.java | 82 - .../tag/id3/framebody/FrameBodyTOPE.java | 84 - .../tag/id3/framebody/FrameBodyTORY.java | 103 - .../tag/id3/framebody/FrameBodyTOWN.java | 82 - .../tag/id3/framebody/FrameBodyTPE1.java | 82 - .../tag/id3/framebody/FrameBodyTPE2.java | 82 - .../tag/id3/framebody/FrameBodyTPE3.java | 83 - .../tag/id3/framebody/FrameBodyTPE4.java | 83 - .../tag/id3/framebody/FrameBodyTPOS.java | 135 - .../tag/id3/framebody/FrameBodyTPRO.java | 79 - .../tag/id3/framebody/FrameBodyTPUB.java | 83 - .../tag/id3/framebody/FrameBodyTRCK.java | 144 - .../tag/id3/framebody/FrameBodyTRDA.java | 83 - .../tag/id3/framebody/FrameBodyTRSN.java | 83 - .../tag/id3/framebody/FrameBodyTRSO.java | 83 - .../tag/id3/framebody/FrameBodyTSIZ.java | 82 - .../tag/id3/framebody/FrameBodyTSO2.java | 57 - .../tag/id3/framebody/FrameBodyTSOA.java | 79 - .../tag/id3/framebody/FrameBodyTSOC.java | 57 - .../tag/id3/framebody/FrameBodyTSOP.java | 78 - .../tag/id3/framebody/FrameBodyTSOT.java | 81 - .../tag/id3/framebody/FrameBodyTSRC.java | 78 - .../tag/id3/framebody/FrameBodyTSSE.java | 82 - .../tag/id3/framebody/FrameBodyTSST.java | 79 - .../tag/id3/framebody/FrameBodyTXXX.java | 254 -- .../tag/id3/framebody/FrameBodyTYER.java | 95 - .../tag/id3/framebody/FrameBodyUFID.java | 136 - .../tag/id3/framebody/FrameBodyUSER.java | 145 - .../tag/id3/framebody/FrameBodyUSLT.java | 244 -- .../id3/framebody/FrameBodyUnsupported.java | 160 - .../tag/id3/framebody/FrameBodyWCOM.java | 82 - .../tag/id3/framebody/FrameBodyWCOP.java | 82 - .../tag/id3/framebody/FrameBodyWOAF.java | 81 - .../tag/id3/framebody/FrameBodyWOAR.java | 83 - .../tag/id3/framebody/FrameBodyWOAS.java | 82 - .../tag/id3/framebody/FrameBodyWORS.java | 81 - .../tag/id3/framebody/FrameBodyWPAY.java | 81 - .../tag/id3/framebody/FrameBodyWPUB.java | 82 - .../tag/id3/framebody/FrameBodyWXXX.java | 195 -- .../tag/id3/framebody/FrameBodyXSOA.java | 59 - .../tag/id3/framebody/FrameBodyXSOP.java | 59 - .../tag/id3/framebody/FrameBodyXSOT.java | 59 - .../tag/id3/framebody/ID3v22FrameBody.java | 27 - .../tag/id3/framebody/ID3v23FrameBody.java | 27 - .../tag/id3/framebody/ID3v24FrameBody.java | 27 - .../id3/framebody/ID3v2ChapterFrameBody.java | 27 - .../tag/id3/reference/ID3Rating.java | 32 - .../tag/id3/reference/ITunesRating.java | 99 - .../reference/MediaMonkeyPlayerRating.java | 148 - .../tag/id3/reference/MediaPlayerRating.java | 95 - .../tag/id3/valuepair/ChannelTypes.java | 54 - .../valuepair/EventTimingTimestampTypes.java | 49 - .../tag/id3/valuepair/EventTimingTypes.java | 91 - .../id3/valuepair/ID3NumberTotalFields.java | 36 - .../valuepair/ID3V2ExtendedGenreTypes.java | 25 - .../tag/id3/valuepair/ImageFormats.java | 263 -- .../tag/id3/valuepair/InterpolationTypes.java | 45 - .../tag/id3/valuepair/MusicianCredits.java | 823 ----- .../tag/id3/valuepair/ReceivedAsTypes.java | 60 - .../tag/id3/valuepair/StandardIPLSKey.java | 51 - .../SynchronisedLyricsContentType.java | 36 - .../tag/id3/valuepair/TextEncoding.java | 108 - .../tag/id3/valuepair/V2GenreTypes.java | 44 - .../tag/images/AndroidArtwork.java | 218 -- .../mp3/jaudiotagger/tag/images/Artwork.java | 70 - .../tag/images/ArtworkFactory.java | 49 - .../tag/lyrics3/AbstractLyrics3.java | 54 - .../AbstractLyrics3v2FieldFrameBody.java | 164 - .../tag/lyrics3/FieldFrameBodyAUT.java | 97 - .../tag/lyrics3/FieldFrameBodyEAL.java | 99 - .../tag/lyrics3/FieldFrameBodyEAR.java | 100 - .../tag/lyrics3/FieldFrameBodyETT.java | 98 - .../tag/lyrics3/FieldFrameBodyIMG.java | 336 -- .../tag/lyrics3/FieldFrameBodyIND.java | 103 - .../tag/lyrics3/FieldFrameBodyINF.java | 97 - .../tag/lyrics3/FieldFrameBodyLYR.java | 412 --- .../lyrics3/FieldFrameBodyUnsupported.java | 183 - .../jaudiotagger/tag/lyrics3/Lyrics3v1.java | 327 -- .../tag/lyrics3/Lyrics3v1Iterator.java | 104 - .../jaudiotagger/tag/lyrics3/Lyrics3v2.java | 529 --- .../tag/lyrics3/Lyrics3v2Field.java | 269 -- .../tag/lyrics3/Lyrics3v2Fields.java | 82 - .../mp3/jaudiotagger/tag/mp4/Mp4FieldKey.java | 387 --- .../tag/mp4/Mp4NonStandardFieldKey.java | 55 - .../com/mp3/jaudiotagger/tag/mp4/Mp4Tag.java | 938 ----- .../jaudiotagger/tag/mp4/Mp4TagCreator.java | 151 - .../mp3/jaudiotagger/tag/mp4/Mp4TagField.java | 193 - .../tag/mp4/Mp4TagFieldSubType.java | 18 - .../tag/mp4/atom/Mp4ContentTypeValue.java | 63 - .../jaudiotagger/tag/mp4/atom/Mp4DataBox.java | 157 - .../jaudiotagger/tag/mp4/atom/Mp4MeanBox.java | 49 - .../jaudiotagger/tag/mp4/atom/Mp4NameBox.java | 48 - .../tag/mp4/atom/Mp4RatingValue.java | 50 - .../tag/mp4/field/Mp4DiscNoField.java | 177 - .../tag/mp4/field/Mp4FieldType.java | 82 - .../tag/mp4/field/Mp4GenreField.java | 128 - .../tag/mp4/field/Mp4TagBinaryField.java | 146 - .../tag/mp4/field/Mp4TagByteField.java | 149 - .../tag/mp4/field/Mp4TagCoverField.java | 202 -- .../tag/mp4/field/Mp4TagRawBinaryField.java | 126 - .../tag/mp4/field/Mp4TagReverseDnsField.java | 301 -- .../tag/mp4/field/Mp4TagTextField.java | 154 - .../tag/mp4/field/Mp4TagTextNumberField.java | 117 - .../tag/mp4/field/Mp4TrackField.java | 194 -- .../tag/options/PadNumberOption.java | 18 - .../tag/reference/GenreTypes.java | 288 -- .../tag/reference/ID3V2Version.java | 12 - .../tag/reference/ISOCountry.java | 342 -- .../jaudiotagger/tag/reference/ISOScript.java | 220 -- .../jaudiotagger/tag/reference/Languages.java | 523 --- .../tag/reference/MusicalKey.java | 95 - .../tag/reference/PerformerHelper.java | 18 - .../tag/reference/PictureTypes.java | 77 - .../jaudiotagger/tag/reference/Tagger.java | 43 - .../VorbisAlbumArtistReadOptions.java | 17 - .../VorbisAlbumArtistSaveOptions.java | 18 - .../vorbiscomment/VorbisCommentCreator.java | 90 - .../vorbiscomment/VorbisCommentFieldKey.java | 220 -- .../vorbiscomment/VorbisCommentReader.java | 146 - .../tag/vorbiscomment/VorbisCommentTag.java | 934 ----- .../vorbiscomment/VorbisCommentTagField.java | 243 -- .../tag/vorbiscomment/util/Base64Coder.java | 161 - .../mp3/jaudiotagger/tag/wav/WavInfoTag.java | 135 - .../com/mp3/jaudiotagger/tag/wav/WavTag.java | 656 ---- .../utils/DirectByteBufferUtils.java | 247 -- .../mp3/jaudiotagger/utils/EqualsUtil.java | 77 - .../mp3/jaudiotagger/utils/FileTypeUtil.java | 111 - .../jaudiotagger/utils/PrimitiveUtils.java | 9 - .../utils/tree/DefaultMutableTreeNode.java | 1493 -------- .../utils/tree/DefaultTreeModel.java | 666 ---- .../utils/tree/EventListenerList.java | 276 -- .../utils/tree/MutableTreeNode.java | 56 - .../jaudiotagger/utils/tree/TreeModel.java | 143 - .../utils/tree/TreeModelEvent.java | 297 -- .../utils/tree/TreeModelListener.java | 81 - .../mp3/jaudiotagger/utils/tree/TreeNode.java | 70 - .../mp3/jaudiotagger/utils/tree/TreePath.java | 323 -- settings.gradle.kts | 3 +- 525 files changed, 4 insertions(+), 94215 deletions(-) delete mode 100644 jaudiotagger/.gitignore delete mode 100644 jaudiotagger/build.gradle.kts delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/FileConstants.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/StandardCharsets.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFile.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileFilter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileIO.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/SupportedFileFormat.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffAudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffInfoReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagFieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffUtil.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/ExtDouble.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkSummary.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffCompressionType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AnnotationChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ApplicationChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AuthorChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommentsChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommonChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CopyrightChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/FormatVersionChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ID3Chunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/NameChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/SoundChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/TextChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfExtendedHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AudioStreamChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/Chunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ChunkContainer.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContainerType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentBranding.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentDescription.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncodingChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncryptionChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/FileHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUID.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUIDFormatException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/LanguageList.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainer.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainerFactory.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataDescriptor.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/VideoStreamChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfHeaderReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfStreamer.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkContainerReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkHeaderReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkModifier.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkRemover.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentBrandingReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentDescriptionReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingInputStream.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingOutputstream.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncodingChunkReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncryptionChunkReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FileHeaderReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FullRequestInputStream.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/LanguageListReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/MetadataReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ModificationResult.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamChunkReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunkModifer.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/ChunkPositionComparator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/TagConverter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/Utils.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsdChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/Dsf.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfChunkType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/FmtChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/ID3Chunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadVideoException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotWriteException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ModifyVetoException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoReadPermissionsException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoWritePermissionsException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NullBoxIdException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ReadOnlyFileException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToCreateFileException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToModifyFileException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToRenameFileException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacAudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacInfoReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacStreamReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagCreator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/BlockType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTagCreator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationAdapter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationListener.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericAudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/ModificationHandler.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/TagWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/Utils.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/Chunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkSummary.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/IffHeaderChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/ByteArrayMP3AudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/LameFrame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3AudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3File.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MPEGFrameHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/VbriFrame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/XingFrame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/EncoderType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomTree.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AudioHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4InfoReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MdhdBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MetaBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/NullPadding.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/VorbisVersion.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggCRCFactory.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggInfoReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggPageHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisPacketType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavChunkType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavInfoReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavOptions.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavRIFFHeader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOptions.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOrder.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSubFormat.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagWriter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavChunkSummary.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFactChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFormatChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavId3Chunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoIdentifier.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavListChunk.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/AbstractTagDisplayFormatter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/ErrorMessage.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/FileSystemMessage.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/Hex.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/PlainTextTagDisplayFormatter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/XMLTagDisplayFormatter.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/EmptyFrameException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldDataInvalidException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidDataTypeException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameIdentifierException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidTagException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/KeyNotFoundException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/PaddingException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagNotFoundException.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagOptionSingleton.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagTextField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTagFieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AbstractAsfTagImageField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfFieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagBannerField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagCoverField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagTextField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataTypeList.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractIntStringValuePair.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractString.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractValuePair.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanByte.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanString.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/DataTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCode.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCodeList.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/HashMapInterface.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ID3v2LyricLine.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Image.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Line.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberFixedLength.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberHashMap.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberVariableLength.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Pair.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PartOfSet.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDate.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDateTime.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringFixedLength.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringHashMap.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringNullTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringSizeTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCode.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCodeList.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TCONString.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TempoCode.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/flac/FlacTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v1Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Frame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagItem.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AggregatedFrame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Compression.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Frames.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3SyncSafeInteger.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Tags.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3TextEncodingConversion.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Unsynchronization.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v11Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1FieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Iterator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1TagField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22FieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frames.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23FieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frames.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24FieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frames.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v2ChapterFrames.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3FieldType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3SupportingTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyNumberTotal.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyPairs.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractID3v2FrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAENC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRP1.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVIN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVNM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCOP.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSER.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ID3Rating.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ITunesRating.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaPlayerRating.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ChannelTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3NumberTotalFields.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ImageFormats.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/MusicianCredits.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/StandardIPLSKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/TextEncoding.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/AndroidArtwork.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/Artwork.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/ArtworkFactory.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4FieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4Tag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagCreator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4DataBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4NameBox.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4FieldType.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4GenreField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagByteField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TrackField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/options/PadNumberOption.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/GenreTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ID3V2Version.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOCountry.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOScript.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Languages.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/MusicalKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PerformerHelper.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PictureTypes.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Tagger.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistReadOptions.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistSaveOptions.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavInfoTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavTag.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/DirectByteBufferUtils.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/EqualsUtil.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/FileTypeUtil.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/PrimitiveUtils.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultMutableTreeNode.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultTreeModel.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/EventListenerList.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/MutableTreeNode.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModel.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelEvent.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelListener.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeNode.java delete mode 100644 jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreePath.java diff --git a/buildSrc/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/buildSrc/src/main/kotlin/Versions.kt index c15ac7b7..cb42e0a8 100644 --- a/buildSrc/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/buildSrc/src/main/kotlin/Versions.kt @@ -140,6 +140,7 @@ object Extras { const val youtubeDownloader = "com.shabinder.downloader:youtube-api-dl:0.1" //Local Maven const val fuzzyWuzzy = "me.xdrop:fuzzywuzzy:1.3.1" const val mp3agic = "com.mpatric:mp3agic:0.9.0" + const val jaudioTagger = "com.github.Shabinder:JAudioTagger-Android:1.0" const val kermit = "co.touchlab:kermit:${Versions.kermit}" object Android { val razorpay = "com.razorpay:checkout:1.6.5" diff --git a/common/dependency-injection/build.gradle.kts b/common/dependency-injection/build.gradle.kts index dcd0922c..376b63d6 100644 --- a/common/dependency-injection/build.gradle.kts +++ b/common/dependency-injection/build.gradle.kts @@ -52,7 +52,7 @@ kotlin { implementation(Extras.Android.fetch) implementation(Extras.Android.razorpay) api(Extras.mp3agic) - api(project(":jaudiotagger")) + api(Extras.jaudioTagger) // api(files("$rootDir/libs/mobile-ffmpeg.aar")) } } @@ -62,7 +62,7 @@ kotlin { implementation(Ktor.clientApache) implementation(Ktor.slf4j) api(Extras.mp3agic) - api(project(":jaudiotagger")) + api(Extras.jaudioTagger) } } jsMain { diff --git a/jaudiotagger/.gitignore b/jaudiotagger/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/jaudiotagger/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/jaudiotagger/build.gradle.kts b/jaudiotagger/build.gradle.kts deleted file mode 100644 index 6b082805..00000000 --- a/jaudiotagger/build.gradle.kts +++ /dev/null @@ -1,8 +0,0 @@ -plugins { - id("java-library") -} - -java { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/FileConstants.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/FileConstants.java deleted file mode 100644 index 38a4a3b8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/FileConstants.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/StandardCharsets.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/StandardCharsets.java deleted file mode 100644 index dec92b24..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/StandardCharsets.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.mp3.jaudiotagger; - -import java.nio.charset.Charset; - -/** - * Constant definitions for the standard {@link Charset Charsets}. These - * charsets are guaranteed to be available on every implementation of the Java - * platform. - * - * @see Standard Charsets - * @since 1.7 - */ -public final class StandardCharsets { - - private StandardCharsets() { - throw new AssertionError("No com.mp3.jaudiotagger.StandardCharsets instances for you!"); - } - /** - * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the - * Unicode character set - */ - public static final Charset US_ASCII = Charset.forName("US-ASCII"); - /** - * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1 - */ - public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - /** - * Eight-bit UCS Transformation Format - */ - public static final Charset UTF_8 = Charset.forName("UTF-8"); - /** - * Sixteen-bit UCS Transformation Format, big-endian byte order - */ - public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); - /** - * Sixteen-bit UCS Transformation Format, little-endian byte order - */ - public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); - /** - * Sixteen-bit UCS Transformation Format, byte order identified by an - * optional byte-order mark - */ - public static final Charset UTF_16 = Charset.forName("UTF-16"); -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFile.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFile.java deleted file mode 100644 index 749a586e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFile.java +++ /dev/null @@ -1,476 +0,0 @@ -package com.mp3.jaudiotagger.audio; - -import com.mp3.jaudiotagger.audio.dsf.Dsf; -import com.mp3.jaudiotagger.audio.exceptions.*; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import com.mp3.jaudiotagger.audio.real.RealTag; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.aiff.AiffTag; -import com.mp3.jaudiotagger.tag.asf.AsfTag; -import com.mp3.jaudiotagger.tag.flac.FlacTag; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v22Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v23Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v24Tag; -import com.mp3.jaudiotagger.tag.mp4.Mp4Tag; -import com.mp3.jaudiotagger.tag.reference.ID3V2Version; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -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 preferred way to obtain an AudioFile is to use the AudioFileIO.read(File) method. - *

The AudioHeader 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$ - * @see AudioFileIO - * @see Tag - * @since v0.01 - */ -public class AudioFile -{ - //Logger - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio"); - - /** - * - * The physical file that this instance represents. - */ - protected File file; - - /** - * The Audio header info - */ - protected AudioHeader audioHeader; - - /** - * The tag - */ - protected Tag tag; - - /** - * The tag - */ - protected String extension; - - 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; - } - - /** - *

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 NoWritePermissionsException if the file could not be written to due to file permissions - * @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); - } - - /** - *

Delete any tags that exist in the fie , this is the same as calling the AudioFileIO.delete(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 delete() throws CannotReadException, CannotWriteException - { - AudioFileIO.delete(this); - } - - /** - * Set the file to store the info in - * - * @param file - */ - public void setFile(File file) - { - this.file = file; - } - - /** - * Retrieve the physical file - * - * @return - */ - public File getFile() - { - return file; - } - - /** - * Set the file extension - * - * @param ext - */ - public void setExt(String ext) - { - this.extension = ext; - } - - /** - * Retrieve the file extension - * - * @return - */ - public String getExt() - { - return extension; - } - - /** - * Assign a tag to this audio file - * - * @param tag Tag to be assigned - */ - public void setTag(Tag tag) - { - this.tag = tag; - } - - /** - * 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; - } - - /** - *

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 - * @throws ReadOnlyFileException - * @throws FileNotFoundException - * @return - */ - protected RandomAccessFile checkFilePermissions(File file, boolean readOnly) throws ReadOnlyFileException, FileNotFoundException, CannotReadException - { - RandomAccessFile newFile; - checkFileExists(file); - - // Unless opened as readonly the file must be writable - if (readOnly) - { - //May not even be readable - if(!file.canRead()) - { - logger.severe("Unable to read file:" + file.getPath()); - throw new NoReadPermissionsException(ErrorMessage.GENERAL_READ_FAILED_DO_NOT_HAVE_PERMISSION_TO_READ_FILE.getMsg(file.getPath())); - } - newFile = new RandomAccessFile(file, "r"); - } - else - { - if (TagOptionSingleton.getInstance().isCheckIsWritable() && !file.canWrite()) - { - throw new ReadOnlyFileException(ErrorMessage.NO_PERMISSIONS_TO_WRITE_TO_FILE.getMsg(file.getPath())); - } - newFile = new RandomAccessFile(file, "rw"); - } - 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() - { - String extension = getExt(); - if(extension == null) - { - String fileName = file.getName(); - extension = fileName.substring(fileName.lastIndexOf('.') + 1); - setExt(extension); - } - if(SupportedFileFormat.FLAC.getFilesuffix().equals(extension)) - { - return new FlacTag(VorbisCommentTag.createNewTag(), new ArrayList< MetadataBlockDataPicture >()); - } - else if(SupportedFileFormat.OGG.getFilesuffix().equals(extension)) - { - return VorbisCommentTag.createNewTag(); - } - else if(SupportedFileFormat.MP4.getFilesuffix().equals(extension)) - { - return new Mp4Tag(); - } - else if(SupportedFileFormat.M4A.getFilesuffix().equals(extension)) - { - return new Mp4Tag(); - } - else if(SupportedFileFormat.M4P.getFilesuffix().equals(extension)) - { - return new Mp4Tag(); - } - else if(SupportedFileFormat.WMA.getFilesuffix().equals(extension)) - { - return new AsfTag(); - } - else if(SupportedFileFormat.WAV.getFilesuffix().equals(extension)) - { - return new WavTag(TagOptionSingleton.getInstance().getWavOptions()); - } - else if(SupportedFileFormat.RA.getFilesuffix().equals(extension)) - { - return new RealTag(); - } - else if(SupportedFileFormat.RM.getFilesuffix().equals(extension)) - { - return new RealTag(); - } - else if(SupportedFileFormat.AIF.getFilesuffix().equals(extension)) - { - return new AiffTag(); - } - else if(SupportedFileFormat.AIFC.getFilesuffix().equals(extension)) - { - return new AiffTag(); - } - else if(SupportedFileFormat.AIFF.getFilesuffix().equals(extension)) - { - return new AiffTag(); - } - else if(SupportedFileFormat.DSF.getFilesuffix().equals(extension)) - { - return Dsf.createDefaultTag(); - } - 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 - * as the tag of this file - * - * @return - */ - public Tag getTagOrCreateAndSetDefault() - { - Tag tag = getTagOrCreateDefault(); - setTag(tag); - return tag; - } - - /** - * Get the tag and convert to the default tag version or if the file doesn't have one at all, create a default tag - * set as tag for this file - * - * Conversions are currently only necessary/available for formats that support ID3 - * - * @return - */ - public Tag getTagAndConvertOrCreateAndSetDefault() - { - Tag tag = getTagOrCreateDefault(); - - /* TODO Currently only works for Dsf We need additional check here for Wav and Aif because they wrap the ID3 tag so never return - * null for getTag() and the wrapper stores the location of the existing tag, would that be broken if tag set to something else - */ - if(tag instanceof AbstractID3v2Tag) - { - Tag convertedTag = convertID3Tag((AbstractID3v2Tag)tag, TagOptionSingleton.getInstance().getID3V2Version()); - if(convertedTag!=null) - { - setTag(convertedTag); - } - else - { - setTag(tag); - } - } - else - { - setTag(tag); - } - return getTag(); - } - - /** - * - * @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(); - } - - /** - * If using ID3 format convert tag from current version to another as specified by id3V2Version, - * - * @return null if no conversion necessary - */ - public AbstractID3v2Tag convertID3Tag(AbstractID3v2Tag 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 null; - } - } - else if(tag instanceof ID3v23Tag) - { - switch(id3V2Version) - { - case ID3_V22: - return new ID3v22Tag((ID3v23Tag)tag); - case ID3_V23: - return null; - case ID3_V24: - return new ID3v24Tag((ID3v23Tag)tag); - } - } - else if(tag instanceof ID3v22Tag) - { - switch(id3V2Version) - { - case ID3_V22: - return null; - case ID3_V23: - return new ID3v23Tag((ID3v22Tag)tag); - case ID3_V24: - return new ID3v24Tag((ID3v22Tag)tag); - } - } - return null; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileFilter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileFilter.java deleted file mode 100644 index 4ba6ae08..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileFilter.java +++ /dev/null @@ -1,87 +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 com.mp3.jaudiotagger.audio; - -import com.mp3.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$ - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileIO.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileIO.java deleted file mode 100644 index ad46867c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioFileIO.java +++ /dev/null @@ -1,502 +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 com.mp3.jaudiotagger.audio; - -import com.mp3.jaudiotagger.audio.aiff.AiffFileReader; -import com.mp3.jaudiotagger.audio.aiff.AiffFileWriter; -import com.mp3.jaudiotagger.audio.asf.AsfFileReader; -import com.mp3.jaudiotagger.audio.asf.AsfFileWriter; -import com.mp3.jaudiotagger.audio.dsf.DsfFileReader; -import com.mp3.jaudiotagger.audio.dsf.DsfFileWriter; -import com.mp3.jaudiotagger.audio.exceptions.*; -import com.mp3.jaudiotagger.audio.flac.FlacFileReader; -import com.mp3.jaudiotagger.audio.flac.FlacFileWriter; -import com.mp3.jaudiotagger.audio.generic.*; -import com.mp3.jaudiotagger.audio.mp3.MP3FileReader; -import com.mp3.jaudiotagger.audio.mp3.MP3FileWriter; -import com.mp3.jaudiotagger.audio.mp4.Mp4FileReader; -import com.mp3.jaudiotagger.audio.mp4.Mp4FileWriter; -import com.mp3.jaudiotagger.audio.ogg.OggFileReader; -import com.mp3.jaudiotagger.audio.ogg.OggFileWriter; -import com.mp3.jaudiotagger.audio.real.RealFileReader; -import com.mp3.jaudiotagger.audio.wav.WavFileReader; -import com.mp3.jaudiotagger.audio.wav.WavFileWriter; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.TagException; - -import java.io.Closeable; -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$ - * @see AudioFile - * @see com.mp3.jaudiotagger.tag.Tag - * @since v0.01 - */ -public class AudioFileIO -{ - - //Logger - public static Logger logger = Logger.getLogger("com.mp3.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; - - /** - * - * Delete the tag, if any, contained in the given file. - * - * - * @param f The file where the tag will be deleted - * @throws CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - * @throws 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. - * @param ext The extension to be used. - * @return The AudioFile with the file tag and the file encoding info. - * @throws CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws TagException - * @throws ReadOnlyFileException - * @throws IOException - * @throws InvalidAudioFrameException - */ - public static AudioFile readAs(File f,String ext) - throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException - { - return getDefaultAudioFileIO().readFileAs(f,ext); - } - - /** - * - * 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 CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws TagException - * @throws ReadOnlyFileException - * @throws IOException - * @throws InvalidAudioFrameException - */ - public static AudioFile readMagic(File f) - throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException - { - return getDefaultAudioFileIO().readFileMagic(f); - } - - /** - * - * 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 CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws TagException - * @throws ReadOnlyFileException - * @throws IOException - * @throws 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 NoWritePermissionsException if the file could not be written to due to file permissions - * @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,null); - } - - /** - * - * Write the tag contained in the audioFile in the actual file on the disk. - * - * - * @param f The AudioFile to be written - * @param targetPath The AudioFile path to which to be written without the extension. Cannot be null - * @throws NoWritePermissionsException if the file could not be written to due to file permissions - * @throws CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - */ - public static void writeAs(AudioFile f, String targetPath) throws CannotWriteException - { - if (targetPath == null || targetPath.isEmpty()) { - throw new CannotWriteException("Not a valid target path: " + targetPath); - } - getDefaultAudioFileIO().writeFile(f,targetPath); - } - - /** - * 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 - public Map readers = new HashMap(); - public Map writers = new HashMap(); - - - /** - * Creates an instance. - */ - public AudioFileIO() - { - this.modificationHandler = new ModificationHandler(); - prepareReadersAndWriters(); - } - - /** - * 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 CannotWriteException If the file could not be written/accessed, the extension - * wasn't recognized, or other IO error occurred. - * @throws 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()); - readers.put(SupportedFileFormat.AIFC.getFilesuffix(), new AiffFileReader()); - readers.put(SupportedFileFormat.AIFF.getFilesuffix(), new AiffFileReader()); - readers.put(SupportedFileFormat.DSF.getFilesuffix(), new DsfFileReader()); - 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()); - writers.put(SupportedFileFormat.AIF.getFilesuffix(), new AiffFileWriter()); - writers.put(SupportedFileFormat.AIFC.getFilesuffix(), new AiffFileWriter()); - writers.put(SupportedFileFormat.AIFF.getFilesuffix(), new AiffFileWriter()); - writers.put(SupportedFileFormat.DSF.getFilesuffix(), new DsfFileWriter()); - - // 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 CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws TagException - * @throws ReadOnlyFileException - * @throws IOException - * @throws 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)); - } - AudioFile tempFile = afr.read(f); - tempFile.setExt(ext); - return tempFile; - } - - /** - * - * 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 CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws TagException - * @throws ReadOnlyFileException - * @throws IOException - * @throws InvalidAudioFrameException - */ - public AudioFile readFileMagic(File f) - throws CannotReadException, IOException, TagException, ReadOnlyFileException, InvalidAudioFrameException - { - checkFileExists(f); - String ext = Utils.getMagicExtension(f); - - AudioFileReader afr = readers.get(ext); - if (afr == null) - { - throw new CannotReadException(ErrorMessage.NO_READER_FOR_THIS_FORMAT.getMsg(ext)); - } - - AudioFile tempFile = afr.read(f); - tempFile.setExt(ext); - return tempFile; - - } - - /** - * - * Read the tag contained in the given file. - * - * - * @param f The file to read. - * @param ext The extension to be used. - * @return The AudioFile with the file tag and the file encoding info. - * @throws CannotReadException If the file could not be read, the extension wasn't - * recognized, or an IO error occurred during the read. - * @throws TagException - * @throws ReadOnlyFileException - * @throws IOException - * @throws InvalidAudioFrameException - */ - public AudioFile readFileAs(File f,String ext) - 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)); - } - - AudioFile tempFile = afr.read(f); - tempFile.setExt(ext); - return tempFile; - - } - - /** - * Check does file exist - * - * @param file - * @throws 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 - * @param targetPath a file path, without an extension, which provides a "save as". If null, then normal "save" function - * @throws NoWritePermissionsException if the file could not be written to due to file permissions - * @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, String targetPath) throws CannotWriteException - { - String ext = f.getExt(); - - if (targetPath != null && !targetPath.isEmpty()) - { - final File destination = new File(targetPath + "." + ext); - try - { - Utils.copyThrowsOnException(f.getFile(), destination); - f.setFile(destination); - } catch (IOException e) { - throw new CannotWriteException("Error While Copying" + e.getMessage()); - } - } - - AudioFileWriter afw = writers.get(ext); - if (afw == null) - { - throw new CannotWriteException(ErrorMessage.NO_WRITER_FOR_THIS_FORMAT.getMsg(ext)); - } - - afw.write(f); - } - - /** - * Closes resource unconditionally such as input stream or output stream. - */ - public static void closeQuietly(Closeable... closeables) { - for (Closeable closeable : closeables) { - if (closeable != null) { - try { - closeable.close(); - } catch (IOException e) { - // ignore - } - } - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioHeader.java deleted file mode 100644 index f4322cdf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/AudioHeader.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.mp3.jaudiotagger.audio; - -/** - * Representation of AudioHeader - * - *

Contains info about the Audio Header - */ -public interface AudioHeader -{ - /** - * @return the audio file type - */ - public abstract String getEncodingType(); - - /** - * @return the ByteRate of the Audio, this is the total average amount of bytes of data sampled per second - */ - public Integer getByteRate(); - - - - /** - * @return the BitRate of the Audio, this is the amount of kilobits of data sampled per second - */ - public String getBitRate(); - - /** - * @return bitRate as a number, this is the amount of kilobits of data sampled per second - */ - public long getBitRateAsNumber(); - - - /** - * - * @return length of the audio data in bytes, exactly what this means depends on the audio format - * - * TODO currently only used by Wav/Aiff/Flac/Mp4 - */ - public Long getAudioDataLength(); - - - /** - * - * @return the location in the file where the audio samples start - * - * TODO currently only used by Wav/Aiff/Flac/Mp4 - */ - public Long getAudioDataStartPosition(); - - - /** - * - * @return the location in the file where the audio samples end - * - * TODO currently only used by Wav/Aiff/Flac/Mp4 - */ - public Long getAudioDataEndPosition(); - - - /** - * @return the Sampling rate, the number of samples taken per second - */ - public String getSampleRate(); - - /** - * @return he Sampling rate, the number of samples taken per second - */ - public int getSampleRateAsNumber(); - - /** - * @return the format - */ - public String getFormat(); - - /** - * @return the number of channels (i.e 1 = Mono, 2 = Stereo) - */ - public String getChannels(); - - /** - * @return if the sampling bitRate is variable or constant - */ - public boolean isVariableBitRate(); - - /** - * @return track length in seconds - */ - public int getTrackLength(); - - /** - * - * @return track length as float - */ - public double getPreciseTrackLength(); - - /** - * @return the number of bits in each sample - */ - public int getBitsPerSample(); - - /** - * - * @return if the audio codec is lossless or lossy - */ - public boolean isLossless(); - - /** - * - * @return the total number of samples, this can usually be used in conjunction with the - * sample rate to determine the track duration - */ - public Long getNoOfSamples(); -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/SupportedFileFormat.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/SupportedFileFormat.java deleted file mode 100644 index fd138a92..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/SupportedFileFormat.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.mp3.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"), - AIFF("aiff"), - AIFC("aifc"), - DSF("dsf"); - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffAudioHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffAudioHeader.java deleted file mode 100644 index a1438c13..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffAudioHeader.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.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 -{ - - public enum Endian - { - BIG_ENDIAN, - LITTLE_ENDIAN - } - - private AiffType 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; - private List annotations; - - public AiffAudioHeader() - { - this.applicationIdentifiers = new ArrayList(); - this.comments = new ArrayList(); - this.annotations = new ArrayList(); - this.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 AiffType getFileType() - { - return fileType; - } - - /** - * Set the file type (AIFF or AIFC) - */ - public void setFileType(AiffType 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 annotations; - } - - /** - * Add an annotation. There can be any number of these. - */ - public void addAnnotation(String a) - { - annotations.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); - } - - public String toString() - { - StringBuilder sb = new StringBuilder("\n"); - - if(name!=null && !name.isEmpty()) - { - sb.append("\tName:"+name+"\n"); - } - - if(author!=null && !author.isEmpty()) - { - sb.append("\tAuthor:"+author+"\n"); - } - - if(copyright!=null && !copyright.isEmpty()) - { - sb.append("\tCopyright:"+copyright+"\n"); - } - - if(comments.size()>0) - { - sb.append("Comments:\n"); - for(String next:comments) - { - sb.append("\t"+next+"\n"); - } - } - - if(applicationIdentifiers.size()>0) - { - sb.append("ApplicationIds:\n"); - for(String next:applicationIdentifiers) - { - sb.append("\t"+next+"\n"); - } - } - - if(annotations.size()>0) - { - sb.append("Annotations:\n"); - for(String next:annotations) - { - sb.append("\t"+next+"\n"); - } - } - return super.toString() + sb.toString(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileHeader.java deleted file mode 100644 index da234a8a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileHeader.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.logging.Hex; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -import static java.nio.ByteOrder.BIG_ENDIAN; -import static com.mp3.jaudiotagger.audio.aiff.AiffType.AIFC; -import static com.mp3.jaudiotagger.audio.aiff.AiffType.AIFF; -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.HEADER_LENGTH; -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.TYPE_LENGTH; - -/** - *

- * Aiff File Header always consists of - *

- * - */ -public class AiffFileHeader -{ - private static final String FORM = "FORM"; - private static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.aiff.AudioFileHeader"); - - /** - * Reads the file header and registers the data (file type) with the given header. - * - * @param fc random access file - * @param aiffAudioHeader the {@link com.mp3.jaudiotagger.audio.AudioHeader} we set the read data to - * @param fileName - * @return the number of bytes in the FORM chunk, i.e. the size of the payload - * @throws IOException - * @throws CannotReadException if the file is not a valid AIFF file - */ - public long readHeader(FileChannel fc, final AiffAudioHeader aiffAudioHeader, String fileName) throws IOException, CannotReadException - { - final ByteBuffer headerData = ByteBuffer.allocateDirect(HEADER_LENGTH); - headerData.order(BIG_ENDIAN); - final int bytesRead = fc.read(headerData); - headerData.position(0); - - if (bytesRead < HEADER_LENGTH) - { - throw new IOException(fileName + " AIFF:Unable to read required number of databytes read:" + bytesRead + ":required:" + HEADER_LENGTH); - } - - final String signature = Utils.readFourBytesAsChars(headerData); - if(FORM.equals(signature)) - { - // read chunk size - final long chunkSize = headerData.getInt(); - logger.severe(fileName + " Reading AIFF header size:" + Hex.asDecAndHex(chunkSize)); - - readFileType(headerData, aiffAudioHeader); - // subtract the file type length from the chunk size to get remaining number of bytes - return chunkSize - TYPE_LENGTH; - } - else - { - throw new CannotReadException(fileName + "Not an AIFF file: incorrect signature " + signature); - } - } - - /** - * Reads the file type ({@link AiffType}). - * - * @throws CannotReadException if the file type is not supported - */ - private void readFileType(final ByteBuffer bytes, final AiffAudioHeader aiffAudioHeader) throws IOException, CannotReadException { - final String type = Utils.readFourBytesAsChars(bytes); - if (AIFF.getCode().equals(type)) - { - aiffAudioHeader.setFileType(AIFF); - } - else if (AIFC.getCode().equals(type)) - { - aiffAudioHeader.setFileType(AIFC); - } - else - { - throw new CannotReadException("Invalid AIFF file: Incorrect file type info " + type); - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileReader.java deleted file mode 100644 index a8e9b6a2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileReader.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader2; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.tag.Tag; - -import java.io.File; -import java.io.IOException; - -/** - * Reads Audio and Metadata information contained in Aiff file. - */ -public class AiffFileReader extends AudioFileReader2 { - private AiffInfoReader ir = new AiffInfoReader(); - private AiffTagReader im = new AiffTagReader(); - - @Override - protected GenericAudioHeader getEncodingInfo(File file) throws CannotReadException, IOException { - return ir.read(file); - } - - @Override - protected Tag getTag(File file) throws CannotReadException, IOException { - return im.read(file); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileWriter.java deleted file mode 100644 index 0ccfcb42..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffFileWriter.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 com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter2; -import com.mp3.jaudiotagger.tag.Tag; - -import java.io.File; - - -/** - * Write/delete tag info for Aiff file (Old Apple format) - */ -public class AiffFileWriter extends AudioFileWriter2 -{ - - private AiffTagWriter tw = new AiffTagWriter(); - - @Override - protected void writeTag(Tag tag, File file) throws CannotWriteException - { - tw.write(tag, file); - } - - @Override - protected void deleteTag(Tag tag, File file) throws CannotWriteException - { - tw.delete(tag, file); - } - - -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffInfoReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffInfoReader.java deleted file mode 100644 index 37f3aa93..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffInfoReader.java +++ /dev/null @@ -1,161 +0,0 @@ - -package com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.aiff.chunk.*; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.logging.Hex; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Read Aiff chunks, except the ID3 chunk. - */ -public class AiffInfoReader extends AiffChunkReader { - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.aiff"); - - - protected GenericAudioHeader read(File file) throws CannotReadException, IOException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - logger.config(file + " Reading AIFF file size:" + Hex.asDecAndHex(fc.size())); - AiffAudioHeader aiffAudioHeader = new AiffAudioHeader(); - final AiffFileHeader fileHeader = new AiffFileHeader(); - long noOfBytes = fileHeader.readHeader(fc, aiffAudioHeader, file.toString()); - while (fc.position() < fc.size()) { - if (!readChunk(fc, aiffAudioHeader, file.toString())) { - logger.severe(file + " UnableToReadProcessChunk"); - break; - } - } - calculateBitRate(aiffAudioHeader); - return aiffAudioHeader; - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Calculate bitrate, done it here because requires data from multiple chunks - * - * @param info - * @throws CannotReadException - */ - private void calculateBitRate(GenericAudioHeader info) throws CannotReadException { - if (info.getAudioDataLength() != null) { - info.setBitRate((int) (Math.round(info.getAudioDataLength() - * Utils.BITS_IN_BYTE_MULTIPLIER / (info.getPreciseTrackLength() * Utils.KILOBYTE_MULTIPLIER)))); - } - } - - /** - * Reads an AIFF Chunk. - * - * @return {@code false}, if we were not able to read a valid chunk id - */ - private boolean readChunk(FileChannel fc, AiffAudioHeader aiffAudioHeader, String fileName) throws IOException, CannotReadException { - logger.config(fileName + " Reading Info Chunk"); - final Chunk chunk; - final ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.BIG_ENDIAN); - if (!chunkHeader.readHeader(fc)) { - return false; - } - - logger.config(fileName + "Reading Next Chunk:" + chunkHeader.getID() + ":starting at:" + chunkHeader.getStartLocationInFile() + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - chunk = createChunk(fc, chunkHeader, aiffAudioHeader); - if (chunk != null) { - if (!chunk.readChunk()) { - logger.severe(fileName + "ChunkReadFail:" + chunkHeader.getID()); - return false; - } - } else { - if (chunkHeader.getSize() < 0) { - String msg = fileName + " Not a valid header, unable to read a sensible size:Header" - + chunkHeader.getID() + "Size:" + chunkHeader.getSize(); - logger.severe(msg); - throw new CannotReadException(msg); - } - fc.position(fc.position() + chunkHeader.getSize()); - } - IffHeaderChunk.ensureOnEqualBoundary(fc, chunkHeader); - return true; - } - - /** - * Create a chunk. May return {@code null}, if the chunk is not of a valid type. - * - * @param fc - * @param chunkHeader - * @param aiffAudioHeader - * @return - * @throws IOException - */ - private Chunk createChunk(FileChannel fc, final ChunkHeader chunkHeader, AiffAudioHeader aiffAudioHeader) - throws IOException { - final AiffChunkType chunkType = AiffChunkType.get(chunkHeader.getID()); - Chunk chunk; - if (chunkType != null) { - switch (chunkType) { - case FORMAT_VERSION: - chunk = new FormatVersionChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case APPLICATION: - chunk = new ApplicationChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case COMMON: - chunk = new CommonChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case COMMENTS: - chunk = new CommentsChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case NAME: - chunk = new NameChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case AUTHOR: - chunk = new AuthorChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case COPYRIGHT: - chunk = new CopyrightChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case ANNOTATION: - chunk = new AnnotationChunk(chunkHeader, readChunkDataIntoBuffer(fc, chunkHeader), aiffAudioHeader); - break; - - case SOUND: - //Dont need to read chunk itself just need size - aiffAudioHeader.setAudioDataLength(chunkHeader.getSize()); - aiffAudioHeader.setAudioDataStartPosition(fc.position()); - aiffAudioHeader.setAudioDataEndPosition(fc.position() + chunkHeader.getSize()); - - chunk = null; - break; - - default: - chunk = null; - } - } else { - chunk = null; - } - return chunk; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagFieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagFieldKey.java deleted file mode 100644 index b075411c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagFieldKey.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagReader.java deleted file mode 100644 index 20062b45..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagReader.java +++ /dev/null @@ -1,138 +0,0 @@ - -package com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.aiff.chunk.AiffChunkReader; -import com.mp3.jaudiotagger.audio.aiff.chunk.AiffChunkType; -import com.mp3.jaudiotagger.audio.aiff.chunk.ID3Chunk; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.aiff.AiffTag; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Read the AIff file chunks, until finds Aiff Common chunk and then generates AudioHeader from it - */ -public class AiffTagReader extends AiffChunkReader { - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.aiff"); - - - /** - * Read editable Metadata - * - * @param file - * @return - * @throws CannotReadException - * @throws IOException - */ - public AiffTag read(File file) throws CannotReadException, IOException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - AiffAudioHeader aiffAudioHeader = new AiffAudioHeader(); - AiffTag aiffTag = new AiffTag(); - - final AiffFileHeader fileHeader = new AiffFileHeader(); - fileHeader.readHeader(fc, aiffAudioHeader, file.toString()); - while (fc.position() < fc.size()) { - if (!readChunk(fc, aiffTag, file.toString())) { - logger.severe(file + " UnableToReadProcessChunk"); - break; - } - } - - if (aiffTag.getID3Tag() == null) { - aiffTag.setID3Tag(AiffTag.createDefaultID3Tag()); - } - return aiffTag; - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Reads an AIFF ID3 Chunk. - * - * @return {@code false}, if we were not able to read a valid chunk id - */ - private boolean readChunk(FileChannel fc, AiffTag aiffTag, String fileName) throws IOException { - logger.config(fileName + " Reading Tag Chunk"); - - ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.BIG_ENDIAN); - if (!chunkHeader.readHeader(fc)) { - return false; - } - logger.config(fileName + " Reading Chunk:" + chunkHeader.getID() + ":starting at:" - + Hex.asDecAndHex(chunkHeader.getStartLocationInFile()) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - - long startLocationOfId3TagInFile = fc.position(); - AiffChunkType chunkType = AiffChunkType.get(chunkHeader.getID()); - if (chunkType != null && chunkType == AiffChunkType.TAG && chunkHeader.getSize() > 0) { - ByteBuffer chunkData = readChunkDataIntoBuffer(fc, chunkHeader); - aiffTag.addChunkSummary(new ChunkSummary(chunkHeader.getID(), chunkHeader.getStartLocationInFile(), chunkHeader.getSize())); - - //If we havent already for an ID3 Tag - if (aiffTag.getID3Tag() == null) { - Chunk chunk = new ID3Chunk(chunkHeader, chunkData, aiffTag); - chunk.readChunk(); - aiffTag.setExistingId3Tag(true); - aiffTag.getID3Tag().setStartLocationInFile(startLocationOfId3TagInFile); - aiffTag.getID3Tag().setEndLocationInFile(fc.position()); - } - //else otherwise we discard because the first one found is the one that will be used by other apps - { - logger.warning(fileName + " Ignoring ID3Tag because already have one:" - + chunkHeader.getID() + ":" - + chunkHeader.getStartLocationInFile() - + Hex.asDecAndHex(chunkHeader.getStartLocationInFile() - 1) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - } - } - //Special handling to recognise ID3Tags written on odd boundary because original preceding chunk odd length but - //didn't write padding byte - else if (chunkType != null && chunkType == AiffChunkType.CORRUPT_TAG_LATE) { - logger.warning(fileName + "Found Corrupt ID3 Chunk, starting at Odd Location:" + chunkHeader.getID() + ":" - + Hex.asDecAndHex(chunkHeader.getStartLocationInFile() - 1) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - - //We only want to know if first metadata tag is misaligned - if (aiffTag.getID3Tag() == null) { - aiffTag.setIncorrectlyAlignedTag(true); - } - fc.position(fc.position() - (ChunkHeader.CHUNK_HEADER_SIZE + 1)); - return true; - } - //Other Special handling for ID3Tags - else if (chunkType != null && chunkType == AiffChunkType.CORRUPT_TAG_EARLY) { - logger.warning(fileName + " Found Corrupt ID3 Chunk, starting at Odd Location:" + chunkHeader.getID() - + ":" + Hex.asDecAndHex(chunkHeader.getStartLocationInFile()) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - - //We only want to know if first metadata tag is misaligned - if (aiffTag.getID3Tag() == null) { - aiffTag.setIncorrectlyAlignedTag(true); - } - fc.position(fc.position() - (ChunkHeader.CHUNK_HEADER_SIZE - 1)); - return true; - } else { - logger.config(fileName + "Skipping Chunk:" + chunkHeader.getID() + ":" + chunkHeader.getSize()); - aiffTag.addChunkSummary(new ChunkSummary(chunkHeader.getID(), chunkHeader.getStartLocationInFile(), chunkHeader.getSize())); - fc.position(fc.position() + chunkHeader.getSize()); - } - IffHeaderChunk.ensureOnEqualBoundary(fc, chunkHeader); - return true; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagWriter.java deleted file mode 100644 index 0f449570..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffTagWriter.java +++ /dev/null @@ -1,403 +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 com.mp3.jaudiotagger.audio.aiff; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.aiff.chunk.AiffChunkSummary; -import com.mp3.jaudiotagger.audio.aiff.chunk.AiffChunkType; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.aiff.AiffTag; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.SIGNATURE_LENGTH; -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.SIZE_LENGTH; - - -/** - * Write Aiff Tag. - */ -public class AiffTagWriter { - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.aiff"); - - /** - * Read existing metadata - * - * @param file - * @return tags within Tag wrapper - * @throws IOException - * @throws CannotWriteException - */ - private AiffTag getExistingMetadata(File file) throws IOException, CannotWriteException { - try { - //Find AiffTag (if any) - AiffTagReader im = new AiffTagReader(); - return im.read(file); - } catch (CannotReadException ex) { - throw new CannotWriteException(file + " Failed to read file"); - } - } - - /** - * Seek in file to start of LIST Metadata chunk - * - * @param fc - * @param existingTag - * @throws IOException - * @throws CannotWriteException - */ - private ChunkHeader seekToStartOfMetadata(FileChannel fc, AiffTag existingTag, String fileName) throws IOException, CannotWriteException { - fc.position(existingTag.getStartLocationInFileOfId3Chunk()); - final ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.BIG_ENDIAN); - chunkHeader.readHeader(fc); - fc.position(fc.position() - ChunkHeader.CHUNK_HEADER_SIZE); - - if (!AiffChunkType.TAG.getCode().equals(chunkHeader.getID())) { - throw new CannotWriteException(fileName + " Unable to find ID3 chunk at expected location:" + existingTag.getStartLocationInFileOfId3Chunk()); - } - return chunkHeader; - } - - /** - * @param existingTag - * @param fc - * @return true if at end of file (also take into account padding byte) - * @throws IOException - */ - private boolean isAtEndOfFileAllowingForPaddingByte(AiffTag existingTag, FileChannel fc) throws IOException { - return ( - ( - existingTag.getID3Tag().getEndLocationInFile() == fc.size() - ) - || - ( - Utils.isOddLength(existingTag.getID3Tag().getEndLocationInFile()) - && - existingTag.getID3Tag().getEndLocationInFile() + 1 == fc.size() - ) - ); - } - - /** - * Delete given {@link Tag} from file. - * - * @param tag tag, must be instance of {@link AiffTag} - * @param file - * @throws IOException - * @throws com.mp3.jaudiotagger.audio.exceptions.CannotWriteException - */ - public void delete(final Tag tag, File file) throws CannotWriteException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - logger.severe(file + " Deleting tag from file"); - final AiffTag existingTag = getExistingMetadata(file); - - if (existingTag.isExistingId3Tag() && existingTag.getID3Tag().getStartLocationInFile() != null) { - ChunkHeader chunkHeader = seekToStartOfMetadata(fc, existingTag, file.toString()); - if (isAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - logger.severe(file + " Setting new length to:" + (existingTag.getStartLocationInFileOfId3Chunk())); - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk()); - } else { - logger.severe(file + " Deleting tag chunk"); - deleteTagChunk(fc, existingTag, chunkHeader, file.toString()); - } - rewriteRiffHeaderSize(fc); - } - logger.severe(file + " Deleted tag from file"); - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - *

Deletes the given ID3-{@link Tag}/{@link Chunk} from the file by moving all following chunks up.

- *
-     * [chunk][-id3-][chunk][chunk]
-     * [chunk] <<--- [chunk][chunk]
-     * [chunk][chunk][chunk]
-     * 
- * - * @param fc, filechannel - * @param existingTag existing tag - * @param tagChunkHeader existing chunk header for the tag - * @throws IOException if something goes wrong - */ - private void deleteTagChunk(FileChannel fc, final AiffTag existingTag, final ChunkHeader tagChunkHeader, String fileName) throws IOException { - int lengthTagChunk = (int) tagChunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE; - if (Utils.isOddLength(lengthTagChunk)) { - if (existingTag.getStartLocationInFileOfId3Chunk() + lengthTagChunk < fc.size()) { - lengthTagChunk++; - } - } - final long newLength = fc.size() - lengthTagChunk; - logger.severe(fileName + " Size of id3 chunk to delete is:" + lengthTagChunk + ":Location:" + existingTag.getStartLocationInFileOfId3Chunk()); - - // position for reading after the id3 tag - fc.position(existingTag.getStartLocationInFileOfId3Chunk() + lengthTagChunk); - - deleteTagChunkUsingSmallByteBufferSegments(existingTag, fc, newLength, lengthTagChunk); - // truncate the file after the last chunk - logger.severe(fileName + " Setting new length to:" + newLength); - fc.truncate(newLength); - } - - /** - * If Metadata tags are corrupted and no other tags later in the file then just truncate ID3 tags and start again - * - * @param fc - * @param existingTag - * @throws IOException - */ - private void deleteRemainderOfFile(FileChannel fc, final AiffTag existingTag, String fileName) throws IOException { - ChunkSummary precedingChunk = AiffChunkSummary.getChunkBeforeStartingMetadataTag(existingTag); - if (!Utils.isOddLength(precedingChunk.getEndLocation())) { - logger.severe(fileName + " Truncating corrupted ID3 tags from:" + (existingTag.getStartLocationInFileOfId3Chunk() - 1)); - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk() - 1); - } else { - logger.severe(fileName + " Truncating corrupted ID3 tags from:" + (existingTag.getStartLocationInFileOfId3Chunk())); - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk()); - } - } - - /** - * The following seems to work on Windows but hangs on OSX! - * Bug is filed here. - * - * @param existingTag existing tag - * @param channel channel - * @param newLength new length - * @throws IOException if something goes wrong - */ - private void deleteTagChunkUsingChannelTransfer(final AiffTag existingTag, final FileChannel channel, final long newLength) - throws IOException { - long read; - //Read from just after the ID3Chunk into the channel at where the ID3 chunk started, should usually only require one transfer - //but put into loop in case multiple calls are required - for (long position = existingTag.getStartLocationInFileOfId3Chunk(); - (read = channel.transferFrom(channel, position, newLength - position)) < newLength - position; - position += read) - ;//is this problem if loop called more than once do we need to update position of channel to modify - //where write to ? - } - - /** - * Use ByteBuffers to copy a 4mb chunk, write the chunk and repeat until the rest of the file after the ID3 tag - * is rewritten - * - * @param existingTag existing tag - * @param channel channel - * @param newLength new length - * @param lengthTagChunk length tag chunk - * @throws IOException if something goes wrong - */ - // TODO: arguments are not used, position is implicit - private void deleteTagChunkUsingSmallByteBufferSegments(final AiffTag existingTag, final FileChannel channel, final long newLength, final long lengthTagChunk) - throws IOException { - final ByteBuffer buffer = ByteBuffer.allocateDirect((int) TagOptionSingleton.getInstance().getWriteChunkSize()); - while (channel.read(buffer) >= 0 || buffer.position() != 0) { - buffer.flip(); - final long readPosition = channel.position(); - channel.position(readPosition - lengthTagChunk - buffer.limit()); - channel.write(buffer); - channel.position(readPosition); - buffer.compact(); - } - } - - /** - * @param tag - * @param file - * @throws CannotWriteException - * @throws IOException - */ - public void write(final Tag tag, File file) throws CannotWriteException { - logger.severe(file + " Writing Aiff tag to file"); - AiffTag existingTag = null; - try { - existingTag = getExistingMetadata(file); - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } - - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - long existingFileLength = fc.size(); - - final AiffTag aiffTag = (AiffTag) tag; - final ByteBuffer bb = convert(aiffTag, existingTag); - - //Replacing ID3 tag - if (existingTag.isExistingId3Tag() && existingTag.getID3Tag().getStartLocationInFile() != null) { - //Usual case - if (!existingTag.isIncorrectlyAlignedTag()) { - final ChunkHeader chunkHeader = seekToStartOfMetadata(fc, existingTag, file.toString()); - logger.info(file + "Current Space allocated:" + existingTag.getSizeOfID3TagOnly() + ":NewTagRequires:" + bb.limit()); - - //Usual case ID3 is last chunk - if (isAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - writeDataToFile(fc, bb); - } - //Unusual Case where ID3 is not last chunk - else { - deleteTagChunk(fc, existingTag, chunkHeader, file.toString()); - fc.position(fc.size()); - writeExtraByteIfChunkOddSize(fc, fc.size()); - writeDataToFile(fc, bb); - } - } - //Existing ID3 tag is incorrectly aligned so if we can lets delete it and any subsequentially added - //ID3 tags as we only want one ID3 tag. - else if (AiffChunkSummary.isOnlyMetadataTagsAfterStartingMetadataTag(existingTag)) { - deleteRemainderOfFile(fc, existingTag, file.toString()); - fc.position(fc.size()); - writeExtraByteIfChunkOddSize(fc, fc.size()); - writeDataToFile(fc, bb); - } else { - throw new CannotWriteException(file + " Metadata tags are corrupted and not at end of file so cannot be fixed"); - } - } - //New Tag - else { - fc.position(fc.size()); - if (Utils.isOddLength(fc.size())) { - fc.write(ByteBuffer.allocateDirect(1)); - } - writeDataToFile(fc, bb); - } - - if (existingFileLength != fc.size()) { - rewriteRiffHeaderSize(fc); - } - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Rewrite RAF header to reflect new file length - * - * @param fc - * @throws IOException - */ - private void rewriteRiffHeaderSize(FileChannel fc) throws IOException { - - fc.position(IffHeaderChunk.SIGNATURE_LENGTH); - ByteBuffer bb = ByteBuffer.allocateDirect(IffHeaderChunk.SIZE_LENGTH); - bb.order(ByteOrder.BIG_ENDIAN); - int size = ((int) fc.size()) - SIGNATURE_LENGTH - SIZE_LENGTH; - bb.putInt(size); - bb.flip(); - fc.write(bb); - } - - /** - * Writes data as a {@link AiffChunkType#TAG} chunk to the file. - * - * @param fc filechannel - * @param bb data to write - * @throws IOException - */ - private void writeDataToFile(FileChannel fc, final ByteBuffer bb) - throws IOException { - final ChunkHeader ch = new ChunkHeader(ByteOrder.BIG_ENDIAN); - ch.setID(AiffChunkType.TAG.getCode()); - ch.setSize(bb.limit()); - fc.write(ch.writeHeader()); - fc.write(bb); - writeExtraByteIfChunkOddSize(fc, bb.limit()); - } - - /** - * Chunk must also start on an even byte so if our chunksize is odd we need - * to write another byte. This should never happen as ID3Tag is now amended - * to ensure always write padding byte if needed to stop it being odd sized - * but we keep check in just incase. - * - * @param fc - * @param size - * @throws IOException - */ - private void writeExtraByteIfChunkOddSize(FileChannel fc, long size) - throws IOException { - if (Utils.isOddLength(size)) { - fc.write(ByteBuffer.allocateDirect(1)); - } - } - - /** - * Converts tag to {@link ByteBuffer}. - * - * @param tag tag - * @param existingTag - * @return byte buffer containing the tag data - * @throws UnsupportedEncodingException - */ - public ByteBuffer convert(final AiffTag tag, AiffTag existingTag) throws UnsupportedEncodingException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - long existingTagSize = existingTag.getSizeOfID3TagOnly(); - - //If existingTag is uneven size lets make it even - if (existingTagSize > 0) { - if ((existingTagSize & 1) != 0) { - existingTagSize++; - } - } - - //Write Tag to buffer - tag.getID3Tag().write(baos, (int) existingTagSize); - - //If the tag is now odd because we needed to increase size and the data made it odd sized - //we redo adding a padding byte to make it even - if ((baos.toByteArray().length & 1) != 0) { - int newSize = baos.toByteArray().length + 1; - baos = new ByteArrayOutputStream(); - tag.getID3Tag().write(baos, newSize); - } - final 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffType.java deleted file mode 100644 index 073f3e16..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffType.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff; - -/** - * AIFF types, refers to BigEndian or LittleEndian - */ -public enum AiffType -{ - AIFF("AIFF"), //Original non-compressed format on Mac pre-intel hardware - AIFC("AIFC"), //Originally Compressed AIFF but also used for Uncompressed in LE rather than BE order - ; - - String code; - - AiffType(String code) - { - this.code=code; - } - - public String getCode() - { - return code; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffUtil.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffUtil.java deleted file mode 100644 index 7731bb85..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/AiffUtil.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - -/** - * Utility methods only of use for Aiff datatypes - */ -public class AiffUtil -{ - - private final static SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - - - public static double read80BitDouble(ByteBuffer chunkData) throws IOException - { - byte[] buf = new byte[10]; - chunkData.get(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); - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/ExtDouble.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/ExtDouble.java deleted file mode 100644 index 4bab0315..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/ExtDouble.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkReader.java deleted file mode 100644 index f73f272c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkReader.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; - -/** - * Abstract class For reading Aiff Chunks used by both Audio and Tag Reader - */ -public abstract class AiffChunkReader -{ - /** - * Read the next chunk into ByteBuffer as specified by ChunkHeader and moves raf file pointer - * to start of next chunk/end of file. - * - * @param fc - * @param chunkHeader - * @return - * @throws IOException - */ - protected ByteBuffer readChunkDataIntoBuffer(FileChannel fc, final ChunkHeader chunkHeader) throws IOException - { - final ByteBuffer chunkData = ByteBuffer.allocateDirect((int)chunkHeader.getSize()); - chunkData.order(ByteOrder.BIG_ENDIAN); - fc.read(chunkData); - chunkData.position(0); - return chunkData; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkSummary.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkSummary.java deleted file mode 100644 index 41b744dd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkSummary.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.tag.aiff.AiffTag; - -/** - * AIFF Specific methods for ChunkSummarys - */ -public class AiffChunkSummary -{ - /** - * Checks that there are only id3 tags after the currently selected id3tag because this means its safe to truncate - * the remainder of the file. - * - * @param tag - * @return - */ - public static boolean isOnlyMetadataTagsAfterStartingMetadataTag(AiffTag tag) - { - boolean firstId3Tag = false; - for(ChunkSummary cs:tag.getChunkSummaryList()) - { - if(firstId3Tag) - { - if(!cs.getChunkId().equals(AiffChunkType.TAG.getCode())) - { - return false; - } - } - else - { - if (cs.getFileStartLocation() == tag.getStartLocationInFileOfId3Chunk()) - { - //Found starting point - firstId3Tag = true; - } - } - } - - //Should always be true but this is to protect against something gone wrong - if(firstId3Tag==true) - { - return true; - } - return false; - - } - - /** - * Get chunk before starting metadata tag - * - * @param tag - * @return - */ - public static ChunkSummary getChunkBeforeStartingMetadataTag(AiffTag tag) - { - for(int i=0;i < tag.getChunkSummaryList().size(); i++) - { - ChunkSummary cs = tag.getChunkSummaryList().get(i); - if (cs.getFileStartLocation() == tag.getStartLocationInFileOfId3Chunk()) - { - return tag.getChunkSummaryList().get(i - 1); - } - } - return null; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkType.java deleted file mode 100644 index 1e0e5101..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffChunkType.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import java.util.HashMap; -import java.util.Map; - -/** - * Chunk types mark each {@link com.mp3.jaudiotagger.audio.iff.ChunkHeader}. They are always 4 ASCII chars long. - * - * @see com.mp3.jaudiotagger.audio.iff.Chunk - */ -public enum AiffChunkType -{ - FORMAT_VERSION("FVER"), - APPLICATION("APPL"), - SOUND("SSND"), - COMMON("COMM"), - COMMENTS("COMT"), - NAME("NAME"), - AUTHOR("AUTH"), - COPYRIGHT("(c) "), - ANNOTATION("ANNO"), - TAG("ID3 "), - CORRUPT_TAG_LATE("D3 \u0000"), - CORRUPT_TAG_EARLY("\u0000ID3"); - - private static final Map CODE_TYPE_MAP = new HashMap(); - private String code; - - /** - * @param code 4 char string - */ - AiffChunkType(final String code) - { - this.code=code; - } - - /** - * Get {@link AiffChunkType} for code (e.g. "SSND"). - * - * @param code chunk id - * @return chunk type or {@code null} if not registered - */ - public synchronized static AiffChunkType get(final String code) { - if (CODE_TYPE_MAP.isEmpty()) { - for (final AiffChunkType type : values()) { - CODE_TYPE_MAP.put(type.getCode(), type); - } - } - return CODE_TYPE_MAP.get(code); - } - - /** - * 4 char type code. - * - * @return 4 char type code, e.g. "SSND" for the sound chunk. - */ - public String getCode() - { - return code; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffCompressionType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffCompressionType.java deleted file mode 100644 index 1092d09c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AiffCompressionType.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import java.util.HashMap; -import java.util.Map; - -/** - * Known compression types that can be used with AIFF, taken from - * https://en.wikipedia.org/wiki/Audio_Interchange_File_Format. - * - * Note SOWT is not a compression format but it uses AIFF-C to allow it store music data in Little-Endian order, - * it only affects audio data not the other chunks such as metadata. - */ -public enum AiffCompressionType -{ - NONE("NONE", "not compressed","big-endian", "Apple", true), - RAW("raw ", "PCM 8-bit","offset-binary", "Apple", false), - TWOS("twos", "PCM 16-bit","twos-complement little-endian", "Apple", false), - SOWT("sowt", "not compressed","little-endian", "Apple", true), - fl32("fl32", "PCM 32-bit","floating point,", "Apple", false), - ll64("fl64", "PCM 64-bit","floating point", "Apple", false), - IN24("in24", "PCM 24-bit","integer", "Apple", false), - IN32("in32", "PCM 32-bit","integer", "Apple", false), - alaw("alaw","Alaw 2:1", "8-bit ITU-T G.711 A-law", "Apple", false), - ulaw("ulaw","µlaw 2:1","8-bit ITU-T G.711 µ-law","Apple", false), - MAC3("MAC3", "MACE 3-to-1","", "Apple", false), - MAC6("MAC6", "MACE 6-to-1","", "Apple", false), - ALAW("ALAW","CCITT G.711 A-law", "8-bit ITU-T G.711 A-law (64 kbit/s)", "SGI", false), - ULAW("ULAW","CCITT G.711 u-law","8-bit ITU-T G.711 A-law (64 kbit/s)","SGI", false), - FL32("FL32", "Float 32","IEEE 32-bit float", "SoundHack & Csound", false), - rt24("rt24", "RT24 50:1","", "Voxware", false), - rt29("rt29", "RT29 50:1","", "Voxware", false), - ; - - // Reverse-lookup map for getting a compression type from code - private static final Map lookup = new HashMap(); - - static - { - for (AiffCompressionType d : AiffCompressionType.values()) - { - lookup.put(d.getCode(), d); - } - } - - - private final String code; - private final String compression; - private final String dataType; - private final String provider; - private final boolean isLossless; - - AiffCompressionType(final String code, final String compression, final String dataType, final String provider, final boolean isLossless) - { - this.code = code; - this.compression = compression; - this.dataType = dataType; - this.provider=provider; - this.isLossless=isLossless; - } - - public String getCode() - { - return code; - } - - public String getCompression() - { - return compression; - } - - public boolean isLossless() - { - return isLossless; - } - - public String getDataType() - { - return dataType; - } - - public String getProvider() - { - return provider; - } - - public static AiffCompressionType getByCode(String code) - { - return lookup.get(code); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AnnotationChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AnnotationChunk.java deleted file mode 100644 index 06c67d92..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AnnotationChunk.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Contains a comment. Use of this chunk is discouraged within FORM AIFF. The more powerful {@link CommentsChunk} - * should be used instead. The Annotation Chunk is optional. Many Annotation Chunks may exist within a FORM AIFF. - * - * @see CommentsChunk - */ -public class AnnotationChunk extends TextChunk -{ - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader The AiffAudioHeader into which information is stored - */ - public AnnotationChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkHeader, chunkData, aiffAudioHeader); - } - - @Override - public boolean readChunk() throws IOException - { - aiffAudioHeader.addAnnotation(readChunkText()); - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ApplicationChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ApplicationChunk.java deleted file mode 100644 index 49b6fa7e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ApplicationChunk.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * The Application Chunk can be used for any purposes whatsoever by developers and application authors. For - * example, an application that edits sounds might want to use this chunk to store editor state parameters such as - * magnification levels, last cursor position, etc. - */ -public class ApplicationChunk extends Chunk -{ - private static final String SIGNATURE_PDOS = "pdos"; - private static final String SIGNATURE_STOC = "stoc"; - - private AiffAudioHeader aiffHeader; - - /** - * Constructor. - * - * @param chunkHeader The header for this chunk - * @param chunkData The file from which the AIFF data are being read - * @param aiffAudioHeader audio header - */ - public ApplicationChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkData, chunkHeader); - this.aiffHeader = aiffAudioHeader; - } - - /** - * 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 - { - final String applicationSignature = Utils.readFourBytesAsChars(chunkData); - String applicationName = null; - - /* 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 (SIGNATURE_STOC.equals(applicationSignature) || SIGNATURE_PDOS.equals(applicationSignature)) - { - applicationName = Utils.readPascalString(chunkData); - } - aiffHeader.addApplicationIdentifier(applicationSignature + ": " + applicationName); - - return true; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AuthorChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AuthorChunk.java deleted file mode 100644 index 99e84e88..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/AuthorChunk.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Contains one or more author names. An author in this case is the creator of a sampled sound. - * The Author Chunk is optional. No more than one Author Chunk may exist within a FORM AIFF. - */ -public class AuthorChunk extends TextChunk -{ - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader The AiffAudioHeader into which information is stored - */ - public AuthorChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkHeader, chunkData, aiffAudioHeader); - } - - @Override - public boolean readChunk() throws IOException - { - aiffAudioHeader.setAuthor(readChunkText()); - return true; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommentsChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommentsChunk.java deleted file mode 100644 index 02f9507e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommentsChunk.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.aiff.AiffUtil; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Date; - -/** - *

- * A comment consists of a time stamp, marker id, and a text count followed by text. - *

- *
- * typedef struct {
- *    unsigned long   timeStamp;
- *    MarkerID        marker;
- *    unsigned short  count;
- *    char            text[];
- * } Comment;
- * 
- *

- * {@code timeStamp} indicates when the comment was created. Units are the number of seconds - * since January 1, 1904. (This time convention is the one used by the Macintosh. For procedures - * that manipulate the time stamp, see The Operating System Utilities chapter in Inside Macintosh, - * vol II). For a routine that will convert this to an Apple II GS/OS format time, please see - * Apple II File Type Note for filetype 0xD8, aux type 0x0000. - *

- *

- * A comment can be linked to a marker. This allows applications to store long descriptions of - * markers as a comment. If the comment is referring to a marker, then marker is the ID of that - * marker. Otherwise, marker is zero, indicating that this comment is not linked to a marker. - *

- *

- * {@code count} is the length of the text that makes up the comment. This is a 16 bit quantity, - * allowing much longer comments than would be available with a pstring. - *

- *

- * {@code text} contains the comment itself. This text must be padded with a byte at the end to - * insure that it is an even number of bytes in length. This pad byte, if present, is not - * included in count. - *

- * - * @see AnnotationChunk - */ -public class CommentsChunk extends Chunk -{ - private static final int TIMESTAMP_LENGTH = 4; - private static final int MARKERID_LENGTH = 2; - private static final int COUNT_LENGTH = 2; - - private AiffAudioHeader aiffHeader; - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader audio header - */ - public CommentsChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkData, chunkHeader); - this.aiffHeader = aiffAudioHeader; - } - - /** - * Reads a chunk and extracts information. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public boolean readChunk() throws IOException - { - final int numComments = Utils.u(chunkData.getShort()); - - //For each comment - for (int i = 0; i < numComments; i++) - { - final long timestamp = Utils.u(chunkData.getInt()); - final Date jTimestamp = AiffUtil.timestampToDate(timestamp); - final int marker = Utils.u(chunkData.getShort()); - final int count = Utils.u(chunkData.getShort()); - // Append a timestamp to the comment - final String text = Utils.getString(chunkData, 0, count, StandardCharsets.ISO_8859_1) + " " + AiffUtil.formatDate(jTimestamp); - if (count % 2 != 0) { - // if count is odd, text is padded with an extra byte that we need to consume - chunkData.get(); - } - aiffHeader.addComment(text); - } - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommonChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommonChunk.java deleted file mode 100644 index 3731e4c2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CommonChunk.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.aiff.AiffType; -import com.mp3.jaudiotagger.audio.aiff.AiffUtil; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - The Common Chunk describes fundamental parameters of the waveform data such as sample rate, - bit resolution, and how many channels of digital audio are stored in the FORM AIFF. - */ -public class CommonChunk extends Chunk -{ - private AiffAudioHeader aiffHeader; - - /** - * - * @param hdr - * @param chunkData - * @param aiffAudioHeader - */ - public CommonChunk(ChunkHeader hdr, ByteBuffer chunkData, AiffAudioHeader aiffAudioHeader) - { - super(chunkData, hdr); - aiffHeader = aiffAudioHeader; - } - - - @Override - public boolean readChunk() throws IOException - { - - int numChannels = Utils.u(chunkData.getShort()); - long numSamples = chunkData.getInt(); - int bitsPerSample = Utils.u(chunkData.getShort()); - double sampleRate = AiffUtil.read80BitDouble(chunkData); - //Compression format, but not necessarily compressed - String compressionType; - String compressionName; - if (aiffHeader.getFileType() == AiffType.AIFC) - { - // This is a rather special case, but testing did turn up - // a file that misbehaved in this way. - if (chunkData.remaining()==0) - { - return false; - } - compressionType = Utils.readFourBytesAsChars(chunkData); - if (compressionType.equals(AiffCompressionType.SOWT.getCode())) - { - aiffHeader.setEndian(AiffAudioHeader.Endian.LITTLE_ENDIAN); - } - compressionName = Utils.readPascalString(chunkData); - // Proper handling of compression type should depend - // on whether raw output is set - if (compressionType != null) - { - //Is it a known compression type - AiffCompressionType act = AiffCompressionType.getByCode(compressionType); - if (act != null) - { - compressionName = act.getCompression(); - aiffHeader.setLossless(act.isLossless()); - // we assume that the bitrate is not variable, if there is no compression - if (act == AiffCompressionType.NONE) { - aiffHeader.setVariableBitRate(false); - } - } - else - { - // We don't know compression type, so we have to assume lossy compression as we know we are using AIFC format - aiffHeader.setLossless(false); - } - - if (compressionName.isEmpty()) - { - aiffHeader.setEncodingType(compressionType); - } - else - { - aiffHeader.setEncodingType(compressionName); - } - } - } - //Must be lossless - else - { - aiffHeader.setLossless(true); - aiffHeader.setEncodingType(AiffCompressionType.NONE.getCompression()); - // regular AIFF has no variable bit rate AFAIK - aiffHeader.setVariableBitRate(false); - } - - aiffHeader.setBitsPerSample(bitsPerSample); - aiffHeader.setSamplingRate((int) sampleRate); - aiffHeader.setChannelNumber(numChannels); - aiffHeader.setPreciseLength((numSamples / sampleRate)); - aiffHeader.setNoOfSamples(numSamples); - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CopyrightChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CopyrightChunk.java deleted file mode 100644 index c0bac4cb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/CopyrightChunk.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - *

- * The Copyright Chunk contains a copyright notice for the sound. text contains a date followed - * by the copyright owner. The chunk ID '(c) ' serves as the copyright characters '©'. For example, - * a Copyright Chunk containing the text "1988 Apple Computer, Inc." means "© 1988 Apple Computer, Inc." - *

- *

- * The Copyright Chunk is optional. No more than one Copyright Chunk may exist within a FORM AIFF. - *

- */ -public class CopyrightChunk extends TextChunk -{ - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader The AiffAudioHeader into which information is stored - */ - public CopyrightChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkHeader, chunkData, aiffAudioHeader); - } - - @Override - public boolean readChunk() throws IOException - { - aiffAudioHeader.setCopyright(readChunkText()); - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/FormatVersionChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/FormatVersionChunk.java deleted file mode 100644 index d0258d9f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/FormatVersionChunk.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.aiff.AiffUtil; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Date; - -/** - *

- * The Format Version Chunk contains a date field to indicate the format rules for an - * AIFF-C specification. This will enable smoother future upgrades to this specification. - *

- *

- * ckID is always 'FVER'. - *

- *

- * {@code ckDataSize} is the size of the data portion of the chunk, in bytes. It does not - * include the 8 bytes used by ckID and ckDataSize. For this Chunk, ckDataSize has a value of 4. - *

- *

- * {@code timeStamp} indicates when the format version for the AIFF-C file was created. - * Units are the number of seconds since January 1, 1904. (This time convention is the one - * used by the Macintosh. For procedures that manipulate the time stamp, see The Operating - * System Utilities chapter in Inside Macintosh, vol II ). For a routine that will convert - * this to an Apple II GS/OS format time, please see Apple II File Type Note for filetype - * 0xD8, aux type 0x0000. - *

- *

- * The Format Version Chunk is required. One and only one Format Version Chunk must appear in a FORM AIFC. - *

- */ -public class FormatVersionChunk extends Chunk -{ - private AiffAudioHeader aiffHeader; - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader The AiffTag into which information is stored - */ - public FormatVersionChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkData, chunkHeader); - this.aiffHeader = aiffAudioHeader; - } - - /** - * Reads a chunk and extracts information. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public boolean readChunk() throws IOException - { - final long rawTimestamp = chunkData.getInt(); - // The timestamp is in seconds since January 1, 1904. - // We must convert to Java time. - final Date timestamp = AiffUtil.timestampToDate(rawTimestamp); - aiffHeader.setTimestamp(timestamp); - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ID3Chunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ID3Chunk.java deleted file mode 100644 index 4d2e1807..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/ID3Chunk.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.aiff.AiffTag; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v22Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v23Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v24Tag; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Contains the ID3 tags. - */ -public class ID3Chunk extends Chunk -{ - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.aiff.chunk"); - private AiffTag aiffTag; - - /** - * Constructor. - * - * @param chunkHeader The header for this chunk - * @param chunkData The content of this chunk - * @param tag The AiffTag into which information is stored - */ - public ID3Chunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffTag tag) - { - super(chunkData, chunkHeader); - aiffTag = tag; - } - - @Override - public boolean readChunk() throws IOException - { - AudioFile.logger.severe("Reading chunk"); - if (!isId3v2Tag(chunkData)) - { - logger.severe("Invalid ID3 header for ID3 chunk"); - return false; - } - - final int version = chunkData.get(); - final AbstractID3v2Tag id3Tag; - switch (version) - { - case ID3v22Tag.MAJOR_VERSION: - id3Tag = new ID3v22Tag(); - AudioFile.logger.severe("Reading ID3V2.2 tag"); - break; - case ID3v23Tag.MAJOR_VERSION: - id3Tag = new ID3v23Tag(); - AudioFile.logger.severe("Reading ID3V2.3 tag"); - break; - case ID3v24Tag.MAJOR_VERSION: - id3Tag = new ID3v24Tag(); - AudioFile.logger.severe("Reading ID3V2.4 tag"); - break; - default: - return false; // bad or unknown version - } - - aiffTag.setID3Tag(id3Tag); - chunkData.position(0); - try - { - id3Tag.read(chunkData); - } - catch (TagException e) - { - AudioFile.logger.info("Exception reading ID3 tag: " + e.getClass().getName() + ": " + e.getMessage()); - return false; - } - return true; - } - - /** - * Reads 3 bytes to determine if the tag really looks like ID3 data. - */ - private boolean isId3v2Tag(final ByteBuffer headerData) throws IOException - { - for (int i = 0; i < AbstractID3v2Tag.FIELD_TAGID_LENGTH; i++) - { - if (headerData.get() != AbstractID3v2Tag.TAG_ID[i]) - { - return false; - } - } - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/NameChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/NameChunk.java deleted file mode 100644 index eb83030d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/NameChunk.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Contains the name of the sampled sound. The Name Chunk is optional. - * No more than one Name Chunk may exist within a FORM AIFF. - */ -public class NameChunk extends TextChunk -{ - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader The AiffAudioHeader into which information is stored - */ - public NameChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkHeader, chunkData, aiffAudioHeader); - } - - @Override - public boolean readChunk() throws IOException - { - aiffAudioHeader.setName(readChunkText()); - return true; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/SoundChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/SoundChunk.java deleted file mode 100644 index ab2263ba..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/SoundChunk.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Sound chunk. - * Doesn't actually read the content, but skips it. - */ -public class SoundChunk extends Chunk -{ - - /** - * @param chunkHeader The header for this chunk - * @param chunkData The file from which the AIFF data are being read - */ - public SoundChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData) - { - super(chunkData, chunkHeader); - } - - /** - * Reads a chunk and extracts information. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public boolean readChunk() throws IOException - { - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/TextChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/TextChunk.java deleted file mode 100644 index 0ca582eb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/aiff/chunk/TextChunk.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.mp3.jaudiotagger.audio.aiff.chunk; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.aiff.AiffAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Provides common functionality for textual chunks like {@link NameChunk}, {@link AuthorChunk}, - * {@link CopyrightChunk} and {@link AnnotationChunk}. - */ -public abstract class TextChunk extends Chunk -{ - protected final AiffAudioHeader aiffAudioHeader; - - /** - * Constructor. - * - * @param chunkHeader The header for this chunk - * @param chunkData The buffer from which the AIFF data are being read - * @param aiffAudioHeader aiff header - */ - public TextChunk(final ChunkHeader chunkHeader, final ByteBuffer chunkData, final AiffAudioHeader aiffAudioHeader) - { - super(chunkData, chunkHeader); - this.aiffAudioHeader = aiffAudioHeader; - } - - /** - * Reads the chunk and transforms it to a {@link String}. - * - * @return text string - * @throws IOException if the read fails - */ - protected String readChunkText() throws IOException { - // the spec actually only defines ASCII, not ISO_8859_1, but it probably does not hurt to be lenient - return Utils.getString(chunkData, 0, chunkData.remaining(), StandardCharsets.ISO_8859_1); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileReader.java deleted file mode 100644 index 11c39598..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileReader.java +++ /dev/null @@ -1,278 +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 com.mp3.jaudiotagger.audio.asf; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.asf.data.AudioStreamChunk; -import com.mp3.jaudiotagger.audio.asf.data.MetadataContainer; -import com.mp3.jaudiotagger.audio.asf.data.MetadataDescriptor; -import com.mp3.jaudiotagger.audio.asf.io.*; -import com.mp3.jaudiotagger.audio.asf.util.TagConverter; -import com.mp3.jaudiotagger.audio.asf.util.Utils; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.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("com.mp3.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 com.mp3.jaudiotagger.audio.generic.AudioFileReader#getEncodingInfo(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 com.mp3.jaudiotagger.audio.generic.AudioFileReader#getTag(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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileWriter.java deleted file mode 100644 index 3e913af9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/AsfFileWriter.java +++ /dev/null @@ -1,144 +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 com.mp3.jaudiotagger.audio.asf; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.asf.data.ChunkContainer; -import com.mp3.jaudiotagger.audio.asf.data.MetadataContainer; -import com.mp3.jaudiotagger.audio.asf.io.*; -import com.mp3.jaudiotagger.audio.asf.util.TagConverter; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.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(Tag tag, final RandomAccessFile raf, final RandomAccessFile tempRaf) throws CannotWriteException, IOException - { - writeTag(null, 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(AudioFile audioFile, 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfExtendedHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfExtendedHeader.java deleted file mode 100644 index 0ede862b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfExtendedHeader.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfHeader.java deleted file mode 100644 index 07238c50..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AsfHeader.java +++ /dev/null @@ -1,223 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AudioStreamChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AudioStreamChunk.java deleted file mode 100644 index 35e354cd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/AudioStreamChunk.java +++ /dev/null @@ -1,318 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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; - } - - /** - * @return Returns the bitsPerSample. - */ - public int getBitsPerSample() - { - return this.bitsPerSample; - } - - /** - * @return Returns the blockAlignment. - */ - public long getBlockAlignment() - { - return this.blockAlignment; - } - - /** - * @return Returns the channelCount. - */ - public long getChannelCount() - { - return this.channelCount; - } - - /** - * @return Returns the codecData. - */ - public byte[] getCodecData() - { - return this.codecData.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; - } - - /** - * @return Returns the errorConcealment. - */ - public GUID getErrorConcealment() - { - return this.errorConcealment; - } - - /** - * 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; - } - - /** - * 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(); - } - - /** - * @param avgeBytesPerSec The averageBytesPerSec to set. - */ - public void setAverageBytesPerSec(final long avgeBytesPerSec) - { - this.averageBytesPerSec = avgeBytesPerSec; - } - - /** - * Sets the bitsPerSample - * - * @param bps - */ - public void setBitsPerSample(final int bps) - { - this.bitsPerSample = bps; - } - - /** - * Sets the blockAlignment. - * - * @param align - */ - public void setBlockAlignment(final long align) - { - this.blockAlignment = align; - } - - /** - * @param channels The channelCount to set. - */ - public void setChannelCount(final long channels) - { - this.channelCount = channels; - } - - /** - * Sets the codecData - * - * @param codecSpecificData - */ - public void setCodecData(final byte[] codecSpecificData) - { - if (codecSpecificData == null) - { - throw new IllegalArgumentException(); - } - this.codecData = codecSpecificData.clone(); - } - - /** - * @param cFormatCode The compressionFormat to set. - */ - public void setCompressionFormat(final long cFormatCode) - { - this.compressionFormat = cFormatCode; - } - - /** - * 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; - } - - /** - * @param sampRate The samplingRate to set. - */ - public void setSamplingRate(final long sampRate) - { - this.samplingRate = sampRate; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/Chunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/Chunk.java deleted file mode 100644 index 6f909f32..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/Chunk.java +++ /dev/null @@ -1,183 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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; - } - - /** - * 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(); - } - - /** - * Sets the position. - * - * @param pos position to set. - */ - public void setPosition(final long pos) - { - this.position = pos; - } - - /** - * (overridden) - * - * @see Object#toString() - */ - @Override - public String toString() - { - return prettyPrint(""); - } - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ChunkContainer.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ChunkContainer.java deleted file mode 100644 index f6bb13b1..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ChunkContainer.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.audio.asf.util.ChunkPositionComparator; -import com.mp3.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); - } - - /** - * 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; - } - - /** - * 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>(); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContainerType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContainerType.java deleted file mode 100644 index d418c980..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContainerType.java +++ /dev/null @@ -1,284 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.audio.asf.util.Utils; -import com.mp3.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); - - /** - * 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}; - } - - /** - * 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} - */ - private 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; - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentBranding.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentBranding.java deleted file mode 100644 index 5a1e2f9b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentBranding.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.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); - } - - /** - * Returns the copyright URL. - * - * @return the banner image URL. - */ - public String getCopyRightURL() - { - return getValueFor(KEY_COPYRIGHT_URL); - } - - /** - * {@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); - } - - /** - * 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); - } - } - - /** - * 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); - } - } - - /** - * @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(StandardCharsets.US_ASCII)); - Utils.writeUINT32(getCopyRightURL().length(), out); - out.write(getCopyRightURL().getBytes(StandardCharsets.US_ASCII)); - return chunkSize; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentDescription.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentDescription.java deleted file mode 100644 index d7ae6143..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/ContentDescription.java +++ /dev/null @@ -1,254 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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); - } - - /** - * @return Returns the comment. - */ - public String getComment() - { - return getValueFor(KEY_DESCRIPTION); - } - - /** - * @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); - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return getValueFor(KEY_TITLE); - } - - /** - * {@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 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); - } - - /** - * @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); - } - - /** - * @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); - } - - /** - * @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); - } - - /** - * @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 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncodingChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncodingChunk.java deleted file mode 100644 index 6cd9b218..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncodingChunk.java +++ /dev/null @@ -1,91 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncryptionChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncryptionChunk.java deleted file mode 100644 index 731c59cc..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/EncryptionChunk.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.audio.asf.util.Utils; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collection; - -/** - * @author eric - */ -public class EncryptionChunk extends Chunk -{ - private String keyID; - - private String licenseURL; - private String protectionType; - private String secretData; - /** - * The read strings. - */ - private final ArrayList strings; - - /** - * 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 gets the license URL. - * - * @return - */ - public String getLicenseURL() - { - return this.licenseURL; - } - - /** - * This method gets the secret data. - * - * @return - */ - public String getProtectionType() - { - return this.protectionType; - } - - /** - * This method gets the secret data. - * - * @return - */ - public String getSecretData() - { - return this.secretData; - } - - /** - * 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(); - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void setKeyID(final String toAdd) - { - this.keyID = toAdd; - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void setLicenseURL(final String toAdd) - { - this.licenseURL = toAdd; - } - - /** - * This method appends a String. - * - * @param toAdd String to add. - */ - public void setProtectionType(final String toAdd) - { - this.protectionType = toAdd; - } - - /** - * This method adds the secret data. - * - * @param toAdd String to add. - */ - public void setSecretData(final String toAdd) - { - this.secretData = toAdd; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/FileHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/FileHeader.java deleted file mode 100644 index c7578bbf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/FileHeader.java +++ /dev/null @@ -1,238 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUID.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUID.java deleted file mode 100644 index 510339a4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUID.java +++ /dev/null @@ -1,520 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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"); - - /** - * 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 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 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; - - /** - * 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"); - - 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); - } - } - - /** - * 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); - } - - /** - * 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 compares two objects. If the given Object is a {@link GUID}, - * the stored GUID values are compared.
- * - * @see Object#equals(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; - } - - /** - * 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(); - } - - /** - * 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."); - } - } - - /** - * {@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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUIDFormatException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUIDFormatException.java deleted file mode 100644 index 74b8a7b6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/GUIDFormatException.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/LanguageList.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/LanguageList.java deleted file mode 100644 index eb96d985..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/LanguageList.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.audio.asf.util.Utils; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainer.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainer.java deleted file mode 100644 index 482e6df4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainer.java +++ /dev/null @@ -1,477 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.audio.asf.io.WriteableChunk; -import com.mp3.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 -{ - - /** - * 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; - } - } - - /** - * 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; - } - - /** - * 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); - } - - /** - * 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; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainerFactory.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainerFactory.java deleted file mode 100644 index 84177687..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataContainerFactory.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.mp3.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(); - - /** - * Returns an instance. - * - * @return an instance. - */ - public static MetadataContainerFactory getInstance() - { - return INSTANCE; - } - - /** - * Hidden utility class constructor. - */ - private MetadataContainerFactory() - { - // Hidden - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataDescriptor.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataDescriptor.java deleted file mode 100644 index 3399599e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/MetadataDescriptor.java +++ /dev/null @@ -1,940 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.jaudiotagger.audio.asf.util.Utils; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.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(); - - /** - * Logger instance. - */ - private static final Logger LOGGER = Logger.getLogger("com.mp3.jaudiotagger.audio.asf.data"); - - /** - * 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; - - /** - * Stores the containerType of the descriptor. - */ - private final ContainerType containerType; - - /** - * 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 name of the metadata descriptor. - */ - private final String name; - - /** - * 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 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 Object#equals(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; - } - - /** - * 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; - } - - /** - * 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; - } - - /** - * 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 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; - } - - /** - * 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 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; - } - - /** - * 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); - } - } - - /** - * 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 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java deleted file mode 100644 index 9695b011..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamBitratePropertiesChunk.java +++ /dev/null @@ -1,112 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamChunk.java deleted file mode 100644 index e32dd617..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/StreamChunk.java +++ /dev/null @@ -1,192 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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 -{ - - /** - * 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 stream type.
- * - * @see GUID#GUID_AUDIOSTREAM - * @see GUID#GUID_VIDEOSTREAM - */ - private final GUID type; - - /** - * 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; - } - - /** - * @return Returns the streamSpecificDataSize. - */ - public long getStreamSpecificDataSize() - { - return this.streamSpecificDataSize; - } - - /** - * 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; - } - - /** - * @return Returns the typeSpecificDataSize. - */ - public long getTypeSpecificDataSize() - { - return this.typeSpecificDataSize; - } - - /** - * @return Returns the contentEncrypted. - */ - public boolean isContentEncrypted() - { - return this.contentEncrypted; - } - - /** - * (overridden) - * - * @see 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(); - } - - /** - * @param cntEnc The contentEncrypted to set. - */ - public void setContentEncrypted(final boolean cntEnc) - { - this.contentEncrypted = cntEnc; - } - - /** - * @param streamNum The streamNumber to set. - */ - public void setStreamNumber(final int streamNum) - { - this.streamNumber = streamNum; - } - - /** - * @param strSpecDataSize The streamSpecificDataSize to set. - */ - public void setStreamSpecificDataSize(final long strSpecDataSize) - { - this.streamSpecificDataSize = strSpecDataSize; - } - - /** - * @param timeOffs sets the time offset - */ - public void setTimeOffset(final long timeOffs) - { - this.timeOffset = timeOffs; - } - - /** - * @param typeSpecDataSize The typeSpecificDataSize to set. - */ - public void setTypeSpecificDataSize(final long typeSpecDataSize) - { - this.typeSpecificDataSize = typeSpecDataSize; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/VideoStreamChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/VideoStreamChunk.java deleted file mode 100644 index ae4c874f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/data/VideoStreamChunk.java +++ /dev/null @@ -1,140 +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 com.mp3.jaudiotagger.audio.asf.data; - -import com.mp3.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(); - } - - /** - * 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; - } - - /** - * @return Returns the pictureWidth. - */ - public long getPictureWidth() - { - return this.pictureWidth; - } - - /** - * (overridden) - * - * @see 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(); - } - - /** - * @param codecIdentifier The codecId to set. - */ - public void setCodecId(final byte[] codecIdentifier) - { - this.codecId = codecIdentifier.clone(); - } - - /** - * @param picHeight - */ - public void setPictureHeight(final long picHeight) - { - this.pictureHeight = picHeight; - } - - /** - * @param picWidth - */ - public void setPictureWidth(final long picWidth) - { - this.pictureWidth = picWidth; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java deleted file mode 100644 index 14084524..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderModifier.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java deleted file mode 100644 index 2cf5486a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfExtHeaderReader.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.AsfExtendedHeader; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfHeaderReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfHeaderReader.java deleted file mode 100644 index b0fd3ea9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfHeaderReader.java +++ /dev/null @@ -1,236 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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 com.mp3.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 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); - } - - /** - * 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); - } - - /** - * {@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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfStreamer.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfStreamer.java deleted file mode 100644 index f704aa51..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/AsfStreamer.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkContainerReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkContainerReader.java deleted file mode 100644 index 65b58669..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkContainerReader.java +++ /dev/null @@ -1,231 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.ChunkContainer; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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 -{ - - /** - * Logger - */ - protected static final Logger LOGGER = Logger.getLogger("org.jaudiotabgger.audio"); //$NON-NLS-1$ - - /** - * Within this range, a {@link ChunkReader} should be aware if it fails. - */ - public final static int READ_LIMIT = 8192; - - /** - * If true each chunk type will only be read once.
- */ - protected final boolean eachChunkOnce; - - /** - * 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; - - /** - * Registers GUIDs to their reader classes.
- */ - protected final Map readerMap = new HashMap(); - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkHeaderReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkHeaderReader.java deleted file mode 100644 index da81c1b9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkHeaderReader.java +++ /dev/null @@ -1,93 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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 com.mp3.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(); - - /** - * Returns an instance of the reader. - * - * @return instance. - */ - public static ChunkHeaderReader getInstance() - { - return INSTANCE; - } - - /** - * Hidden Utility class constructor. - */ - private ChunkHeaderReader() - { - // Hidden - } - - /** - * {@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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkModifier.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkModifier.java deleted file mode 100644 index 70859808..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkModifier.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkReader.java deleted file mode 100644 index c644e500..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkReader.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkRemover.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkRemover.java deleted file mode 100644 index c87f99a7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ChunkRemover.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentBrandingReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentBrandingReader.java deleted file mode 100644 index 3d3be801..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentBrandingReader.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.ContentBranding; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentDescriptionReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentDescriptionReader.java deleted file mode 100644 index 9dfa3eeb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ContentDescriptionReader.java +++ /dev/null @@ -1,134 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.ContentDescription; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingInputStream.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingInputStream.java deleted file mode 100644 index e721ad0d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingInputStream.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingOutputstream.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingOutputstream.java deleted file mode 100644 index ba93dc04..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/CountingOutputstream.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.mp3.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 -{ - - /** - * Stores the amount of bytes written. - */ - private long count = 0; - - /** - * The stream to forward the write calls. - */ - private final OutputStream wrapped; - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncodingChunkReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncodingChunkReader.java deleted file mode 100644 index 6604ff43..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncodingChunkReader.java +++ /dev/null @@ -1,105 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.EncodingChunk; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncryptionChunkReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncryptionChunkReader.java deleted file mode 100644 index 10152237..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/EncryptionChunkReader.java +++ /dev/null @@ -1,132 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.EncryptionChunk; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FileHeaderReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FileHeaderReader.java deleted file mode 100644 index 1162a75d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FileHeaderReader.java +++ /dev/null @@ -1,96 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.FileHeader; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FullRequestInputStream.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FullRequestInputStream.java deleted file mode 100644 index 1434580f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/FullRequestInputStream.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/LanguageListReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/LanguageListReader.java deleted file mode 100644 index 33bcb32c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/LanguageListReader.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.jaudiotagger.audio.asf.data.LanguageList; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/MetadataReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/MetadataReader.java deleted file mode 100644 index be127d96..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/MetadataReader.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.*; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ModificationResult.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ModificationResult.java deleted file mode 100644 index 5feeb4ab..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/ModificationResult.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java deleted file mode 100644 index eecc4028..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileInputstream.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java deleted file mode 100644 index 448af6b4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/RandomAccessFileOutputStream.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java deleted file mode 100644 index 02056055..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamBitratePropertiesReader.java +++ /dev/null @@ -1,91 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.jaudiotagger.audio.asf.data.StreamBitratePropertiesChunk; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamChunkReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamChunkReader.java deleted file mode 100644 index df8cb432..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/StreamChunkReader.java +++ /dev/null @@ -1,191 +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 com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.*; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunk.java deleted file mode 100644 index a30b0125..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunk.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunkModifer.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunkModifer.java deleted file mode 100644 index b6860e4b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/io/WriteableChunkModifer.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.mp3.jaudiotagger.audio.asf.io; - -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/ChunkPositionComparator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/ChunkPositionComparator.java deleted file mode 100644 index 9de68289..00000000 --- a/jaudiotagger/src/main/java/com/mp3/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 com.mp3.jaudiotagger.audio.asf.util; - -import com.mp3.jaudiotagger.audio.asf.data.Chunk; - -import java.io.Serializable; -import java.util.Comparator; - -/** - * This class is needed for ordering all types of - * {@link 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/TagConverter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/TagConverter.java deleted file mode 100644 index 0b8fe071..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/TagConverter.java +++ /dev/null @@ -1,204 +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 com.mp3.jaudiotagger.audio.asf.util; - -import com.mp3.jaudiotagger.audio.asf.data.*; -import com.mp3.jaudiotagger.tag.FieldKey; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.asf.*; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; - -import java.util.Iterator; -import java.util.List; - -/** - * This class provides functionality to convert - * {@link AsfHeader}objects into - * {@link Tag}objects.
- * - * @author Christian Laireiter (liree) - */ -public final class TagConverter -{ - - /** - * 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; - } - - /** - * Hidden utility class constructor. - */ - private TagConverter() - { - // Nothing to do. - } - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/Utils.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/Utils.java deleted file mode 100644 index 995d4eb6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/asf/util/Utils.java +++ /dev/null @@ -1,536 +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 com.mp3.jaudiotagger.audio.asf.util; - -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.asf.data.GUID; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsdChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsdChunk.java deleted file mode 100644 index edbe8e04..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsdChunk.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.mp3.jaudiotagger.audio.dsf; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * DSD Chunk - */ -public class DsdChunk -{ - private long chunkSizeLength; - private long fileLength; - private long metadataOffset; - - public static final int CHUNKSIZE_LENGTH = 8; - public static final int FILESIZE_LENGTH = 8; - public static final int METADATA_OFFSET_LENGTH = 8; - public static final int FMT_CHUNK_MIN_DATA_SIZE_ = 40; - - public static final int DSD_HEADER_LENGTH = IffHeaderChunk.SIGNATURE_LENGTH + CHUNKSIZE_LENGTH + FILESIZE_LENGTH + METADATA_OFFSET_LENGTH; - - public static DsdChunk readChunk(ByteBuffer dataBuffer) - { - String type = Utils.readFourBytesAsChars(dataBuffer); - if (DsfChunkType.DSD.getCode().equals(type)) - { - return new DsdChunk(dataBuffer); - } - return null; - } - - private DsdChunk(ByteBuffer dataBuffer) - { - chunkSizeLength = dataBuffer.getLong(); - fileLength = dataBuffer.getLong(); - metadataOffset = dataBuffer.getLong(); - } - - public String toString() - { - - return "ChunkSize:"+chunkSizeLength - + ":fileLength:"+fileLength - + ":metadata:"+metadataOffset; - - } - - public long getChunkSizeLength() - { - return chunkSizeLength; - } - - public void setChunkSizeLength(long chunkSizeLength) - { - this.chunkSizeLength = chunkSizeLength; - } - - public long getFileLength() - { - return fileLength; - } - - public void setFileLength(long fileLength) - { - this.fileLength = fileLength; - } - - public long getMetadataOffset() - { - return metadataOffset; - } - - public void setMetadataOffset(long metadataOffset) - { - this.metadataOffset = metadataOffset; - } - - /** - * Write new DSDchunk to buffer - * - * @return - */ - public ByteBuffer write() - { - ByteBuffer buffer = ByteBuffer.allocateDirect(DSD_HEADER_LENGTH); - buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.put(DsfChunkType.DSD.getCode().getBytes(StandardCharsets.US_ASCII)); - buffer.putLong(chunkSizeLength); - buffer.putLong(fileLength); - buffer.putLong(metadataOffset); - buffer.flip(); - return buffer; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/Dsf.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/Dsf.java deleted file mode 100644 index 4aade677..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/Dsf.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mp3.jaudiotagger.audio.dsf; - -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.ID3v22Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v23Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v24Tag; -import com.mp3.jaudiotagger.tag.reference.ID3V2Version; - -/** - * Created by Paul on 28/01/2016. - */ -public class Dsf -{ - public static 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfChunkType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfChunkType.java deleted file mode 100644 index 80bbf7f1..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfChunkType.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.mp3.jaudiotagger.audio.dsf; - -import java.util.HashMap; -import java.util.Map; - -/** - * Chunk types mark each {@link com.mp3.jaudiotagger.audio.iff.ChunkHeader}. They are always 4 ASCII chars long. - * - * @see com.mp3.jaudiotagger.audio.iff.Chunk - */ -public enum DsfChunkType -{ - DSD("DSD "), - FORMAT("fmt "), - DATA("data"), - ID3("ID3"), - ; - - private static final Map CODE_TYPE_MAP = new HashMap(); - private String code; - - /** - * @param code 4 char string - */ - DsfChunkType(final String code) - { - this.code=code; - } - - /** - * Get {@link DsfChunkType} for code (e.g. "SSND"). - * - * @param code chunk id - * @return chunk type or {@code null} if not registered - */ - public synchronized static DsfChunkType get(final String code) { - if (CODE_TYPE_MAP.isEmpty()) { - for (final DsfChunkType type : values()) { - CODE_TYPE_MAP.put(type.getCode(), type); - } - } - return CODE_TYPE_MAP.get(code); - } - - /** - * 4 char type code. - * - * @return 4 char type code, e.g. "SSND" for the sound chunk. - */ - public String getCode() - { - return code; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileReader.java deleted file mode 100644 index 03a1cb85..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileReader.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Created on 03.05.2015 - * Author: Veselin Markov. - */ -package com.mp3.jaudiotagger.audio.dsf; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader2; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v22Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v23Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v24Tag; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Level; - -import static com.mp3.jaudiotagger.audio.dsf.DsdChunk.CHUNKSIZE_LENGTH; - -/** - * Reads the ID3 Tags as specified by DSFFileFormatSpec_E.pdf . - * - * @author Veselin Markov (veselin_m84 a_t yahoo.com) - */ -public class DsfFileReader extends AudioFileReader2 { - - @Override - protected GenericAudioHeader getEncodingInfo(File file) throws CannotReadException, IOException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - DsdChunk dsd = DsdChunk.readChunk(Utils.readFileDataIntoBufferLE(fc, DsdChunk.DSD_HEADER_LENGTH)); - if (dsd != null) { - ByteBuffer fmtChunkBuffer = Utils.readFileDataIntoBufferLE(fc, IffHeaderChunk.SIGNATURE_LENGTH + CHUNKSIZE_LENGTH); - FmtChunk fmt = FmtChunk.readChunkHeader(fmtChunkBuffer); - if (fmt != null) { - return fmt.readChunkData(dsd, fc); - } else { - throw new CannotReadException(file + " Not a valid dsf file. Content does not include 'fmt ' chunk"); - } - } else { - throw new CannotReadException(file + " Not a valid dsf file. Content does not start with 'DSD '"); - } - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - @Override - protected Tag getTag(File file) throws CannotReadException, IOException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - DsdChunk dsd = DsdChunk.readChunk(Utils.readFileDataIntoBufferLE(fc, DsdChunk.DSD_HEADER_LENGTH)); - if (dsd != null) { - return readTag(fc, dsd, file.toString()); - } else { - throw new CannotReadException(file + " Not a valid dsf file. Content does not start with 'DSD '."); - } - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Reads the ID3v2 tag starting at the {@code tagOffset} position in the - * supplied file. - * - * @param fc the filechannel from which to read - * @param dsd the dsd chunk - * @param fileName - * @return the read tag or an empty tag if something went wrong. Never - * null. - * @throws IOException if cannot read file. - */ - private Tag readTag(FileChannel fc, DsdChunk dsd, String fileName) throws CannotReadException, IOException { - if (dsd.getMetadataOffset() > 0) { - fc.position(dsd.getMetadataOffset()); - ID3Chunk id3Chunk = ID3Chunk.readChunk(Utils.readFileDataIntoBufferLE(fc, (int) (fc.size() - fc.position()))); - if (id3Chunk != null) { - int version = id3Chunk.getDataBuffer().get(AbstractID3v2Tag.FIELD_TAG_MAJOR_VERSION_POS); - try { - switch (version) { - case ID3v22Tag.MAJOR_VERSION: - return new ID3v22Tag(id3Chunk.getDataBuffer(), ""); - case ID3v23Tag.MAJOR_VERSION: - return new ID3v23Tag(id3Chunk.getDataBuffer(), ""); - case ID3v24Tag.MAJOR_VERSION: - return new ID3v24Tag(id3Chunk.getDataBuffer(), ""); - default: - logger.log(Level.WARNING, fileName + " Unknown ID3v2 version " + version + ". Returning an empty ID3v2 Tag."); - return null; - } - } catch (TagException e) { - throw new CannotReadException(fileName + " Could not read ID3v2 tag:corruption"); - } - } else { - logger.log(Level.WARNING, fileName + " No existing ID3 tag(1)"); - return null; - } - } else { - logger.log(Level.WARNING, fileName + " No existing ID3 tag(2)"); - return null; - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileWriter.java deleted file mode 100644 index c48956df..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/DsfFileWriter.java +++ /dev/null @@ -1,151 +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 com.mp3.jaudiotagger.audio.dsf; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter2; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Tag; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - -/** - * Write/delete tag info for Dsf file - */ -public class DsfFileWriter extends AudioFileWriter2 { - - protected void writeTag(Tag tag, File file) throws CannotWriteException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - DsdChunk dsd = DsdChunk.readChunk(Utils.readFileDataIntoBufferLE(fc, DsdChunk.DSD_HEADER_LENGTH)); - if (dsd != null) { - if (dsd.getMetadataOffset() > 0) { - fc.position(dsd.getMetadataOffset()); - ID3Chunk id3Chunk = ID3Chunk.readChunk(Utils.readFileDataIntoBufferLE(fc, (int) (fc.size() - fc.position()))); - if (id3Chunk != null) { - //Remove Existing tag - fc.position(dsd.getMetadataOffset()); - final ByteBuffer bb = convert((AbstractID3v2Tag) tag); - fc.write(bb); - } else { - throw new CannotWriteException(file + "Could not find existing ID3v2 Tag"); - } - } else { - //Write new tag and new offset and size - fc.position(fc.size()); - dsd.setMetadataOffset(fc.size()); - final ByteBuffer bb = convert((AbstractID3v2Tag) tag); - fc.write(bb); - dsd.setFileLength(fc.size()); - fc.position(0); - fc.write(dsd.write()); - } - } - } catch (IOException ioe) { - throw new CannotWriteException(ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Convert ID3 tag into a ByteBuffer, also ensures always even to avoid problems - * - * @param tag - * @return - * @throws UnsupportedEncodingException - */ - public ByteBuffer convert(final AbstractID3v2Tag tag) throws UnsupportedEncodingException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - long existingTagSize = tag.getSize(); - - //If existingTag is uneven size lets make it even - if (existingTagSize > 0) { - if (Utils.isOddLength(existingTagSize)) { - existingTagSize++; - } - } - - //Write Tag to buffer - tag.write(baos, (int) existingTagSize); - - //If the tag is now odd because we needed to increase size and the data made it odd sized - //we redo adding a padding byte to make it even - if ((baos.toByteArray().length & 1) != 0) { - int newSize = baos.toByteArray().length + 1; - baos = new ByteArrayOutputStream(); - tag.write(baos, newSize); - } - final 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); - } - } - - /** - * Delete Metadata tag - * - * @param tag - * @param file - * @throws CannotWriteException - * @throws IOException - */ - @Override - protected void deleteTag(Tag tag, File file) throws CannotWriteException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - DsdChunk dsd = DsdChunk.readChunk(Utils.readFileDataIntoBufferLE(fc, DsdChunk.DSD_HEADER_LENGTH)); - if (dsd != null) { - if (dsd.getMetadataOffset() > 0) { - fc.position(dsd.getMetadataOffset()); - ID3Chunk id3Chunk = ID3Chunk.readChunk(Utils.readFileDataIntoBufferLE(fc, (int) (fc.size() - fc.position()))); - if (id3Chunk != null) { - fc.truncate(dsd.getMetadataOffset()); - //set correct value for fileLength and zero offset - dsd.setMetadataOffset(0); - dsd.setFileLength(fc.size()); - fc.position(0); - fc.write(dsd.write()); - } - } else { - //Do Nothing; - } - } - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/FmtChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/FmtChunk.java deleted file mode 100644 index a51162ed..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/FmtChunk.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.mp3.jaudiotagger.audio.dsf; - -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static com.mp3.jaudiotagger.audio.dsf.DsdChunk.CHUNKSIZE_LENGTH; - - -/** - * Created by Paul on 25/01/2016. - */ -public class FmtChunk -{ - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.dsf.FmtChunk"); - - public static final int FMT_CHUNK_MIN_DATA_SIZE_ = 40; - private long chunkSizeLength; - - public static FmtChunk readChunkHeader(ByteBuffer dataBuffer) - { - String type = Utils.readFourBytesAsChars(dataBuffer); - if (DsfChunkType.FORMAT.getCode().equals(type)) - { - return new FmtChunk(dataBuffer); - } - return null; - } - - private FmtChunk(ByteBuffer dataBuffer) - { - chunkSizeLength = dataBuffer.getLong(); - } - - public GenericAudioHeader readChunkData(DsdChunk dsd,FileChannel fc) throws IOException - { - long sizeExcludingChunkHeader = chunkSizeLength - (IffHeaderChunk.SIGNATURE_LENGTH + CHUNKSIZE_LENGTH); - ByteBuffer audioData = Utils.readFileDataIntoBufferLE(fc, (int)sizeExcludingChunkHeader); - return readAudioInfo(dsd, audioData); - } - - /** - * @param audioInfoChunk contains the bytes from "format version" up to "reserved" - * fields - * @return an empty {@link com.mp3.jaudiotagger.audio.generic.GenericAudioHeader} if audioInfoChunk has less - * than 40 bytes, the read data otherwise. Never null. - */ - @SuppressWarnings("unused") - private GenericAudioHeader readAudioInfo(DsdChunk dsd, ByteBuffer audioInfoChunk) - { - GenericAudioHeader audioHeader = new GenericAudioHeader(); - if (audioInfoChunk.limit() < FMT_CHUNK_MIN_DATA_SIZE_) - { - logger.log(Level.WARNING, "Not enough bytes supplied for Generic audio header. Returning an empty one."); - return audioHeader; - } - - audioInfoChunk.order(ByteOrder.LITTLE_ENDIAN); - int version = audioInfoChunk.getInt(); - int formatId =audioInfoChunk.getInt(); - int channelType =audioInfoChunk.getInt(); - int channelNumber = audioInfoChunk.getInt(); - int samplingFreqency = audioInfoChunk.getInt(); - int bitsPerSample =audioInfoChunk.getInt(); - long sampleCount = audioInfoChunk.getLong(); - int blocksPerSample = audioInfoChunk.getInt(); - - audioHeader.setEncodingType("DSF"); - audioHeader.setBitRate(bitsPerSample * samplingFreqency * channelNumber); - audioHeader.setBitsPerSample(bitsPerSample); - audioHeader.setChannelNumber(channelNumber); - audioHeader.setSamplingRate(samplingFreqency); - audioHeader.setNoOfSamples(sampleCount); - audioHeader.setPreciseLength((float) sampleCount / samplingFreqency); - audioHeader.setVariableBitRate(false); - logger.log(Level.FINE, "Created audio header: " + audioHeader); - return audioHeader; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/ID3Chunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/ID3Chunk.java deleted file mode 100644 index ba70c716..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/dsf/ID3Chunk.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.mp3.jaudiotagger.audio.dsf; - -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Created by Paul on 28/01/2016. - */ -public class ID3Chunk -{ - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.generic.ID3Chunk"); - - private ByteBuffer dataBuffer; - public static ID3Chunk readChunk(ByteBuffer dataBuffer) - { - String type = Utils.readThreeBytesAsChars(dataBuffer); - if (DsfChunkType.ID3.getCode().equals(type)) - { - return new ID3Chunk(dataBuffer); - } - logger.log(Level.WARNING,"Invalid type:"+type+" where expected ID3 tag"); - return null; - } - - public ID3Chunk(ByteBuffer dataBuffer) - { - this.dataBuffer = dataBuffer; - } - - public ByteBuffer getDataBuffer() - { - return dataBuffer; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadException.java deleted file mode 100644 index 4524a594..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadException.java +++ /dev/null @@ -1,62 +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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadVideoException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadVideoException.java deleted file mode 100644 index b22f5aed..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotReadVideoException.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotWriteException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotWriteException.java deleted file mode 100644 index f66e5609..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/CannotWriteException.java +++ /dev/null @@ -1,73 +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 com.mp3.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(String) - */ - public CannotWriteException(String message) - { - super(message); - } - - /** - * (overridden) - * - * @param message - * @param cause - * @see Exception#Exception(String,Throwable) - */ - public CannotWriteException(String message, Throwable cause) - { - super(message, cause); - } - - /** - * (overridden) - * - * @param cause - * @see Exception#Exception(Throwable) - */ - public CannotWriteException(Throwable cause) - { - super(cause); - - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java deleted file mode 100644 index 8e217dbe..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidAudioFrameException.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * Date :${DATE} - * - * Jaikoz Copyright Copyright (C) 2003 -2005 JThink Ltd - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java deleted file mode 100644 index 5b3b138a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/InvalidBoxHeaderException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ModifyVetoException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ModifyVetoException.java deleted file mode 100644 index a2ae8346..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ModifyVetoException.java +++ /dev/null @@ -1,77 +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 com.mp3.jaudiotagger.audio.exceptions; - - -/** - * This exception is thrown if a - * {@link com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener} wants to - * prevent; from actually finishing its - * operation.
- * This exception can be used in all methods but - * {@link com.mp3.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(String) - */ - public ModifyVetoException(String message) - { - super(message); - } - - /** - * (overridden) - * - * @param message - * @param cause - * @see Exception#Exception(String,Throwable) - */ - public ModifyVetoException(String message, Throwable cause) - { - super(message, cause); - } - - /** - * (overridden) - * - * @param cause - * @see Exception#Exception(Throwable) - */ - public ModifyVetoException(Throwable cause) - { - super(cause); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoReadPermissionsException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoReadPermissionsException.java deleted file mode 100644 index a04930a2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoReadPermissionsException.java +++ /dev/null @@ -1,60 +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 com.mp3.jaudiotagger.audio.exceptions; - -/** - * Use this exception insstead of the more general CannotReadException if unable to read file because of a permissions - * problem - */ -public class NoReadPermissionsException extends CannotReadException -{ - /** - * Creates an instance. - */ - public NoReadPermissionsException() - { - super(); - } - - public NoReadPermissionsException(Throwable ex) - { - super(ex); - } - - /** - * Creates an instance. - * - * @param message The message. - */ - public NoReadPermissionsException(String message) - { - super(message); - } - - /** - * Creates an instance. - * - * @param message The error message. - * @param cause The throwable causing this exception. - */ - public NoReadPermissionsException(String message, Throwable cause) - { - super(message, cause); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoWritePermissionsException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoWritePermissionsException.java deleted file mode 100644 index 633a6f9e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NoWritePermissionsException.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.mp3.jaudiotagger.audio.exceptions; - -/** - * Use this exception instead of the more general CannotWriteException if unable to write file because of a permissions - * problem - */ -public class NoWritePermissionsException extends CannotWriteException -{ - /** - * Creates an instance. - */ - public NoWritePermissionsException() - { - super(); - } - - public NoWritePermissionsException(Throwable ex) - { - super(ex); - } - - /** - * Creates an instance. - * - * @param message The message. - */ - public NoWritePermissionsException(String message) - { - super(message); - } - - /** - * Creates an instance. - * - * @param message The error message. - * @param cause The throwable causing this exception. - */ - public NoWritePermissionsException(String message, Throwable cause) - { - super(message, cause); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NullBoxIdException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NullBoxIdException.java deleted file mode 100644 index a70e15f4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/NullBoxIdException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ReadOnlyFileException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ReadOnlyFileException.java deleted file mode 100644 index 1b7e8c0b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/ReadOnlyFileException.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToCreateFileException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToCreateFileException.java deleted file mode 100644 index 27c855c9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToCreateFileException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToModifyFileException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToModifyFileException.java deleted file mode 100644 index d36ad2f9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToModifyFileException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mp3.jaudiotagger.audio.exceptions; - -import java.io.IOException; - -/** - * Should be thrown when unable to modify a file when it is expected it should be modifiable. 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToRenameFileException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToRenameFileException.java deleted file mode 100644 index 46e7bf11..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/exceptions/UnableToRenameFileException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacAudioHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacAudioHeader.java deleted file mode 100644 index fe7e3145..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacAudioHeader.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mp3.jaudiotagger.audio.flac; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileReader.java deleted file mode 100644 index 9e7590b7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/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 com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader2; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.tag.Tag; - -import java.io.File; -import java.io.IOException; - -/** - * Read encoding and tag info for Flac file (open source lossless encoding) - */ -public class FlacFileReader extends AudioFileReader2 { - - private FlacInfoReader ir = new FlacInfoReader(); - private FlacTagReader tr = new FlacTagReader(); - - protected GenericAudioHeader getEncodingInfo(File file) throws CannotReadException, IOException { - return ir.read(file); - } - - protected Tag getTag(File file) throws CannotReadException, IOException { - return tr.read(file); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileWriter.java deleted file mode 100644 index 485e1709..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacFileWriter.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 com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter2; -import com.mp3.jaudiotagger.tag.Tag; - -import java.io.File; - - -/** - * Write/delete tag info for Flac file (opensource lossless encoding) - */ -public class FlacFileWriter extends AudioFileWriter2 -{ - - private FlacTagWriter tw = new FlacTagWriter(); - - @Override - protected void writeTag(Tag tag, File file) throws CannotWriteException - { - tw.write(tag, file); - } - - @Override - protected void deleteTag(Tag tag, File file) throws CannotWriteException - { - tw.delete(tag, file); - } - - -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacInfoReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacInfoReader.java deleted file mode 100644 index 6ffdce14..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacInfoReader.java +++ /dev/null @@ -1,132 +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 com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.flac.metadatablock.BlockType; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataStreamInfo; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Read info from Flac file - */ -public class FlacInfoReader { - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.flac"); - - - public FlacAudioHeader read(File file) throws CannotReadException, IOException { - logger.config(file.getPath() + ":start"); - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - FlacStreamReader flacStream = new FlacStreamReader(fc, file.getPath()); - 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 == false) { - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(fc); - logger.info(file.getPath() + " " + mbh.toString()); - if (mbh.getBlockType() == BlockType.STREAMINFO) { - mbdsi = new MetadataBlockDataStreamInfo(mbh, fc); - if (!mbdsi.isValid()) { - throw new CannotReadException(file.getPath() + ":FLAC StreamInfo not valid"); - } - } else { - fc.position(fc.position() + mbh.getDataLength()); - } - isLastBlock = mbh.isLastBlock(); - } - - //Audio continues from this point to end of file (normally - TODO might need to allow for an ID3v1 tag at file end ?) - long streamStart = fc.position(); - - if (mbdsi == null) { - throw new CannotReadException(file.getPath() + ":Unable to find Flac StreamInfo"); - } - - FlacAudioHeader info = new FlacAudioHeader(); - info.setNoOfSamples(mbdsi.getNoOfSamples()); - info.setPreciseLength(mbdsi.getPreciseLength()); - info.setChannelNumber(mbdsi.getNoOfChannels()); - info.setSamplingRate(mbdsi.getSamplingRate()); - info.setBitsPerSample(mbdsi.getBitsPerSample()); - info.setEncodingType(mbdsi.getEncodingType()); - info.setLossless(true); - info.setMd5(mbdsi.getMD5Signature()); - info.setAudioDataLength(fc.size() - streamStart); - info.setAudioDataStartPosition(streamStart); - info.setAudioDataEndPosition(fc.size()); - info.setBitRate(computeBitrate(info.getAudioDataLength(), mbdsi.getPreciseLength())); - return info; - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - private int computeBitrate(long size, float length) { - return (int) ((size / Utils.KILOBYTE_MULTIPLIER) * Utils.BITS_IN_BYTE_MULTIPLIER / 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 = null; - try { - raf = new RandomAccessFile(f, "r"); - FileChannel fc = raf.getChannel(); - FlacStreamReader flacStream = new FlacStreamReader(fc, f.getPath() + " "); - flacStream.findStream(); - - boolean isLastBlock = false; - - int count = 0; - while (!isLastBlock) { - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(fc); - logger.config(f + ":Found block:" + mbh.getBlockType()); - fc.position(fc.position() + mbh.getDataLength()); - isLastBlock = mbh.isLastBlock(); - count++; - } - return count; - } finally { - AudioFileIO.closeQuietly(raf); - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacStreamReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacStreamReader.java deleted file mode 100644 index 105d36e3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacStreamReader.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Tag; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Flac Stream - * - * Reader files and identifies if this is in fact a flac stream - */ -public class FlacStreamReader -{ - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.flac"); - - public static final int FLAC_STREAM_IDENTIFIER_LENGTH = 4; - public static final String FLAC_STREAM_IDENTIFIER = "fLaC"; - - private FileChannel fc; - private String loggingName; - private int startOfFlacInFile; - - /** - * Create instance for holding stream info - * @param fc - * @param loggingName - */ - public FlacStreamReader(FileChannel fc, String loggingName) - { - this.fc = fc; - this.loggingName =loggingName; - } - - /** - * 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 (fc.size() == 0) - { - //Empty File - throw new CannotReadException("Error: File empty"+ " " + loggingName); - } - fc.position(0); - - //FLAC Stream at start - if (isFlacHeader()) - { - startOfFlacInFile = 0; - return; - } - - //Ok maybe there is an ID3v24tag first - if (isId3v2Tag()) - { - startOfFlacInFile = (int) (fc.position() - FLAC_STREAM_IDENTIFIER_LENGTH); - return; - } - throw new CannotReadException(loggingName + ErrorMessage.FLAC_NO_FLAC_HEADER_FOUND.getMsg()); - } - - private boolean isId3v2Tag() throws IOException - { - fc.position(0); - if(AbstractID3v2Tag.isId3Tag(fc)) - { - logger.warning(loggingName + ErrorMessage.FLAC_CONTAINS_ID3TAG.getMsg(fc.position())); - //FLAC Stream immediately after end of id3 tag - if (isFlacHeader()) - { - return true; - } - } - return false; - } - - private boolean isFlacHeader() throws IOException - { - ByteBuffer headerBuffer = Utils.readFileDataIntoBufferBE(fc, FLAC_STREAM_IDENTIFIER_LENGTH); - return Utils.readFourBytesAsChars(headerBuffer).equals(FLAC_STREAM_IDENTIFIER); - } - - /** - * Usually flac header is at start of file, but unofficially an 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagCreator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagCreator.java deleted file mode 100644 index 6b30bca4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagCreator.java +++ /dev/null @@ -1,122 +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 com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.flac.metadatablock.BlockType; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPadding; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; -import com.mp3.jaudiotagger.audio.generic.AbstractTagCreator; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.flac.FlacTag; -import com.mp3.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 -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.flac"); - - //TODO make an option - public static final int DEFAULT_PADDING = 4000; - - private static final VorbisCommentCreator creator = new VorbisCommentCreator(); - - /** - * @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().limit() + 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagReader.java deleted file mode 100644 index 72c7674b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagReader.java +++ /dev/null @@ -1,129 +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 com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.InvalidFrameException; -import com.mp3.jaudiotagger.tag.flac.FlacTag; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentReader; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -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("com.mp3.jaudiotagger.audio.flac"); - - private VorbisCommentReader vorbisCommentReader = new VorbisCommentReader(); - - - public FlacTag read(File file) throws CannotReadException, IOException { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - FlacStreamReader flacStream = new FlacStreamReader(fc, file.getPath()); - 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(file.getPath() + " Looking for MetaBlockHeader at:" + fc.position()); - } - - //Read the header - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(fc); - if (mbh == null) { - break; - } - - if (logger.isLoggable(Level.CONFIG)) { - logger.config(file.getPath() + " Reading MetadataBlockHeader:" + mbh.toString() + " ending at " + fc.position()); - } - - //Is it one containing some sort of metadata, therefore interested in it? - - //JAUDIOTAGGER-466:CBlocktype can be null - if (mbh.getBlockType() != null) { - switch (mbh.getBlockType()) { - //We got a vorbiscomment comment block, parse it - case VORBIS_COMMENT: - ByteBuffer commentHeaderRawPacket = ByteBuffer.allocate(mbh.getDataLength()); - fc.read(commentHeaderRawPacket); - tag = vorbisCommentReader.read(commentHeaderRawPacket.array(), false); - break; - - case PICTURE: - try { - MetadataBlockDataPicture mbdp = new MetadataBlockDataPicture(mbh, fc); - images.add(mbdp); - } catch (IOException ioe) { - logger.warning(file.getPath() + "Unable to read picture metablock, ignoring:" + ioe.getMessage()); - } catch (InvalidFrameException ive) { - logger.warning(file.getPath() + "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(file.getPath() + "Ignoring MetadataBlock:" + mbh.getBlockType()); - } - fc.position(fc.position() + mbh.getDataLength()); - break; - } - } - isLastBlock = mbh.isLastBlock(); - } - logger.config("Audio should start at:" + Hex.asHex(fc.position())); - - //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; - } finally { - AudioFileIO.closeQuietly(raf); - } - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagWriter.java deleted file mode 100644 index 733f1d82..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/FlacTagWriter.java +++ /dev/null @@ -1,491 +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 com.mp3.jaudiotagger.audio.flac; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.flac.metadatablock.*; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.flac.FlacTag; -import com.mp3.jaudiotagger.utils.DirectByteBufferUtils; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.FileChannel.MapMode; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static com.mp3.jaudiotagger.utils.PrimitiveUtils.safeLongToInt; - - -/** - * Write Flac Tag - */ -public class FlacTagWriter { - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.flac"); - private FlacTagCreator tc = new FlacTagCreator(); - - /** - * @param tag - * @param file - * @throws IOException - * @throws CannotWriteException - */ - public void delete(Tag tag, File file) throws CannotWriteException { - //This will save the file without any Comment or PictureData blocks - FlacTag emptyTag = new FlacTag(null, new ArrayList()); - write(emptyTag, file); - } - - 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); - } - - /** - * @param tag - * @param file - * @throws CannotWriteException - * @throws IOException - */ - public void write(Tag tag, File file) throws CannotWriteException { - logger.config(file + " Writing tag"); - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - MetadataBlockInfo blockInfo = new MetadataBlockInfo(); - - //Read existing data - FlacStreamReader flacStream = new FlacStreamReader(fc, file.toString() + " "); - try { - flacStream.findStream(); - } catch (CannotReadException cre) { - throw new CannotWriteException(cre.getMessage()); - } - - boolean isLastBlock = false; - while (!isLastBlock) { - try { - MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(fc); - if (mbh.getBlockType() != null) { - switch (mbh.getBlockType()) { - case STREAMINFO: { - blockInfo.streamInfoBlock = new MetadataBlock(mbh, new MetadataBlockDataStreamInfo(mbh, fc)); - 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 - fc.position(fc.position() + mbh.getDataLength()); - MetadataBlockData mbd = new MetadataBlockDataPadding(mbh.getDataLength()); - blockInfo.metadataBlockPadding.add(new MetadataBlock(mbh, mbd)); - break; - } - case APPLICATION: { - MetadataBlockData mbd = new MetadataBlockDataApplication(mbh, fc); - blockInfo.metadataBlockApplication.add(new MetadataBlock(mbh, mbd)); - break; - } - case SEEKTABLE: { - MetadataBlockData mbd = new MetadataBlockDataSeekTable(mbh, fc); - blockInfo.metadataBlockSeekTable.add(new MetadataBlock(mbh, mbd)); - break; - } - case CUESHEET: { - MetadataBlockData mbd = new MetadataBlockDataCueSheet(mbh, fc); - blockInfo.metadataBlockCueSheet.add(new MetadataBlock(mbh, mbd)); - break; - } - default: { - //What are the consequences of doing this - fc.position(fc.position() + mbh.getDataLength()); - break; - } - } - } - isLastBlock = mbh.isLastBlock(); - } catch (CannotReadException cre) { - throw new CannotWriteException(cre.getMessage()); - } - } - - //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(); - - //Other blocks required size - int otherBlocksRequiredSize = computeNeededRoom(blockInfo); - - //Number of bytes required for new tagdata and other metadata blocks - int neededRoom = newTagSize + otherBlocksRequiredSize; - - //Go to start of Flac within file - fc.position(flacStream.getStartOfFlacInFile()); - - logger.config(file + ":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)) { - logger.config(file + ":Room to Rewrite"); - //Jump over Id3 (if exists) and flac header - fc.position(flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH); - - //Write stream info and other non metadata blocks - writeOtherMetadataBlocks(fc, blockInfo); - - //Write tag (and padding) - fc.write(tc.convert(tag, availableRoom - neededRoom)); - } - //Need to move audio - else { - logger.config(file + ":Audio must be shifted " + "NewTagSize:" + newTagSize + ":AvailableRoom:" + availableRoom + ":MinimumAdditionalRoomRequired:" + (neededRoom - availableRoom)); - //As we are having to both anyway may as well put in the default padding - insertUsingChunks(file, tag, fc, blockInfo, flacStream, neededRoom + FlacTagCreator.DEFAULT_PADDING, availableRoom); - } - } catch (IOException ioe) { - logger.log(Level.SEVERE, ioe.getMessage(), ioe); - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Insert metadata into space that is not large enough, so have to shift existing audio data by copying into buffer - * and the reinserting after adding the metadata - *

- * However this method requires a contiguous amount of memory equal to the size of the audio to be available and this - * can cause a failure on low memory systems, so no longer used. - * - * @param tag - * @param fc - * @param blockInfo - * @param flacStream - * @param availableRoom - * @throws IOException - * @throws UnsupportedEncodingException - */ - private void insertUsingDirectBuffer(File file, Tag tag, FileChannel fc, MetadataBlockInfo blockInfo, FlacStreamReader flacStream, int availableRoom) throws IOException { - //Find end of metadata blocks (start of Audio), i.e start of Flac + 4 bytes for 'fLaC', 4 bytes for streaminfo header and - //34 bytes for streaminfo and then size of all the other existing blocks - fc.position(flacStream.getStartOfFlacInFile() - + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH - + MetadataBlockHeader.HEADER_LENGTH - + MetadataBlockDataStreamInfo.STREAM_INFO_DATA_LENGTH - + availableRoom); - - //And copy into Buffer, because direct buffer doesnt use heap - ByteBuffer audioData = ByteBuffer.allocateDirect((int) (fc.size() - fc.position())); - fc.read(audioData); - audioData.flip(); - - //Jump over Id3 (if exists) Flac Header - fc.position(flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH); - writeOtherMetadataBlocks(fc, blockInfo); - - //Write tag (and add some default padding) - fc.write(tc.convert(tag, FlacTagCreator.DEFAULT_PADDING)); - - //Write Audio - fc.write(audioData); - } - - - /** - * Insert metadata into space that is not large enough - *

- * We do this by reading/writing chunks of data allowing it to work on low memory systems - *

- * Chunk size defined by TagOptionSingleton.getInstance().getWriteChunkSize() - * - * @param tag - * @param fc - * @param blockInfo - * @param flacStream - * @param neededRoom - * @param availableRoom - * @throws IOException - * @throws UnsupportedEncodingException - */ - private void insertUsingChunks(File file, Tag tag, FileChannel fc, MetadataBlockInfo blockInfo, FlacStreamReader flacStream, int neededRoom, int availableRoom) throws IOException, UnsupportedEncodingException { - long originalFileSize = fc.size(); - - //Find end of metadata blocks (start of Audio), i.e start of Flac + 4 bytes for 'fLaC', 4 bytes for streaminfo header and - //34 bytes for streaminfo and then size of all the other existing blocks - long audioStart = flacStream.getStartOfFlacInFile() - + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH - + MetadataBlockHeader.HEADER_LENGTH - + MetadataBlockDataStreamInfo.STREAM_INFO_DATA_LENGTH - + availableRoom; - - //Extra Space Required for larger metadata block - int extraSpaceRequired = neededRoom - availableRoom; - logger.config(file + " Audio needs shifting:" + extraSpaceRequired); - - //ChunkSize must be at least as large as the extra space required to write the metadata - int chunkSize = (int) TagOptionSingleton.getInstance().getWriteChunkSize(); - if (chunkSize < extraSpaceRequired) { - chunkSize = extraSpaceRequired; - } - - Queue queue = new LinkedBlockingQueue(); - - //Read first chunk of audio - fc.position(audioStart); - { - ByteBuffer audioBuffer = ByteBuffer.allocateDirect(chunkSize); - fc.read(audioBuffer); - audioBuffer.flip(); - queue.add(audioBuffer); - } - long readPosition = fc.position(); - - //Jump over Id3 (if exists) and Flac Header - fc.position(flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH); - writeOtherMetadataBlocks(fc, blockInfo); - fc.write(tc.convert(tag, FlacTagCreator.DEFAULT_PADDING)); - long writePosition = fc.position(); - - - fc.position(readPosition); - while (fc.position() < originalFileSize) { - //Read next chunk - ByteBuffer audioBuffer = ByteBuffer.allocateDirect(chunkSize); - fc.read(audioBuffer); - readPosition = fc.position(); - audioBuffer.flip(); - queue.add(audioBuffer); - - //Write previous chunk - fc.position(writePosition); - fc.write(queue.remove()); - writePosition = fc.position(); - - fc.position(readPosition); - } - fc.position(writePosition); - fc.write(queue.remove()); - } - - /** - * Insert new metadata into file by using memory mapped file, and if fails write in chunks - *

- * But this is problematic on 32bit systems for large flac files may not be able to map a contiguous address space large enough - * for a large audio size , so no longer used since better to go straight to using chunks - * - * @param tag - * @param fc - * @param blockInfo - * @param flacStream - * @param neededRoom - * @param availableRoom - * @throws IOException - * @throws UnsupportedEncodingException - */ - private void insertTagAndShift(File file, Tag tag, FileChannel fc, MetadataBlockInfo blockInfo, FlacStreamReader flacStream, int neededRoom, int availableRoom) throws IOException, UnsupportedEncodingException { - int headerLength = flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH + MetadataBlockHeader.HEADER_LENGTH // this should be the length of the block header for the stream info - + MetadataBlockDataStreamInfo.STREAM_INFO_DATA_LENGTH; - long targetSizeBeforeAudioData = headerLength + neededRoom + FlacTagCreator.DEFAULT_PADDING; - long remainderTargetSize = fc.size() - (headerLength + availableRoom); - long totalTargetSize = targetSizeBeforeAudioData + remainderTargetSize; - - MappedByteBuffer mappedFile = null; - try { - //Use ByteBuffer - mappedFile = fc.map(MapMode.READ_WRITE, 0, totalTargetSize); - insertTagAndShiftViaMappedByteBuffer(tag, mappedFile, fc, targetSizeBeforeAudioData, totalTargetSize, blockInfo, flacStream, neededRoom, availableRoom); - } catch (IOException ioe) { - //#175: Flac Map error on write - if (mappedFile == null) { - insertUsingChunks(file, tag, fc, blockInfo, flacStream, neededRoom + FlacTagCreator.DEFAULT_PADDING, availableRoom); - } else { - logger.log(Level.SEVERE, ioe.getMessage(), ioe); - throw ioe; - } - } - } - - /** - * Insert new metadata into file by using memory mapped file - *

- * But this is problematic on 32bit systems for large flac files may not be able to map a contiguous address space large enough - * for a large audio size , so no longer used - * - * @param tag - * @param mappedFile - * @param fc - * @param targetSizeBeforeAudioData - * @param totalTargetSize - * @param blockInfo - * @param flacStream - * @param neededRoom - * @param availableRoom - * @throws IOException - * @throws UnsupportedEncodingException - */ - private void insertTagAndShiftViaMappedByteBuffer(Tag tag, MappedByteBuffer mappedFile, FileChannel fc, long targetSizeBeforeAudioData, long totalTargetSize, MetadataBlockInfo blockInfo, FlacStreamReader flacStream, int neededRoom, int availableRoom) throws IOException, UnsupportedEncodingException { - //Find end of metadata blacks (start of Audio) - int currentEndOfFilePosition = safeLongToInt(fc.size()); - /* - * First shift data to the 'right' of the tag to the end of the file, whose position is currentEndOfTagsPosition - */ - int currentEndOfTagsPosition = safeLongToInt((targetSizeBeforeAudioData - FlacTagCreator.DEFAULT_PADDING) - neededRoom + availableRoom); - int lengthDiff = safeLongToInt(totalTargetSize - currentEndOfFilePosition); - final int BLOCK_SIZE = safeLongToInt(TagOptionSingleton.getInstance().getWriteChunkSize()); - int currentPos = currentEndOfFilePosition - BLOCK_SIZE; - byte[] buffer = new byte[BLOCK_SIZE]; - for (; currentPos >= currentEndOfTagsPosition; currentPos -= BLOCK_SIZE) { - mappedFile.position(currentPos); - mappedFile.get(buffer, 0, BLOCK_SIZE); - mappedFile.position(currentPos + lengthDiff); - mappedFile.put(buffer, 0, BLOCK_SIZE); - } - - /* - * Final movement of start bytes. This also covers cases where BLOCK_SIZE is larger than the audio data - */ - int remainder = (currentPos + BLOCK_SIZE) - currentEndOfTagsPosition; - if (remainder > 0) { - mappedFile.position(currentEndOfTagsPosition); - mappedFile.get(buffer, 0, remainder); - mappedFile.position(currentEndOfTagsPosition + lengthDiff); - mappedFile.put(buffer, 0, remainder); - } - - DirectByteBufferUtils.release(mappedFile); - - /* Now overwrite the tag */ - writeTags(tag, fc, blockInfo, flacStream); - } - - private void writeTags(Tag tag, FileChannel fc, MetadataBlockInfo blockInfo, FlacStreamReader flacStream) throws IOException, UnsupportedEncodingException { - //Jump over Id3 (if exists) Flac Header - fc.position(flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH); - writeOtherMetadataBlocks(fc, blockInfo); - - //Write tag (and add some default padding) - fc.write(tc.convert(tag, FlacTagCreator.DEFAULT_PADDING)); - } - - /** - * Write all metadata blocks except for the the actual tag metadata - *

- * We always write blocks in this order - * - * @param fc - * @param blockInfo - * @throws IOException - */ - private void writeOtherMetadataBlocks(FileChannel fc, MetadataBlockInfo blockInfo) throws IOException { - //Write StreamInfo, we always write this first even if wasn't first in original spec - fc.write(ByteBuffer.wrap(blockInfo.streamInfoBlock.getHeader().getBytesWithoutIsLastBlockFlag())); - fc.write(blockInfo.streamInfoBlock.getData().getBytes()); - - //Write Application Blocks - for (MetadataBlock aMetadataBlockApplication : blockInfo.metadataBlockApplication) { - fc.write(ByteBuffer.wrap(aMetadataBlockApplication.getHeader().getBytesWithoutIsLastBlockFlag())); - fc.write(aMetadataBlockApplication.getData().getBytes()); - } - - //Write Seek Table Blocks - for (MetadataBlock aMetadataBlockSeekTable : blockInfo.metadataBlockSeekTable) { - fc.write(ByteBuffer.wrap(aMetadataBlockSeekTable.getHeader().getBytesWithoutIsLastBlockFlag())); - fc.write(aMetadataBlockSeekTable.getData().getBytes()); - } - - //Write Cue sheet Blocks - for (MetadataBlock aMetadataBlockCueSheet : blockInfo.metadataBlockCueSheet) { - fc.write(ByteBuffer.wrap(aMetadataBlockCueSheet.getHeader().getBytesWithoutIsLastBlockFlag())); - fc.write(aMetadataBlockCueSheet.getData().getBytes()); - } - } - - /** - * @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(); - } - - //Note when reading metadata has been put into padding as well for purposes of write - 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; - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/BlockType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/BlockType.java deleted file mode 100644 index 5ad5181f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/BlockType.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java deleted file mode 100644 index 6a7f5418..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlock.java +++ /dev/null @@ -1,53 +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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java deleted file mode 100644 index 3fb56768..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockData.java +++ /dev/null @@ -1,37 +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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import java.nio.ByteBuffer; - -/** - * This defines the interface required of the different metadata block types - */ -public interface MetadataBlockData -{ - /** - * @return the rawdata as it will be written to file - */ - public ByteBuffer getBytes(); - - /** - * @return the length in bytes that the data uses when written to file - */ - public int getLength(); -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java deleted file mode 100644 index 19780a02..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataApplication.java +++ /dev/null @@ -1,54 +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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - - -/** - * 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 ByteBuffer data; - - public MetadataBlockDataApplication(MetadataBlockHeader header, FileChannel fc) throws IOException - { - data = ByteBuffer.allocate(header.getDataLength()); - fc.read(data); - data.flip(); - } - - public ByteBuffer getBytes() - { - return data; - } - - - public int getLength() - { - return data.limit(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java deleted file mode 100644 index d0f91632..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataCueSheet.java +++ /dev/null @@ -1,53 +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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - -/** - * 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 ByteBuffer data; - - public MetadataBlockDataCueSheet(MetadataBlockHeader header, FileChannel fc) throws IOException - { - data = ByteBuffer.allocate(header.getDataLength()); - fc.read(data); - data.flip(); - } - - public ByteBuffer getBytes() - { - return data; - } - - public int getLength() - { - return data.limit(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.java deleted file mode 100644 index 13f7aa1f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPadding.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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import java.nio.ByteBuffer; - -/** - * 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 ByteBuffer getBytes() - { - return ByteBuffer.allocate(length); - } - - public int getLength() - { - return length; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java deleted file mode 100644 index be98b287..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataPicture.java +++ /dev/null @@ -1,369 +0,0 @@ -package com.mp3.jaudiotagger.audio.flac.metadatablock; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.tag.FieldKey; -import com.mp3.jaudiotagger.tag.InvalidFrameException; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.reference.PictureTypes; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - - -/** - * Picture Block - * - * - * pThis 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: - * Size in bits 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. - * n*8 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. - * n*8 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. - * n*8 The binary picture data. - */ -public class MetadataBlockDataPicture implements MetadataBlockData, TagField -{ - public static final String IMAGE_IS_URL = "-->"; - - private int pictureType; - private String mimeType =""; - private String description; - private int width; - private int height; - private int colourDepth; - private int indexedColouredCount; - private int lengthOfPictureInBytes; - private byte[] imageData; - - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.flac.MetadataBlockDataPicture"); - - 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, StandardCharsets.ISO_8859_1.name()); - - //Description - int descriptionSize = rawdata.getInt(); - description = getString(rawdata, descriptionSize, StandardCharsets.UTF_8.name()); - - //Image width - width = rawdata.getInt(); - - //Image height - height = rawdata.getInt(); - - //Colour Depth - colourDepth = rawdata.getInt(); - - //Indexed Colour Count - indexedColouredCount = rawdata.getInt(); - - lengthOfPictureInBytes = rawdata.getInt(); - //ImageData - imageData = new byte[lengthOfPictureInBytes]; - rawdata.get(imageData); - - logger.config("Read image:" + this.toString()); - } - - /** - * 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 fc - * @throws IOException - * @throws InvalidFrameException - */ - //TODO check for buffer underflows see http://research.eeye.com/html/advisories/published/AD20071115.html - public MetadataBlockDataPicture(MetadataBlockHeader header, FileChannel fc ) throws IOException, InvalidFrameException - { - ByteBuffer rawdata = ByteBuffer.allocate(header.getDataLength()); - int bytesRead = fc.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 - if(mimeType!=null) - { - this.mimeType = mimeType; - } - - //Description - this.description = description; - - this.width = width; - - this.height = height; - - this.colourDepth = colourDepth; - - this.indexedColouredCount = indexedColouredCount; - //ImageData - this.imageData = imageData; - } - - 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 ByteBuffer getBytes() - { - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(Utils.getSizeBEInt32(pictureType)); - baos.write(Utils.getSizeBEInt32(mimeType.length())); - baos.write(mimeType.getBytes(StandardCharsets.ISO_8859_1)); - baos.write(Utils.getSizeBEInt32(description.length())); - baos.write(description.getBytes(StandardCharsets.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 ByteBuffer.wrap(baos.toByteArray()); - - } - catch (IOException ioe) - { - throw new RuntimeException(ioe.getMessage()); - } - } - - public int getLength() - { - return getBytes().limit(); - } - - 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 new String(getImageData(), 0, getImageData().length, StandardCharsets.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:" + lengthOfPictureInBytes + "/" + 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 com.mp3.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 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. - */ - public byte[] getRawContent() throws UnsupportedEncodingException - { - return getBytes().array(); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.java deleted file mode 100644 index ec59c5b2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataSeekTable.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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - - -/** - * 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 ByteBuffer data; - - public MetadataBlockDataSeekTable(MetadataBlockHeader header, FileChannel fc) throws IOException - { - data = ByteBuffer.allocate(header.getDataLength()); - fc.read(data); - data.flip(); - } - - public ByteBuffer getBytes() - { - return data; - } - - - public int getLength() - { - return data.limit(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java deleted file mode 100644 index 7e9e34f3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockDataStreamInfo.java +++ /dev/null @@ -1,230 +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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -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: - * Size in bits 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("com.mp3.jaudiotagger.audio.flac.MetadataBlockDataStreamInfo"); - - private int minBlockSize, maxBlockSize, minFrameSize, maxFrameSize, samplingRate, samplingRatePerChannel, bitsPerSample, noOfChannels, noOfSamples; - private float trackLength; - private String md5; - private boolean isValid = true; - - private ByteBuffer rawdata; - - public MetadataBlockDataStreamInfo(MetadataBlockHeader header, FileChannel fc) throws IOException - { - rawdata = ByteBuffer.allocate(header.getDataLength()); - rawdata.order(ByteOrder.BIG_ENDIAN); - int bytesRead = fc.read(rawdata); - if (bytesRead < header.getDataLength()) - { - throw new IOException("Unable to read required number of bytes, read:" + bytesRead + ":required:" + header.getDataLength()); - } - rawdata.flip(); - - minBlockSize = Utils.u(rawdata.getShort()); - maxBlockSize = Utils.u(rawdata.getShort()); - minFrameSize = readThreeByteInteger(rawdata.get(), rawdata.get(), rawdata.get()); - maxFrameSize = readThreeByteInteger(rawdata.get(), rawdata.get(), rawdata.get()); - samplingRate = readSamplingRate(); - noOfChannels = readNoOfChannels(); - bitsPerSample = readBitsPerSample(); - noOfSamples = readTotalNumberOfSamples(); - md5 = readMd5(); - trackLength = (float) ((double) noOfSamples / samplingRate); - samplingRatePerChannel = samplingRate / noOfChannels; - rawdata.rewind(); - } - - private final static char[] hexArray = "0123456789abcdef".toCharArray(); - - private String readMd5() - { - char[] hexChars = new char[32]; // MD5 is always 32 characters - - if(rawdata.limit()>=34) - { - for (int i = 0; i < 16; i++) - { - int v = rawdata.get(i + 18) & 0xFF; // Offset 18 - hexChars[i * 2] = hexArray[v >>> 4]; - hexChars[i * 2 + 1] = hexArray[v & 0x0F]; - } - } - - return new String(hexChars); - } - - /** - * @return the rawdata as it will be written to file - */ - public ByteBuffer getBytes() - { - return rawdata; - } - - public int getLength() - { - return rawdata.limit(); - } - - - - public String toString() - { - - return "MinBlockSize:" + minBlockSize + "MaxBlockSize:" + maxBlockSize + "MinFrameSize:" + minFrameSize + "MaxFrameSize:" + maxFrameSize + "SampleRateTotal:" + samplingRate + "SampleRatePerChannel:" + samplingRatePerChannel + ":Channel number:" + noOfChannels + ":Bits per sample: " + bitsPerSample + ":TotalNumberOfSamples: " + noOfSamples + ":Length: " + trackLength; - - } - - public float getPreciseLength() - { - return trackLength; - } - - public int getNoOfChannels() - { - return noOfChannels; - } - - public int getSamplingRate() - { - return samplingRate; - } - - public int getSamplingRatePerChannel() - { - return samplingRatePerChannel; - } - - public String getEncodingType() - { - return "FLAC " + bitsPerSample + " bits"; - } - - public int getBitsPerSample() - { - return bitsPerSample; - } - - public long getNoOfSamples() - { - return noOfSamples; - } - - public String getMD5Signature() - { - return md5; - } - - public boolean isValid() - { - return isValid; - } - - /** - * SOme values are stored as 3 byte integrals (instead of the more usual 2 or 4) - * - * @param b1 - * @param b2 - * @param b3 - * @return - */ - private int readThreeByteInteger(byte b1, byte b2, byte b3) - { - int rate = (Utils.u(b1) << 16) + (Utils.u(b2) << 8) + (Utils.u(b3)); - return rate; - } - - /** - * Sampling rate is stored over 20 bits bytes 10 and 11 and half of bytes 12 so have to mask third one - * - * @return - */ - private int readSamplingRate() - { - int rate = (Utils.u(rawdata.get(10)) << 12) + (Utils.u(rawdata.get(11)) << 4) + ((Utils.u(rawdata.get(12)) & 0xF0) >>> 4); - return rate; - } - - /** - Stored in 5th to 7th bits of byte 12 - */ - private int readNoOfChannels() - { - return ((Utils.u(rawdata.get(12)) & 0x0E) >>> 1) + 1; - } - - /** Stored in last bit of byte 12 and first 4 bits of byte 13 */ - private int readBitsPerSample() - { - return ((Utils.u(rawdata.get(12)) & 0x01) << 4) + ((Utils.u(rawdata.get(13)) & 0xF0) >>> 4) + 1; - } - - /** Stored in second half of byte 13 plus bytes 14 - 17 - * - * @return - */ - private int readTotalNumberOfSamples() - { - int nb = Utils.u(rawdata.get(17)); - nb += Utils.u(rawdata.get(16)) << 8; - nb += Utils.u(rawdata.get(15)) << 16; - nb += Utils.u(rawdata.get(14)) << 24; - nb += (Utils.u(rawdata.get(13)) & 0x0F) << 32; - return nb; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java deleted file mode 100644 index 70948525..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/flac/metadatablock/MetadataBlockHeader.java +++ /dev/null @@ -1,160 +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 com.mp3.jaudiotagger.audio.flac.metadatablock; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.logging.ErrorMessage; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * 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; - - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.flac"); - /** - * Create header by reading from file - * - * @param fc - * @return - * @throws IOException - */ - public static MetadataBlockHeader readHeader(FileChannel fc) throws CannotReadException, IOException - { - ByteBuffer rawdata = ByteBuffer.allocate(HEADER_LENGTH); - int bytesRead = fc.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; - } - - /** - * Construct header by reading bytes - * - * @param rawdata - */ - public MetadataBlockHeader(ByteBuffer rawdata) throws CannotReadException - { - 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); - } - } - else - { - throw new CannotReadException(ErrorMessage.FLAC_NO_BLOCKTYPE.getMsg(type)); - } - } - - /** - * 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); - } - } - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTag.java deleted file mode 100644 index 4152a0cc..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTag.java +++ /dev/null @@ -1,482 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; - -import java.nio.charset.Charset; -import java.util.*; - -/** - * This class is the default implementation for - * {@link 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 Tag#addField(TagField) - * - * Changed so add empty fields - */ - @Override - 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 Tag#getFields(String) - */ - @Override - 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 - */ - @Override - public String getFirst(FieldKey genericKey) throws KeyNotFoundException - { - return getValue(genericKey,0); - } - - @Override - public String getFirst(String id) - { - List l = getFields(id); - return (l.size() != 0) ? l.get(0).toString() : ""; - } - - @Override - public TagField getFirstField(String id) - { - List l = getFields(id); - return (l.size() != 0) ? l.get(0) : null; - } - - public List getAll() - { - List fieldList = new ArrayList(); - for(List listOfFields : fields.values()) - { - for(TagField next:listOfFields) - { - fieldList.add(next); - } - } - return fieldList; - } - - @Override - 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(); - } - - @Override - public boolean hasNext() - { - if (fieldsIt == null) - { - changeIt(); - } - return it.hasNext() || (fieldsIt != null && fieldsIt.hasNext()); - } - - @Override - public TagField next() - { - if (!fieldsIt.hasNext()) - { - changeIt(); - } - - return fieldsIt.next(); - } - - @Override - public void remove() - { - fieldsIt.remove(); - } - }; - } - - /** - * Return field count - * - * TODO:There must be a more efficient way to do this. - * - * @return field count - */ - @Override - public int getFieldCount() - { - Iterator it = getFields(); - int count = 0; - while (it.hasNext()) - { - count++; - it.next(); - } - return count; - } - - @Override - public int getFieldCountIncludingSubValues() - { - return getFieldCount(); - } - - /** - * Does this tag contain any comon fields - * - * @see Tag#hasCommonFields() - */ - @Override - public boolean hasCommonFields() - { - return commonNumber != 0; - } - - /** - * Does this tag contain a field with the specified id - * - * @see Tag#hasField(String) - */ - @Override - public boolean hasField(String id) - { - return getFields(id).size() != 0; - } - - @Override - 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(Charset enc); - - /** - * Is this tag empty - * - * @see Tag#isEmpty() - */ - @Override - public boolean isEmpty() - { - return fields.size() == 0; - } - - /** - * Create new field and set it in the tag - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - 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 - */ - @Override - 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 Tag#setField(TagField) - */ - @Override - 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 Tag#setEncoding(String) - */ - public boolean setEncoding(final Charset 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 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTagCreator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTagCreator.java deleted file mode 100644 index 34f929ec..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AbstractTagCreator.java +++ /dev/null @@ -1,53 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationAdapter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationAdapter.java deleted file mode 100644 index 62101b34..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationAdapter.java +++ /dev/null @@ -1,78 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.ModifyVetoException; - -import java.io.File; - -/** - * - * - * @author Christian Laireiter - */ -public class AudioFileModificationAdapter implements AudioFileModificationListener -{ - - /** - * (overridden) - * - * @see com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#fileModified(com.mp3.jaudiotagger.audio.AudioFile, - *File) - */ - public void fileModified(AudioFile original, File temporary) throws ModifyVetoException - { - // Nothing to do - } - - /** - * (overridden) - * - * @see com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#fileOperationFinished(File) - */ - public void fileOperationFinished(File result) - { - // Nothing to do - } - - /** - * (overridden) - * - * @see com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#fileWillBeModified(com.mp3.jaudiotagger.audio.AudioFile, - *boolean) - */ - public void fileWillBeModified(AudioFile file, boolean delete) throws ModifyVetoException - { - // Nothing to do - } - - /** - * (overridden) - * - * @see com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#vetoThrown(com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener, - *com.mp3.jaudiotagger.audio.AudioFile, - *com.mp3.jaudiotagger.audio.exceptions.ModifyVetoException) - */ - public void vetoThrown(AudioFileModificationListener cause, AudioFile original, ModifyVetoException veto) - { - // Nothing to do - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationListener.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationListener.java deleted file mode 100644 index 85286897..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileModificationListener.java +++ /dev/null @@ -1,94 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.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. - */ - public 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. - */ - public 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. - */ - public 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. - */ - public void vetoThrown(AudioFileModificationListener cause, AudioFile original, ModifyVetoException veto); - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader.java deleted file mode 100644 index e50d17fd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader.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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import com.mp3.jaudiotagger.audio.exceptions.NoReadPermissionsException; -import com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.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$ - *@since v0.02 - */ - -public abstract class AudioFileReader -{ - - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.generic"); - protected static final int MINIMUM_SIZE_FOR_VALID_AUDIO_FILE = 100; - - /* - * 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 NoReadPermissionsException(ErrorMessage.GENERAL_READ_FAILED_DO_NOT_HAVE_PERMISSION_TO_READ_FILE.getMsg(f.getPath())); - } - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader2.java deleted file mode 100644 index d4e42ac3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileReader2.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import com.mp3.jaudiotagger.audio.exceptions.NoReadPermissionsException; -import com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagException; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.logging.Level; - -/** - * Replacement for AudioFileReader class - */ -public abstract class AudioFileReader2 extends AudioFileReader -{ - /* - * 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 NoReadPermissionsException if permissions prevent reading of file - * @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.getPath())); - } - - if (!f.canRead()) - { - throw new NoReadPermissionsException(ErrorMessage.GENERAL_READ_FAILED_DO_NOT_HAVE_PERMISSION_TO_READ_FILE.getMsg(f.getPath())); - } - - if (f.length() <= MINIMUM_SIZE_FOR_VALID_AUDIO_FILE) - { - throw new CannotReadException(ErrorMessage.GENERAL_READ_FAILED_FILE_TOO_SMALL.getMsg(f.getPath())); - } - - GenericAudioHeader info = getEncodingInfo(f); - Tag tag = getTag(f); - return new AudioFile(f, info, tag); - } - - /** - * - * Read Encoding Information - * - * @param file - * @return - * @throws CannotReadException - * @throws IOException - */ - protected abstract GenericAudioHeader getEncodingInfo(File file) throws CannotReadException, IOException; - - protected GenericAudioHeader getEncodingInfo(RandomAccessFile raf) throws CannotReadException, IOException - { - throw new UnsupportedOperationException("Old method not used in version 2"); - } - - /** - * Read tag Information - * - * @param file - * @return - * @throws CannotReadException - * @throws IOException - */ - protected abstract Tag getTag(File file) throws CannotReadException, IOException; - - protected Tag getTag(RandomAccessFile file) throws CannotReadException, IOException - { - throw new UnsupportedOperationException("Old method not used in version 2"); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter.java deleted file mode 100644 index 17a8c6f6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter.java +++ /dev/null @@ -1,637 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.exceptions.ModifyVetoException; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; - -import java.io.*; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -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 = "rw"; - protected static final int MINIMUM_FILESIZE = 100; - - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.generic"); - - //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; - - /** - * 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 com.mp3.jaudiotagger.audio.exceptions.CannotReadException - */ - public void delete(AudioFile af) throws CannotReadException, CannotWriteException { - File file = af.getFile(); - if (TagOptionSingleton.getInstance().isCheckIsWritable() && !file.canWrite()) { - throw new CannotWriteException(ErrorMessage.GENERAL_DELETE_FAILED.getMsg(file.getPath())); - } - - if (af.getFile().length() <= MINIMUM_FILESIZE) { - throw new CannotWriteException(ErrorMessage.GENERAL_DELETE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.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(af.getTag(), 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 tag - * @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 com.mp3.jaudiotagger.audio.exceptions.CannotReadException - * @throws IOException - */ - public void delete(Tag tag, RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotReadException, CannotWriteException, IOException { - raf.seek(0); - tempRaf.seek(0); - deleteTag(tag, raf, tempRaf); - } - - /** - * Same as above, but delete tag in the file. - * - * @param tag - * @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 com.mp3.jaudiotagger.audio.exceptions.CannotReadException - */ - protected abstract void deleteTag(Tag tag, 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())); - } - - File file = af.getFile(); - if (TagOptionSingleton.getInstance().isCheckIsWritable() && !file.canWrite()) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(af.getFile().getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath())); - } - - if (af.getFile().length() <= MINIMUM_FILESIZE) { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.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, 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) { - transferNewFileToOriginalFile(newFile, af.getFile(), TagOptionSingleton.getInstance().isPreserveFileIdentity()); - } 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); - } - } - - /** - *

- * Transfers the content from {@code newFile} to a file named {@code originalFile}. - * With regards to file identity (inode/fileIndex), - * after execution, {@code originalFile} may be a completely new file or the same file as before execution, depending - * on {@code reuseExistingOriginalFile}. - *

- *

- * Reusing the existing file may be slower, if both the temp file and the original file are located - * in the same filesystem, because an actual copy is created instead of just a file rename. - * If both files are on different filesystems, a copy is always needed — regardless of which method is used. - *

- * - * @param newFile new file - * @param originalFile original file - * @param reuseExistingOriginalFile {@code true} or {@code false} - * @throws CannotWriteException If the file cannot be written - */ - private void transferNewFileToOriginalFile(final File newFile, final File originalFile, final boolean reuseExistingOriginalFile) throws CannotWriteException { - if (reuseExistingOriginalFile) { - transferNewFileContentToOriginalFile(newFile, originalFile); - } else { - transferNewFileToNewOriginalFile(newFile, originalFile); - } - } - - /** - *

- * Writes the contents of the given {@code newFile} to the given {@code originalFile}, - * overwriting the already existing content in {@code originalFile}. - * This ensures that the file denoted by the abstract pathname {@code originalFile} - * keeps the same Unix inode or Windows - * fileIndex. - *

- *

- * If no errors occur, the method follows this approach: - *

- *
    - *
  1. Rename originalFile to originalFile.old
  2. - *
  3. Rename newFile to originalFile (this implies a file identity change for originalFile)
  4. - *
  5. Delete originalFile.old
  6. - *
  7. Delete newFile
  8. - *
- * - * @param newFile File containing the data we want in the {@code originalFile} - * @param originalFile Before execution this denotes the original, unmodified file. - * After execution it denotes the name of the file with the modified content and new inode/fileIndex. - * @throws CannotWriteException if the file cannot be written - */ - private void transferNewFileContentToOriginalFile(final File newFile, final File originalFile) throws CannotWriteException { - // try to obtain exclusive lock on the file - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(originalFile, "rw"); - final FileChannel outChannel = raf.getChannel(); - FileLock lock = null; - try { - lock = outChannel.tryLock(); - if (lock != null) { - transferNewFileContentToOriginalFile(newFile, originalFile, raf, outChannel); - } else { - // we didn't get a lock - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(originalFile.getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(originalFile.getPath())); - } - } catch (IOException e) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(originalFile.getPath())); - // we didn't get a lock, this may be, because locking is not supported by the OS/JRE - // this can happen on OS X with network shares (samba, afp) - // for details see https://stackoverflow.com/questions/33220148/samba-share-gradle-java-io-exception - // coarse check that works on OS X: - if ("Operation not supported".equals(e.getMessage())) { - // transfer without lock - transferNewFileContentToOriginalFile(newFile, originalFile, raf, outChannel); - } else { - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(originalFile.getPath()), e); - } - } catch (Exception e) { - // tryLock failed for some reason other than an IOException — we're definitely doomed - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(originalFile.getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(originalFile.getPath()), e); - } finally { - if (lock != null) - lock.release(); - } - } catch (FileNotFoundException e) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(originalFile.getAbsolutePath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(originalFile.getPath()), e); - } catch (Exception e) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(originalFile.getAbsolutePath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(originalFile.getPath()), e); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - private void transferNewFileContentToOriginalFile(final File newFile, final File originalFile, final RandomAccessFile raf, final FileChannel outChannel) throws CannotWriteException { - FileInputStream in = null; - try { - in = new FileInputStream(newFile); - FileChannel inChannel = in.getChannel(); - // copy contents of newFile to originalFile, - // overwriting the old content in that file - final long size = inChannel.size(); - long position = 0; - while (position < size) { - position += inChannel.transferTo(position, 1024L * 1024L, outChannel); - } - // truncate raf, in case it used to be longer - raf.setLength(size); - } catch (FileNotFoundException e) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_NEW_FILE_DOESNT_EXIST.getMsg(newFile.getAbsolutePath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_NEW_FILE_DOESNT_EXIST.getMsg(newFile.getName()), e); - } catch (IOException e) { - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName()), e); - } finally { - AudioFileIO.closeQuietly(in); - } - // file is written, all is good, let's delete newFile, as it's not needed anymore - if (newFile.exists() && !newFile.delete()) { - // non-critical failed deletion - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_DELETE_TEMPORARY_FILE.getMsg(newFile.getPath())); - } - } - - /** - *

- * Replaces the original file with the new file in a way that changes the file identity. - * In other words, the Unix inode or the Windows - * fileIndex - * of the resulting file with the name {@code originalFile} is not identical to the inode/fileIndex - * of the file named {@code originalFile} before this method was called. - *

- *

- * If no errors occur, the method follows this approach: - *

- *
    - *
  1. Rename originalFile to originalFile.old
  2. - *
  3. Rename newFile to originalFile (this implies a file identity change for originalFile)
  4. - *
  5. Delete originalFile.old
  6. - *
  7. Delete newFile
  8. - *
- * - * @param newFile File containing the data we want in the {@code originalFile} - * @param originalFile Before execution this denotes the original, unmodified file. - * After execution it denotes the name of the file with the modified content and new inode/fileIndex. - * @throws CannotWriteException if the file cannot be written - */ - private void transferNewFileToNewOriginalFile(final File newFile, final File originalFile) throws CannotWriteException { - // Rename Original File - // Can fail on Vista if have Special Permission 'Delete' set Deny - 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++; - } - - boolean renameResult = Utils.rename(originalFile, originalFileBackup); - if (!renameResult) { - logger.log(Level.SEVERE, ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP.getMsg(originalFile.getAbsolutePath(), originalFileBackup.getName())); - //Delete the temp file because write has failed - // TODO: Simplify: newFile is always != null, otherwise we would not have entered this block (-> if (newFile.length() > 0) {}) - if (newFile != null) { - newFile.delete(); - } - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP.getMsg(originalFile.getPath(), originalFileBackup.getName())); - } - - // Rename Temp File to Original File - renameResult = Utils.rename(newFile, 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 - if (!originalFileBackup.renameTo(originalFile)) { - // 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(), originalFile.getName())); - } - - logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.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())); - } - } - } - - /** - * 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 audioFile - * @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 com.mp3.jaudiotagger.audio.exceptions.CannotReadException - */ - protected abstract void writeTag(AudioFile audioFile, Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotReadException, CannotWriteException, IOException; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter2.java deleted file mode 100644 index 761a8d75..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/AudioFileWriter2.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Created by Paul on 28/01/2016. - */ -public abstract class AudioFileWriter2 extends AudioFileWriter -{ - /** - * Delete the tag (if any) present in the given file - * - * @param af The file to process - * - * @throws CannotWriteException if anything went wrong - * @throws com.mp3.jaudiotagger.audio.exceptions.CannotReadException - */ - @Override - public void delete(AudioFile af) throws CannotReadException, CannotWriteException - { - File file = af.getFile(); - - if (TagOptionSingleton.getInstance().isCheckIsWritable() && !file.canWrite()) - { - throw new CannotWriteException(ErrorMessage.GENERAL_DELETE_FAILED - .getMsg(file)); - } - - if (af.getFile().length() <= MINIMUM_FILESIZE) - { - throw new CannotWriteException(ErrorMessage.GENERAL_DELETE_FAILED_BECAUSE_FILE_IS_TOO_SMALL - .getMsg(file)); - } - deleteTag(af.getTag(), file); - } - - /** - * Replace with new tag - * - * @param af The file we want to process - * @throws CannotWriteException - */ - @Override - public void write(AudioFile af) throws CannotWriteException - { - File file = af.getFile(); - - if (TagOptionSingleton.getInstance().isCheckIsWritable() && !file.canWrite()) - { - logger.severe(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(af.getFile() - .getPath())); - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING - .getMsg(file)); - } - - if (af.getFile().length() <= MINIMUM_FILESIZE) - { - throw new CannotWriteException(ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL - .getMsg(file)); - } - writeTag(af.getTag(), file); - } - - /** - * Must be implemented by each audio format - * - * @param tag - * @param file - * @throws CannotReadException - * @throws CannotWriteException - */ - protected abstract void deleteTag(Tag tag, File file) throws CannotReadException, CannotWriteException; - - - public void deleteTag(Tag tag, RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotReadException, CannotWriteException, IOException - { - throw new UnsupportedOperationException("Old method not used in version 2"); - } - - /** - * Must be implemented by each audio format - * - * @param tag - * @param file - * @throws CannotWriteException - */ - protected abstract void writeTag(Tag tag, File file) throws CannotWriteException; - - protected void writeTag(AudioFile audioFile, Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotReadException, CannotWriteException, IOException - { - throw new UnsupportedOperationException("Old method not used in version 2"); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericAudioHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericAudioHeader.java deleted file mode 100644 index 2bdd106c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericAudioHeader.java +++ /dev/null @@ -1,410 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioHeader; - - -/** - * 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 -{ - //Use objects so clearer wherher has been set or not - private Long audioDataLength; - private Long audioDataStartPosition; - private Long audioDataEndPosition; - private Integer bitRate; - private Integer noOfChannels; - private Integer samplingRate; - private Integer bitsPerSample; - private String encodingType; - private Boolean isVbr = Boolean.TRUE; //TODO this is a weird default - private Boolean isLossless; - private Double trackLength; - private Long noOfSamples; - private Integer byteRate; - - - - /** - * Creates an instance with emtpy values.
- */ - public GenericAudioHeader() - { - - } - - public String getBitRate() - { - return String.valueOf(bitRate); - } - - - /** - * This method returns the bitRate of the represented audio clip in - * "Kbps".
- * - * @return The bitRate in Kbps. - */ - public long getBitRateAsNumber() - { - return bitRate; - } - - /** - * 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 noOfChannels; - } - - /** - * @return - */ - public String getChannels() - { - return String.valueOf(getChannelNumber()); - } - - /** - * Returns the encoding type. - * - * @return The encoding type - */ - public String getEncodingType() - { - return encodingType; - } - - /** - * Returns the format, same as encoding type - * - * @return The encoding type - */ - public String getFormat() - { - return encodingType; - } - - - - /** - * This method returns the duration of the represented audio clip in - * seconds.
- * - * @return The duration to the nearest seconds. - * @see #getPreciseTrackLength() - */ - public int getTrackLength() - { - return (int) Math.round(getPreciseTrackLength()); - } - - /** - * This method returns the duration of the represented audio clip in seconds - * (single-precision).
- * - * @return The duration in seconds. - * @see #getTrackLength() - */ - public double getPreciseTrackLength() - { - return trackLength; - } - - /** - * 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 String.valueOf(samplingRate); - } - - public int getSampleRateAsNumber() - { - return samplingRate; - } - - /** - * @return The number of bits per sample - */ - public int getBitsPerSample() - { - //TODO remove bandaid - if(bitsPerSample==null) - { - return -1; - } - return 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() - { - //TODO remove this bandaid - if(isVbr==null) - { - return false; - } - return isVbr; - } - - /** - * This method returns true, if the audio file is encoded - * with "Lossless".
- * - * @return true if audio clip is encoded with VBR. - */ - public boolean isLossless() - { - //TODO remove this bandaid - if(isLossless==null) - { - return false; - } - return isLossless; - } - - /** - * This Method sets the bitRate in "Kbps".
- * - * @param bitRate bitRate in kbps. - */ - public void setBitRate(int bitRate) - { - this.bitRate = bitRate; - } - - /** - * Sets the number of channels. - * - * @param channelMode number of channels (2 for stereo, 1 for mono). - */ - public void setChannelNumber(int channelMode) - { - this.noOfChannels = channelMode; - } - - /** - * 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) - { - this.encodingType=encodingType; - } - - /** - * This method sets the audio duration of the represented clip.
- * - * @param length The duration of the audio in seconds (single-precision). - */ - public void setPreciseLength(double length) - { - this.trackLength = length; - } - - /** - * Sets the Sampling rate in "Hz"
- * - * @param samplingRate Sample rate. - */ - public void setSamplingRate(int samplingRate) - { - this.samplingRate = samplingRate; - } - - /* - * Sets the Bits per Sample
- * - * @params bitsPerSample Bits Per Sample - */ - public void setBitsPerSample(int bitsPerSample) - { - this.bitsPerSample = bitsPerSample; - } - - /* - * Sets the ByteRate (per second) - * - * @params ByteRate - */ - public void setByteRate(int byteRate) - { - this.byteRate = byteRate; - } - - - /** - * Sets the VBR flag for the represented audio clip.
- * - * @param isVbr true if VBR. - */ - public void setVariableBitRate(boolean isVbr) - { - this.isVbr=isVbr; - } - - /** - * Sets the Lossless flag for the represented audio clip.
- * - * @param isLossless true if Lossless. - */ - public void setLossless(boolean isLossless) - { - this.isLossless = isLossless; - } - - - - /** - * Pretty prints this encoding info - * - * @see Object#toString() - */ - public String toString() - { - StringBuilder out = new StringBuilder(); - out.append("Audio Header content:\n"); - if(audioDataLength!=null) - { - out.append("\taudioDataLength:"+audioDataLength+"\n"); - } - if(audioDataStartPosition!=null) - { - out.append("\taudioDataStartPosition:"+audioDataStartPosition+"\n"); - } - if(audioDataEndPosition!=null) - { - out.append("\taudioDataEndPosition:"+audioDataEndPosition+"\n"); - } - if(byteRate!=null) - { - out.append("\tbyteRate:"+byteRate+"\n"); - } - if(bitRate!=null) - { - out.append("\tbitRate:"+bitRate+"\n"); - } - if(samplingRate!=null) - { - out.append("\tsamplingRate:"+samplingRate+"\n"); - } - if(bitsPerSample!=null) - { - out.append("\tbitsPerSample:"+bitsPerSample+"\n"); - } - if(noOfSamples!=null) - { - out.append("\ttotalNoSamples:"+noOfSamples+"\n"); - } - if(noOfChannels!=null) - { - out.append("\tnumberOfChannels:"+noOfChannels+"\n"); - } - if(encodingType!=null) - { - out.append("\tencodingType:"+encodingType+"\n"); - } - if(isVbr!=null) - { - out.append("\tisVbr:"+isVbr+"\n"); - } - if(isLossless!=null) - { - out.append("\tisLossless:"+isLossless+"\n"); - } - if(trackLength!=null) - { - out.append("\ttrackDuration:"+trackLength+"\n"); - } - return out.toString(); - } - - public Long getAudioDataLength() - { - return audioDataLength; - } - - public void setAudioDataLength(long audioDataLength) - { - this.audioDataLength = audioDataLength; - } - - public Integer getByteRate() - { - return byteRate; - } - - public Long getNoOfSamples() - { - return noOfSamples; - } - - public void setNoOfSamples(Long noOfSamples) - { - this.noOfSamples = noOfSamples; - } - - - @Override - public Long getAudioDataStartPosition() - { - return audioDataStartPosition; - } - - public void setAudioDataStartPosition(Long audioDataStartPosition) - { - this.audioDataStartPosition = audioDataStartPosition; - } - - @Override - public Long getAudioDataEndPosition() - { - return audioDataEndPosition; - } - - public void setAudioDataEndPosition(Long audioDataEndPosition) - { - this.audioDataEndPosition = audioDataEndPosition; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericTag.java deleted file mode 100644 index 43a5633e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/GenericTag.java +++ /dev/null @@ -1,256 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; - -import java.nio.charset.Charset; -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} - * - * @author Raphaël Slinckx - */ -public abstract class GenericTag extends AbstractTag -{ - private static final byte[] EMPTY_BYTE_ARRAY = new byte[]{}; - protected static EnumSet supportedKeys; - - static - { - supportedKeys = EnumSet.of(FieldKey.ALBUM,FieldKey.ARTIST,FieldKey.TITLE,FieldKey.TRACK,FieldKey.GENRE,FieldKey.COMMENT,FieldKey.YEAR); - } - - - public static EnumSet getSupportedKeys() - { - return supportedKeys; - } - - /** - * Implementations of {@link TagTextField} for use with - * "ISO-8859-1" strings. - * - * @author Raphaël Slinckx - */ - protected class GenericTagTextField implements TagTextField - { - - /** - * Stores the string. - */ - private String content; - - /** - * Stores the identifier. - */ - private final String id; - - /** - * Creates an instance. - * - * @param fieldId The identifier. - * @param initialContent The string. - */ - public GenericTagTextField(final String fieldId, final String initialContent) - { - this.id = fieldId; - this.content = initialContent; - } - - @Override - public void copyContent(final TagField field) - { - if (field instanceof TagTextField) - { - this.content = ((TagTextField) field).getContent(); - } - } - - @Override - public String getContent() - { - return this.content; - } - - @Override - public Charset getEncoding() - { - return StandardCharsets.ISO_8859_1; - } - - @Override - public String getId() - { - return id; - } - - @Override - public byte[] getRawContent() - { - return this.content == null ? EMPTY_BYTE_ARRAY : this.content.getBytes(getEncoding()); - } - - @Override - public boolean isBinary() - { - return false; - } - - @Override - public void isBinary(boolean b) - { - /* not supported */ - } - - @Override - public boolean isCommon() - { - return true; - } - - @Override - public boolean isEmpty() - { - return "".equals(this.content); - } - - @Override - public void setContent(final String s) - { - this.content = s; - } - - @Override - public void setEncoding(final Charset s) - { - /* Not allowed */ - } - - @Override - public String toString() - { - return getContent(); - } - } - - @Override - protected boolean isAllowedEncoding(final Charset enc) - { - return true; - } - - @Override - public TagField createField(final FieldKey genericKey, final String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if(supportedKeys.contains(genericKey)) - { - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - return new GenericTagTextField(genericKey.name(),values[0]); - } - else - { - throw new UnsupportedOperationException(ErrorMessage.OPERATION_NOT_SUPPORTED_FOR_FIELD.getMsg(genericKey)); - } - } - - @Override - public String getFirst(final FieldKey genericKey) throws KeyNotFoundException - { - return getValue(genericKey, 0); - } - - @Override - public String getValue(final FieldKey genericKey, final int index) throws KeyNotFoundException - { - if(supportedKeys.contains(genericKey)) - { - return getItem(genericKey.name(),index); - } - else - { - throw new UnsupportedOperationException(ErrorMessage.OPERATION_NOT_SUPPORTED_FOR_FIELD.getMsg(genericKey)); - } - } - - @Override - public List getFields(final FieldKey genericKey) throws KeyNotFoundException - { - List list = fields.get(genericKey.name()); - if (list == null) - { - return new ArrayList(); - } - return list; - } - - @Override - public List getAll(final FieldKey genericKey) throws KeyNotFoundException - { - return super.getAll(genericKey.name()); - } - - @Override - public void deleteField(final FieldKey genericKey) throws KeyNotFoundException - { - if(supportedKeys.contains(genericKey)) - { - deleteField(genericKey.name()); - } - else - { - throw new UnsupportedOperationException(ErrorMessage.OPERATION_NOT_SUPPORTED_FOR_FIELD.getMsg(genericKey)); - } - } - - @Override - public TagField getFirstField(final FieldKey genericKey) throws KeyNotFoundException - { - if(supportedKeys.contains(genericKey)) - { - return getFirstField(genericKey.name()); - } - else - { - throw new UnsupportedOperationException(ErrorMessage.OPERATION_NOT_SUPPORTED_FOR_FIELD.getMsg(genericKey)); - } - } - - @Override - public List getArtworkList() - { - return Collections.emptyList(); - } - - @Override - public TagField createField(final Artwork artwork) throws FieldDataInvalidException - { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/ModificationHandler.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/ModificationHandler.java deleted file mode 100644 index efe91c0e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/ModificationHandler.java +++ /dev/null @@ -1,142 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.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 com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#fileModified(com.mp3.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 com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#fileOperationFinished(File) - */ - public void fileOperationFinished(File result) - { - for (AudioFileModificationListener listener : this.listeners) - { - AudioFileModificationListener current = listener; - current.fileOperationFinished(result); - } - } - - /** - * (overridden) - * - * @see com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#fileWillBeModified(com.mp3.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 com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener#vetoThrown(com.mp3.jaudiotagger.audio.generic.AudioFileModificationListener, - *com.mp3.jaudiotagger.audio.AudioFile, - *com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/TagWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/TagWriter.java deleted file mode 100644 index 884732c7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/TagWriter.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.tag.Tag; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * Created by Paul on 15/09/2015. - */ -public interface TagWriter -{ - public void delete(Tag tag, RandomAccessFile raf, RandomAccessFile tempRaf) throws IOException, CannotWriteException; - - - /** - * Write tag to file - * - * @param tag - * @param raf - * @param rafTemp - * @throws com.mp3.jaudiotagger.audio.exceptions.CannotWriteException - * @throws IOException - */ - public void write(AudioFile af, Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/Utils.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/Utils.java deleted file mode 100644 index 93e75d87..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/generic/Utils.java +++ /dev/null @@ -1,507 +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 com.mp3.jaudiotagger.audio.generic; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.utils.FileTypeUtil; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static com.mp3.jaudiotagger.StandardCharsets.ISO_8859_1; -import static com.mp3.jaudiotagger.StandardCharsets.US_ASCII; - -/** - * Contains various frequently used static functions in the different tag formats. - * - * @author Raphael Slinckx - */ -public class Utils { - public static int BITS_IN_BYTE_MULTIPLIER = 8; - public static int KILOBYTE_MULTIPLIER = 1000; - - private static final Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.generic.utils"); - private static final int MAX_BASE_TEMP_FILENAME_LENGTH = 20; - - /** - * 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(final File f) { - final String name = f.getName().toLowerCase(); - final int i = name.lastIndexOf("."); - if (i == -1) { - return ""; - } - - return name.substring(i + 1); - } - - /** - * Returns the extension of the given file based on the file signature. - * The extension is empty if the file signature is not recognized. - * - * @param f The file whose extension is requested - * @return The extension of the given file - */ - public static String getMagicExtension(final File f) throws IOException { - final String fileType = FileTypeUtil.getMagicFileType(f); - return FileTypeUtil.getMagicExt(fileType); - } - - /** - * Computes a number whereby the 1st byte is the least signifcant and the last - * byte is the most significant. - * So if storing a number which only requires one byte it will be stored in the first - * byte. - * - * @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. - */ - public static long getLongLE(final ByteBuffer b, final int start, final 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(final ByteBuffer b, final int start, final 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(final 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(final byte[] b, final int start, final 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 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(final ByteBuffer b, final int start, final 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(final ByteBuffer b, final int start, final int end) { - return (short) getIntBE(b, start, end); - } - - /** - * Convert int to byte representation - Big Endian (as used by mp4). - * - * @param size - * @return byte representation - */ - public static byte[] getSizeBEInt32(final int size) { - final 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 representation - */ - public static byte[] getSizeBEInt16(final short size) { - final 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 representation - */ - public static byte[] getSizeLEInt32(final int size) { - final 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; - } - - /** - * Convert a byte array to a Pascal string. The first byte is the byte count, - * followed by that many active characters. - * - * @param bb - * @return - * @throws IOException - */ - public static String readPascalString(final ByteBuffer bb) throws IOException { - final int len = Utils.u(bb.get()); //Read as unsigned value - final byte[] buf = new byte[len]; - bb.get(buf); - return new String(buf, 0, len, ISO_8859_1); - } - - /** - * Reads bytes from a ByteBuffer as if they were encoded in the specified CharSet. - * - * @param buffer - * @param offset offset from current position - * @param length size of data to process - * @param encoding - * @return - */ - public static String getString(final ByteBuffer buffer, final int offset, final int length, final Charset encoding) { - final byte[] b = new byte[length]; - buffer.position(buffer.position() + offset); - buffer.get(b); - return new String(b, 0, length, encoding); - } - - /** - * Reads bytes from a ByteBuffer as if they were encoded in the specified CharSet. - * - * @param buffer - * @param encoding - * @return - */ - public static String getString(final ByteBuffer buffer, final Charset encoding) { - final byte[] b = new byte[buffer.remaining()]; - buffer.get(b); - return new String(b, 0, b.length, encoding); - } - - /** - * Read a 32-bit big-endian unsigned integer using a DataInput. - *

- * Reads 4 bytes but returns as long - */ - public static long readUint32(final DataInput di) throws IOException { - final byte[] buf8 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - di.readFully(buf8, 4, 4); - return ByteBuffer.wrap(buf8).getLong(); - } - - /** - * Read a 16-bit big-endian unsigned integer. - *

- * Reads 2 bytes but returns as an integer - */ - public static int readUint16(final DataInput di) throws IOException { - final byte[] buf = {0x00, 0x00, 0x00, 0x00}; - di.readFully(buf, 2, 2); - return ByteBuffer.wrap(buf).getInt(); - } - - - /** - * Read a string of a specified number of ASCII bytes. - */ - public static String readString(final DataInput di, final int charsToRead) throws IOException { - final byte[] buf = new byte[charsToRead]; - di.readFully(buf); - return new String(buf, US_ASCII); - } - - /** - * 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(final File file) { - final 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(final File file) { - final 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(final File fromFile, final 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. - *

- * ToDo refactor AbstractTestCase to use this method as it contains an exact duplicate. - * - * @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(final File fromFile, final File toFile) { - try { - copyThrowsOnException(fromFile, toFile); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - /** - * Reads 4 bytes and concatenates them into a String. - * This pattern is used for ID's of various kinds. - * - * @param bytes - * @return - * @throws IOException - */ - public static String readFourBytesAsChars(final ByteBuffer bytes) { - byte[] b = new byte[4]; - bytes.get(b); - return new String(b, ISO_8859_1); - } - - /** - * Reads 3 bytes and concatenates them into a String. - * This pattern is used for ID's of various kinds. - * - * @param bytes - * @return - */ - public static String readThreeBytesAsChars(final ByteBuffer bytes) { - byte[] b = new byte[3]; - bytes.get(b); - return new String(b, ISO_8859_1); - } - - /** - * Used to convert (signed integer) to an long as if signed integer was unsigned hence allowing - * it to represent full range of integral values. - * - * @param n - * @return - */ - public static long u(final int n) { - return n & 0xffffffffl; - } - - /** - * Used to convert (signed short) to an integer as if signed short was unsigned hence allowing - * it to represent values 0 -> 65536 rather than -32786 -> 32786 - * - * @param n - * @return - */ - public static int u(final short n) { - return n & 0xffff; - } - - /** - * Used to convert (signed byte) to an integer as if signed byte was unsigned hence allowing - * it to represent values 0 -> 255 rather than -128 -> 127. - * - * @param n - * @return - */ - public static int u(final byte n) { - return n & 0xff; - } - - /** - * @param fc - * @param size - * @return - * @throws IOException - */ - public static ByteBuffer readFileDataIntoBufferLE(FileChannel fc, final int size) throws IOException { - final ByteBuffer tagBuffer = ByteBuffer.allocateDirect(size); - fc.read(tagBuffer); - tagBuffer.position(0); - tagBuffer.order(ByteOrder.LITTLE_ENDIAN); - return tagBuffer; - } - - /** - * @param fc - * @param size - * @return - * @throws IOException - */ - public static ByteBuffer readFileDataIntoBufferBE(FileChannel fc, final int size) throws IOException { - final ByteBuffer tagBuffer = ByteBuffer.allocateDirect(size); - fc.read(tagBuffer); - tagBuffer.position(0); - tagBuffer.order(ByteOrder.BIG_ENDIAN); - return tagBuffer; - } - - /** - * Copy src file to dst file. FileChannels are used to maximize performance. - * - * @param source source File - * @param destination destination File which will be created or truncated, before copying, if it already exists - * @throws IOException if any error occurS - */ - public static void copyThrowsOnException(final File source, final File destination) throws IOException { - // Must be done in a loop as there's no guarantee that a request smaller than request count will complete in one invocation. - // Setting the transfer size more than about 1MB is pretty pointless because there is no asymptotic benefit. What you're trying - // to achieve with larger transfer sizes is fewer context switches, and every time you double the transfer size you halve the - // context switch cost. Pretty soon it vanishes into the noise. - FileInputStream inStream = null; - FileOutputStream outStream = null; - try { - inStream = new FileInputStream(source); - outStream = new FileOutputStream(destination); - final FileChannel inChannel = inStream.getChannel(); - final FileChannel outChannel = outStream.getChannel(); - final long size = inChannel.size(); - long position = 0; - while (position < size) { - position += inChannel.transferTo(position, 1024L * 1024L, outChannel); - } - } finally { //Closeables closed exiting try block in all circumstances - AudioFileIO.closeQuietly(inStream, outStream); - } - } - - /** - * @param length - * @return true if length is an odd number - */ - public static boolean isOddLength(long length) { - if ((length & 1) != 0) { - return true; - } - return false; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/Chunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/Chunk.java deleted file mode 100644 index 2ac16932..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/Chunk.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mp3.jaudiotagger.audio.iff; - -import java.io.IOException; -import java.nio.ByteBuffer; - - -/** - * Abstract superclass for IFF/AIFF chunks. - * - * @author Gary McGath - */ -public abstract class Chunk -{ - protected ByteBuffer chunkData; - protected ChunkHeader chunkHeader; - - - - /** - * Constructor used by Wav - * - * @param chunkData - * @param chunkHeader - */ - public Chunk(ByteBuffer chunkData, ChunkHeader chunkHeader) - { - this.chunkData = chunkData; - this.chunkHeader = chunkHeader; - } - - /** - * Reads a chunk and puts appropriate information into - * the RepInfo object. - * - * @return false if the chunk is structurally - * invalid, otherwise true - */ - public abstract boolean readChunk() throws IOException; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkHeader.java deleted file mode 100644 index 5f7a1be0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkHeader.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.mp3.jaudiotagger.audio.iff; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; - -/** - * Each {@link Chunk} starts with a chunk header consisting of a 4 byte id and then a 4 byte size field, the size field - * stores the size of the chunk itself excluding the size of the header. - */ -public class ChunkHeader -{ - public static final int CHUNK_HEADER_SIZE = 8; - - private long size; // This does not include the 8 bytes of header itself - private String chunkId; // Four character Id of the chunk - private ByteOrder byteOrder; - private long startLocationInFile; - - - public ChunkHeader(ByteOrder byteOrder) - { - this.byteOrder=byteOrder; - } - /** - * Reads the header of a chunk. - * - * @return {@code true}, if we were able to read a chunk header and believe we found a valid chunk id. - */ - public boolean readHeader(final FileChannel fc) throws IOException - { - ByteBuffer header = ByteBuffer.allocate(CHUNK_HEADER_SIZE); - startLocationInFile = fc.position(); - fc.read(header); - header.order(byteOrder); - header.position(0); - this.chunkId = Utils.readFourBytesAsChars(header); - this.size = header.getInt(); - - return true; - } - - /** - * Reads the header of a chunk. - * - * @return {@code true}, if we were able to read a chunk header and believe we found a valid chunk id. - */ - public boolean readHeader(final RandomAccessFile raf) throws IOException - { - ByteBuffer header = ByteBuffer.allocate(CHUNK_HEADER_SIZE); - startLocationInFile = raf.getFilePointer(); - raf.getChannel().read(header); - header.order(byteOrder); - header.position(0); - this.chunkId = Utils.readFourBytesAsChars(header); - this.size = header.getInt(); - - return true; - } - - /** - * Writes this chunk header to a {@link ByteBuffer}. - * - * @return the byte buffer containing the - */ - public ByteBuffer writeHeader() - { - final ByteBuffer bb = ByteBuffer.allocate(CHUNK_HEADER_SIZE); - bb.order(byteOrder); - bb.put(chunkId.getBytes(StandardCharsets.US_ASCII)); - bb.putInt((int)size); - bb.flip(); - return bb; - } - - /** - * Sets the chunk type, which is a 4-character code, directly. - * - * @param id 4-char id - */ - public void setID(final String id) - { - this.chunkId = id; - } - - /** - * Returns the chunk type, which is a 4-character code. - * - * @return id - */ - public String getID() - { - return this.chunkId; - } - - /** - * Returns the chunk size (excluding the first 8 bytes). - * - * @see #setSize(long) - */ - public long getSize() - { - return size; - } - - /** - * Set chunk size. - * - * @param size chunk size without header - * @see #getSize() - */ - public void setSize(final long size) - { - this.size=size; - } - - /** The start of this chunk(header) in the file */ - public long getStartLocationInFile() - { - return startLocationInFile; - } - - public String toString() - { - return getID() +":Size:" + getSize() +"startLocation:"+getStartLocationInFile(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkSummary.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkSummary.java deleted file mode 100644 index 0cc0d07d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/ChunkSummary.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.mp3.jaudiotagger.audio.iff; - -import com.mp3.jaudiotagger.logging.Hex; - -/** - * Created by Paul on 22/01/2016. - */ -public class ChunkSummary -{ - private String chunkId; - private long fileStartLocation; - private long chunkSize; - - public ChunkSummary(String chunkId, long fileStartLocation, long chunkSize) - { - this.chunkId=chunkId; - this.fileStartLocation=fileStartLocation; - this.chunkSize=chunkSize; - } - - @Override - public String toString() - { - long endLocation = fileStartLocation + chunkSize + ChunkHeader.CHUNK_HEADER_SIZE; - return chunkId+":StartLocation:" - + Hex.asDecAndHex(fileStartLocation) - + ":SizeIncHeader:" - + chunkSize + ChunkHeader.CHUNK_HEADER_SIZE - + ":EndLocation:" - + Hex.asDecAndHex(endLocation); - } - - public long getEndLocation() - { - return fileStartLocation + chunkSize + ChunkHeader.CHUNK_HEADER_SIZE; - } - public String getChunkId() - { - return chunkId; - } - - public void setChunkId(String chunkId) - { - this.chunkId = chunkId; - } - - public long getFileStartLocation() - { - return fileStartLocation; - } - - public void setFileStartLocation(long fileStartLocation) - { - this.fileStartLocation = fileStartLocation; - } - - public long getChunkSize() - { - return chunkSize; - } - - public void setChunkSize(long chunkSize) - { - this.chunkSize = chunkSize; - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/IffHeaderChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/IffHeaderChunk.java deleted file mode 100644 index 867bbf50..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/iff/IffHeaderChunk.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.mp3.jaudiotagger.audio.iff; - -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Common to all IFF formats such as Wav and Aiff - */ -public class IffHeaderChunk -{ - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.iff"); - - public static int SIGNATURE_LENGTH = 4; - public static int SIZE_LENGTH = 4; - public static int TYPE_LENGTH = 4; - public static int HEADER_LENGTH = SIGNATURE_LENGTH + SIZE_LENGTH + TYPE_LENGTH; - - /** - * If Size is not even then we skip a byte, because chunks have to be aligned - * - * @param raf - * @param chunkHeader - * @throws IOException - */ - public static void ensureOnEqualBoundary(final RandomAccessFile raf,ChunkHeader chunkHeader) throws IOException - { - if (Utils.isOddLength(chunkHeader.getSize())) - { - // Must come out to an even byte boundary unless at end of file - if(raf.getFilePointer() - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General 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 com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; - -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, StandardCharsets.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, StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3AudioHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3AudioHeader.java deleted file mode 100644 index e10ed765..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3AudioHeader.java +++ /dev/null @@ -1,871 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.jaudiotagger.audio.AudioHeader; -import com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.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 -{ - protected MPEGFrameHeader mp3FrameHeader; - protected XingFrame mp3XingFrame; - protected VbriFrame mp3VbriFrame; - - private Long audioDataStartPosition; - private Long audioDataEndPosition; - - private long fileSize; - private long startByte; - private double timePerFrame; - private double trackLength; - private long numberOfFrames; - private long numberOfFramesEstimate; - private long bitrate; - private String encoder = ""; - - 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; - - //Logger - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.mp3"); - - /** - * 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; - - 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 - */ - 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 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; - } - - /** - * Set the location of where the Audio file begins in the file - * - * @param startByte - */ - protected void setMp3StartByte(final long startByte) - { - this.startByte = startByte; - } - - - /** - * 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 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 accurately as possible - */ - public long getNumberOfFrames() - { - return numberOfFrames; - } - - @Override - public Long getNoOfSamples() - { - 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(); - - //Because when calculating framelength we may have altered the calculation slightly for MPEGVersion2 - //to account for mono/stereo we seem to have to make a corresponding modification to get the correct time - if ((mp3FrameHeader.getVersion() == MPEGFrameHeader.VERSION_2) || (mp3FrameHeader.getVersion() == MPEGFrameHeader.VERSION_2_5)) - { - if ((mp3FrameHeader.getLayer() == MPEGFrameHeader.LAYER_II) || (mp3FrameHeader.getLayer() == MPEGFrameHeader.LAYER_III)) - { - if (mp3FrameHeader.getNumberOfChannels() == 1) - { - timePerFrame = timePerFrame / 2; - } - } - } - } - - /** - * @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; - } - - /** - * TODO (Was originally added for Wavs) - * @return - */ - public Integer getByteRate() - { - return null; - } - - /** - * TODO (Was origjnally added for Wavs) - * @return - */ - public Long getAudioDataLength() - { - return Long.valueOf(0); - } - - @Override - public Long getAudioDataStartPosition() - { - return audioDataStartPosition; - } - - public void setAudioDataStartPosition(Long audioDataStartPosition) - { - this.audioDataStartPosition = audioDataStartPosition; - } - - @Override - public Long getAudioDataEndPosition() - { - return audioDataEndPosition; - } - - public void setAudioDataEndPosition(Long audioDataEndPosition) - { - this.audioDataEndPosition = audioDataEndPosition; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3File.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3File.java deleted file mode 100644 index 0f4fbf6a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3File.java +++ /dev/null @@ -1,1152 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp3; -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.*; -import com.mp3.jaudiotagger.logging.*; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.TagNotFoundException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.*; -import com.mp3.jaudiotagger.tag.lyrics3.AbstractLyrics3; -import com.mp3.jaudiotagger.tag.reference.ID3V2Version; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.logging.Level; - -/** - * This class represents a physical MP3 File - */ -public class MP3File extends AudioFile -{ - 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 com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(String filename) throws IOException, TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException - { - this(new File(filename)); - } - - - /* 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; - - /** - * 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 com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(File file, int loadOptions) throws IOException, TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException - { - this(file, loadOptions, false); - } - - /** - * 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 the file to read tags from - * @param loadOptions load options - * @throws IOException IO issues - * @throws TagException tag issues - */ - 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; - try - { - fis = new FileInputStream(file); - final ByteBuffer bb = ByteBuffer.allocateDirect(startByte); - fis.getChannel().read(bb,0); - 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 { - AudioFileIO.closeQuietly(fis); - } - } - 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 - * @throws IOException - * - * @return true if all the bytes between in the file between startByte and endByte are null, false - * otherwise - */ - 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; - } - } - } - - /** - * 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 com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(File file, int loadOptions, boolean readOnly) throws IOException, TagException, ReadOnlyFileException, CannotReadException, 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(); - } - } - } - - /** - * 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 IOException - * @throws com.mp3.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; - } - } - - /** - * 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); - } - - /** - * 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); - } - */ - - /** - * 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 com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException - * @throws com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public MP3File(File file) throws IOException, TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException - { - this(file, LOAD_ALL); - } - - /** - * 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; - } - - /** - * 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); - } - - /** - * Returns the ID3v1 tag for this dataType. - * - * @return the ID3v1 tag for this dataType - */ - public ID3v1Tag getID3v1Tag() - { - return id3v1tag; - } - - /** - * Calculates hash with given algorithm. Buffer size is 32768 byte. - * Hash is calculated EXCLUDING meta-data, like id3v1 or id3v2 - * - * @return hash value in byte - * @param algorithm options MD5,SHA-1,SHA-256 - * @throws IOException - * @throws InvalidAudioFrameException - * @throws NoSuchAlgorithmException - */ - - public byte[] getHash(String algorithm) throws NoSuchAlgorithmException, InvalidAudioFrameException, IOException{ - - return getHash(algorithm, 32768); - - - } - - /** - * Calculates hash with given buffer size. - * Hash is calculated EXCLUDING meta-data, like id3v1 or id3v2 - * @param buffer - * @return byte[] hash value in byte - * @throws IOException - * @throws InvalidAudioFrameException - * @throws NoSuchAlgorithmException - */ - - public byte[] getHash(int buffer) throws NoSuchAlgorithmException, InvalidAudioFrameException, IOException{ - - return getHash("MD5", buffer); - - - } - /** - * Calculates hash with algorithm "MD5". Buffer size is 32768 byte. - * Hash is calculated EXCLUDING meta-data, like id3v1 or id3v2 - * - * @return byte[] hash value. - * @throws IOException - * @throws InvalidAudioFrameException - * @throws NoSuchAlgorithmException - */ - - public byte[] getHash() throws NoSuchAlgorithmException, InvalidAudioFrameException, IOException{ - - return getHash("MD5", 32768); - - } - - /** - * Calculates hash with algorithm "MD5", "SHA-1" or SHA-256". - * Hash is calculated EXCLUDING meta-data, like id3v1 or id3v2 - * - * @return byte[] hash value in byte - * @throws IOException - * @throws InvalidAudioFrameException - * @throws NoSuchAlgorithmException - */ - - public byte[] getHash(String algorithm, int bufferSize) throws InvalidAudioFrameException, IOException, NoSuchAlgorithmException - { - File mp3File = getFile(); - long startByte = getMP3StartByte(mp3File); - - int id3v1TagSize = 0; - if (hasID3v1Tag()){ - ID3v1Tag id1tag= getID3v1Tag(); - id3v1TagSize = id1tag.getSize(); - } - - InputStream inStream = new FileInputStream(mp3File); - - byte[] buffer = new byte[bufferSize]; - - MessageDigest digest = MessageDigest.getInstance(algorithm); - - inStream.skip(startByte); - - int read; - long totalSize = mp3File.length() - startByte - id3v1TagSize; - int pointer = buffer.length; - - while (pointer <= totalSize ) { - - read = inStream.read(buffer); - - digest.update(buffer, 0, read); - pointer += buffer.length; - } - read = inStream.read(buffer,0,(int)totalSize - pointer + buffer.length); - digest.update(buffer, 0, read); - - byte[] hash = digest.digest(); - - inStream.close(); - return hash; - } - - /** - * 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); - - } - - /** - * 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); - } - } - - /** - * 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; - } - - /** - * Returns the ID3v2 tag for this datatype. - * - * @return the ID3v2 tag for this datatype - */ - public AbstractID3v2Tag getID3v2Tag() - { - return id3v2tag; - } - - /** - * @return a representation of tag as v24 - */ - public ID3v24Tag getID3v2TagAsv24() - { - return id3v2Asv24tag; - } - - /** - * 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; - } - */ - - /** - * Remove tag from file - * - * @param mp3tag - * @throws FileNotFoundException - * @throws IOException - */ - public void delete(AbstractTag mp3tag) throws FileNotFoundException, IOException - { - RandomAccessFile raf = new RandomAccessFile(this.file, "rw"); - 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 NoWritePermissionsException if the file could not be written to due to file permissions - * @throws CannotWriteException - */ - public void commit() throws CannotWriteException - { - try - { - save(); - } - catch (UnableToModifyFileException umfe) - { - throw new NoWritePermissionsException(umfe); - } - 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 (TagOptionSingleton.getInstance().isCheckIsWritable() && !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, "rw"); - (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()); - final MP3AudioHeader mp3AudioHeader = (MP3AudioHeader) this.getAudioHeader(); - final long mp3StartByte = mp3AudioHeader.getMp3StartByte(); - final long newMp3StartByte = id3v2tag.write(file, mp3StartByte); - if (mp3StartByte != newMp3StartByte) { - logger.config("New mp3 start byte: " + newMp3StartByte); - mp3AudioHeader.setMp3StartByte(newMp3StartByte); - } - - } - } - rfile = new RandomAccessFile(file, "rw"); - - //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(); - } - - private static void createXMLStructureFormatter() - { - tagFormatter = new XMLTagDisplayFormatter(); - } - - private static void createPlainTextStructureFormatter() - { - tagFormatter = new PlainTextTagDisplayFormatter(); - } - - public static AbstractTagDisplayFormatter getStructureFormatter() - { - return tagFormatter; - } - - /** - * 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(); - } - - - - /** - * Overridden 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 convertedTag = convertID3Tag((AbstractID3v2Tag)tag, TagOptionSingleton.getInstance().getID3V2Version()); - if(convertedTag!=null) - { - setTag(convertedTag); - } - else - { - setTag(tag); - } - return getTag(); - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileReader.java deleted file mode 100644 index 80d20cf2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileReader.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import com.mp3.jaudiotagger.audio.exceptions.ReadOnlyFileException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.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, CannotReadException, 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 TagException - * @throws IOException - * @throws com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException - */ - public AudioFile readMustBeWritable(File f) throws IOException, TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException - { - MP3File mp3File = new MP3File(f, MP3File.LOAD_IDV1TAG | MP3File.LOAD_IDV2TAG, false); - return mp3File; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileWriter.java deleted file mode 100644 index 46e467fc..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MP3FileWriter.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter; -import com.mp3.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(AudioFile audioFile, Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException - { - throw new RuntimeException("MP3FileReaderwriteTag should not be called"); - } - - protected void deleteTag(Tag tag, RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotWriteException, IOException - { - throw new RuntimeException("MP3FileReader.getEncodingInfo should be called"); - } -} - - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MPEGFrameHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MPEGFrameHeader.java deleted file mode 100644 index b564f6b8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/MPEGFrameHeader.java +++ /dev/null @@ -1,888 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * Date :${DATE} - * - * Jaikoz Copyright Copyright (C) 2003 -2005 JThink Ltd - */ -package com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.jaudiotagger.FileConstants; -import com.mp3.jaudiotagger.audio.exceptions.InvalidAudioFrameException; -import com.mp3.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 -{ - /** - * 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; - 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; - - private static final byte[] header = new byte[HEADER_SIZE]; - - - /** - * 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; - - static - { - mpegVersionMap.put(VERSION_2_5, "MPEG-2.5"); - mpegVersionMap.put(VERSION_2, "MPEG-2"); - mpegVersionMap.put(VERSION_1, "MPEG-1"); - } - - /** - * 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; - - static - { - mpegLayerMap.put(LAYER_I, "Layer 1"); - mpegLayerMap.put(LAYER_II, "Layer 2"); - mpegLayerMap.put(LAYER_III, "Layer 3"); - } - - /** - * 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; - - /** - * Bit Rates, the setBitrate varies for different Version and Layer - */ - private static final Map bitrateMap = new HashMap(); - - 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); - } - - /** - * 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; - - static - { - modeMap.put(MODE_STEREO, "Stereo"); - modeMap.put(MODE_JOINT_STEREO, "Joint Stereo"); - modeMap.put(MODE_DUAL_CHANNEL, "Dual"); - modeMap.put(MODE_MONO, "Mono"); - } - - /** - * Constants for Emphasis - */ - private static final Map emphasisMap = new HashMap(); - 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; - - static - { - emphasisMap.put(EMPHASIS_NONE, "None"); - emphasisMap.put(EMPHASIS_5015MS, "5015MS"); - emphasisMap.put(EMPHASIS_RESERVED, "Reserved"); - emphasisMap.put(EMPHASIS_CCITT, "CCITT"); - } - - - 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; - - 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"); - } - - /** - * 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(); - - 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); - } - - /* 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(); - - 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, 1152); - - samplesPerFrameV25Map.put(LAYER_I, 384); - samplesPerFrameV25Map.put(LAYER_II, 1152); - samplesPerFrameV25Map.put(LAYER_III, 1152); - - samplesPerFrameMap.put(VERSION_1, samplesPerFrameV1Map); - samplesPerFrameMap.put(VERSION_2, samplesPerFrameV2Map); - samplesPerFrameMap.put(VERSION_2_5, samplesPerFrameV25Map); - - } - - - 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; - - - 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; - - - /** - * 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 com.mp3.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 com.mp3.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 com.mp3.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 com.mp3.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 com.mp3.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 com.mp3.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 com.mp3.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; - } - - - /** - * Hide Constructor - * @throws com.mp3.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)); - } - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/VbriFrame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/VbriFrame.java deleted file mode 100644 index 6e31dd94..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/VbriFrame.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.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 - 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; - - public static final int MAX_BUFFER_SIZE_NEEDED_TO_READ_VBRI = VBRI_OFFSET + VBRI_HEADER_BUFFER_SIZE; - - 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(); - } - - /** - * 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; - } - - /** - * Parse the VBRIFrame of an MP3File, cannot be called until we have validated that - * this is a VBRIFrame - * - * @return - * @throws com.mp3.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; - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/XingFrame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/XingFrame.java deleted file mode 100644 index f7a91c2d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp3/XingFrame.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp3; - -import com.mp3.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; - 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; - - 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 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); - } - } - - 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; - } - - /** - * 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; - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/EncoderType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/EncoderType.java deleted file mode 100644 index c1e558bd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/EncoderType.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java deleted file mode 100644 index 9d5534a2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomIdentifier.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomTree.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomTree.java deleted file mode 100644 index 24b9bc55..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AtomTree.java +++ /dev/null @@ -1,514 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.NullBoxIdException; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4MetaBox; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4StcoBox; -import com.mp3.jaudiotagger.audio.mp4.atom.NullPadding; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.utils.tree.DefaultMutableTreeNode; -import com.mp3.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 -{ - private DefaultMutableTreeNode rootNode; - private DefaultTreeModel dataTree; - private DefaultMutableTreeNode moovNode; - private DefaultMutableTreeNode mdatNode; - private DefaultMutableTreeNode ilstNode; - private DefaultMutableTreeNode metaNode; - private DefaultMutableTreeNode tagsNode; - private DefaultMutableTreeNode udtaNode; - private DefaultMutableTreeNode hdlrWithinMdiaNode; - private DefaultMutableTreeNode hdlrWithinMetaNode; - private List stcoNodes = new ArrayList(); - private List freeNodes = new ArrayList(); - private List mdatNodes = new ArrayList(); - private List trakNodes = new ArrayList(); - - private List stcos = new ArrayList(); - private ByteBuffer moovBuffer; //Contains all the data under moov - private Mp4BoxHeader moovHeader; - - //Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.mp4"); - - /** - * 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 IOException - * @throws com.mp3.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())) - { - stcos.add(new Mp4StcoBox(boxHeader, moovBuffer)); - stcoNodes.add(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 List getStcoNodes() - { - return stcoNodes; - } - - /** - * - * @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 List getStcos() - { - return stcos; - } - - /** - * - * @return - */ - public ByteBuffer getMoovBuffer() - { - return moovBuffer; - } - - /** - * - * @return - */ - public Mp4BoxHeader getMoovHeader() - { - return moovHeader; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AudioHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AudioHeader.java deleted file mode 100644 index 8745f633..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4AudioHeader.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4EsdsBox; - -/** - * Store some additional attributes useful for Mp4s - */ -public class Mp4AudioHeader extends GenericAudioHeader -{ - private Mp4EsdsBox.Kind kind; - private Mp4EsdsBox.AudioProfile profile; - private String brand; - - - public void setKind(Mp4EsdsBox.Kind kind) - { - this.kind=kind; - } - - /** - * @return kind - */ - public Mp4EsdsBox.Kind getKind() - { - return kind; - } - - /** - * The key for the profile - * - * @param profile - */ - public void setProfile(Mp4EsdsBox.AudioProfile profile) - { - this.profile=profile; - } - - /** - * @return audio profile - */ - public Mp4EsdsBox.AudioProfile getProfile() - { - return profile; - } - - /** - * @param brand - */ - public void setBrand(String brand) - { - this.brand=brand; - } - - - /** - * @return brand - */ - public String getBrand() - { - return brand; - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileReader.java deleted file mode 100644 index e8261679..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileReader.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 com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileWriter.java deleted file mode 100644 index ff4f668d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4FileWriter.java +++ /dev/null @@ -1,49 +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 com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter; -import com.mp3.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(AudioFile audioFile, Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotWriteException, IOException - { - tw.write(tag, raf, rafTemp); - } - - protected void deleteTag(Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws IOException - { - tw.delete(raf, rafTemp); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4InfoReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4InfoReader.java deleted file mode 100644 index 9fea14a1..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4InfoReader.java +++ /dev/null @@ -1,357 +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 com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadVideoException; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.mp4.atom.*; -import com.mp3.jaudiotagger.logging.ErrorMessage; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -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("com.mp3.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()); - if (boxHeader != null) - { - return true; - } - return false; - } - - public GenericAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException - { - FileChannel fc = raf.getChannel(); - Mp4AudioHeader info = new Mp4AudioHeader(); - - //File Identification - Mp4BoxHeader ftypHeader = Mp4BoxHeader.seekWithinLevel(fc, Mp4AtomIdentifier.FTYP.getFieldName()); - if (ftypHeader == null) - { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_CONTAINER.getMsg()); - } - ByteBuffer ftypBuffer = ByteBuffer.allocate(ftypHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH); - fc.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(fc, Mp4AtomIdentifier.MOOV.getFieldName()); - if (moovHeader == null) - { - throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg()); - } - ByteBuffer moovBuffer = ByteBuffer.allocate(moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH); - moovBuffer.order(ByteOrder.LITTLE_ENDIAN); - fc.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.setPreciseLength(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 - int positionBeforeStsdSearch = mvhdBuffer.position(); - 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()); - } - } - } - } - } - - //Level 6-Searching for "stco within "stbl" to get size of audio data - mvhdBuffer.position(positionBeforeStsdSearch); - boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STCO.getFieldName()); - if (boxHeader != null) - { - Mp4StcoBox stco = new Mp4StcoBox(boxHeader, mvhdBuffer); - info.setAudioDataStartPosition((long)stco.getFirstOffSet()); - info.setAudioDataEndPosition((long)fc.size()); - info.setAudioDataLength(fc.size() - stco.getFirstOffSet()); - } - - //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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagReader.java deleted file mode 100644 index ae8673de..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagReader.java +++ /dev/null @@ -1,319 +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 com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4MetaBox; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.jaudiotagger.tag.mp4.Mp4NonStandardFieldKey; -import com.mp3.jaudiotagger.tag.mp4.Mp4Tag; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import com.mp3.jaudiotagger.tag.mp4.field.*; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -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
- * 
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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagWriter.java deleted file mode 100644 index 8a179f9f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/Mp4TagWriter.java +++ /dev/null @@ -1,1263 +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 com.mp3.jaudiotagger.audio.mp4; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.mp4.atom.*; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.mp4.Mp4Tag; -import com.mp3.jaudiotagger.tag.mp4.Mp4TagCreator; -import com.mp3.jaudiotagger.utils.tree.DefaultMutableTreeNode; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.List; -import java.util.logging.Logger; - - -/** - * Writes metadata from mp4, the metadata tags are held under the {@code ilst} atom as shown below, (note all free atoms are - * optional). - *

- * When writing changes the size of all the atoms up to {@code ilst} has to be recalculated, then if the size of - * the metadata is increased the size of the free atom (below {@code meta}) should be reduced accordingly or vice versa. - * If the size of the metadata has increased by more than the size of the {@code free} atom then the size of {@code meta}, - * {@code udta} and {@code moov} should be recalculated and the top level {@code free} atom reduced accordingly. - * If there is not enough space even if using both of the {@code free} atoms, then the {@code mdat} atom has to be - * shifted down accordingly to make space, and the {@code stco} atoms have to have their offsets to {@code 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 (there may be more than one trak atom, e.g. Native Instrument STEM files)
- * |......|.......|
- * |......|.......|-- tkhd
- * |......|.......|-- mdia
- * |......|............|
- * |......|............|-- mdhd
- * |......|............|-- hdlr
- * |......|............|-- minf
- * |......|.................|
- * |......|.................|-- smhd
- * |......|.................|-- dinf
- * |......|.................|-- stbl
- * |......|......................|
- * |......|......................|-- stsd
- * |......|......................|-- stts
- * |......|......................|-- stsc
- * |......|......................|-- stsz
- * |......|......................|-- stco (important! may need to be adjusted.)
- * |......|
- * |......|----- udta
- * |..............|
- * |..............|-- meta
- * |....................|
- * |....................|-- hdlr
- * |....................|-- ilst
- * |....................|.. ..|
- * |....................|.....|---- @nam (Optional for each metadatafield)
- * |....................|.....|.......|-- data
- * |....................|.....|....... ecetera
- * |....................|.....|---- ---- (Optional for reverse dns field)
- * |....................|.............|-- mean
- * |....................|.............|-- name
- * |....................|.............|-- data
- * |....................|................ ecetera
- * |....................|-- free
- * |--- free
- * |--- mdat
- * 
- */ -public class Mp4TagWriter -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.tag.mp4"); - - private Mp4TagCreator tc = new Mp4TagCreator(); - - - /** - * Replace the {@code ilst} metadata. - *

- * Because it is the same size as the original data nothing else has to be modified. - * - * @param fileReadChannel - * @param fileWriteChannel - * @param newIlstData - * @throws CannotWriteException - * @throws IOException - */ - private void writeMetadataSameSize(FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader ilstHeader, ByteBuffer newIlstData, Mp4BoxHeader tagsHeader) throws CannotWriteException, IOException - { - logger.config("Writing:Option 1:Same Size"); - - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, ilstHeader.getFilePos()); - fileWriteChannel.position(ilstHeader.getFilePos()); - fileWriteChannel.write(newIlstData); - fileReadChannel.position(ilstHeader.getFileEndPos()); - - 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 - * {@code 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.getFileEndPos()); - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - - /** - * When the size of the metadata has changed and it can't be compensated for by {@code free} atom - * we have to adjust the size of the size field up to the moovheader level for the {@code udta} atom and - * its child {@code meta} atom. - * - * @param moovHeader - * @param moovBuffer - * @param sizeAdjustment can be negative or positive * - * @param udtaHeader - * @param metaHeader - * @return - * @throws 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); - - } - - /** - * Existing metadata larger than new metadata, so we can just add a free atom. - * - * @param fileReadChannel - * @param fileWriteChannel - * @param moovHeader - * @param udtaHeader - * @param metaHeader - * @param ilstHeader - * @param mdatHeader - * @param neroTagsHeader - * @param moovBuffer - * @param newIlstData - * @param stcos - * @param sizeOfExistingMetaLevelFreeAtom - * @throws IOException - * @throws CannotWriteException - */ - private void writeOldMetadataLargerThanNewMetadata(FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader moovHeader, Mp4BoxHeader udtaHeader, Mp4BoxHeader metaHeader, Mp4BoxHeader ilstHeader, Mp4BoxHeader mdatHeader, Mp4BoxHeader neroTagsHeader, ByteBuffer moovBuffer, ByteBuffer newIlstData, List stcos, int sizeOfExistingMetaLevelFreeAtom) throws IOException, CannotWriteException - { - logger.config("Writing:Option 1:Smaller Size"); - - int ilstPositionRelativeToAfterMoovHeader = (int) (ilstHeader.getFilePos() - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - //Create an amended freeBaos atom and write it if it previously existed as a free atom immediately - //after ilst as a child of meta - - int sizeRequiredByNewIlstAtom = newIlstData.limit(); - - if (sizeOfExistingMetaLevelFreeAtom > 0) - { - logger.config("Writing:Option 2:Smaller Size have free atom:" + ilstHeader.getLength() + ":" + sizeRequiredByNewIlstAtom); - writeDataUptoIncludingIlst(fileReadChannel, fileWriteChannel, ilstHeader, newIlstData); - - //Write the modified free atom that comes after ilst - int newFreeSize = sizeOfExistingMetaLevelFreeAtom + (ilstHeader.getLength() - sizeRequiredByNewIlstAtom); - 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() + sizeOfExistingMetaLevelFreeAtom); - writeDataAfterIlst(fileReadChannel, fileWriteChannel, neroTagsHeader); - } - //No free atom we need to create a new one or adjust top level free atom - else - { - int newFreeSize = (ilstHeader.getLength() - sizeRequiredByNewIlstAtom) - 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, ilstHeader, newIlstData); - - //Create new free box - Mp4FreeBox newFreeBox = new Mp4FreeBox(newFreeSize); - fileWriteChannel.write(newFreeBox.getHeader().getHeaderData()); - fileWriteChannel.write(newFreeBox.getData()); - writeDataAfterIlst(fileReadChannel, fileWriteChannel, neroTagsHeader); - } - //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 = ilstHeader.getLength() - sizeRequiredByNewIlstAtom; - - //Write stuff before Moov (ftyp) - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, moovHeader.getFilePos()); - fileWriteChannel.position(moovHeader.getFilePos()); - - //Edit stcos atoms 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()) - { - for (final Mp4StcoBox stoc : stcos) { - stoc.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(ilstPositionRelativeToAfterMoovHeader); - fileWriteChannel.write(moovBuffer); - - //Write ilst data - fileWriteChannel.write(newIlstData); - - //Write rest of moov, as we may have adjusted stcos atoms that occur after ilst - moovBuffer.limit(moovBuffer.capacity()); - moovBuffer.position(ilstPositionRelativeToAfterMoovHeader + ilstHeader.getLength()); - fileWriteChannel.write(moovBuffer); - - //Write the rest after moov - fileReadChannel.position(moovHeader.getFileEndPos() + sizeReducedBy); - writeDataAfterIlst(fileReadChannel, fileWriteChannel, neroTagsHeader); - } - } - } - - /** - * We can fit the metadata in under the meta item just by using some of the padding available in the {@code free} - * atom under the {@code meta} atom need to take of the side of free header otherwise might end up with - * solution where can fit in data, but can't fit in free atom header. - * - * @param fileReadChannel - * @param fileWriteChannel - * @param neroTagsHeader - * @param sizeOfExistingMetaLevelFreeAtom - * @param newIlstData - * @param additionalSpaceRequiredForMetadata - * @throws IOException - * @throws CannotWriteException - */ - private void writeNewMetadataLargerButCanUseFreeAtom(FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader ilstHeader, Mp4BoxHeader neroTagsHeader, int sizeOfExistingMetaLevelFreeAtom, ByteBuffer newIlstData, int additionalSpaceRequiredForMetadata) throws IOException, CannotWriteException - { - int newFreeSize = sizeOfExistingMetaLevelFreeAtom - (additionalSpaceRequiredForMetadata); - logger.config("Writing:Option 5;Larger Size can use meta free atom need extra:" + newFreeSize + "bytes"); - - writeDataUptoIncludingIlst(fileReadChannel, fileWriteChannel, ilstHeader, newIlstData); - - //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() + sizeOfExistingMetaLevelFreeAtom); - writeDataAfterIlst(fileReadChannel, fileWriteChannel, neroTagsHeader); - } - - /** - * Write tag to {@code 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"); - FileChannel fileReadChannel = raf.getChannel(); - FileChannel fileWriteChannel = rafTemp.getChannel(); - - int sizeOfExistingIlstAtom = 0; - int sizeRequiredByNewIlstAtom; - int positionOfNewIlstAtomRelativeToMoovAtom; - int positionInExistingFileOfWhereNewIlstAtomShouldBeWritten; - int sizeOfExistingMetaLevelFreeAtom; - int positionOfTopLevelFreeAtom; - int sizeOfExistingTopLevelFreeAtom; - long endOfMoov = 0; - //Found top level free atom that comes after moov and before mdat, (also true if no free atom ?) - boolean topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata; - 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 newIlstData = tc.convert(tag); - newIlstData.rewind(); - sizeRequiredByNewIlstAtom = newIlstData.limit(); - - //Moov Box header - Mp4BoxHeader moovHeader = atomTree.getBoxHeader(atomTree.getMoovNode()); - List stcos = atomTree.getStcos(); - 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 neroTagsHeader = atomTree.getBoxHeader(atomTree.getTagsNode()); - Mp4BoxHeader trakHeader = atomTree.getBoxHeader(atomTree.getTrakNodes().get(atomTree.getTrakNodes().size()-1)); - ByteBuffer moovBuffer = atomTree.getMoovBuffer(); - - - //Work out if we/what kind of metadata hierarchy 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) - { - sizeOfExistingIlstAtom = ilstHeader.getLength(); - - //Relative means relative to moov buffer after moov header - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten = (int) ilstHeader.getFilePos(); - positionOfNewIlstAtomRelativeToMoovAtom = (int) (positionInExistingFileOfWhereNewIlstAtomShouldBeWritten - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } - else - { - //Place ilst immediately after existing hdlr atom - if (hdlrMetaHeader != null) - { - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten = (int) hdlrMetaHeader.getFileEndPos(); - positionOfNewIlstAtomRelativeToMoovAtom = (int) (positionInExistingFileOfWhereNewIlstAtomShouldBeWritten - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } - //Place ilst after data fields in meta atom - //TODO Should we create a hdlr atom - else - { - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten = (int) metaHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH + Mp4MetaBox.FLAGS_LENGTH; - positionOfNewIlstAtomRelativeToMoovAtom = (int) ((positionInExistingFileOfWhereNewIlstAtomShouldBeWritten) - (moovHeader.getFilePos() + Mp4BoxHeader.HEADER_LENGTH)); - } - } - } - else - { - //There no ilst or meta header so we set to position where it would be if it existed - positionOfNewIlstAtomRelativeToMoovAtom = moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH; - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten = (int) (moovHeader.getFileEndPos()); - } - } - //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 last trak atom, as that means - // all modifications to trak atoms and its children (stco atoms) are *explicitly* written - // as part of the moov atom (and not just bulk copied via writeDataAfterIlst()) - if (metaHeader != null) - { - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten = (int) trakHeader.getFileEndPos(); - positionOfNewIlstAtomRelativeToMoovAtom = (int) (positionInExistingFileOfWhereNewIlstAtomShouldBeWritten - (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 - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten = (int) (moovHeader.getFileEndPos()); - positionOfNewIlstAtomRelativeToMoovAtom = moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH; - } - } - - //Find size of Level-4 Free atom (if any) immediately after ilst atom - sizeOfExistingMetaLevelFreeAtom = getMetaLevelFreeAtomSize(atomTree); - - - //Level-1 free atom - positionOfTopLevelFreeAtom = 0; - sizeOfExistingTopLevelFreeAtom = 0; - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata = true; - for (DefaultMutableTreeNode freeNode : atomTree.getFreeNodes()) - { - DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) freeNode.getParent(); - if (parentNode.isRoot()) - { - topLevelFreeHeader = ((Mp4BoxHeader) freeNode.getUserObject()); - sizeOfExistingTopLevelFreeAtom = topLevelFreeHeader.getLength(); - positionOfTopLevelFreeAtom = (int) topLevelFreeHeader.getFilePos(); - break; - } - } - - if (sizeOfExistingTopLevelFreeAtom > 0) - { - if (positionOfTopLevelFreeAtom > mdatHeader.getFilePos()) - { - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata = false; - } - else if (positionOfTopLevelFreeAtom < moovHeader.getFilePos()) - { - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata = false; - } - } - else - { - positionOfTopLevelFreeAtom = (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 ilst - if (sizeOfExistingIlstAtom == sizeRequiredByNewIlstAtom) - { - writeMetadataSameSize(fileReadChannel, fileWriteChannel, ilstHeader, newIlstData, neroTagsHeader); - } - //.. 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 (sizeOfExistingIlstAtom > sizeRequiredByNewIlstAtom) - { - writeOldMetadataLargerThanNewMetadata(fileReadChannel, - fileWriteChannel, - moovHeader, - udtaHeader, - metaHeader, - ilstHeader, - mdatHeader, - neroTagsHeader, - moovBuffer, - newIlstData, - stcos, - sizeOfExistingMetaLevelFreeAtom); - } - //Size of metadata has increased, the most complex situation, more atoms affected - else - { - int additionalSpaceRequiredForMetadata = sizeRequiredByNewIlstAtom - sizeOfExistingIlstAtom; - if (additionalSpaceRequiredForMetadata <= (sizeOfExistingMetaLevelFreeAtom - Mp4BoxHeader.HEADER_LENGTH)) - { - writeNewMetadataLargerButCanUseFreeAtom( - fileReadChannel, - fileWriteChannel, - ilstHeader, - neroTagsHeader, - sizeOfExistingMetaLevelFreeAtom, - newIlstData, - additionalSpaceRequiredForMetadata); - } - //There is not enough padding in the metadata free atom anyway - else - { - int additionalMetaSizeThatWontFitWithinMetaAtom = additionalSpaceRequiredForMetadata - (sizeOfExistingMetaLevelFreeAtom); - - //Write stuff before Moov (ftyp) - writeUpToMoovHeader(fileReadChannel, fileWriteChannel, moovHeader); - if (udtaHeader == null) - { - writeNoExistingUdtaAtom(fileReadChannel, - fileWriteChannel, - newIlstData, - moovHeader, - moovBuffer, - mdatHeader, - stcos, - sizeOfExistingTopLevelFreeAtom, - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - neroTagsHeader, - sizeOfExistingMetaLevelFreeAtom, - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten, - sizeOfExistingIlstAtom, - positionOfTopLevelFreeAtom, - additionalMetaSizeThatWontFitWithinMetaAtom); - } - else if (metaHeader == null) - { - writeNoExistingMetaAtom( - udtaHeader, - fileReadChannel, - fileWriteChannel, - newIlstData, - moovHeader, - moovBuffer, - mdatHeader, - stcos, - sizeOfExistingTopLevelFreeAtom, - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - neroTagsHeader, - sizeOfExistingMetaLevelFreeAtom, - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten, - sizeOfExistingIlstAtom, - positionOfTopLevelFreeAtom, - additionalMetaSizeThatWontFitWithinMetaAtom); - } - else - { - writeHaveExistingMetadata(udtaHeader, - metaHeader, - fileReadChannel, - fileWriteChannel, - positionOfNewIlstAtomRelativeToMoovAtom, - moovHeader, - moovBuffer, - mdatHeader, - stcos, - additionalMetaSizeThatWontFitWithinMetaAtom, - sizeOfExistingTopLevelFreeAtom, - topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - newIlstData, - neroTagsHeader, - sizeOfExistingMetaLevelFreeAtom, - positionInExistingFileOfWhereNewIlstAtomShouldBeWritten, - sizeOfExistingIlstAtom); - } - - } - } - //Close all channels to original file - fileReadChannel.close(); - raf.close(); - - //Ensure we have written correctly, reject if not - checkFileWrittenCorrectly(rafTemp, mdatHeader, fileWriteChannel, stcos); - } - - private void writeUpToMoovHeader(FileChannel fileReadChannel, - FileChannel fileWriteChannel, - Mp4BoxHeader moovHeader) - throws IOException, CannotWriteException - { - //Write stuff before Moov (ftyp) - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, moovHeader.getFilePos()); - fileWriteChannel.position(moovHeader.getFilePos()); - } - - /** - * Write the remainder of data in read channel to write channel data in {@link TagOptionSingleton#getWriteChunkSize()} - * 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); - } - - if(mod > 0) - { - 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 {@code 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 {@code ilst}. - *

Can be used as long as we don't have to adjust the size of {@code moov} header. - * - * @param fileReadChannel - * @param fileWriteChannel - * @param ilstHeader - * @param newIlstAtomData - * @throws IOException - */ - private void writeDataUptoIncludingIlst(FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader ilstHeader, ByteBuffer newIlstAtomData) throws IOException - { - fileReadChannel.position(0); - fileWriteChannel.transferFrom(fileReadChannel, 0, ilstHeader.getFilePos()); - fileWriteChannel.position(ilstHeader.getFilePos()); - fileWriteChannel.write(newIlstAtomData); - fileReadChannel.position(ilstHeader.getFileEndPos()); - } - - /** - * Write data after {@code ilst} up to the end of the file. - *

- *

Can be used if don't need to adjust size of {@code moov} header of modify top level {@code 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 {@code free} atom immediately after {@code ilst} atom at the same level (if any), - * we can use this if {@code 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 stcos - * @throws CannotWriteException - * @throws IOException - */ - private void checkFileWrittenCorrectly(RandomAccessFile rafTemp, Mp4BoxHeader mdatHeader, FileChannel fileWriteChannel, List stcos) 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 that we at the very least have the same number of chunk offsets - final List newStcos = newAtomTree.getStcos(); - if (newStcos.size() != stcos.size()) - { - // at the very least, we have to have the same number of 'stco' atoms - throw new CannotWriteException(ErrorMessage.MP4_CHANGES_TO_FILE_FAILED_INCORRECT_NUMBER_OF_TRACKS.getMsg(stcos.size(), newStcos.size())); - } - //Check offsets are correct, may not match exactly in original file so just want to make - //sure that the discrepancy if any is preserved - - // compare the first new stco offset with mdat, - // and ensure that all following ones have a constant shift - - int shift = 0; - for (int i=0; i - *

This is achieved by writing an empty {@code 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()); - } - } - - /** - * Use when we need to write metadata and there is no existing {@code udta} atom so we have to create the complete - * udta/metadata structure. - * - * @param fileWriteChannel - * @param newIlstData - * @param moovHeader - * @param moovBuffer - * @param mdatHeader - * @param stcos - * @param sizeOfExistingTopLevelFreeAtom - * @param topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata - * @throws IOException - * @throws CannotWriteException - */ - private void writeNoExistingUdtaAtom(FileChannel fileReadChannel, - FileChannel fileWriteChannel, - ByteBuffer newIlstData, - Mp4BoxHeader moovHeader, - ByteBuffer moovBuffer, - Mp4BoxHeader mdatHeader, - List stcos, - int sizeOfExistingTopLevelFreeAtom, - boolean topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - Mp4BoxHeader neroTagsHeader, - int sizeOfExistingMetaLevelFreeAtom, - int positionInExistingFileOfWhereNewIlstAtomShouldBeWritten, - int existingSizeOfIlstData, - int topLevelFreeSize, - int additionalMetaSizeThatWontFitWithinMetaAtom) - throws IOException, CannotWriteException - - { - logger.severe("Writing:Option 5.1;No udta atom"); - long endOfMoov = moovHeader.getFileEndPos(); - Mp4HdlrBox hdlrBox = Mp4HdlrBox.createiTunesStyleHdlrBox(); - Mp4MetaBox metaBox = Mp4MetaBox.createiTunesStyleMetaBox(hdlrBox.getHeader().getLength() + newIlstData.limit()); - Mp4BoxHeader udtaHeader = new Mp4BoxHeader(Mp4AtomIdentifier.UDTA.getFieldName()); - udtaHeader.setLength(Mp4BoxHeader.HEADER_LENGTH + metaBox.getHeader().getLength()); - - boolean isMdatDataMoved = adjustStcosIfNoSuitableTopLevelAtom(sizeOfExistingTopLevelFreeAtom, topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, udtaHeader.getLength(), stcos, moovHeader, mdatHeader); - - //Edit the Moov header to length and rewrite to account for new udta atom - moovHeader.setLength(moovHeader.getLength() + udtaHeader.getLength()); - fileWriteChannel.write(moovHeader.getHeaderData()); - moovBuffer.rewind(); - 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()); - - //Now write ilst data - fileWriteChannel.write(newIlstData); - - //Skip over the read channel existing ilst(if exists) and metadata free atom - fileReadChannel.position(positionInExistingFileOfWhereNewIlstAtomShouldBeWritten + existingSizeOfIlstData + sizeOfExistingMetaLevelFreeAtom); - //Write the remainder of any data in the moov buffer thats comes after existing ilst/metadata level free atoms - //but we replace any neroTags atoms with free atoms as these cause problems - if (neroTagsHeader != null) - { - writeFromEndOfIlstToNeroTagsAndMakeNeroFree(endOfMoov, fileReadChannel, fileWriteChannel, neroTagsHeader); - } - else - { - //Write the remaining children under moov that come after ilst/free which wont have changed - long extraData = endOfMoov - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), extraData); - fileWriteChannel.position(fileWriteChannel.position() + extraData); - } - - if (!isMdatDataMoved) - { - adjustFreeAtom(fileReadChannel, fileWriteChannel, topLevelFreeSize, additionalMetaSizeThatWontFitWithinMetaAtom); - } - else - { - logger.config("Writing:Option 9;Top Level Free comes after Mdat or before Metadata or not large enough"); - } - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - - /** - * Use when we need to write metadata, we have a {@code udta} atom but there is no existing meta atom so we - * have to create the complete metadata structure. - * - * @param fileWriteChannel - * @param newIlstData - * @param moovHeader - * @param moovBuffer - * @param mdatHeader - * @param stcos - * @param sizeOfExistingTopLevelFreeAtom - * @param topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata - * @throws IOException - * @throws CannotWriteException - */ - private void writeNoExistingMetaAtom(Mp4BoxHeader udtaHeader, - FileChannel fileReadChannel, - FileChannel fileWriteChannel, - ByteBuffer newIlstData, - Mp4BoxHeader moovHeader, - ByteBuffer moovBuffer, - Mp4BoxHeader mdatHeader, - List stcos, - int sizeOfExistingTopLevelFreeAtom, - boolean topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - Mp4BoxHeader neroTagsHeader, - int sizeOfExistingMetaLevelFreeAtom, - int positionInExistingFileOfWhereNewIlstAtomShouldBeWritten, - int existingSizeOfIlstData, - int topLevelFreeSize, - int additionalMetaSizeThatWontFitWithinMetaAtom) throws IOException, CannotWriteException - - { - //Create a new udta atom - logger.severe("Writing:Option 5.2;No meta atom"); - - long endOfMoov = moovHeader.getFileEndPos(); - - int newIlstDataSize = newIlstData.limit(); - int existingMoovHeaderDataLength = moovHeader.getDataLength(); - - //Udta didnt have a meta atom but it may have some other data we want to preserve (I think) - int existingUdtaLength = udtaHeader.getLength(); - int existingUdtaDataLength = udtaHeader.getDataLength(); - - Mp4HdlrBox hdlrBox = Mp4HdlrBox.createiTunesStyleHdlrBox(); - Mp4MetaBox metaBox = Mp4MetaBox.createiTunesStyleMetaBox(hdlrBox.getHeader().getLength() + newIlstDataSize); - udtaHeader = new Mp4BoxHeader(Mp4AtomIdentifier.UDTA.getFieldName()); - udtaHeader.setLength(Mp4BoxHeader.HEADER_LENGTH + metaBox.getHeader().getLength() + existingUdtaDataLength); - - int increaseInSizeOfUdtaAtom = udtaHeader.getDataLength() - existingUdtaDataLength; - - boolean isMdatDataMoved = adjustStcosIfNoSuitableTopLevelAtom(sizeOfExistingTopLevelFreeAtom, topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, increaseInSizeOfUdtaAtom, stcos, moovHeader, mdatHeader); - - //Edit and rewrite the Moov header upto start of Udta - moovHeader.setLength(moovHeader.getLength() + increaseInSizeOfUdtaAtom); - fileWriteChannel.write(moovHeader.getHeaderData()); - moovBuffer.rewind(); - moovBuffer.limit(existingMoovHeaderDataLength - existingUdtaLength); - fileWriteChannel.write(moovBuffer); - - //Write new atoms required for holding metadata in iTunes format - fileWriteChannel.write(udtaHeader.getHeaderData()); - - //Write any atoms if they previously existed within udta atom - if(moovBuffer.position() + Mp4BoxHeader.HEADER_LENGTH < moovBuffer.capacity()) - { - moovBuffer.limit(moovBuffer.capacity()); - moovBuffer.position(moovBuffer.position() + Mp4BoxHeader.HEADER_LENGTH); - fileWriteChannel.write(moovBuffer); - } - - //Write our newly constructed meta/hdlr headers (required for ilst) - fileWriteChannel.write(metaBox.getHeader().getHeaderData()); - fileWriteChannel.write(metaBox.getData()); - fileWriteChannel.write(hdlrBox.getHeader().getHeaderData()); - fileWriteChannel.write(hdlrBox.getData()); - - //Now write ilst data - fileWriteChannel.write(newIlstData); - - //Skip over the read channel existing ilst(if exists) and metadata free atom - fileReadChannel.position(positionInExistingFileOfWhereNewIlstAtomShouldBeWritten + existingSizeOfIlstData + sizeOfExistingMetaLevelFreeAtom); - //Write the remainder of any data in the moov buffer thats comes after existing ilst/metadata level free atoms - //but we replace any neroTags atoms with free atoms as these cause problems - if (neroTagsHeader != null) - { - writeFromEndOfIlstToNeroTagsAndMakeNeroFree(endOfMoov, fileReadChannel, fileWriteChannel, neroTagsHeader); - } - else - { - //Now write the rest of children under moov thats come after ilst/free which wont have changed - long extraData = endOfMoov - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), extraData); - fileWriteChannel.position(fileWriteChannel.position() + extraData); - } - - if (!isMdatDataMoved) - { - adjustFreeAtom(fileReadChannel, fileWriteChannel, topLevelFreeSize, additionalMetaSizeThatWontFitWithinMetaAtom); - } - else - { - logger.config("Writing:Option 9;Top Level Free comes after Mdat or before Metadata or not large enough"); - } - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - - /** - * We have existing structure but we need more space. - * - * @param udtaHeader - * @param fileWriteChannel - * @param positionOfNewIlstAtomRelativeToMoovAtom - * @param moovHeader - * @param moovBuffer - * @param mdatHeader - * @param stcos - * @param additionalMetaSizeThatWontFitWithinMetaAtom - * @param topLevelFreeSize - * @param topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata - * @throws IOException - * @throws CannotWriteException - */ - private void writeHaveExistingMetadata(Mp4BoxHeader udtaHeader, - Mp4BoxHeader metaHeader, - FileChannel fileReadChannel, - FileChannel fileWriteChannel, - int positionOfNewIlstAtomRelativeToMoovAtom, - Mp4BoxHeader moovHeader, - ByteBuffer moovBuffer, - Mp4BoxHeader mdatHeader, - List stcos, - int additionalMetaSizeThatWontFitWithinMetaAtom, - int topLevelFreeSize, - boolean topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - ByteBuffer newIlstData, - Mp4BoxHeader neroTagsHeader, - int sizeOfExistingMetaLevelFreeAtom, - int positionInExistingFileOfWhereNewIlstAtomShouldBeWritten, - int existingSizeOfIlstData) - throws IOException, CannotWriteException - { - logger.config("Writing:Option 5.3;udta and meta atom exists"); - - boolean isMdatDataMoved = adjustStcosIfNoSuitableTopLevelAtom(topLevelFreeSize, topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, additionalMetaSizeThatWontFitWithinMetaAtom, stcos, moovHeader, mdatHeader); - - long endOfMoov = moovHeader.getFileEndPos(); - - //Edit and rewrite the Moov header inc udta and meta headers) - adjustSizeOfMoovHeader(moovHeader, moovBuffer, additionalMetaSizeThatWontFitWithinMetaAtom, udtaHeader, metaHeader); - fileWriteChannel.write(moovHeader.getHeaderData()); - - //Now write from this edited buffer up until location of start of ilst atom - moovBuffer.rewind(); - moovBuffer.limit(positionOfNewIlstAtomRelativeToMoovAtom); - fileWriteChannel.write(moovBuffer); - - //Now write ilst data - fileWriteChannel.write(newIlstData); - - //Write the remainder of any data in the moov buffer thats comes after existing ilst/metadata level free atoms - //but we replace any neroTags atoms with free atoms as these cause problems - if (neroTagsHeader != null) - { - //Skip over the read channel existing ilst(if exists) and metadata free atom - fileReadChannel.position(positionInExistingFileOfWhereNewIlstAtomShouldBeWritten + existingSizeOfIlstData + sizeOfExistingMetaLevelFreeAtom); - // TODO: Does this handle changed stco tags correctly that occur *after* ilst? - writeFromEndOfIlstToNeroTagsAndMakeNeroFree(endOfMoov, fileReadChannel, fileWriteChannel, neroTagsHeader); - } - else - { - //Write the remaining children under moov that come after ilst/free - //These might have changed, if they contain stco atoms - moovBuffer.limit(moovBuffer.capacity()); - moovBuffer.position(positionOfNewIlstAtomRelativeToMoovAtom + existingSizeOfIlstData + sizeOfExistingMetaLevelFreeAtom); - fileWriteChannel.write(moovBuffer); - fileReadChannel.position(moovHeader.getFileEndPos() - additionalMetaSizeThatWontFitWithinMetaAtom); - } - - if (!isMdatDataMoved) - { - adjustFreeAtom(fileReadChannel, fileWriteChannel, topLevelFreeSize, additionalMetaSizeThatWontFitWithinMetaAtom); - } - else - { - logger.config("Writing:Option 9;Top Level Free comes after Mdat or before Metadata or not large enough"); - } - writeDataInChunks(fileReadChannel, fileWriteChannel); - } - - /** - * If any data between existing {@code ilst} atom and {@code tags} atom write it to new file, then convert - * {@code tags} atom to a {@code free} atom. - * - * @param endOfMoov - * @param fileReadChannel - * @param fileWriteChannel - * @param neroTagsHeader - * @throws IOException - */ - private void writeFromEndOfIlstToNeroTagsAndMakeNeroFree(long endOfMoov, FileChannel fileReadChannel, FileChannel fileWriteChannel, Mp4BoxHeader neroTagsHeader) - throws IOException - { - //Write from after ilst upto tags atom - long writeBetweenIlstAndTags = neroTagsHeader.getFilePos() - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), writeBetweenIlstAndTags); - fileWriteChannel.position(fileWriteChannel.position() + writeBetweenIlstAndTags); - convertandWriteTagsAtomToFreeAtom(fileWriteChannel, neroTagsHeader); - - //Write after tags atom upto end of moov - fileReadChannel.position(neroTagsHeader.getFileEndPos()); - long extraData = endOfMoov - fileReadChannel.position(); - fileWriteChannel.transferFrom(fileReadChannel, fileWriteChannel.position(), extraData); - } - - /** - * We adjust {@code free} atom, allowing us to not need to move {@code mdat} atom. - * - * @param fileReadChannel - * @param fileWriteChannel - * @param topLevelFreeSize - * @param additionalMetaSizeThatWontFitWithinMetaAtom - * @throws IOException - * @throws CannotWriteException - */ - private void adjustFreeAtom(FileChannel fileReadChannel, FileChannel fileWriteChannel, int topLevelFreeSize, int additionalMetaSizeThatWontFitWithinMetaAtom) - throws IOException, CannotWriteException - { - //If the shift is less than the space available in this second free atom data size we just - //shrink the free atom accordingly - 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); - } - //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); - } - else - { - //MDAT comes before MOOV, nothing to do because data has already been written - } - } - - /** - * May need to rewrite the {@code stco} offsets, if the location of {@code mdat} (audio) header is going to move. - * - * @param topLevelFreeSize - * @param topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata - * @param additionalSizeRequired - * @param stcos - * @param moovHeader - * @param mdatHeader - * - * @return {@code true}, if offsets were adjusted because unable to fit in new - * metadata without shifting {@code mdat} header further down - */ - private boolean adjustStcosIfNoSuitableTopLevelAtom(int topLevelFreeSize, - boolean topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata, - int additionalSizeRequired, - List stcos, - Mp4BoxHeader moovHeader, - Mp4BoxHeader mdatHeader) - { - //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 as long as mdat is after moov - if (mdatHeader.getFilePos() > moovHeader.getFilePos()) - { - //Edit stco atoms 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 not matching exactly the free atom plus header so could remove free atom completely) - if ((!topLevelFreeAtomComesBeforeMdatAtomAndAfterMetadata) || - ((topLevelFreeSize - Mp4BoxHeader.HEADER_LENGTH < additionalSizeRequired) - && (topLevelFreeSize != additionalSizeRequired))) - { - for (final Mp4StcoBox stoc : stcos) - { - stoc.adjustOffsets(additionalSizeRequired); - } - return true; - } - } - return false; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java deleted file mode 100644 index 751759c9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/AbstractMp4Box.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java deleted file mode 100644 index 8a583790..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4AlacBox.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * AlacBox ( Apple Lossless Codec information description box), - * - * Normally occurs twice, the first ALAC contains 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); - dataBuffer.order(ByteOrder.BIG_ENDIAN); - - maxSamplePerFrame = dataBuffer.getInt(); - unknown1 = Utils.u(dataBuffer.get()); - sampleSize = Utils.u(dataBuffer.get()); - historyMult = Utils.u(dataBuffer.get()); - initialHistory = Utils.u(dataBuffer.get()); - kModifier = Utils.u(dataBuffer.get()); - channels = Utils.u(dataBuffer.get()); - unknown2 = dataBuffer.getShort(); - maxCodedFrameSize = dataBuffer.getInt(); - bitRate = dataBuffer.getInt(); - sampleRate = dataBuffer.getInt(); - } - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java deleted file mode 100644 index 30c343f7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4BoxHeader.java +++ /dev/null @@ -1,385 +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 com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.exceptions.InvalidBoxHeaderException; -import com.mp3.jaudiotagger.audio.exceptions.NullBoxIdException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.logging.ErrorMessage; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; -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 -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.mp4.atom"); - - 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; - - //Box identifier - private String id; - - //Box length - protected int length; - - //If reading from file , this can be used to hold the headers position in the file - private long filePos; - - //Raw Header data - protected ByteBuffer dataBuffer; - - //Mp4 uses UTF-8 for all text - public static final String CHARSET_UTF_8 = "UTF-8"; - - /** - * 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); - } - - /** - * 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); - dataBuffer.order(ByteOrder.BIG_ENDIAN); - - //Calculate box size and id - this.length = dataBuffer.getInt(); - this.id = Utils.readFourBytesAsChars(dataBuffer); - - 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 fc.size()) - { - return null; - } - headerBuffer.rewind(); - bytesRead = fc.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 - * @throws IOException - * @return - */ - 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; - } - - /** - * @return location in file of the start of atom header (i.e where the 4 byte length field starts) - */ - public long getFilePos() - { - return filePos; - } - - /** - * - * @return location in file of the end of atom - */ - public long getFileEndPos() - { - return filePos + length; - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java deleted file mode 100644 index 35656060..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4DrmsBox.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java deleted file mode 100644 index ee9ca018..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4EsdsBox.java +++ /dev/null @@ -1,342 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -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; - - //Data we are tring to extract - private Kind kind; - private AudioProfile audioProfile; - private int numberOfChannels; - private int maxBitrate; - private int avgBitrate; - - //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); - } - } - - /** - * 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; - dataBuffer.order(ByteOrder.BIG_ENDIAN); - - //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 = dataBuffer.getInt(); - this.avgBitrate = dataBuffer.getInt(); - } - //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 = Utils.u(dataBuffer.get()); - } - else - { - datalength = Utils.u(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 static 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 static 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java deleted file mode 100644 index de62283f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FreeBox.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.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(Mp4AtomIdentifier.FREE.getFieldName().getBytes(StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java deleted file mode 100644 index 31527606..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4FtypBox.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -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 String majorBrand; - private int majorBrandVersion; - private List compatibleBrands = new ArrayList(); - - 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 - - /** - * @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; - this.dataBuffer.order(ByteOrder.BIG_ENDIAN); - } - - 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 = dataBuffer.getInt(); - 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 static 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java deleted file mode 100644 index c70de5eb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4HdlrBox.java +++ /dev/null @@ -1,177 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.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 int reserved; // 32 bit - private String handlerType; // 4 bytes; - private String name; // Variable length but 4 bytes in existing files - private MediaDataType mediaDataType; - - 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); - } - } - /** - * 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; - } - - public void processData() throws CannotReadException - { - //Skip other flags - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + RESERVED_FLAG_LENGTH); - - - CharsetDecoder decoder = Charset.forName("ISO-8859-1").newDecoder(); - try - { - handlerType = decoder.decode((ByteBuffer) dataBuffer.slice().limit(HANDLER_LENGTH)).toString(); - } - catch (CharacterCodingException cee) - { - //Ignore - - } - - //To getFields human readable name - mediaDataType = mediaDataTypeMap.get( handlerType); - } - - public String getHandlerType() - { - return handlerType; - } - - public MediaDataType getMediaDataType() - { - return mediaDataType; - } - - public String toString() - { - String s = "handlerType:" + handlerType + ":human readable:"+mediaDataType.getDescription(); - return s; - } - - public static enum MediaDataType - { - ODSM("odsm", "ObjectDescriptorStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - CRSM("crsm", "ClockReferenceStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - SDSM("sdsm", "SceneDescriptionStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - M7SM("m7sm", "MPEG7Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - OCSM("ocsm", "ObjectContentInfoStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - IPSM("ipsm", "IPMP Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - MJSM("mjsm", "MPEG-J Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"), - MDIR("mdir", "Apple Meta Data iTunes Reader"), - MP7B("mp7b", "MPEG-7 binary XML"), - MP7T("mp7t", "MPEG-7 XML"), - VIDE("vide", "Video Track"), - SOUN("soun", "Sound Track"), - HINT("hint", "Hint Track"), - APPL("appl", "Apple specific"), - META("meta", "Timed Metadata track - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"),; - - private String id; - private String description; - - - MediaDataType(String id, String description) - { - this.id = id; - this.description=description; - } - - public String getId() - { - return id; - } - - public String getDescription() - { - return description; - } - } - - /** - * 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

- * - * @return - */ - public static Mp4HdlrBox createiTunesStyleHdlrBox() - { - Mp4BoxHeader hdlrHeader = new Mp4BoxHeader(Mp4AtomIdentifier.HDLR.getFieldName()); - hdlrHeader.setLength(Mp4BoxHeader.HEADER_LENGTH + Mp4HdlrBox.ITUNES_META_HDLR_DAT_LENGTH); - - ByteBuffer hdlrData = ByteBuffer.allocate(Mp4HdlrBox.ITUNES_META_HDLR_DAT_LENGTH); - hdlrData.put(HANDLER_POS,(byte)0x6d); //mdir - hdlrData.put(HANDLER_POS+1,(byte)0x64); - hdlrData.put(HANDLER_POS+2,(byte)0x69); - hdlrData.put(HANDLER_POS+3,(byte)0x72); - hdlrData.put(RESERVED1_POS,(byte)0x61); //appl - hdlrData.put(RESERVED1_POS+1,(byte)0x70); - hdlrData.put(RESERVED1_POS+2,(byte)0x70); - hdlrData.put(RESERVED1_POS+3,(byte)0x6c); - hdlrData.rewind(); - - Mp4HdlrBox hdlrBox = new Mp4HdlrBox(hdlrHeader,hdlrData); - return hdlrBox; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MdhdBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MdhdBox.java deleted file mode 100644 index a86d38e2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MdhdBox.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * MdhdBox ( media (stream) header), holds the Sampling Rate used. - */ -public class Mp4MdhdBox 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 samplingRate; - private long timeLength; - /** - * @param header header info - * @param dataBuffer data of box (doesnt include header data) - */ - public Mp4MdhdBox(Mp4BoxHeader header, ByteBuffer dataBuffer) - { - this.header = header; - dataBuffer.order(ByteOrder.BIG_ENDIAN); - byte version = dataBuffer.get(VERSION_FLAG_POS); - - if (version == LONG_FORMAT) - { - this.samplingRate = dataBuffer.getInt(TIMESCALE_LONG_POS); - timeLength = dataBuffer.getLong(DURATION_LONG_POS); - - } - else - { - this.samplingRate = dataBuffer.getInt(TIMESCALE_SHORT_POS); - timeLength = Utils.u(dataBuffer.getInt(DURATION_SHORT_POS)); - - } - } - - public int getSampleRate() - { - return samplingRate; - } - - public long getTimeLength() - { - return timeLength; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MetaBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MetaBox.java deleted file mode 100644 index 52bfa692..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MetaBox.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.mp4.Mp4AtomIdentifier; -import com.mp3.jaudiotagger.logging.ErrorMessage; - -import java.nio.ByteBuffer; - -/** - * This MP4 MetaBox is the parent of metadata, it usually contains four bytes of data - * that needs to be processed before we can examine the children. But I also have a file that contains - * meta (and no udta) that does not have this children data. - */ -public class Mp4MetaBox extends AbstractMp4Box -{ - public static final int FLAGS_LENGTH = 4; - - /** - * @param header header info - * @param dataBuffer data of box (doesn't include header data) - */ - public Mp4MetaBox(Mp4BoxHeader header, ByteBuffer dataBuffer) - { - this.header = header; - this.dataBuffer = dataBuffer; - } - - 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()); - } - } - - /** - * Create an iTunes style Meta box - * - *

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; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java deleted file mode 100644 index d386d766..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4Mp4aBox.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.java deleted file mode 100644 index 83bf1676..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4MvhdBox.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 com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * 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; - dataBuffer.order(ByteOrder.BIG_ENDIAN); - byte version = dataBuffer.get(VERSION_FLAG_POS); - - if (version == LONG_FORMAT) - { - timeScale = dataBuffer.getInt(TIMESCALE_LONG_POS); - timeLength = dataBuffer.getLong(DURATION_LONG_POS); - - } - else - { - timeScale = dataBuffer.getInt(TIMESCALE_SHORT_POS); - timeLength = Utils.u(dataBuffer.getInt(DURATION_SHORT_POS)); - } - } - - public int getLength() - { - return (int) (this.timeLength / this.timeScale); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java deleted file mode 100644 index 26017ed4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StcoBox.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.Mp4AtomIdentifier; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; - -/** - * 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(); - dataBuffer.order(ByteOrder.BIG_ENDIAN); - //Skip the flags - dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH); - - //No of offsets - this.noOfOffSets = dataBuffer.getInt(); - - //First Offset, useful for sanity checks - firstOffSet = dataBuffer.getInt(); - } - - 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 = dataBuffer.getInt(); - System.out.println("offset into audio data is:" + offset); - } - int offset = dataBuffer.getInt(); - 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 = dataBuffer.getInt(); - - //Calculate new offset and update buffer - offset = offset + adjustment; - dataBuffer.position(dataBuffer.position() - OFFSET_LENGTH); - dataBuffer.putInt(offset); - } - } - - /** - * 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)); - } - } - - /** - * The number of offsets - * - * @return - */ - public int getNoOfOffSets() - { - return noOfOffSets; - } - - /** - * The value of the first offset - * - * @return - */ - public int getFirstOffSet() - { - return firstOffSet; - } - - public static Mp4StcoBox getStco(RandomAccessFile raf) throws IOException, CannotReadException - { - FileChannel fc = raf.getChannel(); - Mp4BoxHeader moovHeader = Mp4BoxHeader.seekWithinLevel(fc, 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); - fc.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); - return stco; - } - - public static void debugShowStcoInfo(RandomAccessFile raf) throws IOException, CannotReadException - { - Mp4StcoBox stco = getStco(raf); - stco.printAllOffsets(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java deleted file mode 100644 index 619cb821..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/Mp4StsdBox.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.mp3.jaudiotagger.audio.mp4.atom; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/NullPadding.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/NullPadding.java deleted file mode 100644 index 6e917958..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/mp4/atom/NullPadding.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileReader.java deleted file mode 100644 index a6dec8e6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileReader.java +++ /dev/null @@ -1,141 +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 com.mp3.jaudiotagger.audio.ogg; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.ogg.util.OggInfoReader; -import com.mp3.jaudiotagger.audio.ogg.util.OggPageHeader; -import com.mp3.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("com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileWriter.java deleted file mode 100644 index 19990017..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggFileWriter.java +++ /dev/null @@ -1,52 +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 com.mp3.jaudiotagger.audio.ogg; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter; -import com.mp3.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("com.mp3.jaudiotagger.audio.ogg"); - - private OggVorbisTagWriter vtw = new OggVorbisTagWriter(); - - protected void writeTag(AudioFile audioFile, Tag tag, RandomAccessFile raf, RandomAccessFile rafTemp) throws CannotReadException, CannotWriteException, IOException - { - vtw.write(tag, raf, rafTemp); - } - - protected void deleteTag(Tag tag, RandomAccessFile raf, RandomAccessFile tempRaf) throws CannotReadException, CannotWriteException, IOException - { - vtw.delete(raf, tempRaf); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java deleted file mode 100644 index dc84b67e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisCommentTagCreator.java +++ /dev/null @@ -1,66 +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 com.mp3.jaudiotagger.audio.ogg; - -import com.mp3.jaudiotagger.audio.ogg.util.VorbisHeader; -import com.mp3.jaudiotagger.audio.ogg.util.VorbisPacketType; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.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 -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.ogg"); - - public static final int FIELD_FRAMING_BIT_LENGTH = 1; - public static final byte FRAMING_BIT_VALID_VALUE = (byte) 0x01; - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagReader.java deleted file mode 100644 index 76de1384..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagReader.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 com.mp3.jaudiotagger.audio.ogg; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.ogg.util.OggPageHeader; -import com.mp3.jaudiotagger.audio.ogg.util.VorbisHeader; -import com.mp3.jaudiotagger.audio.ogg.util.VorbisPacketType; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentReader; -import com.mp3.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("com.mp3.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 = new String(headerData, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH, StandardCharsets.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 = new String(headerData, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH, StandardCharsets.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 - * @throws com.mp3.jaudiotagger.audio.exceptions.CannotReadException - * @throws IOException - * @return - */ - 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 - * @throws com.mp3.jaudiotagger.audio.exceptions.CannotReadException - * @throws IOException - * @return - */ - 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 - * @throws com.mp3.jaudiotagger.audio.exceptions.CannotReadException - * @throws IOException - * @return - */ - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagWriter.java deleted file mode 100644 index a5e48102..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/OggVorbisTagWriter.java +++ /dev/null @@ -1,716 +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 com.mp3.jaudiotagger.audio.ogg; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.ogg.util.OggCRCFactory; -import com.mp3.jaudiotagger.audio.ogg.util.OggPageHeader; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v1Tag; -import com.mp3.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("com.mp3.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 com.mp3.jaudiotagger.audio.exceptions.CannotReadException - * @throws com.mp3.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(); - long bytesToDiscard = 0; - while(bb.hasRemaining()) - { - OggPageHeader nextPage=null; - try - { - nextPage = OggPageHeader.read(bb); - } - catch(CannotReadException cre) - { - //Go back to where were - bb.position(bb.position() - OggPageHeader.CAPTURE_PATTERN.length); - //#117:Ogg file with invalid ID3v1 tag at end remove and save - if(Utils.readThreeBytesAsChars(bb).equals(AbstractID3v1Tag.TAG)) - { - bytesToDiscard = bb.remaining() + AbstractID3v1Tag.TAG.length(); - break; - } - else - { - throw cre; - } - } - //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.flip(); - rafTemp.getChannel().write(bbTemp); - //Check we have written all the data (minus any invalid Tag at end) - if ((raf.length() - startAudio) != ((rafTemp.length() + bytesToDiscard) - startAudioWritten)) - { - throw new CannotWriteException("File written counts don't match, file not written:" - +"origAudioLength:"+(raf.length() - startAudio) - +":newAudioLength:"+((rafTemp.length() + bytesToDiscard) - startAudioWritten) - +":bytesDiscarded:"+bytesToDiscard); - } - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/VorbisVersion.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/VorbisVersion.java deleted file mode 100644 index 84f70897..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/VorbisVersion.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggCRCFactory.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggCRCFactory.java deleted file mode 100644 index 1cbef1e9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggCRCFactory.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 com.mp3.jaudiotagger.audio.ogg.util; - -import java.util.logging.Logger; - - -/** - * OffCRC Calculations - * - * $Id$ - * - * @author Raphael Slinckx (KiKiDonK) - * @version 19 d�cembre 2003 - */ -public class OggCRCFactory -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.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 boolean checkCRC(byte[] data, byte[] crc) - { - return new String(crc).equals(new String(computeCRC(data))); - } - - 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; - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggInfoReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggInfoReader.java deleted file mode 100644 index e4d43b19..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggInfoReader.java +++ /dev/null @@ -1,161 +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 com.mp3.jaudiotagger.audio.ogg.util; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.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("com.mp3.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()]; - - if(vorbisData.length < OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH) - { - throw new CannotReadException("Invalid Identification header for this Ogg File"); - } - 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()); - - //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); - } - return info; - } - - private int computeBitrate(int length, long size) - { - //Protect against audio less than 0.5 seconds that can be rounded to zero causing Arithmetic Exception - if(length==0) - { - length=1; - } - return (int) ((size / Utils.KILOBYTE_MULTIPLIER) * Utils.BITS_IN_BYTE_MULTIPLIER / length); - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggPageHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggPageHeader.java deleted file mode 100644 index 7db17a64..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/OggPageHeader.java +++ /dev/null @@ -1,410 +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 com.mp3.jaudiotagger.audio.ogg.util; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.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$ - * - * reference:http://xiph.org/ogg/doc/framing.html - * - * @author Raphael Slinckx (KiKiDonK) - * @version 16 d�cembre 2003 - */ -public class OggPageHeader -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.ogg.atom"); - - //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; - - 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; - - /** - * 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; - } - - 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()); - } - } - - 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.finer("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; - } - - /** - * 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 + "),"; - } - } - - /** - * 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 static 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; - } - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisHeader.java deleted file mode 100644 index d309a4f4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisHeader.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.mp3.jaudiotagger.audio.ogg.util; - -/** - * Defines variables common to all vorbis headers - */ -public interface VorbisHeader -{ - //Capture pattern at start of header - public static final String CAPTURE_PATTERN = "vorbis"; - - public static final byte[] CAPTURE_PATTERN_AS_BYTES = {'v', 'o', 'r', 'b', 'i', 's'}; - - public static final int FIELD_PACKET_TYPE_POS = 0; - public static final int FIELD_CAPTURE_PATTERN_POS = 1; - - public static final int FIELD_PACKET_TYPE_LENGTH = 1; - public static final int FIELD_CAPTURE_PATTERN_LENGTH = 6; - - //Vorbis uses UTF-8 for all text - public static final String CHARSET_UTF_8 = "UTF-8"; - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java deleted file mode 100644 index 90473494..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisIdentificationHeader.java +++ /dev/null @@ -1,163 +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 com.mp3.jaudiotagger.audio.ogg.util; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.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$ - * - * @author Raphael Slinckx (KiKiDonK) - * @version 16 d�cembre 2003 - */ -public class VorbisIdentificationHeader implements VorbisHeader -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.ogg.atom"); - - private int audioChannels; - private boolean isValid = false; - - private int vorbisVersion, audioSampleRate; - private int bitrateMinimal, bitrateNominal, bitrateMaximal; - - 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; - - - 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 = new String(b, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH, StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisPacketType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisPacketType.java deleted file mode 100644 index e2bcfc5d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisPacketType.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java deleted file mode 100644 index 7901ce96..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/ogg/util/VorbisSetupHeader.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.mp3.jaudiotagger.audio.ogg.util; - -import com.mp3.jaudiotagger.StandardCharsets; - -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("com.mp3.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 = new String(b, FIELD_CAPTURE_PATTERN_POS, FIELD_CAPTURE_PATTERN_LENGTH, StandardCharsets.ISO_8859_1); - if (packetType == VorbisPacketType.SETUP_HEADER.getType() && vorbis.equals(CAPTURE_PATTERN)) - { - isValid = true; - } - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealChunk.java deleted file mode 100644 index 3b16c0e3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealChunk.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.mp3.jaudiotagger.audio.real; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.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 static RealChunk readChunk(RandomAccessFile raf) - throws CannotReadException, IOException { - final String id = Utils.readString(raf, 4); - final int size = (int)Utils.readUint32(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 RealChunk(String id, int size, byte[] bytes) { - super(); - this.id = id; - this.size = size; - this.bytes = 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealFileReader.java deleted file mode 100644 index 4a86cace..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealFileReader.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.mp3.jaudiotagger.audio.real; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.tag.FieldDataInvalidException; -import com.mp3.jaudiotagger.tag.FieldKey; -import com.mp3.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 = (int)Utils.readUint32(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.setPreciseLength(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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealTag.java deleted file mode 100644 index edc97fb9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/real/RealTag.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.mp3.jaudiotagger.audio.real; - -import com.mp3.jaudiotagger.audio.generic.GenericTag; -import com.mp3.jaudiotagger.tag.FieldDataInvalidException; -import com.mp3.jaudiotagger.tag.FieldKey; -import com.mp3.jaudiotagger.tag.KeyNotFoundException; -import com.mp3.jaudiotagger.tag.TagField; - -public class RealTag extends GenericTag -{ - public String toString() - { - String output = "REAL " + super.toString(); - return output; - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return createField(FieldKey.IS_COMPILATION,String.valueOf(value)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavChunkType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavChunkType.java deleted file mode 100644 index eca7ca56..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavChunkType.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav; - -import java.util.HashMap; -import java.util.Map; - -/** - * Chunk types mark each {@link com.mp3.jaudiotagger.audio.iff.ChunkHeader}. They are always 4 ASCII chars long. - * - * @see com.mp3.jaudiotagger.audio.iff.Chunk - */ -public enum WavChunkType -{ - FORMAT("fmt ", "Basic Audio Information"), - FACT("fact", "Only strictly required for Non-PCM or compressed data"), - DATA("data", "Stores the actual audio data"), - LIST("LIST", "List chunk, wraps round other chunks"), - INFO("INFO", "Original metadata implementation"), - ID3("id3 ", "Stores metadata in ID3 chunk"), - CORRUPT_LIST("iLIS", "List chunk, wraps round other chunks"), - CORRUPT_ID3_LATE("d3 \u0000", "Stores metadata in ID3 chunk"), - CORRUPT_ID3_EARLY("\u0000id3", "Stores metadata in ID3 chunk"); - ; - - private static final Map CODE_TYPE_MAP = new HashMap(); - private String code; - private String description; - - /** - * Get {@link WavChunkType} for code (e.g. "SSND"). - * - * @param code chunk id - * @return chunk type or {@code null} if not registered - */ - public synchronized static WavChunkType get(final String code) { - if (CODE_TYPE_MAP.isEmpty()) { - for (final WavChunkType type : values()) { - CODE_TYPE_MAP.put(type.getCode(), type); - } - } - return CODE_TYPE_MAP.get(code); - } - - /** - * @param code 4 char string - */ - WavChunkType(final String code, String description) - { - this.code=code; - this.description=description; - } - - /** - * 4 char type code. - * - * @return 4 char type code, e.g. "SSND" for the sound chunk. - */ - public String getCode() - { - return code; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileReader.java deleted file mode 100644 index 4fbe483e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileReader.java +++ /dev/null @@ -1,60 +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 com.mp3.jaudiotagger.audio.wav; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.AudioFileReader2; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.io.File; -import java.io.IOException; - -/** - * Reads Audio and Metadata information contained in Wav file. - */ -public class WavFileReader extends AudioFileReader2 -{ - public WavFileReader() - { - - } - - protected GenericAudioHeader getEncodingInfo(File file) throws CannotReadException, IOException - { - return new WavInfoReader(file.getPath()).read(file); - } - - @Override - protected Tag getTag(File file) throws IOException, CannotReadException - { - WavTag tag = new WavTagReader(file.getPath()).read(file); - switch (TagOptionSingleton.getInstance().getWavOptions()) - { - case READ_ID3_ONLY_AND_SYNC: - case READ_ID3_UNLESS_ONLY_INFO_AND_SYNC: - case READ_INFO_ONLY_AND_SYNC: - case READ_INFO_UNLESS_ONLY_ID3_AND_SYNC: - tag.syncTagsAfterRead(); - } - return tag; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileWriter.java deleted file mode 100644 index 51f62935..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavFileWriter.java +++ /dev/null @@ -1,40 +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 com.mp3.jaudiotagger.audio.wav; - -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.AudioFileWriter2; -import com.mp3.jaudiotagger.tag.Tag; - -import java.io.File; - -public class WavFileWriter extends AudioFileWriter2 -{ - @Override - protected void writeTag(Tag tag, File file) throws CannotWriteException - { - new WavTagWriter(file.getPath()).write(tag, file); - } - - @Override - protected void deleteTag(Tag tag, File file) throws CannotWriteException - { - new WavTagWriter(file.getPath()).delete(tag, file); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavInfoReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavInfoReader.java deleted file mode 100644 index 27961575..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavInfoReader.java +++ /dev/null @@ -1,177 +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 com.mp3.jaudiotagger.audio.wav; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.audio.wav.chunk.WavFactChunk; -import com.mp3.jaudiotagger.audio.wav.chunk.WavFormatChunk; -import com.mp3.jaudiotagger.logging.Hex; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Read the Wav file chunks, until finds WavFormatChunk and then generates AudioHeader from it - */ -public class WavInfoReader { - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.wav"); - - - private String loggingName; - - public WavInfoReader(String loggingName) { - this.loggingName = loggingName; - } - - public GenericAudioHeader read(File file) throws CannotReadException, IOException { - GenericAudioHeader info = new GenericAudioHeader(); - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - if (WavRIFFHeader.isValidHeader(fc)) { - while (fc.position() < fc.size()) { - if (!readChunk(fc, info)) { - break; - } - } - } else { - throw new CannotReadException(loggingName + " Wav RIFF Header not valid"); - } - } finally { - AudioFileIO.closeQuietly(raf); - } - calculateTrackLength(info); - return info; - } - - /** - * Calculate track length, done it here because requires data from multiple chunks - * - * @param info - * @throws CannotReadException - */ - private void calculateTrackLength(GenericAudioHeader info) throws CannotReadException { - //If we have fact chunk we can calculate accurately by taking total of samples (per channel) divided by the number - //of samples taken per second (per channel) - if (info.getNoOfSamples() != null) { - if (info.getSampleRateAsNumber() > 0) { - info.setPreciseLength((float) info.getNoOfSamples() / info.getSampleRateAsNumber()); - } - } - //Otherwise adequate to divide the total number of sampling bytes by the average byte rate - else if (info.getAudioDataLength() > 0) { - info.setPreciseLength((float) info.getAudioDataLength() / info.getByteRate()); - } else { - throw new CannotReadException(loggingName + " Wav Data Header Missing"); - } - } - - /** - * Reads a Wav Chunk. - */ - protected boolean readChunk(FileChannel fc, GenericAudioHeader info) throws IOException, CannotReadException { - Chunk chunk; - ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.LITTLE_ENDIAN); - if (!chunkHeader.readHeader(fc)) { - return false; - } - - String id = chunkHeader.getID(); - logger.fine(loggingName + " Reading Chunk:" + id - + ":starting at:" + Hex.asDecAndHex(chunkHeader.getStartLocationInFile()) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - final WavChunkType chunkType = WavChunkType.get(id); - - //If known chunkType - if (chunkType != null) { - switch (chunkType) { - case FACT: { - ByteBuffer fmtChunkData = Utils.readFileDataIntoBufferLE(fc, (int) chunkHeader.getSize()); - chunk = new WavFactChunk(fmtChunkData, chunkHeader, info); - if (!chunk.readChunk()) { - return false; - } - break; - } - - case DATA: { - //We just need this value from header dont actually need to read data itself - info.setAudioDataLength(chunkHeader.getSize()); - info.setAudioDataStartPosition(fc.position()); - info.setAudioDataEndPosition(fc.position() + chunkHeader.getSize()); - fc.position(fc.position() + chunkHeader.getSize()); - break; - } - - case FORMAT: { - ByteBuffer fmtChunkData = Utils.readFileDataIntoBufferLE(fc, (int) chunkHeader.getSize()); - chunk = new WavFormatChunk(fmtChunkData, chunkHeader, info); - if (!chunk.readChunk()) { - return false; - } - break; - } - - case CORRUPT_LIST: - logger.severe(loggingName + " Found Corrupt LIST Chunk, starting at Odd Location:" + chunkHeader.getID() + ":" + chunkHeader.getSize()); - fc.position(fc.position() - (ChunkHeader.CHUNK_HEADER_SIZE - 1)); - return true; - - //Dont need to do anything with these just skip - default: - logger.config(loggingName + " Skipping chunk bytes:" + chunkHeader.getSize()); - fc.position(fc.position() + chunkHeader.getSize()); - } - } - //Unknown chunk type just skip - else { - if (chunkHeader.getSize() < 0) { - String msg = loggingName + " Not a valid header, unable to read a sensible size:Header" - + chunkHeader.getID() + "Size:" + chunkHeader.getSize(); - logger.severe(msg); - throw new CannotReadException(msg); - } - logger.config(loggingName + " Skipping chunk bytes:" + chunkHeader.getSize() + " for " + chunkHeader.getID()); - - fc.position(fc.position() + chunkHeader.getSize()); - if (fc.position() > fc.size()) { - String msg = loggingName + " Failed to move to invalid position to " + fc.position() + " because file length is only " + fc.size() - + " indicates invalid chunk"; - logger.severe(msg); - throw new CannotReadException(msg); - } - } - IffHeaderChunk.ensureOnEqualBoundary(fc, chunkHeader); - return true; - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavOptions.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavOptions.java deleted file mode 100644 index f9cf2b9e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavOptions.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav; - -/** - * Wav files can store metadata within a LISTINFO chunk, an ID3 chunk, both or neither. When a WavTag is read - * we read both tags if they exist, and if either don't exists we initialize WavTag with empty instances of - * ID3Tag and/or InfoTag. But only one of the tags is accessible through the common interface and WavOptions - * define which one this is. - * - * Here we define how we should interpret WavTag metadata when using the common interface, for example - * if the default READ_ID3_ONLY option is used then methods on Tag interface will read and write to the ID3 - * chunk and ignore the Info Tag for the purposes of the active tag, but the info tag will still be read and - * stored in the info tag. - * If the READ_ID3_UNLESS_ONLY_INFO option is used the same applies as long - * as the file already has an ID3 tag, if it does not but does have an INFO tag then methods apply to the INFO - * chunk instead, so the Info tag becomes the active tag. - * - * Note the INFO tag can only store a small subset of the data that an ID3 tag can so the INFO options should only - * be used to preserve compatibility with legacy applications that do not support ID3 chunks in Wav files. - * - * This option should be set using TagOptionSingleton.setWavOptions(), modifying this option will not affect - * existing instances of WavTag - * - * The _AND_SYNC versions synchronize the active tag with any additional data that may be available in the nonactive tag - * after the initial read. For example if the ID3 tag is the active tag but contains no artist tag, but the nonactive - * Info tag does then the ID3 tag will be initialized with the same value for the artist field. - */ -public enum WavOptions -{ - READ_ID3_ONLY, - READ_INFO_ONLY, - READ_ID3_UNLESS_ONLY_INFO, - READ_INFO_UNLESS_ONLY_ID3, - READ_ID3_ONLY_AND_SYNC, - READ_INFO_ONLY_AND_SYNC, - READ_ID3_UNLESS_ONLY_INFO_AND_SYNC, - READ_INFO_UNLESS_ONLY_ID3_AND_SYNC - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavRIFFHeader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavRIFFHeader.java deleted file mode 100644 index 927d3426..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavRIFFHeader.java +++ /dev/null @@ -1,58 +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 com.mp3.jaudiotagger.audio.wav; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.HEADER_LENGTH; - -/** - * Processes the Wav Header - * - * This is simply the first 12 bytes of the file http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html - */ -public class WavRIFFHeader -{ - public static final String RIFF_SIGNATURE = "RIFF"; - public static final String WAVE_SIGNATURE = "WAVE"; - - public static boolean isValidHeader(FileChannel fc) throws IOException, CannotReadException - { - if (fc.size() - fc.position() < HEADER_LENGTH) - { - throw new CannotReadException("This is not a WAV File (<12 bytes)"); - } - ByteBuffer headerBuffer = Utils.readFileDataIntoBufferLE(fc, HEADER_LENGTH); - if(Utils.readFourBytesAsChars(headerBuffer).equals(RIFF_SIGNATURE)) - { - headerBuffer.getInt(); //Size - if(Utils.readFourBytesAsChars(headerBuffer).equals(WAVE_SIGNATURE)) - { - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOptions.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOptions.java deleted file mode 100644 index a61e137e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOptions.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav; - -/** - * Wav files can store metadata within a LISTINFO chunk, an ID3 chunk, both or neither - * - * Here we define how we should save Wav metadata, the options should be considered in conjunction with the - * option selected in WavOptions - * - * If SAVE_EXISTING_ACTIVE is selected then any chunks currently existing in the file will be saved back to file, plus - * even if the active chink is not currently in the file that will be saved as well. So if WavOptions.READ_ID3_ONLY is enabled - * then an ID3 tag will always be written and the info tag will as well if it already exists, if it does not it will not. - * - * If SAVE_ACTIVE is selected only that tag will be saved to file. So if WavOptions.READ_ID3_ONLY only this will be saved - * to file, any existing INFO chunk will be deleted - * - * If SAVE_BOTH is selected an ID3 chunk and an INFO chunk are always written, regardless of whether or not they currently exist. - * - * The _SYNC_ methods write any data added to the active tag to the inactive tag just before writing and also remove data - * fields that exists in the inactive tag but not the active tag (Except for fields that the inactive tag supports but the active tag does not) - * - * This option should be set using TagOptionSingleton.setWavSaveOptions() - */ -public enum WavSaveOptions -{ - SAVE_EXISTING_AND_ACTIVE, - SAVE_ACTIVE, - SAVE_BOTH, - SAVE_EXISTING_AND_ACTIVE_AND_SYNC, - SAVE_BOTH_AND_SYNC, - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOrder.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOrder.java deleted file mode 100644 index 8a19d36d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSaveOrder.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav; - -/** - * Wav files can store metadata within a LISTINFO chunk, an ID3 chunk, both or neither. - * - * When saving both we can define in which order they should be saved, the correct order - * may be required to better support data in legacy applications - */ -public enum WavSaveOrder -{ - INFO_THEN_ID3, - ID3_THEN_INFO - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSubFormat.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSubFormat.java deleted file mode 100644 index 6138857c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavSubFormat.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav; - -import java.util.HashMap; -import java.util.Map; - -/** - * Wav sub format stored as two byte le integer - */ -public enum WavSubFormat -{ - FORMAT_PCM(0x1,"WAV PCM"), - FORMAT_FLOAT(0x3, "WAV IEEE_FLOAT"), - FORMAT_ALAW(0x6, "WAV A-LAW"), - FORMAT_MULAW(0x7, "WAV µ-LAW"), - FORMAT_EXTENSIBLE(0xFFFE, "EXTENSIBLE"), - FORMAT_GSM_COMPRESSED(0x31, "GSM_COMPRESSED"), - ; - - private int code; - private String description; - - WavSubFormat(int code, String description) - { - this.code=code; - this.description=description; - } - - public int getCode() - { - return code; - } - - public String getDescription() - { - return description; - } - - // Reverse-lookup map for getting a compression type from code - private static final Map lookup = new HashMap(); - - static - { - for (WavSubFormat next : WavSubFormat.values()) - { - lookup.put(next.getCode(), next); - } - } - - public static WavSubFormat getByCode(Integer code) - { - return lookup.get(code); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagReader.java deleted file mode 100644 index 2f7fd61e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagReader.java +++ /dev/null @@ -1,201 +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 com.mp3.jaudiotagger.audio.wav; - -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.audio.wav.chunk.WavId3Chunk; -import com.mp3.jaudiotagger.audio.wav.chunk.WavListChunk; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.wav.WavInfoTag; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.logging.Logger; - -/** - * Read the Wav file chunks, until finds WavFormatChunk and then generates AudioHeader from it - */ -public class WavTagReader { - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.wav"); - - private String loggingName; - - public WavTagReader(String loggingName) { - this.loggingName = loggingName; - } - - - /** - * Read file and return tag metadata - * - * @param file - * @return - * @throws CannotReadException - * @throws IOException - */ - public WavTag read(File file) throws CannotReadException, IOException { - logger.config(loggingName + " Read Tag:start"); - WavTag tag = new WavTag(TagOptionSingleton.getInstance().getWavOptions()); - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - FileChannel fc = raf.getChannel(); - if (WavRIFFHeader.isValidHeader(fc)) { - while (fc.position() < fc.size()) { - if (!readChunk(fc, tag)) { - break; - } - } - } else { - throw new CannotReadException(loggingName + " Wav RIFF Header not valid"); - } - } finally { - AudioFileIO.closeQuietly(raf); - } - createDefaultMetadataTagsIfMissing(tag); - logger.config(loggingName + " Read Tag:end"); - return tag; - } - - /** - * So if the file doesn't contain (both) types of metadata we construct them so data can be - * added and written back to file on save - * - * @param tag - */ - private void createDefaultMetadataTagsIfMissing(WavTag tag) { - if (!tag.isExistingId3Tag()) { - tag.setID3Tag(WavTag.createDefaultID3Tag()); - } - if (!tag.isExistingInfoTag()) { - tag.setInfoTag(new WavInfoTag()); - } - } - - /** - * Reads Wavs Chunk that contain tag metadata - *

- * If the same chunk exists more than once in the file we would just use the last occurence - * - * @param tag - * @return - * @throws IOException - */ - protected boolean readChunk(FileChannel fc, WavTag tag) throws IOException, CannotReadException { - Chunk chunk; - ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.LITTLE_ENDIAN); - if (!chunkHeader.readHeader(fc)) { - return false; - } - - String id = chunkHeader.getID(); - logger.config(loggingName + " Next Id is:" + id + ":FileLocation:" + fc.position() + ":Size:" + chunkHeader.getSize()); - final WavChunkType chunkType = WavChunkType.get(id); - if (chunkType != null) { - switch (chunkType) { - case LIST: - tag.addChunkSummary(new ChunkSummary(chunkHeader.getID(), chunkHeader.getStartLocationInFile(), chunkHeader.getSize())); - if (tag.getInfoTag() == null) { - chunk = new WavListChunk(loggingName, Utils.readFileDataIntoBufferLE(fc, (int) chunkHeader.getSize()), chunkHeader, tag); - if (!chunk.readChunk()) { - return false; - } - } else { - logger.warning(loggingName + " Ignoring LIST chunk because already have one:" + chunkHeader.getID() - + ":" + Hex.asDecAndHex(chunkHeader.getStartLocationInFile() - 1) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - } - break; - - case CORRUPT_LIST: - logger.severe(loggingName + " Found Corrupt LIST Chunk, starting at Odd Location:" + chunkHeader.getID() + ":" + chunkHeader.getSize()); - - if (tag.getInfoTag() == null && tag.getID3Tag() == null) { - tag.setIncorrectlyAlignedTag(true); - } - fc.position(fc.position() - (ChunkHeader.CHUNK_HEADER_SIZE - 1)); - return true; - - case ID3: - tag.addChunkSummary(new ChunkSummary(chunkHeader.getID(), chunkHeader.getStartLocationInFile(), chunkHeader.getSize())); - if (tag.getID3Tag() == null) { - chunk = new WavId3Chunk(Utils.readFileDataIntoBufferLE(fc, (int) chunkHeader.getSize()), chunkHeader, tag); - if (!chunk.readChunk()) { - return false; - } - } else { - logger.warning(loggingName + " Ignoring id3 chunk because already have one:" + chunkHeader.getID() + ":" - + Hex.asDecAndHex(chunkHeader.getStartLocationInFile()) - + ":sizeIncHeader:" + (chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE)); - } - break; - - case CORRUPT_ID3_EARLY: - logger.severe(loggingName + " Found Corrupt id3 chunk, starting at Odd Location:" + chunkHeader.getID() + ":" + chunkHeader.getSize()); - if (tag.getInfoTag() == null && tag.getID3Tag() == null) { - tag.setIncorrectlyAlignedTag(true); - } - fc.position(fc.position() - (ChunkHeader.CHUNK_HEADER_SIZE - 1)); - return true; - - case CORRUPT_ID3_LATE: - logger.severe(loggingName + " Found Corrupt id3 chunk, starting at Odd Location:" + chunkHeader.getID() + ":" + chunkHeader.getSize()); - if (tag.getInfoTag() == null && tag.getID3Tag() == null) { - tag.setIncorrectlyAlignedTag(true); - } - fc.position(fc.position() - (ChunkHeader.CHUNK_HEADER_SIZE - 1)); - return true; - - default: - tag.addChunkSummary(new ChunkSummary(chunkHeader.getID(), chunkHeader.getStartLocationInFile(), chunkHeader.getSize())); - fc.position(fc.position() + chunkHeader.getSize()); - } - } - //Unknown chunk type just skip - else { - if (chunkHeader.getSize() < 0) { - String msg = loggingName + " Not a valid header, unable to read a sensible size:Header" - + chunkHeader.getID() + "Size:" + chunkHeader.getSize(); - logger.severe(msg); - throw new CannotReadException(msg); - } - logger.config(loggingName + " Skipping chunk bytes:" + chunkHeader.getSize() + "for" + chunkHeader.getID()); - fc.position(fc.position() + chunkHeader.getSize()); - if (fc.position() > fc.size()) { - String msg = loggingName + " Failed to move to invalid position to " + fc.position() + " because file length is only " + fc.size() - + " indicates invalid chunk"; - logger.severe(msg); - throw new CannotReadException(msg); - } - } - IffHeaderChunk.ensureOnEqualBoundary(fc, chunkHeader); - return true; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagWriter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagWriter.java deleted file mode 100644 index b8fb2cf4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/WavTagWriter.java +++ /dev/null @@ -1,924 +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 com.mp3.jaudiotagger.audio.wav; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.AudioFileIO; -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.exceptions.CannotWriteException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.audio.wav.chunk.WavChunkSummary; -import com.mp3.jaudiotagger.audio.wav.chunk.WavInfoIdentifier; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.wav.WavInfoTag; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Logger; - -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.SIGNATURE_LENGTH; -import static com.mp3.jaudiotagger.audio.iff.IffHeaderChunk.SIZE_LENGTH; - -/** - * Write Wav Tag. - */ -public class WavTagWriter { - //For logging - private String loggingName; - - public WavTagWriter(String loggingName) { - this.loggingName = loggingName; - } - - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.wav"); - - /** - * Read existing metadata - * - * @param file - * @return tags within Tag wrapper - * @throws IOException - * @throws CannotWriteException - */ - private WavTag getExistingMetadata(File file) throws IOException, CannotWriteException { - try { - //Find WavTag (if any) - WavTagReader im = new WavTagReader(loggingName); - return im.read(file); - } catch (CannotReadException ex) { - throw new CannotWriteException("Failed to read file " + file.getPath()); - } - } - - /** - * Seek in file to start of LIST Metadata chunk - * - * @param fc - * @param existingTag - * @throws IOException - * @throws CannotWriteException - */ - private ChunkHeader seekToStartOfListInfoMetadata(FileChannel fc, WavTag existingTag) throws IOException, CannotWriteException { - fc.position(existingTag.getInfoTag().getStartLocationInFile()); - final ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.LITTLE_ENDIAN); - chunkHeader.readHeader(fc); - fc.position(fc.position() - ChunkHeader.CHUNK_HEADER_SIZE); - - if (!WavChunkType.LIST.getCode().equals(chunkHeader.getID())) { - throw new CannotWriteException(loggingName + " Unable to find List chunk at original location has file been modified externally"); - } - return chunkHeader; - } - - /** - * Seek in file to start of Id3 Metadata chunk - * - * @param fc - * @param existingTag - * @throws IOException - * @throws CannotWriteException - */ - private ChunkHeader seekToStartOfId3Metadata(FileChannel fc, WavTag existingTag) throws IOException, CannotWriteException { - fc.position(existingTag.getStartLocationInFileOfId3Chunk()); - final ChunkHeader chunkHeader = new ChunkHeader(ByteOrder.LITTLE_ENDIAN); - chunkHeader.readHeader(fc); - fc.position(fc.position() - ChunkHeader.CHUNK_HEADER_SIZE); - if (!WavChunkType.ID3.getCode().equals(chunkHeader.getID())) { - throw new CannotWriteException(loggingName + " Unable to find ID3 chunk at original location has file been modified externally"); - } - return chunkHeader; - } - - /** - * Delete any existing metadata tags from files - * - * @param tag - * @param file - * @throws IOException - * @throws CannotWriteException - */ - public void delete(Tag tag, File file) throws CannotWriteException { - logger.info(loggingName + " Deleting metadata from file"); - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - WavTag existingTag = getExistingMetadata(file); - - //have both tags - if (existingTag.isExistingId3Tag() && existingTag.isExistingInfoTag()) { - BothTagsFileStructure fs = checkExistingLocations(existingTag, fc); - //We can delete both chunks in one go - if (fs.isContiguous) { - //Quick method - if (fs.isAtEnd) { - if (fs.isInfoTagFirst) { - logger.info(loggingName + ":Setting new length to:" + existingTag.getInfoTag().getStartLocationInFile()); - fc.truncate(existingTag.getInfoTag().getStartLocationInFile()); - } else { - logger.info(loggingName + ":Setting new length to:" + existingTag.getStartLocationInFileOfId3Chunk()); - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk()); - } - } - //Slower - else { - if (fs.isInfoTagFirst) { - final int lengthTagChunk = (int) (existingTag.getEndLocationInFileOfId3Chunk() - existingTag.getInfoTag().getStartLocationInFile()); - deleteTagChunk(fc, (int) existingTag.getEndLocationInFileOfId3Chunk(), lengthTagChunk); - } else { - final int lengthTagChunk = (int) (existingTag.getInfoTag().getEndLocationInFile().intValue() - existingTag.getStartLocationInFileOfId3Chunk()); - deleteTagChunk(fc, (int) existingTag.getInfoTag().getEndLocationInFile().intValue(), lengthTagChunk); - } - } - } - //Tricky to delete both because once one is deleted affects the location of the other - else { - WavInfoTag existingInfoTag = existingTag.getInfoTag(); - ChunkHeader infoChunkHeader = seekToStartOfListInfoMetadata(fc, existingTag); - - ChunkHeader id3ChunkHeader = seekToStartOfId3Metadata(fc, existingTag); - - //If one of these two at end of file delete first then remove the other as a chunk - if (isInfoTagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - fc.truncate(existingInfoTag.getStartLocationInFile()); - deleteId3TagChunk(fc, existingTag, id3ChunkHeader); - } else if (isID3TagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk()); - deleteInfoTagChunk(fc, existingTag, infoChunkHeader); - } else { - deleteId3TagChunk(fc, existingTag, id3ChunkHeader); - //Reread then delete other tag - existingTag = getExistingMetadata(file); - deleteInfoTagChunk(fc, existingTag, infoChunkHeader); - } - } - } - //Delete Info if exists - else if (existingTag.isExistingInfoTag()) { - WavInfoTag existingInfoTag = existingTag.getInfoTag(); - ChunkHeader chunkHeader = seekToStartOfListInfoMetadata(fc, existingTag); - //and it is at end of the file - if (existingInfoTag.getEndLocationInFile() == fc.size()) { - logger.info(loggingName + ":Setting new length to:" + existingInfoTag.getStartLocationInFile()); - fc.truncate(existingInfoTag.getStartLocationInFile()); - } else { - deleteInfoTagChunk(fc, existingTag, chunkHeader); - } - } else if (existingTag.isExistingId3Tag()) { - ChunkHeader chunkHeader = seekToStartOfId3Metadata(fc, existingTag); - //and it is at end of the file - if (isID3TagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - logger.info(loggingName + ":Setting new length to:" + existingTag.getStartLocationInFileOfId3Chunk()); - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk()); - } else { - deleteId3TagChunk(fc, existingTag, chunkHeader); - } - } else { - //Nothing to delete - } - - rewriteRiffHeaderSize(fc); - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Delete existing Info Tag - * - * @param fc - * @param existingTag - * @param chunkHeader - * @throws IOException - */ - private void deleteInfoTagChunk(final FileChannel fc, final WavTag existingTag, final ChunkHeader chunkHeader) throws IOException { - final WavInfoTag existingInfoTag = existingTag.getInfoTag(); - final int lengthTagChunk = (int) chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE; - deleteTagChunk(fc, existingInfoTag.getEndLocationInFile().intValue(), lengthTagChunk); - } - - /** - * Delete existing Id3 Tag - * - * @param fc - * @param existingTag - * @param chunkHeader - * @throws IOException - */ - private void deleteId3TagChunk(FileChannel fc, final WavTag existingTag, final ChunkHeader chunkHeader) throws IOException { - final int lengthTagChunk = (int) chunkHeader.getSize() + ChunkHeader.CHUNK_HEADER_SIZE; - deleteTagChunk(fc, (int) existingTag.getEndLocationInFileOfId3Chunk(), lengthTagChunk); - } - - /** - * Delete Tag Chunk - *

- * Can be used when chunk is not the last chunk - *

- * Continually copy a 4mb chunk, write the chunk and repeat until the rest of the file after the tag - * is rewritten - * - * @param fc - * @param endOfExistingChunk - * @param lengthTagChunk - * @throws IOException - */ - private void deleteTagChunk(final FileChannel fc, int endOfExistingChunk, final int lengthTagChunk) throws IOException { - //Position for reading after the tag - fc.position(endOfExistingChunk); - - final ByteBuffer buffer = ByteBuffer.allocate((int) TagOptionSingleton.getInstance().getWriteChunkSize()); - while (fc.read(buffer) >= 0 || buffer.position() != 0) { - buffer.flip(); - final long readPosition = fc.position(); - fc.position(readPosition - lengthTagChunk - buffer.limit()); - fc.write(buffer); - fc.position(readPosition); - buffer.compact(); - } - //Truncate the file after the last chunk - final long newLength = fc.size() - lengthTagChunk; - logger.config(loggingName + " Setting new length to:" + newLength); - fc.truncate(newLength); - } - - /** - * @param tag - * @param file - * @throws CannotWriteException - */ - public void write(final Tag tag, File file) throws CannotWriteException { - logger.config(loggingName + " Writing tag to file:start"); - - WavSaveOptions wso = TagOptionSingleton.getInstance().getWavSaveOptions(); - WavTag existingTag = null; - try { - existingTag = getExistingMetadata(file); - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } - - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "rw"); - FileChannel fc = raf.getChannel(); - final WavTag wavTag = (WavTag) tag; - if (wso == WavSaveOptions.SAVE_BOTH) { - saveBoth(wavTag, fc, existingTag); - } else if (wso == WavSaveOptions.SAVE_ACTIVE) { - saveActive(wavTag, fc, existingTag); - } else if (wso == WavSaveOptions.SAVE_EXISTING_AND_ACTIVE) { - saveActiveExisting(wavTag, fc, existingTag); - } else if (wso == WavSaveOptions.SAVE_BOTH_AND_SYNC) { - wavTag.syncTagBeforeWrite(); - saveBoth(wavTag, fc, existingTag); - } else if (wso == WavSaveOptions.SAVE_EXISTING_AND_ACTIVE_AND_SYNC) { - wavTag.syncTagBeforeWrite(); - saveActiveExisting(wavTag, fc, existingTag); - } - //Invalid Option, should never happen - else { - throw new RuntimeException(loggingName + " No setting for:WavSaveOptions"); - } - rewriteRiffHeaderSize(fc); - } catch (IOException ioe) { - throw new CannotWriteException(file + ":" + ioe.getMessage()); - } finally { - AudioFileIO.closeQuietly(raf); - } - } - - /** - * Rewrite RAF header to reflect new file size - * - * @param fc - * @throws IOException - */ - private void rewriteRiffHeaderSize(FileChannel fc) throws IOException { - fc.position(IffHeaderChunk.SIGNATURE_LENGTH); - ByteBuffer bb = ByteBuffer.allocateDirect(IffHeaderChunk.SIZE_LENGTH); - bb.order(ByteOrder.LITTLE_ENDIAN); - int size = ((int) fc.size()) - SIGNATURE_LENGTH - SIZE_LENGTH; - bb.putInt(size); - bb.flip(); - fc.write(bb); - } - - /** - * Write LISTINFOChunk of specified size to current file location - * ensuring it is on even file boundary - * - * @param fc random access file - * @param bb data to write - * @param chunkSize chunk size - * @throws IOException - */ - private void writeInfoDataToFile(FileChannel fc, final ByteBuffer bb, final long chunkSize) throws IOException { - if (Utils.isOddLength(fc.position())) { - writePaddingToFile(fc, 1); - } - //Write LIST header - final ByteBuffer listHeaderBuffer = ByteBuffer.allocate(ChunkHeader.CHUNK_HEADER_SIZE); - listHeaderBuffer.order(ByteOrder.LITTLE_ENDIAN); - listHeaderBuffer.put(WavChunkType.LIST.getCode().getBytes(StandardCharsets.US_ASCII)); - listHeaderBuffer.putInt((int) chunkSize); - listHeaderBuffer.flip(); - fc.write(listHeaderBuffer); - - //Now write actual data - fc.write(bb); - writeExtraByteIfChunkOddSize(fc, chunkSize); - } - - /** - * Write new Info chunk and dont worry about the size of existing chunk just use size of new chunk - * - * @param fc - * @param bb - * @throws IOException - */ - private void writeInfoDataToFile(final FileChannel fc, final ByteBuffer bb) throws IOException { - writeInfoDataToFile(fc, bb, bb.limit()); - } - - /** - * Write Id3Chunk of specified size to current file location - * ensuring it is on even file boundary - * - * @param fc random access file - * @param bb data to write - * @throws IOException - */ - private void writeID3DataToFile(final FileChannel fc, final ByteBuffer bb) throws IOException { - if (Utils.isOddLength(fc.position())) { - writePaddingToFile(fc, 1); - } - - //Write ID3Data header - final ByteBuffer listBuffer = ByteBuffer.allocate(ChunkHeader.CHUNK_HEADER_SIZE); - listBuffer.order(ByteOrder.LITTLE_ENDIAN); - listBuffer.put(WavChunkType.ID3.getCode().getBytes(StandardCharsets.US_ASCII)); - listBuffer.putInt(bb.limit()); - listBuffer.flip(); - fc.write(listBuffer); - - //Now write actual data - fc.write(bb); - } - - /** - * Write Padding bytes - * - * @param fc - * @param paddingSize - * @throws IOException - */ - private void writePaddingToFile(final FileChannel fc, final int paddingSize) throws IOException { - fc.write(ByteBuffer.allocateDirect(paddingSize)); - } - - class InfoFieldWriterOrderComparator implements Comparator { - public int compare(TagField field1, TagField field2) { - WavInfoIdentifier code1 = WavInfoIdentifier.getByByFieldKey(FieldKey.valueOf(field1.getId())); - WavInfoIdentifier code2 = WavInfoIdentifier.getByByFieldKey(FieldKey.valueOf(field2.getId())); - int order1 = Integer.MAX_VALUE; - int order2 = Integer.MAX_VALUE; - if (code1 != null) { - order1 = code1.getPreferredWriteOrder(); - } - if (code2 != null) { - order2 = code2.getPreferredWriteOrder(); - } - return order1 - order2; - } - } - - /** - * Converts INfO tag to {@link ByteBuffer}. - * - * @param tag tag - * @return byte buffer containing the tag data - * @throws UnsupportedEncodingException - */ - public ByteBuffer convertInfoChunk(final WavTag tag) throws UnsupportedEncodingException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - WavInfoTag wif = tag.getInfoTag(); - - //Write the Info chunks - List fields = wif.getAll(); - Collections.sort(fields, new InfoFieldWriterOrderComparator()); - for (TagField nextField : fields) { - TagTextField next = (TagTextField) nextField; - WavInfoIdentifier wii = WavInfoIdentifier.getByByFieldKey(FieldKey.valueOf(next.getId())); - baos.write(wii.getCode().getBytes(StandardCharsets.US_ASCII)); - logger.config(loggingName + " Writing:" + wii.getCode() + ":" + next.getContent()); - - //TODO Is UTF8 allowed format - byte[] contentConvertedToBytes = next.getContent().getBytes(StandardCharsets.UTF_8); - baos.write(Utils.getSizeLEInt32(contentConvertedToBytes.length)); - baos.write(contentConvertedToBytes); - - //Write extra byte if data length not equal - if (Utils.isOddLength(contentConvertedToBytes.length)) { - baos.write(0); - } - - //Add a duplicated record for Twonky - if (wii == WavInfoIdentifier.TRACKNO) { - if (TagOptionSingleton.getInstance().isWriteWavForTwonky()) { - baos.write(WavInfoIdentifier.TWONKY_TRACKNO.getCode().getBytes(StandardCharsets.US_ASCII)); - logger.config(loggingName + " Writing:" + WavInfoIdentifier.TWONKY_TRACKNO.getCode() + ":" + next.getContent()); - - baos.write(Utils.getSizeLEInt32(contentConvertedToBytes.length)); - baos.write(contentConvertedToBytes); - - //Write extra byte if data length not equal - if (Utils.isOddLength(contentConvertedToBytes.length)) { - baos.write(0); - } - } - } - } - - //Write any existing unrecognized tuples - Iterator ti = wif.getUnrecognisedFields().iterator(); - while (ti.hasNext()) { - TagTextField next = ti.next(); - baos.write(next.getId().getBytes(StandardCharsets.US_ASCII)); - logger.config(loggingName + " Writing:" + next.getId() + ":" + next.getContent()); - byte[] contentConvertedToBytes = next.getContent().getBytes(StandardCharsets.UTF_8); - baos.write(Utils.getSizeLEInt32(contentConvertedToBytes.length)); - baos.write(contentConvertedToBytes); - - //Write extra byte if data length not equal - if (Utils.isOddLength(contentConvertedToBytes.length)) { - baos.write(0); - } - } - - final ByteBuffer infoBuffer = ByteBuffer.wrap(baos.toByteArray()); - infoBuffer.rewind(); - - //Now Write INFO header - final ByteBuffer infoHeaderBuffer = ByteBuffer.allocate(SIGNATURE_LENGTH); - infoHeaderBuffer.put(WavChunkType.INFO.getCode().getBytes(StandardCharsets.US_ASCII)); - infoHeaderBuffer.flip(); - - - //Construct a single ByteBuffer from both - ByteBuffer listInfoBuffer = ByteBuffer.allocateDirect(infoHeaderBuffer.limit() + infoBuffer.limit()); - listInfoBuffer.put(infoHeaderBuffer); - listInfoBuffer.put(infoBuffer); - listInfoBuffer.flip(); - return listInfoBuffer; - } catch (IOException ioe) { - //Should never happen as not writing to file at this point - throw new RuntimeException(ioe); - } - } - - /** - * Converts ID3tag to {@link ByteBuffer}. - * - * @param tag tag containing ID3tag - * @return byte buffer containing the tag data - * @throws UnsupportedEncodingException - */ - public ByteBuffer convertID3Chunk(final WavTag tag, WavTag existingTag) throws UnsupportedEncodingException { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - long existingTagSize = existingTag.getSizeOfID3TagOnly(); - - //If existingTag is uneven size lets make it even - if (existingTagSize > 0) { - if ((existingTagSize & 1) != 0) { - existingTagSize++; - } - } - - //Write Tag to buffer - tag.getID3Tag().write(baos, (int) existingTagSize); - - //If the tag is now odd because we needed to increase size and the data made it odd sized - //we redo adding a padding byte to make it even - if ((baos.toByteArray().length & 1) != 0) { - int newSize = baos.toByteArray().length + 1; - baos = new ByteArrayOutputStream(); - tag.getID3Tag().write(baos, newSize); - } - final 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); - } - } - - /** - * Used when writing both tags to work out the best way to do it - */ - class BothTagsFileStructure { - boolean isInfoTagFirst = false; - boolean isContiguous = false; - boolean isAtEnd = false; - - public String toString() { - return "IsInfoTagFirst:" + isInfoTagFirst - + ":isContiguous:" + isContiguous - + ":isAtEnd:" + isAtEnd; - } - } - - /** - * Identify where both metadata chunks are in relation to each other and other chunks - * - * @param wavTag - * @param fc - * @return - * @throws IOException - */ - private BothTagsFileStructure checkExistingLocations(WavTag wavTag, FileChannel fc) throws IOException { - BothTagsFileStructure fs = new BothTagsFileStructure(); - if (wavTag.getInfoTag().getStartLocationInFile() < wavTag.getID3Tag().getStartLocationInFile()) { - fs.isInfoTagFirst = true; - //Must allow for odd size chunks - if (Math.abs(wavTag.getInfoTag().getEndLocationInFile() - wavTag.getStartLocationInFileOfId3Chunk()) <= 1) { - fs.isContiguous = true; - if (isID3TagAtEndOfFileAllowingForPaddingByte(wavTag, fc)) { - fs.isAtEnd = true; - } - } - } else { - //Must allow for odd size chunks - if (Math.abs(wavTag.getID3Tag().getEndLocationInFile() - wavTag.getInfoTag().getStartLocationInFile()) <= 1) { - fs.isContiguous = true; - if (isInfoTagAtEndOfFileAllowingForPaddingByte(wavTag, fc)) { - fs.isAtEnd = true; - } - } - } - return fs; - } - - /** - * Write Info chunk to current location which is last chunk of file - * - * @param fc - * @param existingInfoTag - * @param newTagBuffer - * @throws CannotWriteException - * @throws IOException - */ - private void writeInfoChunk(FileChannel fc, final WavInfoTag existingInfoTag, ByteBuffer newTagBuffer) - throws CannotWriteException, IOException { - long newInfoTagSize = newTagBuffer.limit(); - //We have enough existing space in chunk so just keep existing chunk size - if (existingInfoTag.getSizeOfTag() >= newInfoTagSize) { - writeInfoDataToFile(fc, newTagBuffer, existingInfoTag.getSizeOfTag()); - //To ensure old data from previous tag are erased - if (existingInfoTag.getSizeOfTag() > newInfoTagSize) { - writePaddingToFile(fc, (int) (existingInfoTag.getSizeOfTag() - newInfoTagSize)); - } - } - //New tag is larger so set chunk size to accommodate it - else { - writeInfoDataToFile(fc, newTagBuffer, newInfoTagSize); - } - } - - /** - * Chunk must also start on an even byte so if our chinksize is odd we need - * to write another byte - * - * @param fc - * @param size - * @throws IOException - */ - private void writeExtraByteIfChunkOddSize(FileChannel fc, long size) - throws IOException { - if (Utils.isOddLength(size)) { - writePaddingToFile(fc, 1); - } - } - - - /** - * @param existingTag - * @param fc - * @return trueif ID3Tag at end of the file - * @throws IOException - */ - private boolean isID3TagAtEndOfFileAllowingForPaddingByte(WavTag existingTag, FileChannel fc) throws IOException { - return ((existingTag.getID3Tag().getEndLocationInFile() == fc.size()) || - (((existingTag.getID3Tag().getEndLocationInFile() & 1) != 0) && existingTag.getID3Tag().getEndLocationInFile() + 1 == fc.size())); - } - - /** - * @param existingTag - * @param fc - * @return - * @throws IOException - */ - private boolean isInfoTagAtEndOfFileAllowingForPaddingByte(WavTag existingTag, FileChannel fc) throws IOException { - return ((existingTag.getInfoTag().getEndLocationInFile() == fc.size()) || - (((existingTag.getInfoTag().getEndLocationInFile() & 1) != 0) && existingTag.getInfoTag().getEndLocationInFile() + 1 == fc.size())); - } - - - /** - * Save both Info and ID3 chunk - * - * @param wavTag - * @param fc - * @param existingTag - * @throws CannotWriteException - * @throws IOException - */ - private void saveBoth(WavTag wavTag, FileChannel fc, final WavTag existingTag) - throws CannotWriteException, IOException { - //Convert both tags and get existing ones - final ByteBuffer infoTagBuffer = convertInfoChunk(wavTag); - final ByteBuffer id3TagBuffer = convertID3Chunk(wavTag, existingTag); - - //If both tags already exist in file - if (existingTag.isExistingInfoTag() && existingTag.isExistingId3Tag()) { - if (!existingTag.isIncorrectlyAlignedTag()) { - BothTagsFileStructure fs = checkExistingLocations(existingTag, fc); - //We can write both chunks without affecting anything else - if (fs.isContiguous && fs.isAtEnd) { - if (fs.isInfoTagFirst) { - seekToStartOfListInfoMetadata(fc, existingTag); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - fc.truncate(fc.position()); - } else { - seekToStartOfId3Metadata(fc, existingTag); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - fc.truncate(fc.position()); - } - } - //Both chunks are together but there is another chunk after them - else { - ChunkHeader infoChunkHeader = seekToStartOfListInfoMetadata(fc, existingTag); - ChunkHeader id3ChunkHeader = seekToStartOfId3Metadata(fc, existingTag); - deleteInfoTagChunk(fc, existingTag, infoChunkHeader); - deleteId3TagChunk(fc, existingTag, id3ChunkHeader); - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - } - } - //Existing metadata tag is incorrectly aligned so if we can lets delete it and any subsequentially added - //tags and start again - else if (WavChunkSummary.isOnlyMetadataTagsAfterStartingMetadataTag(existingTag)) { - deleteExistingMetadataTagsToEndOfFile(fc, existingTag); - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - } else { - throw new CannotWriteException(loggingName + " Metadata tags are corrupted and not at end of file so cannot be fixed"); - } - } - //If only INFO chunk exists - else if (existingTag.isExistingInfoTag() && !existingTag.isExistingId3Tag()) { - if (!existingTag.isIncorrectlyAlignedTag()) { - ChunkHeader infoChunkHeader = seekToStartOfListInfoMetadata(fc, existingTag); - if (isInfoTagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - fc.truncate(fc.position()); - } else { - deleteInfoTagChunk(fc, existingTag, infoChunkHeader); - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - } - } - //Existing metadata tag is incorrectly aligned so if we can lets delete it and any subsequentially added - //tags and start again - else if (WavChunkSummary.isOnlyMetadataTagsAfterStartingMetadataTag(existingTag)) { - deleteExistingMetadataTagsToEndOfFile(fc, existingTag); - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - } else { - throw new CannotWriteException(loggingName + " Metadata tags are corrupted and not at end of file so cannot be fixed"); - } - } - //If only ID3 chunk exists - else if (existingTag.isExistingId3Tag() && !existingTag.isExistingInfoTag()) { - if (!existingTag.isIncorrectlyAlignedTag()) { - ChunkHeader id3ChunkHeader = seekToStartOfId3Metadata(fc, existingTag); - if (isID3TagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - fc.truncate(fc.position()); - } else { - deleteId3TagChunk(fc, existingTag, id3ChunkHeader); - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - } - } - //Existing metadata tag is incorrectly aligned so if we can lets delete it and any subsequentially added - //tags and start again - else if (WavChunkSummary.isOnlyMetadataTagsAfterStartingMetadataTag(existingTag)) { - deleteExistingMetadataTagsToEndOfFile(fc, existingTag); - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - - } else { - throw new CannotWriteException(loggingName + " Metadata tags are corrupted and not at end of file so cannot be fixed"); - } - } - //No existing tags so write both to the end (or existing tag but couldnt not be written) - else { - //Go to end of file - fc.position(fc.size()); - writeBothTags(fc, infoTagBuffer, id3TagBuffer); - } - } - - /** - * Write both tags in the order preferred by the options - * - * @param fc - * @param infoTagBuffer - * @param id3TagBuffer - * @throws IOException - */ - private void writeBothTags(FileChannel fc, ByteBuffer infoTagBuffer, ByteBuffer id3TagBuffer) - throws IOException { - if (TagOptionSingleton.getInstance().getWavSaveOrder() == WavSaveOrder.INFO_THEN_ID3) { - writeInfoDataToFile(fc, infoTagBuffer); - writeID3DataToFile(fc, id3TagBuffer); - } else { - writeID3DataToFile(fc, id3TagBuffer); - writeInfoDataToFile(fc, infoTagBuffer); - } - } - - /** - * Save Active chunk only, if a non-active metadata chunk exists will be removed - * - * @param wavTag - * @param fc - * @param existingTag - * @throws CannotWriteException - * @throws IOException - */ - private void saveActive(WavTag wavTag, FileChannel fc, final WavTag existingTag) - throws CannotWriteException, IOException { - //Info is Active Tag - if (wavTag.getActiveTag() instanceof WavInfoTag) { - final ByteBuffer infoTagBuffer = convertInfoChunk(wavTag); - final long newInfoTagSize = infoTagBuffer.limit(); - - //Usual Case - if (!existingTag.isIncorrectlyAlignedTag()) { - //We have an ID3 tag which we do not want - if (existingTag.isExistingId3Tag()) { - if (isID3TagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - fc.truncate(existingTag.getStartLocationInFileOfId3Chunk()); - } else { - ChunkHeader id3ChunkHeader = seekToStartOfId3Metadata(fc, existingTag); - deleteId3TagChunk(fc, existingTag, id3ChunkHeader); - } - } - - //We already have such a tag - if (existingTag.isExistingInfoTag()) { - ChunkHeader infoChunkHeader = seekToStartOfListInfoMetadata(fc, existingTag); - if (isInfoTagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - writeInfoChunk(fc, existingTag.getInfoTag(), infoTagBuffer); - } else { - deleteInfoTagChunk(fc, existingTag, infoChunkHeader); - fc.position(fc.size()); - writeInfoDataToFile(fc, infoTagBuffer, infoTagBuffer.limit()); - } - } - //Don't have tag so have to create new - else { - fc.position(fc.size()); - writeInfoDataToFile(fc, infoTagBuffer, newInfoTagSize); - } - } - //Existing one is in wrong place - //Existing Info tag is incorrectly aligned so if we can lets delete it and any subsequentially added - //tags and start again - else if (WavChunkSummary.isOnlyMetadataTagsAfterStartingMetadataTag(existingTag)) { - deleteExistingMetadataTagsToEndOfFile(fc, existingTag); - fc.position(fc.size()); - writeInfoDataToFile(fc, infoTagBuffer, newInfoTagSize); - } else { - throw new CannotWriteException(loggingName + " Metadata tags are corrupted and not at end of file so cannot be fixed"); - } - } - //ID3 is Active Tag - else { - final ByteBuffer id3TagBuffer = convertID3Chunk(wavTag, existingTag); - if (!existingTag.isIncorrectlyAlignedTag()) { - if (existingTag.isExistingInfoTag()) { - ChunkHeader infoChunkHeader = seekToStartOfListInfoMetadata(fc, existingTag); - if (isInfoTagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - fc.truncate(existingTag.getInfoTag().getStartLocationInFile()); - } else { - deleteInfoTagChunk(fc, existingTag, infoChunkHeader); - } - } - - if (existingTag.isExistingId3Tag()) { - ChunkHeader id3ChunkHeader = seekToStartOfId3Metadata(fc, existingTag); - if (isID3TagAtEndOfFileAllowingForPaddingByte(existingTag, fc)) { - writeID3DataToFile(fc, id3TagBuffer); - } else { - deleteId3TagChunk(fc, existingTag, id3ChunkHeader); - fc.position(fc.size()); - writeID3DataToFile(fc, id3TagBuffer); - } - } else { - fc.position(fc.size()); - writeID3DataToFile(fc, id3TagBuffer); - } - } else if (WavChunkSummary.isOnlyMetadataTagsAfterStartingMetadataTag(existingTag)) { - deleteExistingMetadataTagsToEndOfFile(fc, existingTag); - fc.position(fc.size()); - writeID3DataToFile(fc, id3TagBuffer); - } else { - throw new CannotWriteException(loggingName + " Metadata tags are corrupted and not at end of file so cannot be fixed"); - } - } - } - - /** - * Save Active chunk and existing chunks even if not the active chunk - * - * @param wavTag - * @param fc - * @param existingTag - * @throws CannotWriteException - * @throws IOException - */ - private void saveActiveExisting(WavTag wavTag, FileChannel fc, final WavTag existingTag) - throws CannotWriteException, IOException { - if (wavTag.getActiveTag() instanceof WavInfoTag) { - if (existingTag.isExistingId3Tag()) { - saveBoth(wavTag, fc, existingTag); - } else { - saveActive(wavTag, fc, existingTag); - } - } else { - if (existingTag.isExistingInfoTag()) { - saveBoth(wavTag, fc, existingTag); - } else { - saveActive(wavTag, fc, existingTag); - } - } - } - - /** - * If Info/ID3 Metadata tags are corrupted and only metadata tags later in the file then just truncate metadata tags and start again - * - * @param fc - * @param existingTag - * @throws IOException - */ - private void deleteExistingMetadataTagsToEndOfFile(final FileChannel fc, final WavTag existingTag) throws IOException { - ChunkSummary precedingChunk = WavChunkSummary.getChunkBeforeFirstMetadataTag(existingTag); - //Preceding chunk ends on odd boundary - if (!Utils.isOddLength(precedingChunk.getEndLocation())) { - logger.severe(loggingName + " Truncating corrupted metadata tags from:" + (existingTag.getInfoTag().getStartLocationInFile() - 1)); - fc.truncate(existingTag.getInfoTag().getStartLocationInFile() - 1); - } - //Preceding chunk ends on even boundary - else { - logger.severe(loggingName + " Truncating corrupted metadata tags from:" + (existingTag.getInfoTag().getStartLocationInFile())); - fc.truncate(existingTag.getInfoTag().getStartLocationInFile()); - } - } - - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavChunkSummary.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavChunkSummary.java deleted file mode 100644 index 9f95569f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavChunkSummary.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.audio.wav.WavChunkType; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.util.logging.Logger; - -/** - * AIFF Specific methods for ChunkSummarys - */ -public class WavChunkSummary -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.wav.chunk"); - - /** - * Get start location in file of first metadata chunk (could be LIST or ID3) - * - * @param tag - * @return - */ - public static long getStartLocationOfFirstMetadataChunk(WavTag tag) - { - //Work out the location of the first metadata tag (could be id3 or LIST tag) - long startLocationOfMetadatTag = -1; - if(tag.getInfoTag()!=null) - { - startLocationOfMetadatTag = tag.getInfoTag().getStartLocationInFile(); - - if(tag.getID3Tag()!=null) - { - if(tag.getStartLocationInFileOfId3Chunk() < startLocationOfMetadatTag) - { - startLocationOfMetadatTag = tag.getStartLocationInFileOfId3Chunk(); - } - } - } - else if(tag.getID3Tag()!=null) - { - startLocationOfMetadatTag = tag.getStartLocationInFileOfId3Chunk(); - } - return startLocationOfMetadatTag; - } - - /** - * Checks that there are only id3 tags after the currently selected id3tag because this means its safe to truncate - * the remainder of the file. - * - * @param tag - * @return - */ - public static boolean isOnlyMetadataTagsAfterStartingMetadataTag(WavTag tag) - { - long startLocationOfMetadatTag = getStartLocationOfFirstMetadataChunk(tag); - if(startLocationOfMetadatTag==-1) - { - logger.severe("Unable to find any metadata tags !"); - return false; - } - - boolean firstMetadataTag = false; - for(ChunkSummary cs:tag.getChunkSummaryList()) - { - if(firstMetadataTag) - { - if( - !cs.getChunkId().equals(WavChunkType.ID3.getCode()) && - !cs.getChunkId().equals(WavChunkType.LIST.getCode()) && - !cs.getChunkId().equals(WavChunkType.INFO.getCode()) - ) - { - return false; - } - } - else - { - if (cs.getFileStartLocation() == startLocationOfMetadatTag) - { - //Found starting point - firstMetadataTag = true; - } - } - } - - //Should always be true but this is to protect against something gone wrong - if(firstMetadataTag==true) - { - return true; - } - return false; - - } - - - /** - * Get chunk before the first metadata tag - * - * @param tag - * @return - */ - public static ChunkSummary getChunkBeforeFirstMetadataTag(WavTag tag) - { - long startLocationOfMetadatTag = getStartLocationOfFirstMetadataChunk(tag); - - for(int i=0;i < tag.getChunkSummaryList().size(); i++) - { - ChunkSummary cs = tag.getChunkSummaryList().get(i); - if (cs.getFileStartLocation() == startLocationOfMetadatTag) - { - return tag.getChunkSummaryList().get(i - 1); - } - } - return null; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFactChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFactChunk.java deleted file mode 100644 index 634d47fe..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFactChunk.java +++ /dev/null @@ -1,59 +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 com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Reads the fact header, this contains the information required for constructing Audio header - * - * 0 - 3 uint totalNoSamples (Per channel ?) -*/ -public class WavFactChunk extends Chunk -{ - private boolean isValid = false; - - private GenericAudioHeader info; - - public WavFactChunk(ByteBuffer chunkData, ChunkHeader hdr, GenericAudioHeader info) throws IOException - { - super(chunkData, hdr); - this.info=info; - } - - public boolean readChunk() throws IOException - { - info.setNoOfSamples(Utils.u(chunkData.getInt())); - return true; - } - - - public String toString() - { - String out = "Fact Chunk:\n"; - out += "Is valid?: " + isValid; - return out; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFormatChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFormatChunk.java deleted file mode 100644 index 48690f20..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavFormatChunk.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 com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.audio.generic.GenericAudioHeader; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.wav.WavSubFormat; -import com.mp3.jaudiotagger.logging.Hex; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Reads the fmt header, this contains the information required for constructing Audio header - * - * 0 - 1 ushort SubFormatIdentifier; - * 2 - 3 ushort NoOfChannels; - * 4 - 7 uint NoOfSamplesPerSec; - * 8 - 11 uint AverageNoBytesPerSec; - * 12 - 13 ushort BlockAlign; - * 14 - 15 ushort NoofBitsPerSample; - * //May be additional fields here, depending upon wFormatTag. - * } FormatChunk -*/ -public class WavFormatChunk extends Chunk -{ - private static final int STANDARD_DATA_SIZE = 18; - private static final int EXTENSIBLE_DATA_SIZE = 22; - private static final int EXTENSIBLE_DATA_SIZE_WE_NEED = 10; - - private static final String WAV_RIFF_ENCODING_PREPEND = "WAV-RIFF "; - - - private boolean isValid = false; - - private int blockAlign, channelMask; - private WavSubFormat wsf; - private GenericAudioHeader info; - - public WavFormatChunk(ByteBuffer chunkData, ChunkHeader hdr, GenericAudioHeader info) throws IOException - { - super(chunkData, hdr); - this.info=info; - } - - public boolean readChunk() throws IOException - { - int subFormatCode = Utils.u(chunkData.getShort()); - wsf = WavSubFormat.getByCode(subFormatCode); - info.setChannelNumber(Utils.u(chunkData.getShort())); - info.setSamplingRate(chunkData.getInt()); - info.setByteRate(chunkData.getInt()); - info.setBitRate( info.getByteRate() * Utils.BITS_IN_BYTE_MULTIPLIER / Utils.KILOBYTE_MULTIPLIER); //AvgBytePerSec converted to kb/sec - info.setVariableBitRate(false); - blockAlign = Utils.u(chunkData.getShort()); - info.setBitsPerSample(Utils.u(chunkData.getShort())); - if (wsf!=null && wsf == WavSubFormat.FORMAT_EXTENSIBLE) - { - int extensibleSize = Utils.u(chunkData.getShort()); - if(extensibleSize == EXTENSIBLE_DATA_SIZE) - { - info.setBitsPerSample(Utils.u(chunkData.getShort())); - //We dont use this currently - channelMask = chunkData.getInt(); - - //If Extensible then the actual formatCode is held here - wsf = WavSubFormat.getByCode(Utils.u(chunkData.getShort())); - } - } - if(wsf!=null) - { - if(info.getBitsPerSample()>0) - { - info.setEncodingType(wsf.getDescription() + " " + info.getBitsPerSample() + " bits"); - } - else - { - info.setEncodingType(wsf.getDescription()); - } - } - else - { - info.setEncodingType("Unknown Sub Format Code:"+ Hex.asHex(subFormatCode)); - } - return true; - } - - - public String toString() - { - String out = "RIFF-WAVE Header:\n"; - out += "Is valid?: " + isValid; - return out; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavId3Chunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavId3Chunk.java deleted file mode 100644 index dc6f56c3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavId3Chunk.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v22Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v23Tag; -import com.mp3.jaudiotagger.tag.id3.ID3v24Tag; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.logging.Logger; - -/** - * Contains the ID3 tags. - */ -public class WavId3Chunk extends Chunk -{ - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.wav.chunk"); - private WavTag wavTag; - - /** - * Constructor. - * @param chunkData The content of this chunk - * @param chunkHeader The header for this chunk - * @param tag The WavTag into which information is stored - */ - public WavId3Chunk(final ByteBuffer chunkData, final ChunkHeader chunkHeader, final WavTag tag) - { - super(chunkData, chunkHeader); - wavTag = tag; - } - - @Override - public boolean readChunk() throws IOException - { - if (!isId3v2Tag(chunkData)) - { - logger.severe("Invalid ID3 header for ID3 chunk"); - return false; - } - - final int version = chunkData.get(); - final AbstractID3v2Tag id3Tag; - switch (version) - { - case ID3v22Tag.MAJOR_VERSION: - id3Tag = new ID3v22Tag(); - AudioFile.logger.finest("Reading ID3V2.2 tag"); - break; - case ID3v23Tag.MAJOR_VERSION: - id3Tag = new ID3v23Tag(); - AudioFile.logger.finest("Reading ID3V2.3 tag"); - break; - case ID3v24Tag.MAJOR_VERSION: - id3Tag = new ID3v24Tag(); - AudioFile.logger.finest("Reading ID3V2.4 tag"); - break; - default: - return false; // bad or unknown version - } - - id3Tag.setStartLocationInFile(chunkHeader.getStartLocationInFile() + ChunkHeader.CHUNK_HEADER_SIZE); - id3Tag.setEndLocationInFile(chunkHeader.getStartLocationInFile() + ChunkHeader.CHUNK_HEADER_SIZE + chunkHeader.getSize()); - - wavTag.setExistingId3Tag(true); - wavTag.setID3Tag(id3Tag); - chunkData.position(0); - try - { - id3Tag.read(chunkData); - } - catch (TagException e) - { - AudioFile.logger.info("Exception reading ID3 tag: " + e.getClass().getName() + ": " + e.getMessage()); - return false; - } - return true; - } - - /** - * Reads 3 bytes to determine if the tag really looks like ID3 data. - */ - private boolean isId3v2Tag(final ByteBuffer headerData) throws IOException - { - for (int i = 0; i < AbstractID3v2Tag.FIELD_TAGID_LENGTH; i++) - { - if (headerData.get() != AbstractID3v2Tag.TAG_ID[i]) - { - return false; - } - } - return true; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoChunk.java deleted file mode 100644 index 35449c7d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoChunk.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.IffHeaderChunk; -import com.mp3.jaudiotagger.tag.FieldDataInvalidException; -import com.mp3.jaudiotagger.tag.wav.WavInfoTag; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Stores basic only metadata but only exists as part of a LIST chunk, doesn't have its own size field - * instead contains a number of name,size, value tuples. So for this reason we do not subclass the Chunk class - */ -public class WavInfoChunk { - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.audio.wav.WavInfoChunk"); - - private WavInfoTag wavInfoTag; - private String loggingName; - - public WavInfoChunk(WavTag tag, String loggingName) { - this.loggingName = loggingName; - wavInfoTag = new WavInfoTag(); - tag.setInfoTag(wavInfoTag); - } - - /** - * Read Info chunk - * - * @param chunkData - */ - public boolean readChunks(ByteBuffer chunkData) { - while (chunkData.remaining() >= IffHeaderChunk.TYPE_LENGTH) { - String id = Utils.readFourBytesAsChars(chunkData); - //Padding - if (id.trim().isEmpty()) { - return true; - } - int size = chunkData.getInt(); - - if ( - (!isAlphabetic(id.charAt(0))) || - (!isAlphabetic(id.charAt(1))) || - (!isAlphabetic(id.charAt(2))) || - (!isAlphabetic(id.charAt(3))) - ) { - logger.severe(loggingName + "LISTINFO appears corrupt, ignoring:" + id + ":" + size); - return false; - } - - String value = null; - try { - value = Utils.getString(chunkData, 0, size, StandardCharsets.UTF_8); - } catch (BufferUnderflowException bue) { - logger.log(Level.SEVERE, loggingName + "LISTINFO appears corrupt, ignoring:" + bue.getMessage(), bue); - return false; - } - - logger.config(loggingName + "Result:" + id + ":" + size + ":" + value + ":"); - WavInfoIdentifier wii = WavInfoIdentifier.getByCode(id); - if (wii != null && wii.getFieldKey() != null) { - try { - wavInfoTag.setField(wii.getFieldKey(), value); - } catch (FieldDataInvalidException fdie) { - logger.log(Level.SEVERE, loggingName + fdie.getMessage(), fdie); - } - } - //Add unless just padding - else if (id != null && !id.trim().isEmpty()) { - wavInfoTag.addUnRecognizedField(id, value); - } - - //Each tuple aligned on even byte boundary - if (Utils.isOddLength(size) && chunkData.hasRemaining()) { - chunkData.get(); - } - } - return true; - } - - private static boolean isAlphabetic(int codePoint) { - return (((((1 << Character.UPPERCASE_LETTER) | - (1 << Character.LOWERCASE_LETTER) | - (1 << Character.TITLECASE_LETTER) | - (1 << Character.MODIFIER_LETTER) | - (1 << Character.OTHER_LETTER) | - (1 << Character.LETTER_NUMBER)) >> Character.getType(codePoint)) & 1) != 0); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoIdentifier.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoIdentifier.java deleted file mode 100644 index 5daedf54..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavInfoIdentifier.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.tag.FieldKey; - -import java.util.HashMap; -import java.util.Map; - -/** - * Known Identifiers used in an INFO Chunk together with their mapping to a generic FieldKey (if known) - */ -public enum WavInfoIdentifier -{ - ARTIST("IART", FieldKey.ARTIST, 1), - ALBUM("IPRD", FieldKey.ALBUM, 2), - TITLE("INAM", FieldKey.TITLE, 3), - TRACKNO("ITRK", FieldKey.TRACK, 4), - YEAR("ICRD", FieldKey.YEAR, 5), - GENRE("IGNR", FieldKey.GENRE, 6), - //Custom MediaMonkey field, theres appears to be no official AlbumArtist field, nothing ever displayed for this field or IAAR in Windows Explorer - ALBUM_ARTIST("iaar", FieldKey.ALBUM_ARTIST, 7), - COMMENTS("ICMT", FieldKey.COMMENT, 8), - COMPOSER("IMUS", FieldKey.COMPOSER, 9), - CONDUCTOR("ITCH", FieldKey.CONDUCTOR, 10), - LYRICIST("IWRI", FieldKey.LYRICIST, 11), - ENCODER("ISFT", FieldKey.ENCODER, 12), - RATING("IRTD", FieldKey.RATING, 13), - ISRC("ISRC", FieldKey.ISRC, 14), - LABEL("ICMS", FieldKey.RECORD_LABEL, 15), - TRACK_GAIN("ITGL", null, 16), //Currently No mapping to a FieldKey for this - ALBUM_GAIN("IAGL", null, 17), //Currently No mapping to a FieldKey for this - COPYRIGHT("ICOP", null, 18), - TWONKY_TRACKNO("itrk", null, 1), //Uses nonstandard field - ; - private static final Map CODE_TYPE_MAP = new HashMap(); - private static final Map FIELDKEY_TYPE_MAP = new HashMap(); - private String code; - private FieldKey fieldKey; - private int preferredWriteOrder; - - WavInfoIdentifier(String code, FieldKey fieldKey, int preferredWriteOrder) - { - this.code = code; - this.fieldKey = fieldKey; - this.preferredWriteOrder=preferredWriteOrder; - } - - public String getCode() - { - return code; - } - - public FieldKey getFieldKey() - { - return fieldKey; - } - - public int getPreferredWriteOrder() - { - return preferredWriteOrder; - } - - /** - * Get {@link WavInfoIdentifier} for code (e.g. "SSND"). - * - * @param code chunk id - * @return chunk type or {@code null} if not registered - */ - public synchronized static WavInfoIdentifier getByCode(final String code) - { - if (CODE_TYPE_MAP.isEmpty()) - { - for (final WavInfoIdentifier type : values()) - { - CODE_TYPE_MAP.put(type.getCode(), type); - } - } - return CODE_TYPE_MAP.get(code); - } - - /** - * Get {@link WavInfoIdentifier} for code (e.g. "SSND"). - * - * @param fieldKey - * @return chunk type or {@code null} if not registered - */ - public synchronized static WavInfoIdentifier getByByFieldKey(final FieldKey fieldKey) - { - if (FIELDKEY_TYPE_MAP.isEmpty()) - { - for (final WavInfoIdentifier type : values()) - { - if (type.getFieldKey() != null) - { - FIELDKEY_TYPE_MAP.put(type.getFieldKey(), type); - } - } - } - return FIELDKEY_TYPE_MAP.get(fieldKey); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavListChunk.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavListChunk.java deleted file mode 100644 index 9ed9baa9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/audio/wav/chunk/WavListChunk.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 com.mp3.jaudiotagger.audio.wav.chunk; - -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.iff.Chunk; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.wav.WavChunkType; -import com.mp3.jaudiotagger.tag.wav.WavTag; - -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * Reads a list chunk, only interested in it if contains INFO chunk as this contains basic metadata - */ -public class WavListChunk extends Chunk -{ - - private boolean isValid = false; - - private WavTag tag; - private String loggingName; - - public WavListChunk(String loggingName, ByteBuffer chunkData, ChunkHeader chunkHeader, WavTag tag) throws IOException - { - super(chunkData, chunkHeader); - this.tag=tag; - this.loggingName = loggingName; - } - - /** - * - * @return true if successfully read chunks - * - * @throws IOException - */ - public boolean readChunk() throws IOException - { - boolean result = false; - String subIdentifier = Utils.readFourBytesAsChars(chunkData); - if(subIdentifier.equals(WavChunkType.INFO.getCode())) - { - WavInfoChunk chunk = new WavInfoChunk(tag, loggingName); - result = chunk.readChunks(chunkData); - //This is the start of the enclosing LIST element - tag.getInfoTag().setStartLocationInFile(chunkHeader.getStartLocationInFile()); - tag.getInfoTag().setEndLocationInFile(chunkHeader.getStartLocationInFile() + ChunkHeader.CHUNK_HEADER_SIZE + chunkHeader.getSize()); - tag.setExistingInfoTag(true); - } - return result; - } - - - public String toString() - { - String out = "RIFF-WAVE Header:\n"; - out += "Is valid?: " + isValid; - return out; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/AbstractTagDisplayFormatter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/AbstractTagDisplayFormatter.java deleted file mode 100644 index 609bbd05..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/AbstractTagDisplayFormatter.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 com.mp3.jaudiotagger.logging; - -import java.util.HashMap; - -/** - * Abstract class that provides structure to use for displaying a files metadata content - */ -public abstract class AbstractTagDisplayFormatter -{ - protected int level; - - private static HashMap hexBinaryMap = new HashMap(); - - 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(); - - /** - * 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); - } - - 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"); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/ErrorMessage.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/ErrorMessage.java deleted file mode 100644 index 2d5497aa..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/ErrorMessage.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.mp3.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_INCORRECT_NUMBER_OF_TRACKS("Unable to make changes to Mp4 file, incorrect number of tracks: {0} vs {1}"), - 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_GET_CREATION_TIME_FAILED("Failed to read creation time for file {0}"), - GENERAL_SET_CREATION_TIME_FAILED("Failed to write creation time for file {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} because not writable"), - 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"), - OPERATION_NOT_SUPPORTED_FOR_FIELD("Not available for this field {0}"), - 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}"), - NOT_STANDARD_MP$_GENRE("This is not a standard genre value, use custom genre field instead"), - FLAC_NO_BLOCKTYPE("Flac file has invalid block type {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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/FileSystemMessage.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/FileSystemMessage.java deleted file mode 100644 index fb3e02cd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/FileSystemMessage.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.mp3.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"), - PERMISSION_DENIED("Permission denied"), // message from a *nix OS - - ; - String msg; - - FileSystemMessage(String msg) - { - this.msg = msg; - } - - public String getMsg() - { - return msg; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/Hex.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/Hex.java deleted file mode 100644 index eb9c3708..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/Hex.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.mp3.jaudiotagger.logging; - -/** - * Display as hex - */ -public class Hex -{ - /** - * Display as hex - * - * @param value - * @return - */ - public static String asHex(long value) - { - String val = Long.toHexString(value); - if(val.length()==1) - { - return "0x0" + val; - } - return "0x" + val; - } - - public static String asHex(int value) - { - return "0x" + Integer.toHexString(value); - } - - - /** - * Display as hex - * - * @param value - * @return - */ - public static String asHex(byte value) - { - return "0x" + Integer.toHexString(value); - } - - /** - * Display as integral and hex calue in brackets - * - * @param value - * @return - */ - public static String asDecAndHex(long value) - { - return value + " (" + Hex.asHex(value)+ ")"; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/PlainTextTagDisplayFormatter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/PlainTextTagDisplayFormatter.java deleted file mode 100644 index c702a6a6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/PlainTextTagDisplayFormatter.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.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 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(); - } - - public static AbstractTagDisplayFormatter getInstanceOf() - { - if (formatter == null) - { - formatter = new PlainTextTagDisplayFormatter(); - } - return formatter; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/XMLTagDisplayFormatter.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/XMLTagDisplayFormatter.java deleted file mode 100644 index 98ec75a8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/logging/XMLTagDisplayFormatter.java +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.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 -{ - private static XMLTagDisplayFormatter formatter; - - 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 = ""; - - - 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(Integer.toString(Character.codePointAt(xmlData,i),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); - } - - - 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(); - } - - - /** - * 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/EmptyFrameException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/EmptyFrameException.java deleted file mode 100644 index 3fb504c4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/EmptyFrameException.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.jaudiotagger.tag; - -/** - * Thrown when find a Frame but it contains no data. - * - * @version $Revision$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldDataInvalidException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldDataInvalidException.java deleted file mode 100644 index 64c48cd6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldDataInvalidException.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldKey.java deleted file mode 100644 index e3382b47..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/FieldKey.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.mp3.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_ARTISTS, - ALBUM_ARTISTS_SORT, - ALBUM_SORT, - AMAZON_ID, - ARRANGER, - ARRANGER_SORT, - ARTIST, - ARTISTS, - ARTISTS_SORT, - ARTIST_SORT, - BARCODE, - BPM, - CATALOG_NO, - CLASSICAL_CATALOG, - CLASSICAL_NICKNAME, - CHOIR, - CHOIR_SORT, - COMMENT, - COMPOSER, - COMPOSER_SORT, - CONDUCTOR, - CONDUCTOR_SORT, - COPYRIGHT, - COUNTRY, - COVER_ART, - CUSTOM1, - CUSTOM2, - CUSTOM3, - CUSTOM4, - CUSTOM5, - DISC_NO, - DISC_SUBTITLE, - DISC_TOTAL, - DJMIXER, - ENCODER, - ENGINEER, - ENSEMBLE, - ENSEMBLE_SORT, - FBPM, - GENRE, - GROUP, - GROUPING, - INSTRUMENT, - INVOLVED_PERSON, - ISRC, - IS_CLASSICAL, - IS_SOUNDTRACK, - IS_COMPILATION, - ITUNES_GROUPING, - KEY, - LANGUAGE, - LYRICIST, - LYRICS, - MEDIA, - MIXER, - MOOD, - MOOD_ACOUSTIC, - MOOD_AGGRESSIVE, - MOOD_AROUSAL, - MOOD_DANCEABILITY, - MOOD_ELECTRONIC, - MOOD_HAPPY, - MOOD_INSTRUMENTAL, - MOOD_PARTY, - MOOD_RELAXED, - MOOD_SAD, - MOOD_VALENCE, - MOVEMENT, - MOVEMENT_NO, - MOVEMENT_TOTAL, - 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_TRACK_ID, - MUSICBRAINZ_RELEASE_TYPE, - MUSICBRAINZ_TRACK_ID, - MUSICBRAINZ_WORK, - MUSICBRAINZ_WORK_ID, - MUSICBRAINZ_WORK_COMPOSITION, - MUSICBRAINZ_WORK_COMPOSITION_ID, - MUSICBRAINZ_WORK_PART_LEVEL1, - MUSICBRAINZ_WORK_PART_LEVEL1_ID, - MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, - MUSICBRAINZ_WORK_PART_LEVEL2, - MUSICBRAINZ_WORK_PART_LEVEL2_ID, - MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, - MUSICBRAINZ_WORK_PART_LEVEL3, - MUSICBRAINZ_WORK_PART_LEVEL3_ID, - MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, - MUSICBRAINZ_WORK_PART_LEVEL4, - MUSICBRAINZ_WORK_PART_LEVEL4_ID, - MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, - MUSICBRAINZ_WORK_PART_LEVEL5, - MUSICBRAINZ_WORK_PART_LEVEL5_ID, - MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, - MUSICBRAINZ_WORK_PART_LEVEL6, - MUSICBRAINZ_WORK_PART_LEVEL6_ID, - MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, - MUSICIP_ID, - OCCASION, - OPUS, - ORCHESTRA, - ORCHESTRA_SORT, - ORIGINAL_ALBUM, - ORIGINAL_ARTIST, - ORIGINAL_LYRICIST, - ORIGINAL_YEAR, - PART, - PART_NUMBER, - PART_TYPE, - PERFORMER, - PERFORMER_NAME, - PERFORMER_NAME_SORT, - PERIOD, - PRODUCER, - QUALITY, - RANKING, - RATING, - RECORD_LABEL, - REMIXER, - SCRIPT, - SINGLE_DISC_TRACK_NO, - SUBTITLE, - TAGS, - TEMPO, - TIMBRE, - TITLE, - TITLE_SORT, - TITLE_MOVEMENT, - TONALITY, - 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, - WORK, - WORK_TYPE, - YEAR, - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidDataTypeException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidDataTypeException.java deleted file mode 100644 index 10a69c7f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidDataTypeException.java +++ /dev/null @@ -1,61 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameException.java deleted file mode 100644 index 23c5bc17..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameException.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.jaudiotagger.tag; - -/** - * Thrown if frame cannot be read correctly. - * - * @author Eric Farng - * @version $Revision$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameIdentifierException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameIdentifierException.java deleted file mode 100644 index 5d1f226f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidFrameIdentifierException.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.jaudiotagger.tag; - -/** - * Thrown if a frame identifier isn't valid. - * - * @author Eric Farng - * @version $Revision$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidTagException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidTagException.java deleted file mode 100644 index 86367419..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/InvalidTagException.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/KeyNotFoundException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/KeyNotFoundException.java deleted file mode 100644 index d3f544a0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/KeyNotFoundException.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/PaddingException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/PaddingException.java deleted file mode 100644 index a2fd4ba9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/PaddingException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/Tag.java deleted file mode 100644 index f55eda9e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/Tag.java +++ /dev/null @@ -1,338 +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 com.mp3.jaudiotagger.tag; - -import com.mp3.jaudiotagger.tag.images.Artwork; - -import java.nio.charset.Charset; -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(Charset 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. - * - * Usually the value field should only be one value, but certain fields may require more than one value - * currently the only field to require this is the MUSICIAN field, it should contain instrument and then - * performer name - * - * @param genericKey is the generic key - * @param value to store - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - TagField createField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException; - - /** - * Creates isCompilation field - * - * It is useful to have this method because it handles ensuring that the correct value to represent a boolean - * is stored in the underlying field format. - * - * @param value - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException; - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagException.java deleted file mode 100644 index 51cac03a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagException.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.jaudiotagger.tag; - -/** - * This is the exception that is always generated by any class in these - * packages. - * - * @author Eric Farng - * @version $Revision$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagField.java deleted file mode 100644 index 72a221d7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagField.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 com.mp3.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 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. - */ - public 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 com.mp3.jaudiotagger.audio.generic.AbstractTag} will use the "id" to summarize multiple - * fields. - * - * @return Unique identifier for the fields type. (title, artist...) - */ - public 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. - */ - public 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). - */ - public 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. - */ - public 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. - */ - public boolean isCommon(); - - /** - * Determines whether the content of the field is empty.
- * - * @return true if no data is stored (or empty String). - */ - public 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. - */ - public String toString(); -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagNotFoundException.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagNotFoundException.java deleted file mode 100644 index df56769d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagNotFoundException.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -package com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagOptionSingleton.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagOptionSingleton.java deleted file mode 100644 index 0e2722c2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagOptionSingleton.java +++ /dev/null @@ -1,1359 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Options that are used for every datatype and class in this library. - * - */ -package com.mp3.jaudiotagger.tag; - -import com.mp3.jaudiotagger.audio.wav.WavOptions; -import com.mp3.jaudiotagger.audio.wav.WavSaveOptions; -import com.mp3.jaudiotagger.audio.wav.WavSaveOrder; -import com.mp3.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyTIPL; -import com.mp3.jaudiotagger.tag.id3.framebody.ID3v24FrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.tag.lyrics3.Lyrics3v2Fields; -import com.mp3.jaudiotagger.tag.options.PadNumberOption; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; -import com.mp3.jaudiotagger.tag.reference.ID3V2Version; -import com.mp3.jaudiotagger.tag.reference.Languages; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisAlbumArtistReadOptions; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisAlbumArtistSaveOptions; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; - -public class TagOptionSingleton -{ - private boolean isWriteWavForTwonky = false; - - private WavOptions wavOptions = WavOptions.READ_ID3_ONLY; - - public void setWavOptions(WavOptions wavOptions) - { - this.wavOptions = wavOptions; - } - - public WavOptions getWavOptions() - { - return wavOptions; - } - - private WavSaveOptions wavSaveOptions = WavSaveOptions.SAVE_BOTH; - - public void setWavSaveOptions(WavSaveOptions wavSaveOptions) - { - this.wavSaveOptions = wavSaveOptions; - } - - public WavSaveOptions getWavSaveOptions() - { - return wavSaveOptions; - } - - private WavSaveOrder wavSaveOrder = WavSaveOrder.INFO_THEN_ID3; - - public void setWavSaveOrder(WavSaveOrder wavSaveOrder) - { - this.wavSaveOrder = wavSaveOrder; - } - - public WavSaveOrder getWavSaveOrder() - { - return wavSaveOrder; - } - - private VorbisAlbumArtistSaveOptions vorbisAlbumArtistSaveOptions = VorbisAlbumArtistSaveOptions.WRITE_ALBUMARTIST; - - public void setVorbisAlbumArtistSaveOptions(VorbisAlbumArtistSaveOptions vorbisAlbumArtistSaveOptions) - { - this.vorbisAlbumArtistSaveOptions = vorbisAlbumArtistSaveOptions; - } - - public VorbisAlbumArtistSaveOptions getVorbisAlbumArtistSaveOptions() - { - return vorbisAlbumArtistSaveOptions; - } - - private VorbisAlbumArtistReadOptions vorbisAlbumArtistReadOptions = VorbisAlbumArtistReadOptions.READ_ALBUMARTIST_THEN_JRIVER; - - public void setVorbisAlbumArtistReadOptions(VorbisAlbumArtistReadOptions vorbisAlbumArtistReadOptions) - { - this.vorbisAlbumArtistReadOptions = vorbisAlbumArtistReadOptions; - } - - public VorbisAlbumArtistReadOptions getVorbisAlbumArtisReadOptions() - { - return vorbisAlbumArtistReadOptions; - } - - /** - * - */ - 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; - - private boolean isAPICDescriptionITunesCompatible = 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 , default to 4mb - */ - private long writeChunkSize= (4 * 1024 * 1024); - - private boolean isWriteMp4GenresAsText=false; - - private boolean isWriteMp3GenresAsText=false; - - private ID3V2Version id3v2Version = ID3V2Version.ID3_V23; - - /** - * Whether Files.isWritable should be used to check if a file can be written. In some - * cases, isWritable can return false negatives. - */ - private boolean checkIsWritable = false; - - /** - * Preserve file identity if possible - */ - private boolean preserveFileIdentity = true; - - /** - * - */ - - /** - * 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; - } - - /** - * @param filenameTagSave - */ - public void setFilenameTagSave(boolean filenameTagSave) - { - this.filenameTagSave = filenameTagSave; - } - - /** - * @return - */ - public boolean isFilenameTagSave() - { - return filenameTagSave; - } - - /** - * @param id3v2Version - */ - public void setID3V2Version(ID3V2Version id3v2Version) - { - this.id3v2Version = id3v2Version; - } - - /** - * @return - */ - public ID3V2Version getID3V2Version() - { - return id3v2Version; - } - - - /** - * @param instanceKey - */ - public void setInstanceKey(String instanceKey) - { - TagOptionSingleton.defaultOptions = instanceKey; - } - - /** - * @return - */ - public static String getInstanceKey() - { - return defaultOptions; - } - - - /** - * @param id3v1Save - */ - public void setId3v1Save(boolean id3v1Save) - { - this.id3v1Save = id3v1Save; - } - - /** - * @return - */ - public boolean isId3v1Save() - { - return id3v1Save; - } - - /** - * @param id3v1SaveAlbum - */ - public void setId3v1SaveAlbum(boolean id3v1SaveAlbum) - { - this.id3v1SaveAlbum = id3v1SaveAlbum; - } - - /** - * @return - */ - public boolean isId3v1SaveAlbum() - { - return id3v1SaveAlbum; - } - - /** - * @param id3v1SaveArtist - */ - public void setId3v1SaveArtist(boolean id3v1SaveArtist) - { - this.id3v1SaveArtist = id3v1SaveArtist; - } - - /** - * @return - */ - public boolean isId3v1SaveArtist() - { - return id3v1SaveArtist; - } - - /** - * @param id3v1SaveComment - */ - public void setId3v1SaveComment(boolean id3v1SaveComment) - { - this.id3v1SaveComment = id3v1SaveComment; - } - - /** - * @return - */ - public boolean isId3v1SaveComment() - { - return id3v1SaveComment; - } - - /** - * @param id3v1SaveGenre - */ - public void setId3v1SaveGenre(boolean id3v1SaveGenre) - { - this.id3v1SaveGenre = id3v1SaveGenre; - } - - /** - * @return - */ - public boolean isId3v1SaveGenre() - { - return id3v1SaveGenre; - } - - /** - * @param id3v1SaveTitle - */ - public void setId3v1SaveTitle(boolean id3v1SaveTitle) - { - this.id3v1SaveTitle = id3v1SaveTitle; - } - - /** - * @return - */ - public boolean isId3v1SaveTitle() - { - return id3v1SaveTitle; - } - - /** - * @param id3v1SaveTrack - */ - public void setId3v1SaveTrack(boolean id3v1SaveTrack) - { - this.id3v1SaveTrack = id3v1SaveTrack; - } - - /** - * @return - */ - public boolean isId3v1SaveTrack() - { - return id3v1SaveTrack; - } - - /** - * @param id3v1SaveYear - */ - public void setId3v1SaveYear(boolean id3v1SaveYear) - { - this.id3v1SaveYear = id3v1SaveYear; - } - - /** - * @return - */ - public boolean isId3v1SaveYear() - { - return id3v1SaveYear; - } - - - /** - * @param id3v2PaddingCopyTag - */ - public void setId3v2PaddingCopyTag(boolean id3v2PaddingCopyTag) - { - this.id3v2PaddingCopyTag = id3v2PaddingCopyTag; - } - - /** - * @return - */ - public boolean isId3v2PaddingCopyTag() - { - return id3v2PaddingCopyTag; - } - - - /** - * @param id3v2PaddingWillShorten - */ - public void setId3v2PaddingWillShorten(boolean id3v2PaddingWillShorten) - { - this.id3v2PaddingWillShorten = id3v2PaddingWillShorten; - } - - /** - * @return - */ - public boolean isId3v2PaddingWillShorten() - { - return id3v2PaddingWillShorten; - } - - /** - * @param id3v2Save - */ - public void setId3v2Save(boolean id3v2Save) - { - this.id3v2Save = id3v2Save; - } - - /** - * @return - */ - public boolean isId3v2Save() - { - return 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(); - } - - /** - * 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; - } - } - - /** - * 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; - } - - /** - * @param lyrics3KeepEmptyFieldIfRead - */ - public void setLyrics3KeepEmptyFieldIfRead(boolean lyrics3KeepEmptyFieldIfRead) - { - this.lyrics3KeepEmptyFieldIfRead = lyrics3KeepEmptyFieldIfRead; - } - - /** - * @return - */ - public boolean isLyrics3KeepEmptyFieldIfRead() - { - return lyrics3KeepEmptyFieldIfRead; - } - - /** - * @param lyrics3Save - */ - public void setLyrics3Save(boolean lyrics3Save) - { - this.lyrics3Save = lyrics3Save; - } - - /** - * @return - */ - public boolean isLyrics3Save() - { - return lyrics3Save; - } - - /** - * @param lyrics3SaveEmptyField - */ - public void setLyrics3SaveEmptyField(boolean lyrics3SaveEmptyField) - { - this.lyrics3SaveEmptyField = lyrics3SaveEmptyField; - } - - /** - * @return - */ - public boolean isLyrics3SaveEmptyField() - { - return 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); - } - - /** - * 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; - } - - /** - * 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; - } - - /** - * @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(); - } - - /** - * @param originalSavedAfterAdjustingID3v2Padding - * - */ - public void setOriginalSavedAfterAdjustingID3v2Padding(boolean originalSavedAfterAdjustingID3v2Padding) - { - this.originalSavedAfterAdjustingID3v2Padding = originalSavedAfterAdjustingID3v2Padding; - } - - /** - * @return - */ - public boolean isOriginalSavedAfterAdjustingID3v2Padding() - { - return originalSavedAfterAdjustingID3v2Padding; - } - - - /** - * 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; - } - } - - /** - * 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; - } - - /** - * - */ - public void setToDefault() - { - isWriteWavForTwonky = false; - wavOptions = WavOptions.READ_ID3_UNLESS_ONLY_INFO; - wavSaveOptions = WavSaveOptions.SAVE_BOTH; - 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; - isAPICDescriptionITunesCompatible=false; - isEncodeUTF16BomAsLittleEndian = true; - writeChunkSize=5000000; - isWriteMp4GenresAsText=false; - padNumberTotalLength = PadNumberOption.PAD_ONE_ZERO; - id3v2Version = ID3V2Version.ID3_V23; - checkIsWritable = false; - preserveFileIdentity = false; - //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; - } - - /** - * 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; - } - - /** - * 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 isWriteMp3GenresAsText() - { - return isWriteMp3GenresAsText; - } - - public void setWriteMp3GenresAsText(boolean writeMp3GenresAsText) - { - isWriteMp3GenresAsText = writeMp3GenresAsText; - } - - /** - * 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; - } - - /** - * Itunes expects APIC description to be encoded as ISO-8859-1 even if text encoding is set to 1 (UTF16) - */ - public boolean isAPICDescriptionITunesCompatible() - { - return isAPICDescriptionITunesCompatible; - } - - public void setAPICDescriptionITunesCompatible(boolean APICDescriptionITunesCompatible) - { - isAPICDescriptionITunesCompatible = APICDescriptionITunesCompatible; - } - - /** - * Whether Files.isWritable should be used to check if a file can be written. In some - * cases, isWritable can return false negatives. - */ - public boolean isCheckIsWritable() { - return checkIsWritable; - } - - public void setCheckIsWritable(boolean checkIsWritable) { - this.checkIsWritable = checkIsWritable; - } - - /** - *

- * If set to {@code true}, when writing, make an attempt to overwrite the existing file in-place - * instead of first moving it out of the way and moving a temp file into its place. - *

- *

- * Preserving the file identity has the advantage of preserving the creation time - * as well as the Unix inode or Windows - * fileIndex. - *

- * - * @return {@code true} or {@code false}. Default is {@code false}. - */ - public boolean isPreserveFileIdentity() { - return preserveFileIdentity; - } - - /** - * If set to {@code true}, when writing, make an attempt to preserve the file identity. - * - * @param preserveFileIdentity {@code true} or {@code false} - * @see #isPreserveFileIdentity() - */ - public void setPreserveFileIdentity(final boolean preserveFileIdentity) { - this.preserveFileIdentity = preserveFileIdentity; - } - - public boolean isWriteWavForTwonky() - { - return isWriteWavForTwonky; - } - - public void setWriteWavForTwonky(boolean isWriteWavForTwonky) - { - this.isWriteWavForTwonky = isWriteWavForTwonky; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagTextField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagTextField.java deleted file mode 100644 index c1fcf339..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/TagTextField.java +++ /dev/null @@ -1,60 +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 com.mp3.jaudiotagger.tag; - -import java.nio.charset.Charset; - -/** - * 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(); - - /** - * Returns the current used charset encoding. - * - * @return Charset encoding. - */ - Charset getEncoding(); - - /** - * Sets the content of the field. - * - * @param content fields content. - */ - void setContent(String content); - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - void setEncoding(Charset encoding); -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTag.java deleted file mode 100644 index 95d5ee73..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTag.java +++ /dev/null @@ -1,412 +0,0 @@ -package com.mp3.jaudiotagger.tag.aiff; - -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.id3.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.reference.ID3V2Version; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Wraps ID3Tag for most of its metadata. - */ -public class AiffTag implements Tag, Id3SupportingTag -{ - private List chunkSummaryList = new ArrayList(); - - public void addChunkSummary(ChunkSummary cs) - { - chunkSummaryList.add(cs); - } - - public List getChunkSummaryList() - { - return chunkSummaryList; - } - - private boolean isIncorrectlyAlignedTag = false; - - private boolean isExistingId3Tag = false; - - /** - * @return true if the file that this tag was written from already contains an ID3 chunk - */ - public boolean isExistingId3Tag() - { - return isExistingId3Tag; - } - - public void setExistingId3Tag(boolean isExistingId3Tag) - { - this.isExistingId3Tag = isExistingId3Tag; - } - - private AbstractID3v2Tag id3Tag; - - 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; - } - - @Override - public void addField(TagField field) throws FieldDataInvalidException - { - id3Tag.addField(field); - } - - @Override - 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 - */ - @Override - public List getAll(FieldKey genericKey) throws KeyNotFoundException - { - return id3Tag.getAll(genericKey); - } - - @Override - 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. - */ - @Override - public boolean isEmpty() - { - return (id3Tag == null || id3Tag.isEmpty()); - } - - @Override - public void setField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - - @Override - public void addField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - /** - * @param field - * @throws FieldDataInvalidException - */ - @Override - public void setField(TagField field) throws FieldDataInvalidException - { - id3Tag.setField(field); - } - - @Override - public TagField createField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException - { - return id3Tag.createField(genericKey, value); - } - - @Override - public String getFirst(String id) - { - return id3Tag.getFirst(id); - } - - @Override - public String getValue(FieldKey id, int index) throws KeyNotFoundException - { - return id3Tag.getValue(id, index); - } - - @Override - public String getFirst(FieldKey id) throws KeyNotFoundException - { - return getValue(id, 0); - } - - @Override - public TagField getFirstField(String id) - { - return id3Tag.getFirstField(id); - } - - @Override - 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 - */ - @Override - public void deleteField(FieldKey fieldKey) throws KeyNotFoundException - { - id3Tag.deleteField(fieldKey); - } - - @Override - public void deleteField(String id) throws KeyNotFoundException - { - id3Tag.deleteField(id); - } - - @Override - public Iterator getFields() - { - return id3Tag.getFields(); - } - - @Override - public int getFieldCount() - { - return id3Tag.getFieldCount(); - } - - @Override - public int getFieldCountIncludingSubValues() - { - return getFieldCount(); - } - - @Override - public boolean setEncoding(Charset enc) throws FieldDataInvalidException - { - return id3Tag.setEncoding(enc); - } - - /** - * Create artwork field. Not currently supported. - */ - @Override - public TagField createField(Artwork artwork) throws FieldDataInvalidException - { - return id3Tag.createField(artwork); - } - - @Override - public void setField(Artwork artwork) throws FieldDataInvalidException - { - id3Tag.setField(artwork); - } - - @Override - public void addField(Artwork artwork) throws FieldDataInvalidException - { - id3Tag.addField(artwork); - } - - @Override - public List getArtworkList() - { - return id3Tag.getArtworkList(); - } - - @Override - public List getFields(FieldKey id) throws KeyNotFoundException - { - return id3Tag.getFields(id); - } - - @Override - public Artwork getFirstArtwork() - { - return id3Tag.getFirstArtwork(); - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - @Override - public void deleteArtworkField() throws KeyNotFoundException - { - id3Tag.deleteArtworkField(); - } - - @Override - public boolean hasField(FieldKey genericKey) - { - return id3Tag.hasField(genericKey); - } - - - @Override - public boolean hasField(String id) - { - return id3Tag.hasField(id); - } - - @Override - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return createField(FieldKey.IS_COMPILATION, String.valueOf(value)); - } - - @Override - public String toString() - { - StringBuilder sb = new StringBuilder(); - - for(ChunkSummary cs:chunkSummaryList) - { - sb.append(cs.toString()+"\n"); - } - if (id3Tag != null) - { - sb.append("Aiff ID3 Tag:\n"); - if(isExistingId3Tag()) - { - if(isIncorrectlyAlignedTag) - { - sb.append("\tincorrectly starts as odd byte\n"); - } - sb.append("\tstartLocation:" + Hex.asDecAndHex(getStartLocationInFileOfId3Chunk()) + "\n"); - sb.append("\tendLocation:" + Hex.asDecAndHex(getEndLocationInFileOfId3Chunk()) + "\n"); - } - sb.append(id3Tag.toString()+"\n"); - return sb.toString(); - } - else - { - return "tag:empty"; - } - } - - /** - * @return size of the vanilla ID3Tag excluding surrounding chunk - */ - public long getSizeOfID3TagOnly() - { - if (!isExistingId3Tag()) - { - return 0; - } - return (id3Tag.getEndLocationInFile() - id3Tag.getStartLocationInFile()); - } - - /** - * @return size of the ID3 Chunk including header - */ - public long getSizeOfID3TagIncludingChunkHeader() - { - if (!isExistingId3Tag()) - { - return 0; - } - return getSizeOfID3TagOnly() + ChunkHeader.CHUNK_HEADER_SIZE; - } - - /** - * Offset into file of start ID3Chunk including header - * - * @return - */ - public long getStartLocationInFileOfId3Chunk() - { - if (!isExistingId3Tag()) - { - return 0; - } - return id3Tag.getStartLocationInFile() - ChunkHeader.CHUNK_HEADER_SIZE; - } - - public long getEndLocationInFileOfId3Chunk() - { - if(!isExistingId3Tag()) - { - return 0; - } - return id3Tag.getEndLocationInFile(); - } - - public boolean equals(Object obj) - { - return id3Tag.equals(obj); - } - - public boolean isIncorrectlyAlignedTag() - { - return isIncorrectlyAlignedTag; - } - - public void setIncorrectlyAlignedTag(boolean isIncorrectlyAlignedTag) - { - this.isIncorrectlyAlignedTag = isIncorrectlyAlignedTag; - } - - /** - * Default based on user option - * - * @return - */ - public static AbstractID3v2Tag createDefaultID3Tag() - { - 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 ID3v23Tag(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTagFieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTagFieldKey.java deleted file mode 100644 index 710a8434..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/aiff/AiffTagFieldKey.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AbstractAsfTagImageField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AbstractAsfTagImageField.java deleted file mode 100644 index 798df657..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AbstractAsfTagImageField.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.MetadataDescriptor; -import com.mp3.jaudiotagger.tag.TagField; - -/** - * 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); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfFieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfFieldKey.java deleted file mode 100644 index be348532..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfFieldKey.java +++ /dev/null @@ -1,391 +0,0 @@ -package com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.ContainerType; -import com.mp3.jaudiotagger.audio.asf.data.ContentBranding; -import com.mp3.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 - */ - - ACOUSTID_FINGERPRINT("Acoustid/Fingerprint", false), - ACOUSTID_FINGERPRINT_OLD("AcoustId/Fingerprint", false), - ACOUSTID_ID("Acoustid/Id", false), - ALBUM("WM/AlbumTitle", false), - ALBUM_ARTIST("WM/AlbumArtist", true), - ALBUM_ARTIST_SORT("WM/AlbumArtistSortOrder", false), - ALBUM_ARTISTS("ALBUM_ARTISTS", true), - ALBUM_ARTISTS_SORT("ALBUM_ARTISTS_SORT", true), - ALBUM_SORT("WM/AlbumSortOrder", false), - AMAZON_ID("ASIN", false), - ARRANGER("WM/Arranger",false), - ARRANGER_SORT("ARRANGER_SORT",true), - ARTISTS("WM/ARTISTS", true), - ARTISTS_SORT("WM/ARTISTS_SORT",true), - ARTIST_SORT("WM/ArtistSortOrder", false), - BARCODE("WM/Barcode", false), - BPM("WM/BeatsPerMinute", false), - CATALOG_NO("WM/CatalogNo", false), - CATEGORY("WM/Category", true), - CHOIR("CHOIR", true), - CHOIR_SORT("CHOIR_SORT", true), - CLASSICAL_CATALOG("CLASSICAL_CATALOG", true), - CLASSICAL_NICKNAME("CLASSICAL_NICKNAME", true), - COMPOSER("WM/Composer", true), - COMPOSER_SORT("WM/ComposerSort", false), - CONDUCTOR("WM/Conductor", true), - CONDUCTOR_SORT("CONDUCTOR_SORT",true), - COUNTRY("WM/Country", false), - 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), - DJMIXER("WM/DJMixer",false), - ENCODED_BY("WM/EncodedBy", false), - ENCODER("WM/ToolName", false), - ENGINEER("WM/Engineer",false), - ENSEMBLE("ENSEMBLE",true), - ENSEMBLE_SORT("ENSEMBLE_SORT",true), - FBPM("FBPM", true), - GENRE("WM/Genre", true), - GENRE_ID("WM/GenreID", true), - GROUP("GROUP", false), - GROUPING("WM/ContentGroupDescription", false), - INITIAL_KEY("WM/InitialKey", false), - INSTRUMENT("INSTRUMENT", true), - INVOLVED_PERSON("WM/InvolvedPerson", true), - ISRC("WM/ISRC", false), - ISVBR("IsVBR", true), - IS_CLASSICAL("IS_CLASSICAL", false), - IS_COMPILATION("WM/IsCompilation", false), - IS_SOUNDTRACK("IS_SOUNDTRACK", false), - LANGUAGE("WM/Language", true), - LYRICIST("WM/Writer", true), - LYRICS("WM/Lyrics", false), - LYRICS_SYNCHRONISED("WM/Lyrics_Synchronised", true), - MEDIA("WM/Media", false), - MIXER("WM/Mixer",false), - MM_RATING("SDB/Rating", true), - MOOD("WM/Mood", true), - MOOD_ACOUSTIC("MOOD_ACOUSTIC", false), - MOOD_AGGRESSIVE("MOOD_AGGRESSIVE", false), - MOOD_AROUSAL("MOOD_AROUSAL", false), - MOOD_DANCEABILITY("MOOD_DANCEABILITY", false), - MOOD_ELECTRONIC("MOOD_ELECTRONIC", false), - MOOD_HAPPY("MOOD_HAPPY", false), - MOOD_INSTRUMENTAL("MOOD_INSTRUMENTAL", false), - MOOD_PARTY("MOOD_PARTY", false), - MOOD_RELAXED("MOOD_RELAXED", false), - MOOD_SAD("MOOD_SAD", false), - MOOD_VALENCE("MOOD_VALENCE", false), - MOVEMENT("MOVEMENT", false), - MOVEMENT_NO("MOVEMENT_NO", false), - MOVEMENT_TOTAL("MOVEMENT_TOTAL", false), - MUSICBRAINZ_ARTISTID("MusicBrainz/Artist Id", false), - MUSICBRAINZ_DISC_ID("MusicBrainz/Disc Id", false), - MUSICBRAINZ_ORIGINAL_RELEASEID("MusicBrainz/Original Album Id", false), - MUSICBRAINZ_RELEASEARTISTID("MusicBrainz/Album Artist Id", false), - MUSICBRAINZ_RELEASEGROUPID("MusicBrainz/Release Group Id", false), - MUSICBRAINZ_RELEASEID("MusicBrainz/Album Id", false), - MUSICBRAINZ_RELEASETRACKID("MusicBrainz/Release Track 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_TRACK_ID("MusicBrainz/Track Id", false), - MUSICBRAINZ_WORKID("MusicBrainz/Work Id", false), - MUSICBRAINZ_WORK_COMPOSITION("MUSICBRAINZ_WORK_COMPOSITION",true), - MUSICBRAINZ_WORK_COMPOSITION_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_COMPOSITION_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL1("MUSICBRAINZ_WORK_PART_LEVEL1",true), - MUSICBRAINZ_WORK_PART_LEVEL1_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_PART_LEVEL1_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL1_TYPE("MUSICBRAINZ_WORK_PART_LEVEL1_TYPE",true), - MUSICBRAINZ_WORK_PART_LEVEL2("MUSICBRAINZ_WORK_PART_LEVEL2",true), - MUSICBRAINZ_WORK_PART_LEVEL2_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_PART_LEVEL2_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL2_TYPE("MUSICBRAINZ_WORK_PART_LEVEL2_TYPE",true), - MUSICBRAINZ_WORK_PART_LEVEL3("MUSICBRAINZ_WORK_PART_LEVEL3",true), - MUSICBRAINZ_WORK_PART_LEVEL3_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_PART_LEVEL3_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL3_TYPE("MUSICBRAINZ_WORK_PART_LEVEL3_TYPE",true), - MUSICBRAINZ_WORK_PART_LEVEL4("MUSICBRAINZ_WORK_PART_LEVEL4",true), - MUSICBRAINZ_WORK_PART_LEVEL4_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_PART_LEVEL4_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL4_TYPE("MUSICBRAINZ_WORK_PART_LEVEL4_TYPE",true), - MUSICBRAINZ_WORK_PART_LEVEL5("MUSICBRAINZ_WORK_PART_LEVEL5",true), - MUSICBRAINZ_WORK_PART_LEVEL5_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_PART_LEVEL5_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL5_TYPE("MUSICBRAINZ_WORK_PART_LEVEL5_TYPE",true), - MUSICBRAINZ_WORK_PART_LEVEL6_ID("MUSICBRAINZ_MUSICBRAINZ_WORK_PART_LEVEL6_ID",true), - MUSICBRAINZ_WORK_PART_LEVEL6("MUSICBRAINZ_WORK_PART_LEVEL6",true), - MUSICBRAINZ_WORK_PART_LEVEL6_TYPE("MUSICBRAINZ_WORK_PART_LEVEL6_TYPE",true), - MUSICIP_ID("MusicIP/PUID", false), - OCCASION("Occasion", true), - OPUS("OPUS",true), - ORCHESTRA("ORCHESTRA", true), - ORCHESTRA_SORT("ORCHESTRA_SORT",true), - ORIGINAL_ALBUM("WM/OriginalAlbumTitle", true), - ORIGINAL_ARTIST("WM/OriginalArtist", true), - ORIGINAL_LYRICIST("WM/OriginalLyricist", true), - ORIGINAL_YEAR("WM/OriginalReleaseYear", true), - PART("PART", true), - PART_NUMBER("PARTNUMBER",true), - PART_TYPE("PART_TYPE",true), - PERFORMER("PERFORMER", true), - PERFORMER_NAME("PERFORMER_NAME",true), - PERFORMER_NAME_SORT("PERFORMER_NAME_SORT",true), - PERIOD("PERIOD",true), - PRODUCER("WM/Producer", false), - QUALITY("Quality", true), - RANKING("RANKING", true), - RECORD_LABEL("WM/Publisher", false), - REMIXER("WM/ModifiedBy", false), - SCRIPT("WM/Script", false), - SINGLE_DISC_TRACK_NO("SINGLE_DISC_TRACK_NO",true), - SUBTITLE("WM/SubTitle", false), - TAGS("WM/Tags", false), - TEMPO("Tempo", true), - TIMBRE("TIMBRE_BRIGHTNESS", false), - TITLE_MOVEMENT("TITLE_MOVEMENT", false), - MUSICBRAINZ_WORK("MUSICBRAINZ_WORK", false), - TITLE_SORT("WM/TitleSortOrder", false), - TONALITY("TONALITY", 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_LYRICS_SITE("WM/LyricsUrl", 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), - USER_RATING("WM/SharedUserRating", true), - WORK("WORK", true), - WORK_TYPE("WORK_TYPE",true), - YEAR("WM/Year", 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); - } - } - } - - - /** - * 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(); - } - - - /** - * 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. - */ - private 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. - */ - private 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. - */ - private 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); - } - - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTag.java deleted file mode 100644 index 2967e7d9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTag.java +++ /dev/null @@ -1,792 +0,0 @@ -package com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.generic.AbstractTag; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.jaudiotagger.tag.reference.PictureTypes; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.*; - -/** - * Tag implementation for ASF.
- * - * @author Christian Laireiter - */ -public final class AsfTag extends AbstractTag -{ - /** - * 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(); - } - } - - /** - * Stores a list of field keys, which identify common fields.
- */ - public final static Set COMMON_FIELDS; - - /** - * This map contains the mapping from {@link com.mp3.jaudiotagger.tag.FieldKey} to - * {@link AsfFieldKey}. - */ - private static final EnumMap tagFieldToAsfField; - - // Mapping from generic key to asf key - - static - { - tagFieldToAsfField = new EnumMap(FieldKey.class); - - tagFieldToAsfField.put(FieldKey.ACOUSTID_FINGERPRINT, AsfFieldKey.ACOUSTID_FINGERPRINT); - tagFieldToAsfField.put(FieldKey.ACOUSTID_ID, AsfFieldKey.ACOUSTID_ID); - 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_ARTISTS, AsfFieldKey.ALBUM_ARTISTS); - tagFieldToAsfField.put(FieldKey.ALBUM_ARTISTS_SORT, AsfFieldKey.ALBUM_ARTISTS_SORT); - tagFieldToAsfField.put(FieldKey.ALBUM_SORT, AsfFieldKey.ALBUM_SORT); - tagFieldToAsfField.put(FieldKey.AMAZON_ID, AsfFieldKey.AMAZON_ID); - tagFieldToAsfField.put(FieldKey.ARRANGER, AsfFieldKey.ARRANGER); - tagFieldToAsfField.put(FieldKey.ARRANGER_SORT, AsfFieldKey.ARRANGER_SORT); - tagFieldToAsfField.put(FieldKey.ARTIST, AsfFieldKey.AUTHOR); - tagFieldToAsfField.put(FieldKey.ARTISTS, AsfFieldKey.ARTISTS); - tagFieldToAsfField.put(FieldKey.ARTISTS_SORT, AsfFieldKey.ARTISTS_SORT); - tagFieldToAsfField.put(FieldKey.ARTIST_SORT, AsfFieldKey.ARTIST_SORT); - tagFieldToAsfField.put(FieldKey.BARCODE, AsfFieldKey.BARCODE); - tagFieldToAsfField.put(FieldKey.BPM, AsfFieldKey.BPM); - tagFieldToAsfField.put(FieldKey.CATALOG_NO, AsfFieldKey.CATALOG_NO); - tagFieldToAsfField.put(FieldKey.CHOIR, AsfFieldKey.CHOIR); - tagFieldToAsfField.put(FieldKey.CHOIR_SORT, AsfFieldKey.CHOIR_SORT); - tagFieldToAsfField.put(FieldKey.CLASSICAL_CATALOG, AsfFieldKey.CLASSICAL_CATALOG); - tagFieldToAsfField.put(FieldKey.CLASSICAL_NICKNAME, AsfFieldKey.CLASSICAL_NICKNAME); - 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.CONDUCTOR_SORT, AsfFieldKey.CONDUCTOR_SORT); - tagFieldToAsfField.put(FieldKey.COPYRIGHT, AsfFieldKey.COPYRIGHT); - tagFieldToAsfField.put(FieldKey.COUNTRY, AsfFieldKey.COUNTRY); - 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.DJMIXER, AsfFieldKey.DJMIXER); - tagFieldToAsfField.put(FieldKey.MOOD_ELECTRONIC, AsfFieldKey.MOOD_ELECTRONIC); - tagFieldToAsfField.put(FieldKey.ENCODER, AsfFieldKey.ENCODER); - tagFieldToAsfField.put(FieldKey.ENGINEER, AsfFieldKey.ENGINEER); - tagFieldToAsfField.put(FieldKey.ENSEMBLE, AsfFieldKey.ENSEMBLE); - tagFieldToAsfField.put(FieldKey.ENSEMBLE_SORT, AsfFieldKey.ENSEMBLE_SORT); - tagFieldToAsfField.put(FieldKey.FBPM, AsfFieldKey.FBPM); - tagFieldToAsfField.put(FieldKey.GENRE, AsfFieldKey.GENRE); - tagFieldToAsfField.put(FieldKey.GROUP, AsfFieldKey.GROUP); - tagFieldToAsfField.put(FieldKey.GROUPING, AsfFieldKey.GROUPING); - tagFieldToAsfField.put(FieldKey.INSTRUMENT, AsfFieldKey.INSTRUMENT); - tagFieldToAsfField.put(FieldKey.INVOLVED_PERSON, AsfFieldKey.INVOLVED_PERSON); - tagFieldToAsfField.put(FieldKey.ISRC, AsfFieldKey.ISRC); - tagFieldToAsfField.put(FieldKey.IS_CLASSICAL, AsfFieldKey.IS_CLASSICAL); - tagFieldToAsfField.put(FieldKey.IS_COMPILATION, AsfFieldKey.IS_COMPILATION); - tagFieldToAsfField.put(FieldKey.IS_SOUNDTRACK, AsfFieldKey.IS_SOUNDTRACK); - 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.MIXER, AsfFieldKey.MIXER); - tagFieldToAsfField.put(FieldKey.MOOD, AsfFieldKey.MOOD); - tagFieldToAsfField.put(FieldKey.MOOD_ACOUSTIC, AsfFieldKey.MOOD_ACOUSTIC); - tagFieldToAsfField.put(FieldKey.MOOD_AGGRESSIVE, AsfFieldKey.MOOD_AGGRESSIVE); - tagFieldToAsfField.put(FieldKey.MOOD_AROUSAL, AsfFieldKey.MOOD_AROUSAL); - tagFieldToAsfField.put(FieldKey.MOOD_DANCEABILITY, AsfFieldKey.MOOD_DANCEABILITY); - tagFieldToAsfField.put(FieldKey.MOOD_HAPPY, AsfFieldKey.MOOD_HAPPY); - tagFieldToAsfField.put(FieldKey.MOOD_INSTRUMENTAL, AsfFieldKey.MOOD_INSTRUMENTAL); - tagFieldToAsfField.put(FieldKey.MOOD_PARTY, AsfFieldKey.MOOD_PARTY); - tagFieldToAsfField.put(FieldKey.MOOD_RELAXED, AsfFieldKey.MOOD_RELAXED); - tagFieldToAsfField.put(FieldKey.MOOD_SAD, AsfFieldKey.MOOD_SAD); - tagFieldToAsfField.put(FieldKey.MOOD_VALENCE, AsfFieldKey.MOOD_VALENCE); - tagFieldToAsfField.put(FieldKey.MOVEMENT, AsfFieldKey.MOVEMENT); - tagFieldToAsfField.put(FieldKey.MOVEMENT_NO, AsfFieldKey.MOVEMENT_NO); - tagFieldToAsfField.put(FieldKey.MOVEMENT_TOTAL, AsfFieldKey.MOVEMENT_TOTAL); - 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_TRACK_ID, AsfFieldKey.MUSICBRAINZ_RELEASETRACKID); - 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, AsfFieldKey.MUSICBRAINZ_WORK); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_ID, AsfFieldKey.MUSICBRAINZ_WORKID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION, AsfFieldKey.MUSICBRAINZ_WORK_COMPOSITION); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID, AsfFieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL1); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL2); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL3); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL4); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL5); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL6); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID); - tagFieldToAsfField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, AsfFieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE); - - tagFieldToAsfField.put(FieldKey.MUSICIP_ID, AsfFieldKey.MUSICIP_ID); - tagFieldToAsfField.put(FieldKey.OCCASION, AsfFieldKey.OCCASION); - tagFieldToAsfField.put(FieldKey.OPUS, AsfFieldKey.OPUS); - tagFieldToAsfField.put(FieldKey.ORCHESTRA, AsfFieldKey.ORCHESTRA); - tagFieldToAsfField.put(FieldKey.ORCHESTRA_SORT, AsfFieldKey.ORCHESTRA_SORT); - tagFieldToAsfField.put(FieldKey.ORIGINAL_ALBUM, AsfFieldKey.ORIGINAL_ALBUM); - tagFieldToAsfField.put(FieldKey.ORIGINAL_ARTIST, AsfFieldKey.ORIGINAL_ARTIST); - tagFieldToAsfField.put(FieldKey.ORIGINAL_LYRICIST, AsfFieldKey.ORIGINAL_LYRICIST); - tagFieldToAsfField.put(FieldKey.ORIGINAL_YEAR, AsfFieldKey.ORIGINAL_YEAR); - tagFieldToAsfField.put(FieldKey.PART, AsfFieldKey.PART); - tagFieldToAsfField.put(FieldKey.PART_NUMBER, AsfFieldKey.PART_NUMBER); - tagFieldToAsfField.put(FieldKey.PART_TYPE, AsfFieldKey.PART_TYPE); - tagFieldToAsfField.put(FieldKey.PERFORMER, AsfFieldKey.PERFORMER); - tagFieldToAsfField.put(FieldKey.PERFORMER_NAME, AsfFieldKey.PERFORMER_NAME); - tagFieldToAsfField.put(FieldKey.PERFORMER_NAME_SORT, AsfFieldKey.PERFORMER_NAME_SORT); - tagFieldToAsfField.put(FieldKey.PERIOD, AsfFieldKey.PERIOD); - tagFieldToAsfField.put(FieldKey.PRODUCER, AsfFieldKey.PRODUCER); - tagFieldToAsfField.put(FieldKey.QUALITY, AsfFieldKey.QUALITY); - tagFieldToAsfField.put(FieldKey.RANKING, AsfFieldKey.RANKING); - tagFieldToAsfField.put(FieldKey.RATING, AsfFieldKey.USER_RATING); - tagFieldToAsfField.put(FieldKey.RECORD_LABEL, AsfFieldKey.RECORD_LABEL); - tagFieldToAsfField.put(FieldKey.REMIXER, AsfFieldKey.REMIXER); - tagFieldToAsfField.put(FieldKey.SCRIPT, AsfFieldKey.SCRIPT); - tagFieldToAsfField.put(FieldKey.SINGLE_DISC_TRACK_NO, AsfFieldKey.SINGLE_DISC_TRACK_NO); - tagFieldToAsfField.put(FieldKey.SUBTITLE, AsfFieldKey.SUBTITLE); - tagFieldToAsfField.put(FieldKey.TAGS, AsfFieldKey.TAGS); - tagFieldToAsfField.put(FieldKey.TEMPO, AsfFieldKey.TEMPO); - tagFieldToAsfField.put(FieldKey.TIMBRE, AsfFieldKey.TIMBRE); - tagFieldToAsfField.put(FieldKey.TITLE, AsfFieldKey.TITLE); - tagFieldToAsfField.put(FieldKey.TITLE_MOVEMENT, AsfFieldKey.TITLE_MOVEMENT); - tagFieldToAsfField.put(FieldKey.TITLE_SORT, AsfFieldKey.TITLE_SORT); - tagFieldToAsfField.put(FieldKey.TONALITY, AsfFieldKey.TONALITY); - 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.WORK, AsfFieldKey.WORK); - tagFieldToAsfField.put(FieldKey.WORK_TYPE, AsfFieldKey.WORK_TYPE); - tagFieldToAsfField.put(FieldKey.YEAR, AsfFieldKey.YEAR); - } - - 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... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (values == null || values[0] == 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, values[0]); - } - - /** - * 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()); - } - - /** - * {@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 com.mp3.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()); - } - - /** - * {@inheritDoc} - * @param enc - */ - @Override - protected boolean isAllowedEncoding(final Charset 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)); - } - } - - /** - * Sets the copyright.
- * - * @param Copyright the copyright to set. - */ - public void setCopyright(final String Copyright) - { - setField(createCopyrightField(Copyright)); - } - - /** - * Sets the Rating.
- * - * @param rating the rating to set. - */ - public void setRating(final String rating) - { - setField(createRatingField(rating)); - } - - /** - * - * @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; - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return createField(FieldKey.IS_COMPILATION,String.valueOf(value)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagBannerField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagBannerField.java deleted file mode 100644 index 0941d807..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagBannerField.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.ContainerType; -import com.mp3.jaudiotagger.audio.asf.data.ContentBranding; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagCoverField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagCoverField.java deleted file mode 100644 index 24bb5954..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagCoverField.java +++ /dev/null @@ -1,226 +0,0 @@ -package com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.asf.data.MetadataDescriptor; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.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("com.mp3.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; - this.imageDataSize = data.length; - this.pictureType = pictureType; - this.mimeType = mimeType; - - // 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(com.mp3.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 = com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagField.java deleted file mode 100644 index c98e7fcc..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagField.java +++ /dev/null @@ -1,157 +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 com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.MetadataDescriptor; -import com.mp3.jaudiotagger.tag.TagField; - -/** - * This class encapsulates a - * {@link com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagTextField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagTextField.java deleted file mode 100644 index 5ff8a952..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/asf/AsfTagTextField.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.mp3.jaudiotagger.tag.asf; - -import com.mp3.jaudiotagger.audio.asf.data.AsfHeader; -import com.mp3.jaudiotagger.audio.asf.data.MetadataDescriptor; -import com.mp3.jaudiotagger.audio.asf.util.Utils; -import com.mp3.jaudiotagger.tag.TagTextField; - -import java.nio.charset.Charset; - -/** - * 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); - } - - @Override - public String getContent() { - return getDescriptor().getString(); - } - - @Override - public Charset getEncoding() { - return AsfHeader.ASF_CHARSET; - } - - /** - * @return true if blank or only contains whitespace - */ - @Override - public boolean isEmpty() { - return Utils.isBlank(getContent()); - } - - @Override - public void setContent(final String content) { - getDescriptor().setString(content); - } - - @Override - public void setEncoding(final Charset encoding) { - if (!AsfHeader.ASF_CHARSET.equals(encoding)) { - throw new IllegalArgumentException( - "Only UTF-16LE is possible with ASF."); - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataType.java deleted file mode 100644 index 2c5ad12b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataType.java +++ /dev/null @@ -1,413 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -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("com.mp3.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 if (copyObject.value instanceof ArrayList) - { - this.value = ((ArrayList) copyObject.value).clone(); - } - else if (copyObject.value instanceof LinkedList) - { - this.value = ((LinkedList) copyObject.value).clone(); - } - else - { - throw new UnsupportedOperationException("Unable to create copy of class " + copyObject.getClass()); - } - } - - /** - * Set the framebody that this datatype is associated with - * - * @param frameBody - */ - public void setBody(AbstractTagFrameBody frameBody) - { - this.frameBody = frameBody; - } - - /** - * Get the framebody associated with this datatype - * - * @return the framebody that this datatype is associated with - */ - public AbstractTagFrameBody getBody() - { - return 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; - } - - /** - * 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; - } - - /** - * Get value held by this Object - * - * @return value held by this Object - */ - public Object getValue() - { - return 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 com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataTypeList.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataTypeList.java deleted file mode 100644 index ca16a950..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractDataTypeList.java +++ /dev/null @@ -1,149 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents a list of {@link Cloneable}(!!) {@link AbstractDataType}s, continuing until the end of the buffer. - * - * @author Hendrik Schreiber - * @version $Id:$ - */ -public abstract class AbstractDataTypeList extends AbstractDataType -{ - - public AbstractDataTypeList(final String identifier, final AbstractTagFrameBody frameBody) - { - super(identifier, frameBody); - setValue(new ArrayList()); - } - - /** - * Copy constructor. - * By convention, subclasses must implement a constructor, accepting an argument of their own class type - * and call this constructor for {@link com.mp3.jaudiotagger.tag.id3.ID3Tags#copyObject(Object)} to work. - * A parametrized {@code AbstractDataTypeList} is not sufficient. - * - * @param copy instance - */ - protected AbstractDataTypeList(final AbstractDataTypeList copy) - { - super(copy); - } - - public List getValue() - { - return (List)super.getValue(); - } - - public void setValue(final List list) - { - super.setValue(list == null ? new ArrayList() : new ArrayList(list)); - } - - /** - * Return the size in byte of this datatype list. - * - * @return the size in bytes - */ - public int getSize() - { - int size = 0; - for (final T t : getValue()) { - size+=t.getSize(); - } - return size; - } - - /** - * Reads list of {@link EventTimingCode}s from buffer starting at the given offset. - * - * @param buffer buffer - * @param offset initial offset into the buffer - * @throws NullPointerException - * @throws IndexOutOfBoundsException - */ - public void readByteArray(final byte[] buffer, final int offset) throws InvalidDataTypeException - { - if (buffer == 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 = " + buffer.length); - } - - // no events - if (offset >= buffer.length) - { - getValue().clear(); - return; - } - for (int currentOffset = offset; currentOffset -{ - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractString.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractString.java deleted file mode 100644 index 501ac782..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractString.java +++ /dev/null @@ -1,191 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -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) - final byte textEncoding = this.getBody().getTextEncoding(); - final TextEncoding encoding = TextEncoding.getInstanceOf(); - final Charset charset = encoding.getCharsetForId(textEncoding); - CharsetEncoder encoder = charset.newEncoder(); - - if (encoder.canEncode((String) value)) - { - return true; - } - else - { - logger.finest("Failed Trying to decode" + value + "with" + encoder.toString()); - return false; - } - } - - /** - * If they have specified UTF-16 then decoder works out by looking at BOM - * but if missing we have to make an educated guess otherwise just use - * specified decoder - * - * @param inBuffer - * @return - */ - protected CharsetDecoder getCorrectDecoder(ByteBuffer inBuffer) - { - CharsetDecoder decoder=null; - if(inBuffer.remaining()<=2) - { - decoder = getTextEncodingCharSet().newDecoder(); - decoder.reset(); - return decoder; - } - - if(getTextEncodingCharSet()== StandardCharsets.UTF_16) - { - if(inBuffer.getChar(0)==0xfffe || inBuffer.getChar(0)==0xfeff) - { - //Get the Specified Decoder - decoder = getTextEncodingCharSet().newDecoder(); - decoder.reset(); - } - else - { - if(inBuffer.get(0)==0) - { - decoder = StandardCharsets.UTF_16BE.newDecoder(); - decoder.reset(); - } - else - { - decoder = StandardCharsets.UTF_16LE.newDecoder(); - decoder.reset(); - } - } - } - else - { - decoder = getTextEncodingCharSet().newDecoder(); - decoder.reset(); - } - return decoder; - } - - /** - * 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 Charset getTextEncodingCharSet() - { - final byte textEncoding = this.getBody().getTextEncoding(); - final Charset charSetName = TextEncoding.getInstanceOf().getCharsetForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charSetName.name()); - return charSetName; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java deleted file mode 100644 index c1c0c30c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractStringStringValuePair.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractValuePair.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractValuePair.java deleted file mode 100644 index bf4f32fa..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/AbstractValuePair.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanByte.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanByte.java deleted file mode 100644 index 164ba300..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanByte.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanString.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanString.java deleted file mode 100644 index 503c5322..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/BooleanString.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java deleted file mode 100644 index 4f8fbe0f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ByteArraySizeTerminated.java +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/DataTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/DataTypes.java deleted file mode 100644 index 023db20e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/DataTypes.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 com.mp3.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"; - - //ETCO Frame - public static final String OBJ_TYPE_OF_EVENT = "TypeOfEvent"; - public static final String OBJ_TIMED_EVENT = "TimedEvent"; - public static final String OBJ_TIMED_EVENT_LIST = "TimedEventList"; - //SYTC Frame - public static final String OBJ_SYNCHRONISED_TEMPO_DATA = "SynchronisedTempoData"; - public static final String OBJ_SYNCHRONISED_TEMPO = "SynchronisedTempo"; - public static final String OBJ_SYNCHRONISED_TEMPO_LIST = "SynchronisedTempoList"; - /** - * - */ - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCode.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCode.java deleted file mode 100644 index 9f44cb47..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCode.java +++ /dev/null @@ -1,151 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.EventTimingTypes; - -/** - * A single event timing code. Part of a list of timing codes ({@link EventTimingCodeList}), that are contained in - * {@link com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyETCO}. - * - * @author Hendrik Schreiber - * @version $Id:$ - */ -public class EventTimingCode extends AbstractDataType implements Cloneable -{ - - private static final int SIZE = 5; - private NumberHashMap type = new NumberHashMap(DataTypes.OBJ_TYPE_OF_EVENT, null, 1); - private NumberFixedLength timestamp = new NumberFixedLength(DataTypes.OBJ_DATETIME, null, 4); - - public EventTimingCode(final EventTimingCode copy) { - super(copy); - this.type.setValue(copy.type.getValue()); - this.timestamp.setValue(copy.timestamp.getValue()); - } - - public EventTimingCode(final String identifier, final AbstractTagFrameBody frameBody) - { - this(identifier, frameBody, 0x00, 0L); - } - - public EventTimingCode(final String identifier, final AbstractTagFrameBody frameBody, final int type, final long timestamp) - { - super(identifier, frameBody); - setBody(frameBody); - this.type.setValue(type); - this.timestamp.setValue(timestamp); - } - - @Override - public void setBody(final AbstractTagFrameBody frameBody) - { - super.setBody(frameBody); - this.type.setBody(frameBody); - this.timestamp.setBody(frameBody); - } - - public long getTimestamp() - { - return ((Number)timestamp.getValue()).longValue(); - } - - public void setTimestamp(final long timestamp) - { - this.timestamp.setValue(timestamp); - } - - public int getType() - { - return ((Number) type.getValue()).intValue(); - } - - public void setType(final int type) - { - this.type.setValue(type); - } - - @Override - public int getSize() - { - return SIZE; - } - - @Override - public void readByteArray(final byte[] buffer, final int originalOffset) throws InvalidDataTypeException - { - int localOffset = originalOffset; - int size = getSize(); - - logger.finest("offset:" + localOffset); - - //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 (originalOffset > buffer.length-size) - { - logger.warning("Invalid size for FrameBody"); - throw new InvalidDataTypeException("Invalid size for FrameBody"); - } - - this.type.readByteArray(buffer, localOffset); - localOffset += this.type.getSize(); - this.timestamp.readByteArray(buffer, localOffset); - localOffset += this.timestamp.getSize(); - } - - @Override - public byte[] writeByteArray() - { - final byte[] typeData = this.type.writeByteArray(); - final byte[] timeData = this.timestamp.writeByteArray(); - if (typeData == null || timeData == null) return null; - - final byte[] objectData = new byte[typeData.length + timeData.length]; - System.arraycopy(typeData, 0, objectData, 0, typeData.length); - System.arraycopy(timeData, 0, objectData, typeData.length, timeData.length); - return objectData; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - - final EventTimingCode that = (EventTimingCode) o; - if (this.getType() != that.getType() || this.getTimestamp() != that.getTimestamp()) return false; - return true; - } - - @Override - public int hashCode() - { - int result = type != null ? type.hashCode() : 0; - result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "" + getType() + " (\"" + EventTimingTypes.getInstanceOf().getValueForId(getType()) + "\"), " + getTimestamp(); - } - - @Override - public Object clone() throws CloneNotSupportedException { - return new EventTimingCode(this); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCodeList.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCodeList.java deleted file mode 100644 index 9c402a11..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/EventTimingCodeList.java +++ /dev/null @@ -1,48 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyETCO; - -/** - * List of {@link EventTimingCode}s. - * - * @author Hendrik Schreiber - * @version $Id:$ - */ -public class EventTimingCodeList extends AbstractDataTypeList -{ - - /** - * Mandatory, concretely-typed copy constructor, as required by - * {@link AbstractDataTypeList#AbstractDataTypeList(AbstractDataTypeList)}. - * - * @param copy instance to copy - */ - public EventTimingCodeList(final EventTimingCodeList copy) - { - super(copy); - } - - public EventTimingCodeList(final FrameBodyETCO body) - { - super(DataTypes.OBJ_TIMED_EVENT_LIST, body); - } - - @Override - protected EventTimingCode createListElement() - { - return new EventTimingCode(DataTypes.OBJ_TIMED_EVENT, frameBody); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/HashMapInterface.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/HashMapInterface.java deleted file mode 100644 index 6c1b1b2b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/HashMapInterface.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * A simple Interface required by classes which use a HashMap to Store ValuePairs - */ - -package com.mp3.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 - */ - public Map getKeyToValue(); - - /** - * @return a mapping between the value to the key within the frame - */ - public Map getValueToKey(); - - /** - * @return an interator of the values within the map - */ - public Iterator iterator(); -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ID3v2LyricLine.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ID3v2LyricLine.java deleted file mode 100644 index b0c8448c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/ID3v2LyricLine.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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; - } - - public void setText(String text) - { - this.text = text; - } - - /** - * @return - */ - public String getText() - { - return text; - } - - public void setTimeStamp(long timeStamp) - { - this.timeStamp = timeStamp; - } - - /** - * @return - */ - public long getTimeStamp() - { - return 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 = new String(arr, offset, arr.length - offset - 4, StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Image.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Image.java deleted file mode 100644 index 6f661246..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Image.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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; - } - - /** - * @param description - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return - */ - public String getDescription() - { - return this.description; - } - - /** - * @param filename - */ - public void setFilename(String filename) - { - this.filename = filename; - } - - /** - * @return - */ - public String getFilename() - { - return this.filename; - } - - /** - * @return - */ - public int getSize() - { - int size; - - size = filename.length() + 2 + description.length() + 2; - - if (time != null) - { - size += time.getSize(); - } - - return size; - } - - /** - * @param time - */ - public void setTimeStamp(Lyrics3TimeStamp time) - { - this.time = time; - } - - /** - * @return - */ - public Lyrics3TimeStamp getTimeStamp() - { - return this.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 writeString().getBytes(StandardCharsets.ISO_8859_1); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Line.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Line.java deleted file mode 100644 index bf33768d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3Line.java +++ /dev/null @@ -1,228 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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; - } - - public void setLyric(ID3v2LyricLine line) - { - this.lyric = line.getText(); - } - - /** - * @return - */ - public String getLyric() - { - return lyric; - } - - /** - * @return - */ - public int getSize() - { - int size = 0; - for (Object aTimeStamp : timeStamp) - { - size += ((Lyrics3TimeStamp) aTimeStamp).getSize(); - } - return size + lyric.length(); - } - - /** - * @param time - */ - public void setTimeStamp(Lyrics3TimeStamp time) - { - timeStamp.clear(); - timeStamp.add(time); - } - - /** - * @return - */ - public Iterator getTimeStamp() - { - return timeStamp.iterator(); - } - - 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 writeString().getBytes(StandardCharsets.ISO_8859_1); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java deleted file mode 100644 index 1187d9cb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Lyrics3TimeStamp.java +++ /dev/null @@ -1,238 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -public class Lyrics3TimeStamp extends AbstractDataType -{ - /** - * - */ - private long minute = 0; - - /** - * - */ - private long second = 0; - - /** - * Todo this is wrong - * @param s - */ - public void readString(String s) - { - } - - /** - * 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; - } - - public void setMinute(long minute) - { - this.minute = minute; - } - - /** - * @return - */ - public long getMinute() - { - return minute; - } - - public void setSecond(long second) - { - this.second = second; - } - - /** - * @return - */ - public long getSecond() - { - return 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 writeString().getBytes(StandardCharsets.ISO_8859_1); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java deleted file mode 100644 index d6d75847..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/MultipleTextEncodedStringNullTerminated.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.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 Values(); - } - - public MultipleTextEncodedStringNullTerminated(TextEncodedStringSizeTerminated object) - { - super(object); - value = new 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberFixedLength.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberFixedLength.java deleted file mode 100644 index 01fd70af..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberFixedLength.java +++ /dev/null @@ -1,187 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Represents a Number of a fixed number of decimal places. - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.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; - } - - - /** - * 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; - } - } - - /** - * Return size - * - * @return the size of this number - */ - public int getSize() - { - return 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberHashMap.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberHashMap.java deleted file mode 100644 index a7bc98e8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberHashMap.java +++ /dev/null @@ -1,271 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.*; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; -import com.mp3.jaudiotagger.tag.reference.PictureTypes; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberVariableLength.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberVariableLength.java deleted file mode 100644 index ab571533..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/NumberVariableLength.java +++ /dev/null @@ -1,246 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Pair.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Pair.java deleted file mode 100644 index 9dc27efd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/Pair.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - -/** - * A pair of values - * - * USed by TIPL, TMCL and IPLS frames that store pairs of values - */ -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; - } - - public String getPairValue() - { - return getKey() + '\0' + getValue(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java deleted file mode 100644 index f8ef0251..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PairedTextEncodedStringNullTerminated.java +++ /dev/null @@ -1,300 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.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 ValuePairs(); - } - - public PairedTextEncodedStringNullTerminated(TextEncodedStringSizeTerminated object) - { - super(object); - value = new 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 String toString() - { - return value.toString(); - } - - /** - * 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(); - } - - public void add(Pair pair) - { - mapping.add(pair); - } - /** - * 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()+','); - } - if(sb.length()>0) - { - sb.setLength(sb.length() - 1); - } - 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()); - } - } - - public ValuePairs getValue() - { - return (ValuePairs) value; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PartOfSet.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PartOfSet.java deleted file mode 100644 index 9281e4ce..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/PartOfSet.java +++ /dev/null @@ -1,524 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.tag.options.PadNumberOption; -import com.mp3.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 and MVNM - * - * 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 - CharsetDecoder decoder = getTextEncodingCharSet().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); - } - } - } - - final Charset charset = getTextEncodingCharSet(); - final String valueWithBOM; - final CharsetEncoder encoder; - if (StandardCharsets.UTF_16.equals(charset)) - { - encoder = StandardCharsets.UTF_16LE.newEncoder(); - //Note remember LE BOM is ff fe but this is handled by encoder Unicode char is fe ff - valueWithBOM = '\ufeff' + value; - } - else - { - encoder = charset.newEncoder(); - valueWithBOM = value; - } - encoder.onMalformedInput(CodingErrorAction.IGNORE); - encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - - final ByteBuffer bb = encoder.encode(CharBuffer.wrap(valueWithBOM)); - 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 Charset getTextEncodingCharSet() - { - final byte textEncoding = this.getBody().getTextEncoding(); - final Charset charset = TextEncoding.getInstanceOf().getCharsetForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charset.name()); - return charset; - } - - /** - * Holds data - */ - public static class PartOfSetValue - { - private static final Pattern trackNoPatternWithTotalCount; - private static final Pattern trackNoPattern; - - 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 static final String SEPARATOR = "/"; - 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 Integer getTotal() - { - return total; - } - - 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 void setCount(String count) - { - try - { - this.count = Integer.parseInt(count); - this.rawCount = count; - resetValueFromCounts(); - } - catch (NumberFormatException nfe) - { - - } - } - - public void setTotal(String total) - { - try - { - this.total = Integer.parseInt(total); - this.rawTotal = total; - resetValueFromCounts(); - } - catch (NumberFormatException nfe) - { - - } - } - - 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()); - } - } - - public PartOfSetValue getValue() - { - return (PartOfSetValue) value; - } - - public String toString() - { - return value.toString(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDate.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDate.java deleted file mode 100644 index 1b110687..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDate.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.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); - } - - /** - * @param value - */ - public void setValue(Object value) - { - if (value != null) - { - this.value = ID3Tags.stripChar(value.toString(), '-'); - } - } - - /** - * @return - */ - public Object getValue() - { - if (value != null) - { - return ID3Tags.stripChar(value.toString(), '-'); - } - else - { - return null; - } - } - - public boolean equals(Object obj) - { - return obj instanceof StringDate && super.equals(obj); - - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDateTime.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDateTime.java deleted file mode 100644 index a2a3bb43..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringDateTime.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.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); - } - - /** - * @param value - */ - public void setValue(Object value) - { - if (value != null) - { - this.value = value.toString().replace(' ', 'T'); - } - } - - /** - * @return - */ - public Object getValue() - { - if (value != null) - { - return value.toString().replace(' ', 'T'); - } - else - { - return null; - } - } - - public boolean equals(Object obj) - { - return obj instanceof StringDateTime && super.equals(obj); - - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringFixedLength.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringFixedLength.java deleted file mode 100644 index 6e929339..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringFixedLength.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.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 - { - final CharsetDecoder decoder = getTextEncodingCharSet().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 - { - final Charset charset = getTextEncodingCharSet(); - final CharsetEncoder encoder; - if (StandardCharsets.UTF_16.equals(charset)) - { - //Note remember LE BOM is ff fe but tis is handled by encoder Unicode char is fe ff - encoder = StandardCharsets.UTF_16LE.newEncoder(); - dataBuffer = encoder.encode(CharBuffer.wrap('\ufeff' + (String) value)); - } - else - { - encoder = charset.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 Charset getTextEncodingCharSet() - { - final byte textEncoding = this.getBody().getTextEncoding(); - final Charset charset = TextEncoding.getInstanceOf().getCharsetForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charset.name()); - return charset; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringHashMap.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringHashMap.java deleted file mode 100644 index 74496aaf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringHashMap.java +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.jaudiotagger.tag.reference.Languages; - -import java.nio.charset.Charset; -import java.util.Iterator; -import java.util.Map; -import java.util.TreeSet; - -import static com.mp3.jaudiotagger.StandardCharsets.ISO_8859_1; - - -/** - * 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 || keyToValue.get(value) == null) - { - return ""; - } - else - { - return keyToValue.get(value); - } - } - - /** - * @return the ISO_8859 encoding for Datatypes of this type - */ - protected Charset getTextEncodingCharSet() - { - return ISO_8859_1; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringNullTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringNullTerminated.java deleted file mode 100644 index a5718207..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringNullTerminated.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.nio.charset.Charset; - -import static com.mp3.jaudiotagger.StandardCharsets.ISO_8859_1; - -/** - * 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 Charset getTextEncodingCharSet() - { - return ISO_8859_1; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringSizeTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringSizeTerminated.java deleted file mode 100644 index 681116aa..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/StringSizeTerminated.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.nio.charset.Charset; - -import static com.mp3.jaudiotagger.StandardCharsets.ISO_8859_1; - -/** - * 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 Charset getTextEncodingCharSet() - { - return ISO_8859_1; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCode.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCode.java deleted file mode 100644 index d223732d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCode.java +++ /dev/null @@ -1,151 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.EventTimingTypes; - -/** - * A single synchronized tempo code. Part of a list of temnpo codes ({@link com.mp3.jaudiotagger.tag.datatype.SynchronisedTempoCodeList}), that are contained in - * {@link com.mp3.jaudiotagger.tag.id3.framebody.FrameBodySYTC} - * - * @author Hendrik Schreiber - * @version $Id:$ - */ -public class SynchronisedTempoCode extends AbstractDataType implements Cloneable -{ - - private TempoCode tempo = new TempoCode(DataTypes.OBJ_SYNCHRONISED_TEMPO_DATA, null, 1); - private NumberFixedLength timestamp = new NumberFixedLength(DataTypes.OBJ_DATETIME, null, 4); - - public SynchronisedTempoCode(final SynchronisedTempoCode copy) { - super(copy); - this.tempo.setValue(copy.tempo.getValue()); - this.timestamp.setValue(copy.timestamp.getValue()); - } - - public SynchronisedTempoCode(final String identifier, final AbstractTagFrameBody frameBody) - { - this(identifier, frameBody, 0x00, 0L); - } - - public SynchronisedTempoCode(final String identifier, final AbstractTagFrameBody frameBody, final int tempo, final long timestamp) - { - super(identifier, frameBody); - setBody(frameBody); - this.tempo.setValue(tempo); - this.timestamp.setValue(timestamp); - } - - @Override - public void setBody(final AbstractTagFrameBody frameBody) - { - super.setBody(frameBody); - this.tempo.setBody(frameBody); - this.timestamp.setBody(frameBody); - } - - public long getTimestamp() - { - return ((Number)timestamp.getValue()).longValue(); - } - - public void setTimestamp(final long timestamp) - { - this.timestamp.setValue(timestamp); - } - - public int getTempo() - { - return ((Number) tempo.getValue()).intValue(); - } - - public void setTempo(final int tempo) - { - if (tempo < 0 || tempo > 510) throw new IllegalArgumentException("Tempo must be a positive value less than 511: " + tempo); - this.tempo.setValue(tempo); - } - - @Override - public int getSize() - { - return this.tempo.getSize() + this.timestamp.getSize(); - } - - @Override - public void readByteArray(final byte[] buffer, final int originalOffset) throws InvalidDataTypeException - { - int localOffset = originalOffset; - int size = getSize(); - - logger.finest("offset:" + localOffset); - - //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 (originalOffset > buffer.length-size) - { - logger.warning("Invalid size for FrameBody"); - throw new InvalidDataTypeException("Invalid size for FrameBody"); - } - - this.tempo.readByteArray(buffer, localOffset); - localOffset += this.tempo.getSize(); - this.timestamp.readByteArray(buffer, localOffset); - localOffset += this.timestamp.getSize(); - } - - @Override - public byte[] writeByteArray() - { - final byte[] typeData = this.tempo.writeByteArray(); - final byte[] timeData = this.timestamp.writeByteArray(); - if (typeData == null || timeData == null) return null; - - final byte[] objectData = new byte[typeData.length + timeData.length]; - System.arraycopy(typeData, 0, objectData, 0, typeData.length); - System.arraycopy(timeData, 0, objectData, typeData.length, timeData.length); - return objectData; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - - final SynchronisedTempoCode that = (SynchronisedTempoCode) o; - if (this.getTempo() != that.getTempo() || this.getTimestamp() != that.getTimestamp()) return false; - return true; - } - - @Override - public int hashCode() - { - int result = tempo != null ? tempo.hashCode() : 0; - result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "" + getTempo() + " (\"" + EventTimingTypes.getInstanceOf().getValueForId(getTempo()) + "\"), " + getTimestamp(); - } - - @Override - public Object clone() throws CloneNotSupportedException { - return new SynchronisedTempoCode(this); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCodeList.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCodeList.java deleted file mode 100644 index 33fc11d3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/SynchronisedTempoCodeList.java +++ /dev/null @@ -1,48 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodySYTC; - -/** - * List of {@link SynchronisedTempoCode}s. - * - * @author Hendrik Schreiber - * @version $Id:$ - */ -public class SynchronisedTempoCodeList extends AbstractDataTypeList -{ - - /** - * Mandatory, concretely-typed copy constructor, as required by - * {@link AbstractDataTypeList#AbstractDataTypeList(AbstractDataTypeList)}. - * - * @param copy instance to copy - */ - public SynchronisedTempoCodeList(final SynchronisedTempoCodeList copy) - { - super(copy); - } - - public SynchronisedTempoCodeList(final FrameBodySYTC body) - { - super(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST, body); - } - - @Override - protected SynchronisedTempoCode createListElement() - { - return new SynchronisedTempoCode(DataTypes.OBJ_SYNCHRONISED_TEMPO, frameBody); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TCONString.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TCONString.java deleted file mode 100644 index c4619dda..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TCONString.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - - -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Overrides in order to properly support the ID3v23 implemenation of TCON - */ -public class TCONString extends TextEncodedStringSizeTerminated -{ - private boolean isNullSeperateMultipleValues = true; - - - /** - * Creates a new empty TextEncodedStringSizeTerminated datatype. - * - * @param identifier identifies the frame type - * @param frameBody - */ - public TCONString(String identifier, AbstractTagFrameBody frameBody) - { - super(identifier, frameBody); - } - - /** - * Copy constructor - * - * @param object - */ - public TCONString(TCONString object) - { - super(object); - } - - public boolean equals(Object obj) - { - if(this==obj) - { - return true; - } - return obj instanceof TCONString && super.equals(obj); - } - - /** - * If this field is used with ID3v24 then it is usual to null separate values. Within ID3v23 not many - * frames officially support multiple values, so in absense of better solution we use the v24 method, however - * some frames such as TCON have there own method and should not null separate values. This can be controlled - * by this field. - */ - public boolean isNullSeperateMultipleValues() - { - return isNullSeperateMultipleValues; - } - - public void setNullSeperateMultipleValues(boolean nullSeperateMultipleValues) - { - isNullSeperateMultipleValues = nullSeperateMultipleValues; - } - - - /** - * Add an additional String to the current String value - * - * @param value - */ - @Override - public void addValue(String value) - { - //For ID3v24 we separate each value by a null - if(isNullSeperateMultipleValues()) - { - setValue(this.value + "\u0000" + value); - } - else - { - //For ID3v23 if they pass a numeric value in brackets this indicates a mapping to an ID3v2 genre and - //can be seen as a refinement and therefore do not need the non-standard (for ID3v23) null seperator - if(value.startsWith("(")) - { - setValue(this.value + value); - } - //but if just text we need to separate some way so we do using null separator - else - { - 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 getValues().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 = getValues(); - return (String) values.get(index); - } - - public static List splitV23(String value) - { - String[] valuesarray = value.replaceAll("(\\(\\d+\\)|\\(RX\\)|\\(CR\\)\\w*)", "$1\u0000").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; - } - - /** - * - * @return list of all values - */ - public List getValues() - { - if(isNullSeperateMultipleValues()) - { - return splitByNullSeperator((String) value); - } - else - { - return splitV23((String)value); - } - } - - /** - * Get value(s) whilst removing any trailing nulls - * - * @return - */ - public String getValueWithoutTrailingNull() - { - List values = getValues(); - StringBuffer sb = new StringBuffer(); - for(int i=0;iHendrik Schreiber - * @version $Id:$ - */ -public class TempoCode extends AbstractDataType -{ - private static final int MINIMUM_NO_OF_DIGITS = 1; - private static final int MAXIMUM_NO_OF_DIGITS = 2; - - public TempoCode(final TempoCode copy) - { - super(copy); - } - - public TempoCode(final String identifier, final AbstractTagFrameBody frameBody) - { - super(identifier, frameBody, 0); - } - - public TempoCode(final String identifier, final AbstractTagFrameBody frameBody, final Object value) { - super(identifier, frameBody, value); - } - - - @Override - public int getSize() - { - if (value == null) - { - return 0; - } - else - { - return ID3Tags.getWholeNumber(value) < 0xFF ? MINIMUM_NO_OF_DIGITS : MAXIMUM_NO_OF_DIGITS; - } - } - - @Override - public boolean equals(final Object that) - { - return that instanceof TempoCode && super.equals(that); - } - - @Override - public void readByteArray(final byte[] arr, final int offset) throws InvalidDataTypeException - { - if (arr == null) - { - throw new NullPointerException("Byte array is null"); - } - if (offset < 0) - { - throw new IllegalArgumentException("negative offset into an array offset:" + offset); - } - if (offset >= arr.length) - { - throw new InvalidDataTypeException("Offset to byte array is out of bounds: offset = " + offset + ", array.length = " + arr.length); - } - - long lvalue = 0; - lvalue += (arr[offset] & 0xff); - if (lvalue == 0xFF) - { - lvalue += (arr[offset+1] & 0xff); - } - value = lvalue; - } - - @Override - public byte[] writeByteArray() - { - final int size = getSize(); - final byte[] arr = new byte[size]; - long temp = ID3Tags.getWholeNumber(value); - int offset = 0; - if (temp >= 0xFF) - { - arr[offset] = (byte)0xFF; - offset++; - temp -= 0xFF; - } - arr[offset] = (byte) (temp & 0xFF); - return arr; - } - - @Override - public String toString() - { - return value == null ? "" : value.toString(); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java deleted file mode 100644 index 4763a9d7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringNullTerminated.java +++ /dev/null @@ -1,264 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; -import com.mp3.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 - final Charset charset = getTextEncodingCharSet(); - - - //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 = StandardCharsets.ISO_8859_1 == charset || StandardCharsets.UTF_8 == charset; - - 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); - - final CharsetDecoder decoder = getCorrectDecoder(inBuffer); - 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. - final Charset charset = getTextEncodingCharSet(); - try - { - if (StandardCharsets.UTF_16.equals(charset)) - { - if(TagOptionSingleton.getInstance().isEncodeUTF16BomAsLittleEndian()) - { - final CharsetEncoder encoder = StandardCharsets.UTF_16LE.newEncoder(); - encoder.onMalformedInput(CodingErrorAction.IGNORE); - encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - - //Note remember LE BOM is ff fe but this is handled by encoder Unicode char is fe ff - final ByteBuffer bb = encoder.encode(CharBuffer.wrap('\ufeff' + (String) value + '\0')); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } - else - { - final CharsetEncoder encoder = StandardCharsets.UTF_16BE.newEncoder(); - encoder.onMalformedInput(CodingErrorAction.IGNORE); - encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - - //Note BE BOM will leave as fe ff - final ByteBuffer bb = encoder.encode(CharBuffer.wrap('\ufeff' + (String) value + '\0')); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } - } - else - { - final CharsetEncoder encoder = charset.newEncoder(); - encoder.onMalformedInput(CodingErrorAction.IGNORE); - encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - - final ByteBuffer bb = encoder.encode(CharBuffer.wrap((String) value + '\0')); - data = new byte[bb.limit()]; - bb.get(data, 0, bb.limit()); - } - } - //https://bitbucket.org/ijabz/jaudiotagger/issue/1/encoding-metadata-to-utf-16-can-fail-if - catch (CharacterCodingException ce) - { - logger.severe(ce.getMessage()+":"+charset.name()+":"+value); - throw new RuntimeException(ce); - } - setSize(data.length); - return data; - } - - protected Charset getTextEncodingCharSet() - { - final byte textEncoding = this.getBody().getTextEncoding(); - final Charset charset = TextEncoding.getInstanceOf().getCharsetForId(textEncoding); - logger.finest("text encoding:" + textEncoding + " charset:" + charset.name()); - return charset; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java deleted file mode 100644 index e1b91ab9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/datatype/TextEncodedStringSizeTerminated.java +++ /dev/null @@ -1,361 +0,0 @@ -package com.mp3.jaudiotagger.tag.datatype; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrameBody; - -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 Foobar2000 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); - } - - 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 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 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); - - - //Decode sliced inBuffer - ByteBuffer inBuffer; - //#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); - - CharBuffer outBuffer = CharBuffer.allocate(arr.length - offset); - - - CharsetDecoder decoder = getCorrectDecoder(inBuffer); - 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 (StandardCharsets.UTF_16.equals(getTextEncodingCharSet())) { - 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.finest("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 - */ - protected 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 - */ - protected ByteBuffer writeStringUTF16LEBOM(final String next, final int i, final int noOfValues) - throws CharacterCodingException { - final CharsetEncoder encoder = StandardCharsets.UTF_16LE.newEncoder(); - encoder.onMalformedInput(CodingErrorAction.IGNORE); - encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - - ByteBuffer bb; - //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 - */ - protected ByteBuffer writeStringUTF16BEBOM(final String next, final int i, final int noOfValues) - throws CharacterCodingException { - final CharsetEncoder encoder = StandardCharsets.UTF_16BE.newEncoder(); - encoder.onMalformedInput(CodingErrorAction.IGNORE); - encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - - ByteBuffer bb; - //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 not be there but some applications continue to write - * this unnecessary null char. - */ - protected 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 - */ - protected 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() - final Charset charset = getTextEncodingCharSet(); - try { - - stripTrailingNull(); - - //Special Handling because there is no UTF16 BOM LE charset - String stringValue = (String) value; - Charset actualCharSet = null; - if (StandardCharsets.UTF_16.equals(charset)) { - if (TagOptionSingleton.getInstance().isEncodeUTF16BomAsLittleEndian()) { - actualCharSet = StandardCharsets.UTF_16LE; - } else { - actualCharSet = StandardCharsets.UTF_16BE; - } - } - - //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 (StandardCharsets.UTF_16LE.equals(actualCharSet)) { - outputBuffer.put(writeStringUTF16LEBOM(next, i, values.size())); - } else if (StandardCharsets.UTF_16BE.equals(actualCharSet)) { - outputBuffer.put(writeStringUTF16BEBOM(next, i, values.size())); - } else { - final CharsetEncoder charsetEncoder = charset.newEncoder(); - charsetEncoder.onMalformedInput(CodingErrorAction.IGNORE); - charsetEncoder.onUnmappableCharacter(CodingErrorAction.IGNORE); - outputBuffer.put(writeString(charsetEncoder, next, i, values.size())); - } - } - outputBuffer.flip(); - data = new byte[outputBuffer.limit()]; - outputBuffer.rewind(); - outputBuffer.get(data, 0, outputBuffer.limit()); - setSize(data.length); - } - //https://bitbucket.org/ijabz/jaudiotagger/issue/1/encoding-metadata-to-utf-16-can-fail-if - catch (CharacterCodingException ce) { - logger.severe(ce.getMessage() + ":" + charset + ":" + value); - throw new RuntimeException(ce); - } - return data; - } - - - /** - * 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; - } - - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/flac/FlacTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/flac/FlacTag.java deleted file mode 100644 index 7ad0ee1f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/flac/FlacTag.java +++ /dev/null @@ -1,631 +0,0 @@ -package com.mp3.jaudiotagger.tag.flac; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.jaudiotagger.tag.reference.PictureTypes; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey; -import com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; - -import java.nio.charset.Charset; -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< MetadataBlockDataPicture >()); - } - - 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; - } - - @Override - public void setField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - String value = values[0]; - if(genericKey==FieldKey.ALBUM_ARTIST) - { - switch(TagOptionSingleton.getInstance().getVorbisAlbumArtistSaveOptions()) - { - case WRITE_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - return; - } - - case WRITE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - setField(tagfield); - return; - } - - case WRITE_ALBUMARTIST_AND_DELETE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER.getFieldName()); - return; - } - - case WRITE_JRIVER_ALBUMARTIST_AND_DELETE_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - setField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST.getFieldName()); - return; - } - case WRITE_BOTH: - { - TagField tagfield1 = createField(genericKey, value); - setField(tagfield1); - TagField tagfield2 = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - setField(tagfield2); - return; - } - - } - } - else - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - } - - /** - * Create new field and add it to the tag - * - * @param genericKey - * @param values - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public void addField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - String value = values[0]; - if(genericKey==FieldKey.ALBUM_ARTIST) - { - switch(TagOptionSingleton.getInstance().getVorbisAlbumArtistSaveOptions()) - { - case WRITE_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - case WRITE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - addField(tagfield); - return; - } - case WRITE_ALBUMARTIST_AND_DELETE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER.getFieldName()); - return; - } - - case WRITE_JRIVER_ALBUMARTIST_AND_DELETE_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - addField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST.getFieldName()); - return; - } - case WRITE_BOTH: - { - TagField tagfield1 = createField(genericKey, value); - addField(tagfield1); - TagField tagfield2 = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - addField(tagfield2); - return; - } - - } - } - else - { - 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 com.mp3.jaudiotagger.tag.KeyNotFoundException - * @throws com.mp3.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(); - } - - @Override - public boolean setEncoding(Charset 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 - { - if(imageData==null) - { - throw new FieldDataInvalidException("ImageData cannot be null"); - } - 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(url.getBytes(StandardCharsets.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( - artwork.getImageUrl().getBytes(StandardCharsets.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); - } - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return tag.createCompilationField(value); - } - - public String toString() - { - return "FLAC " + getVorbisCommentTag(); - } - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3Tag.java deleted file mode 100644 index cfe39029..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3Tag.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Base class for all ID3 tags - * - */ -package com.mp3.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 -{ - //Logger - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.tag.id3"); - - public AbstractID3Tag() - { - } - - protected static final String TAG_RELEASE = "ID3v"; - - //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 = ""; - - /** - * 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(); - - - public AbstractID3Tag(AbstractID3Tag copyObject) - { - super(copyObject); - } - - - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v1Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v1Tag.java deleted file mode 100644 index f9c7cde5..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v1Tag.java +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Abstract superclass of all URL Frames - * - */ -package com.mp3.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 -{ - - //Logger - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.tag.id3"); - - - public AbstractID3v1Tag() - { - } - - public AbstractID3v1Tag(AbstractID3v1Tag copyObject) - { - super(copyObject); - } - - //If field is less than maximum field length this is how it is terminated - protected static final byte END_OF_FIELD = (byte) 0; - - //Used to detect end of field in String constructed from Data - protected static Pattern endofStringPattern = Pattern.compile("\\x00"); - - //Tag ID as held in file - public static final String TAG = "TAG"; - 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"; - - /** - * 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; - } - - /** - * 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)); - } - /** - * 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)) - { - try - { - logger.config("Deleted ID3v1 tag"); - file.setLength(file.length() - TAG_LENGTH); - } - catch(IOException ex) - { - logger.severe("Unable to delete existing ID3v1 Tag:"+ex.getMessage()); - } - } - else - { - logger.config("Unable to find ID3v1 tag to deleteField"); - } - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Frame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Frame.java deleted file mode 100644 index 6976072f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Frame.java +++ /dev/null @@ -1,655 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyEncrypted; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyUnsupported; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.logging.Level; - -/** - * This abstract class is each frame header inside a ID3v2 tag. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id$ - */ -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; - - //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 = ""; - - /** - * - * @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(); - - /** - * Create an empty frame - */ - protected AbstractID3v2Frame() - { - } - - /** - * 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; - - /** - * 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("com.mp3.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); - } - - /** - * 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) - { - if( - (buffer[0]=='\0')&& - (buffer[1]=='\0')&& - (buffer[2]=='\0')&& - (buffer[3]=='\0') - ) - { - return true; - } - return false; - } - - /** - * 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("com.mp3.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 PaddingException,InvalidFrameException - { - byte[] buffer = new byte[getFrameIdSize()]; - - //Read the Frame Identifier - if(getFrameIdSize()<=byteBuffer.remaining()) - { - byteBuffer.get(buffer, 0, getFrameIdSize()); - } - - if(isPadding(buffer)) - { - throw new PaddingException(getLoggingFilename() + ":only padding found"); - } - - if ((getFrameHeaderSize() - getFrameIdSize()) > byteBuffer.remaining()) - { - logger.warning(getLoggingFilename() + ":" + "No space to find another frame:"); - throw new InvalidFrameException(getLoggingFilename() + ":" + "No space to find another frame"); - } - - - 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("com.mp3.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; - } - - 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()); - - } - } - - /** - * 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(); - } - - /** - * Returns the current used charset encoding. - * - * @return Charset encoding. - */ - public Charset getEncoding() - { - final byte textEncoding = this.getBody().getTextEncoding(); - return TextEncoding.getInstanceOf().getCharsetForId(textEncoding); - } - - /** - * 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"); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Tag.java deleted file mode 100644 index 7b1aea54..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractID3v2Tag.java +++ /dev/null @@ -1,3094 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.AudioFile; -import com.mp3.jaudiotagger.audio.exceptions.UnableToCreateFileException; -import com.mp3.jaudiotagger.audio.exceptions.UnableToModifyFileException; -import com.mp3.jaudiotagger.audio.exceptions.UnableToRenameFileException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.logging.FileSystemMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.id3.framebody.*; -import com.mp3.jaudiotagger.tag.id3.valuepair.ID3NumberTotalFields; -import com.mp3.jaudiotagger.tag.id3.valuepair.StandardIPLSKey; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.reference.Languages; -import com.mp3.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.nio.charset.Charset; -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$ - */ -public abstract class AbstractID3v2Tag extends AbstractID3Tag implements Tag -{ - //Start location of this chunk - //TODO currently only used by ID3 embedded into Wav/Aiff but shoudl be extended to mp3s - private Long startLocationInFile = null; - - //End location of this chunk - private Long endLocationInFile = null; - - protected static final String TYPE_HEADER = "header"; - protected static final String TYPE_BODY = "body"; - - //Tag ID as held in file - public static final byte[] TAG_ID = {'I', 'D', '3'}; - public static final String TAGID = "ID3"; - - //The tag header is the same for ID3v2 versions - public static final int TAG_HEADER_LENGTH = 10; - public static final int FIELD_TAGID_LENGTH = 3; - public static final int FIELD_TAG_MAJOR_VERSION_LENGTH = 1; - public static final int FIELD_TAG_MINOR_VERSION_LENGTH = 1; - public static final int FIELD_TAG_FLAG_LENGTH = 1; - public static final int FIELD_TAG_SIZE_LENGTH = 4; - - protected static final int FIELD_TAGID_POS = 0; - public 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; - - //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; - - /** - * Holds the ids of invalid duplicate frames - */ - protected static final String TYPE_DUPLICATEFRAMEID = "duplicateFrameId"; - protected String duplicateFrameId = ""; - - /** - * Holds count the number of bytes used up by invalid duplicate frames - */ - protected static final String TYPE_DUPLICATEBYTES = "duplicateBytes"; - protected int duplicateBytes = 0; - - /** - * Holds count the number bytes used up by empty frames - */ - protected static final String TYPE_EMPTYFRAMEBYTES = "emptyFrameBytes"; - protected int emptyFrameBytes = 0; - - /** - * Holds the size of the tag as reported by the tag header - */ - protected static final String TYPE_FILEREADSIZE = "fileReadSize"; - protected int fileReadSize = 0; - - /** - * Holds count of invalid frames, (frames that could not be read) - */ - protected static final String TYPE_INVALIDFRAMES = "invalidFrames"; - protected int invalidFrames = 0; - - /** - * 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); - if (!(Arrays.equals(tagIdentifier, TAG_ID))) - { - return false; - } - return true; - } - - private static boolean isID3V2Header(FileChannel fc) throws IOException - { - long start = fc.position(); - ByteBuffer headerBuffer = Utils.readFileDataIntoBufferBE(fc, FIELD_TAGID_LENGTH); - fc.position(start); - String s = Utils.readThreeBytesAsChars(headerBuffer); - return s.equals(TAGID); - } - - - /** - * 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() + FIELD_TAGID_LENGTH + FIELD_TAG_MAJOR_VERSION_LENGTH + FIELD_TAG_MINOR_VERSION_LENGTH + FIELD_TAG_FLAG_LENGTH); - raf.read(tagHeader); - ByteBuffer bb = ByteBuffer.wrap(tagHeader); - - int size = ID3SyncSafeInteger.bufferToValue(bb); - raf.seek(size + TAG_HEADER_LENGTH); - return true; - } - - /** - * Is ID3 tag - * - * @param fc - * @return - * @throws IOException - */ - public static boolean isId3Tag(FileChannel fc) throws IOException - { - if (!isID3V2Header(fc)) - { - return false; - } - //So we have a tag - ByteBuffer bb = ByteBuffer.allocateDirect(FIELD_TAG_SIZE_LENGTH); - fc.position(fc.position() + FIELD_TAGID_LENGTH + FIELD_TAG_MAJOR_VERSION_LENGTH + FIELD_TAG_MINOR_VERSION_LENGTH + FIELD_TAG_FLAG_LENGTH); - fc.read(bb); - bb.flip(); - int size = ID3SyncSafeInteger.bufferToValue(bb); - fc.position(size + TAG_HEADER_LENGTH); - return true; - } - - /** - * 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) - { - } - - /** - * 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); - } - else if (o instanceof TyerTdatAggregatedFrame) - { - for (AbstractID3v2Frame next : ((TyerTdatAggregatedFrame) o).getFrames()) - { - addFrame(next); - } - } - //MultiFrames - else if (o instanceof ArrayList) - { - for (AbstractID3v2Frame frame : (ArrayList) o) - { - addFrame(frame); - } - } - } - } - - /** - * Add the frame converted to the correct version - * @param frame - */ - protected abstract void addFrame(AbstractID3v2Frame frame); - - /** - * Convert the frame to the correct frame(s) - * - * @param frame - * @return - * @throws InvalidFrameException - */ - protected abstract List convertFrame(AbstractID3v2Frame frame) throws InvalidFrameException; - - /** - * 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... values) throws KeyNotFoundException, FieldDataInvalidException - { - TagField tagfield = createField(genericKey, values); - setField(tagfield); - } - - public void addField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - - - /** - * All Number/Count frames are treated the same (TCK, TPOS, MVNM) - * - * @param newFrame - * @param nextFrame - */ - public void mergeNumberTotalFrames(AbstractID3v2Frame newFrame, AbstractID3v2Frame nextFrame) - { - AbstractFrameBodyNumberTotal newBody = (AbstractFrameBodyNumberTotal) newFrame.getBody(); - AbstractFrameBodyNumberTotal oldBody = (AbstractFrameBodyNumberTotal) nextFrame.getBody(); - - if (newBody.getNumber() != null && newBody.getNumber() > 0) - { - oldBody.setNumber(newBody.getNumberAsText()); - } - - if (newBody.getTotal() != null && newBody.getTotal() > 0) - { - oldBody.setTotal(newBody.getTotalAsText()); - } - return; - } - - /** - * 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; - } - } - //e.g TRCK, TPOS, MVNM - else if (newFrame.getBody() instanceof AbstractFrameBodyNumberTotal) - { - mergeNumberTotalFrames(newFrame,nextFrame); - return; - } - //e.g TIPL IPLS, TMCL - else if (newFrame.getBody() instanceof AbstractFrameBodyPairs) - { - AbstractFrameBodyPairs frameBody = (AbstractFrameBodyPairs) newFrame.getBody(); - AbstractFrameBodyPairs existingFrameBody = (AbstractFrameBodyPairs) 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 AbstractFrameBodyPairs) - { - AbstractFrameBodyPairs frameBody = (AbstractFrameBodyPairs) frame.getBody(); - AbstractFrameBodyPairs existingFrameBody = (AbstractFrameBodyPairs) existingFrame.getBody(); - existingFrameBody.addPair(frameBody.getText()); - } - else if (frame.getBody() instanceof AbstractFrameBodyNumberTotal) - { - AbstractFrameBodyNumberTotal frameBody = (AbstractFrameBodyNumberTotal) frame.getBody(); - AbstractFrameBodyNumberTotal existingFrameBody = (AbstractFrameBodyNumberTotal) existingFrame.getBody(); - - if (frameBody.getNumber() != null && frameBody.getNumber() > 0) - { - existingFrameBody.setNumber(frameBody.getNumberAsText()); - } - - if (frameBody.getTotal() != null && frameBody.getTotal() > 0) - { - existingFrameBody.setTotal(frameBody.getTotalAsText()); - } - } - 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); - } - } - - - /** - * 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 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(); - } - } - */ - - /** - * 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 - * @return new audioStartByte - different only if the audio content had to be moved - * @throws IOException - */ - public abstract long 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; - } - //#129 Workaround for https://bugs.openjdk.java.net/browse/JDK-8025619 - catch (Error error) - { - 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, int currentTagSize) throws IOException - { - } - - /** - * Write tag to output stream - * - * @param outputStream - * @throws IOException - */ - public void write(OutputStream outputStream) throws IOException - { - write(Channels.newChannel(outputStream), 0); - } - - /** - * Write tag to output stream - * - * @param outputStream - * @throws IOException - */ - public void write(OutputStream outputStream, int currentTagSize) throws IOException - { - write(Channels.newChannel(outputStream), currentTagSize); - } - - - /** - * Write paddings byte to the channel - * - * @param channel - * @param padding - * @throws IOException - */ - protected void writePadding(WritableByteChannel channel, int padding) throws IOException - { - if (padding > 0) - { - channel.write(ByteBuffer.wrap(new byte[padding])); - } - } - - /** - * 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 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; - } - - /** - * 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 - * the preferredSize and the min size required for new tag. For mp3 - * preferred size is the location of the audio, for other formats - * preferred size is the size of the existing tag - * - * @param tagSize - * @param preferredSize - * @return - */ - protected int calculateTagSize(int tagSize, int preferredSize) - { - /** We can fit in the tag so no adjustments required */ - if (tagSize <= preferredSize) - { - return preferredSize; - } - /** 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 FileNotFoundException, 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, "rw").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().contains(FileSystemMessage.ACCESS_IS_DENIED.getMsg()) || fe.getMessage().contains(FileSystemMessage.PERMISSION_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())); - } - } - } - - /** - * If frame already exists default behaviour is to just add another one, but can be overrridden if - * special handling required - * - * @param newFrame - * @param existingFrame - */ - protected void processDuplicateFrame(AbstractID3v2Frame newFrame, AbstractID3v2Frame existingFrame) - { - List list = new ArrayList(); - list.add(existingFrame); - list.add(newFrame); - frameMap.put(newFrame.getIdentifier(), list); - } - - /** - * 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 - * - * @param id - * @param newFrame - */ - protected final void copyFrameIntoMap(String id, AbstractID3v2Frame newFrame) - { - if (frameMap.containsKey(newFrame.getIdentifier())) - { - Object o = frameMap.get(newFrame.getIdentifier()); - if (o instanceof AbstractID3v2Frame) - { - processDuplicateFrame(newFrame, (AbstractID3v2Frame)o); - } - else if (o instanceof AggregatedFrame) - { - logger.severe("Duplicated Aggregate Frame, ignoring:" + id); - } - else if (o instanceof List) - { - List list = (List) o; - list.add(newFrame); - } - else - { - logger.severe("Unknown frame class:discarding:" + o.getClass()); - } - } - 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 if (o instanceof AggregatedFrame) - { - AggregatedFrame af = (AggregatedFrame) o; - for (AbstractID3v2Frame next : af.frames) - { - size += next.getSize(); - } - } - else if (o instanceof List) - { - 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. - List values = new ArrayList(); - List fields = getFields(genericKey); - - if (ID3NumberTotalFields.isNumber(genericKey)) - { - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - values.add(((AbstractFrameBodyNumberTotal) frame.getBody()).getNumberAsText()); - } - return values; - } - else if (ID3NumberTotalFields.isTotal(genericKey)) - { - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - values.add(((AbstractFrameBodyNumberTotal) frame.getBody()).getTotalAsText()); - } - return values; - } - else if(genericKey == FieldKey.RATING) - { - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - values.add(String.valueOf(((FrameBodyPOPM) frame.getBody()).getRating())); - } - return values; - } - else - { - 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 com.mp3.jaudiotagger.tag.Tag#hasField(String) - */ - public boolean hasField(String id) - { - return hasFrame(id); - } - - /** - * Is this tag empty - * - * @see com.mp3.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? - - @Override - public boolean setEncoding(final Charset 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 (ID3NumberTotalFields.isNumber(genericKey)||ID3NumberTotalFields.isTotal(genericKey)) - { - 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 (ID3NumberTotalFields.isNumber(genericKey)) - { - return ((AbstractFrameBodyNumberTotal) frame.getBody()).getNumberAsText(); - } - else if (ID3NumberTotalFields.isTotal(genericKey)) - { - return ((AbstractFrameBodyNumberTotal) frame.getBody()).getTotalAsText(); - } - } - else - { - return ""; - } - } - //Special Case, TODO may be possible to put into doGetValueAtIndex but getUserFriendlyValue in POPMGFrameBody - //is implemented different to what we would need. - else 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 field - * - * Only MUSICIAN field make use of Varargs values field - * - * @param genericKey is the generic key - * @param values - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public TagField createField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - - String value = values[0]; - 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 (ID3NumberTotalFields.isNumber(genericKey)) - { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - AbstractFrameBodyNumberTotal framebody = (AbstractFrameBodyNumberTotal) frame.getBody(); - framebody.setNumber(value); - return frame; - } - else if (ID3NumberTotalFields.isTotal(genericKey)) - { - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - AbstractFrameBodyNumberTotal framebody = (AbstractFrameBodyNumberTotal) frame.getBody(); - framebody.setTotal(value); - return frame; - } - else - { - return doCreateTagField(formatKey, values); - } - } - - /** - * 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 values - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - protected TagField doCreateTagField(FrameAndSubId formatKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - String value = values[0]; - - 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) - { - if (formatKey.getSubId() != null) - { - ((FrameBodyIPLS) (frame.getBody())).addPair(formatKey.getSubId(), value); - } - else - { - if(values.length>=2) - { - ((FrameBodyIPLS) (frame.getBody())).addPair(values[0], values[1]); - } - else - { - ((FrameBodyIPLS) (frame.getBody())).addPair(values[0]); - } - } - } - else if (frame.getBody() instanceof FrameBodyTIPL) - { - ((FrameBodyTIPL) (frame.getBody())).addPair(formatKey.getSubId(), value); - } - else if (frame.getBody() instanceof FrameBodyTMCL) - { - if(values.length>=2) - { - ((FrameBodyTMCL) (frame.getBody())).addPair(values[0], values[1]); - } - else - { - ((FrameBodyTMCL) (frame.getBody())).addPair(values[0]); - } - } - 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 (sub)frame - *

- * 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(); - - if (formatKey.getSubId() != null) - { - //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())) - { - if (((FrameBodyUFID) next).getUniqueIdentifier() != null) - { - values.add(new String(((FrameBodyUFID) next).getUniqueIdentifier())); - } - } - } - else if (next instanceof AbstractFrameBodyPairs) - { - for (Pair entry : ((AbstractFrameBodyPairs) next).getPairing().getMapping()) - { - if (entry.getKey().equals(formatKey.getSubId())) - { - if (entry.getValue() != null) - { - values.add(entry.getValue()); - } - } - } - } - else - { - throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass()); - } - } - } - //Special handling for paired fields with no defined key - else if ((formatKey.getGenericKey()!=null)&& - ((formatKey.getGenericKey() == FieldKey.PERFORMER)||(formatKey.getGenericKey() == FieldKey.INVOLVED_PERSON)) - ) - { - List list = getFields(formatKey.getFrameId()); - ListIterator li = list.listIterator(); - while (li.hasNext()) - { - AbstractTagFrameBody next = ((AbstractID3v2Frame) li.next()).getBody(); - if (next instanceof AbstractFrameBodyPairs) - { - for (Pair entry : ((AbstractFrameBodyPairs) next).getPairing().getMapping()) - { - if(!StandardIPLSKey.isKey(entry.getKey())) - { - if (!entry.getValue().isEmpty()) - { - if (!entry.getKey().isEmpty()) - { - values.add(entry.getPairValue()); - } - else - { - values.add(entry.getValue()); - } - } - } - } - } - } - } - //Simple 1 to 1 mapping - else - { - 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; - } - - /** - * 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, url.getBytes(StandardCharsets.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, url.getBytes(StandardCharsets.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; - } - - - /** - * Some frames are used to store a number/total value, we have to consider both values when requested to delete a - * key relating to one of them - * - * @param formatKey - * @param numberFieldKey - * @param totalFieldKey - * @param deleteNumberFieldKey - */ - private void deleteNumberTotalFrame(FrameAndSubId formatKey, FieldKey numberFieldKey, FieldKey totalFieldKey, boolean deleteNumberFieldKey) - { - if (deleteNumberFieldKey) - { - String total = this.getFirst(totalFieldKey); - if (total.length() == 0) - { - doDeleteTagField(formatKey); - return; - } - else - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) this.getFrame(formatKey.getFrameId()); - AbstractFrameBodyNumberTotal frameBody = (AbstractFrameBodyNumberTotal) frame.getBody(); - frameBody.setNumber(0); - return; - } - } - else - { - String number = this.getFirst(numberFieldKey); - if (number.length() == 0) - { - doDeleteTagField(formatKey); - return; - } - else - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) this.getFrame(formatKey.getFrameId()); - AbstractFrameBodyNumberTotal frameBody = (AbstractFrameBodyNumberTotal) frame.getBody(); - frameBody.setTotal(0); - return; - } - } - } - /** - * Delete fields with this generic key - * - * If generic key maps to multiple frames then do special processing here rather doDeleteField() - * - * @param fieldKey - */ - public void deleteField(FieldKey fieldKey) throws KeyNotFoundException - { - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(fieldKey); - if (fieldKey == null) - { - throw new KeyNotFoundException(); - } - - switch(fieldKey) - { - case TRACK: - deleteNumberTotalFrame(formatKey, FieldKey.TRACK, FieldKey.TRACK_TOTAL, true); - break; - case TRACK_TOTAL: - deleteNumberTotalFrame(formatKey, FieldKey.TRACK, FieldKey.TRACK_TOTAL, false); - break; - case DISC_NO: - deleteNumberTotalFrame(formatKey, FieldKey.DISC_NO, FieldKey.DISC_TOTAL, true); - break; - case DISC_TOTAL: - deleteNumberTotalFrame(formatKey, FieldKey.DISC_NO, FieldKey.DISC_TOTAL, false); - break; - case MOVEMENT_NO: - deleteNumberTotalFrame(formatKey, FieldKey.MOVEMENT_NO, FieldKey.MOVEMENT_TOTAL, true); - break; - case MOVEMENT_TOTAL: - deleteNumberTotalFrame(formatKey, FieldKey.MOVEMENT_NO, FieldKey.MOVEMENT_TOTAL, false); - break; - default: - doDeleteTagField(formatKey); - } - - } - - /** - * Internal delete method, for deleting/modifying an individual ID3 frame - * - * @param formatKey - * @throws KeyNotFoundException - */ - protected void doDeleteTagField(FrameAndSubId formatKey) throws KeyNotFoundException - { - if (formatKey.getSubId() != null) - { - //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()); - } - } - } - else if ((formatKey.getGenericKey()!=null) && - ((formatKey.getGenericKey() == FieldKey.PERFORMER) || (formatKey.getGenericKey() == FieldKey.INVOLVED_PERSON)) - ) - { - List list = getFields(formatKey.getFrameId()); - ListIterator li = list.listIterator(); - while (li.hasNext()) - { - AbstractTagFrameBody next = ((AbstractID3v2Frame) li.next()).getBody(); - if (next instanceof AbstractFrameBodyPairs) - { - PairedTextEncodedStringNullTerminated.ValuePairs pairs = ((AbstractFrameBodyPairs) next).getPairing(); - ListIterator pairIterator = pairs.getMapping().listIterator(); - while (pairIterator.hasNext()) - { - Pair nextPair = pairIterator.next(); - if(!StandardIPLSKey.isKey(nextPair.getKey())) - { - pairIterator.remove(); - } - } - - if (pairs.getMapping().size() == 0) - { - removeFrame(formatKey.getFrameId()); - } - } - } - } - //Simple 1 to 1 mapping - else if (formatKey.getSubId() == null) - { - removeFrame(formatKey.getFrameId()); - } - } - - 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(); - - 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 if (next instanceof FrameBodyUnsupported) - { - return list; - } - else - { - throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass()); - } - } - return filteredList; - } - else if(ID3NumberTotalFields.isNumber(genericKey)) - { - for (TagField tagfield : list) - { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof AbstractFrameBodyNumberTotal) - { - if (((AbstractFrameBodyNumberTotal) next).getNumber() != null) - { - filteredList.add(tagfield); - } - } - } - return filteredList; - } - else if(ID3NumberTotalFields.isTotal(genericKey)) - { - for (TagField tagfield : list) - { - AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody(); - if (next instanceof AbstractFrameBodyNumberTotal) - { - if (((AbstractFrameBodyNumberTotal) next).getTotal() != null) - { - filteredList.add(tagfield); - } - } - } - return filteredList; - } - else - { - return list; - } - } - - /** - * 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 FieldKey genericKey; - private String frameId; - private String subId; - - public FrameAndSubId(FieldKey genericKey, String frameId, String subId) - { - this.genericKey = genericKey; - this.frameId = frameId; - this.subId = subId; - } - - public FieldKey getGenericKey() - { - return genericKey; - } - - public String getFrameId() - { - return frameId; - } - - public String getSubId() - { - return subId; - } - - } - - 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(); - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - if (value) - { - return createField(FieldKey.IS_COMPILATION, "1"); - } - else - { - return createField(FieldKey.IS_COMPILATION, "0"); - } - } - - public Long getStartLocationInFile() - { - return startLocationInFile; - } - - public void setStartLocationInFile(long startLocationInFile) - { - this.startLocationInFile = startLocationInFile; - } - - public Long getEndLocationInFile() - { - return endLocationInFile; - } - - public void setEndLocationInFile(long endLocationInFile) - { - this.endLocationInFile = endLocationInFile; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTag.java deleted file mode 100644 index 0c3f4430..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTag.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description:This class represents any type of tag in an MP3 file, including ID3 and - * Lyrics and the file name. - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrame.java deleted file mode 100644 index 8f5811c1..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrame.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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); - } - - /** - * 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 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; - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrameBody.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrameBody.java deleted file mode 100644 index 2e790506..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagFrameBody.java +++ /dev/null @@ -1,342 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.datatype.AbstractDataType; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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 -{ - public void createStructure() - { - } - - /** - * 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; - - /** - * List of data types that make up this particular frame body. - */ - protected ArrayList objectList = new ArrayList(); - - /** - * 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); - } - - - /** - * 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); - } - } - - - /** - * - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagItem.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagItem.java deleted file mode 100644 index 168e1dc6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AbstractTagItem.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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("com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AggregatedFrame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AggregatedFrame.java deleted file mode 100644 index 7d6de685..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/AggregatedFrame.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.TagTextField; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -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(); - } - - /** - * Returns the current used charset encoding. - * - * @return Charset encoding. - */ - public Charset getEncoding() - { - final byte textEncoding = frames.iterator().next().getBody().getTextEncoding(); - return TextEncoding.getInstanceOf().getCharsetForId(textEncoding); - } - - /** - * Sets the content of the field. - * - * @param content fields content. - */ - public void setContent(String content) - { - - } - - /** - * Sets the charset encoding used by the field. - * - * @param encoding charset. - */ - public void setEncoding(Charset 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Compression.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Compression.java deleted file mode 100644 index 3ac741ae..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Compression.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.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("com.mp3.jaudiotagger.tag.id3"); - - /** - * Decompress realFrameSize bytes to decompressedFrameSize bytes and return as ByteBuffer - * - * @param byteBuffer - * @param decompressedFrameSize - * @param realFrameSize - * @return - * @throws com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Frames.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Frames.java deleted file mode 100644 index 40d6c9f7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Frames.java +++ /dev/null @@ -1,290 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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$ - */ -public abstract class ID3Frames extends AbstractStringStringValuePair -{ - /** - * 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(); - - /** - * 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); - } - - - /** - * 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(); - - - 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_INVOLVED_PEOPLE, 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); - - //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_INVOLVED_PEOPLE); - //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_INVOLVED_PEOPLE); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ISRC, ID3v23Frames.FRAME_ID_V3_ISRC); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_ITUNES_GROUPING, ID3v23Frames.FRAME_ID_V3_ITUNES_GROUPING); - 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_MOVEMENT, ID3v23Frames.FRAME_ID_V3_MOVEMENT); - convertv22Tov23.put(ID3v22Frames.FRAME_ID_V2_MOVEMENT_NO, ID3v23Frames.FRAME_ID_V3_MOVEMENT_NO); - 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); - } - - static - { - loadID3v22ID3v23Mapping(); - loadID3v23ID3v24Mapping(); - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3SyncSafeInteger.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3SyncSafeInteger.java deleted file mode 100644 index 08689b56..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3SyncSafeInteger.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.mp3.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 - */ - public 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 - */ - public 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Tags.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Tags.java deleted file mode 100644 index 55b8bec0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Tags.java +++ /dev/null @@ -1,471 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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$ - */ -public class ID3Tags -{ - //Logger - public static Logger logger = Logger.getLogger("com.mp3.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((String)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)) - { - String toParseNumberFrom = str.substring(i, j); - if(!toParseNumberFrom.equals("-")) num = Long.parseLong(toParseNumberFrom); - else throw new TagException("Unable to find integer in string: " + str); - } - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3TextEncodingConversion.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3TextEncodingConversion.java deleted file mode 100644 index f61c5671..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3TextEncodingConversion.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.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("com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Unsynchronization.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Unsynchronization.java deleted file mode 100644 index 792d357e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3Unsynchronization.java +++ /dev/null @@ -1,239 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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("com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v11Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v11Tag.java deleted file mode 100644 index 4473f306..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v11Tag.java +++ /dev/null @@ -1,631 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * This class is for a ID3v1.1 Tag - * - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.id3.framebody.*; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; - -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; - - /** - * Track is held as a single byte in v1.1 - */ - protected byte track = (byte) TRACK_UNDEFINED; - - private static final byte RELEASE = 1; - private static final byte MAJOR_VERSION = 1; - private static final byte REVISION = 0; - - /** - * 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; - } - - /** - * Creates a new ID3v11 datatype. - */ - public ID3v11Tag() - { - - } - - public int getFieldCount() - { - return 7; - } - - 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) - { - Integer genreId = GenreTypes.getInstanceOf().getIdForValue(text); - if(null!= genreId) this.genre = genreId.byteValue(); - else - { - 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, ""); - - } - - /** - * 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; - } - - /** - * 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); - } - } - - /** - * 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(); - } - } - - 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 = new String(dataBuffer, FIELD_TITLE_POS, FIELD_TITLE_LENGTH, StandardCharsets.ISO_8859_1).trim(); - Matcher m = AbstractID3v1Tag.endofStringPattern.matcher(title); - if (m.find()) - { - title = title.substring(0, m.start()); - } - artist = new String(dataBuffer, FIELD_ARTIST_POS, FIELD_ARTIST_LENGTH, StandardCharsets.ISO_8859_1).trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(artist); - if (m.find()) - { - artist = artist.substring(0, m.start()); - } - album = new String(dataBuffer, FIELD_ALBUM_POS, FIELD_ALBUM_LENGTH, StandardCharsets.ISO_8859_1).trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(album); - if (m.find()) - { - album = album.substring(0, m.start()); - } - year = new String(dataBuffer, FIELD_YEAR_POS, FIELD_YEAR_LENGTH, StandardCharsets.ISO_8859_1).trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(year); - if (m.find()) - { - year = year.substring(0, m.start()); - } - comment = new String(dataBuffer, FIELD_COMMENT_POS, FIELD_COMMENT_LENGTH, StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1FieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1FieldKey.java deleted file mode 100644 index 19d9e41b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1FieldKey.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -/** - * Basic ID3v11 Field Names - */ -public enum ID3v1FieldKey -{ - ARTIST, - ALBUM, - GENRE, - TITLE, - YEAR, - TRACK, - COMMENT -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Iterator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Iterator.java deleted file mode 100644 index c557c127..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Iterator.java +++ /dev/null @@ -1,209 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Tag.java deleted file mode 100644 index 23f87119..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1Tag.java +++ /dev/null @@ -1,1101 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; -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 -{ - 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); - } - - //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; - - /** - * - */ - protected String album = ""; - - /** - * - */ - protected String artist = ""; - - /** - * - */ - protected String comment = ""; - - /** - * - */ - protected String title = ""; - - /** - * - */ - protected String year = ""; - - /** - * - */ - protected byte genre = (byte) -1; - - - private static final byte RELEASE = 1; - private static final byte MAJOR_VERSION = 0; - private static final byte REVISION = 0; - - /** - * 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; - } - - /** - * 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, ""); - } - - 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; - } - - /** - * 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 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 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); - } - - /** - * 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 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); - } - - /** - * @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(); - } - } - - /** - * Get Comment - * - * @return comment - */ - public String getFirstComment() - { - return comment; - } - - /** - * 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 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(); - } - } - - /** - * 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 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 year - * - * @param year - */ - public void setYear(String year) - { - this.year = ID3Tags.truncate(year, FIELD_YEAR_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(); - } - } - - 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(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; - } - } - - @Override - public boolean setEncoding(final Charset encoding) - { - return true; - } - - /** - * Create Tag Field using generic key - */ - public TagField createField(FieldKey genericKey, String... values) - { - String value = values[0]; - 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 Charset getEncoding() - { - return StandardCharsets.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 = new String(dataBuffer, FIELD_TITLE_POS, FIELD_TITLE_LENGTH, StandardCharsets.ISO_8859_1).trim(); - Matcher m = AbstractID3v1Tag.endofStringPattern.matcher(title); - if (m.find()) - { - title = title.substring(0, m.start()); - } - artist = new String(dataBuffer, FIELD_ARTIST_POS, FIELD_ARTIST_LENGTH, StandardCharsets.ISO_8859_1).trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(artist); - if (m.find()) - { - artist = artist.substring(0, m.start()); - } - album = new String(dataBuffer, FIELD_ALBUM_POS, FIELD_ALBUM_LENGTH, StandardCharsets.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 = new String(dataBuffer, FIELD_YEAR_POS, FIELD_YEAR_LENGTH, StandardCharsets.ISO_8859_1).trim(); - m = AbstractID3v1Tag.endofStringPattern.matcher(year); - if (m.find()) - { - year = year.substring(0, m.start()); - } - comment = new String(dataBuffer, FIELD_COMMENT_POS, FIELD_COMMENT_LENGTH, StandardCharsets.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()); - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - throw new UnsupportedOperationException(ErrorMessage.GENERIC_NOT_SUPPORTED.getMsg()); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1TagField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1TagField.java deleted file mode 100644 index 96b64686..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v1TagField.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.TagTextField; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; - -/** - * 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(final byte[] raw) throws UnsupportedEncodingException - { - String field = new String(raw, StandardCharsets.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(final String fieldId, final 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); - } - - @Override - public void copyContent(TagField field) - { - if (field instanceof TagTextField) - { - this.content = ((TagTextField) field).getContent(); - } - } - - @Override - public String getContent() - { - return content; - } - - @Override - public Charset getEncoding() - { - return StandardCharsets.ISO_8859_1; - } - - @Override - public String getId() - { - return this.id; - } - - @Override - public byte[] getRawContent() throws UnsupportedEncodingException - { - byte[] size = new byte[4]; - byte[] idBytes = this.id.getBytes(StandardCharsets.ISO_8859_1); - byte[] contentBytes = this.content.getBytes(StandardCharsets.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; - } - - @Override - public boolean isBinary() - { - return false; - } - - @Override - public void isBinary(boolean b) - { - //Do nothing, always false - } - - @Override - public boolean isCommon() - { - return common; - } - - @Override - public boolean isEmpty() - { - return "".equals(this.content); - } - - @Override - public void setContent(String s) - { - this.content = s; - } - - @Override - public void setEncoding(Charset s) - { - //Do nothing, encoding is always ISO-8859-1 for this tag - } - - @Override - public String toString() - { - return getContent(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22FieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22FieldKey.java deleted file mode 100644 index 5f30f1ad..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22FieldKey.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyTXXX; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyUFID; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyWXXX; -import com.mp3.jaudiotagger.tag.id3.valuepair.StandardIPLSKey; - -/** - * 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 -{ - 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), - 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_ARTISTS(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ALBUM_ARTISTS, Id3FieldType.TEXT), - ALBUM_ARTISTS_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ALBUM_ARTISTS_SORT, 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), - ARRANGER(ID3v22Frames.FRAME_ID_V2_IPLS, StandardIPLSKey.ARRANGER.getKey(), Id3FieldType.TEXT), - ARRANGER_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ARRANGER_SORT, Id3FieldType.TEXT), - ARTIST(ID3v22Frames.FRAME_ID_V2_ARTIST, Id3FieldType.TEXT), - ARTISTS(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS, Id3FieldType.TEXT), - ARTISTS_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS_SORT, 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), - CHOIR(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.CHOIR, Id3FieldType.TEXT), - CHOIR_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.CHOIR_SORT, Id3FieldType.TEXT), - CLASSICAL_CATALOG(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.CLASSICAL_CATALOG, Id3FieldType.TEXT), - CLASSICAL_NICKNAME(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.CLASSICAL_NICKNAME, 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), - CONDUCTOR_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.CONDUCTOR_SORT, Id3FieldType.TEXT), - COPYRIGHT(ID3v22Frames.FRAME_ID_V2_COPYRIGHTINFO,Id3FieldType.TEXT), - COUNTRY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.COUNTRY, 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), - DJMIXER(ID3v22Frames.FRAME_ID_V2_IPLS, StandardIPLSKey.DJMIXER.getKey(), Id3FieldType.TEXT), - ENCODER(ID3v22Frames.FRAME_ID_V2_ENCODEDBY, Id3FieldType.TEXT), - ENGINEER(ID3v22Frames.FRAME_ID_V2_IPLS, StandardIPLSKey.ENGINEER.getKey(), Id3FieldType.TEXT), - ENSEMBLE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ENSEMBLE, Id3FieldType.TEXT), - ENSEMBLE_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ENSEMBLE_SORT, Id3FieldType.TEXT), - FBPM(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.FBPM, Id3FieldType.TEXT), - GENRE(ID3v22Frames.FRAME_ID_V2_GENRE, Id3FieldType.TEXT), - GROUP(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.GROUP, Id3FieldType.TEXT), - GROUPING(ID3v22Frames.FRAME_ID_V2_CONTENT_GROUP_DESC, Id3FieldType.TEXT), - MOOD_INSTRUMENTAL(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_INSTRUMENTAL, Id3FieldType.TEXT), - INVOLVED_PERSON(ID3v22Frames.FRAME_ID_V2_IPLS, Id3FieldType.TEXT), - INSTRUMENT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.INSTRUMENT, Id3FieldType.TEXT), - ISRC(ID3v22Frames.FRAME_ID_V2_ISRC, Id3FieldType.TEXT), - IS_CLASSICAL(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.IS_CLASSICAL, Id3FieldType.TEXT), - IS_COMPILATION(ID3v22Frames.FRAME_ID_V2_IS_COMPILATION, Id3FieldType.TEXT), - IS_SOUNDTRACK(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.IS_SOUNDTRACK, Id3FieldType.TEXT), - ITUNES_GROUPING(ID3v22Frames.FRAME_ID_V2_ITUNES_GROUPING, 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), - MIXER(ID3v22Frames.FRAME_ID_V2_IPLS, StandardIPLSKey.MIXER.getKey(), Id3FieldType.TEXT), - MOOD(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD, Id3FieldType.TEXT), - MOOD_ACOUSTIC(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_ACOUSTIC, Id3FieldType.TEXT), - MOOD_AGGRESSIVE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_AGGRESSIVE, Id3FieldType.TEXT), - MOOD_AROUSAL(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_AROUSAL, Id3FieldType.TEXT), - MOOD_DANCEABILITY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_DANCEABILITY, Id3FieldType.TEXT), - MOOD_ELECTRONIC(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_ELECTRONIC, Id3FieldType.TEXT), - MOOD_HAPPY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_HAPPY, Id3FieldType.TEXT), - MOOD_PARTY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_PARTY, Id3FieldType.TEXT), - MOOD_RELAXED(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_RELAXED, Id3FieldType.TEXT), - MOOD_SAD(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_SAD, Id3FieldType.TEXT), - MOOD_VALENCE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_VALENCE, Id3FieldType.TEXT), - MOVEMENT(ID3v22Frames.FRAME_ID_V2_MOVEMENT, Id3FieldType.TEXT), - MOVEMENT_NO(ID3v22Frames.FRAME_ID_V2_MOVEMENT_NO, Id3FieldType.TEXT), - MOVEMENT_TOTAL(ID3v22Frames.FRAME_ID_V2_MOVEMENT_NO, 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_TRACK_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_RELEASE_TRACKID, 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_COMPOSITION(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_COMPOSITION, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_COMPOSITION_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_COMPOSITION_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORKID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL1_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL2_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL3_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL4_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL5_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL6_ID(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6_ID, 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), - OPUS(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.OPUS, Id3FieldType.TEXT), - ORCHESTRA(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ORCHESTRA, Id3FieldType.TEXT), - ORCHESTRA_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.ORCHESTRA_SORT, 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), - PART(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.PART, Id3FieldType.TEXT), - PART_NUMBER(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.PART_NUMBER, Id3FieldType.TEXT), - PART_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.PART_TYPE, Id3FieldType.TEXT), - PERFORMER(ID3v22Frames.FRAME_ID_V2_IPLS, Id3FieldType.TEXT), - PERFORMER_NAME(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.PERFORMER_NAME, Id3FieldType.TEXT), - PERFORMER_NAME_SORT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.PERFORMER_NAME_SORT, Id3FieldType.TEXT), - PERIOD(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.PERIOD, Id3FieldType.TEXT), - PRODUCER(ID3v22Frames.FRAME_ID_V2_IPLS, StandardIPLSKey.PRODUCER.getKey(), Id3FieldType.TEXT), - QUALITY(ID3v22Frames.FRAME_ID_V2_COMMENT, FrameBodyCOMM.MM_QUALITY,Id3FieldType.TEXT), - RANKING(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.RANKING, 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), - SINGLE_DISC_TRACK_NO(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.SINGLE_DISC_TRACK_NO, 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), - TIMBRE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.TIMBRE, Id3FieldType.TEXT), - TITLE(ID3v22Frames.FRAME_ID_V2_TITLE, Id3FieldType.TEXT), - TITLE_MOVEMENT(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.TITLE_MOVEMENT, Id3FieldType.TEXT), - MUSICBRAINZ_WORK(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK, Id3FieldType.TEXT), - TITLE_SORT(ID3v22Frames.FRAME_ID_V2_TITLE_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - TONALITY(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.TONALITY, 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), - WORK(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.WORK, Id3FieldType.TEXT), - WORK_PART_LEVEL1(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1, Id3FieldType.TEXT), - WORK_PART_LEVEL1_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL2(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2, Id3FieldType.TEXT), - WORK_PART_LEVEL2_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL3(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3, Id3FieldType.TEXT), - WORK_PART_LEVEL3_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL4(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4, Id3FieldType.TEXT), - WORK_PART_LEVEL4_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL5(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5, Id3FieldType.TEXT), - WORK_PART_LEVEL5_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL6(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6, Id3FieldType.TEXT), - WORK_PART_LEVEL6_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, Id3FieldType.TEXT), - WORK_TYPE(ID3v22Frames.FRAME_ID_V2_USER_DEFINED_INFO, FrameBodyTXXX.WORK_TYPE, Id3FieldType.TEXT), - YEAR(ID3v22Frames.FRAME_ID_V2_TYER, 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frame.java deleted file mode 100644 index a8ecce97..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frame.java +++ /dev/null @@ -1,525 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.tag.EmptyFrameException; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.InvalidFrameException; -import com.mp3.jaudiotagger.tag.InvalidFrameIdentifierException; -import com.mp3.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyDeprecated; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyUnsupported; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -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$ - */ -public class ID3v22Frame extends AbstractID3v2Frame -{ - private static Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{2}"); - - 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; - - public ID3v22Frame() - { - - } - - protected int getFrameIdSize() - { - return FRAME_ID_SIZE; - } - - protected int getFrameSizeSize() - { - return FRAME_SIZE_SIZE; - } - - protected int getFrameHeaderSize() - { - return FRAME_HEADER_SIZE; - } - - /** - * Creates a new ID3v22 Frame with given body - * - * @param body New body and frame is based on this - */ - public ID3v22Frame(AbstractID3v2FrameBody body) - { - super(body); - } - - /** - * 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); - - } - - /** - * 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("com.mp3.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"); - } - - 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); - } - } - - /** - * Creates a new ID3v22 Frame from another frame of a different tag version - * - * @param frame to construct the new frame from - * @throws com.mp3.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, and 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 com.mp3.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 - * @deprecated use {@link #ID3v22Frame(ByteBuffer,String)} instead - * @throws com.mp3.jaudiotagger.tag.InvalidFrameException - */ - public ID3v22Frame(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException - { - this(byteBuffer, ""); - } - - /** - * Return size of frame - * - * @return int size of frame - */ - public int getSize() - { - return frameBody.getSize() + getFrameHeaderSize(); - } - - @Override - protected boolean isPadding(byte[] buffer) - { - if( - (buffer[0]=='\0')&& - (buffer[1]=='\0')&& - (buffer[2]=='\0') - ) - { - return true; - } - return false; - } - - /** - * 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 - * - */ - 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(getIdentifier().getBytes(StandardCharsets.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(final Charset encoding) - { - Integer encodingId = TextEncoding.getInstanceOf().getIdForCharset(encoding); - if(encodingId!=null) - { - if(encodingId <2) - { - this.getBody().setTextEncoding(encodingId.byteValue()); - } - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frames.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frames.java deleted file mode 100644 index 7753e972..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Frames.java +++ /dev/null @@ -1,505 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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$ - */ -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_ITUNES_GROUPING = "GP1"; - 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_MOVEMENT = "MVN"; - public static final String FRAME_ID_V2_MOVEMENT_NO = "MVI"; - 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); - - - public static ID3v22Frames getInstanceOf() - { - if (id3v22Frames == null) - { - id3v22Frames = new ID3v22Frames(); - } - return id3v22Frames; - } - - 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_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_ITUNES_GROUPING); - 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_MOVEMENT); - supportedFrames.add(FRAME_ID_V2_MOVEMENT_NO); - 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_ITUNES_GROUPING, "iTunes Grouping"); - 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_MOVEMENT, "Text: Movement"); - idToValue.put(FRAME_ID_V2_MOVEMENT_NO, "Text: Movement No"); - 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.ACOUSTID_FINGERPRINT, ID3v22FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToId3.put(FieldKey.ACOUSTID_ID, ID3v22FieldKey.ACOUSTID_ID); - 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_ARTISTS, ID3v22FieldKey.ALBUM_ARTISTS); - tagFieldToId3.put(FieldKey.ALBUM_ARTISTS_SORT, ID3v22FieldKey.ALBUM_ARTISTS_SORT); - tagFieldToId3.put(FieldKey.ALBUM_SORT, ID3v22FieldKey.ALBUM_SORT); - tagFieldToId3.put(FieldKey.AMAZON_ID, ID3v22FieldKey.AMAZON_ID); - tagFieldToId3.put(FieldKey.ARRANGER, ID3v22FieldKey.ARRANGER); - tagFieldToId3.put(FieldKey.ARRANGER_SORT, ID3v22FieldKey.ARRANGER_SORT); - tagFieldToId3.put(FieldKey.ARTIST, ID3v22FieldKey.ARTIST); - tagFieldToId3.put(FieldKey.ARTISTS, ID3v22FieldKey.ARTISTS); - tagFieldToId3.put(FieldKey.ARTISTS_SORT, ID3v22FieldKey.ARTISTS_SORT); - 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.CHOIR, ID3v22FieldKey.CHOIR); - tagFieldToId3.put(FieldKey.CHOIR_SORT, ID3v22FieldKey.CHOIR_SORT); - tagFieldToId3.put(FieldKey.CLASSICAL_CATALOG, ID3v22FieldKey.CLASSICAL_CATALOG); - tagFieldToId3.put(FieldKey.CLASSICAL_NICKNAME, ID3v22FieldKey.CLASSICAL_NICKNAME); - 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.CONDUCTOR_SORT, ID3v22FieldKey.CONDUCTOR_SORT); - tagFieldToId3.put(FieldKey.COUNTRY, ID3v22FieldKey.COUNTRY); - tagFieldToId3.put(FieldKey.COPYRIGHT, ID3v22FieldKey.COPYRIGHT); - 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.DJMIXER, ID3v22FieldKey.DJMIXER); - tagFieldToId3.put(FieldKey.ENCODER, ID3v22FieldKey.ENCODER); - tagFieldToId3.put(FieldKey.ENGINEER, ID3v22FieldKey.ENGINEER); - tagFieldToId3.put(FieldKey.ENSEMBLE, ID3v22FieldKey.ENSEMBLE); - tagFieldToId3.put(FieldKey.ENSEMBLE_SORT, ID3v22FieldKey.ENSEMBLE_SORT); - tagFieldToId3.put(FieldKey.FBPM, ID3v22FieldKey.FBPM); - tagFieldToId3.put(FieldKey.GENRE, ID3v22FieldKey.GENRE); - tagFieldToId3.put(FieldKey.GROUP, ID3v22FieldKey.GROUP); - tagFieldToId3.put(FieldKey.GROUPING, ID3v22FieldKey.GROUPING); - tagFieldToId3.put(FieldKey.INSTRUMENT, ID3v22FieldKey.INSTRUMENT); - tagFieldToId3.put(FieldKey.INVOLVED_PERSON, ID3v22FieldKey.INVOLVED_PERSON); - tagFieldToId3.put(FieldKey.ISRC, ID3v22FieldKey.ISRC); - tagFieldToId3.put(FieldKey.IS_CLASSICAL, ID3v22FieldKey.IS_CLASSICAL); - tagFieldToId3.put(FieldKey.IS_COMPILATION, ID3v22FieldKey.IS_COMPILATION); - tagFieldToId3.put(FieldKey.IS_SOUNDTRACK, ID3v22FieldKey.IS_SOUNDTRACK); - tagFieldToId3.put(FieldKey.ITUNES_GROUPING, ID3v22FieldKey.ITUNES_GROUPING); - 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.MIXER, ID3v22FieldKey.MIXER); - tagFieldToId3.put(FieldKey.MOOD, ID3v22FieldKey.MOOD); - tagFieldToId3.put(FieldKey.MOOD_ACOUSTIC, ID3v22FieldKey.MOOD_ACOUSTIC); - tagFieldToId3.put(FieldKey.MOOD_AGGRESSIVE, ID3v22FieldKey.MOOD_AGGRESSIVE); - tagFieldToId3.put(FieldKey.MOOD_AROUSAL, ID3v22FieldKey.MOOD_AROUSAL); - tagFieldToId3.put(FieldKey.MOOD_DANCEABILITY, ID3v22FieldKey.MOOD_DANCEABILITY); - tagFieldToId3.put(FieldKey.MOOD_ELECTRONIC, ID3v22FieldKey.MOOD_ELECTRONIC); - tagFieldToId3.put(FieldKey.MOOD_HAPPY, ID3v22FieldKey.MOOD_HAPPY); - tagFieldToId3.put(FieldKey.MOOD_INSTRUMENTAL, ID3v22FieldKey.MOOD_INSTRUMENTAL); - tagFieldToId3.put(FieldKey.MOOD_PARTY, ID3v22FieldKey.MOOD_PARTY); - tagFieldToId3.put(FieldKey.MOOD_RELAXED, ID3v22FieldKey.MOOD_RELAXED); - tagFieldToId3.put(FieldKey.MOOD_SAD, ID3v22FieldKey.MOOD_SAD); - tagFieldToId3.put(FieldKey.MOOD_VALENCE, ID3v22FieldKey.MOOD_VALENCE); - tagFieldToId3.put(FieldKey.MOVEMENT, ID3v22FieldKey.MOVEMENT); - tagFieldToId3.put(FieldKey.MOVEMENT_NO, ID3v22FieldKey.MOVEMENT_NO); - tagFieldToId3.put(FieldKey.MOVEMENT_TOTAL, ID3v22FieldKey.MOVEMENT_TOTAL); - 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_TRACK_ID, ID3v22FieldKey.MUSICBRAINZ_RELEASE_TRACK_ID); - 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, ID3v22FieldKey.MUSICBRAINZ_WORK); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID, ID3v22FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID); - tagFieldToId3.put(FieldKey.MUSICIP_ID, ID3v22FieldKey.MUSICIP_ID); - tagFieldToId3.put(FieldKey.OCCASION, ID3v22FieldKey.OCCASION); - tagFieldToId3.put(FieldKey.OPUS, ID3v22FieldKey.OPUS); - tagFieldToId3.put(FieldKey.ORCHESTRA, ID3v22FieldKey.ORCHESTRA); - tagFieldToId3.put(FieldKey.ORCHESTRA_SORT, ID3v22FieldKey.ORCHESTRA_SORT); - 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.PART, ID3v22FieldKey.PART); - tagFieldToId3.put(FieldKey.PART_NUMBER, ID3v22FieldKey.PART_NUMBER); - tagFieldToId3.put(FieldKey.PART_TYPE, ID3v22FieldKey.PART_TYPE); - tagFieldToId3.put(FieldKey.PERFORMER, ID3v22FieldKey.PERFORMER); - tagFieldToId3.put(FieldKey.PERFORMER_NAME, ID3v22FieldKey.PERFORMER_NAME); - tagFieldToId3.put(FieldKey.PERFORMER_NAME_SORT, ID3v22FieldKey.PERFORMER_NAME_SORT); - tagFieldToId3.put(FieldKey.PERIOD, ID3v22FieldKey.PERIOD); - tagFieldToId3.put(FieldKey.PRODUCER, ID3v22FieldKey.PRODUCER); - tagFieldToId3.put(FieldKey.QUALITY, ID3v22FieldKey.QUALITY); - tagFieldToId3.put(FieldKey.RANKING, ID3v22FieldKey.RANKING); - 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.SINGLE_DISC_TRACK_NO, ID3v22FieldKey.SINGLE_DISC_TRACK_NO); - tagFieldToId3.put(FieldKey.SUBTITLE, ID3v22FieldKey.SUBTITLE); - tagFieldToId3.put(FieldKey.TAGS, ID3v22FieldKey.TAGS); - tagFieldToId3.put(FieldKey.TEMPO, ID3v22FieldKey.TEMPO); - tagFieldToId3.put(FieldKey.TIMBRE, ID3v22FieldKey.TIMBRE); - tagFieldToId3.put(FieldKey.TITLE, ID3v22FieldKey.TITLE); - tagFieldToId3.put(FieldKey.TITLE_MOVEMENT, ID3v22FieldKey.TITLE_MOVEMENT); - tagFieldToId3.put(FieldKey.TITLE_SORT, ID3v22FieldKey.TITLE_SORT); - tagFieldToId3.put(FieldKey.TONALITY, ID3v22FieldKey.TONALITY); - 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.WORK, ID3v22FieldKey.WORK); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION, ID3v22FieldKey.MUSICBRAINZ_WORK_COMPOSITION); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1, ID3v22FieldKey.WORK_PART_LEVEL1); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, ID3v22FieldKey.WORK_PART_LEVEL1_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2, ID3v22FieldKey.WORK_PART_LEVEL2); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, ID3v22FieldKey.WORK_PART_LEVEL2_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3, ID3v22FieldKey.WORK_PART_LEVEL3); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, ID3v22FieldKey.WORK_PART_LEVEL3_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4, ID3v22FieldKey.WORK_PART_LEVEL4); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, ID3v22FieldKey.WORK_PART_LEVEL4_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5, ID3v22FieldKey.WORK_PART_LEVEL5); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, ID3v22FieldKey.WORK_PART_LEVEL5_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6, ID3v22FieldKey.WORK_PART_LEVEL6); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, ID3v22FieldKey.WORK_PART_LEVEL6_TYPE); - tagFieldToId3.put(FieldKey.WORK_TYPE, ID3v22FieldKey.WORK_TYPE); - tagFieldToId3.put(FieldKey.YEAR, ID3v22FieldKey.YEAR); - - - for(Map.Entry next:tagFieldToId3.entrySet()) - { - id3ToTagField.put(next.getValue(), next.getKey()); - } - } - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java deleted file mode 100644 index 604a1c30..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22PreferredFrameOrderComparator.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.mp3.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); - if(frameId1Index==-1) - { - frameId1Index=Integer.MAX_VALUE; - } - int frameId2Index= frameIdsInPreferredOrder.indexOf(frameId2); - - //Because othwerwise returns -1 whihc would be tags in list went to top of list - if(frameId2Index==-1) - { - frameId2Index=Integer.MAX_VALUE; - } - - //To have determinable ordering AND because if returns equal Treese considers as equal - if(frameId1Index==frameId2Index) - { - return frameId1.compareTo(frameId2); - } - return frameId1Index - frameId2Index; - } - - public boolean equals(Object obj) - { - return obj instanceof ID3v22PreferredFrameOrderComparator; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Tag.java deleted file mode 100644 index 8d24297d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v22Tag.java +++ /dev/null @@ -1,908 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.FileConstants; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.framebody.*; -import com.mp3.jaudiotagger.tag.id3.valuepair.ImageFormats; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.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$ - */ -public class ID3v22Tag extends AbstractID3v2Tag -{ - - protected static final String TYPE_COMPRESSION = "compression"; - protected static final String TYPE_UNSYNCHRONISATION = "unsyncronisation"; - - /** - * 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; - - /** - * 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; - - public static final byte RELEASE = 2; - public static final byte MAJOR_VERSION = 2; - public static final byte REVISION = 0; - - /** - * 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; - } - - /** - * Creates a new empty ID3v2_2 tag. - */ - public ID3v22Tag() - { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - } - - /** - * 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; - } - } - - - - /** - * 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, ""); - } - - /** - * @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); - } - - @Override - protected List convertFrame(AbstractID3v2Frame frame) throws InvalidFrameException - { - List frames = new ArrayList(); - if ((frame.getIdentifier().equals(ID3v24Frames.FRAME_ID_YEAR)) && (frame.getBody() instanceof FrameBodyTDRC)) - { - 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()); - frames.add(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()); - frames.add(newFrame); - } - } - else - { - frames.add(new ID3v22Frame(frame)); - } - return frames; - } - - @Override - public void addFrame(AbstractID3v2Frame frame) - { - try - { - if (frame instanceof ID3v22Frame) - { - copyFrameIntoMap(frame.getIdentifier(), frame); - } - else - { - List frames = convertFrame(frame); - for(AbstractID3v2Frame next:frames) - { - copyFrameIntoMap(next.getIdentifier(), next); - } - } - } - 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 long 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); - return sizeIncPadding; - } - - - /** - * {@inheritDoc} - */ - @Override - public void write(WritableByteChannel channel, int currentTagSize) 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); - } - - int padding = 0; - if(currentTagSize > 0) - { - int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) currentTagSize); - padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH); - } - ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length); - - channel.write(headerBuffer); - channel.write(ByteBuffer.wrap(bodyByteBuffer)); - writePadding(channel, padding); - } - - 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 doCreateTagField(new FrameAndSubId(null, id3Key.getFrameId(), id3Key.getSubId()), value); - } - - public TagField createField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if (values == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - String value = values[0]; - if (genericKey == FieldKey.GENRE) - { - if (value == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey); - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTCON framebody = (FrameBodyTCON) frame.getBody(); - framebody.setV23Format(); - framebody.setText(FrameBodyTCON.convertGenericToID3v22Genre(value)); - return frame; - } - else - { - return super.createField(genericKey, values); - } - } - - /** - * Retrieve the first value that exists for this id3v22key - * - * @param id3v22FieldKey - * @return - * @throws com.mp3.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(null, id3v22FieldKey.getFrameId(), id3v22FieldKey.getSubId()); - return super.doGetValueAtIndex(frameAndSubId, 0); - } - } - - /** - * Delete fields with this id3v22FieldKey - * - * @param id3v22FieldKey - * @throws com.mp3.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(ID3v22FieldKey id3v22FieldKey) throws KeyNotFoundException - { - if (id3v22FieldKey == null) - { - throw new KeyNotFoundException(); - } - super.doDeleteTagField(new FrameAndSubId(null, id3v22FieldKey.getFrameId(), id3v22FieldKey.getSubId())); - } - - /** - * Delete fields with this (frame) id - * @param id - */ - public void deleteField(String id) - { - super.doDeleteTagField(new FrameAndSubId(null, 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(genericKey, 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; - } - - /** - * 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 - { - if(genericKey == FieldKey.GENRE) - { - List fields = getFields(genericKey); - List convertedGenres = new ArrayList(); - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - FrameBodyTCON body = (FrameBodyTCON)frame.getBody(); - - for(String next:body.getValues()) - { - convertedGenres.add(FrameBodyTCON.convertID3v22GenreToGeneric(next)); - } - } - return convertedGenres; - } - else - { - return super.getAll(genericKey); - } - } - - @Override - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if(genericKey == FieldKey.GENRE) - { - List fields = getFields(genericKey); - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - FrameBodyTCON body = (FrameBodyTCON)frame.getBody(); - return FrameBodyTCON.convertID3v22GenreToGeneric(body.getValues().get(index)); - } - return ""; - } - else - { - return super.getValue(genericKey, index); - } - } - - protected void loadFrameIntoMap(String frameId, AbstractID3v2Frame next) - { - if (next.getBody() instanceof FrameBodyTCON) - { - ((FrameBodyTCON)next.getBody()).setV23Format(); - } - super.loadFrameIntoMap(frameId, next); - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23FieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23FieldKey.java deleted file mode 100644 index d8216d9e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23FieldKey.java +++ /dev/null @@ -1,243 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyTXXX; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyUFID; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyWXXX; -import com.mp3.jaudiotagger.tag.id3.valuepair.StandardIPLSKey; - -/** - * 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 -{ - - 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), - 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_ARTISTS(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ALBUM_ARTISTS, Id3FieldType.TEXT), - ALBUM_ARTISTS_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ALBUM_ARTISTS_SORT, 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), - ARRANGER(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, StandardIPLSKey.ARRANGER.getKey(), Id3FieldType.TEXT), - ARRANGER_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ARRANGER_SORT, Id3FieldType.TEXT), - ARTIST(ID3v23Frames.FRAME_ID_V3_ARTIST, Id3FieldType.TEXT), - ARTISTS(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS, Id3FieldType.TEXT), - ARTISTS_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS_SORT, 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), - CHOIR(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.CHOIR, Id3FieldType.TEXT), - CHOIR_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.CHOIR_SORT, Id3FieldType.TEXT), - CLASSICAL_CATALOG(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.CLASSICAL_CATALOG, Id3FieldType.TEXT), - CLASSICAL_NICKNAME(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.CLASSICAL_NICKNAME, 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), - CONDUCTOR_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.CONDUCTOR_SORT, Id3FieldType.TEXT), - COPYRIGHT(ID3v23Frames.FRAME_ID_V3_COPYRIGHTINFO, Id3FieldType.TEXT), - COUNTRY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.COUNTRY, 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), - DJMIXER(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, StandardIPLSKey.DJMIXER.getKey(), Id3FieldType.TEXT), - ENCODER(ID3v23Frames.FRAME_ID_V3_ENCODEDBY, Id3FieldType.TEXT), - ENGINEER(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, StandardIPLSKey.ENGINEER.getKey(), Id3FieldType.TEXT), - ENSEMBLE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ENSEMBLE, Id3FieldType.TEXT), - ENSEMBLE_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ENSEMBLE_SORT, Id3FieldType.TEXT), - FBPM(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.FBPM, Id3FieldType.TEXT), - GENRE(ID3v23Frames.FRAME_ID_V3_GENRE, Id3FieldType.TEXT), - GROUP(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.GROUP, Id3FieldType.TEXT), - GROUPING(ID3v23Frames.FRAME_ID_V3_CONTENT_GROUP_DESC, Id3FieldType.TEXT), - INVOLVED_PERSON(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, Id3FieldType.TEXT), - INSTRUMENT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.INSTRUMENT, Id3FieldType.TEXT), - ISRC(ID3v23Frames.FRAME_ID_V3_ISRC, Id3FieldType.TEXT), - IS_CLASSICAL(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.IS_CLASSICAL, Id3FieldType.TEXT), - IS_COMPILATION(ID3v23Frames.FRAME_ID_V3_IS_COMPILATION, Id3FieldType.TEXT), - IS_SOUNDTRACK(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.IS_SOUNDTRACK, Id3FieldType.TEXT), - ITUNES_GROUPING(ID3v23Frames.FRAME_ID_V3_ITUNES_GROUPING, 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), - MIXER(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, StandardIPLSKey.MIXER.getKey(), Id3FieldType.TEXT), - MOOD(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD, Id3FieldType.TEXT), - MOOD_ACOUSTIC(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_ACOUSTIC, Id3FieldType.TEXT), - MOOD_AGGRESSIVE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_AGGRESSIVE, Id3FieldType.TEXT), - MOOD_AROUSAL(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_AROUSAL, Id3FieldType.TEXT), - MOOD_DANCEABILITY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_DANCEABILITY, Id3FieldType.TEXT), - MOOD_ELECTRONIC(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_ELECTRONIC, Id3FieldType.TEXT), - MOOD_HAPPY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_HAPPY, Id3FieldType.TEXT), - MOOD_INSTRUMENTAL(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_INSTRUMENTAL, Id3FieldType.TEXT), - MOOD_PARTY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_PARTY, Id3FieldType.TEXT), - MOOD_RELAXED(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_RELAXED, Id3FieldType.TEXT), - MOOD_SAD(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_SAD, Id3FieldType.TEXT), - MOOD_VALENCE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_VALENCE, Id3FieldType.TEXT), - MOVEMENT(ID3v23Frames.FRAME_ID_V3_MOVEMENT, Id3FieldType.TEXT), - MOVEMENT_NO(ID3v23Frames.FRAME_ID_V3_MOVEMENT_NO, Id3FieldType.TEXT), - MOVEMENT_TOTAL(ID3v23Frames.FRAME_ID_V3_MOVEMENT_NO, 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_TRACK_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_RELEASE_TRACKID, 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_COMPOSITION(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_COMPOSITION, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_COMPOSITION_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_COMPOSITION_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORKID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL1_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL2_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL3_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL4_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL5_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL6_ID(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6_ID, 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), - OPUS(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.OPUS, Id3FieldType.TEXT), - ORCHESTRA(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ORCHESTRA, Id3FieldType.TEXT), - ORCHESTRA_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.ORCHESTRA_SORT, 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), - PART(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.PART, Id3FieldType.TEXT), - PART_NUMBER(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.PART_NUMBER, Id3FieldType.TEXT), - PART_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.PART_TYPE, Id3FieldType.TEXT), - PERFORMER(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, Id3FieldType.TEXT), - PERFORMER_NAME(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.PERFORMER_NAME, Id3FieldType.TEXT), - PERFORMER_NAME_SORT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.PERFORMER_NAME_SORT, Id3FieldType.TEXT), - PERIOD(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.PERIOD, Id3FieldType.TEXT), - PRODUCER(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE, StandardIPLSKey.PRODUCER.getKey(),Id3FieldType.TEXT), - QUALITY(ID3v23Frames.FRAME_ID_V3_COMMENT, FrameBodyCOMM.MM_QUALITY,Id3FieldType.TEXT), - RANKING(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.RANKING, 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), - SINGLE_DISC_TRACK_NO(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.SINGLE_DISC_TRACK_NO, 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), - TIMBRE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.TIMBRE, Id3FieldType.TEXT), - TITLE(ID3v23Frames.FRAME_ID_V3_TITLE, Id3FieldType.TEXT), - TITLE_MOVEMENT(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.TITLE_MOVEMENT, Id3FieldType.TEXT), - MUSICBRAINZ_WORK(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK, Id3FieldType.TEXT), - TITLE_SORT(ID3v23Frames.FRAME_ID_V3_TITLE_SORT_ORDER_ITUNES, Id3FieldType.TEXT), - TONALITY(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.TONALITY, 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), - WORK(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.WORK, Id3FieldType.TEXT), - WORK_PART_LEVEL1(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1, Id3FieldType.TEXT), - WORK_PART_LEVEL1_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL2(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2, Id3FieldType.TEXT), - WORK_PART_LEVEL2_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL3(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3, Id3FieldType.TEXT), - WORK_PART_LEVEL3_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL4(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4, Id3FieldType.TEXT), - WORK_PART_LEVEL4_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL5(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5, Id3FieldType.TEXT), - WORK_PART_LEVEL5_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL6(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6, Id3FieldType.TEXT), - WORK_PART_LEVEL6_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, Id3FieldType.TEXT), - WORK_TYPE(ID3v23Frames.FRAME_ID_V3_USER_DEFINED_INFO, FrameBodyTXXX.WORK_TYPE, Id3FieldType.TEXT), - YEAR(ID3v23Frames.FRAME_ID_V3_TYER, 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frame.java deleted file mode 100644 index f1c48bec..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frame.java +++ /dev/null @@ -1,880 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.FileConstants; -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.EmptyFrameException; -import com.mp3.jaudiotagger.tag.InvalidDataTypeException; -import com.mp3.jaudiotagger.tag.InvalidFrameException; -import com.mp3.jaudiotagger.tag.InvalidFrameIdentifierException; -import com.mp3.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyDeprecated; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyUnsupported; -import com.mp3.jaudiotagger.tag.id3.framebody.ID3v23FrameBody; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Represents an ID3v2.3 frame. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id$ - */ -public class ID3v23Frame extends AbstractID3v2Frame -{ - private static Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{3}"); - - 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; - - /** - * 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; - - protected int getFrameIdSize() - { - return FRAME_ID_SIZE; - } - - protected int getFrameSizeSize() - { - return FRAME_SIZE_SIZE; - } - - protected int getFrameHeaderSize() - { - return FRAME_HEADER_SIZE; - } - - /** - * 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()); - } - - /** - * Partially construct ID3v24 Frame form an IS3v23Frame - * - * Used for Special Cases - * - * @param frame - * @param identifier - * @throws InvalidFrameException - */ - protected ID3v23Frame(ID3v24Frame frame, String identifier) throws InvalidFrameException - { - this.identifier=identifier; - statusFlags = new StatusFlags((ID3v24Frame.StatusFlags) frame.getStatusFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } - - /** - * Creates a new ID3v23Frame based on another frame of a different version. - * - * @param frame - * @throws com.mp3.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"); - } - else if (frame instanceof ID3v22Frame) - { - statusFlags = new StatusFlags(); - encodingFlags = new EncodingFlags(); - } - else 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 com.mp3.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 - * @deprecated use {@link #ID3v23Frame(ByteBuffer,String)} instead - * @throws com.mp3.jaudiotagger.tag.InvalidFrameException - */ - public ID3v23Frame(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException - { - this(byteBuffer, ""); - } - - /** - * 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:"+frameSize+":" + identifier); - throw new InvalidFrameException(identifier + " is invalid frame:"+frameSize); - } - 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:"+frameSize +" larger than size of" + byteBuffer.remaining() + " before mp3 audio:" + identifier); - } - - //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(); - } - - if(((EncodingFlags)encodingFlags).isNonStandardFlags()) - { - //Probably corrupt so treat as a standard frame - logger.severe(getLoggingFilename() + ":InvalidEncodingFlags:" + Hex.asHex(((EncodingFlags)encodingFlags).getFlags())); - } - - if (((EncodingFlags) encodingFlags).isCompression()) - { - if (decompressedFrameSize > (100 * frameSize)) - { - throw new InvalidFrameException(identifier + " is invalid frame, frame size " + frameSize + " cannot be:" + decompressedFrameSize + " when uncompressed"); - } - } - - //Work out the real size of the frameBody data - int realFrameSize = frameSize - extraHeaderBytesCount; - - if(realFrameSize<=0) - { - throw new InvalidFrameException(identifier + " is invalid frame, realframeSize is:" + realFrameSize); - } - - ByteBuffer frameBodyBuffer; - //Read the body data - try - { - if (((EncodingFlags) encodingFlags).isCompression()) - { - frameBodyBuffer = ID3Compression.uncompress(identifier,getLoggingFilename(),byteBuffer, decompressedFrameSize, realFrameSize); - if(((EncodingFlags) encodingFlags).isEncryption()) - { - frameBody = readEncryptedBody(id, frameBodyBuffer, decompressedFrameSize); - } - else - { - frameBody = readBody(id, frameBodyBuffer, decompressedFrameSize); - } - } - else if (((EncodingFlags) encodingFlags).isEncryption()) - { - frameBodyBuffer = byteBuffer.slice(); - frameBodyBuffer.limit(frameSize); - frameBody = readEncryptedBody(identifier, frameBodyBuffer, 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 - * - */ - 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(getIdentifier().getBytes(StandardCharsets.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; - } - - /** - * 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); - } - } - - /** - * 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(final Charset encoding) - { - Integer encodingId = TextEncoding.getInstanceOf().getIdForCharset(encoding); - if(encodingId!=null) - { - if(encodingId <2) - { - this.getBody().setTextEncoding(encodingId.byteValue()); - } - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frames.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frames.java deleted file mode 100644 index 94d57609..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Frames.java +++ /dev/null @@ -1,556 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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$ - */ -public class ID3v23Frames extends ID3Frames -{ - /** - * Define all frames that are valid within ID3v23 - * Frame IDs beginning with T are text frames, and 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_INVOLVED_PEOPLE = "IPLS"; - public static final String FRAME_ID_V3_ISRC = "TSRC"; - public static final String FRAME_ID_V3_ITUNES_GROUPING = "GRP1"; - 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_MOVEMENT = "MVNM"; - public static final String FRAME_ID_V3_MOVEMENT_NO = "MVIN"; - 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); - - public static ID3v23Frames getInstanceOf() - { - if (id3v23Frames == null) - { - id3v23Frames = new ID3v23Frames(); - } - return id3v23Frames; - } - - 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_INVOLVED_PEOPLE); - supportedFrames.add(FRAME_ID_V3_ISRC); - supportedFrames.add(FRAME_ID_V3_ITUNES_GROUPING); - 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_MOVEMENT); - supportedFrames.add(FRAME_ID_V3_MOVEMENT_NO); - 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_INVOLVED_PEOPLE, "Involved people list"); - idToValue.put(FRAME_ID_V3_ISRC, "Text: ISRC (International Standard Recording Code)"); - idToValue.put(FRAME_ID_V3_ITUNES_GROUPING, "Text: iTunes Grouping"); - 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_MOVEMENT, "Text: Movement"); - idToValue.put(FRAME_ID_V3_MOVEMENT_NO, "Text: Movement No"); - 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.ACOUSTID_FINGERPRINT, ID3v23FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToId3.put(FieldKey.ACOUSTID_ID, ID3v23FieldKey.ACOUSTID_ID); - 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_ARTISTS, ID3v23FieldKey.ALBUM_ARTISTS); - tagFieldToId3.put(FieldKey.ALBUM_ARTISTS_SORT, ID3v23FieldKey.ALBUM_ARTISTS_SORT); - tagFieldToId3.put(FieldKey.ALBUM_SORT, ID3v23FieldKey.ALBUM_SORT); - tagFieldToId3.put(FieldKey.AMAZON_ID, ID3v23FieldKey.AMAZON_ID); - tagFieldToId3.put(FieldKey.ARRANGER, ID3v23FieldKey.ARRANGER); - tagFieldToId3.put(FieldKey.ARRANGER_SORT, ID3v23FieldKey.ARRANGER_SORT); - tagFieldToId3.put(FieldKey.ARTIST, ID3v23FieldKey.ARTIST); - tagFieldToId3.put(FieldKey.ARTISTS, ID3v23FieldKey.ARTISTS); - tagFieldToId3.put(FieldKey.ARTISTS_SORT, ID3v23FieldKey.ARTISTS_SORT); - 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.CHOIR, ID3v23FieldKey.CHOIR); - tagFieldToId3.put(FieldKey.CHOIR_SORT, ID3v23FieldKey.CHOIR_SORT); - tagFieldToId3.put(FieldKey.CLASSICAL_CATALOG, ID3v23FieldKey.CLASSICAL_CATALOG); - tagFieldToId3.put(FieldKey.CLASSICAL_NICKNAME, ID3v23FieldKey.CLASSICAL_NICKNAME); - 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.CONDUCTOR_SORT, ID3v23FieldKey.CONDUCTOR_SORT); - tagFieldToId3.put(FieldKey.COPYRIGHT, ID3v23FieldKey.COPYRIGHT); - tagFieldToId3.put(FieldKey.COUNTRY, ID3v23FieldKey.COUNTRY); - 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.DJMIXER, ID3v23FieldKey.DJMIXER); - tagFieldToId3.put(FieldKey.MOOD_ELECTRONIC, ID3v23FieldKey.MOOD_ELECTRONIC); - tagFieldToId3.put(FieldKey.ENCODER, ID3v23FieldKey.ENCODER); - tagFieldToId3.put(FieldKey.ENGINEER, ID3v23FieldKey.ENGINEER); - tagFieldToId3.put(FieldKey.ENSEMBLE, ID3v23FieldKey.ENSEMBLE); - tagFieldToId3.put(FieldKey.ENSEMBLE_SORT, ID3v23FieldKey.ENSEMBLE_SORT); - tagFieldToId3.put(FieldKey.FBPM, ID3v23FieldKey.FBPM); - tagFieldToId3.put(FieldKey.GENRE, ID3v23FieldKey.GENRE); - tagFieldToId3.put(FieldKey.GROUP, ID3v23FieldKey.GROUP); - tagFieldToId3.put(FieldKey.GROUPING, ID3v23FieldKey.GROUPING); - tagFieldToId3.put(FieldKey.INSTRUMENT, ID3v23FieldKey.INSTRUMENT); - tagFieldToId3.put(FieldKey.INVOLVED_PERSON, ID3v23FieldKey.INVOLVED_PERSON); - tagFieldToId3.put(FieldKey.ISRC, ID3v23FieldKey.ISRC); - tagFieldToId3.put(FieldKey.IS_CLASSICAL, ID3v23FieldKey.IS_CLASSICAL); - tagFieldToId3.put(FieldKey.IS_COMPILATION, ID3v23FieldKey.IS_COMPILATION); - tagFieldToId3.put(FieldKey.IS_SOUNDTRACK, ID3v23FieldKey.IS_SOUNDTRACK); - tagFieldToId3.put(FieldKey.ITUNES_GROUPING, ID3v23FieldKey.ITUNES_GROUPING); - 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.MIXER, ID3v23FieldKey.MIXER); - tagFieldToId3.put(FieldKey.MOOD,ID3v23FieldKey.MOOD); - tagFieldToId3.put(FieldKey.MOOD_ACOUSTIC, ID3v23FieldKey.MOOD_ACOUSTIC); - tagFieldToId3.put(FieldKey.MOOD_AGGRESSIVE, ID3v23FieldKey.MOOD_AGGRESSIVE); - tagFieldToId3.put(FieldKey.MOOD_AROUSAL, ID3v23FieldKey.MOOD_AROUSAL); - tagFieldToId3.put(FieldKey.MOOD_DANCEABILITY, ID3v23FieldKey.MOOD_DANCEABILITY); - tagFieldToId3.put(FieldKey.MOOD_HAPPY, ID3v23FieldKey.MOOD_HAPPY); - tagFieldToId3.put(FieldKey.MOOD_INSTRUMENTAL, ID3v23FieldKey.MOOD_INSTRUMENTAL); - tagFieldToId3.put(FieldKey.MOOD_PARTY, ID3v23FieldKey.MOOD_PARTY); - tagFieldToId3.put(FieldKey.MOOD_RELAXED, ID3v23FieldKey.MOOD_RELAXED); - tagFieldToId3.put(FieldKey.MOOD_SAD, ID3v23FieldKey.MOOD_SAD); - tagFieldToId3.put(FieldKey.MOOD_VALENCE, ID3v23FieldKey.MOOD_VALENCE); - tagFieldToId3.put(FieldKey.MOVEMENT, ID3v23FieldKey.MOVEMENT); - tagFieldToId3.put(FieldKey.MOVEMENT_NO, ID3v23FieldKey.MOVEMENT_NO); - tagFieldToId3.put(FieldKey.MOVEMENT_TOTAL, ID3v23FieldKey.MOVEMENT_TOTAL); - 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_TRACK_ID, ID3v23FieldKey.MUSICBRAINZ_RELEASE_TRACK_ID); - 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, ID3v23FieldKey.MUSICBRAINZ_WORK); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID, ID3v23FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID); - tagFieldToId3.put(FieldKey.MUSICIP_ID, ID3v23FieldKey.MUSICIP_ID); - tagFieldToId3.put(FieldKey.OCCASION, ID3v23FieldKey.OCCASION); - tagFieldToId3.put(FieldKey.OPUS, ID3v23FieldKey.OPUS); - tagFieldToId3.put(FieldKey.ORCHESTRA, ID3v23FieldKey.ORCHESTRA); - tagFieldToId3.put(FieldKey.ORCHESTRA_SORT, ID3v23FieldKey.ORCHESTRA_SORT); - 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.PART, ID3v23FieldKey.PART); - tagFieldToId3.put(FieldKey.PART_NUMBER, ID3v23FieldKey.PART_NUMBER); - tagFieldToId3.put(FieldKey.PART_TYPE, ID3v23FieldKey.PART_TYPE); - tagFieldToId3.put(FieldKey.PERFORMER, ID3v23FieldKey.PERFORMER); - tagFieldToId3.put(FieldKey.PERFORMER_NAME, ID3v23FieldKey.PERFORMER_NAME); - tagFieldToId3.put(FieldKey.PERFORMER_NAME_SORT, ID3v23FieldKey.PERFORMER_NAME_SORT); - - tagFieldToId3.put(FieldKey.PERIOD, ID3v23FieldKey.PERIOD); - tagFieldToId3.put(FieldKey.PRODUCER, ID3v23FieldKey.PRODUCER); - tagFieldToId3.put(FieldKey.QUALITY, ID3v23FieldKey.QUALITY); - tagFieldToId3.put(FieldKey.RANKING, ID3v23FieldKey.RANKING); - 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.SINGLE_DISC_TRACK_NO, ID3v23FieldKey.SINGLE_DISC_TRACK_NO); - tagFieldToId3.put(FieldKey.SUBTITLE, ID3v23FieldKey.SUBTITLE); - tagFieldToId3.put(FieldKey.TAGS, ID3v23FieldKey.TAGS); - tagFieldToId3.put(FieldKey.TEMPO, ID3v23FieldKey.TEMPO); - tagFieldToId3.put(FieldKey.TIMBRE, ID3v23FieldKey.TIMBRE); - tagFieldToId3.put(FieldKey.TITLE, ID3v23FieldKey.TITLE); - tagFieldToId3.put(FieldKey.TITLE_MOVEMENT, ID3v23FieldKey.TITLE_MOVEMENT); - tagFieldToId3.put(FieldKey.TITLE_SORT, ID3v23FieldKey.TITLE_SORT); - tagFieldToId3.put(FieldKey.TONALITY, ID3v23FieldKey.TONALITY); - 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.WORK, ID3v23FieldKey.WORK); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION, ID3v23FieldKey.MUSICBRAINZ_WORK_COMPOSITION); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1, ID3v23FieldKey.WORK_PART_LEVEL1); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, ID3v23FieldKey.WORK_PART_LEVEL1_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2, ID3v23FieldKey.WORK_PART_LEVEL2); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, ID3v23FieldKey.WORK_PART_LEVEL2_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3, ID3v23FieldKey.WORK_PART_LEVEL3); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, ID3v23FieldKey.WORK_PART_LEVEL3_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4, ID3v23FieldKey.WORK_PART_LEVEL4); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, ID3v23FieldKey.WORK_PART_LEVEL4_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5, ID3v23FieldKey.WORK_PART_LEVEL5); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, ID3v23FieldKey.WORK_PART_LEVEL5_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6, ID3v23FieldKey.WORK_PART_LEVEL6); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, ID3v23FieldKey.WORK_PART_LEVEL6_TYPE); - tagFieldToId3.put(FieldKey.WORK_TYPE, ID3v23FieldKey.WORK_TYPE); - tagFieldToId3.put(FieldKey.YEAR, ID3v23FieldKey.YEAR); - - for(Map.Entry next:tagFieldToId3.entrySet()) - { - id3ToTagField.put(next.getValue(), next.getKey()); - } - } - - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java deleted file mode 100644 index 40447062..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23PreferredFrameOrderComparator.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.mp3.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_INVOLVED_PEOPLE); - 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); - if(frameId1Index==-1) - { - frameId1Index=Integer.MAX_VALUE; - } - int frameId2Index= frameIdsInPreferredOrder.indexOf(frameId2); - - //Because othwerwise returns -1 whihc would be tags in list went to top of list - if(frameId2Index==-1) - { - frameId2Index=Integer.MAX_VALUE; - } - - //To have determinable ordering AND because if returns equal Treese considers as equal - if(frameId1Index==frameId2Index) - { - return frameId1.compareTo(frameId2); - } - return frameId1Index - frameId2Index; - } - - public boolean equals(Object obj) - { - return obj instanceof ID3v23PreferredFrameOrderComparator; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Tag.java deleted file mode 100644 index 8186d27c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v23Tag.java +++ /dev/null @@ -1,1372 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.FileConstants; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.id3.framebody.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.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$ - */ -public class ID3v23Tag extends AbstractID3v2Tag -{ - - 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; - - /** - * 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; - - /** - * CRC Checksum calculated - */ - protected boolean crcDataFlag = false; - - /** - * Experiemntal tag - */ - protected boolean experimental = false; - - /** - * Contains extended header - */ - protected boolean extended = false; - - /** - * Crcdata Checksum in extended header - */ - private int crc32; - - /** - * Tag padding - */ - private int paddingSize = 0; - - /** - * All frames in the tag uses unsynchronisation - */ - protected boolean unsynchronization = false; - - /** - * The tag is compressed - */ - protected boolean compression = false; - - - public static final byte RELEASE = 2; - public static final byte MAJOR_VERSION = 3; - public static final byte REVISION = 0; - - - /** - * 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; - } - - /** - * Creates a new empty ID3v2_3 datatype. - */ - public ID3v23Tag() - { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - } - - /** - * 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; - } - } - - /** - * Override to merge TIPL/TMCL into single IPLS frame - * - * @param newFrame - * @param existingFrame - */ - @Override - protected void processDuplicateFrame(AbstractID3v2Frame newFrame, AbstractID3v2Frame existingFrame) - { - //We dont add this new frame we just add the contents to existing frame - if(newFrame.getIdentifier().equals(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE)) - { - PairedTextEncodedStringNullTerminated.ValuePairs oldVps = ((FrameBodyIPLS)(existingFrame).getBody()).getPairing(); - PairedTextEncodedStringNullTerminated.ValuePairs newVps = ((FrameBodyIPLS)newFrame.getBody()).getPairing(); - for(Pair next:newVps.getMapping()) - { - oldVps.add(next); - } - } - else - { - List list = new ArrayList(); - list.add(existingFrame); - list.add(newFrame); - frameMap.put(newFrame.getIdentifier(), list); - } - } - - @Override - public void addFrame(AbstractID3v2Frame frame) - { - try - { - if (frame instanceof ID3v23Frame) - { - copyFrameIntoMap(frame.getIdentifier(), frame); - } - else - { - List frames = convertFrame(frame); - for(AbstractID3v2Frame next:frames) - { - copyFrameIntoMap(next.getIdentifier(), next); - } - } - } - catch (InvalidFrameException ife) - { - logger.log(Level.SEVERE, "Unable to convert frame:" + frame.getIdentifier()); - } - } - - @Override - protected List convertFrame(AbstractID3v2Frame frame) throws InvalidFrameException - { - List frames = new ArrayList(); - if ((frame.getIdentifier().equals(ID3v24Frames.FRAME_ID_YEAR)) && (frame.getBody() instanceof FrameBodyTDRC)) - { - //TODO will overwrite any existing TYER or TIME frame, do we ever want multiples of these - FrameBodyTDRC tmpBody = (FrameBodyTDRC) frame.getBody(); - tmpBody.findMatchingMaskAndExtractV3Values(); - ID3v23Frame newFrame; - if (!tmpBody.getYear().equals("")) - { - newFrame = new ID3v23Frame(ID3v23Frames.FRAME_ID_V3_TYER); - ((FrameBodyTYER) newFrame.getBody()).setText(tmpBody.getYear()); - frames.add(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()); - frames.add(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()); - frames.add(newFrame); - } - } - //If at later stage we have multiple IPLS frames we have to merge - else if ((frame.getIdentifier().equals(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE)) && (frame.getBody() instanceof FrameBodyTIPL)) - { - List pairs= ((FrameBodyTIPL)frame.getBody()).getPairing().getMapping(); - AbstractID3v2Frame ipls = new ID3v23Frame((ID3v24Frame)frame,ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE); - FrameBodyIPLS iplsBody = new FrameBodyIPLS(frame.getBody().getTextEncoding(),pairs); - ipls.setBody(iplsBody); - frames.add(ipls); - } - else if ((frame.getIdentifier().equals(ID3v24Frames.FRAME_ID_MUSICIAN_CREDITS)) && (frame.getBody() instanceof FrameBodyTMCL)) - { - List pairs= ((FrameBodyTMCL)frame.getBody()).getPairing().getMapping(); - AbstractID3v2Frame ipls = new ID3v23Frame((ID3v24Frame)frame,ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE); - FrameBodyIPLS iplsBody = new FrameBodyIPLS(frame.getBody().getTextEncoding(),pairs); - ipls.setBody(iplsBody); - frames.add(ipls); - } - else - { - frames.add(new ID3v23Frame(frame)); - } - return frames; - } - - /** - * 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, ""); - } - - /** - * @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 - int posBeforeRead = byteBuffer.position(); - logger.config(getLoggingFilename() + ":Looking for next frame at:" + posBeforeRead); - next = new ID3v23Frame(byteBuffer, getLoggingFilename()); - id = next.getIdentifier(); - logger.config(getLoggingFilename() + ":Found "+ id+ " at frame at:" + posBeforeRead); - 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 long 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); - return sizeIncPadding; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(WritableByteChannel channel, int currentTagSize) 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); - } - - int padding = 0; - if(currentTagSize > 0) - { - int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) currentTagSize); - padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH); - logger.config(getLoggingFilename() + ":Padding:"+padding); - } - ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length); - - channel.write(headerBuffer); - channel.write(ByteBuffer.wrap(bodyByteBuffer)); - writePadding(channel, padding); - } - - - /** - * 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(null, id3Key.getFrameId(), id3Key.getSubId()), value); - } - - /** - * Retrieve the first value that exists for this id3v23key - * - * @param id3v23FieldKey - * @return - * @throws com.mp3.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(null, id3v23FieldKey.getFrameId(), id3v23FieldKey.getSubId()); - return super.doGetValueAtIndex(frameAndSubId, 0); - } - } - - /** - * Delete fields with this id3v23FieldKey - * - * @param id3v23FieldKey - * @throws com.mp3.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(ID3v23FieldKey id3v23FieldKey) throws KeyNotFoundException - { - if (id3v23FieldKey == null) - { - throw new KeyNotFoundException(); - } - super.doDeleteTagField(new FrameAndSubId(null, id3v23FieldKey.getFrameId(), id3v23FieldKey.getSubId())); - } - - /** - * Delete fields with this (frame) id - * @param id - */ - public void deleteField(String id) - { - super.doDeleteTagField(new FrameAndSubId(null, 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(genericKey, 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 - * @see PictureTypes - * @return - */ - 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 values to store - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public TagField createField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - - String value = values[0]; - if (genericKey == FieldKey.GENRE) - { - if (value == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey); - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTCON framebody = (FrameBodyTCON) frame.getBody(); - framebody.setV23Format(); - - if(TagOptionSingleton.getInstance().isWriteMp3GenresAsText()) - { - framebody.setText(value); - } - else - { - framebody.setText(FrameBodyTCON.convertGenericToID3v23Genre(value)); - } - return frame; - } - else if (genericKey == FieldKey.YEAR) - { - if(value.length()==1) - { - AbstractID3v2Frame tyer = createFrame(ID3v23Frames.FRAME_ID_V3_TYER); - ((AbstractFrameBodyTextInfo) tyer.getBody()).setText("000" + value); - return tyer; - } - else if(value.length()==2) - { - AbstractID3v2Frame tyer = createFrame(ID3v23Frames.FRAME_ID_V3_TYER); - ((AbstractFrameBodyTextInfo) tyer.getBody()).setText("00" + value); - return tyer; - } - else if(value.length()==3) - { - AbstractID3v2Frame tyer = createFrame(ID3v23Frames.FRAME_ID_V3_TYER); - ((AbstractFrameBodyTextInfo) tyer.getBody()).setText("0" + value); - return tyer; - } - else if(value.length()==4) - { - AbstractID3v2Frame tyer = createFrame(ID3v23Frames.FRAME_ID_V3_TYER); - ((AbstractFrameBodyTextInfo) tyer.getBody()).setText(value); - 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; - } - } - else - { - return super.createField(genericKey, values); - } - } - - /** - * - * @param genericKey - * @param index - * @return - * @throws KeyNotFoundException - */ - @Override - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if(genericKey == FieldKey.YEAR) - { - AggregatedFrame af = (AggregatedFrame)getFrame(TyerTdatAggregatedFrame.ID_TYER_TDAT); - if(af!=null) - { - return af.getContent(); - } - else - { - return super.getValue(genericKey, index); - } - } - else if(genericKey == FieldKey.GENRE) - { - List fields = getFields(genericKey); - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - FrameBodyTCON body = (FrameBodyTCON)frame.getBody(); - return FrameBodyTCON.convertID3v23GenreToGeneric(body.getValues().get(index)); - } - return ""; - } - else - { - return super.getValue(genericKey, index); - } - } - - protected void loadFrameIntoMap(String frameId, AbstractID3v2Frame next) - { - if (next.getBody() instanceof FrameBodyTCON) - { - ((FrameBodyTCON)next.getBody()).setV23Format(); - } - super.loadFrameIntoMap(frameId, next); - } - - 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(frameId.equals(ID3v23Frames.FRAME_ID_V3_TDAT)) - { - if(frame.getContent().length()==0) - { - //Discard not useful to complicate by trying to map it - logger.warning("TDAT is empty so just ignoring"); - 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); - } - } - - } - - /** - * Overridden because GENRE can need converting of data to ID3v23 format and - * YEAR key is specially processed by getFields() for ID3 - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - @Override - public List getAll(FieldKey genericKey) throws KeyNotFoundException - { - if(genericKey == FieldKey.GENRE) - { - List fields = getFields(genericKey); - List convertedGenres = new ArrayList(); - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - FrameBodyTCON body = (FrameBodyTCON)frame.getBody(); - - for(String next:body.getValues()) - { - convertedGenres.add(FrameBodyTCON.convertID3v23GenreToGeneric(next)); - } - } - return convertedGenres; - } - else if(genericKey == FieldKey.YEAR) - { - List fields = getFields(genericKey); - List results = new ArrayList(); - if (fields != null && fields.size() > 0) - { - for(TagField next:fields) - { - if(next instanceof TagTextField) - { - results.add(((TagTextField)next).getContent()); - } - } - } - return results; - } - else - { - return super.getAll(genericKey); - } - } - - /** - * Overridden because YEAR key can be served by TDAT, TYER or special aggreagted frame - * - * @param genericKey - * @return - * @throws KeyNotFoundException - */ - @Override - public List getFields(FieldKey genericKey) throws KeyNotFoundException - { - if (genericKey == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - - if(genericKey == FieldKey.YEAR) - { - AggregatedFrame af = (AggregatedFrame)getFrame(TyerTdatAggregatedFrame.ID_TYER_TDAT); - if(af!=null) - { - List list = new ArrayList(); - list.add(af); - return list; - } - else - { - return super.getFields(genericKey); - } - } - else - { - return super.getFields(genericKey); - } - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24FieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24FieldKey.java deleted file mode 100644 index dfd3c67c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24FieldKey.java +++ /dev/null @@ -1,243 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyTXXX; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyUFID; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyWXXX; -import com.mp3.jaudiotagger.tag.id3.valuepair.StandardIPLSKey; - -/** - * 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 -{ - 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), - 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_ARTISTS(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ALBUM_ARTISTS, Id3FieldType.TEXT), - ALBUM_ARTISTS_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ALBUM_ARTISTS_SORT, 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), - ARRANGER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, StandardIPLSKey.ARRANGER.getKey(), Id3FieldType.TEXT), - ARRANGER_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ARRANGER_SORT, Id3FieldType.TEXT), - ARTIST(ID3v24Frames.FRAME_ID_ARTIST, Id3FieldType.TEXT), - ARTISTS(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS, Id3FieldType.TEXT), - ARTISTS_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ARTISTS_SORT, 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), - CHOIR(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.CHOIR, Id3FieldType.TEXT), - CHOIR_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.CHOIR_SORT, Id3FieldType.TEXT), - CLASSICAL_CATALOG(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.CLASSICAL_CATALOG, Id3FieldType.TEXT), - CLASSICAL_NICKNAME(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.CLASSICAL_NICKNAME, 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), - CONDUCTOR_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.CONDUCTOR_SORT, Id3FieldType.TEXT), - COPYRIGHT(ID3v24Frames.FRAME_ID_COPYRIGHTINFO, Id3FieldType.TEXT), - COUNTRY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.COUNTRY, 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), - DJMIXER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, StandardIPLSKey.DJMIXER.getKey(), Id3FieldType.TEXT), - ENCODER(ID3v24Frames.FRAME_ID_ENCODEDBY, Id3FieldType.TEXT), - ENGINEER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, StandardIPLSKey.ENGINEER.getKey(), Id3FieldType.TEXT), - ENSEMBLE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ENSEMBLE, Id3FieldType.TEXT), - ENSEMBLE_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ENSEMBLE_SORT, Id3FieldType.TEXT), - FBPM(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.FBPM, Id3FieldType.TEXT), - GENRE(ID3v24Frames.FRAME_ID_GENRE, Id3FieldType.TEXT), - GROUP(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.GROUP, Id3FieldType.TEXT), - GROUPING(ID3v24Frames.FRAME_ID_CONTENT_GROUP_DESC, Id3FieldType.TEXT), - INVOLVED_PERSON(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, Id3FieldType.TEXT), - INSTRUMENT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.INSTRUMENT, Id3FieldType.TEXT), - ISRC(ID3v24Frames.FRAME_ID_ISRC, Id3FieldType.TEXT), - IS_CLASSICAL(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.IS_CLASSICAL, Id3FieldType.TEXT), - IS_COMPILATION(ID3v24Frames.FRAME_ID_IS_COMPILATION, Id3FieldType.TEXT), - IS_SOUNDTRACK(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.IS_SOUNDTRACK, Id3FieldType.TEXT), - ITUNES_GROUPING(ID3v24Frames.FRAME_ID_ITUNES_GROUPING, 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), - MIXER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, StandardIPLSKey.MIXER.getKey(), Id3FieldType.TEXT), - MOOD(ID3v24Frames.FRAME_ID_MOOD, Id3FieldType.TEXT), - MOOD_ACOUSTIC(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_ACOUSTIC, Id3FieldType.TEXT), - MOOD_AGGRESSIVE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_AGGRESSIVE, Id3FieldType.TEXT), - MOOD_AROUSAL(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_AROUSAL, Id3FieldType.TEXT), - MOOD_DANCEABILITY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_DANCEABILITY, Id3FieldType.TEXT), - MOOD_ELECTRONIC(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_ELECTRONIC, Id3FieldType.TEXT), - MOOD_HAPPY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_HAPPY, Id3FieldType.TEXT), - MOOD_INSTRUMENTAL(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_INSTRUMENTAL, Id3FieldType.TEXT), - MOOD_PARTY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_PARTY, Id3FieldType.TEXT), - MOOD_RELAXED(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_RELAXED, Id3FieldType.TEXT), - MOOD_SAD(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_SAD, Id3FieldType.TEXT), - MOOD_VALENCE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MOOD_VALENCE, Id3FieldType.TEXT), - MOVEMENT(ID3v24Frames.FRAME_ID_MOVEMENT, Id3FieldType.TEXT), - MOVEMENT_NO(ID3v24Frames.FRAME_ID_MOVEMENT_NO, Id3FieldType.TEXT), - MOVEMENT_TOTAL(ID3v24Frames.FRAME_ID_MOVEMENT_NO, 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_TRACK_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_RELEASE_TRACKID, 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_COMPOSITION_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_COMPOSITION_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORKID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL1_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL2_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL3_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL4_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL5_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5_ID, Id3FieldType.TEXT), - MUSICBRAINZ_WORK_PART_LEVEL6_ID(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6_ID, 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), - OPUS(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.OPUS, Id3FieldType.TEXT), - ORCHESTRA(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ORCHESTRA, Id3FieldType.TEXT), - ORCHESTRA_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.ORCHESTRA_SORT, 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), - PART(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.PART, Id3FieldType.TEXT), - PART_NUMBER(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.PART_NUMBER, Id3FieldType.TEXT), - PART_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.PART_TYPE, Id3FieldType.TEXT), - PERFORMER(ID3v24Frames.FRAME_ID_MUSICIAN_CREDITS, Id3FieldType.TEXT), - PERFORMER_NAME(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.PERFORMER_NAME, Id3FieldType.TEXT), - PERFORMER_NAME_SORT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.PERFORMER_NAME_SORT, Id3FieldType.TEXT), - PERIOD(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.PERIOD, Id3FieldType.TEXT), - PRODUCER(ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE, StandardIPLSKey.PRODUCER.getKey(), Id3FieldType.TEXT), - QUALITY(ID3v24Frames.FRAME_ID_COMMENT, FrameBodyCOMM.MM_QUALITY,Id3FieldType.TEXT), - RANKING(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.RANKING, 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), - SINGLE_DISC_TRACK_NO(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.SINGLE_DISC_TRACK_NO, 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), - TIMBRE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.TIMBRE, Id3FieldType.TEXT), - TITLE(ID3v24Frames.FRAME_ID_TITLE, Id3FieldType.TEXT), - TITLE_MOVEMENT(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.TITLE_MOVEMENT, Id3FieldType.TEXT), - MUSICBRAINZ_WORK(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK, Id3FieldType.TEXT), - TITLE_SORT(ID3v24Frames.FRAME_ID_TITLE_SORT_ORDER, Id3FieldType.TEXT), - TONALITY(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.TONALITY, 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), - WORK(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.WORK, Id3FieldType.TEXT), - WORK_COMPOSITION(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_COMPOSITION, Id3FieldType.TEXT), - WORK_PARTOF_LEVEL3_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL1(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1, Id3FieldType.TEXT), - WORK_PART_LEVEL1_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL2(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2, Id3FieldType.TEXT), - WORK_PART_LEVEL2_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL3(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL3, Id3FieldType.TEXT), - WORK_PART_LEVEL4(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4, Id3FieldType.TEXT), - WORK_PART_LEVEL4_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL5(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5, Id3FieldType.TEXT), - WORK_PART_LEVEL5_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, Id3FieldType.TEXT), - WORK_PART_LEVEL6(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6, Id3FieldType.TEXT), - WORK_PART_LEVEL6_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, Id3FieldType.TEXT), - WORK_TYPE(ID3v24Frames.FRAME_ID_USER_DEFINED_INFO, FrameBodyTXXX.WORK_TYPE, Id3FieldType.TEXT), - YEAR(ID3v24Frames.FRAME_ID_YEAR, 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frame.java deleted file mode 100644 index 23c66411..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frame.java +++ /dev/null @@ -1,1162 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.FileConstants; -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.datatype.Lyrics3Line; -import com.mp3.jaudiotagger.tag.id3.framebody.*; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.tag.lyrics3.*; -import com.mp3.jaudiotagger.utils.EqualsUtil; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -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$ - */ -public class ID3v24Frame extends AbstractID3v2Frame -{ - private static Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{3}"); - - 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; - - /** - * 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; - - 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; - } - - - 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 ID3v24 frame 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()); - } - - 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); - } - } - - /** - * Partially construct ID3v24 Frame form an IS3v23Frame - * - * Used for Special Cases - * - * @param frame - * @param identifier - * @throws InvalidFrameException - */ - protected ID3v24Frame(ID3v23Frame frame, String identifier) throws InvalidFrameException - { - this.identifier=identifier; - statusFlags = new StatusFlags((ID3v23Frame.StatusFlags) frame.getStatusFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } - - /** - * Creates a new ID3v24 frame 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 com.mp3.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"); - } - else if (frame instanceof ID3v23Frame) - { - statusFlags = new StatusFlags((ID3v23Frame.StatusFlags) frame.getStatusFlags()); - encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags()); - } - else if (frame instanceof ID3v22Frame) - { - 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 com.mp3.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 com.mp3.jaudiotagger.tag.InvalidFrameException - * - * @deprecated use {@link #ID3v24Frame(ByteBuffer,String)} instead - */ - public ID3v24Frame(ByteBuffer byteBuffer) throws InvalidFrameException, InvalidDataTypeException - { - this(byteBuffer, ""); - } - - /** - * @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); - if(((EncodingFlags) encodingFlags).isEncryption()) - { - frameBody = readEncryptedBody(identifier, frameBodyBuffer, dataLengthSize); - } - else - { - 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. - * - */ - 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(getIdentifier().getBytes(StandardCharsets.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 - ((EncodingFlags) encodingFlags).unsetNonStandardFlags(); - - //Encoding we only support unsynchronization - if (unsynchronization) - { - ((EncodingFlags) encodingFlags).setUnsynchronised(); - } - else - { - ((EncodingFlags) encodingFlags).unsetUnsynchronised(); - } - //These are not currently supported on write - ((EncodingFlags) encodingFlags).unsetCompression(); - ((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; - } - - /** - * Member Class This represents a frame headers Status Flags - * Make adjustments if necessary based on frame type and specification. - */ - public 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); - } - } - - /** - * 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(final Charset encoding) - { - Integer encodingId = TextEncoding.getInstanceOf().getIdForCharset(encoding); - if(encodingId!=null) - { - if(encodingId <4) - { - this.getBody().setTextEncoding(encodingId.byteValue()); - } - } - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frames.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frames.java deleted file mode 100644 index ea618e95..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Frames.java +++ /dev/null @@ -1,554 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.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$ - */ -public class ID3v24Frames extends ID3Frames -{ - /** - * Frame IDs beginning with T are text frames, and 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_ITUNES_GROUPING = "GRP1"; - 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_MOVEMENT = "MVNM"; - public static final String FRAME_ID_MOVEMENT_NO = "MVIN"; - 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; - - protected EnumMap tagFieldToId3 = new EnumMap(FieldKey.class); - - /** - * Maps from ID3 key to Generic key - */ - protected EnumMap id3ToTagField = new EnumMap(ID3v24FieldKey.class); - - - private static ID3v24Frames id3v24Frames; - - public static ID3v24Frames getInstanceOf() - { - if (id3v24Frames == null) - { - id3v24Frames = new ID3v24Frames(); - } - return id3v24Frames; - } - - 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_ITUNES_GROUPING); - 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_MOVEMENT); - supportedFrames.add(FRAME_ID_MOVEMENT_NO); - 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_ITUNES_GROUPING, "iTunes Grouping"); - 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_MOVEMENT, "Text: Movement"); - idToValue.put(FRAME_ID_MOVEMENT_NO, "Text: Movement No"); - 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.ACOUSTID_FINGERPRINT, ID3v24FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToId3.put(FieldKey.ACOUSTID_ID, ID3v24FieldKey.ACOUSTID_ID); - 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_ARTISTS, ID3v24FieldKey.ALBUM_ARTISTS); - tagFieldToId3.put(FieldKey.ALBUM_ARTISTS_SORT, ID3v24FieldKey.ALBUM_ARTISTS_SORT); - tagFieldToId3.put(FieldKey.ALBUM_SORT, ID3v24FieldKey.ALBUM_SORT); - tagFieldToId3.put(FieldKey.AMAZON_ID, ID3v24FieldKey.AMAZON_ID); - tagFieldToId3.put(FieldKey.ARRANGER, ID3v24FieldKey.ARRANGER); - tagFieldToId3.put(FieldKey.ARRANGER_SORT, ID3v24FieldKey.ARRANGER_SORT); - tagFieldToId3.put(FieldKey.ARTIST, ID3v24FieldKey.ARTIST); - tagFieldToId3.put(FieldKey.ARTISTS, ID3v24FieldKey.ARTISTS); - tagFieldToId3.put(FieldKey.ARTISTS_SORT, ID3v24FieldKey.ARTISTS_SORT); - 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.CHOIR, ID3v24FieldKey.CHOIR); - tagFieldToId3.put(FieldKey.CHOIR_SORT, ID3v24FieldKey.CHOIR_SORT); - tagFieldToId3.put(FieldKey.CLASSICAL_CATALOG, ID3v24FieldKey.CLASSICAL_CATALOG); - tagFieldToId3.put(FieldKey.CLASSICAL_NICKNAME, ID3v24FieldKey.CLASSICAL_NICKNAME); - 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.CONDUCTOR_SORT, ID3v24FieldKey.CONDUCTOR_SORT); - tagFieldToId3.put(FieldKey.COPYRIGHT, ID3v24FieldKey.COPYRIGHT); - tagFieldToId3.put(FieldKey.COUNTRY, ID3v24FieldKey.COUNTRY); - 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.DJMIXER, ID3v24FieldKey.DJMIXER); - tagFieldToId3.put(FieldKey.MOOD_ELECTRONIC, ID3v24FieldKey.MOOD_ELECTRONIC); - tagFieldToId3.put(FieldKey.ENCODER, ID3v24FieldKey.ENCODER); - tagFieldToId3.put(FieldKey.ENGINEER, ID3v24FieldKey.ENGINEER); - tagFieldToId3.put(FieldKey.ENSEMBLE, ID3v24FieldKey.ENSEMBLE); - tagFieldToId3.put(FieldKey.ENSEMBLE_SORT, ID3v24FieldKey.ENSEMBLE_SORT); - tagFieldToId3.put(FieldKey.FBPM, ID3v24FieldKey.FBPM); - tagFieldToId3.put(FieldKey.GENRE, ID3v24FieldKey.GENRE); - tagFieldToId3.put(FieldKey.GROUP, ID3v24FieldKey.GROUP); - tagFieldToId3.put(FieldKey.GROUPING, ID3v24FieldKey.GROUPING); - tagFieldToId3.put(FieldKey.INSTRUMENT, ID3v24FieldKey.INSTRUMENT); - tagFieldToId3.put(FieldKey.INVOLVED_PERSON, ID3v24FieldKey.INVOLVED_PERSON); - tagFieldToId3.put(FieldKey.ISRC, ID3v24FieldKey.ISRC); - tagFieldToId3.put(FieldKey.IS_CLASSICAL, ID3v24FieldKey.IS_CLASSICAL); - tagFieldToId3.put(FieldKey.IS_COMPILATION, ID3v24FieldKey.IS_COMPILATION); - tagFieldToId3.put(FieldKey.IS_SOUNDTRACK, ID3v24FieldKey.IS_SOUNDTRACK); - tagFieldToId3.put(FieldKey.ITUNES_GROUPING, ID3v24FieldKey.ITUNES_GROUPING); - 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.MIXER, ID3v24FieldKey.MIXER); - tagFieldToId3.put(FieldKey.MOOD, ID3v24FieldKey.MOOD); - tagFieldToId3.put(FieldKey.MOOD_ACOUSTIC, ID3v24FieldKey.MOOD_ACOUSTIC); - tagFieldToId3.put(FieldKey.MOOD_AGGRESSIVE, ID3v24FieldKey.MOOD_AGGRESSIVE); - tagFieldToId3.put(FieldKey.MOOD_AROUSAL, ID3v24FieldKey.MOOD_AROUSAL); - tagFieldToId3.put(FieldKey.MOOD_DANCEABILITY, ID3v24FieldKey.MOOD_DANCEABILITY); - tagFieldToId3.put(FieldKey.MOOD_HAPPY, ID3v24FieldKey.MOOD_HAPPY); - tagFieldToId3.put(FieldKey.MOOD_INSTRUMENTAL, ID3v24FieldKey.MOOD_INSTRUMENTAL); - tagFieldToId3.put(FieldKey.MOOD_PARTY, ID3v24FieldKey.MOOD_PARTY); - tagFieldToId3.put(FieldKey.MOOD_RELAXED, ID3v24FieldKey.MOOD_RELAXED); - tagFieldToId3.put(FieldKey.MOOD_SAD, ID3v24FieldKey.MOOD_SAD); - tagFieldToId3.put(FieldKey.MOOD_VALENCE, ID3v24FieldKey.MOOD_VALENCE); - tagFieldToId3.put(FieldKey.MOVEMENT, ID3v24FieldKey.MOVEMENT); - tagFieldToId3.put(FieldKey.MOVEMENT_NO, ID3v24FieldKey.MOVEMENT_NO); - tagFieldToId3.put(FieldKey.MOVEMENT_TOTAL, ID3v24FieldKey.MOVEMENT_TOTAL); - 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_TRACK_ID, ID3v24FieldKey.MUSICBRAINZ_RELEASE_TRACK_ID); - 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, ID3v24FieldKey.MUSICBRAINZ_WORK); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION, ID3v24FieldKey.WORK_COMPOSITION); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID, ID3v24FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID); - tagFieldToId3.put(FieldKey.MUSICIP_ID, ID3v24FieldKey.MUSICIP_ID); - tagFieldToId3.put(FieldKey.OCCASION, ID3v24FieldKey.OCCASION); - tagFieldToId3.put(FieldKey.OPUS, ID3v24FieldKey.OPUS); - tagFieldToId3.put(FieldKey.ORCHESTRA, ID3v24FieldKey.ORCHESTRA); - tagFieldToId3.put(FieldKey.ORCHESTRA_SORT, ID3v24FieldKey.ORCHESTRA_SORT); - 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.PART, ID3v24FieldKey.PART); - tagFieldToId3.put(FieldKey.PART_NUMBER, ID3v24FieldKey.PART_NUMBER); - tagFieldToId3.put(FieldKey.PART_TYPE, ID3v24FieldKey.PART_TYPE); - tagFieldToId3.put(FieldKey.PERFORMER, ID3v24FieldKey.PERFORMER); - tagFieldToId3.put(FieldKey.PERFORMER_NAME, ID3v24FieldKey.PERFORMER_NAME); - tagFieldToId3.put(FieldKey.PERFORMER_NAME_SORT, ID3v24FieldKey.PERFORMER_NAME_SORT); - tagFieldToId3.put(FieldKey.PERIOD, ID3v24FieldKey.PERIOD); - tagFieldToId3.put(FieldKey.PRODUCER, ID3v24FieldKey.PRODUCER); - tagFieldToId3.put(FieldKey.QUALITY, ID3v24FieldKey.QUALITY); - tagFieldToId3.put(FieldKey.RANKING, ID3v24FieldKey.RANKING); - 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.SINGLE_DISC_TRACK_NO, ID3v24FieldKey.SINGLE_DISC_TRACK_NO); - tagFieldToId3.put(FieldKey.SUBTITLE, ID3v24FieldKey.SUBTITLE); - tagFieldToId3.put(FieldKey.TAGS, ID3v24FieldKey.TAGS); - tagFieldToId3.put(FieldKey.TEMPO, ID3v24FieldKey.TEMPO); - tagFieldToId3.put(FieldKey.TIMBRE, ID3v24FieldKey.TIMBRE); - tagFieldToId3.put(FieldKey.TITLE, ID3v24FieldKey.TITLE); - tagFieldToId3.put(FieldKey.TITLE_MOVEMENT, ID3v24FieldKey.TITLE_MOVEMENT); - tagFieldToId3.put(FieldKey.TITLE_SORT, ID3v24FieldKey.TITLE_SORT); - tagFieldToId3.put(FieldKey.TONALITY, ID3v24FieldKey.TONALITY); - 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.WORK, ID3v24FieldKey.WORK); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1, ID3v24FieldKey.WORK_PART_LEVEL1); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, ID3v24FieldKey.WORK_PART_LEVEL1_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2, ID3v24FieldKey.WORK_PART_LEVEL2); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, ID3v24FieldKey.WORK_PART_LEVEL2_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3, ID3v24FieldKey.WORK_PART_LEVEL3); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, ID3v24FieldKey.WORK_PARTOF_LEVEL3_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4, ID3v24FieldKey.WORK_PART_LEVEL4); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, ID3v24FieldKey.WORK_PART_LEVEL4_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5, ID3v24FieldKey.WORK_PART_LEVEL5); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, ID3v24FieldKey.WORK_PART_LEVEL5_TYPE); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6, ID3v24FieldKey.WORK_PART_LEVEL6); - tagFieldToId3.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, ID3v24FieldKey.WORK_PART_LEVEL6_TYPE); - tagFieldToId3.put(FieldKey.WORK_TYPE, ID3v24FieldKey.WORK_TYPE); - tagFieldToId3.put(FieldKey.YEAR, ID3v24FieldKey.YEAR); - - for(Map.Entry next:tagFieldToId3.entrySet()) - { - id3ToTagField.put(next.getValue(), next.getKey()); - } - } - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java deleted file mode 100644 index 5e8e5e25..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24PreferredFrameOrderComparator.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -import static com.mp3.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); - if(frameId1Index==-1) - { - frameId1Index=Integer.MAX_VALUE; - } - int frameId2Index= frameIdsInPreferredOrder.indexOf(frameId2); - - //Because othwerwise returns -1 whihc would be tags in list went to top of list - if(frameId2Index==-1) - { - frameId2Index=Integer.MAX_VALUE; - } - - //To have determinable ordering AND because if returns equal Treese considers as equal - if(frameId1Index==frameId2Index) - { - return frameId1.compareTo(frameId2); - } - return frameId1Index - frameId2Index; - } - - public boolean equals(Object obj) - { - return obj instanceof ID3v24PreferredFrameOrderComparator; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Tag.java deleted file mode 100644 index 59fd784f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v24Tag.java +++ /dev/null @@ -1,1492 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.FileConstants; -import com.mp3.jaudiotagger.audio.mp3.MP3File; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.id3.framebody.*; -import com.mp3.jaudiotagger.tag.id3.valuepair.MusicianCredits; -import com.mp3.jaudiotagger.tag.id3.valuepair.StandardIPLSKey; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.jaudiotagger.tag.lyrics3.AbstractLyrics3; -import com.mp3.jaudiotagger.tag.lyrics3.Lyrics3v2; -import com.mp3.jaudiotagger.tag.lyrics3.Lyrics3v2Field; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; -import com.mp3.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$ - */ -public class ID3v24Tag extends AbstractID3v2Tag -{ - 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"; - 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; - - /** - * 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 are the same as the header flags. WHY?!?! move the - * flags from thier position in 2.3?????????? - */ - /** - * 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; - - /** - * 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; - - public static final byte RELEASE = 2; - public static final byte MAJOR_VERSION = 4; - public static final byte REVISION = 0; - - /** - * 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; - } - - - /** - * Creates a new empty ID3v2_4 datatype. - */ - public ID3v24Tag() - { - frameMap = new LinkedHashMap(); - encryptedFrameMap = new LinkedHashMap(); - - } - - /** - * 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; - } - } - - /** - * Copy the frame - * - * If the frame is already an ID3v24 frame we can add as is, if not we need to convert - * to id3v24 frame(s) - * - * @param frame - */ - @Override - public void addFrame(AbstractID3v2Frame frame) - { - try - { - if (frame instanceof ID3v24Frame) - { - copyFrameIntoMap(frame.getIdentifier(), frame); - } - else - { - List frames = convertFrame(frame); - for(AbstractID3v2Frame next:frames) - { - copyFrameIntoMap(next.getIdentifier(), next); - } - } - } - catch (InvalidFrameException ife) - { - logger.log(Level.SEVERE, "Unable to convert frame:" + frame.getIdentifier()); - } - } - - /** - * Convert frame into ID3v24 frame(s) - * @param frame - * @return - * @throws InvalidFrameException - */ - @Override - protected List convertFrame(AbstractID3v2Frame frame) throws InvalidFrameException - { - List frames = new ArrayList(); - if(frame instanceof ID3v22Frame && frame.getIdentifier().equals(ID3v22Frames.FRAME_ID_V2_IPLS)) - { - frame = new ID3v23Frame(frame); - } - - //This frame may need splitting and converting into two frames depending on its content - if(frame instanceof ID3v23Frame && frame.getIdentifier().equals(ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE)) - { - List pairs= ((FrameBodyIPLS)frame.getBody()).getPairing().getMapping(); - List pairsTipl = new ArrayList(); - List pairsTmcl = new ArrayList(); - - for(Pair next:pairs) - { - if(StandardIPLSKey.isKey(next.getKey())) - { - pairsTipl.add(next); - } - else if(MusicianCredits.isKey(next.getKey())) - { - pairsTmcl.add(next); - } - else - { - pairsTipl.add(next); - } - } - AbstractID3v2Frame tipl = new ID3v24Frame((ID3v23Frame)frame,ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE); - FrameBodyTIPL tiplBody = new FrameBodyTIPL(frame.getBody().getTextEncoding(),pairsTipl); - tipl.setBody(tiplBody); - frames.add(tipl); - - AbstractID3v2Frame tmcl = new ID3v24Frame((ID3v23Frame)frame,ID3v24Frames.FRAME_ID_MUSICIAN_CREDITS); - FrameBodyTMCL tmclBody = new FrameBodyTMCL(frame.getBody().getTextEncoding(),pairsTmcl); - tmcl.setBody(tmclBody); - frames.add(tmcl); - } - else - { - frames.add(new ID3v24Frame(frame)); - } - return frames; - } - - /** - * 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 - * - * @param newFrame - * @param existingFrame - */ - @Override - protected void processDuplicateFrame(AbstractID3v2Frame newFrame, AbstractID3v2Frame existingFrame) - { - //We dont add this new frame we just add the contents to existing frame - // - if (newFrame.getBody() instanceof FrameBodyTDRC) - { - if (existingFrame.getBody() instanceof FrameBodyTDRC) - { - FrameBodyTDRC body = (FrameBodyTDRC) existingFrame.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 (existingFrame.getBody() instanceof FrameBodyUnsupported) - { - frameMap.put(newFrame.getIdentifier(), newFrame); - } - else - { - //we just lose this frame, we have already got one with the correct id. - logger.warning("Found duplicate TDRC frame in invalid situation,discarding:" + newFrame.getIdentifier()); - } - } - else - { - List list = new ArrayList(); - list.add(existingFrame); - list.add(newFrame); - frameMap.put(newFrame.getIdentifier(), list); - } - } - - - /** - * 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, ""); - } - - /** - * @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 com.mp3.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 long 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); - return sizeIncPadding; - } - - /** - * {@inheritDoc} - */ - @Override - public void write(WritableByteChannel channel, int currentTagSize) throws IOException - { - logger.severe("Writing tag to channel"); - - byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray(); - - - int padding = 0; - if(currentTagSize > 0) - { - int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) currentTagSize); - padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH); - } - ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length); - - channel.write(headerBuffer); - channel.write(ByteBuffer.wrap(bodyByteBuffer)); - writePadding(channel, padding); - } - - /** - * 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(null, id3Key.getFrameId(), id3Key.getSubId()), value); - } - - /** - * Retrieve the first value that exists for this id3v24key - * - * @param id3v24FieldKey - * @return - * @throws com.mp3.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(null, id3v24FieldKey.getFrameId(), id3v24FieldKey.getSubId()); - return super.doGetValueAtIndex(frameAndSubId, 0); - } - } - - - /** - * Delete fields with this id3v24FieldKey - * - * @param id3v24FieldKey - * @throws com.mp3.jaudiotagger.tag.KeyNotFoundException - */ - public void deleteField(ID3v24FieldKey id3v24FieldKey) throws KeyNotFoundException - { - if (id3v24FieldKey == null) - { - throw new KeyNotFoundException(); - } - super.doDeleteTagField(new FrameAndSubId(null, id3v24FieldKey.getFrameId(), id3v24FieldKey.getSubId())); - } - - /** - * Delete fields with this (frame) id - * @param id - */ - public void deleteField(String id) - { - super.doDeleteTagField(new FrameAndSubId(null, 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(genericKey, 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 - * @see PictureTypes - * @return - */ - 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; - } - - /** - * Overridden for special Genre support - * - * @param genericKey is the generic key - * @param values - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public TagField createField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if (genericKey == FieldKey.GENRE) - { - if (values == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - String value = values[0]; - if (value == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey); - AbstractID3v2Frame frame = createFrame(formatKey.getFrameId()); - FrameBodyTCON framebody = (FrameBodyTCON) frame.getBody(); - - if(TagOptionSingleton.getInstance().isWriteMp3GenresAsText()) - { - framebody.setText(value); - } - else - { - framebody.setText(FrameBodyTCON.convertGenericToID3v24Genre(value)); - } - return frame; - } - else - { - return super.createField(genericKey, values); - } - } - /** - * 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 - { - if(genericKey == FieldKey.GENRE) - { - List fields = getFields(genericKey); - List convertedGenres = new ArrayList(); - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - FrameBodyTCON body = (FrameBodyTCON)frame.getBody(); - - for(String next:body.getValues()) - { - convertedGenres.add(FrameBodyTCON.convertID3v24GenreToGeneric(next)); - } - } - return convertedGenres; - } - else - { - return super.getAll(genericKey); - } - } - - /** - * 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 - */ - @Override - public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - if(genericKey == FieldKey.GENRE) - { - List fields = getFields(genericKey); - if (fields != null && fields.size() > 0) - { - AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(0); - FrameBodyTCON body = (FrameBodyTCON)frame.getBody(); - return FrameBodyTCON.convertID3v24GenreToGeneric(body.getValues().get(index)); - } - return ""; - } - else - { - return super.getValue(genericKey, index); - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v2ChapterFrames.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v2ChapterFrames.java deleted file mode 100644 index 5beb7bb7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/ID3v2ChapterFrames.java +++ /dev/null @@ -1,55 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.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$ - */ -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; - - public static ID3v2ChapterFrames getInstanceOf() - { - if (id3v2ChapterFrames == null) - { - id3v2ChapterFrames = new ID3v2ChapterFrames(); - } - return 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3FieldType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3FieldType.java deleted file mode 100644 index 21131523..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3FieldType.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -/** - * Categorises id3 fields to aid in mapping to generic keys - */ -public enum Id3FieldType -{ - TEXT, - USER_DEFINED_TEXT, - BINARY -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3SupportingTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3SupportingTag.java deleted file mode 100644 index 170c7b3a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/Id3SupportingTag.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -/** - * This interface indicates that the tag supports ID3 - */ -public interface Id3SupportingTag -{ - public AbstractID3v2Tag getID3Tag(); - - public void setID3Tag(AbstractID3v2Tag t); -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java deleted file mode 100644 index ebd2fae2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/TyerTdatAggregatedFrame.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3; - -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyTDAT; - -import java.util.Iterator; - -/** - * For use in ID3 for mapping YEAR field to TYER and TDAT Frames - */ -public class TyerTdatAggregatedFrame extends AggregatedFrame -{ - public TyerTdatAggregatedFrame() - { - - } - - 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(); - if(tdat.getContent().length()==FrameBodyTDAT.DATA_SIZE) - { - sb.append("-"); - sb.append(tdat.getContent().substring(FrameBodyTDAT.MONTH_START, FrameBodyTDAT.MONTH_END)); - - if(!((FrameBodyTDAT)tdat.getBody()).isMonthOnly()) - { - sb.append("-"); - sb.append(tdat.getContent().substring(FrameBodyTDAT.DAY_START, FrameBodyTDAT.DAY_END)); - } - } - return sb.toString(); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyNumberTotal.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyNumberTotal.java deleted file mode 100644 index 7a921415..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyNumberTotal.java +++ /dev/null @@ -1,167 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.datatype.PartOfSet; -import com.mp3.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$ - */ -public abstract class AbstractFrameBodyNumberTotal extends AbstractID3v2FrameBody -{ - /** - * Creates a new FrameBodyTRCK datatype. - */ - public AbstractFrameBodyNumberTotal() - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue()); - } - - public AbstractFrameBodyNumberTotal(AbstractFrameBodyNumberTotal body) - { - super(body); - } - - /** - * Creates a new FrameBodyTRCK datatype, the value is parsed literally - * - * @param textEncoding - * @param text - */ - public AbstractFrameBodyNumberTotal(byte textEncoding, String text) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } - - public AbstractFrameBodyNumberTotal(byte textEncoding, Integer trackNo, Integer trackTotal) - { - super(); - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(trackNo,trackTotal)); - } - - public String getUserFriendlyValue() - { - PartOfSet.PartOfSetValue value = (PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT); - return String.valueOf(value.getCount()); - } - - /** - * Creates a new FrameBodyTRCK datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws com.mp3.jaudiotagger.tag.InvalidTagException - */ - public AbstractFrameBodyNumberTotal(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public abstract String getIdentifier(); - - public String getText() - { - return getObjectValue(DataTypes.OBJ_TEXT).toString(); - } - - public void setText(String text) - { - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } - - public Integer getNumber() - { - PartOfSet.PartOfSetValue value = (PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT); - return value.getCount(); - } - - public String getNumberAsText() - { - return ((PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT)).getCountAsText(); - } - - - public void setNumber(Integer trackNo) - { - ((PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT)).setCount(trackNo); - } - - public void setNumber(String trackNo) - { - ((PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT)).setCount(trackNo); - } - - public Integer getTotal() - { - return ((PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT)).getTotal(); - } - - public String getTotalAsText() - { - return ((PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT)).getTotalAsText(); - } - - public void setTotal(Integer trackTotal) - { - ((PartOfSet.PartOfSetValue)getObjectValue(DataTypes.OBJ_TEXT)).setTotal(trackTotal); - } - - public void setTotal(String 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyPairs.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyPairs.java deleted file mode 100644 index 0a46bca8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyPairs.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * People List - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.StringTokenizer; - - -/** - * Used by frames that take a pair of values such as TIPL, IPLS and TMCL - * - */ -public abstract class AbstractFrameBodyPairs extends AbstractID3v2FrameBody implements ID3v24FrameBody -{ - - /** - * Creates a new AbstractFrameBodyPairs datatype. - */ - public AbstractFrameBodyPairs() - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, TextEncoding.ISO_8859_1); - } - - /** - * Creates a new AbstractFrameBodyPairs data type. - * - * @param textEncoding - * @param text - */ - public AbstractFrameBodyPairs(byte textEncoding, String text) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - setText(text); - } - - /** - * Creates a new AbstractFrameBodyPairs data type. - * - * @param byteBuffer - * @param frameSize - * @throws com.mp3.jaudiotagger.tag.InvalidTagException - */ - public AbstractFrameBodyPairs(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public abstract String getIdentifier(); - - /** - * 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); - } - - /** - * Parse text as a null separated pairing of function and name - * - * @param text - */ - public void addPair(String text) - { - StringTokenizer stz = new StringTokenizer(text, "\0"); - if (stz.countTokens()==2) - { - addPair(stz.nextToken(),stz.nextToken()); - } - else - { - addPair("", text); - } - } - - /** - * 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(); - } - - public String getUserFriendlyValue() - { - return getText(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java deleted file mode 100644 index 0e758d52..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyTextInfo.java +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.datatype.TextEncodedStringSizeTerminated; -import com.mp3.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import com.mp3.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: - * - * Header for 'Text information frame', ID: "T000" - "TZZZ", - * excluding "TXXX" described in 4.2.6. - * - * Text encoding $xx - * Information text string(s) according to encoding - * - * 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); - } - - /** - * 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); - } - - 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); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java deleted file mode 100644 index 17c5d7a7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/AbstractFrameBodyUrlLink.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.StringSizeTerminated; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.ByteBuffer; -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(); - } - - /** - * 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); - } - - /** - * Get URL Link - * - * @return the urllink - */ - public String getUrlLink() - { - return (String) getObjectValue(DataTypes.OBJ_URLLINK); - } - - /** - * If the description cannot be encoded using the current encoding change the encoder - */ - public void write(ByteArrayOutputStream tagBuffer) - { - CharsetEncoder encoder = StandardCharsets.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("(? (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 - */ - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAENC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAENC.java deleted file mode 100644 index 3e9e123e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAENC.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java deleted file mode 100644 index 3ebb4463..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyAPIC.java +++ /dev/null @@ -1,313 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.ImageFormats; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.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$ - */ -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() - { - if(getImageData()!=null) - { - return getMimeType() + ":" + getDescription() + ":" + getImageData().length; - } - else - { - return getMimeType() + ":" + getDescription() + ":0"; - } - } - - - /** - * Set a description of the image - * - * @param description - */ - public void setDescription(String description) - { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * Get a description of the image - * - * @return a description of the image - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set mimeType - * - * @param mimeType - */ - public void setMimeType(String mimeType) - { - setObjectValue(DataTypes.OBJ_MIME_TYPE, mimeType); - } - - /** - * Get mimetype - * - * @return a description of the image - */ - public String getMimeType() - { - return (String) getObjectValue(DataTypes.OBJ_MIME_TYPE); - } - - /** - * Set imageData - * - * @param imageData - */ - public void setImageData(byte[] imageData) - { - setObjectValue(DataTypes.OBJ_PICTURE_DATA, imageData); - } - - /** - * Get Image data - * - * @return - */ - public byte[] getImageData() - { - return (byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA); - } - - /** - * Set Picture Type - * - * @param pictureType - */ - public void setPictureType(byte pictureType) - { - setObjectValue(DataTypes.OBJ_PICTURE_TYPE, pictureType); - } - - /** - * @return picturetype - */ - public int getPictureType() - { - return ((Long) getObjectValue(DataTypes.OBJ_PICTURE_TYPE)).intValue(); - } - - /** - * 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(TagOptionSingleton.getInstance().isAPICDescriptionITunesCompatible()) - { - this.setTextEncoding(TextEncoding.ISO_8859_1); - if (!((AbstractString) getObject(DataTypes.OBJ_DESCRIPTION)).canBeEncoded()) - { - setDescription(""); - } - } - else - { - 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 new String(((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)), 0, ((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)).length, StandardCharsets.ISO_8859_1); - } - else - { - return ""; - } - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java deleted file mode 100644 index 15715569..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyASPI.java +++ /dev/null @@ -1,139 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.jaudiotagger.tag.datatype.NumberVariableLength; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java deleted file mode 100644 index 2c6dd889..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCHAP.java +++ /dev/null @@ -1,151 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java deleted file mode 100644 index 1ce6401e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMM.java +++ /dev/null @@ -1,333 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.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$ - */ -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"; - - //Various descriptions used by MediaMonkey, (note Media Monkey uses non-standard language field XXX) - private static final String MM_PREFIX = "Songs-DB"; - 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"; - - 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; - } - - - /** - * 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); - } - - - /** - * 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); - } - - /** - * Get the description field, which describes the type of comment - * - * @return description field - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_COMMENT; - } - - /** - * 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); - } - - /** - * Get the language the comment is written in - * - * @return the language - */ - public String getLanguage() - { - return (String) getObjectValue(DataTypes.OBJ_LANGUAGE); - } - - /** - * @param text - */ - public void setText(String text) - { - if (text == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - setObjectValue(DataTypes.OBJ_TEXT, text); - } - - /** - * 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); - } - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java deleted file mode 100644 index 21c9d5c0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCOMR.java +++ /dev/null @@ -1,207 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.ReceivedAsTypes; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java deleted file mode 100644 index a2bcb27f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCRM.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java deleted file mode 100644 index a74aab11..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyCTOC.java +++ /dev/null @@ -1,145 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java deleted file mode 100644 index 0ee8aabf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyDeprecated.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java deleted file mode 100644 index 47c5dc77..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyENCR.java +++ /dev/null @@ -1,139 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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$ - */ -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; - } - - /** - * @param owner - */ - public void setOwner(String owner) - { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * @return - */ - public String getOwner() - { - return (String) getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java deleted file mode 100644 index 7410d5c9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQU2.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java deleted file mode 100644 index aa07d70a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEQUA.java +++ /dev/null @@ -1,95 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java deleted file mode 100644 index 68ffc721..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyETCO.java +++ /dev/null @@ -1,347 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.EventTimingCode; -import com.mp3.jaudiotagger.tag.datatype.EventTimingCodeList; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.EventTimingTimestampTypes; - -import java.nio.ByteBuffer; -import java.util.*; - -/** - * 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 - *

- * Absolute 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 - * @author : Hendrik Schreiber - * @version $Id$ - */ -public class FrameBodyETCO extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody -{ - - public static final int MPEG_FRAMES = 1; - public static final int MILLISECONDS = 2; - - /** - * Creates a new FrameBodyETCO datatype. - */ - public FrameBodyETCO() - { - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, MILLISECONDS); - } - - public FrameBodyETCO(final FrameBodyETCO body) - { - super(body); - } - - /** - * Creates a new FrameBodyETCO datatype. - * - * @param byteBuffer buffer to read from - * @param frameSize size of the frame - * @throws InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyETCO(final ByteBuffer byteBuffer, final int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - /** - * Timestamp format for all events in this frame. - * A value of {@code 1} means absolute time (32 bit) using MPEG frames as unit. - * A value of {@code 2} means absolute time (32 bit) using milliseconds as unit. - * - * @return timestamp format - * @see #MILLISECONDS - * @see #MPEG_FRAMES - */ - public int getTimestampFormat() - { - return ((Number) getObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT)).intValue(); - } - - /** - * Sets the timestamp format. - * - * @param timestampFormat 1 for MPEG frames or 2 for milliseconds - * @see #getTimestampFormat() - */ - public void setTimestampFormat(final int timestampFormat) - { - if (EventTimingTimestampTypes.getInstanceOf().getValueForId(timestampFormat) == null) - { - throw new IllegalArgumentException("Timestamp format must be 1 or 2 (ID3v2.4, 4.5): " + timestampFormat); - } - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, timestampFormat); - } - - /** - * Chronological map of timing codes. - * - * @return map of timing codes - */ - public Map getTimingCodes() - { - final Map map = new LinkedHashMap(); - final List codes = (List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST); - long lastTimestamp = 0; - for (final EventTimingCode code : codes) - { - final long translatedTimestamp = code.getTimestamp() == 0 ? lastTimestamp : code.getTimestamp(); - final int[] types = map.get(translatedTimestamp); - if (types == null) { - map.put(translatedTimestamp, new int[]{code.getType()}); - } else { - final int[] newTypes = new int[types.length + 1]; - System.arraycopy(types, 0, newTypes, 0, types.length); - newTypes[newTypes.length-1] = code.getType(); - map.put(translatedTimestamp, newTypes); - } - lastTimestamp = translatedTimestamp; - } - return Collections.unmodifiableMap(map); - } - - /** - * Chronological list of timestamps of a set of given types. - * - * @param type types - * @return list of timestamps - */ - public List getTimestamps(final int... type) - { - final Set typeSet = toSet(type); - final List list = new ArrayList(); - final List codes = (List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST); - long lastTimestamp = 0; - for (final EventTimingCode code : codes) - { - final long translatedTimestamp = code.getTimestamp() == 0 ? lastTimestamp : code.getTimestamp(); - if (typeSet.contains(code.getType())) - { - list.add(translatedTimestamp); - } - lastTimestamp = translatedTimestamp; - } - return Collections.unmodifiableList(list); - } - - /** - * Adds a timing code for each given type. - * - * @param timestamp timestamp - * @param types types - */ - public void addTimingCode(final long timestamp, final int... types) - { - final List codes = (List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST); - long lastTimestamp = 0; - int insertIndex = 0; - if (!codes.isEmpty() && codes.get(0).getTimestamp() <= timestamp) - { - for (final EventTimingCode code : codes) - { - final long translatedTimestamp = code.getTimestamp() == 0 ? lastTimestamp : code.getTimestamp(); - if (timestamp < translatedTimestamp) - { - break; - } - insertIndex++; - lastTimestamp = translatedTimestamp; - } - } - for (final int type : types) { - codes.add(insertIndex, new EventTimingCode(DataTypes.OBJ_TIMED_EVENT, this, type, timestamp)); - insertIndex++; // preserve order of types - } - } - - /** - * Removes timestamps at a given time with the given types. - * - * @param timestamp timestamp - * @param types types - * @return {@code true}, if any timestamps were removed - */ - public boolean removeTimingCode(final long timestamp, final int... types) - { - // before we can remove anything, we have to resolve relative 0-timestamps - // otherwise we might remove the anchor a relative timestamp relies on - resolveRelativeTimestamps(); - final Set typeSet = toSet(types); - final List codes = (List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST); - boolean removed = false; - for (final ListIterator iterator = codes.listIterator(); iterator.hasNext(); ) - { - final EventTimingCode code = iterator.next(); - if (timestamp == code.getTimestamp() && typeSet.contains(code.getType())) - { - iterator.remove(); - removed = true; - } - if (timestamp > code.getTimestamp()) - { - break; - } - } - return removed; - } - - /** - * Remove all timing codes. - */ - public void clearTimingCodes() - { - ((List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST)).clear(); - } - - /** - * Resolve any relative timestamp (zero timestamp after a non-zero timestamp) to absolute timestamp. - */ - private void resolveRelativeTimestamps() - { - final List codes = (List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST); - long lastTimestamp = 0; - for (final EventTimingCode code : codes) - { - final long translatedTimestamp = code.getTimestamp() == 0 ? lastTimestamp : code.getTimestamp(); - code.setTimestamp(translatedTimestamp); - lastTimestamp = translatedTimestamp; - } - } - - @Override - public void read(final ByteBuffer byteBuffer) throws InvalidTagException - { - super.read(byteBuffer); - - // validate input - final List codes = (List)getObjectValue(DataTypes.OBJ_TIMED_EVENT_LIST); - long lastTimestamp = 0; - for (final EventTimingCode code : codes) - { - final long translatedTimestamp = code.getTimestamp() == 0 ? lastTimestamp : code.getTimestamp(); - if (code.getTimestamp() < lastTimestamp) - { - logger.warning("Event codes are not in chronological order. " + lastTimestamp + " is followed by " + code.getTimestamp() + "."); - // throw exception??? - } - lastTimestamp = translatedTimestamp; - } - } - - /** - * @return identifier - */ - @Override - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_EVENT_TIMING_CODES; - } - - /** - * Setup object list. - */ - @Override - protected void setupObjectList() - { - objectList.add(new NumberHashMap(DataTypes.OBJ_TIME_STAMP_FORMAT, this, EventTimingTimestampTypes.TIMESTAMP_KEY_FIELD_SIZE)); - objectList.add(new EventTimingCodeList(this)); - } - - private static Set toSet(final int... types) - { - final Set typeSet = new HashSet(); - for (final int type : types) - { - typeSet.add(type); - } - return typeSet; - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java deleted file mode 100644 index d0c881d9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyEncrypted.java +++ /dev/null @@ -1,81 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java deleted file mode 100644 index ef2c1ce8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGEOB.java +++ /dev/null @@ -1,158 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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$ - */ -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); - } - - /** - * @param description - */ - public void setDescription(String description) - { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * @return the description field - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java deleted file mode 100644 index 42347c3c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRID.java +++ /dev/null @@ -1,164 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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$ - */ -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); - } - - /** - * @param textEncoding - */ - public void setGroupSymbol(byte textEncoding) - { - setObjectValue(DataTypes.OBJ_GROUP_SYMBOL, textEncoding); - } - - /** - * @return - */ - public byte getGroupSymbol() - { - if (getObjectValue(DataTypes.OBJ_GROUP_SYMBOL) != null) - { - return ((Long) getObjectValue(DataTypes.OBJ_GROUP_SYMBOL)).byteValue(); - } - else - { - return (byte) 0; - } - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_GROUP_ID_REG; - } - - - /** - * @param owner - */ - public void setOwner(String owner) - { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * @return - */ - public String getOwner() - { - return (String) getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRP1.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRP1.java deleted file mode 100644 index ee1f206e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyGRP1.java +++ /dev/null @@ -1,79 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * iTunes grouping field introduced in 12.5.4.42, before that iTunes used TIT1 as is the norm, but it now uses that - * for Classical Work. Jaudiotagger maps WORK key to TXXX:WORK for work because TIT1 is in use more for GROUPING. - * Unfortunately TIT1 is defined in ID3 spec to be used for either which is problematic - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id$ - */ -public class FrameBodyGRP1 extends AbstractFrameBodyTextInfo implements ID3v24FrameBody, ID3v23FrameBody -{ - /** - * Creates a new FrameBodyTBPM datatype. - */ - public FrameBodyGRP1() - { - } - - public FrameBodyGRP1(FrameBodyGRP1 body) - { - super(body); - } - - /** - * Creates a new FrameBodyTBPM datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyGRP1(byte textEncoding, String text) - { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTBPM datatype. - * - * @param byteBuffer - * @param frameSize - * @throws com.mp3.jaudiotagger.tag.InvalidTagException - */ - public FrameBodyGRP1(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_ITUNES_GROUPING; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java deleted file mode 100644 index 1b024b52..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyIPLS.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * People List - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; -import java.util.List; - - -/** - * 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 FrameBodyIPLS extends AbstractFrameBodyPairs implements ID3v23FrameBody -{ - - /** - * Creates a new FrameBodyIPLS datatype. - */ - public FrameBodyIPLS() - { - super(); - } - - /** - * Creates a new FrameBodyIPLS data type. - * - * @param textEncoding - * @param text - */ - public FrameBodyIPLS(byte textEncoding, String text) - { - super(textEncoding, text); - } - - public FrameBodyIPLS(FrameBodyIPLS body) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - setObjectValue(DataTypes.OBJ_TEXT, body.getPairing()); - } - - /** - * Creates a new FrameBodyIPLS data type. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyIPLS(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - /** - * Convert from V4 to V3 Frame - * - * @param body - */ - public FrameBodyIPLS(FrameBodyTIPL body) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - setObjectValue(DataTypes.OBJ_TEXT, body.getPairing()); - } - - /** - * Construct from a set of pairs - * - * @param textEncoding - * @param pairs - */ - public FrameBodyIPLS(byte textEncoding, List pairs) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - PairedTextEncodedStringNullTerminated.ValuePairs values = new PairedTextEncodedStringNullTerminated.ValuePairs(); - for(Pair next:pairs) - { - values.add(next); - } - setObjectValue(DataTypes.OBJ_TEXT, values); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v23Frames.FRAME_ID_V3_INVOLVED_PEOPLE; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java deleted file mode 100644 index 1d35dde7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyLINK.java +++ /dev/null @@ -1,168 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.StringFixedLength; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.jaudiotagger.tag.datatype.StringSizeTerminated; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java deleted file mode 100644 index 9fb4f2cb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMCDI.java +++ /dev/null @@ -1,107 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java deleted file mode 100644 index 3c0578d5..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMLLT.java +++ /dev/null @@ -1,102 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVIN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVIN.java deleted file mode 100644 index d8270e47..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVIN.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - -/** - * Apple defined Movement No/Total frame works the same way as the TRCK frame - * - * This is not an official standard frame, but Apple makes its own rules ! - * - * @author : Paul Taylor - */ -public class FrameBodyMVIN extends AbstractFrameBodyNumberTotal implements ID3v24FrameBody, ID3v23FrameBody -{ - /** - * Creates a new FrameBodyTALB datatype. - */ - public FrameBodyMVIN() - { - } - - public FrameBodyMVIN(FrameBodyMVIN body) - { - super(body); - } - - /** - * Creates a new FrameBodyTALB datatype. - * - * @param textEncoding - * @param text - */ - public FrameBodyMVIN(byte textEncoding, String text) - { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTALB datatype. - * - * @param byteBuffer - * @param frameSize - * @throws com.mp3.jaudiotagger.tag.InvalidTagException if unable to create framebody from buffer - */ - public FrameBodyMVIN(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - public FrameBodyMVIN(byte textEncoding, Integer movementNo, Integer movementTotal) - { - super(textEncoding, movementNo, movementTotal); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_MOVEMENT_NO; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVNM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVNM.java deleted file mode 100644 index 74b80b78..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyMVNM.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; - - -/** - * Apple defined Movement frame works the same way as regular Text Frames - * - * This is not an official standard frame, but Apple makes its own rules ! - * - */ -public class FrameBodyMVNM extends AbstractFrameBodyTextInfo implements ID3v23FrameBody, ID3v24FrameBody -{ - - /** - * Creates a new FrameBodyMVNM datatype. - */ - public FrameBodyMVNM() - { - super(); - } - - public FrameBodyMVNM(FrameBodyMVNM body) - { - super(body); - } - - /** - * Creates a new FrameBodyTRCK datatype, the value is parsed literally - * - * @param textEncoding - * @param text - */ - public FrameBodyMVNM(byte textEncoding, String text) - { - super(textEncoding, text); - } - - - /** - * Creates a new FrameBodyTRCK datatype. - * - * @param byteBuffer - * @param frameSize - * @throws java.io.IOException - * @throws com.mp3.jaudiotagger.tag.InvalidTagException - */ - public FrameBodyMVNM(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_MOVEMENT; - } - - -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java deleted file mode 100644 index 11f02a7f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyOWNE.java +++ /dev/null @@ -1,141 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java deleted file mode 100644 index d172e11b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPCNT.java +++ /dev/null @@ -1,123 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberVariableLength; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java deleted file mode 100644 index 2342b3bd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPIC.java +++ /dev/null @@ -1,278 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v22Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.ImageFormats; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.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 textstring $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 - */ -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); - } - - /** - * Set a description of the image - * - * @param description of the image - */ - public void setDescription(String description) - { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * Get a description of the image - * - * @return a description of the image - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * Set imageData - * - * @param imageData - */ - public void setImageData(byte[] imageData) - { - setObjectValue(DataTypes.OBJ_PICTURE_DATA, imageData); - } - - /** - * Get Image data - * - * @return - */ - public byte[] getImageData() - { - return (byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA); - } - - /** - * Set Picture Type - * - * @param pictureType - */ - public void setPictureType(byte pictureType) - { - setObjectValue(DataTypes.OBJ_PICTURE_TYPE, pictureType); - } - - /** - * @return picturetype - */ - public int getPictureType() - { - return ((Long) getObjectValue(DataTypes.OBJ_PICTURE_TYPE)).intValue(); - } - - - /** - * 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 new String(((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)), 0, ((byte[]) getObjectValue(DataTypes.OBJ_PICTURE_DATA)).length, StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java deleted file mode 100644 index e399726d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOPM.java +++ /dev/null @@ -1,193 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.jaudiotagger.tag.datatype.NumberVariableLength; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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. - * - *

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

- * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id$ - * 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 -{ - private static final int RATING_FIELD_SIZE = 1; - private static final int COUNTER_MINIMUM_FIELD_SIZE = 0; - public static final String MEDIA_MONKEY_NO_EMAIL = "no@email"; - /** - * 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); - } - - /** - * @param description - */ - public void setEmailToUser(String description) - { - setObjectValue(DataTypes.OBJ_EMAIL, description); - } - - /** - * @return the memail of the user who rated this - */ - public String getEmailToUser() - { - return (String) getObjectValue(DataTypes.OBJ_EMAIL); - } - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java deleted file mode 100644 index c3ecc3dc..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPOSS.java +++ /dev/null @@ -1,118 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.datatype.NumberVariableLength; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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: - * 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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java deleted file mode 100644 index a9402d50..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyPRIV.java +++ /dev/null @@ -1,144 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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' - * Owner identifier - * The private data - * - *

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

- * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id$ - */ -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); - } - - /** - * @param data - */ - public void setData(byte[] data) - { - setObjectValue(DataTypes.OBJ_DATA, data); - } - - /** - * @return - */ - public byte[] getData() - { - return (byte[]) getObjectValue(DataTypes.OBJ_DATA); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_PRIVATE; - } - - /** - * @param owner - */ - public void setOwner(String owner) - { - setObjectValue(DataTypes.OBJ_OWNER, owner); - } - - /** - * @return - */ - public String getOwner() - { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * - */ - protected void setupObjectList() - { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java deleted file mode 100644 index 9c782ef0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRBUF.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.BooleanByte; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java deleted file mode 100644 index 22d42f1f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVA2.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Relative Volume Adjustment - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java deleted file mode 100644 index 20d0d02d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVAD.java +++ /dev/null @@ -1,91 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v23Frames; - -import java.nio.ByteBuffer; - -/** - * Relative volume adjustment frame. - * - * Only partially implemented. - * - * @author : Paul Taylor - * @author : Eric Farng - * @version $Id$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java deleted file mode 100644 index 65064c34..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyRVRB.java +++ /dev/null @@ -1,160 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java deleted file mode 100644 index d208e45d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySEEK.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java deleted file mode 100644 index ec6f04bc..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySIGN.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberFixedLength; -import com.mp3.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); - } - - /** - * @param groupSymbol - */ - public void setGroupSymbol(byte groupSymbol) - { - setObjectValue(DataTypes.OBJ_GROUP_SYMBOL, groupSymbol); - } - - /** - * @return - */ - public byte getGroupSymbol() - { - if (getObjectValue(DataTypes.OBJ_GROUP_SYMBOL) != null) - { - return (Byte) getObjectValue(DataTypes.OBJ_GROUP_SYMBOL); - } - else - { - return (byte) 0; - } - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_SIGNATURE; - } - - /** - * @param signature - */ - public void setSignature(byte[] signature) - { - setObjectValue(DataTypes.OBJ_SIGNATURE, signature); - } - - /** - * @return - */ - public byte[] getSignature() - { - return (byte[]) getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java deleted file mode 100644 index 6fdffc08..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYLT.java +++ /dev/null @@ -1,247 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.EventTimingTimestampTypes; -import com.mp3.jaudiotagger.tag.id3.valuepair.SynchronisedLyricsContentType; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.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$ - */ -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; - } - - - /** - * 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); - } - - /** - * Get lyrics - * - * TODO:better format - * - * @return lyrics - */ - public byte[] getLyrics() - { - return (byte[]) this.getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java deleted file mode 100644 index cc2a1568..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodySYTC.java +++ /dev/null @@ -1,269 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.EventTimingTimestampTypes; - -import java.nio.ByteBuffer; -import java.util.*; - -/** - * 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 - * @author : Hendrik Schreiber - * @version $Id$ - */ -public class FrameBodySYTC extends AbstractID3v2FrameBody implements ID3v24FrameBody, ID3v23FrameBody -{ - public static final int MPEG_FRAMES = 1; - public static final int MILLISECONDS = 2; - - /** - * Creates a new FrameBodySYTC datatype. - */ - public FrameBodySYTC() - { - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, MILLISECONDS); - } - - /** - * @param timestampFormat - * @param tempo - */ - public FrameBodySYTC(final int timestampFormat, final byte[] tempo) - { - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, timestampFormat); - setObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST, tempo); - } - - /** - * Creates a new FrameBody from buffer - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodySYTC(final ByteBuffer byteBuffer, final int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - /** - * Copy constructor - * - * @param body - */ - public FrameBodySYTC(final FrameBodySYTC body) - { - super(body); - } - - /** - * Timestamp format for all events in this frame. - * A value of {@code 1} means absolute time (32 bit) using MPEG frames as unit. - * A value of {@code 2} means absolute time (32 bit) using milliseconds as unit. - * - * @return timestamp format - * @see #MILLISECONDS - * @see #MPEG_FRAMES - */ - public int getTimestampFormat() - { - return ((Number) getObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT)).intValue(); - } - - /** - * Sets the timestamp format. - * - * @param timestampFormat 1 for MPEG frames or 2 for milliseconds - * @see #getTimestampFormat() - */ - public void setTimestampFormat(final int timestampFormat) - { - if (EventTimingTimestampTypes.getInstanceOf().getValueForId(timestampFormat) == null) - { - throw new IllegalArgumentException("Timestamp format must be 1 or 2 (ID3v2.4, 4.7): " + timestampFormat); - } - setObjectValue(DataTypes.OBJ_TIME_STAMP_FORMAT, timestampFormat); - } - - /** - * Chronological map of tempi. - * - * @return map of tempi - */ - public Map getTempi() - { - final Map map = new LinkedHashMap(); - final List codes = (List)getObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST); - for (final SynchronisedTempoCode code : codes) - { - map.put(code.getTimestamp(), code.getTempo()); - } - return Collections.unmodifiableMap(map); - } - - /** - * Chronological list of timestamps. - * - * @return list of timestamps - */ - public List getTimestamps() - { - final List list = new ArrayList(); - final List codes = (List)getObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST); - for (final SynchronisedTempoCode code : codes) - { - list.add(code.getTimestamp()); - } - return Collections.unmodifiableList(list); - } - - /** - * Adds a tempo. - * - * @param timestamp timestamp - * @param tempo tempo - */ - public void addTempo(final long timestamp, final int tempo) - { - // make sure we don't have two tempi at the same time - removeTempo(timestamp); - final List codes = (List)getObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST); - int insertIndex = 0; - if (!codes.isEmpty() && codes.get(0).getTimestamp() <= timestamp) - { - for (final SynchronisedTempoCode code : codes) - { - final long translatedTimestamp = code.getTimestamp(); - if (timestamp < translatedTimestamp) - { - break; - } - insertIndex++; - } - } - codes.add(insertIndex, new SynchronisedTempoCode(DataTypes.OBJ_SYNCHRONISED_TEMPO, this, tempo, timestamp)); - } - - /** - * Removes a tempo at a given timestamp. - * - * @param timestamp timestamp - * @return {@code true}, if any timestamps were removed - */ - public boolean removeTempo(final long timestamp) - { - final List codes = (List)getObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST); - boolean removed = false; - for (final ListIterator iterator = codes.listIterator(); iterator.hasNext(); ) - { - final SynchronisedTempoCode code = iterator.next(); - if (timestamp == code.getTimestamp()) - { - iterator.remove(); - removed = true; - } - if (timestamp > code.getTimestamp()) - { - break; - } - } - return removed; - } - - /** - * Remove all timing codes. - */ - public void clearTempi() - { - ((List)getObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST)).clear(); - } - - @Override - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_SYNC_TEMPO; - } - - @Override - public void read(final ByteBuffer byteBuffer) throws InvalidTagException - { - super.read(byteBuffer); - - // validate input - final List codes = (List)getObjectValue(DataTypes.OBJ_SYNCHRONISED_TEMPO_LIST); - long lastTimestamp = 0; - for (final SynchronisedTempoCode code : codes) - { - if (code.getTimestamp() < lastTimestamp) - { - logger.warning("Synchronised tempo codes are not in chronological order. " + lastTimestamp + " is followed by " + code.getTimestamp() + "."); - // throw exception??? - } - lastTimestamp = code.getTimestamp(); - } - } - - @Override - protected void setupObjectList() - { - objectList.add(new NumberHashMap(DataTypes.OBJ_TIME_STAMP_FORMAT, this, EventTimingTimestampTypes.TIMESTAMP_KEY_FIELD_SIZE)); - objectList.add(new SynchronisedTempoCodeList(this)); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java deleted file mode 100644 index f847e9bf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTALB.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java deleted file mode 100644 index 17dcaac9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTBPM.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java deleted file mode 100644 index c4a55775..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCMP.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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); - } - - public boolean isCompilation() - { - return this.getText().equals(IS_COMPILATION); - } - - /** - * Creates a new FrameBodyTIT1 datatype. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTCMP(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_IS_COMPILATION; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java deleted file mode 100644 index 39f8644f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCOM.java +++ /dev/null @@ -1,86 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java deleted file mode 100644 index a2759c99..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTCON.java +++ /dev/null @@ -1,352 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.datatype.TCONString; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.ID3V2ExtendedGenreTypes; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.jaudiotagger.tag.reference.GenreTypes; - -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$ - */ -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; - } - - - /** - * Convert value to internal genre value - * - * @param value - * @return - */ - public static String convertGenericToID3v24Genre(String value) - { - try - { - //If passed id and known value use it - int genreId = Integer.parseInt(value); - if (genreId <= GenreTypes.getMaxGenreId()) - { - return String.valueOf(genreId); - } - else - { - return value; - } - } - catch (NumberFormatException nfe) - { - // If passed String, use matching integral value if can - Integer genreId = GenreTypes.getInstanceOf().getIdForName(value); - // to preserve iTunes compatibility, don't write genre ids higher than getMaxStandardGenreId, rather use string - if (genreId != null && genreId <= GenreTypes.getMaxStandardGenreId()) - { - return String.valueOf(genreId); - } - - //Covert special string values - if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.RX.getDescription())) - { - value = ID3V2ExtendedGenreTypes.RX.name(); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.CR.getDescription())) - { - value = ID3V2ExtendedGenreTypes.CR.name(); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.RX.name())) - { - value = ID3V2ExtendedGenreTypes.RX.name(); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.CR.name())) - { - value = ID3V2ExtendedGenreTypes.CR.name(); - } - } - return value; - } - - /** - * Convert value to internal genre value - * - * @param value - * @return - */ - public static String convertGenericToID3v23Genre(String value) - { - try - { - //If passed integer and in list use numeric form else use original value - int genreId = Integer.parseInt(value); - if (genreId <= GenreTypes.getMaxGenreId()) - { - return bracketWrap(String.valueOf(genreId)); - } - else - { - return value; - } - } - catch (NumberFormatException nfe) - { - //if passed text try and find integral value otherwise use text - Integer genreId = GenreTypes.getInstanceOf().getIdForName(value); - // to preserve iTunes compatibility, don't write genre ids higher than getMaxStandardGenreId, rather use string - if (genreId != null && genreId <= GenreTypes.getMaxStandardGenreId()) - { - return bracketWrap(String.valueOf(genreId)); - } - - //But special handling for these text values - if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.RX.getDescription())) - { - value = bracketWrap(ID3V2ExtendedGenreTypes.RX.name()); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.CR.getDescription())) - { - value = bracketWrap(ID3V2ExtendedGenreTypes.CR.name()); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.RX.name())) - { - value = bracketWrap(ID3V2ExtendedGenreTypes.RX.name()); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.CR.name())) - { - value = bracketWrap(ID3V2ExtendedGenreTypes.CR.name()); - } - } - return value; - } - - public static String convertGenericToID3v22Genre(String value) - { - return convertGenericToID3v23Genre(value); - } - - private static String bracketWrap(Object value) - { - return "(" + value + ')'; - } - - /** - * Convert internal v24 genre value to generic genre - * - * @param value - * @return - */ - public static String convertID3v24GenreToGeneric(String value) - { - try - { - int genreId = Integer.parseInt(value); - if (genreId <= GenreTypes.getMaxGenreId()) - { - return GenreTypes.getInstanceOf().getValueForId(genreId); - } - else - { - return value; - } - } - catch (NumberFormatException nfe) - { - if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.RX.name())) - { - value = ID3V2ExtendedGenreTypes.RX.getDescription(); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.CR.name())) - { - value = ID3V2ExtendedGenreTypes.CR.getDescription(); - } - else - { - return value; - } - } - return value; - } - - private static String checkBracketed(String value) - { - value=value.replace("(", ""); - value=value.replace(")", ""); - try - { - int genreId = Integer.parseInt(value); - if (genreId <= GenreTypes.getMaxGenreId()) { - return GenreTypes.getInstanceOf().getValueForId(genreId); - } - else - { - return value; - } - } - catch (NumberFormatException nfe) - { - if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.RX.name())) - { - value = ID3V2ExtendedGenreTypes.RX.getDescription(); - } - else if (value.equalsIgnoreCase(ID3V2ExtendedGenreTypes.CR.name())) - { - value = ID3V2ExtendedGenreTypes.CR.getDescription(); - } - else - { - return value; - } - } - return value; - } - - /** - * Convert V23 format to Generic - * - * i.e. - * - * (2) -> Country - * (RX) -> Remix - * Shoegaze -> Shoegaze - * (2)Shoegaze -> Country Shoegaze - * - * Note only handles one field so if the frame stored (2)(3) this would be two separate fields - * and would manifest itself as two different calls to this method once for (2) and once for (3) - * @param value - * @return - */ - public static String convertID3v23GenreToGeneric(String value) - { - if(value.contains(")") && value.lastIndexOf(')')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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java deleted file mode 100644 index 7b8d7d45..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDAT.java +++ /dev/null @@ -1,102 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -public class FrameBodyTDAT extends AbstractFrameBodyTextInfo implements ID3v23FrameBody -{ - public static final int DATA_SIZE = 4; - public static final int DAY_START = 0; - public static final int DAY_END = 2; - public static final int MONTH_START = 2; - public static final int MONTH_END = 4; - - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java deleted file mode 100644 index b299785a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDEN.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java deleted file mode 100644 index ed6bb9b8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDLY.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java deleted file mode 100644 index 9a18dadb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDOR.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java deleted file mode 100644 index 31d37e08..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRC.java +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v23Frames; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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 -{ - /** - * 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; - - private static SimpleDateFormat formatYearIn, formatYearOut; - private static SimpleDateFormat formatDateIn, formatDateOut, formatMonthOut; - private static SimpleDateFormat formatTimeIn, formatTimeOut, formatHoursOut; - - 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; - - 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); - - } - - /** - * Creates a new FrameBodyTDRC datatype. - */ - public FrameBodyTDRC() - { - super(); - } - - public FrameBodyTDRC(FrameBodyTDRC body) - { - super(body); - } - - /** - * Retrieve the original identifier - * @return - */ - public String getOriginalID() - { - return originalID; - } - - /** - * 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. - */ - - /** - * 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 ""; - } - - public String getFormattedText() - { - StringBuffer sb = new StringBuffer(); - if (originalID == null) - { - return this.getText(); - } - else - { - if (year != null && !(year.trim().isEmpty())) - { - 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 void setYear(String year) - { - logger.finest("Setting year to" + year); - this.year = year; - } - - public void setTime(String time) - { - logger.finest("Setting time to:" + time); - this.time = time; - } - - - public void setDate(String date) - { - logger.finest("Setting date to:" + date); - this.date = date; - } - - public String getYear() - { - return year; - } - - public String getTime() - { - return time; - } - - public String getDate() - { - return date; - } - - /** - * 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 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(); - } - - public 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); - } - } - } - - /** - * 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); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java deleted file mode 100644 index 64459f04..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDRL.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java deleted file mode 100644 index db3eae00..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTDTG.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java deleted file mode 100644 index a1d82da6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTENC.java +++ /dev/null @@ -1,84 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java deleted file mode 100644 index f084edca..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTEXT.java +++ /dev/null @@ -1,84 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java deleted file mode 100644 index f14c5b2a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTFLT.java +++ /dev/null @@ -1,99 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java deleted file mode 100644 index a1879c59..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIME.java +++ /dev/null @@ -1,94 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java deleted file mode 100644 index aa69c360..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIPL.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * People List - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.StandardIPLSKey; - -import java.nio.ByteBuffer; -import java.util.List; - - -/** - * 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 AbstractFrameBodyPairs implements ID3v24FrameBody -{ - //Standard function names, code now uses StandardIPLSKey but kept for backwards compatability - public static final String ENGINEER = StandardIPLSKey.ENGINEER.getKey(); - public static final String MIXER = StandardIPLSKey.MIXER.getKey(); - public static final String DJMIXER = StandardIPLSKey.DJMIXER.getKey(); - public static final String PRODUCER = StandardIPLSKey.PRODUCER.getKey(); - public static final String ARRANGER = StandardIPLSKey.ARRANGER.getKey(); - - /** - * Creates a new FrameBodyTIPL datatype. - */ - public FrameBodyTIPL() - { - super(); - } - - /** - * Creates a new FrameBodyTIPL data type. - * - * @param textEncoding - * @param text - */ - public FrameBodyTIPL(byte textEncoding, String text) - { - super(textEncoding, 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()); - } - - - /** - * Construct from a set of pairs - * - * @param textEncoding - * @param pairs - */ - public FrameBodyTIPL(byte textEncoding, List pairs) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - PairedTextEncodedStringNullTerminated.ValuePairs values = new PairedTextEncodedStringNullTerminated.ValuePairs(); - for(Pair next:pairs) - { - values.add(next); - } - setObjectValue(DataTypes.OBJ_TEXT, values); - } - - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_INVOLVED_PEOPLE; - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java deleted file mode 100644 index 6ebbb68a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT1.java +++ /dev/null @@ -1,84 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java deleted file mode 100644 index 4e50fbe9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT2.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java deleted file mode 100644 index 57b7062e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTIT3.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java deleted file mode 100644 index 68e63ff4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTKEY.java +++ /dev/null @@ -1,95 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.java deleted file mode 100644 index 5e97bea3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLAN.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java deleted file mode 100644 index 9866072d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTLEN.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java deleted file mode 100644 index 48514770..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMCL.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser - * General Public License as published by the Free Software Foundation; either version 2.1 of the License, - * or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * People List - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.Pair; -import com.mp3.jaudiotagger.tag.datatype.PairedTextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; - -import java.nio.ByteBuffer; -import java.util.List; - - -/** - * The 'Musician credits list' is intended as a mapping between instruments and the musician that played it. Every odd field is an - * instrument and every even is an artist or a comma delimited list of artists. - * - */ -public class FrameBodyTMCL extends AbstractFrameBodyPairs implements ID3v24FrameBody -{ - /** - * Creates a new FrameBodyTMCL datatype. - */ - public FrameBodyTMCL() - { - super(); - } - - /** - * Creates a new FrameBodyTMCL data type. - * - * @param textEncoding - * @param text - */ - public FrameBodyTMCL(byte textEncoding, String text) - { - super(textEncoding, text); - } - - /** - * Creates a new FrameBodyTMCL data type. - * - * @param byteBuffer - * @param frameSize - * @throws InvalidTagException - */ - public FrameBodyTMCL(ByteBuffer byteBuffer, int frameSize) throws InvalidTagException - { - super(byteBuffer, frameSize); - } - - /** - * Convert from V3 to V4 Frame - * - * @param body - */ - public FrameBodyTMCL(FrameBodyIPLS body) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, body.getTextEncoding()); - setObjectValue(DataTypes.OBJ_TEXT, body.getPairing()); - } - - /** - * Construct from a set of pairs - * - * @param textEncoding - * @param pairs - */ - public FrameBodyTMCL(byte textEncoding, List pairs) - { - setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding); - PairedTextEncodedStringNullTerminated.ValuePairs values = new PairedTextEncodedStringNullTerminated.ValuePairs(); - for(Pair next:pairs) - { - values.add(next); - } - setObjectValue(DataTypes.OBJ_TEXT, values); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_MUSICIAN_CREDITS; - } - -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java deleted file mode 100644 index a39ecc2c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMED.java +++ /dev/null @@ -1,159 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java deleted file mode 100644 index ac52e6b6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTMOO.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java deleted file mode 100644 index bd77e2ec..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOAL.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java deleted file mode 100644 index 654e98d0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOFN.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java deleted file mode 100644 index 01fcc075..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOLY.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java deleted file mode 100644 index fcd51428..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOPE.java +++ /dev/null @@ -1,84 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java deleted file mode 100644 index 40313e14..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTORY.java +++ /dev/null @@ -1,103 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v23Frames; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java deleted file mode 100644 index 74feef54..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTOWN.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java deleted file mode 100644 index dd30ae9a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE1.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java deleted file mode 100644 index f7871ff0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE2.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java deleted file mode 100644 index 86c7cd29..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE3.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java deleted file mode 100644 index dda85e59..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPE4.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java deleted file mode 100644 index 2ac3c5e6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPOS.java +++ /dev/null @@ -1,135 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; - -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$ - */ -public class FrameBodyTPOS extends AbstractFrameBodyNumberTotal implements ID3v23FrameBody, ID3v24FrameBody -{ - /** - * Creates a new FrameBodyTRCK datatype. - */ - public FrameBodyTPOS() - { - super(); - } - - 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) - { - super(textEncoding, text); - } - - public FrameBodyTPOS(byte textEncoding, Integer discNo,Integer discTotal) - { - super(textEncoding, 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 Integer getDiscNo() - { - return getNumber(); - } - - public String getDiscNoAsText() - { - return getNumberAsText(); - } - - public void setDiscNo(Integer discNo) - { - setNumber(discNo); - } - - public void setDiscNo(String discNo) - { - setNumber(discNo); - } - - - public Integer getDiscTotal() - { - return getTotal(); - } - - public String getDiscTotalAsText() - { - return getTotalAsText(); - } - - public void setDiscTotal(Integer discTotal) - { - setTotal(discTotal); - } - - public void setDiscTotal(String discTotal) - { - setTotal(discTotal); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java deleted file mode 100644 index bd47f4f3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPRO.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java deleted file mode 100644 index f8602470..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTPUB.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java deleted file mode 100644 index d2658a09..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRCK.java +++ /dev/null @@ -1,144 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.PartOfSet; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; - -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$ - */ -public class FrameBodyTRCK extends AbstractFrameBodyNumberTotal implements ID3v23FrameBody, ID3v24FrameBody -{ - /** - * Creates a new FrameBodyTRCK datatype. - */ - public FrameBodyTRCK() - { - super(); - } - - 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) - { - super(textEncoding, text); - } - - public FrameBodyTRCK(byte textEncoding, Integer trackNo,Integer trackTotal) - { - super(textEncoding, 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); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_TRACK; - } - - public Integer getTrackNo() - { - return getNumber(); - } - - public String getTrackNoAsText() - { - return getNumberAsText(); - } - - public void setTrackNo(Integer trackNo) - { - setNumber(trackNo); - } - - public void setTrackNo(String trackNo) - { - setNumber(trackNo); - } - - public Integer getTrackTotal() - { - return getTotal(); - } - - public String getTrackTotalAsText() - { - return getTotalAsText(); - } - - - public void setTrackTotal(Integer trackTotal) - { - setTotal(trackTotal); - } - - public void setTrackTotal(String trackTotal) - { - setTotal(trackTotal); - } - - public void setText(String text) - { - setObjectValue(DataTypes.OBJ_TEXT, new PartOfSet.PartOfSetValue(text)); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java deleted file mode 100644 index 943d2fbf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRDA.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java deleted file mode 100644 index e325a5eb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSN.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java deleted file mode 100644 index 3024f793..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTRSO.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java deleted file mode 100644 index 1902bfa5..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSIZ.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java deleted file mode 100644 index 748f40f7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSO2.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java deleted file mode 100644 index 21fef2f4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOA.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java deleted file mode 100644 index c2ad5951..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOC.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java deleted file mode 100644 index 2d6255be..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOP.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java deleted file mode 100644 index 2c7a72a0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSOT.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java deleted file mode 100644 index 0638d0b0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSRC.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java deleted file mode 100644 index 38e1aa29..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSSE.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java deleted file mode 100644 index 5139bbd8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTSST.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java deleted file mode 100644 index 2688579f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTXXX.java +++ /dev/null @@ -1,254 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.NumberHashMap; -import com.mp3.jaudiotagger.tag.datatype.TextEncodedStringNullTerminated; -import com.mp3.jaudiotagger.tag.datatype.TextEncodedStringSizeTerminated; -import com.mp3.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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 ACOUSTID_FINGERPRINT = "Acoustid Fingerprint"; - public static final String ACOUSTID_ID = "Acoustid Id"; - public static final String AMAZON_ASIN = "ASIN"; - public static final String ARRANGER_SORT = "ARRANGER_SORT"; - public static final String ARTISTS = "ARTISTS"; - public static final String ARTISTS_SORT = "ARTISTS_SORT"; - public static final String ALBUM_ARTISTS = "ALBUM_ARTISTS"; - public static final String ALBUM_ARTISTS_SORT = "ALBUM_ARTISTS_SORT"; - public static final String BARCODE = "BARCODE"; - public static final String CATALOG_NO = "CATALOGNUMBER"; - public static final String CHOIR = "CHOIR"; - public static final String CHOIR_SORT = "CHOIR_SORT"; - public static final String CLASSICAL_CATALOG = "CLASSICAL_CATALOG"; - public static final String CLASSICAL_NICKNAME = "CLASSICAL_NICKNAME"; - public static final String CONDUCTOR_SORT = "CONDUCTOR_SORT"; - public static final String COUNTRY = "Country"; - public static final String ENSEMBLE = "ENSEMBLE"; - public static final String ENSEMBLE_SORT = "ENSEMBLE_SORT"; - public static final String FBPM = "FBPM"; - public static final String GROUP = "GROUP"; - public static final String INSTRUMENT = "INSTRUMENT"; - public static final String IS_CLASSICAL = "IS_CLASSICAL"; - public static final String IS_SOUNDTRACK = "IS_SOUNDTRACK"; - public static final String MOOD = "MOOD"; //ID3 v23 only - public static final String MOOD_ACOUSTIC = "MOOD_ACOUSTIC"; - public static final String MOOD_AGGRESSIVE = "MOOD_AGGRESSIVE"; - public static final String MOOD_AROUSAL = "MOOD_AROUSAL"; - public static final String MOOD_DANCEABILITY = "MOOD_DANCEABILITY"; - public static final String MOOD_ELECTRONIC = "MOOD_ELECTRONIC"; - public static final String MOOD_HAPPY = "MOOD_HAPPY"; - public static final String MOOD_INSTRUMENTAL = "MOOD_INSTRUMENTAL"; - public static final String MOOD_PARTY = "MOOD_PARTY"; - public static final String MOOD_RELAXED = "MOOD_RELAXED"; - public static final String MOOD_SAD = "MOOD_SAD"; - public static final String MOOD_VALENCE = "MOOD_VALENCE"; - public static final String MUSICBRAINZ_ALBUMID = "MusicBrainz Album Id"; - public static final String MUSICBRAINZ_ALBUM_ARTISTID = "MusicBrainz Album Artist Id"; - public static final String MUSICBRAINZ_ALBUM_COUNTRY = "MusicBrainz Album Release Country"; - public static final String MUSICBRAINZ_ALBUM_STATUS = "MusicBrainz Album Status"; - public static final String MUSICBRAINZ_ALBUM_TYPE = "MusicBrainz Album Type"; - public static final String MUSICBRAINZ_ARTISTID = "MusicBrainz Artist Id"; - public static final String MUSICBRAINZ_DISCID = "MusicBrainz Disc 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_RELEASE_TRACKID = "MusicBrainz Release Track Id"; - public static final String MUSICBRAINZ_WORK_COMPOSITION = "MUSICBRAINZ_WORK_COMPOSITION"; - public static final String MUSICBRAINZ_WORK_COMPOSITION_ID = "MUSICBRAINZ_WORK_COMPOSITION_ID"; - public static final String MUSICBRAINZ_WORKID = "MusicBrainz Work Id"; - public static final String MUSICBRAINZ_WORK = "MUSICBRAINZ_WORK"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL1 = "MUSICBRAINZ_WORK_PART_LEVEL1"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL1_ID = "MUSICBRAINZ_WORK_PART_LEVEL1_ID"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL1_TYPE = "MUSICBRAINZ_WORK_PART_LEVEL1_TYPE"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL2 = "MUSICBRAINZ_WORK_PART_LEVEL2"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL2_ID = "MUSICBRAINZ_WORK_PART_LEVEL2_ID"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL2_TYPE = "MUSICBRAINZ_WORK_PART_LEVEL2_TYPE"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL3 = "MUSICBRAINZ_WORK_PART_LEVEL3"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL3_ID = "MUSICBRAINZ_WORK_PART_LEVEL3_ID"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL3_TYPE = "MUSICBRAINZ_WORK_PART_LEVEL3_TYPE"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL4 = "MUSICBRAINZ_WORK_PART_LEVEL4"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL4_ID = "MUSICBRAINZ_WORK_PART_LEVEL4_ID"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL4_TYPE = "MUSICBRAINZ_WORK_PART_LEVEL4_TYPE"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL5 = "MUSICBRAINZ_WORK_PART_LEVEL5"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL5_ID = "MUSICBRAINZ_WORK_PART_LEVEL5_ID"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL5_TYPE = "MUSICBRAINZ_WORK_PART_LEVEL5_TYPE"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL6 = "MUSICBRAINZ_WORK_PART_LEVEL6"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL6_ID = "MUSICBRAINZ_WORK_PART_LEVEL6_ID"; - public static final String MUSICBRAINZ_WORK_PART_LEVEL6_TYPE = "MUSICBRAINZ_WORK_PART_LEVEL6_TYPE"; - public static final String MUSICIP_ID = "MusicIP PUID"; - public static final String OPUS = "OPUS"; - public static final String ORCHESTRA = "ORCHESTRA"; - public static final String ORCHESTRA_SORT = "ORCHESTRA_SORT"; - public static final String PART = "PART"; - public static final String PART_NUMBER = "PARTNUMBER"; - public static final String PART_TYPE = "PART_TYPE"; - public static final String PERFORMER_NAME = "PERFORMER_NAME"; - public static final String PERFORMER_NAME_SORT = "PERFORMER_NAME_SORT"; - public static final String PERIOD = "PERIOD"; - public static final String RANKING = "RANKING"; - public static final String SCRIPT = "Script"; - public static final String SINGLE_DISC_TRACK_NO = "SINGLE_DISC_TRACK_NO"; - public static final String TAGS = "TAGS"; - public static final String TIMBRE = "TIMBRE_BRIGHTNESS"; - public static final String TITLE_MOVEMENT = "TITLE_MOVEMENT"; - public static final String TONALITY = "TONALITY"; - public static final String WORK = "WORK"; - public static final String WORK_TYPE = "WORK_TYPE"; - - //used by Foobar 20000 - public static final String ALBUM_ARTIST = "ALBUM ARTIST"; - - /** - * 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); - } - - /** - * Set the description field - * - * @param description - */ - public void setDescription(String description) - { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * @return the description field - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java deleted file mode 100644 index 68c75579..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyTYER.java +++ /dev/null @@ -1,95 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.id3.ID3v23Frames; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java deleted file mode 100644 index fab90394..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUFID.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Represents a Unique File ID for the file which relates - * to an external database. - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.jaudiotagger.tag.datatype.DataTypes; -import com.mp3.jaudiotagger.tag.datatype.StringNullTerminated; -import com.mp3.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; - } - - /** - * 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 url of the the database that this ufid is stored in - */ - public String getOwner() - { - return (String) getObjectValue(DataTypes.OBJ_OWNER); - } - - /** - * Set the unique identifier (within the owners domain) - * - * @param uniqueIdentifier - */ - public void setUniqueIdentifier(byte[] uniqueIdentifier) - { - setObjectValue(DataTypes.OBJ_DATA, uniqueIdentifier); - } - - /** - * @return the unique identifier (within the owners domain) - */ - public byte[] getUniqueIdentifier() - { - return (byte[]) getObjectValue(DataTypes.OBJ_DATA); - } - - protected void setupObjectList() - { - objectList.add(new StringNullTerminated(DataTypes.OBJ_OWNER, this)); - objectList.add(new ByteArraySizeTerminated(DataTypes.OBJ_DATA, this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSER.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSER.java deleted file mode 100644 index 196548a9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSER.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java deleted file mode 100644 index 45f187e5..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUSLT.java +++ /dev/null @@ -1,244 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3TextEncodingConversion; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.jaudiotagger.tag.id3.valuepair.TextEncoding; -import com.mp3.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$ - */ -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(); - } - - - /** - * Set a description field - * - * @param description - */ - public void setDescription(String description) - { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * Get a description field - * - * @return description - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_DESCRIPTION); - } - - /** - * The ID3v2 frame identifier - * - * @return the ID3v2 frame identifier for this frame type - */ - public String getIdentifier() - { - return ID3v24Frames.FRAME_ID_UNSYNC_LYRICS; - } - - /** - * Set the language field - * - * @param language - */ - public void setLanguage(String language) - { - setObjectValue(DataTypes.OBJ_LANGUAGE, language); - } - - /** - * Get the language field - * - * @return language - */ - public String getLanguage() - { - return (String) getObjectValue(DataTypes.OBJ_LANGUAGE); - } - - /** - * Set the lyric field - * - * @param lyric - */ - public void setLyric(String lyric) - { - setObjectValue(DataTypes.OBJ_LYRICS, lyric); - } - - /** - * Get the lyric field - * - * @return lyrics - */ - public String getLyric() - { - return (String) getObjectValue(DataTypes.OBJ_LYRICS); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java deleted file mode 100644 index d48bfd6d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyUnsupported.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Frame that is not currently suported by this application - * - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.ByteArraySizeTerminated; -import com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java deleted file mode 100644 index 2d336646..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOM.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java deleted file mode 100644 index ac0d272d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWCOP.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java deleted file mode 100644 index ef8c3465..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAF.java +++ /dev/null @@ -1,81 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java deleted file mode 100644 index 529c3415..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAR.java +++ /dev/null @@ -1,83 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java deleted file mode 100644 index 27a8dae9..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWOAS.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java deleted file mode 100644 index 88f3c899..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWORS.java +++ /dev/null @@ -1,81 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java deleted file mode 100644 index f05e145a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPAY.java +++ /dev/null @@ -1,81 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java deleted file mode 100644 index e9bcb097..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWPUB.java +++ /dev/null @@ -1,82 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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$ - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java deleted file mode 100644 index 1c427f06..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyWXXX.java +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Represents a user defined URL,must also privide a description - * - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.datatype.*; -import com.mp3.jaudiotagger.tag.id3.ID3v24Frames; -import com.mp3.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); - } - - /** - * Set a description of the hyperlink - * - * @param description - */ - public void setDescription(String description) - { - setObjectValue(DataTypes.OBJ_DESCRIPTION, description); - } - - /** - * @return a description of the hyperlink - */ - public String getDescription() - { - return (String) getObjectValue(DataTypes.OBJ_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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java deleted file mode 100644 index b65e1d84..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOA.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java deleted file mode 100644 index add92d92..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOP.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java deleted file mode 100644 index cf67f9d8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/FrameBodyXSOT.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.framebody; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java deleted file mode 100644 index b94ea3d0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v22FrameBody.java +++ /dev/null @@ -1,27 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a framebody used in ID3v22Tags. - * - * @author Paul Taylor - * @version $Id$ - */ -public interface ID3v22FrameBody -{ - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java deleted file mode 100644 index cd5ed6cf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v23FrameBody.java +++ /dev/null @@ -1,27 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a framebody used in ID3v23Tags. - * - * @author Paul Taylor - * @version $Id$ - */ -public interface ID3v23FrameBody -{ - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java deleted file mode 100644 index 2062b28a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v24FrameBody.java +++ /dev/null @@ -1,27 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a framebody used in ID3v24Tags. - * - * @author Paul Taylor - * @version $Id$ - */ -public interface ID3v24FrameBody -{ - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java deleted file mode 100644 index f2732528..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/framebody/ID3v2ChapterFrameBody.java +++ /dev/null @@ -1,27 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package com.mp3.jaudiotagger.tag.id3.framebody; - -/** - * Indicates that this is a frame used in ID3v2 Chapter Tags. - * - * @author Marc Gimpel, Horizon Wimba S.A. - * @version $Id$ - */ -public interface ID3v2ChapterFrameBody -{ - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ID3Rating.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ID3Rating.java deleted file mode 100644 index 5fad261b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ID3Rating.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.reference; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ITunesRating.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ITunesRating.java deleted file mode 100644 index cad5c276..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/ITunesRating.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.mp3.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 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; - } - - public static ID3Rating getInstance() - { - if(rating==null) - { - rating=new ITunesRating(); - } - return rating; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java deleted file mode 100644 index ec38c86a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaMonkeyPlayerRating.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.mp3.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 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=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; - } - - public static ID3Rating getInstance() - { - if(rating==null) - { - rating=new MediaMonkeyPlayerRating(); - } - return rating; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaPlayerRating.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaPlayerRating.java deleted file mode 100644 index 75237344..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/reference/MediaPlayerRating.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.mp3.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 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=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; - } - - public static ID3Rating getInstance() - { - if(rating==null) - { - rating=new MediaPlayerRating(); - } - return rating; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ChannelTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ChannelTypes.java deleted file mode 100644 index 0e97f7ab..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ChannelTypes.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Channel type used by - */ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class ChannelTypes extends AbstractIntStringValuePair -{ - private static ChannelTypes channelTypes; - - public static ChannelTypes getInstanceOf() - { - if (channelTypes == null) - { - channelTypes = new ChannelTypes(); - } - return 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java deleted file mode 100644 index c18e5d82..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTimestampTypes.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class EventTimingTimestampTypes extends AbstractIntStringValuePair -{ - - private static EventTimingTimestampTypes eventTimingTimestampTypes; - - public static EventTimingTimestampTypes getInstanceOf() - { - if (eventTimingTimestampTypes == null) - { - eventTimingTimestampTypes = new EventTimingTimestampTypes(); - } - return eventTimingTimestampTypes; - } - - public static final int TIMESTAMP_KEY_FIELD_SIZE = 1; - - private EventTimingTimestampTypes() - { - idToValue.put(1, "Absolute time using MPEG [MPEG] frames as unit"); - idToValue.put(2, "Absolute time using milliseconds as unit"); - - createMaps(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java deleted file mode 100644 index 676e3344..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/EventTimingTypes.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class EventTimingTypes extends AbstractIntStringValuePair -{ - private static EventTimingTypes eventTimingTypes; - - public static EventTimingTypes getInstanceOf() - { - if (eventTimingTypes == null) - { - eventTimingTypes = new EventTimingTypes(); - } - return 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"); - - // 0x17-0xDF reserved for future use - - idToValue.put(0xE0, "Not predefined synch 0"); - idToValue.put(0xE1, "Not predefined synch 1"); - idToValue.put(0xE2, "Not predefined synch 2"); - idToValue.put(0xE3, "Not predefined synch 3"); - idToValue.put(0xE4, "Not predefined synch 4"); - idToValue.put(0xE5, "Not predefined synch 5"); - idToValue.put(0xE6, "Not predefined synch 6"); - idToValue.put(0xE7, "Not predefined synch 7"); - idToValue.put(0xE8, "Not predefined synch 8"); - idToValue.put(0xE9, "Not predefined synch 9"); - idToValue.put(0xEA, "Not predefined synch A"); - idToValue.put(0xEB, "Not predefined synch B"); - idToValue.put(0xEC, "Not predefined synch C"); - idToValue.put(0xED, "Not predefined synch D"); - idToValue.put(0xEE, "Not predefined synch E"); - idToValue.put(0xEF, "Not predefined synch F"); - - // 0xF0-0xFC reserved for future use - - idToValue.put(0xFD, "Audio end (start of silence)"); - idToValue.put(0xFE, "Audio file ends"); - - createMaps(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3NumberTotalFields.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3NumberTotalFields.java deleted file mode 100644 index 5f5bf4db..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3NumberTotalFields.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.tag.FieldKey; - -import java.util.EnumSet; - -/** - * Created by Paul on 09/11/2016. - */ -public class ID3NumberTotalFields -{ - private static EnumSet numberField = EnumSet.noneOf(FieldKey.class); - private static EnumSet totalField = EnumSet.noneOf(FieldKey.class); - - static - { - numberField.add(FieldKey.TRACK); - numberField.add(FieldKey.DISC_NO); - numberField.add(FieldKey.MOVEMENT_NO); - - totalField.add(FieldKey.TRACK_TOTAL); - totalField.add(FieldKey.DISC_TOTAL); - totalField.add(FieldKey.MOVEMENT_TOTAL); - } - - public static boolean isNumber(FieldKey fieldKey) - { - return numberField.contains(fieldKey); - } - - public static boolean isTotal(FieldKey fieldKey) - { - return totalField.contains(fieldKey); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java deleted file mode 100644 index efcc2660..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ID3V2ExtendedGenreTypes.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ImageFormats.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ImageFormats.java deleted file mode 100644 index 0617ac2c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ImageFormats.java +++ /dev/null @@ -1,263 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * This class maps from v2.2 Image formats (PIC) to v2.3/v2.4 Mimetypes (APIC) and - * vice versa. - */ -package com.mp3.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. coverImage.getImageData() - * - * - * 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 Can be FF D8 FF DB (samsung) , FF D8 FF E0 (standard) or FF D8 FF E1 or some other formats - //see http://www.garykessler.net/library/file_sigs.html - //FF D8 is SOI Marker, FFE0 or FFE1 is JFIF Marker - return (0xff == (data[0] & 0xff)) && (0xd8 == (data[1] & 0xff)) && (0xff == (data[2] & 0xff)) && (0xdb <= (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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java deleted file mode 100644 index 8a42ebf5..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/InterpolationTypes.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -public class InterpolationTypes extends AbstractIntStringValuePair -{ - private static InterpolationTypes interpolationTypes; - - public static InterpolationTypes getInstanceOf() - { - if (interpolationTypes == null) - { - interpolationTypes = new InterpolationTypes(); - } - return interpolationTypes; - } - - private InterpolationTypes() - { - idToValue.put(0, "Band"); - idToValue.put(1, "Linear"); - createMaps(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/MusicianCredits.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/MusicianCredits.java deleted file mode 100644 index 014e33bd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/MusicianCredits.java +++ /dev/null @@ -1,823 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import java.util.HashSet; -import java.util.Set; - -/** - * List of musician credit keys that can be used when converting from IPLS to TIPL/TMCL to - * signify pair should be allocated to TMCL - */ -public class MusicianCredits -{ - private static Set musicianCredits = new HashSet(); - - static - { - musicianCredits.add("12 string guitar"); - musicianCredits.add("17-string koto"); - musicianCredits.add("accompaniment"); - musicianCredits.add("accordina"); - musicianCredits.add("accordion"); - musicianCredits.add("acoustic"); - musicianCredits.add("additional"); - musicianCredits.add("aeolian harp"); - musicianCredits.add("afoxé"); - musicianCredits.add("afuche / cabasa"); - musicianCredits.add("agogô"); - musicianCredits.add("ajaeng"); - musicianCredits.add("akete"); - musicianCredits.add("alfaia"); - musicianCredits.add("algozey"); - musicianCredits.add("alphorn"); - musicianCredits.add("alto"); - musicianCredits.add("amadinda"); - musicianCredits.add("ankle rattlers"); - musicianCredits.add("anvil"); - musicianCredits.add("appalachian dulcimer"); - musicianCredits.add("archlute"); - musicianCredits.add("archtop guitar"); - musicianCredits.add("arghul"); - musicianCredits.add("assistant"); - musicianCredits.add("associate"); - musicianCredits.add("atabaque"); - musicianCredits.add("atarigane"); - musicianCredits.add("autoharp"); - musicianCredits.add("background vocals"); - musicianCredits.add("baglama"); - musicianCredits.add("bagpipe"); - musicianCredits.add("band"); - musicianCredits.add("bajo sexto"); - musicianCredits.add("balafon"); - musicianCredits.add("balalaika"); - musicianCredits.add("baltic psalteries"); - musicianCredits.add("bamboo angklung"); - musicianCredits.add("bandoneón"); - musicianCredits.add("bandora"); - musicianCredits.add("bandura"); - musicianCredits.add("bandurria"); - musicianCredits.add("bangu"); - musicianCredits.add("banhu"); - musicianCredits.add("banjitar"); - musicianCredits.add("banjo"); - musicianCredits.add("bansuri"); - musicianCredits.add("baritone"); - musicianCredits.add("baroque"); - musicianCredits.add("barrel drum"); - musicianCredits.add("barrel organ"); - musicianCredits.add("baryton"); - musicianCredits.add("bass"); - musicianCredits.add("batá drum"); - musicianCredits.add("bawu"); - musicianCredits.add("bayan"); - musicianCredits.add("bazooka"); - musicianCredits.add("bellow-blown bagpipes"); - musicianCredits.add("bells"); - musicianCredits.add("bell tree"); - musicianCredits.add("bendir"); - musicianCredits.add("berimbau"); - musicianCredits.add("bicycle bell"); - musicianCredits.add("bin-sasara"); - musicianCredits.add("birch lur"); - musicianCredits.add("biwa"); - musicianCredits.add("boatswain's pipe"); - musicianCredits.add("bodhrán"); - musicianCredits.add("body percussion"); - musicianCredits.add("bolon"); - musicianCredits.add("bombarde"); - musicianCredits.add("bones"); - musicianCredits.add("bongos"); - musicianCredits.add("bouzouki"); - musicianCredits.add("bowed piano"); - musicianCredits.add("bowed psaltery"); - musicianCredits.add("bowed string instruments"); - musicianCredits.add("brass"); - musicianCredits.add("bronze lur"); - musicianCredits.add("brushes"); - musicianCredits.add("bugle"); - musicianCredits.add("buisine"); - musicianCredits.add("buk"); - musicianCredits.add("bulbul tarang"); - musicianCredits.add("bullroarer"); - musicianCredits.add("button accordion"); - musicianCredits.add("buzuq"); - musicianCredits.add("cajón"); - musicianCredits.add("calabash"); - musicianCredits.add("calliope"); - musicianCredits.add("cancelled"); - musicianCredits.add("carillon"); - musicianCredits.add("castanets"); - musicianCredits.add("cavaquinho"); - musicianCredits.add("caxixi"); - musicianCredits.add("celeste"); - musicianCredits.add("celesta"); - musicianCredits.add("cello"); - musicianCredits.add("cembalet"); - musicianCredits.add("çevgen"); - musicianCredits.add("chacha"); - musicianCredits.add("chainsaw"); - musicianCredits.add("chakhe"); - musicianCredits.add("chalumeau"); - musicianCredits.add("chamberlin"); - musicianCredits.add("chamber"); - musicianCredits.add("chande"); - musicianCredits.add("chanzy"); - musicianCredits.add("chap"); - musicianCredits.add("chapman stick"); - musicianCredits.add("charango"); - musicianCredits.add("chau gong"); - musicianCredits.add("chikuzen biwa"); - musicianCredits.add("chime bar"); - musicianCredits.add("chimes"); - musicianCredits.add("ching"); - musicianCredits.add("chitra veena"); - musicianCredits.add("choir"); - musicianCredits.add("chromatic button accordion"); - musicianCredits.add("chromatic harmonica"); - musicianCredits.add("citole"); - musicianCredits.add("cittern"); - musicianCredits.add("cizhonghu"); - musicianCredits.add("clarinet"); - musicianCredits.add("classical guitar"); - musicianCredits.add("classical kemençe"); - musicianCredits.add("claves"); - musicianCredits.add("clavichord"); - musicianCredits.add("clavinet"); - musicianCredits.add("claviola"); - musicianCredits.add("co"); - musicianCredits.add("cò ke"); - musicianCredits.add("concert flute"); - musicianCredits.add("concert harp"); - musicianCredits.add("concertina"); - musicianCredits.add("conch"); - musicianCredits.add("congas"); - musicianCredits.add("continuum"); - musicianCredits.add("contrabass clarinet"); - musicianCredits.add("contrabassoon"); - musicianCredits.add("contrabass recorder"); - musicianCredits.add("contrabass saxophone"); - musicianCredits.add("contralto vocals"); - musicianCredits.add("cornamuse"); - musicianCredits.add("cornet"); - musicianCredits.add("cornett"); - musicianCredits.add("countertenor vocals"); - musicianCredits.add("cover"); - musicianCredits.add("cowbell"); - musicianCredits.add("craviola"); - musicianCredits.add("cretan lyra"); - musicianCredits.add("cristal baschet"); - musicianCredits.add("crotales"); - musicianCredits.add("crumhorn"); - musicianCredits.add("crwth"); - musicianCredits.add("cuatro"); - musicianCredits.add("cuíca"); - musicianCredits.add("cümbüş"); - musicianCredits.add("cylindrical drum"); - musicianCredits.add("cymbals"); - musicianCredits.add("cymbalum"); - musicianCredits.add("daegeum"); - musicianCredits.add("daf"); - musicianCredits.add("daire"); - musicianCredits.add("daluo"); - musicianCredits.add("đàn bầu"); - musicianCredits.add("đàn nguyệt"); - musicianCredits.add("đàn nhị"); - musicianCredits.add("đàn tam"); - musicianCredits.add("đàn tam thập lục"); - musicianCredits.add("đàn tranh"); - musicianCredits.add("đàn tứ"); - musicianCredits.add("đàn tứ dây"); - musicianCredits.add("đàn tỳ bà"); - musicianCredits.add("darbuka"); - musicianCredits.add("daruan"); - musicianCredits.add("davul"); - musicianCredits.add("denis d'or"); - musicianCredits.add("descant recorder / soprano recorder"); - musicianCredits.add("dhol"); - musicianCredits.add("dholak"); - musicianCredits.add("diatonic accordion / melodeon"); - musicianCredits.add("diddley bow"); - musicianCredits.add("didgeridoo"); - musicianCredits.add("dilruba"); - musicianCredits.add("đing buốt"); - musicianCredits.add("đing năm"); - musicianCredits.add("ding tac ta"); - musicianCredits.add("disk drive"); - musicianCredits.add("diyingehu"); - musicianCredits.add("dizi"); - musicianCredits.add("djembe"); - musicianCredits.add("dobro"); - musicianCredits.add("dohol"); - musicianCredits.add("dolceola"); - musicianCredits.add("dombra"); - musicianCredits.add("domra"); - musicianCredits.add("donso ngɔni"); - musicianCredits.add("doshpuluur"); - musicianCredits.add("double bass"); - musicianCredits.add("double reed"); - musicianCredits.add("doyra"); - musicianCredits.add("dramyin"); - musicianCredits.add("drum machine"); - musicianCredits.add("drums"); - musicianCredits.add("drumset"); - musicianCredits.add("dubreq stylophone"); - musicianCredits.add("duck call"); - musicianCredits.add("duct flute"); - musicianCredits.add("duduk"); - musicianCredits.add("dulce melos"); - musicianCredits.add("dulcian"); - musicianCredits.add("dulzaina"); - musicianCredits.add("dunun"); - musicianCredits.add("dutar"); - musicianCredits.add("duxianqin"); - musicianCredits.add("ebow"); - musicianCredits.add("effects"); - musicianCredits.add("e-flat clarinet"); - musicianCredits.add("ektara"); - musicianCredits.add("electric bass guitar"); - musicianCredits.add("electric cello"); - musicianCredits.add("electric fretless guitar"); - musicianCredits.add("electric grand piano"); - musicianCredits.add("electric guitar"); - musicianCredits.add("electric harp"); - musicianCredits.add("electric lap steel guitar"); - musicianCredits.add("electric piano"); - musicianCredits.add("electric sitar"); - musicianCredits.add("electric upright bass"); - musicianCredits.add("electric viola"); - musicianCredits.add("electric violin"); - musicianCredits.add("electronic drum set"); - musicianCredits.add("electronic instruments"); - musicianCredits.add("electronic organ"); - musicianCredits.add("electronic wind instrument"); - musicianCredits.add("emeritus"); - musicianCredits.add("end-blown flute"); - musicianCredits.add("english horn"); - musicianCredits.add("erhu"); - musicianCredits.add("esraj"); - musicianCredits.add("euphonium"); - musicianCredits.add("ewi"); - musicianCredits.add("executive"); - musicianCredits.add("farfisa"); - musicianCredits.add("fiddle"); - musicianCredits.add("fife"); - musicianCredits.add("finger cymbals"); - musicianCredits.add("finger snaps"); - musicianCredits.add("five-string banjo"); - musicianCredits.add("floppy disk drive"); - musicianCredits.add("flugelhorn"); - musicianCredits.add("flumpet"); - musicianCredits.add("flute"); - musicianCredits.add("flûte d'amour"); - musicianCredits.add("folk harp"); - musicianCredits.add("foot percussion"); - musicianCredits.add("fortepiano"); - musicianCredits.add("four-string banjo"); - musicianCredits.add("fourth flute"); - musicianCredits.add("frame drum"); - musicianCredits.add("free reed"); - musicianCredits.add("french horn"); - musicianCredits.add("fretless bass"); - musicianCredits.add("friction drum"); - musicianCredits.add("friction idiophone"); - musicianCredits.add("frottoir"); - musicianCredits.add("fujara"); - musicianCredits.add("gadulka"); - musicianCredits.add("gamelan"); - musicianCredits.add("gankogui"); - musicianCredits.add("ganzá"); - musicianCredits.add("gaohu"); - musicianCredits.add("garifuna drum"); - musicianCredits.add("garklein recorder"); - musicianCredits.add("gayageum"); - musicianCredits.add("gehu"); - musicianCredits.add("geomungo"); - musicianCredits.add("german harp"); - musicianCredits.add("ghatam"); - musicianCredits.add("ģīga"); - musicianCredits.add("gittern"); - musicianCredits.add("gizmo"); - musicianCredits.add("glass harmonica"); - musicianCredits.add("glass harp"); - musicianCredits.add("glockenspiel"); - musicianCredits.add("goblet drum"); - musicianCredits.add("gong"); - musicianCredits.add("gong bass drum"); - musicianCredits.add("gongs"); - musicianCredits.add("gralla"); - musicianCredits.add("gramorimba"); - musicianCredits.add("grand piano"); - musicianCredits.add("great bass recorder / c-bass recorder"); - musicianCredits.add("greek baglama"); - musicianCredits.add("guan"); - musicianCredits.add("gudok"); - musicianCredits.add("guest"); - musicianCredits.add("güiro"); - musicianCredits.add("guitalele"); - musicianCredits.add("guitar"); - musicianCredits.add("guitaret"); - musicianCredits.add("guitaret"); - musicianCredits.add("guitarrón chileno"); - musicianCredits.add("guitarrón mexicano"); - musicianCredits.add("guitars"); - musicianCredits.add("guitar synthesizer"); - musicianCredits.add("gumbri"); - musicianCredits.add("guqin"); - musicianCredits.add("gusli"); - musicianCredits.add("gut guitar"); - musicianCredits.add("guzheng"); - musicianCredits.add("haegeum"); - musicianCredits.add("hammered dulcimer"); - musicianCredits.add("hammond organ"); - musicianCredits.add("handbells"); - musicianCredits.add("handclaps"); - musicianCredits.add("hang"); - musicianCredits.add("hardart"); - musicianCredits.add("hard disk drive"); - musicianCredits.add("hardingfele"); - musicianCredits.add("harmonica"); - musicianCredits.add("harmonium"); - musicianCredits.add("harp"); - musicianCredits.add("harp guitar"); - musicianCredits.add("harpsichord"); - musicianCredits.add("hawaiian guitar"); - musicianCredits.add("heckelphone"); - musicianCredits.add("heike biwa"); - musicianCredits.add("helicon"); - musicianCredits.add("hichiriki"); - musicianCredits.add("hi-hat"); - musicianCredits.add("hmông flute"); - musicianCredits.add("horn"); - musicianCredits.add("hotchiku"); - musicianCredits.add("hourglass drum"); - musicianCredits.add("hulusi"); - musicianCredits.add("huqin"); - musicianCredits.add("hurdy gurdy"); - musicianCredits.add("idiophone"); - musicianCredits.add("igil"); - musicianCredits.add("indian bamboo flutes"); - musicianCredits.add("instrument"); - musicianCredits.add("instrumental"); - musicianCredits.add("irish bouzouki"); - musicianCredits.add("irish harp / clàrsach"); - musicianCredits.add("janggu"); - musicianCredits.add("jew's harp"); - musicianCredits.add("jing"); - musicianCredits.add("jing'erhu"); - musicianCredits.add("jinghu"); - musicianCredits.add("jouhikko"); - musicianCredits.add("jug"); - musicianCredits.add("kamancheh"); - musicianCredits.add("kanjira"); - musicianCredits.add("kanklės"); - musicianCredits.add("kantele"); - musicianCredits.add("kanun"); - musicianCredits.add("kartal"); - musicianCredits.add("kaval"); - musicianCredits.add("kazoo"); - musicianCredits.add("kemençe of the black sea"); - musicianCredits.add("kemenche"); - musicianCredits.add("kèn bầu"); - musicianCredits.add("kèn lá"); - musicianCredits.add("keyboard"); - musicianCredits.add("keyboard bass"); - musicianCredits.add("keyed brass instruments"); - musicianCredits.add("keytar"); - musicianCredits.add("khene"); - musicianCredits.add("khèn mèo"); - musicianCredits.add("khim"); - musicianCredits.add("khlui"); - musicianCredits.add("khong wong"); - musicianCredits.add("khong wong lek"); - musicianCredits.add("khong wong yai"); - musicianCredits.add("kinnor"); - musicianCredits.add("ki pah"); - musicianCredits.add("kithara"); - musicianCredits.add("kkwaenggwari"); - musicianCredits.add("klong khaek"); - musicianCredits.add("k'lông pút"); - musicianCredits.add("klong song na"); - musicianCredits.add("klong that"); - musicianCredits.add("klong yao"); - musicianCredits.add("kōauau"); - musicianCredits.add("kokyu"); - musicianCredits.add("komuz"); - musicianCredits.add("kora"); - musicianCredits.add("kortholt"); - musicianCredits.add("kös"); - musicianCredits.add("koto"); - musicianCredits.add("kotsuzumi"); - musicianCredits.add("krakebs"); - musicianCredits.add("krar"); - musicianCredits.add("kudüm"); - musicianCredits.add("lamellophone"); - musicianCredits.add("langeleik"); - musicianCredits.add("laouto"); - musicianCredits.add("lap steel guitar"); - musicianCredits.add("laser harp"); - musicianCredits.add("lasso d'amore"); - musicianCredits.add("launeddas"); - musicianCredits.add("lautenwerck"); - musicianCredits.add("lavta"); - musicianCredits.add("lead vocals"); - musicianCredits.add("limbe"); - musicianCredits.add("lirone"); - musicianCredits.add("lithophone"); - musicianCredits.add("liuqin"); - musicianCredits.add("live"); - musicianCredits.add("low whistle"); - musicianCredits.add("lute"); - musicianCredits.add("luthéal"); - musicianCredits.add("lyre"); - musicianCredits.add("lyricon"); - musicianCredits.add("madal"); - musicianCredits.add("maddale"); - musicianCredits.add("mandocello"); - musicianCredits.add("mandola"); - musicianCredits.add("mandolin"); - musicianCredits.add("mandolute"); - musicianCredits.add("maracas"); - musicianCredits.add("marimba"); - musicianCredits.add("marimba lumina"); - musicianCredits.add("marímbula"); - musicianCredits.add("mark tree"); - musicianCredits.add("marxophone"); - musicianCredits.add("mbira"); - musicianCredits.add("medium"); - musicianCredits.add("medium 1"); - musicianCredits.add("medium 2"); - musicianCredits.add("medium 3"); - musicianCredits.add("medium 4"); - musicianCredits.add("medium 5"); - musicianCredits.add("medium 6"); - musicianCredits.add("medium 7"); - musicianCredits.add("medium 8"); - musicianCredits.add("medium 9"); - musicianCredits.add("medley"); - musicianCredits.add("mellophone"); - musicianCredits.add("mellotron"); - musicianCredits.add("melodica"); - musicianCredits.add("mendoza"); - musicianCredits.add("metal angklung"); - musicianCredits.add("metallophone"); - musicianCredits.add("mexican vihuela"); - musicianCredits.add("mezzo-soprano vocals"); - musicianCredits.add("minimoog"); - musicianCredits.add("minipiano"); - musicianCredits.add("minor"); - musicianCredits.add("mirliton"); - musicianCredits.add("moog"); - musicianCredits.add("morin khuur / matouqin"); - musicianCredits.add("morsing"); - musicianCredits.add("mouth organ"); - musicianCredits.add("mridangam"); - musicianCredits.add("mukkuri"); - musicianCredits.add("musette de cour"); - musicianCredits.add("musical bow"); - musicianCredits.add("musical box"); - musicianCredits.add("musical saw"); - musicianCredits.add("nabal"); - musicianCredits.add("nadaswaram"); - musicianCredits.add("nagadou-daiko"); - musicianCredits.add("nagak"); - musicianCredits.add("nai"); - musicianCredits.add("não bạt / chập chõa"); - musicianCredits.add("naobo"); - musicianCredits.add("natural brass instruments"); - musicianCredits.add("natural horn"); - musicianCredits.add("ney"); - musicianCredits.add("ngɔni"); - musicianCredits.add("nguru"); - musicianCredits.add("nohkan"); - musicianCredits.add("northumbrian pipes"); - musicianCredits.add("nose flute"); - musicianCredits.add("nose whistle"); - musicianCredits.add("number"); - musicianCredits.add("nyatiti"); - musicianCredits.add("nyckelharpa"); - musicianCredits.add("nylon guitar"); - musicianCredits.add("oboe"); - musicianCredits.add("oboe da caccia"); - musicianCredits.add("oboe d'amore"); - musicianCredits.add("ocarina"); - musicianCredits.add("ocean drum"); - musicianCredits.add("octave mandolin"); - musicianCredits.add("oktawka"); - musicianCredits.add("omnichord"); - musicianCredits.add("ondes martenot"); - musicianCredits.add("ophicleide"); - musicianCredits.add("organ"); - musicianCredits.add("original"); - musicianCredits.add("orpharion"); - musicianCredits.add("other instruments"); - musicianCredits.add("other vocals"); - musicianCredits.add("ōtsuzumi"); - musicianCredits.add("oud"); - musicianCredits.add("pahū pounamu"); - musicianCredits.add("pakhavaj"); - musicianCredits.add("pan flute"); - musicianCredits.add("pang gu ly hu hmông"); - musicianCredits.add("paraguayan harp"); - musicianCredits.add("parody"); - musicianCredits.add("partial"); - musicianCredits.add("pātē"); - musicianCredits.add("pedal piano"); - musicianCredits.add("pedal steel guitar"); - musicianCredits.add("percussion"); - musicianCredits.add("phách"); - musicianCredits.add("pi"); - musicianCredits.add("pianet"); - musicianCredits.add("piano"); - musicianCredits.add("piccolo"); - musicianCredits.add("pi nai"); - musicianCredits.add("pipa"); - musicianCredits.add("pipe organ"); - musicianCredits.add("piri"); - musicianCredits.add("pí thiu"); - musicianCredits.add("pkhachich"); - musicianCredits.add("plucked string instruments"); - musicianCredits.add("pocket trumpet"); - musicianCredits.add("poi awhiowhio"); - musicianCredits.add("portuguese guitar"); - musicianCredits.add("pōrutu"); - musicianCredits.add("post horn"); - musicianCredits.add("practice chanter"); - musicianCredits.add("prepared piano"); - musicianCredits.add("primero"); - musicianCredits.add("principal"); - musicianCredits.add("psaltery"); - musicianCredits.add("pūkaea"); - musicianCredits.add("pūmotomoto"); - musicianCredits.add("pūrerehua"); - musicianCredits.add("pūtātara"); - musicianCredits.add("pūtōrino"); - musicianCredits.add("qilaut"); - musicianCredits.add("quena"); - musicianCredits.add("quijada"); - musicianCredits.add("quinto"); - musicianCredits.add("rainstick"); - musicianCredits.add("rammana"); - musicianCredits.add("ranat ek"); - musicianCredits.add("ranat kaeo"); - musicianCredits.add("ranat thum"); - musicianCredits.add("ratchet"); - musicianCredits.add("rattle"); - musicianCredits.add("rauschpfeife"); - musicianCredits.add("ravanahatha"); - musicianCredits.add("reactable"); - musicianCredits.add("rebab"); - musicianCredits.add("rebec"); - musicianCredits.add("recorder"); - musicianCredits.add("reco-reco"); - musicianCredits.add("reed organ"); - musicianCredits.add("reeds"); - musicianCredits.add("rehu"); - musicianCredits.add("repinique"); - musicianCredits.add("resonator guitar"); - musicianCredits.add("rhodes piano"); - musicianCredits.add("rhythm sticks"); - musicianCredits.add("riq"); - musicianCredits.add("rondador"); - musicianCredits.add("rototom"); - musicianCredits.add("ruan"); - musicianCredits.add("rudra veena"); - musicianCredits.add("ryuteki"); - musicianCredits.add("sabar"); - musicianCredits.add("sackbut"); - musicianCredits.add("samba whistle"); - musicianCredits.add("sampler"); - musicianCredits.add("sanshin"); - musicianCredits.add("santoor"); - musicianCredits.add("santur"); - musicianCredits.add("sanxian"); - musicianCredits.add("sáo meò"); - musicianCredits.add("saó ôi flute"); - musicianCredits.add("sáo trúc"); - musicianCredits.add("sapek clappers"); - musicianCredits.add("sarangi"); - musicianCredits.add("saraswati veena"); - musicianCredits.add("šargija"); - musicianCredits.add("sarod"); - musicianCredits.add("saron"); - musicianCredits.add("sarrusophone"); - musicianCredits.add("satsuma biwa"); - musicianCredits.add("saw duang"); - musicianCredits.add("saw sam sai"); - musicianCredits.add("saw u"); - musicianCredits.add("sax"); - musicianCredits.add("saxophone"); - musicianCredits.add("saz"); - musicianCredits.add("schwyzerörgeli"); - musicianCredits.add("scottish smallpipes"); - musicianCredits.add("segunda"); - musicianCredits.add("sênh tiền"); - musicianCredits.add("serpent"); - musicianCredits.add("setar"); - musicianCredits.add("shakers"); - musicianCredits.add("shakuhachi"); - musicianCredits.add("shamisen"); - musicianCredits.add("shawm"); - musicianCredits.add("shehnai"); - musicianCredits.add("shekere"); - musicianCredits.add("sheng"); - musicianCredits.add("shichepshin"); - musicianCredits.add("shime-daiko"); - musicianCredits.add("shinobue"); - musicianCredits.add("sho"); - musicianCredits.add("shofar"); - musicianCredits.add("shruti box"); - musicianCredits.add("shudraga"); - musicianCredits.add("siku"); - musicianCredits.add("singing bowl"); - musicianCredits.add("single reed"); - musicianCredits.add("sistrum"); - musicianCredits.add("sitar"); - musicianCredits.add("slide"); - musicianCredits.add("slit drum"); - musicianCredits.add("snare drum"); - musicianCredits.add("solo"); - musicianCredits.add("song loan"); - musicianCredits.add("sopilka"); - musicianCredits.add("sopranino"); - musicianCredits.add("soprano"); - musicianCredits.add("sousaphone"); - musicianCredits.add("spanish"); - musicianCredits.add("spilåpipa"); - musicianCredits.add("spinet"); - musicianCredits.add("spinettone"); - musicianCredits.add("spoken vocals"); - musicianCredits.add("spoons"); - musicianCredits.add("steel guitar"); - musicianCredits.add("steelpan"); - musicianCredits.add("steel-string guitar"); - musicianCredits.add("strings"); - musicianCredits.add("string quartet"); - musicianCredits.add("string ensemble"); - musicianCredits.add("stroh violin"); - musicianCredits.add("struck idiophone"); - musicianCredits.add("struck string instruments"); - musicianCredits.add("subcontrabass recorder"); - musicianCredits.add("suikinkutsu"); - musicianCredits.add("suka"); - musicianCredits.add("suling"); - musicianCredits.add("suona"); - musicianCredits.add("surdo"); - musicianCredits.add("swarmandal"); - musicianCredits.add("swedish bagpipes"); - musicianCredits.add("synclavier"); - musicianCredits.add("synthesizer"); - musicianCredits.add("syrinx"); - musicianCredits.add("tabla"); - musicianCredits.add("table steel guitar"); - musicianCredits.add("tack piano"); - musicianCredits.add("taepyeongso"); - musicianCredits.add("taiko"); - musicianCredits.add("taishogoto"); - musicianCredits.add("talharpa"); - musicianCredits.add("talkbox"); - musicianCredits.add("talking drum"); - musicianCredits.add("tamborim"); - musicianCredits.add("tambourine"); - musicianCredits.add("tambura"); - musicianCredits.add("tamburitza"); - musicianCredits.add("tanbou ka"); - musicianCredits.add("tanbur"); - musicianCredits.add("tangent piano"); - musicianCredits.add("taonga pūoro"); - musicianCredits.add("tap dancing"); - musicianCredits.add("tape"); - musicianCredits.add("taphon"); - musicianCredits.add("tar"); - musicianCredits.add("taragot"); - musicianCredits.add("tef"); - musicianCredits.add("teleharmonium"); - musicianCredits.add("temple blocks"); - musicianCredits.add("tenor"); - musicianCredits.add("thavil"); - musicianCredits.add("theatre organ"); - musicianCredits.add("theorbo"); - musicianCredits.add("theremin"); - musicianCredits.add("thon"); - musicianCredits.add("tibetan water drum"); - musicianCredits.add("ti bwa"); - musicianCredits.add("tiêu"); - musicianCredits.add("timbales"); - musicianCredits.add("time"); - musicianCredits.add("timpani"); - musicianCredits.add("tin whistle"); - musicianCredits.add("tinya"); - musicianCredits.add("tiple"); - musicianCredits.add("tololoche"); - musicianCredits.add("tom-tom"); - musicianCredits.add("tonkori"); - musicianCredits.add("topshuur"); - musicianCredits.add("toy piano"); - musicianCredits.add("tràm plè"); - musicianCredits.add("trắng jâu"); - musicianCredits.add("trắng lu"); - musicianCredits.add("translated"); - musicianCredits.add("transliterated"); - musicianCredits.add("transverse flute"); - musicianCredits.add("treble"); - musicianCredits.add("tres"); - musicianCredits.add("triangle"); - musicianCredits.add("tromba marina"); - musicianCredits.add("trombone"); - musicianCredits.add("tromboon"); - musicianCredits.add("trống bông"); - musicianCredits.add("trumpet"); - musicianCredits.add("t'rưng"); - musicianCredits.add("tuba"); - musicianCredits.add("tubax"); - musicianCredits.add("tubon"); - musicianCredits.add("tubular bells"); - musicianCredits.add("tumbi"); - musicianCredits.add("tuned percussion"); - musicianCredits.add("turkish baglama"); - musicianCredits.add("turntable(s)"); - musicianCredits.add("txalaparta"); - musicianCredits.add("typewriter"); - musicianCredits.add("tzoura"); - musicianCredits.add("udu"); - musicianCredits.add("uilleann pipes"); - musicianCredits.add("ukeke"); - musicianCredits.add("ukulele"); - musicianCredits.add("upright piano"); - musicianCredits.add("ütőgardon"); - musicianCredits.add("vacuum cleaner"); - musicianCredits.add("valiha"); - musicianCredits.add("valved brass instruments"); - musicianCredits.add("valve trombone"); - musicianCredits.add("venu"); - musicianCredits.add("vessel drum"); - musicianCredits.add("vessel flute"); - musicianCredits.add("vibraphone"); - musicianCredits.add("vibraslap"); - musicianCredits.add("vichitra veena"); - musicianCredits.add("vielle"); - musicianCredits.add("vienna horn"); - musicianCredits.add("vietnamese guitar"); - musicianCredits.add("viola"); - musicianCredits.add("violin"); - musicianCredits.add("violoncello piccolo"); - musicianCredits.add("violone"); - musicianCredits.add("violotta"); - musicianCredits.add("virginal"); - musicianCredits.add("vocal"); - musicianCredits.add("vocals"); - musicianCredits.add("vocoder"); - musicianCredits.add("voice synthesizer"); - musicianCredits.add("wagner tuba"); - musicianCredits.add("warr guitar"); - musicianCredits.add("washboard"); - musicianCredits.add("washtub bass"); - musicianCredits.add("waterphone"); - musicianCredits.add("wavedrum"); - musicianCredits.add("whip"); - musicianCredits.add("whistle"); - musicianCredits.add("willow flute"); - musicianCredits.add("wind chime"); - musicianCredits.add("wind instruments"); - musicianCredits.add("wire-strung harp"); - musicianCredits.add("wood block"); - musicianCredits.add("wooden fish"); - musicianCredits.add("woodwind"); - musicianCredits.add("wot"); - musicianCredits.add("wurlitzer electric piano"); - musicianCredits.add("xalam"); - musicianCredits.add("xaphoon"); - musicianCredits.add("xiao"); - musicianCredits.add("xiaoluo"); - musicianCredits.add("xun"); - musicianCredits.add("xylophone"); - musicianCredits.add("xylorimba"); - musicianCredits.add("yangqin"); - musicianCredits.add("yatga"); - musicianCredits.add("yaylı tanbur"); - musicianCredits.add("yehu"); - musicianCredits.add("yonggo"); - musicianCredits.add("yueqin"); - musicianCredits.add("zabumba"); - musicianCredits.add("żafżafa"); - musicianCredits.add("żaqq"); - musicianCredits.add("zarb"); - musicianCredits.add("zhaleika"); - musicianCredits.add("zhonghu"); - musicianCredits.add("zhongruan"); - musicianCredits.add("zill"); - musicianCredits.add("zither"); - musicianCredits.add("żummara"); - musicianCredits.add("zurna"); - } - - public static boolean isKey(String key) - { - for(String next:musicianCredits) - { - if(key.toLowerCase().trim().startsWith(next)) - { - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java deleted file mode 100644 index a8a09fff..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/ReceivedAsTypes.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Used by Commercial Frame (COMR) - */ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.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; - - public static ReceivedAsTypes getInstanceOf() - { - if (receivedAsTypes == null) - { - receivedAsTypes = new ReceivedAsTypes(); - } - return 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/StandardIPLSKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/StandardIPLSKey.java deleted file mode 100644 index f78aaeef..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/StandardIPLSKey.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -/** - * List of keys used by IPLS, TIPL and TMCL names that we map to individual keys, these are - * handled differently to the remainder such as musicians and their instruments which is - * essentially an infinite list. - */ -public enum StandardIPLSKey -{ - ENGINEER("engineer"), - MIXER("mix"), - DJMIXER("DJ-mix"), - PRODUCER("producer"), - ARRANGER("arranger"),; - - private String key; - - StandardIPLSKey(String key) - { - this.key = key; - } - - public String getKey() - { - return key; - } - - private static final Map lookup = new HashMap(); - - static - { - for (StandardIPLSKey s : EnumSet.allOf(StandardIPLSKey.class)) - { - lookup.put(s.getKey(), s); - } - } - - public static StandardIPLSKey get(String key) - { - return lookup.get(key); - } - - public static boolean isKey(String key) - { - return get(key) != null; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java deleted file mode 100644 index e1d53662..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/SynchronisedLyricsContentType.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -/** - * Content Type used by Sysnchronised Lyrics Frame (SYLT) - */ -public class SynchronisedLyricsContentType extends AbstractIntStringValuePair -{ - private static SynchronisedLyricsContentType eventTimingTypes; - - public static SynchronisedLyricsContentType getInstanceOf() - { - if (SynchronisedLyricsContentType.eventTimingTypes == null) - { - SynchronisedLyricsContentType.eventTimingTypes = new SynchronisedLyricsContentType(); - } - return SynchronisedLyricsContentType.eventTimingTypes; - } - - public static final int CONTENT_KEY_FIELD_SIZE = 1; - - 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/TextEncoding.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/TextEncoding.java deleted file mode 100644 index 86ee610e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/TextEncoding.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Valid Text Encodings - */ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.datatype.AbstractIntStringValuePair; - -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; - - -/** - * 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 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 by 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 final Map idToCharset = new HashMap(); - - /** - * Get singleton for this class. - * - * @return singleton - */ - public static synchronized TextEncoding getInstanceOf() - { - if (textEncodings == null) - { - textEncodings = new TextEncoding(); - } - return textEncodings; - } - - private TextEncoding() - { - idToCharset.put((int) ISO_8859_1, StandardCharsets.ISO_8859_1); - idToCharset.put((int) UTF_16, StandardCharsets.UTF_16); - idToCharset.put((int) UTF_16BE, StandardCharsets.UTF_16BE); - idToCharset.put((int) UTF_8, StandardCharsets.UTF_8); - - for (final Map.Entry e : idToCharset.entrySet()) { - idToValue.put(e.getKey(), e.getValue().name()); - } - - createMaps(); - } - - /** - * Allows to lookup id directly via the {@link Charset} instance. - * - * @param charset charset - * @return id, e.g. {@link #ISO_8859_1}, or {@code null}, if not found - */ - public Integer getIdForCharset(final Charset charset) - { - return valueToId.get(charset.name()); - } - - /** - * Allows direct lookup of the {@link Charset} instance via an id. - * - * @param id id, e.g. {@link #ISO_8859_1} - * @return charset or {@code null}, if not found - */ - public Charset getCharsetForId(final int id) - { - return idToCharset.get(id); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java deleted file mode 100644 index d4c09d8a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/id3/valuepair/V2GenreTypes.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.mp3.jaudiotagger.tag.id3.valuepair; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/AndroidArtwork.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/AndroidArtwork.java deleted file mode 100644 index 62d71048..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/AndroidArtwork.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.mp3.jaudiotagger.tag.images; - -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import com.mp3.jaudiotagger.tag.id3.valuepair.ImageFormats; -import com.mp3.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() - { - - } - 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 int getHeight() - { - return height; - } - - public int getWidth() - { - return width; - } - - public void setDescription(String description) - { - this.description = description; - } - - /** - * 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 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 Artwork from File - * - * @param file - * @return - * @throws 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 Linked Artwork from URL - * - * @param url - * @throws 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()); - } - - /** - * Create artwork from Flac block - * - * @param coverArt - * @return - */ - public static AndroidArtwork createArtworkFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) - { - AndroidArtwork artwork = new AndroidArtwork(); - artwork.setFromMetadataBlockDataPicture(coverArt); - return artwork; - } - - public void setWidth(int width) - { - this.width = width; - } - - public void setHeight(int height) - { - this.height = height; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/Artwork.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/Artwork.java deleted file mode 100644 index acdec96b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/Artwork.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.mp3.jaudiotagger.tag.images; - -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; - -import java.io.File; -import java.io.IOException; - -/** - * Represents artwork in a format independent way - */ -public interface Artwork -{ - public byte[] getBinaryData(); - - - public void setBinaryData(byte[] binaryData); - - public String getMimeType(); - - public void setMimeType(String mimeType); - - public String getDescription(); - - public int getHeight(); - - public int getWidth(); - - public void setDescription(String description); - - /** - * Should be called when you wish to prime the artwork for saving - * - * @return - */ - public boolean setImageFromData(); - - public Object getImage() throws IOException; - - public boolean isLinked(); - - public void setLinked(boolean linked); - - public String getImageUrl(); - - public void setImageUrl(String imageUrl); - - public int getPictureType(); - - public void setPictureType(int pictureType); - - /** - * Create Artwork from File - * - * @param file - * @throws IOException - */ - public void setFromFile(File file) throws IOException; - - /** - * Populate Artwork from MetadataBlockDataPicture as used by Flac and VorbisComment - * - * @param coverArt - */ - public void setFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt); - - - public void setWidth(int width); - - public void setHeight(int height); -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/ArtworkFactory.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/ArtworkFactory.java deleted file mode 100644 index 753f038a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/images/ArtworkFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mp3.jaudiotagger.tag.images; - -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; - -import java.io.File; -import java.io.IOException; - -/** - * Get appropriate Artwork class - */ -public class ArtworkFactory { - - - public static Artwork getNew() { - return new AndroidArtwork(); - } - - /** - * Create Artwork instance from A Flac Metadata Block - * - * @param coverArt - * @return - */ - public static Artwork createArtworkFromMetadataBlockDataPicture(MetadataBlockDataPicture coverArt) { - return AndroidArtwork.createArtworkFromMetadataBlockDataPicture(coverArt); - } - - /** - * Create Artwork instance from an image file - * - * @param file - * @return - * @throws IOException - */ - public static Artwork createArtworkFromFile(File file) throws IOException { - return AndroidArtwork.createArtworkFromFile(file); - } - - /** - * Create Artwork instance from an image file - * - * @param link - * @return - * @throws IOException - */ - public static Artwork createLinkedArtworkFromURL(String link) throws IOException { - return AndroidArtwork.createLinkedArtworkFromURL(link); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3.java deleted file mode 100644 index 0993795c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.id3.AbstractTag; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java deleted file mode 100644 index f7e7519a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/AbstractLyrics3v2FieldFrameBody.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.datatype.AbstractDataType; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java deleted file mode 100644 index c4aa90e1..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyAUT.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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); - } - - /** - * @param author - */ - public void setAuthor(String author) - { - setObjectValue("Author", author); - } - - /** - * @return - */ - public String getAuthor() - { - return (String) getObjectValue("Author"); - } - - /** - * @return - */ - public String getIdentifier() - { - return "AUT"; - } - - /** - * - */ - protected void setupObjectList() - { - objectList.add(new StringSizeTerminated("Author", this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java deleted file mode 100644 index 48ee2adf..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAL.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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); - - } - - /** - * @param album - */ - public void setAlbum(String album) - { - setObjectValue("Album", album); - } - - /** - * @return - */ - public String getAlbum() - { - return (String) getObjectValue("Album"); - } - - /** - * @return - */ - public String getIdentifier() - { - return "EAL"; - } - - /** - * - */ - protected void setupObjectList() - { - objectList.add(new StringSizeTerminated("Album", this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java deleted file mode 100644 index e8ff000e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyEAR.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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); - - } - - /** - * @param artist - */ - public void setArtist(String artist) - { - setObjectValue("Artist", artist); - } - - /** - * @return - */ - public String getArtist() - { - return (String) getObjectValue("Artist"); - } - - /** - * @return - */ - public String getIdentifier() - { - return "EAR"; - } - - /** - * - */ - protected void setupObjectList() - { - objectList.add(new StringSizeTerminated("Artist", this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java deleted file mode 100644 index 8d96a489..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyETT.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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"; - } - - /** - * @param title - */ - public void setTitle(String title) - { - setObjectValue("Title", title); - } - - /** - * @return - */ - public String getTitle() - { - return (String) getObjectValue("Title"); - } - - /** - * - */ - protected void setupObjectList() - { - objectList.add(new StringSizeTerminated("Title", this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java deleted file mode 100644 index 432e448b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIMG.java +++ /dev/null @@ -1,336 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ - -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.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); - } - - /** - * @param value - */ - public void setValue(String value) - { - readString(value); - } - - /** - * @return - */ - public String getValue() - { - return writeString(); - } - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java deleted file mode 100644 index 96dd7ada..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyIND.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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); - } - - /** - * @param author - */ - public void setAuthor(String author) - { - setObjectValue("Author", author); - } - - /** - * @return - */ - public String getAuthor() - { - return (String) getObjectValue("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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java deleted file mode 100644 index db48fab4..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyINF.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.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 com.mp3.jaudiotagger.tag.InvalidTagException - */ - public FieldFrameBodyINF(ByteBuffer byteBuffer) throws InvalidTagException - { - this.read(byteBuffer); - - } - - /** - * @param additionalInformation - */ - public void setAdditionalInformation(String additionalInformation) - { - setObjectValue("Additional Information", additionalInformation); - } - - /** - * @return - */ - public String getAdditionalInformation() - { - return (String) getObjectValue("Additional Information"); - } - - /** - * @return - */ - public String getIdentifier() - { - return "INF"; - } - - /** - * - */ - protected void setupObjectList() - { - objectList.add(new StringSizeTerminated("Additional Information", this)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java deleted file mode 100644 index b7689609..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyLYR.java +++ /dev/null @@ -1,412 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.datatype.ID3v2LyricLine; -import com.mp3.jaudiotagger.tag.datatype.Lyrics3Line; -import com.mp3.jaudiotagger.tag.datatype.Lyrics3TimeStamp; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodySYLT; -import com.mp3.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 com.mp3.jaudiotagger.tag.InvalidTagException - */ - public FieldFrameBodyLYR(ByteBuffer byteBuffer) throws InvalidTagException - { - - this.read(byteBuffer); - - } - - /** - * @return - */ - public String getIdentifier() - { - return "LYR"; - } - - /** - * @param str - */ - public void setLyric(String str) - { - readString(str); - } - - /** - * @return - */ - public String getLyric() - { - return writeString(); - } - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java deleted file mode 100644 index 67970357..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/FieldFrameBodyUnsupported.java +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1.java deleted file mode 100644 index fedbe66e..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1.java +++ /dev/null @@ -1,327 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ - -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.TagNotFoundException; -import com.mp3.jaudiotagger.tag.id3.AbstractTag; -import com.mp3.jaudiotagger.tag.id3.ID3Tags; -import com.mp3.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. - * - * @throws TagNotFoundException - * @throws IOException - * @param byteBuffer - */ - public Lyrics3v1(ByteBuffer byteBuffer) throws TagNotFoundException, IOException - { - try - { - this.read(byteBuffer); - } - catch (TagException e) - { - e.printStackTrace(); - } - } - - /** - * @return - */ - public String getIdentifier() - { - return "Lyrics3v1.00"; - } - - /** - * @param lyric - */ - public void setLyric(String lyric) - { - this.lyric = ID3Tags.truncate(lyric, 5100); - } - - /** - * @return - */ - public String getLyric() - { - return lyric; - } - - /** - * @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 UnsupportedOperationException - * - */ - public Iterator iterator() - { - /** - * @todo Implement this com.mp3.jaudiotagger.tag.AbstractMP3Tag abstract method - */ - throw new 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java deleted file mode 100644 index 50774112..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v1Iterator.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2.java deleted file mode 100644 index b10ca2fb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2.java +++ /dev/null @@ -1,529 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.TagNotFoundException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Frame; -import com.mp3.jaudiotagger.tag.id3.AbstractTag; -import com.mp3.jaudiotagger.tag.id3.ID3v1Tag; -import com.mp3.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. - * - * @throws TagNotFoundException - * @throws IOException - * @param byteBuffer - */ - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java deleted file mode 100644 index 400912a8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Field.java +++ /dev/null @@ -1,269 +0,0 @@ -/** - * @author : Paul Taylor - * @author : Eric Farng - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ - -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.InvalidTagException; -import com.mp3.jaudiotagger.tag.TagException; -import com.mp3.jaudiotagger.tag.TagOptionSingleton; -import com.mp3.jaudiotagger.tag.id3.AbstractID3v2Frame; -import com.mp3.jaudiotagger.tag.id3.AbstractTagFrame; -import com.mp3.jaudiotagger.tag.id3.framebody.AbstractFrameBodyTextInfo; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodyCOMM; -import com.mp3.jaudiotagger.tag.id3.framebody.FrameBodySYLT; -import com.mp3.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. - * - * @throws InvalidTagException - * @param byteBuffer - */ - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java deleted file mode 100644 index 3519050b..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/lyrics3/Lyrics3v2Fields.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.lyrics3; - -import com.mp3.jaudiotagger.tag.datatype.AbstractStringStringValuePair; - -public class Lyrics3v2Fields extends AbstractStringStringValuePair -{ - - private static Lyrics3v2Fields lyrics3Fields; - - /** - * CRLF int set - */ - private static final byte[] crlfByte = {13, 10}; - /** - * CRLF int set - */ - public static final String CRLF = new String(crlfByte); - - public static Lyrics3v2Fields getInstanceOf() - { - if (lyrics3Fields == null) - { - lyrics3Fields = new Lyrics3v2Fields(); - } - return lyrics3Fields; - } - - 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"; - - - 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(); - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4FieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4FieldKey.java deleted file mode 100644 index 839031b3..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4FieldKey.java +++ /dev/null @@ -1,387 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4; - -import com.mp3.jaudiotagger.tag.mp4.field.Mp4FieldType; -import com.mp3.jaudiotagger.tag.mp4.field.Mp4TagReverseDnsField; -import com.mp3.jaudiotagger.tag.reference.Tagger; - -import static com.mp3.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), - AK_ID("akID",Mp4TagFieldSubType.UNKNOWN, INTEGER, 1), - ALBUM("©alb",Mp4TagFieldSubType.TEXT, TEXT), - ALBUM_ARTIST("aART",Mp4TagFieldSubType.TEXT, TEXT), - ALBUM_ARTIST_SORT("soaa",Mp4TagFieldSubType.TEXT, TEXT), - ALBUM_SORT("soal",Mp4TagFieldSubType.TEXT, TEXT), - AP_ID("apID",Mp4TagFieldSubType.UNKNOWN, TEXT), - ARRANGER("com.apple.iTunes", "ARRANGER", TEXT, Tagger.PICARD), - ARRANGER_SORT("com.apple.iTunes","ARRANGER_SORT", TEXT, Tagger.JAIKOZ), - ARTIST("©ART",Mp4TagFieldSubType.TEXT, TEXT), - ARTISTS("com.apple.iTunes", "ARTISTS", TEXT, Tagger.JAIKOZ), - ARTISTS_SORT("com.apple.iTunes","ARTISTS_SORT", TEXT, Tagger.JAIKOZ), - ALBUM_ARTISTS("com.apple.iTunes","ALBUM_ARTISTS", TEXT, Tagger.JAIKOZ), - ALBUM_ARTISTS_SORT("com.apple.iTunes","ALBUM_ARTISTS_SORT", TEXT, Tagger.JAIKOZ), - ARTIST_SORT("soar",Mp4TagFieldSubType.TEXT, TEXT), - ARTWORK("covr",Mp4TagFieldSubType.ARTWORK, COVERART_JPEG), - ASIN("com.apple.iTunes", "ASIN", TEXT, Tagger.PICARD), - AT_ID("atID",Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - BARCODE("com.apple.iTunes", "BARCODE", TEXT, Tagger.PICARD), - BPM("tmpo",Mp4TagFieldSubType.BYTE, INTEGER, 2), - CATALOGNO("com.apple.iTunes", "CATALOGNUMBER", TEXT, Tagger.PICARD), - 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), - CN_ID("cnID",Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - CHOIR("com.apple.iTunes","CHOR", TEXT, Tagger.JAIKOZ), - CHOIR_SORT("com.apple.iTunes","CHOIR_SORT", TEXT, Tagger.JAIKOZ), - CLASSICAL_CATALOG("com.apple.iTunes","CLASSICAL_CATALOG", TEXT, Tagger.JAIKOZ), - CLASSICAL_NICKNAME("com.apple.iTunes","CLASSICAL_NICKNAME", TEXT, Tagger.JAIKOZ), - COMMENT("©cmt",Mp4TagFieldSubType.TEXT, TEXT), - COMPILATION("cpil",Mp4TagFieldSubType.BYTE, INTEGER, 1), - COMPOSER("©wrt",Mp4TagFieldSubType.TEXT, TEXT), - COMPOSER_SORT("soco",Mp4TagFieldSubType.TEXT, TEXT), - CONDUCTOR("com.apple.iTunes", "CONDUCTOR", TEXT, Tagger.PICARD), - CONDUCTOR_MM3BETA("cond",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - CONDUCTOR_SORT("com.apple.iTunes","CONDUCTOR_SORT", TEXT, Tagger.JAIKOZ), - CONTENT_TYPE("stik",Mp4TagFieldSubType.BYTE, INTEGER, 1), - COPYRIGHT("cprt",Mp4TagFieldSubType.TEXT, TEXT), - COUNTRY("com.apple.iTunes", "Country", TEXT, Tagger.PICARD), - 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), - 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), - DJMIXER("com.apple.iTunes", "DJMIXER", TEXT, Tagger.PICARD), - ENCODER("©too",Mp4TagFieldSubType.TEXT, TEXT), - ENGINEER("com.apple.iTunes", "ENGINEER", TEXT, Tagger.PICARD), - ENSEMBLE("com.apple.iTunes", "Ensemble", TEXT, Tagger.JAIKOZ), - ENSEMBLE_SORT("com.apple.iTunes","Ensemble Sort", TEXT, Tagger.JAIKOZ), - EPISODE_GLOBAL_ID("egid",Mp4TagFieldSubType.NUMBER, IMPLICIT), //TODO Actually seems to store text but is marked as numeric! - FBPM("com.apple.iTunes", "fBPM", TEXT, Tagger.JAIKOZ), - GENRE("gnre",Mp4TagFieldSubType.GENRE, IMPLICIT), - GENRE_CUSTOM("©gen",Mp4TagFieldSubType.TEXT, TEXT), - GE_ID("geID",Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - GROUP("com.apple.iTunes", "GROUP", TEXT, Tagger.JAIKOZ), - GROUPING("©grp",Mp4TagFieldSubType.TEXT, TEXT), - INSTRUMENT("com.apple.iTunes", "INSTRUMENT", TEXT, Tagger.JAIKOZ), - INVOLVED_PEOPLE("peop",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - ISRC("com.apple.iTunes", "ISRC", TEXT, Tagger.PICARD), - ISRC_MMBETA("isrc",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - IS_CLASSICAL("com.apple.iTunes", "IS_CLASSICAL", TEXT, Tagger.JAIKOZ), - IS_SOUNDTRACK("com.apple.iTunes", "IS_SOUNDTRACK", TEXT, Tagger.JAIKOZ), - ITUNES_NORM("com.apple.iTunes", "iTunNORM", TEXT), - ITUNES_SMPB("com.apple.iTunes", "iTunSMPB", TEXT), - KEY("com.apple.iTunes", "initialkey", TEXT), - KEYS("keys",Mp4TagFieldSubType.TEXT,TEXT), - KEYWORD("keyw",Mp4TagFieldSubType.TEXT, TEXT), - KEY_OLD("com.apple.iTunes", "KEY", TEXT, Tagger.JAIKOZ), - LABEL("com.apple.iTunes", "LABEL", TEXT, Tagger.PICARD), - LANGUAGE("com.apple.iTunes", "LANGUAGE", TEXT, Tagger.JAIKOZ), - LYRICIST("com.apple.iTunes", "LYRICIST", TEXT, Tagger.PICARD), - LYRICIST_MM3BETA("lyrc",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - LYRICS("©lyr",Mp4TagFieldSubType.TEXT, TEXT), - MEDIA("com.apple.iTunes", "MEDIA", TEXT, Tagger.PICARD), - MIXER("com.apple.iTunes", "MIXER", TEXT, Tagger.PICARD), - 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), - MM_INVOLVED_PEOPLE("com.apple.iTunes", "INVOLVED PEOPLE", TEXT, Tagger.MEDIA_MONKEY), - MM_OCCASION("com.apple.iTunes", "OCCASION", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_ALBUM_TITLE("com.apple.iTunes", "ORIGINAL ALBUM", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_ARTIST("com.apple.iTunes", "ORIGINAL ARTIST", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_LYRICIST("com.apple.iTunes", "ORIGINAL LYRICIST", TEXT, Tagger.MEDIA_MONKEY), - MM_ORIGINAL_YEAR("com.apple.iTunes", "ORIGINAL YEAR", TEXT, Tagger.MEDIA_MONKEY), - MM_PUBLISHER("com.apple.iTunes", "ORGANIZATION", TEXT, Tagger.MEDIA_MONKEY), - MM_QUALITY("com.apple.iTunes", "QUALITY", TEXT, Tagger.MEDIA_MONKEY), - MM_TEMPO("com.apple.iTunes", "TEMPO", TEXT, Tagger.MEDIA_MONKEY), - MOOD("com.apple.iTunes", "MOOD", TEXT, Tagger.PICARD), - MOOD_ACOUSTIC("com.apple.iTunes", "MOOD_ACOUSTIC", TEXT, Tagger.JAIKOZ), - MOOD_AGGRESSIVE("com.apple.iTunes", "MOOD_AGGRESSIVE", TEXT, Tagger.JAIKOZ), - MOOD_AROUSAL("com.apple.iTunes", "MOOD_AROUSAL", TEXT, Tagger.JAIKOZ), - MOOD_DANCEABILITY("com.apple.iTunes", "MOOD_DANCEABILITY", TEXT, Tagger.JAIKOZ), - MOOD_ELECTRONIC("com.apple.iTunes", "MOOD_ELECTRONIC", TEXT, Tagger.JAIKOZ), - MOOD_HAPPY("com.apple.iTunes", "MOOD_HAPPY", TEXT, Tagger.JAIKOZ), - MOOD_INSTRUMENTAL("com.apple.iTunes", "MOOD_INSTRUMENTAL", TEXT, Tagger.JAIKOZ), - MOOD_MM3BETA("mood",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - MOOD_PARTY("com.apple.iTunes", "MOOD_PARTY", TEXT, Tagger.JAIKOZ), - MOOD_RELAXED("com.apple.iTunes", "MOOD_RELAXED", TEXT, Tagger.JAIKOZ), - MOOD_SAD("com.apple.iTunes", "MOOD_SAD", TEXT, Tagger.JAIKOZ), - MOOD_VALENCE("com.apple.iTunes", "MOOD_VALENCE", TEXT, Tagger.JAIKOZ), - MOVEMENT("©mvn",Mp4TagFieldSubType.TEXT, TEXT), - MOVEMENT_NO("©mvi",Mp4TagFieldSubType.BYTE, INTEGER, 1),//Note unlike Trackno/Total uses two different fields - MOVEMENT_TOTAL("©mvc",Mp4TagFieldSubType.BYTE, INTEGER, 1), - 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_RELEASE_TRACKID("com.apple.iTunes", "MusicBrainz Release Track Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_TRACKID("com.apple.iTunes", "MusicBrainz Track Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_WORK("com.apple.iTunes", "MUSICBRAINZ_WORK", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORKID("com.apple.iTunes", "MusicBrainz Work Id", TEXT, Tagger.PICARD), - MUSICBRAINZ_WORK_COMPOSITION("com.apple.iTunes","MUSICBRAINZ_WORK_COMPOSITION", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_COMPOSITION_ID("com.apple.iTunes","MUSICBRAINZ_WORK_COMPOSITION_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL1("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL1", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL1_ID("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL1_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL1_TYPE("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL1_TYPE", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL2("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL2", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL2_ID("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL2_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL2_TYPE("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL2_TYPE", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL3("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL3", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL3_ID("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL3_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL3_TYPE("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL3_TYPE", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL4("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL4", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL4_ID("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL4_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL4_TYPE("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL4_TYPE", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL5("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL5", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL5_ID("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL5_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL5_TYPE("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL5_TYPE", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL6("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL6", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL6_ID("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL6_ID", TEXT, Tagger.JAIKOZ), - MUSICBRAINZ_WORK_PART_LEVEL6_TYPE("com.apple.iTunes","MUSICBRAINZ_WORK_PART_LEVEL6_TYPE", TEXT, Tagger.JAIKOZ), - MUSICIP_PUID("com.apple.iTunes", "MusicIP PUID", TEXT, Tagger.PICARD), - OCCASION("occa",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - OPUS("com.apple.iTunes","OPUS", TEXT, Tagger.JAIKOZ), - ORCHESTRA("com.apple.iTunes", "ORCHESTRA", TEXT, Tagger.PICARD), - ORCHESTRA_SORT("com.apple.iTunes","ORCHESTRA_SORT", TEXT, Tagger.JAIKOZ), - ORIGINAL_ALBUM_TITLE("otit",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - ORIGINAL_ARTIST("oart",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - ORIGINAL_LYRICIST("olyr",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - PART("com.apple.iTunes", "PART", TEXT, Tagger.PICARD), - PART_NUMBER("com.apple.iTunes","PARTNUMBER", TEXT, Tagger.JAIKOZ), - PART_OF_GAPLESS_ALBUM("pgap",Mp4TagFieldSubType.BYTE, INTEGER), - PART_TYPE("com.apple.iTunes","PART_TYPE", TEXT, Tagger.JAIKOZ), - PERFORMER("com.apple.iTunes", "Performer", TEXT, Tagger.PICARD), - PERFORMER_NAME("com.apple.iTunes","PERFORMER_NAME", TEXT, Tagger.JAIKOZ), - PERFORMER_NAME_SORT("com.apple.iTunes","PERFORMER_NAME_SORT", TEXT, Tagger.JAIKOZ), - PERIOD("com.apple.iTunes","PERIOD", TEXT, Tagger.JAIKOZ), - PL_ID("plID",Mp4TagFieldSubType.UNKNOWN, INTEGER, 8), - PODCAST_KEYWORD("keyw",Mp4TagFieldSubType.TEXT, TEXT), - PODCAST_URL("purl",Mp4TagFieldSubType.NUMBER, IMPLICIT), //TODO Actually seems to store text but is marked as numeric! - PRODUCER("com.apple.iTunes", "PRODUCER", TEXT, Tagger.PICARD), - PURCHASE_DATE("purd",Mp4TagFieldSubType.TEXT, TEXT), - QUALITY("qual",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - RANKING("com.apple.iTunes","RANKING", TEXT, Tagger.JAIKOZ), - 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), - REMIXER("com.apple.iTunes", "REMIXER", TEXT, Tagger.PICARD), - SCORE("rate",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), //As in mark out of 100 - SCRIPT("com.apple.iTunes", "SCRIPT", TEXT, Tagger.JAIKOZ), - SF_ID("sfID",Mp4TagFieldSubType.UNKNOWN, INTEGER, 4), - SHOW("tvsh",Mp4TagFieldSubType.TEXT, TEXT), //tv show but also used just as show - SHOW_SORT("sosn",Mp4TagFieldSubType.TEXT, TEXT), - SINGLE_DISC_TRACK_NO("com.apple.iTunes","SINGLE_DISC_TRACK_NO", TEXT, Tagger.JAIKOZ), - SUBTITLE("com.apple.iTunes", "SUBTITLE", TEXT, Tagger.PICARD), - TAGS("com.apple.iTunes", "TAGS", TEXT, Tagger.JAIKOZ), - TEMPO("empo",Mp4TagFieldSubType.TEXT, TEXT, Tagger.MEDIA_MONKEY), - TIMBRE("com.apple.iTunes", "TIMBRE_BRIGHTNESS", TEXT, Tagger.JAIKOZ), - TITLE("©nam",Mp4TagFieldSubType.TEXT, TEXT), - TITLE_MOVEMENT("com.apple.iTunes", "TITLE_MOVEMENT", TEXT, Tagger.JAIKOZ), - TITLE_SORT("sonm",Mp4TagFieldSubType.TEXT, TEXT), - TONALITY("com.apple.iTunes", "TONALITY", TEXT, Tagger.JAIKOZ), - TOOL("tool",Mp4TagFieldSubType.BYTE, INTEGER, 4), - TRACK("trkn",Mp4TagFieldSubType.TRACK_NO, IMPLICIT), - TV_EPISODE("tves",Mp4TagFieldSubType.BYTE, INTEGER, 1), - TV_EPISODE_NUMBER("tven",Mp4TagFieldSubType.TEXT, TEXT), - TV_NETWORK("tvnn",Mp4TagFieldSubType.TEXT, TEXT), - TV_SEASON("tvsn",Mp4TagFieldSubType.BYTE, INTEGER, 1), - URL_DISCOGS_ARTIST_SITE("com.apple.iTunes", "URL_DISCOGS_ARTIST_SITE", TEXT, Tagger.JAIKOZ), - URL_DISCOGS_RELEASE_SITE("com.apple.iTunes", "URL_DISCOGS_RELEASE_SITE", TEXT, Tagger.JAIKOZ), - URL_LYRICS_SITE("com.apple.iTunes", "URL_LYRICS_SITE", TEXT, Tagger.JAIKOZ), - URL_OFFICIAL_ARTIST_SITE("com.apple.iTunes", "URL_OFFICIAL_ARTIST_SITE", TEXT, Tagger.JAIKOZ), - URL_OFFICIAL_RELEASE_SITE("com.apple.iTunes", "URL_OFFICIAL_RELEASE_SITE", TEXT, Tagger.JAIKOZ), - URL_WIKIPEDIA_ARTIST_SITE("com.apple.iTunes", "URL_WIKIPEDIA_ARTIST_SITE", TEXT, Tagger.JAIKOZ), - URL_WIKIPEDIA_RELEASE_SITE("com.apple.iTunes", "URL_WIKIPEDIA_RELEASE_SITE", TEXT, Tagger.JAIKOZ), - WINAMP_PUBLISHER("com.nullsoft.winamp", "publisher", TEXT, Tagger.WINAMP), - WORK("©wrk",Mp4TagFieldSubType.TEXT, TEXT), - WORK_TYPE("com.apple.iTunes","WORK_TYPE", TEXT, Tagger.JAIKOZ), - ; - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java deleted file mode 100644 index dd6dc11d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4NonStandardFieldKey.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4; - -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4Tag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4Tag.java deleted file mode 100644 index 6cbb3553..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4Tag.java +++ /dev/null @@ -1,938 +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 com.mp3.jaudiotagger.tag.mp4; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.AbstractTag; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.jaudiotagger.tag.mp4.field.*; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; - -import static com.mp3.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.ACOUSTID_FINGERPRINT, Mp4FieldKey.ACOUSTID_FINGERPRINT); - tagFieldToMp4Field.put(FieldKey.ACOUSTID_ID, Mp4FieldKey.ACOUSTID_ID); - 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_ARTISTS, Mp4FieldKey.ALBUM_ARTISTS); - tagFieldToMp4Field.put(FieldKey.ALBUM_ARTISTS_SORT, Mp4FieldKey.ALBUM_ARTISTS_SORT); - tagFieldToMp4Field.put(FieldKey.ALBUM_SORT, Mp4FieldKey.ALBUM_SORT); - tagFieldToMp4Field.put(FieldKey.AMAZON_ID, Mp4FieldKey.ASIN); - tagFieldToMp4Field.put(FieldKey.ARRANGER, Mp4FieldKey.ARRANGER); - tagFieldToMp4Field.put(FieldKey.ARRANGER_SORT, Mp4FieldKey.ARRANGER_SORT); - tagFieldToMp4Field.put(FieldKey.ARTIST, Mp4FieldKey.ARTIST); - tagFieldToMp4Field.put(FieldKey.ARTISTS, Mp4FieldKey.ARTISTS); - tagFieldToMp4Field.put(FieldKey.ARTIST_SORT, Mp4FieldKey.ARTIST_SORT); - tagFieldToMp4Field.put(FieldKey.ARTISTS_SORT, Mp4FieldKey.ARTISTS_SORT); - tagFieldToMp4Field.put(FieldKey.BARCODE, Mp4FieldKey.BARCODE); - tagFieldToMp4Field.put(FieldKey.BPM, Mp4FieldKey.BPM); - tagFieldToMp4Field.put(FieldKey.CATALOG_NO, Mp4FieldKey.CATALOGNO); - tagFieldToMp4Field.put(FieldKey.CHOIR, Mp4FieldKey.CHOIR); - tagFieldToMp4Field.put(FieldKey.CHOIR_SORT, Mp4FieldKey.CHOIR_SORT); - tagFieldToMp4Field.put(FieldKey.CLASSICAL_CATALOG, Mp4FieldKey.CLASSICAL_CATALOG); - tagFieldToMp4Field.put(FieldKey.CLASSICAL_NICKNAME, Mp4FieldKey.CLASSICAL_NICKNAME); - 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.COUNTRY, Mp4FieldKey.COUNTRY); - tagFieldToMp4Field.put(FieldKey.CONDUCTOR_SORT, Mp4FieldKey.CONDUCTOR_SORT); - tagFieldToMp4Field.put(FieldKey.COPYRIGHT, Mp4FieldKey.COPYRIGHT); - 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.DJMIXER, Mp4FieldKey.DJMIXER); - tagFieldToMp4Field.put(FieldKey.MOOD_ELECTRONIC, Mp4FieldKey.MOOD_ELECTRONIC); - tagFieldToMp4Field.put(FieldKey.ENCODER, Mp4FieldKey.ENCODER); - tagFieldToMp4Field.put(FieldKey.ENGINEER, Mp4FieldKey.ENGINEER); - tagFieldToMp4Field.put(FieldKey.ENSEMBLE, Mp4FieldKey.ENSEMBLE); - tagFieldToMp4Field.put(FieldKey.ENSEMBLE_SORT, Mp4FieldKey.ENSEMBLE_SORT); - tagFieldToMp4Field.put(FieldKey.FBPM, Mp4FieldKey.FBPM); - tagFieldToMp4Field.put(FieldKey.GENRE, Mp4FieldKey.GENRE); - tagFieldToMp4Field.put(FieldKey.GROUP, Mp4FieldKey.GROUP); - tagFieldToMp4Field.put(FieldKey.GROUPING, Mp4FieldKey.GROUPING); - tagFieldToMp4Field.put(FieldKey.INSTRUMENT, Mp4FieldKey.INSTRUMENT); - tagFieldToMp4Field.put(FieldKey.INVOLVED_PERSON, Mp4FieldKey.INVOLVED_PEOPLE); - tagFieldToMp4Field.put(FieldKey.ISRC, Mp4FieldKey.ISRC); - tagFieldToMp4Field.put(FieldKey.IS_COMPILATION, Mp4FieldKey.COMPILATION); - tagFieldToMp4Field.put(FieldKey.IS_CLASSICAL, Mp4FieldKey.IS_CLASSICAL); - tagFieldToMp4Field.put(FieldKey.IS_SOUNDTRACK, Mp4FieldKey.IS_SOUNDTRACK); - 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.MIXER, Mp4FieldKey.MIXER); - tagFieldToMp4Field.put(FieldKey.MOOD, Mp4FieldKey.MOOD); - tagFieldToMp4Field.put(FieldKey.MOOD_ACOUSTIC, Mp4FieldKey.MOOD_ACOUSTIC); - tagFieldToMp4Field.put(FieldKey.MOOD_AGGRESSIVE, Mp4FieldKey.MOOD_AGGRESSIVE); - tagFieldToMp4Field.put(FieldKey.MOOD_AROUSAL, Mp4FieldKey.MOOD_AROUSAL); - tagFieldToMp4Field.put(FieldKey.MOOD_DANCEABILITY, Mp4FieldKey.MOOD_DANCEABILITY); - tagFieldToMp4Field.put(FieldKey.MOOD_HAPPY, Mp4FieldKey.MOOD_HAPPY); - tagFieldToMp4Field.put(FieldKey.MOOD_INSTRUMENTAL, Mp4FieldKey.MOOD_INSTRUMENTAL); - tagFieldToMp4Field.put(FieldKey.MOOD_PARTY, Mp4FieldKey.MOOD_PARTY); - tagFieldToMp4Field.put(FieldKey.MOOD_RELAXED, Mp4FieldKey.MOOD_RELAXED); - tagFieldToMp4Field.put(FieldKey.MOOD_SAD, Mp4FieldKey.MOOD_SAD); - tagFieldToMp4Field.put(FieldKey.MOOD_VALENCE, Mp4FieldKey.MOOD_VALENCE); - tagFieldToMp4Field.put(FieldKey.MOVEMENT, Mp4FieldKey.MOVEMENT); - tagFieldToMp4Field.put(FieldKey.MOVEMENT_NO, Mp4FieldKey.MOVEMENT_NO); - tagFieldToMp4Field.put(FieldKey.MOVEMENT_TOTAL, Mp4FieldKey.MOVEMENT_TOTAL); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK, Mp4FieldKey.MUSICBRAINZ_WORK); - 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_TRACK_ID, Mp4FieldKey.MUSICBRAINZ_RELEASE_TRACKID); - 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.MUSICBRAINZ_WORK_COMPOSITION_ID, Mp4FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION, Mp4FieldKey.MUSICBRAINZ_WORK_COMPOSITION); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6); - tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, Mp4FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE); - tagFieldToMp4Field.put(FieldKey.MUSICIP_ID, Mp4FieldKey.MUSICIP_PUID); - tagFieldToMp4Field.put(FieldKey.OCCASION, Mp4FieldKey.MM_OCCASION); - tagFieldToMp4Field.put(FieldKey.OPUS, Mp4FieldKey.OPUS); - tagFieldToMp4Field.put(FieldKey.ORCHESTRA, Mp4FieldKey.ORCHESTRA); - tagFieldToMp4Field.put(FieldKey.ORCHESTRA_SORT, Mp4FieldKey.ORCHESTRA_SORT); - 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.PART, Mp4FieldKey.PART); - tagFieldToMp4Field.put(FieldKey.PART_NUMBER, Mp4FieldKey.PART_NUMBER); - tagFieldToMp4Field.put(FieldKey.PART_TYPE, Mp4FieldKey.PART_TYPE); - tagFieldToMp4Field.put(FieldKey.PERFORMER, Mp4FieldKey.PERFORMER); - tagFieldToMp4Field.put(FieldKey.PERFORMER_NAME, Mp4FieldKey.PERFORMER_NAME); - tagFieldToMp4Field.put(FieldKey.PERFORMER_NAME_SORT, Mp4FieldKey.PERFORMER_NAME_SORT); - tagFieldToMp4Field.put(FieldKey.PERIOD, Mp4FieldKey.PERIOD); - tagFieldToMp4Field.put(FieldKey.PRODUCER, Mp4FieldKey.PRODUCER); - tagFieldToMp4Field.put(FieldKey.QUALITY, Mp4FieldKey.MM_QUALITY); - tagFieldToMp4Field.put(FieldKey.RANKING, Mp4FieldKey.RANKING); - 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.SINGLE_DISC_TRACK_NO, Mp4FieldKey.SINGLE_DISC_TRACK_NO); - tagFieldToMp4Field.put(FieldKey.SUBTITLE, Mp4FieldKey.SUBTITLE); - tagFieldToMp4Field.put(FieldKey.TAGS, Mp4FieldKey.TAGS); - tagFieldToMp4Field.put(FieldKey.TEMPO, Mp4FieldKey.TEMPO); - tagFieldToMp4Field.put(FieldKey.TIMBRE, Mp4FieldKey.TIMBRE); - tagFieldToMp4Field.put(FieldKey.TITLE, Mp4FieldKey.TITLE); - tagFieldToMp4Field.put(FieldKey.TITLE_MOVEMENT, Mp4FieldKey.TITLE_MOVEMENT); - tagFieldToMp4Field.put(FieldKey.TITLE_SORT, Mp4FieldKey.TITLE_SORT); - tagFieldToMp4Field.put(FieldKey.TONALITY, Mp4FieldKey.TONALITY); - 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.WORK, Mp4FieldKey.WORK); - tagFieldToMp4Field.put(FieldKey.YEAR, Mp4FieldKey.DAY); - tagFieldToMp4Field.put(FieldKey.WORK_TYPE, Mp4FieldKey.WORK_TYPE); - } - - /** - * 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(Charset enc) - { - return StandardCharsets.UTF_8.equals(enc); - } - - 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.KEY) - { - if (list.size() == 0) - { - list = getFields(KEY_OLD.getFieldName()); - } - return list; - } - else 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 - * @throws com.mp3.jaudiotagger.tag.KeyNotFoundException - * @return - */ - 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 com.mp3.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.KEY) - { - deleteField(Mp4FieldKey.KEY_OLD); - deleteField(mp4FieldName); - } - else 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 if(genericKey == FieldKey.GENRE) - { - super.deleteField(Mp4FieldKey.GENRE.getFieldName()); - super.deleteField(Mp4FieldKey.GENRE_CUSTOM.getFieldName()); - } - else - { - super.deleteField(mp4FieldName); - } - } - - /** - * Delete fields with this mp4key - * - * @param mp4Key - * @throws com.mp3.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 com.mp3.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 values - * @return - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public TagField createField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (values == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - String value = values[0]; - - //Special handling for these number fields because multiple generic keys map to a single mp4 field - 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); - } - } - else if (genericKey == FieldKey.GENRE) - { - //Always write as text - if(TagOptionSingleton.getInstance().isWriteMp4GenresAsText()) - { - return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), value); - } - - if (Mp4GenreField.isValidGenre(value)) - { - return new Mp4GenreField(value); - } - else - { - return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), value); - } - } - //Default for all other fields - return createField(tagFieldToMp4Field.get(genericKey), value); - } - - /** - * Overidden to ensure cannot have both a genre field and a custom genre field - * - * @param genericKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public void setField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException - { - TagField tagfield = createField(genericKey,value); - - if(genericKey==FieldKey.GENRE) - { - if(tagfield.getId().equals(GENRE.getFieldName())) - { - this.deleteField(Mp4FieldKey.GENRE_CUSTOM); - } - else if(tagfield.getId().equals(GENRE_CUSTOM.getFieldName())) - { - this.deleteField(Mp4FieldKey.GENRE); - } - } - setField(tagfield); - } - - /** - * Set mp4 field - * @param fieldKey - * @param value - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - public void setField(Mp4FieldKey fieldKey, String value) throws KeyNotFoundException, FieldDataInvalidException - { - TagField tagfield = createField(fieldKey,value); - setField(tagfield); - } - /** - * 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 , any other values it is set to we treat as false - if(mp4FieldKey==Mp4FieldKey.COMPILATION) - { - if(value.equalsIgnoreCase("true") || value.equals("1")) - { - return createCompilationField(true); - } - else - { - return createCompilationField(false); - } - } - else if(mp4FieldKey==Mp4FieldKey.GENRE) - { - if (Mp4GenreField.isValidGenre(value)) - { - return new Mp4GenreField(value); - } - else - { - throw new IllegalArgumentException(ErrorMessage.NOT_STANDARD_MP$_GENRE.getMsg()); - } - } - else if(mp4FieldKey==Mp4FieldKey.GENRE_CUSTOM) - { - return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), 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; - } - - public TagField createCompilationField(boolean origValue) throws KeyNotFoundException, FieldDataInvalidException - { - String value = ""; - if(origValue) - { - value=Mp4TagByteField.TRUE_VALUE; - return new Mp4TagByteField(Mp4FieldKey.COMPILATION, value, Mp4FieldKey.COMPILATION.getFieldLength()); - } - else - { - value=Mp4TagByteField.FALSE_VALUE; - return new Mp4TagByteField(Mp4FieldKey.COMPILATION, value, Mp4FieldKey.COMPILATION.getFieldLength()); - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagCreator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagCreator.java deleted file mode 100644 index a9668efa..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagCreator.java +++ /dev/null @@ -1,151 +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 com.mp3.jaudiotagger.tag.mp4; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.AbstractTagCreator; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.Mp4AtomIdentifier; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.FieldKey; -import com.mp3.jaudiotagger.tag.KeyNotFoundException; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.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 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(Mp4FieldKey.ARTWORK.getFieldName().getBytes(StandardCharsets.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(Mp4AtomIdentifier.ILST.getFieldName().getBytes(StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagField.java deleted file mode 100644 index d792762d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagField.java +++ /dev/null @@ -1,193 +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 com.mp3.jaudiotagger.tag.mp4; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import com.mp3.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("com.mp3.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 getId().getBytes(StandardCharsets.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(getId().getBytes(StandardCharsets.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(Mp4DataBox.IDENTIFIER.getBytes(StandardCharsets.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java deleted file mode 100644 index b656c0fd..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/Mp4TagFieldSubType.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java deleted file mode 100644 index 18b7caeb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4ContentTypeValue.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4DataBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4DataBox.java deleted file mode 100644 index a30199bb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4DataBox.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.atom; - -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.AbstractMp4Box; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.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; - - private int type; - private String content; - - public static final int NUMBER_LENGTH = 2; - - //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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java deleted file mode 100644 index 6dbd07f6..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4MeanBox.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.atom; - -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.AbstractMp4Box; -import com.mp3.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"; - - private String issuer; - - //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; - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4NameBox.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4NameBox.java deleted file mode 100644 index c335b6f5..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4NameBox.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.atom; - -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.AbstractMp4Box; -import com.mp3.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"; - - private String 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; - - /** - * @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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java deleted file mode 100644 index 9306a1c1..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/atom/Mp4RatingValue.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java deleted file mode 100644 index 479b82fb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4DiscNoField.java +++ /dev/null @@ -1,177 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.FieldDataInvalidException; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4FieldType.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4FieldType.java deleted file mode 100644 index ee93a473..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4FieldType.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.mp3.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 int fileClassId; - - Mp4FieldType(int fileClassId) - { - this.fileClassId = fileClassId; - } - - public int getFileClassId() - { - return fileClassId; - } - - private final static HashMap fileClassIdFiedTypeMap; - - static - { - fileClassIdFiedTypeMap = new HashMap(Mp4FieldType.values().length); - for (Mp4FieldType curr : Mp4FieldType.values()) - { - fileClassIdFiedTypeMap.put(curr.fileClassId,curr); - } - } - - /** - * - * @param fieldClassId - * @return the Mp4FieldType that this fieldClassId maps to - */ - public static Mp4FieldType getFieldType(int fieldClassId) - { - return fileClassIdFiedTypeMap.get(fieldClassId); - } - - private static EnumSet coverArtTypes; - static - { - coverArtTypes = EnumSet.of(COVERART_GIF,COVERART_JPEG,COVERART_PNG,COVERART_BMP); - } - - /** - * - * @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); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4GenreField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4GenreField.java deleted file mode 100644 index 29672d04..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4GenreField.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import com.mp3.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); - } - - /** - * 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; - } - - /** - * 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 <= 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)); - } - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.java deleted file mode 100644 index a7817802..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagBinaryField.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 com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.mp4.Mp4TagField; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagByteField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagByteField.java deleted file mode 100644 index 859cde28..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagByteField.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.FieldDataInvalidException; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.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 - public static String FALSE_VALUE="0"; - //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 com.mp3.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 com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java deleted file mode 100644 index 1082a746..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagCoverField.java +++ /dev/null @@ -1,202 +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 com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.id3.valuepair.ImageFormats; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import com.mp3.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()); - } - - /** - * @return data and header size - */ - public int getDataAndHeaderSize() - { - return dataAndHeaderSize; - } - - /** - * 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; - } - } - - - /** - * 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 - } - - /** - * - * @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; - } - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java deleted file mode 100644 index fcae44a0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagRawBinaryField.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.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 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 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(getId().getBytes(StandardCharsets.ISO_8859_1)); - outerbaos.write(dataBytes); - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java deleted file mode 100644 index cd06cad2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagReverseDnsField.java +++ /dev/null @@ -1,301 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.TagTextField; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.jaudiotagger.tag.mp4.Mp4TagField; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4DataBox; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4MeanBox; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4NameBox; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - -/** - * 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; - - //Issuer - private String issuer; - - //Descriptor - private String descriptor; - - //Data Content, - //TODO assuming always text at the moment - protected String content; - - /** - * 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; - } - - @Override - 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; - } - - @Override - 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; - } - } - - @Override - public void copyContent(TagField field) - { - if (field instanceof Mp4TagReverseDnsField) - { - this.issuer = ((Mp4TagReverseDnsField) field).getIssuer(); - this.descriptor = ((Mp4TagReverseDnsField) field).getDescriptor(); - this.content = ((Mp4TagReverseDnsField) field).getContent(); - } - } - - @Override - public String getContent() - { - return content; - } - - @Override - protected byte[] getDataBytes() throws UnsupportedEncodingException - { - return content.getBytes(getEncoding()); - } - - @Override - public Charset getEncoding() - { - return StandardCharsets.UTF_8; - } - - /** - * Convert back to raw content, includes ----,mean,name and data atom as views as one thing externally - * - * @return - * @throws UnsupportedEncodingException - */ - @Override - 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(Mp4MeanBox.IDENTIFIER.getBytes(StandardCharsets.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(Mp4NameBox.IDENTIFIER.getBytes(StandardCharsets.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(IDENTIFIER.getBytes(StandardCharsets.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); - } - } - - @Override - 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(Mp4DataBox.IDENTIFIER.getBytes(StandardCharsets.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); - } - } - - @Override - public boolean isBinary() - { - return false; - } - - @Override - public boolean isEmpty() - { - return "".equals(this.content.trim()); - } - - @Override - public void setContent(String s) - { - this.content = s; - } - - @Override - public void setEncoding(Charset s) - { - /* Not allowed */ - } - - @Override - public String toString() - { - return content; - } - - /** - * @return the issuer - */ - public String getIssuer() - { - return issuer; - } - - /** - * @return the descriptor - */ - public String getDescriptor() - { - return descriptor; - } - - /** - * Set the issuer, usually reverse dns of the Companies domain - * - * @param issuer - */ - public void setIssuer(String issuer) - { - this.issuer = issuer; - } - - /** - * 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextField.java deleted file mode 100644 index 8a00f211..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextField.java +++ /dev/null @@ -1,154 +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 com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.TagTextField; -import com.mp3.jaudiotagger.tag.mp4.Mp4TagField; -import com.mp3.jaudiotagger.tag.mp4.atom.Mp4DataBox; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - -/** - * 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 initialized 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() contains 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; - } - - @Override - 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(); - } - - @Override - public void copyContent(TagField field) - { - if (field instanceof Mp4TagTextField) - { - this.content = ((Mp4TagTextField) field).getContent(); - } - } - - @Override - public String getContent() - { - return content; - } - - @Override - protected byte[] getDataBytes() throws UnsupportedEncodingException - { - return content.getBytes(getEncoding()); - } - - @Override - public Mp4FieldType getFieldType() - { - return Mp4FieldType.TEXT; - } - - @Override - public Charset getEncoding() - { - return StandardCharsets.UTF_8; - } - - @Override - public boolean isBinary() - { - return false; - } - - @Override - public boolean isEmpty() - { - return this.content.trim().equals(""); - } - - @Override - public void setContent(String s) - { - this.content = s; - } - - @Override - public void setEncoding(Charset s) - { - /* Not allowed */ - } - - @Override - public String toString() - { - return content; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java deleted file mode 100644 index 03869f8c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TagTextNumberField.java +++ /dev/null @@ -1,117 +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 com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TrackField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TrackField.java deleted file mode 100644 index c422d040..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/mp4/field/Mp4TrackField.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.mp3.jaudiotagger.tag.mp4.field; - -import com.mp3.jaudiotagger.audio.mp4.atom.Mp4BoxHeader; -import com.mp3.jaudiotagger.tag.FieldDataInvalidException; -import com.mp3.jaudiotagger.tag.mp4.Mp4FieldKey; -import com.mp3.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 com.mp3.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); - } - - /** - * @return - */ - public Short getTrackTotal() - { - if(numbers.size()<=TRACK_TOTAL_INDEX) - { - return 0; - } - return numbers.get(TRACK_TOTAL_INDEX); - } - - /** - * Set Track No - * - * @param trackNo - */ - public void setTrackNo(int trackNo) - { - numbers.set(TRACK_NO_INDEX, (short) trackNo); - } - - - /** - * Set total number of tracks - * - * @param trackTotal - */ - public void setTrackTotal(int trackTotal) - { - numbers.set(TRACK_TOTAL_INDEX, (short) trackTotal); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/options/PadNumberOption.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/options/PadNumberOption.java deleted file mode 100644 index 64035293..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/options/PadNumberOption.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/GenreTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/GenreTypes.java deleted file mode 100644 index a3c139ca..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/GenreTypes.java +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - */ -package com.mp3.jaudiotagger.tag.reference; - -import com.mp3.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 final int MAX_STANDARD_GENRE_ID = 125; - private static final int MAX_GENRE_ID = 191; - - /** - * @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 int getMaxGenreId() - { - return MAX_GENRE_ID; - } - - private static GenreTypes genreTypes; - - public static GenreTypes getInstanceOf() - { - if (genreTypes == null) - { - genreTypes = new GenreTypes(); - } - return 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"); // to say the least - this name is problematic - 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"); - - // additional Winamp 5.6 values taken from http://en.wikipedia.org/wiki/ID3#Winamp_Extensions - idToValue.put(148, "Abstract"); - idToValue.put(149, "Art Rock"); - idToValue.put(150, "Baroque"); - idToValue.put(151, "Bhangra"); - idToValue.put(152, "Big Beat"); - idToValue.put(153, "Breakbeat"); - idToValue.put(154, "Chillout"); - idToValue.put(155, "Downtempo"); - idToValue.put(156, "Dub"); - idToValue.put(157, "EBM"); - idToValue.put(158, "Eclectic"); - idToValue.put(159, "Electro"); - idToValue.put(160, "Electroclash"); - idToValue.put(161, "Emo"); - idToValue.put(162, "Experimental"); - idToValue.put(163, "Garage"); - idToValue.put(164, "Global"); - idToValue.put(165, "IDM"); - idToValue.put(166, "Illbient"); - idToValue.put(167, "Industro-Goth"); - idToValue.put(168, "Jam Band"); - idToValue.put(169, "Krautrock"); - idToValue.put(170, "Leftfield"); - idToValue.put(171, "Lounge"); - idToValue.put(172, "Math Rock"); - idToValue.put(173, "New Romantic"); - idToValue.put(174, "Nu-Breakz"); - idToValue.put(175, "Post-Punk"); - idToValue.put(176, "Post-Rock"); - idToValue.put(177, "Psytrance"); - idToValue.put(178, "Shoegaze"); - idToValue.put(179, "Space Rock"); - idToValue.put(180, "Trop Rock"); - idToValue.put(181, "World Music"); - idToValue.put(182, "Neoclassical"); - idToValue.put(183, "Audiobook"); - idToValue.put(184, "Audio Theatre"); - idToValue.put(185, "Neue Deutsche Welle"); - idToValue.put(186, "Podcast"); - idToValue.put(187, "Indie Rock"); - idToValue.put(188, "G-Funk"); - idToValue.put(189, "Dubstep"); - idToValue.put(190, "Garage Rock"); - idToValue.put(191, "Psybient"); - - 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()); - } - } - - /** - * Get Id for name, match is not case sensitive - * - * @param name genre name - * @return id or {@code null}, if not found - */ - public Integer getIdForName(String name) - { - return nameToIdMap.get(name.toLowerCase()); - } - - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ID3V2Version.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ID3V2Version.java deleted file mode 100644 index 30775485..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ID3V2Version.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.mp3.jaudiotagger.tag.reference; - -/** - * Defines ID3V2 Versions - */ -public enum ID3V2Version -{ - ID3_V22, - ID3_V23, - ID3_V24, - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOCountry.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOCountry.java deleted file mode 100644 index 226d2195..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOCountry.java +++ /dev/null @@ -1,342 +0,0 @@ -package com.mp3.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); - } - - /** - * List of valid Iso Country, shows 2 letter abbreviation and country human readable name - */ - public static 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(); - } - } - - public static String[] getDescriptionsAsArray() - { - List descriptions = new ArrayList(); - for (Country country : Country.values()) - { - descriptions.add(country.description); - } - return descriptions.toArray(new String[0]); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOScript.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOScript.java deleted file mode 100644 index d60305c0..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/ISOScript.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.mp3.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); - } - - /** - * List of valid Iso Scripts, shows 4 letter abbreviation and script human readable name - */ - public static 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(); - } - } - - public static String[] getDescriptionsAsArray() - { - List descriptions = new ArrayList(); - for(Script script:Script.values()) - { - descriptions.add(script.description); - } - return descriptions.toArray(new String[0]); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Languages.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Languages.java deleted file mode 100644 index a9d5bb2f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Languages.java +++ /dev/null @@ -1,523 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Valid Languages for ID Tags - */ -package com.mp3.jaudiotagger.tag.reference; - -import com.mp3.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; - - - public static Languages getInstanceOf() - { - if (languageTypes == null) - { - languageTypes = new Languages(); - } - return 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(); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/MusicalKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/MusicalKey.java deleted file mode 100644 index 1e4d19d2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/MusicalKey.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.mp3.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 String value; - MusicalKey(String value) - { - this.value=value; - } - - public String getValue() - { - return value; - } - - 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); - } - } - - 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; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PerformerHelper.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PerformerHelper.java deleted file mode 100644 index 2c74fcae..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PerformerHelper.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mp3.jaudiotagger.tag.reference; - -/** - * The PERFORMER field is formatted differently depending on whether writing to the ID3 format that utilises multiple fields or the simple - * TEXT/VALUE fields used by VorbisComments and similar formats, the role is always set to lowercase. - */ -public class PerformerHelper -{ - public static String formatForId3(String artist, String attributes) - { - return attributes.toLowerCase() + '\0' + artist; - } - - public static String formatForNonId3(String artist, String attributes) - { - return artist + " (" + attributes.toLowerCase() + ")"; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PictureTypes.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PictureTypes.java deleted file mode 100644 index 7eab7a96..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/PictureTypes.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @author : Paul Taylor - * - * Version @version:$Id$ - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Description: - * Valid Picture Types in ID3 - */ -package com.mp3.jaudiotagger.tag.reference; - -import com.mp3.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 -{ - private static PictureTypes pictureTypes; - - public static PictureTypes getInstanceOf() - { - if (pictureTypes == null) - { - pictureTypes = new PictureTypes(); - } - return pictureTypes; - } - - 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 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(); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Tagger.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Tagger.java deleted file mode 100644 index 8fe4b45d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/reference/Tagger.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.mp3.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"), - MUSICHI(15, "Musichi"), - ; - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistReadOptions.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistReadOptions.java deleted file mode 100644 index e20da914..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistReadOptions.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.mp3.jaudiotagger.tag.vorbiscomment; - -/** - * Unfortunately there are two diverging values for the AlbumArtist field when used in VorbisComments - * (as used by Ogg and Flac).e.g 'ALBUMARTIST' is the standard used by FooBar, Jaikoz, whereas JRiver and Winamp - * prefer ALBUM ARTIST - * - * This option allows you to configure jaudiotaggers behaviour accordingly when reading metadata from a file - */ -public enum VorbisAlbumArtistReadOptions -{ - READ_ALBUMARTIST, - READ_JRIVER_ALBUMARTIST, - READ_ALBUMARTIST_THEN_JRIVER, - READ_JRIVER_THEN_ALBUMARTIST, - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistSaveOptions.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistSaveOptions.java deleted file mode 100644 index 4c937e16..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisAlbumArtistSaveOptions.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mp3.jaudiotagger.tag.vorbiscomment; - -/** - * Unfortunately there are two diverging values for the AlbumArtist field when used in VorbisComments - * (as used by Ogg and Flac).e.g 'ALBUMARTIST' is the standard used by FooBar, Jaikoz, whereas JRiver and Winamp - * prefer ALBUM ARTIST - * - * This option allows you to configure jaudiotaggers behaviour accordingly - */ -public enum VorbisAlbumArtistSaveOptions -{ - WRITE_ALBUMARTIST, - WRITE_JRIVER_ALBUMARTIST, - WRITE_BOTH, - WRITE_ALBUMARTIST_AND_DELETE_JRIVER_ALBUMARTIST, - WRITE_JRIVER_ALBUMARTIST_AND_DELETE_ALBUMARTIST, - ; -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.java deleted file mode 100644 index b1c73153..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentCreator.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 com.mp3.jaudiotagger.tag.vorbiscomment; - -import com.mp3.jaudiotagger.audio.generic.AbstractTagCreator; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.tag.Tag; -import com.mp3.jaudiotagger.tag.TagField; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.Iterator; - -import static com.mp3.jaudiotagger.StandardCharsets.UTF_8; - -/** - * 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 = vendorString.getBytes(UTF_8).length; - baos.write(Utils.getSizeLEInt32(vendorLength)); - baos.write(vendorString.getBytes(UTF_8)); - - //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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java deleted file mode 100644 index 97918307..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentFieldKey.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.mp3.jaudiotagger.tag.vorbiscomment; - -import com.mp3.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 -{ - ACOUSTID_FINGERPRINT("ACOUSTID_FINGERPRINT",EnumSet.of(Tagger.PICARD)), - ACOUSTID_ID("ACOUSTID_ID",EnumSet.of(Tagger.PICARD)), - ALBUM("ALBUM", EnumSet.of(Tagger.XIPH,Tagger.PICARD,Tagger.JAIKOZ)), - ALBUMARTIST("ALBUMARTIST",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - ALBUMARTISTSORT("ALBUMARTISTSORT",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - ALBUMARTISTS("ALBUM_ARTISTS",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - ALBUMARTISTSSORT("ALBUM_ARTISTS_SORT",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - ALBUMARTIST_JRIVER("ALBUM ARTIST",EnumSet.of(Tagger.JRIVER)), - ALBUMSORT("ALBUMSORT",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - ALBUM_ARTIST("ALBUM_ARTIST",EnumSet.of(Tagger.MEDIA_MONKEY)), - ARRANGER("ARRANGER",EnumSet.of(Tagger.PICARD)), - ARRANGER_SORT("ARRANGER_SORT",EnumSet.of(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)), - ARTISTS_SORT("ARTISTS_SORT",EnumSet.of(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)), - CHOIR("CHOIR",EnumSet.of(Tagger.JAIKOZ)), - CHOIR_SORT("CHOIR_SORT",EnumSet.of(Tagger.JAIKOZ)), - CLASSICAL_CATALOG("CLASSICAL_CATALOG",EnumSet.of(Tagger.JAIKOZ)), - CLASSICAL_NICKNAME("CLASSICAL_NICKNAME",EnumSet.of(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)), - CONDUCTOR_SORT("CONDUCTOR_SORT",EnumSet.of(Tagger.JAIKOZ)), - CONTACT("CONTACT",EnumSet.of(Tagger.XIPH)), - COPYRIGHT("COPYRIGHT",EnumSet.of(Tagger.XIPH,Tagger.PICARD,Tagger.JAIKOZ)), - COUNTRY("COUNTRY",EnumSet.of(Tagger.PICARD)), - 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)), - DJMIXER("DJMIXER",EnumSet.of(Tagger.PICARD)), - ENCODEDBY("ENCODEDBY",EnumSet.of(Tagger.PICARD)), - ENCODER("ENCODER"), - ENGINEER("ENGINEER",EnumSet.of(Tagger.PICARD)), - ENSEMBLE("ENSEMBLE",EnumSet.of(Tagger.MEDIA_MONKEY, Tagger.JAIKOZ)), - ENSEMBLE_SORT("ENSEMBLE_SORT",EnumSet.of(Tagger.JAIKOZ)), - FBPM("FBPM",EnumSet.of(Tagger.BEATUNES)), - GENRE("GENRE",EnumSet.of(Tagger.XIPH,Tagger.PICARD,Tagger.JAIKOZ)), - GROUP("GROUP",EnumSet.of(Tagger.JAIKOZ)), - GROUPING("GROUPING",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - INSTRUMENT("INSTRUMENT",EnumSet.of(Tagger.JAIKOZ)), - INVOLVED_PERSON("INVOLVED_PERSON", EnumSet.of(Tagger.JAIKOZ)), - ISRC("ISRC",EnumSet.of(Tagger.XIPH,Tagger.PICARD,Tagger.JAIKOZ)), - IS_CLASSICAL("IS_CLASSICAL",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - IS_SOUNDTRACK("IS_SOUNDTRACK",EnumSet.of(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)), - MIXER("MIXER",EnumSet.of(Tagger.PICARD)), - MOOD("MOOD",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - MOOD_ACOUSTIC("MOOD_ACOUSTIC", EnumSet.of(Tagger.JAIKOZ)), - MOOD_AGGRESSIVE("MOOD_AGGRESSIVE", EnumSet.of(Tagger.JAIKOZ)), - MOOD_AROUSAL("MOOD_AROUSAL", EnumSet.of(Tagger.JAIKOZ)), - MOOD_DANCEABILITY("MOOD_DANCEABILITY", EnumSet.of(Tagger.JAIKOZ)), - MOOD_ELECTRONIC("MOOD_ELECTRONIC", EnumSet.of(Tagger.JAIKOZ)), - MOOD_HAPPY("MOOD_HAPPY", EnumSet.of(Tagger.JAIKOZ)), - MOOD_INSTRUMENTAL("MOOD_INSTRUMENTAL", EnumSet.of(Tagger.JAIKOZ)), - MOOD_PARTY("MOOD_PARTY", EnumSet.of(Tagger.JAIKOZ)), - MOOD_RELAXED("MOOD_RELAXED", EnumSet.of(Tagger.JAIKOZ)), - MOOD_SAD("MOOD_SAD", EnumSet.of(Tagger.JAIKOZ)), - MOOD_VALENCE("MOOD_VALENCE", EnumSet.of(Tagger.JAIKOZ)), - MOVEMENT("MOVEMENT", EnumSet.of(Tagger.JAIKOZ)), - MOVEMENT_NO("MOVEMENT_NO", EnumSet.of(Tagger.JAIKOZ)), - MOVEMENT_TOTAL("MOVEMENT_TOTAL", EnumSet.of(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_RELEASETRACKID("MUSICBRAINZ_RELEASETRACKID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_TRACKID("MUSICBRAINZ_TRACKID",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - MUSICBRAINZ_WORK("MUSICBRAINZ_WORK", EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORKID("MUSICBRAINZ_WORKID",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_COMPOSITION("MUSICBRAINZ_WORK_COMPOSITION",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_COMPOSITION_ID("MUSICBRAINZ_WORK_COMPOSITION_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL1("MUSICBRAINZ_WORK_PART_LEVEL1",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL1_ID("MUSICBRAINZ_WORK_PART_LEVEL1_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL1_TYPE("MUSICBRAINZ_WORK_PART_LEVEL1_TYPE",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL2("MUSICBRAINZ_WORK_PART_LEVEL2",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL2_ID("MUSICBRAINZ_WORK_PART_LEVEL2_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL2_TYPE("MUSICBRAINZ_WORK_PART_LEVEL2_TYPE",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL3("MUSICBRAINZ_WORK_PART_LEVEL3",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL3_ID("MUSICBRAINZ_WORK_PART_LEVEL3_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL3_TYPE("MUSICBRAINZ_WORK_PART_LEVEL3_TYPE",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL4_ID("MUSICBRAINZ_WORK_PART_LEVEL4_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL4("MUSICBRAINZ_WORK_PART_LEVEL4",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL4_TYPE("MUSICBRAINZ_WORK_PART_LEVEL4_TYPE",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL5("MUSICBRAINZ_WORK_PART_LEVEL5",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL5_ID("MUSICBRAINZ_WORK_PART_LEVEL5_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL5_TYPE("MUSICBRAINZ_WORK_PART_LEVEL5_TYPE",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL6("MUSICBRAINZ_WORK_PART_LEVEL6",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL6_ID("MUSICBRAINZ_WORK_PART_LEVEL6_ID",EnumSet.of(Tagger.JAIKOZ)), - MUSICBRAINZ_WORK_PART_LEVEL6_TYPE("MUSICBRAINZ_WORK_PART_LEVEL6_TYPE",EnumSet.of(Tagger.JAIKOZ)), - MUSICIAN("MUSICIAN", EnumSet.of(Tagger.JAIKOZ)), - MUSICIP_PUID("MUSICIP_PUID",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - OCCASION("OCCASION",EnumSet.of(Tagger.MEDIA_MONKEY)), - OPUS("OPUS",EnumSet.of(Tagger.JAIKOZ)), - ORCHESTRA("ORCHESTRA",EnumSet.of(Tagger.JAIKOZ)), - ORCHESTRA_SORT("ORCHESTRA_SORT",EnumSet.of(Tagger.JAIKOZ)), - 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)), - PART("PART",EnumSet.of(Tagger.JAIKOZ)), - PART_NUMBER("PARTNUMBER",EnumSet.of(Tagger.XIPH)), - PART_TYPE("PART_TYPE",EnumSet.of(Tagger.JAIKOZ)), - PERFORMER("PERFORMER",EnumSet.of(Tagger.XIPH,Tagger.PICARD)), - PERFORMER_NAME("PERFORMER_NAME",EnumSet.of(Tagger.JAIKOZ)), - PERFORMER_NAME_SORT("PERFORMER_NAME_SORT",EnumSet.of(Tagger.JAIKOZ)), - PERIOD("PERIOD",EnumSet.of(Tagger.MUSICHI)), - PRODUCER("PRODUCER",EnumSet.of(Tagger.PICARD)), - PRODUCTNUMBER("PRODUCTNUMBER",EnumSet.of(Tagger.XIPH)), - QUALITY("QUALITY",EnumSet.of(Tagger.MEDIA_MONKEY)), - RANKING("RANKING",EnumSet.of(Tagger.JAIKOZ)), - 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)), - SINGLE_DISC_TRACK_NO("SINGLE_DISC_TRACK_NO",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)), - TIMBRE("TIMBRE_BRIGHTNESS", EnumSet.of(Tagger.JAIKOZ)), - TITLE("TITLE", EnumSet.of(Tagger.XIPH,Tagger.PICARD,Tagger.JAIKOZ)), - TITLE_MOVEMENT("TITLE_MOVEMENT", EnumSet.of(Tagger.JAIKOZ)), - TITLESORT("TITLESORT",EnumSet.of(Tagger.PICARD,Tagger.JAIKOZ)), - TONALITY("TONALITY", EnumSet.of(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) - WORK("WORK",EnumSet.of(Tagger.JAIKOZ)), - WORK_TYPE("WORK_TYPE",EnumSet.of(Tagger.JAIKOZ)), - ; - - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java deleted file mode 100644 index c4583d13..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentReader.java +++ /dev/null @@ -1,146 +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 com.mp3.jaudiotagger.tag.vorbiscomment; - -import com.mp3.jaudiotagger.audio.exceptions.CannotReadException; -import com.mp3.jaudiotagger.audio.generic.Utils; -import com.mp3.jaudiotagger.audio.ogg.util.VorbisHeader; -import com.mp3.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 -{ - // Logger Object - public static Logger logger = Logger.getLogger("com.mp3.jaudiotagger.tag.vorbiscomment.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; - - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java deleted file mode 100644 index ef736f9c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTag.java +++ /dev/null @@ -1,934 +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 com.mp3.jaudiotagger.tag.vorbiscomment; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; -import com.mp3.jaudiotagger.audio.generic.AbstractTag; -import com.mp3.jaudiotagger.audio.ogg.util.VorbisHeader; -import com.mp3.jaudiotagger.logging.ErrorMessage; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.images.ArtworkFactory; -import com.mp3.jaudiotagger.tag.vorbiscomment.util.Base64Coder; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; - -import static com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey.VENDOR; - -/** - * This is the logical representation of Vorbis Comment Data - */ -public class VorbisCommentTag extends AbstractTag -{ - private static EnumMap tagFieldToOggField = new EnumMap(FieldKey.class); - - static - { - tagFieldToOggField.put(FieldKey.ACOUSTID_FINGERPRINT, VorbisCommentFieldKey.ACOUSTID_FINGERPRINT); - tagFieldToOggField.put(FieldKey.ACOUSTID_ID, VorbisCommentFieldKey.ACOUSTID_ID); - tagFieldToOggField.put(FieldKey.ALBUM, VorbisCommentFieldKey.ALBUM); - tagFieldToOggField.put(FieldKey.ALBUM_ARTIST, VorbisCommentFieldKey.ALBUMARTIST); - tagFieldToOggField.put(FieldKey.ALBUM_ARTISTS, VorbisCommentFieldKey.ALBUMARTISTS); - tagFieldToOggField.put(FieldKey.ALBUM_ARTISTS_SORT, VorbisCommentFieldKey.ALBUMARTISTSSORT); - tagFieldToOggField.put(FieldKey.ALBUM_ARTIST_SORT, VorbisCommentFieldKey.ALBUMARTISTSORT); - tagFieldToOggField.put(FieldKey.ALBUM_SORT, VorbisCommentFieldKey.ALBUMSORT); - tagFieldToOggField.put(FieldKey.AMAZON_ID, VorbisCommentFieldKey.ASIN); - tagFieldToOggField.put(FieldKey.ARRANGER, VorbisCommentFieldKey.ARRANGER); - tagFieldToOggField.put(FieldKey.ARRANGER_SORT, VorbisCommentFieldKey.ARRANGER_SORT); - tagFieldToOggField.put(FieldKey.ARTIST, VorbisCommentFieldKey.ARTIST); - tagFieldToOggField.put(FieldKey.ARTISTS, VorbisCommentFieldKey.ARTISTS); - tagFieldToOggField.put(FieldKey.ARTISTS_SORT, VorbisCommentFieldKey.ARTISTS_SORT); - 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.CHOIR, VorbisCommentFieldKey.CHOIR); - tagFieldToOggField.put(FieldKey.CHOIR_SORT, VorbisCommentFieldKey.CHOIR_SORT); - tagFieldToOggField.put(FieldKey.CLASSICAL_CATALOG, VorbisCommentFieldKey.CLASSICAL_CATALOG); - tagFieldToOggField.put(FieldKey.CLASSICAL_NICKNAME, VorbisCommentFieldKey.CLASSICAL_NICKNAME); - tagFieldToOggField.put(FieldKey.COMMENT, VorbisCommentFieldKey.COMMENT); - tagFieldToOggField.put(FieldKey.COMPOSER, VorbisCommentFieldKey.COMPOSER); - tagFieldToOggField.put(FieldKey.COMPOSER_SORT, VorbisCommentFieldKey.COMPOSERSORT); - tagFieldToOggField.put(FieldKey.COPYRIGHT, VorbisCommentFieldKey.COPYRIGHT); - tagFieldToOggField.put(FieldKey.CONDUCTOR, VorbisCommentFieldKey.CONDUCTOR); - tagFieldToOggField.put(FieldKey.CONDUCTOR_SORT, VorbisCommentFieldKey.CONDUCTOR_SORT); - tagFieldToOggField.put(FieldKey.COUNTRY, VorbisCommentFieldKey.COUNTRY); - 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.DJMIXER, VorbisCommentFieldKey.DJMIXER); - tagFieldToOggField.put(FieldKey.ENCODER, VorbisCommentFieldKey.VENDOR); //Known as vendor in VorbisComment - tagFieldToOggField.put(FieldKey.ENGINEER, VorbisCommentFieldKey.ENGINEER); - tagFieldToOggField.put(FieldKey.ENSEMBLE, VorbisCommentFieldKey.ENSEMBLE); - tagFieldToOggField.put(FieldKey.ENSEMBLE_SORT, VorbisCommentFieldKey.ENSEMBLE_SORT); - tagFieldToOggField.put(FieldKey.FBPM, VorbisCommentFieldKey.FBPM); - tagFieldToOggField.put(FieldKey.GENRE, VorbisCommentFieldKey.GENRE); - tagFieldToOggField.put(FieldKey.GROUP, VorbisCommentFieldKey.GROUP); - tagFieldToOggField.put(FieldKey.GROUPING, VorbisCommentFieldKey.GROUPING); - tagFieldToOggField.put(FieldKey.INSTRUMENT, VorbisCommentFieldKey.INSTRUMENT); - tagFieldToOggField.put(FieldKey.INVOLVED_PERSON, VorbisCommentFieldKey.INVOLVED_PERSON); - tagFieldToOggField.put(FieldKey.ISRC, VorbisCommentFieldKey.ISRC); - tagFieldToOggField.put(FieldKey.IS_CLASSICAL, VorbisCommentFieldKey.IS_CLASSICAL); - tagFieldToOggField.put(FieldKey.IS_COMPILATION, VorbisCommentFieldKey.COMPILATION); - tagFieldToOggField.put(FieldKey.IS_SOUNDTRACK, VorbisCommentFieldKey.IS_SOUNDTRACK); - 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.MIXER, VorbisCommentFieldKey.MIXER); - tagFieldToOggField.put(FieldKey.MOOD, VorbisCommentFieldKey.MOOD); - tagFieldToOggField.put(FieldKey.MOOD_ACOUSTIC, VorbisCommentFieldKey.MOOD_ACOUSTIC); - tagFieldToOggField.put(FieldKey.MOOD_AGGRESSIVE, VorbisCommentFieldKey.MOOD_AGGRESSIVE); - tagFieldToOggField.put(FieldKey.MOOD_AROUSAL, VorbisCommentFieldKey.MOOD_AROUSAL); - tagFieldToOggField.put(FieldKey.MOOD_DANCEABILITY, VorbisCommentFieldKey.MOOD_DANCEABILITY); - tagFieldToOggField.put(FieldKey.MOOD_ELECTRONIC, VorbisCommentFieldKey.MOOD_ELECTRONIC); - tagFieldToOggField.put(FieldKey.MOOD_HAPPY, VorbisCommentFieldKey.MOOD_HAPPY); - tagFieldToOggField.put(FieldKey.MOOD_INSTRUMENTAL, VorbisCommentFieldKey.MOOD_INSTRUMENTAL); - tagFieldToOggField.put(FieldKey.MOOD_PARTY, VorbisCommentFieldKey.MOOD_PARTY); - tagFieldToOggField.put(FieldKey.MOOD_RELAXED, VorbisCommentFieldKey.MOOD_RELAXED); - tagFieldToOggField.put(FieldKey.MOOD_SAD, VorbisCommentFieldKey.MOOD_SAD); - tagFieldToOggField.put(FieldKey.MOOD_VALENCE, VorbisCommentFieldKey.MOOD_VALENCE); - tagFieldToOggField.put(FieldKey.MOVEMENT, VorbisCommentFieldKey.MOVEMENT); - tagFieldToOggField.put(FieldKey.MOVEMENT_NO, VorbisCommentFieldKey.MOVEMENT_NO); - tagFieldToOggField.put(FieldKey.MOVEMENT_TOTAL, VorbisCommentFieldKey.MOVEMENT_TOTAL); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_ARTISTID, VorbisCommentFieldKey.MUSICBRAINZ_ARTISTID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_DISC_ID, VorbisCommentFieldKey.MUSICBRAINZ_DISCID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_ORIGINAL_RELEASE_ID, VorbisCommentFieldKey.MUSICBRAINZ_ORIGINAL_ALBUMID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMARTISTID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASEID, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, VorbisCommentFieldKey.RELEASECOUNTRY); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, VorbisCommentFieldKey.MUSICBRAINZ_RELEASEGROUPID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMSTATUS); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_TRACK_ID, VorbisCommentFieldKey.MUSICBRAINZ_RELEASETRACKID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_ALBUMTYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_TRACK_ID, VorbisCommentFieldKey.MUSICBRAINZ_TRACKID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK, VorbisCommentFieldKey.MUSICBRAINZ_WORK); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION, VorbisCommentFieldKey.MUSICBRAINZ_WORK_COMPOSITION); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_COMPOSITION_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORKID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL1); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL1_TYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL2); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL2_TYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL3); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL3_TYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL4); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL4_TYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL5); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL5_TYPE); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL6); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_ID); - tagFieldToOggField.put(FieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE, VorbisCommentFieldKey.MUSICBRAINZ_WORK_PART_LEVEL6_TYPE); - tagFieldToOggField.put(FieldKey.MUSICIP_ID, VorbisCommentFieldKey.MUSICIP_PUID); - tagFieldToOggField.put(FieldKey.OCCASION, VorbisCommentFieldKey.OCCASION); - tagFieldToOggField.put(FieldKey.OPUS, VorbisCommentFieldKey.OPUS); - tagFieldToOggField.put(FieldKey.ORCHESTRA, VorbisCommentFieldKey.ORCHESTRA); - tagFieldToOggField.put(FieldKey.ORCHESTRA_SORT, VorbisCommentFieldKey.ORCHESTRA_SORT); - 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.PART, VorbisCommentFieldKey.PART); - tagFieldToOggField.put(FieldKey.PART_NUMBER, VorbisCommentFieldKey.PART_NUMBER); - tagFieldToOggField.put(FieldKey.PART_TYPE, VorbisCommentFieldKey.PART_TYPE); - tagFieldToOggField.put(FieldKey.PERFORMER, VorbisCommentFieldKey.PERFORMER); - tagFieldToOggField.put(FieldKey.PERFORMER_NAME, VorbisCommentFieldKey.PERFORMER_NAME); - tagFieldToOggField.put(FieldKey.PERFORMER_NAME_SORT, VorbisCommentFieldKey.PERFORMER_NAME_SORT); - tagFieldToOggField.put(FieldKey.PERIOD, VorbisCommentFieldKey.PERIOD); - tagFieldToOggField.put(FieldKey.PRODUCER, VorbisCommentFieldKey.PRODUCER); - tagFieldToOggField.put(FieldKey.QUALITY, VorbisCommentFieldKey.QUALITY); - tagFieldToOggField.put(FieldKey.RANKING, VorbisCommentFieldKey.RANKING); - tagFieldToOggField.put(FieldKey.RATING, VorbisCommentFieldKey.RATING); - tagFieldToOggField.put(FieldKey.RECORD_LABEL, VorbisCommentFieldKey.LABEL); - tagFieldToOggField.put(FieldKey.REMIXER, VorbisCommentFieldKey.REMIXER); - tagFieldToOggField.put(FieldKey.SCRIPT, VorbisCommentFieldKey.SCRIPT); - tagFieldToOggField.put(FieldKey.SINGLE_DISC_TRACK_NO, VorbisCommentFieldKey.SINGLE_DISC_TRACK_NO); - tagFieldToOggField.put(FieldKey.SUBTITLE, VorbisCommentFieldKey.SUBTITLE); - tagFieldToOggField.put(FieldKey.TAGS, VorbisCommentFieldKey.TAGS); - tagFieldToOggField.put(FieldKey.TEMPO, VorbisCommentFieldKey.TEMPO); - tagFieldToOggField.put(FieldKey.TIMBRE, VorbisCommentFieldKey.TIMBRE); - tagFieldToOggField.put(FieldKey.TITLE, VorbisCommentFieldKey.TITLE); - tagFieldToOggField.put(FieldKey.TITLE_MOVEMENT, VorbisCommentFieldKey.TITLE_MOVEMENT); - tagFieldToOggField.put(FieldKey.TITLE_SORT, VorbisCommentFieldKey.TITLESORT); - tagFieldToOggField.put(FieldKey.TONALITY, VorbisCommentFieldKey.TONALITY); - 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.WORK, VorbisCommentFieldKey.WORK); - tagFieldToOggField.put(FieldKey.WORK_TYPE, VorbisCommentFieldKey.WORK_TYPE); - tagFieldToOggField.put(FieldKey.YEAR, VorbisCommentFieldKey.DATE); - } - - - //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"; - - /** - * Only used within Package, hidden because it doesnt set Vendor - * which should be done when created by end user - */ - public 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(Charset 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... values) throws KeyNotFoundException,FieldDataInvalidException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - return createField(tagFieldToOggField.get(genericKey), values[0]); - } - - /** - * Create Tag Field using ogg key - * - * @param vorbisCommentFieldKey - * @param value - * @return - * @throws com.mp3.jaudiotagger.tag.KeyNotFoundException - * @throws com.mp3.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 com.mp3.jaudiotagger.tag.KeyNotFoundException - */ - public List get(VorbisCommentFieldKey vorbisCommentKey) throws KeyNotFoundException - { - if (vorbisCommentKey == null) - { - throw new KeyNotFoundException(); - } - return super.getFields(vorbisCommentKey.getFieldName()); - } - - - /** - * Retrieve the first value that exists for this vorbis comment key - * - * @param vorbisCommentKey - * @return - * @throws com.mp3.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(); - } - - if(genericKey==FieldKey.ALBUM_ARTIST) - { - switch(TagOptionSingleton.getInstance().getVorbisAlbumArtistSaveOptions()) - { - case WRITE_ALBUMARTIST: - case WRITE_ALBUMARTIST_AND_DELETE_JRIVER_ALBUMARTIST: - { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - deleteField(vorbisCommentFieldKey); - return; - } - - case WRITE_JRIVER_ALBUMARTIST: - case WRITE_JRIVER_ALBUMARTIST_AND_DELETE_ALBUMARTIST: - { - deleteField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER); - return; - } - - case WRITE_BOTH: - { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - deleteField(vorbisCommentFieldKey); - deleteField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER); - return; - } - - } - } - else - { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - deleteField(vorbisCommentFieldKey); - } - } - - /** - * Delete fields with this vorbisCommentFieldKey - * - * @param vorbisCommentFieldKey - * @throws com.mp3.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 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( - artwork.getImageUrl().getBytes(StandardCharsets.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); - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return createField(FieldKey.IS_COMPILATION,String.valueOf(value)); - } - - @Override - public void setField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - - String value = values[0]; - if(genericKey==FieldKey.ALBUM_ARTIST) - { - switch(TagOptionSingleton.getInstance().getVorbisAlbumArtistSaveOptions()) - { - case WRITE_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - return; - } - - case WRITE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - setField(tagfield); - return; - } - - case WRITE_ALBUMARTIST_AND_DELETE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER.getFieldName()); - return; - } - - case WRITE_JRIVER_ALBUMARTIST_AND_DELETE_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - setField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST.getFieldName()); - return; - } - - - case WRITE_BOTH: - { - TagField tagfield1 = createField(genericKey, value); - setField(tagfield1); - TagField tagfield2 = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - setField(tagfield2); - return; - } - - } - } - else - { - TagField tagfield = createField(genericKey, value); - setField(tagfield); - } - } - - /** - * Create new field and add it to the tag - * - * @param genericKey - * @param values - * @throws KeyNotFoundException - * @throws FieldDataInvalidException - */ - @Override - public void addField(FieldKey genericKey, String... values) throws KeyNotFoundException, FieldDataInvalidException - { - if (values == null || values[0] == null) - { - throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg()); - } - String value = values[0]; - if(genericKey==FieldKey.ALBUM_ARTIST) - { - switch(TagOptionSingleton.getInstance().getVorbisAlbumArtistSaveOptions()) - { - case WRITE_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - return; - } - case WRITE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - addField(tagfield); - return; - } - case WRITE_ALBUMARTIST_AND_DELETE_JRIVER_ALBUMARTIST: - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER.getFieldName()); - return; - } - - case WRITE_JRIVER_ALBUMARTIST_AND_DELETE_ALBUMARTIST: - { - TagField tagfield = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - addField(tagfield); - deleteField(VorbisCommentFieldKey.ALBUMARTIST.getFieldName()); - return; - } - case WRITE_BOTH: - { - TagField tagfield1 = createField(genericKey, value); - addField(tagfield1); - TagField tagfield2 = createField(VorbisCommentFieldKey.ALBUMARTIST_JRIVER, value); - addField(tagfield2); - return; - } - - } - } - else - { - TagField tagfield = createField(genericKey, value); - addField(tagfield); - } - } - - public String getValue(FieldKey genericKey,int index) throws KeyNotFoundException - { - if(genericKey==FieldKey.ALBUM_ARTIST) - { - switch(TagOptionSingleton.getInstance().getVorbisAlbumArtisReadOptions()) - { - case READ_ALBUMARTIST: - { - VorbisCommentFieldKey vorbisCommentFieldKey = VorbisCommentFieldKey.ALBUMARTIST; - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - - case READ_JRIVER_ALBUMARTIST: - { - VorbisCommentFieldKey vorbisCommentFieldKey = VorbisCommentFieldKey.ALBUMARTIST_JRIVER; - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - - case READ_ALBUMARTIST_THEN_JRIVER: - { - VorbisCommentFieldKey vorbisCommentFieldKey = VorbisCommentFieldKey.ALBUMARTIST; - String value = super.getItem(vorbisCommentFieldKey.getFieldName(), index); - if(value.isEmpty()) - { - vorbisCommentFieldKey = VorbisCommentFieldKey.ALBUMARTIST_JRIVER; - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - else - { - return value; - } - } - - case READ_JRIVER_THEN_ALBUMARTIST: - { - VorbisCommentFieldKey vorbisCommentFieldKey = VorbisCommentFieldKey.ALBUMARTIST_JRIVER; - String value = super.getItem(vorbisCommentFieldKey.getFieldName(), index); - if(value.isEmpty()) - { - vorbisCommentFieldKey = VorbisCommentFieldKey.ALBUMARTIST; - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - else - { - return value; - } - } - - default: - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - if (vorbisCommentFieldKey == null) - { - throw new KeyNotFoundException(); - } - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - } - else - { - VorbisCommentFieldKey vorbisCommentFieldKey = tagFieldToOggField.get(genericKey); - if (vorbisCommentFieldKey == null) - { - throw new KeyNotFoundException(); - } - return super.getItem(vorbisCommentFieldKey.getFieldName(), index); - } - } -} - diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java deleted file mode 100644 index 18584361..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/VorbisCommentTagField.java +++ /dev/null @@ -1,243 +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 com.mp3.jaudiotagger.tag.vorbiscomment; - -import com.mp3.jaudiotagger.StandardCharsets; -import com.mp3.jaudiotagger.tag.TagField; -import com.mp3.jaudiotagger.tag.TagTextField; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; - -import static com.mp3.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey.*; - -/** - * This class represents the name and content of a tag entry in ogg-files. - *
- * - * @author Raphael Slinckx (KiKiDonK) - * @author Christian Laireiter (liree) - */ -public class VorbisCommentTagField 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; - - /** - * If id is invalid - */ - private static final String ERRONEOUS_ID = "ERRONEOUS"; - - /** - * 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); - } - - @Override - public void copyContent(TagField field) - { - if (field instanceof TagTextField) - { - this.content = ((TagTextField) field).getContent(); - } - } - - @Override - public String getContent() - { - return content; - } - - @Override - public Charset getEncoding() - { - return StandardCharsets.UTF_8; - } - - @Override - public String getId() - { - return this.id; - } - - @Override - public byte[] getRawContent() throws UnsupportedEncodingException - { - byte[] size = new byte[VorbisCommentReader.FIELD_COMMENT_LENGTH_LENGTH]; - byte[] idBytes = this.id.getBytes(StandardCharsets.ISO_8859_1); - byte[] contentBytes = this.content.getBytes(StandardCharsets.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; - } - - @Override - public boolean isBinary() - { - return false; - } - - @Override - 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."); - } - } - - @Override - public boolean isCommon() - { - return common; - } - - @Override - public boolean isEmpty() - { - return this.content.equals(""); - } - - @Override - public void setContent(String s) - { - this.content = s; - } - - @Override - public void setEncoding(final Charset s) - { - if (!StandardCharsets.UTF_8.equals(s)) - { - throw new UnsupportedOperationException("The encoding of OggTagFields cannot be " + "changed.(specified to be UTF-8)"); - } - } - - @Override - public String toString() - { - return getContent(); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java deleted file mode 100644 index 5fb4b66f..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/vorbiscomment/util/Base64Coder.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.mp3.jaudiotagger.tag.vorbiscomment.util; - -import com.mp3.jaudiotagger.StandardCharsets; - -/** - * Base64Coder - */ -public class Base64Coder -{ - // Mapping table from 6-bit nibbles to Base64 characters. - private static final char[] map1 = new char[64]; - - 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++] = '/'; - } - - // Mapping table from Base64 characters to 6-bit nibbles. - private static final byte[] map2 = new byte[128]; - - 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(s.getBytes(StandardCharsets.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. - * - * @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++]; - if(i0==13 && i1==10) continue; - 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavInfoTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavInfoTag.java deleted file mode 100644 index 3432fe01..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavInfoTag.java +++ /dev/null @@ -1,135 +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 com.mp3.jaudiotagger.tag.wav; - -import com.mp3.jaudiotagger.audio.generic.GenericTag; -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.*; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -/** - * Represent wav metadata found in the LISTINFO Chunk - * - * An LIST INFO chunk was the original way to store metadata but simailr to ID3v1 it suffers from a limited - * set of fields, although non-standard extra field cannot be added, notably there is no support for images. - * - * Any Wavc editors now instead/addtionally add data with an ID3tag - */ -public class WavInfoTag extends GenericTag -{ - //We dont use these fields but we need to read them so they can be written back if user modifies - private List unrecognisedFields = new ArrayList(); - - private Long startLocationInFile = null; - - //End location of this chunk - private Long endLocationInFile = null; - - - static - { - supportedKeys = EnumSet.of( - - FieldKey.ALBUM, - FieldKey.ARTIST, - FieldKey.ALBUM_ARTIST, - FieldKey.TITLE, - FieldKey.TRACK, - FieldKey.GENRE, - FieldKey.COMMENT, - FieldKey.YEAR, - FieldKey.RECORD_LABEL, - FieldKey.ISRC, - FieldKey.COMPOSER, - FieldKey.LYRICIST, - FieldKey.ENCODER, - FieldKey.CONDUCTOR, - FieldKey.RATING); - } - public String toString() - { - StringBuilder output = new StringBuilder("Wav Info Tag:\n"); - if(getStartLocationInFile()!=null) - { - output.append("\tstartLocation:" + Hex.asDecAndHex(getStartLocationInFile()) + "\n"); - } - if(getEndLocationInFile()!=null) - { - output.append("\tendLocation:" + Hex.asDecAndHex(getEndLocationInFile()) + "\n"); - } - output.append(super.toString()); - if(unrecognisedFields.size()>0) - { - output.append("\nUnrecognized Tags:\n"); - for(TagTextField next:unrecognisedFields) - { - output.append("\t"+next.getId()+":"+next.getContent()+"\n"); - } - } - return output.toString(); - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return createField(FieldKey.IS_COMPILATION,String.valueOf(value)); - } - - public Long getStartLocationInFile() - { - return startLocationInFile; - } - - public void setStartLocationInFile(long startLocationInFile) - { - this.startLocationInFile = startLocationInFile; - } - - public Long getEndLocationInFile() - { - return endLocationInFile; - } - - public void setEndLocationInFile(long endLocationInFile) - { - this.endLocationInFile = endLocationInFile; - } - - public long getSizeOfTag() - { - if(endLocationInFile==null || startLocationInFile==null) - { - return 0; - } - return (endLocationInFile - startLocationInFile) - ChunkHeader.CHUNK_HEADER_SIZE; - } - - public void addUnRecognizedField(String code, String contents) - {; - unrecognisedFields.add(new GenericTagTextField(code, contents)); - } - - public List getUnrecognisedFields() - { - return unrecognisedFields; - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavTag.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavTag.java deleted file mode 100644 index b34fb834..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/tag/wav/WavTag.java +++ /dev/null @@ -1,656 +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 com.mp3.jaudiotagger.tag.wav; - -import com.mp3.jaudiotagger.audio.iff.ChunkHeader; -import com.mp3.jaudiotagger.audio.iff.ChunkSummary; -import com.mp3.jaudiotagger.audio.wav.WavOptions; -import com.mp3.jaudiotagger.logging.Hex; -import com.mp3.jaudiotagger.tag.*; -import com.mp3.jaudiotagger.tag.id3.*; -import com.mp3.jaudiotagger.tag.images.Artwork; -import com.mp3.jaudiotagger.tag.reference.ID3V2Version; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Represent wav metadata found in a Wav file - *

- * This can come from LIST INFO chunk or ID3 tag, LIST INFO can only contain a subset of what can be held in an ID3v2 tag, - * - * The default is that ID3 takes precedence if it exists - */ -public class WavTag implements Tag, Id3SupportingTag -{ - private static final Logger logger = Logger.getLogger(WavTag.class.getName()); - - private static final String NULL = "\0"; - - private List chunkSummaryList = new ArrayList(); - - public void addChunkSummary(ChunkSummary cs) - { - chunkSummaryList.add(cs); - } - - public List getChunkSummaryList() - { - return chunkSummaryList; - } - - private boolean isIncorrectlyAlignedTag = false; - - private boolean isExistingId3Tag = false; - private boolean isExistingInfoTag = false; - - private WavInfoTag infoTag; - private AbstractID3v2Tag id3Tag; - - private WavOptions wavOptions; - - public WavTag(WavOptions wavOptions) - { - this.wavOptions=wavOptions; - } - /** - * @return true if the file that this tag was written from already contains an ID3 chunk - */ - public boolean isExistingId3Tag() - { - return isExistingId3Tag; - } - - /** - * - * @return true if the file that this tag read from already contains a LISTINFO chunk - */ - public boolean isExistingInfoTag() - { - return isExistingInfoTag; - } - - /** - * @return the Info tag - */ - public WavInfoTag getInfoTag() - { - return infoTag; - } - - public void setInfoTag(WavInfoTag infoTag) - { - this.infoTag = infoTag; - } - - /** - * Does the info tag exist, note it is created by default if one does not exist in file it was read from - * - * @return - */ - public boolean isInfoTag() - { - return infoTag != null; - } - - /** - * Returns the ID3 tag - */ - public AbstractID3v2Tag getID3Tag() - { - return id3Tag; - } - - /** - * Sets the ID3 tag - */ - public void setID3Tag(AbstractID3v2Tag t) - { - id3Tag = t; - } - - /** - * Does an ID3 tag exist, note it is created by default if one does not exist in file it was read from - * - * @return - */ - public boolean isID3Tag() - { - return id3Tag != null; - } - - @Override - public String toString() - { - StringBuilder sb = new StringBuilder(); - - for(ChunkSummary cs:chunkSummaryList) - { - sb.append(cs.toString()+"\n"); - } - - if (id3Tag != null) - { - sb.append("Wav ID3 Tag:\n"); - if(isExistingId3Tag()) - { - sb.append("\tstartLocation:" + Hex.asDecAndHex(getStartLocationInFileOfId3Chunk()) + "\n"); - sb.append("\tendLocation:" + Hex.asDecAndHex(getEndLocationInFileOfId3Chunk()) + "\n"); - } - sb.append(id3Tag.toString()+"\n"); - } - if (infoTag != null) - { - sb.append(infoTag.toString()+"\n"); - } - return sb.toString(); - } - - - public Tag getActiveTag() - { - switch(wavOptions) - { - case READ_ID3_ONLY: - case READ_ID3_ONLY_AND_SYNC: - return id3Tag; - - case READ_INFO_ONLY: - case READ_INFO_ONLY_AND_SYNC: - return infoTag; - - case READ_ID3_UNLESS_ONLY_INFO: - case READ_ID3_UNLESS_ONLY_INFO_AND_SYNC: - if (isExistingId3Tag() || !isExistingInfoTag()) - { - return id3Tag; - } - else - { - return infoTag; - } - - case READ_INFO_UNLESS_ONLY_ID3: - case READ_INFO_UNLESS_ONLY_ID3_AND_SYNC: - if (isExistingInfoTag() || !isExistingId3Tag()) - { - return infoTag; - } - else - { - return id3Tag; - } - - default: - return id3Tag; - - } - } - - public boolean equals(Object obj) - { - return getActiveTag().equals(obj); - } - - public void addField(TagField field) throws FieldDataInvalidException - { - getActiveTag().addField(field); - } - - public List getFields(String id) - { - return getActiveTag().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 getActiveTag().getAll(genericKey); - } - - public boolean hasCommonFields() - { - return getActiveTag().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 (getActiveTag() == null || getActiveTag().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 - { - getActiveTag().setField(field); - } - - - public TagField createField(FieldKey genericKey, String... value) throws KeyNotFoundException, FieldDataInvalidException - { - return getActiveTag().createField(genericKey, value); - } - - - public String getFirst(String id) - { - return getActiveTag().getFirst(id); - } - - public String getValue(FieldKey id, int index) throws KeyNotFoundException - { - return getActiveTag().getValue(id, index); - } - - public String getFirst(FieldKey id) throws KeyNotFoundException - { - return getValue(id, 0); - } - - public TagField getFirstField(String id) - { - return getActiveTag().getFirstField(id); - } - - public TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException - { - if (genericKey == null) - { - throw new KeyNotFoundException(); - } - - else - { - return getActiveTag().getFirstField(genericKey); - } - } - - /** - * Delete any instance of tag fields with this key - * - * @param fieldKey - */ - public void deleteField(FieldKey fieldKey) throws KeyNotFoundException - { - getActiveTag().deleteField(fieldKey); - } - - public void deleteField(String id) throws KeyNotFoundException - { - getActiveTag().deleteField(id); - } - - public Iterator getFields() - { - return getActiveTag().getFields(); - } - - public int getFieldCount() - { - return getActiveTag().getFieldCount(); - } - - public int getFieldCountIncludingSubValues() - { - return getFieldCount(); - } - - public boolean setEncoding(final Charset enc) throws FieldDataInvalidException - { - return getActiveTag().setEncoding(enc); - } - - /** - * Create artwork field. Not currently supported. - */ - public TagField createField(Artwork artwork) throws FieldDataInvalidException - { - return getActiveTag().createField(artwork); - } - - public List getFields(FieldKey id) throws KeyNotFoundException - { - return getActiveTag().getFields(id); - } - - public Artwork getFirstArtwork() - { - return getActiveTag().getFirstArtwork(); - } - - /** - * Delete all instance of artwork Field - * - * @throws KeyNotFoundException - */ - public void deleteArtworkField() throws KeyNotFoundException - { - getActiveTag().deleteArtworkField(); - } - - /** - * @param genericKey - * @return - */ - public boolean hasField(FieldKey genericKey) - { - return getActiveTag().hasField(genericKey); - } - - - public boolean hasField(String id) - { - return getActiveTag().hasField(id); - } - - public TagField createCompilationField(boolean value) throws KeyNotFoundException, FieldDataInvalidException - { - return createField(FieldKey.IS_COMPILATION, String.valueOf(value)); - } - - public List getArtworkList() - { - return getActiveTag().getArtworkList(); - } - - /** - * Create field and then set within tag itself - * - * @param artwork - * @throws FieldDataInvalidException - */ - public void setField(Artwork artwork) throws FieldDataInvalidException - { - this.setField(createField(artwork)); - } - - public void addField(Artwork artwork) throws FieldDataInvalidException - { - this.addField(createField(artwork)); - } - - public void setExistingId3Tag(boolean isExistingId3Tag) - { - this.isExistingId3Tag = isExistingId3Tag; - } - - public void setExistingInfoTag(boolean isExistingInfoTag) - { - this.isExistingInfoTag = isExistingInfoTag; - } - - /** - * - * @return size of the vanilla ID3Tag exclusing surrounding chunk - */ - public long getSizeOfID3TagOnly() - { - if(!isExistingId3Tag()) - { - return 0; - } - return (id3Tag.getEndLocationInFile() - id3Tag.getStartLocationInFile()); - } - - /** - * - * @return size of the ID3 Chunk including header - */ - public long getSizeOfID3TagIncludingChunkHeader() - { - if(!isExistingId3Tag()) - { - return 0; - } - return getSizeOfID3TagOnly() + ChunkHeader.CHUNK_HEADER_SIZE; - } - - /** - * Offset into file of start ID3Chunk including header - * @return - */ - public long getStartLocationInFileOfId3Chunk() - { - if(!isExistingId3Tag()) - { - return 0; - } - return id3Tag.getStartLocationInFile() - ChunkHeader.CHUNK_HEADER_SIZE; - } - - public long getEndLocationInFileOfId3Chunk() - { - if(!isExistingId3Tag()) - { - return 0; - } - return id3Tag.getEndLocationInFile(); - } - - - /** - * If we have field in INFO tag but not ID3 tag (perhaps coz doesn't exist add them to ID3 tag) - */ - public void syncToId3FromInfoIfEmpty() - { - - try - { - for(FieldKey fieldKey : WavInfoTag.getSupportedKeys()) - { - if (id3Tag.getFirst(fieldKey).isEmpty()) - { - String first = infoTag.getFirst(fieldKey); - if (!first.isEmpty()) - { - id3Tag.setField(fieldKey, stripNullTerminator(first)); - } - } - } - } - catch(FieldDataInvalidException deie) - { - logger.log(Level.INFO, "Couldn't sync to ID3 because the data to sync was invalid", deie); - } - } - - /** - * If we have field in INFO tag but not ID3 tag (perhaps coz doesn't exist add them to ID3 tag) - */ - public void syncToInfoFromId3IfEmpty() - { - - try - { - for(FieldKey fieldKey : WavInfoTag.getSupportedKeys()) - { - if (infoTag.getFirst(fieldKey).isEmpty()) - { - if (!id3Tag.getFirst(fieldKey).isEmpty()) - { - infoTag.setField(fieldKey, addNullTerminatorIfNone(id3Tag.getFirst(fieldKey))); - } - } - } - } - catch(FieldDataInvalidException deie) - { - logger.log(Level.INFO, "Couldn't sync to INFO because the data to sync was invalid", deie); - } - } - - /** - * If we have field in INFO tag write to ID3 tag, if not we delete form ID3 - * (but only for tag that we can actually have in INFO tag) - */ - public void syncToId3FromInfoOverwrite() - { - try - { - for(FieldKey fieldKey : WavInfoTag.getSupportedKeys()) - { - if (!infoTag.getFirst(fieldKey).isEmpty()) - { - id3Tag.setField(fieldKey, stripNullTerminator(infoTag.getFirst(fieldKey))); - } - else - { - id3Tag.deleteField(fieldKey); - } - } - } - catch(FieldDataInvalidException deie) - { - logger.log(Level.INFO, "Couldn't sync to ID3 because the data to sync was invalid", deie); - } - } - - /** - * If we have field in ID3 tag write to INFO tag - */ - public void syncToInfoFromId3Overwrite() - { - - try - { - for(FieldKey fieldKey : WavInfoTag.getSupportedKeys()) - { - if (!id3Tag.getFirst(fieldKey).isEmpty()) - { - infoTag.setField(fieldKey, addNullTerminatorIfNone(id3Tag.getFirst(fieldKey))); - } - else - { - infoTag.deleteField(fieldKey); - } - } - } - catch(FieldDataInvalidException deie) - { - logger.log(Level.INFO, "Couldn't sync to INFO because the data to sync was invalid", deie); - } - } - - private String stripNullTerminator(String value) { - return value.endsWith(NULL) ? value.substring(0,value.length() - 1) : value; - } - - private String addNullTerminatorIfNone(String value) { - return value.endsWith(NULL) ? value : value + NULL; - } - - /** - * Call after read to ensure your preferred tag can make use of any additional metadata - * held in the other tag, only used if the activetag field is empty for the fieldkey - */ - public void syncTagsAfterRead() - { - if(getActiveTag() instanceof WavInfoTag) - { - syncToInfoFromId3IfEmpty(); - } - else - { - syncToId3FromInfoIfEmpty(); - } - - } - - /** - * Call before save if saving both tags ensure any new information is the active tag is added to the other tag - * overwriting any existing fields - */ - public void syncTagBeforeWrite() - { - if(getActiveTag() instanceof WavInfoTag) - { - syncToId3FromInfoOverwrite(); - } - else - { - syncToInfoFromId3Overwrite(); - } - - } - - public boolean isIncorrectlyAlignedTag() - { - return isIncorrectlyAlignedTag; - } - - public void setIncorrectlyAlignedTag(boolean isIncorrectlyAlignedTag) - { - this.isIncorrectlyAlignedTag = isIncorrectlyAlignedTag; - } - - /** - * Default based on user option - * - * @return - */ - public static AbstractID3v2Tag createDefaultID3Tag() - { - 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 ID3v23Tag(); - } -} \ No newline at end of file diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/DirectByteBufferUtils.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/DirectByteBufferUtils.java deleted file mode 100644 index 45ddf798..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/DirectByteBufferUtils.java +++ /dev/null @@ -1,247 +0,0 @@ -package com.mp3.jaudiotagger.utils; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Utilities for direct {@link ByteBuffer}s. - *

- * The release method was taken from research in the following places: - *

    - *
  • http://bugs.java.com/view_bug.do?bug_id=4724038
  • - *
  • http://stackoverflow.com/questions/2972986/how-to-unmap-a-file-from-memory-mapped-using-filechannel-in-java
  • - *
  • https://bitbucket.org/vladimir.dolzhenko/gflogger/src/366fd4ee0689/core/src/main/java/org/gflogger/util/DirectBufferUtils.java
  • - *
  • https://sourceforge.net/p/tuer/code/HEAD/tree/pre_beta/src/main/java/engine/misc/DeallocationHelper.java
  • - *
- * - * @author gravelld - */ -public class DirectByteBufferUtils -{ - - public static final Logger LOGGER = Logger.getLogger(DirectByteBufferUtils.class.getName()); - - private static ReleaseStrategy releaseStrategy; - - static - { - releaseStrategy = decideReleaseStrategy(); - } - - private interface ReleaseStrategy - { - - /** - * Make a best-effort attempt to release the {@link ByteBuffer} - * - * @param bb - */ - void release(Buffer bb); - } - - private final static class OpenJdkReleaseStrategy implements ReleaseStrategy - { - - private static final ReleaseStrategy INSTANCE = new OpenJdkReleaseStrategy(); - private static final Method cleanerMethod; - private static final Method cleanMethod; - private static final Method viewedBufferMethod; - - static - { - cleanerMethod = loadMethod("sun.nio.ch.DirectBuffer", "cleaner"); - cleanMethod = loadMethod("sun.misc.Cleaner", "clean"); - Method vbMethod = loadMethod("sun.nio.ch.DirectBuffer", "viewedBuffer"); - if (vbMethod == null) - { - // They changed the name in Java 7 (???) - vbMethod = loadMethod("sun.nio.ch.DirectBuffer", "attachment"); - } - viewedBufferMethod = vbMethod; - } - - private OpenJdkReleaseStrategy() - { - } - - @Override - public void release(Buffer bb) - { - try - { - final Object cleaner = cleanerMethod.invoke(bb); - if (cleaner != null) - { - cleanMethod.invoke(cleaner); - } - else - { - final Object viewedBuffer = viewedBufferMethod.invoke(bb); - if (viewedBuffer != null) - { - release((Buffer) viewedBuffer); - } - else - { - LOGGER.log(Level.WARNING, "Can't release direct buffer as neither cleaner nor viewedBuffer were available on:" + bb.getClass()); - } - } - } - catch (IllegalAccessException e) - { - LOGGER.log(Level.WARNING, "Authorisation failed to invoke release on: " + bb, e); - } - catch (InvocationTargetException e) - { - LOGGER.log(Level.WARNING, "Failed to release: " + bb, e); - } - } - - } - - private final static class AndroidReleaseStrategy implements ReleaseStrategy - { - - private static final ReleaseStrategy INSTANCE = new AndroidReleaseStrategy(); - - private static final Method freeMethod; - - static - { - freeMethod = loadMethod("java.nio.DirectByteBuffer", "free"); - } - - private AndroidReleaseStrategy() - { - } - - @Override - public void release(Buffer bb) - { - - if (freeMethod != null) - { - try - { - freeMethod.invoke(bb); - } - catch (IllegalAccessException e) - { - LOGGER.log(Level.WARNING, "Authorisation failed to invoke release on: " + bb, e); - } - catch (InvocationTargetException e) - { - LOGGER.log(Level.WARNING, "Failed to release: " + bb, e); - } - } - else - { - LOGGER.log(Level.WARNING, "Can't release direct buffer as free method weren't available on: " + bb); - } - } - - } - - private final static class UnsupportedJvmReleaseStrategy implements ReleaseStrategy - { - private static final ReleaseStrategy INSTANCE = new UnsupportedJvmReleaseStrategy(); - - private UnsupportedJvmReleaseStrategy() - { - } - - @Override - public void release(Buffer bb) - { - LOGGER.log(Level.WARNING, "Can't release direct buffer as this JVM is unsupported."); - } - } - - /** - * Decide which ReleaseStrategy to use, depending on the JVM - * - * @return - */ - private static ReleaseStrategy decideReleaseStrategy() - { - - final String javaVendor = System.getProperty("java.vendor"); - - if (javaVendor.equals("Sun Microsystems Inc.") || javaVendor.equals("Oracle Corporation")) - { - return OpenJdkReleaseStrategy.INSTANCE; - } - else if (javaVendor.equals("The Android Project")) - { - return AndroidReleaseStrategy.INSTANCE; - } - else - { - LOGGER.log(Level.WARNING, "Won't be able to release direct buffers as this JVM is unsupported: " + javaVendor); - return UnsupportedJvmReleaseStrategy.INSTANCE; - } - } - - private static Method loadMethod(final String className, final String methodName) - { - try - { - final Class clazz = Class.forName(className); - final Method method = clazz.getMethod(methodName); - method.setAccessible(true); - return method; - } - catch (NoSuchMethodException ex) - { - return null; // the method was not found - } - catch (SecurityException ex) - { - return null; // setAccessible not allowed by security policy - } - catch (ClassNotFoundException ex) - { - return null; // the direct buffer implementation was not found - } - } - - /** - * Direct {@link ByteBuffer}s are stored in system memory, and released when garbage collection occurs - * and the buffer is deemed to be unreachable, following vanilla garbage collection procedures. At that - * point, a special finalizer, "Cleaner" runs to de-allocate the system memory (and in the case of - * {@link MappedByteBuffer}s, unmap the file). - *

- * However, if garbage collection does not occur, the system memory remains taken, and the {@link MappedByteBuffer} - * (if applicable) remains mapped, meaning system level operations cannot occur in other processes. - *

- * This method seeks to release a direct {@link ByteBuffer} early by calling well known reflective code - * in a best-attempt fashion. In the case that this reflective code is not present, the method - * finishes with a log message, and normal Java practice takes over; i.e. the buffer is not released - * and if it's a {@link MappedByteBuffer} the file is not unmapped, until later GC occurs or the - * JVM is terminated. - * - * @param bb - * @throws NullPointerException If bb is null. - * @throws IllegalArgumentException If bb is not a "direct" {@link ByteBuffer} - */ - public static void release(Buffer bb) - { - - if (bb == null) - { - throw new NullPointerException(ByteBuffer.class.getSimpleName() + " should not be null"); - } - if (!bb.isDirect()) - { - throw new IllegalArgumentException(bb.getClass().getName() + " is not direct."); - } - - releaseStrategy.release(bb); - } - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/EqualsUtil.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/EqualsUtil.java deleted file mode 100644 index 3649ac3d..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/EqualsUtil.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.mp3.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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/FileTypeUtil.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/FileTypeUtil.java deleted file mode 100644 index 658ac8e7..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/FileTypeUtil.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.mp3.jaudiotagger.utils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class FileTypeUtil { - private static final int BUFFER_SIZE = 4096; - private static final int MAX_SIGNATURE_SIZE = 8; - - // PDF files starts with: %PDF - // MS office files starts with: (D0 CF 11 E0 A1 B1 1A E1) - // Java does not support byte literals. Use int literals instead. - // private static final int[] pdfSig = { 0x25, 0x50, 0x44, 0x46 }; - // private static final int[] msOfficeSig = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, - // 0xb1, 0x1a, 0xe1 }; - - private static final Integer[] mp3v2Sig = { 0x49, 0x44, 0x33 }; - private static final Integer[] mp3v1Sig_1 = { 0xFF, 0xF3 }; - private static final Integer[] mp3v1Sig_2 = { 0xFF, 0xFA }; - private static final Integer[] mp3v1Sig_3 = { 0xFF, 0xF2 }; - private static final Integer[] mp3v1Sig_4 = { 0xFF, 0xFB }; - private static final Integer[] mp4Sig = { 0x00, 0x00, 0x00, null, 0x66, 0x74, 0x79, 0x70 }; - - private static Map signatureMap; - private static Map extensionMap; - - static { - signatureMap = new HashMap(); - signatureMap.put("MP3IDv2", mp3v2Sig); - signatureMap.put("MP3IDv1_1", mp3v1Sig_1); - signatureMap.put("MP3IDv1_2", mp3v1Sig_2); - signatureMap.put("MP3IDv1_3", mp3v1Sig_3); - signatureMap.put("MP3IDv1_4", mp3v1Sig_4); - signatureMap.put("MP4", mp4Sig); - - extensionMap = new HashMap(); - extensionMap.put("MP3IDv2", "mp3"); - extensionMap.put("MP3IDv1_1", "mp3"); - extensionMap.put("MP3IDv1_2", "mp3"); - extensionMap.put("MP3IDv1_3", "mp3"); - extensionMap.put("MP3IDv1_4", "mp3"); - extensionMap.put("MP4", "m4a"); - extensionMap.put("UNKNOWN", ""); - } - - public static String getMagicFileType(File f) throws IOException { - byte[] buffer = new byte[BUFFER_SIZE]; - InputStream in = new FileInputStream(f); - try { - int n = in.read(buffer, 0, BUFFER_SIZE); - int m = n; - while ((m < MAX_SIGNATURE_SIZE) && (n > 0)) { - n = in.read(buffer, m, BUFFER_SIZE - m); - m += n; - } - - String fileType = "UNKNOWN"; - for (Iterator i = signatureMap.keySet().iterator(); i.hasNext();) { - String key = i.next(); - if (matchesSignature(signatureMap.get(key), buffer, m)) { - fileType = key; - break; - } - } - return fileType; - } finally { - in.close(); - } - } - - public static String getMagicExt(String fileType){ - return extensionMap.get(fileType); - } - - - private static boolean matchesSignature(Integer[] signature, byte[] buffer, int size) { - if (size < signature.length) { - return false; - } - - boolean b = true; - for (int i = 0; i < signature.length; i++) { - if (signature[i] != null) { - if (signature[i] != (0x00ff & buffer[i])) { - b = false; - break; - } - } - } - - return b; - } - - - public static void main(String[] args) throws IOException { - // if (args.length < 1) { - // System.out.println("Usage: java TestExcelPDF "); - // System.exit(1); - // } - String testFileLoc = "C:/Users/keerthi/Dropbox/Works/Java/github/GaanaExtractor/workspace/jaudiotagger/testm4a"; - // FileTypeUtil t = new FileTypeUtil(); - String fileType = getMagicFileType(new File(testFileLoc)); - System.out.println("File type: " + fileType); - System.out.println("File Extension: " + getMagicExt(fileType)); - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/PrimitiveUtils.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/PrimitiveUtils.java deleted file mode 100644 index 251c8322..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/PrimitiveUtils.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.mp3.jaudiotagger.utils; - -public class PrimitiveUtils { - - public static int safeLongToInt(long l) { - if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) throw new IllegalArgumentException(l + " cannot be cast to int without changing its value."); - return (int) l; - } -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultMutableTreeNode.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultMutableTreeNode.java deleted file mode 100644 index 9a914fda..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultMutableTreeNode.java +++ /dev/null @@ -1,1493 +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 com.mp3.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}. - * - * @see MutableTreeNode - * - * @version 1.25 03/23/10 - * @author Rob Davis - */ -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 - * @exception ArrayIndexOutOfBoundsException if - * childIndex is out of bounds - * @exception IllegalArgumentException if - * newChild is null or is an - * ancestor of this node - * @exception 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 - * @exception ArrayIndexOutOfBoundsException if - * childIndex is out of bounds - */ - public void remove(int childIndex) { - MutableTreeNode child = (MutableTreeNode)getChildAt(childIndex); - children.removeElementAt(childIndex); - child.setParent(null); - } - - /** - * 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 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; - } - - /** - * Returns the child at the specified index in this node's child array. - * - * @param index an index into this node's child array - * @exception ArrayIndexOutOfBoundsException if index - * is out of bounds - * @return the TreeNode in this node's child array at the specified index - */ - 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 - * @exception IllegalArgumentException if aChild - * is null - * @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 - */ - 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(); - } - } - - /** - * 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 true if this node is allowed to have children. - * - * @return true if this node allows children, else false - */ - public boolean getAllowsChildren() { - return allowsChildren; - } - - /** - * 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; - } - - /** - * 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; - } - - - // - // 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 - * @exception 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. - * - * @see #insert - * @param newChild node to add as a child of this node - * @exception IllegalArgumentException if newChild - * is null - * @exception IllegalStateException if this node does not allow - * children - */ - 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. - * - * @see #isNodeDescendant - * @see #getSharedAncestor - * @param anotherNode node to test as an ancestor of this node - * @return true if this node is a descendant of anotherNode - */ - 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. - * - * @see #isNodeAncestor - * @see #getSharedAncestor - * @param anotherNode node to test as descendant of this node - * @return true if this node is an ancestor of anotherNode - */ - 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. - * - * @see #isNodeAncestor - * @see #isNodeDescendant - * @param aNode node to find common ancestor with - * @return nearest ancestor common to this node and aNode, - * or null if none - */ - 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. - * - * @see #getSharedAncestor - * @see #getRoot - * @return true if aNode is in the same tree as this node; - * false if aNode is null - */ - 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. - * - * @see #getLevel - * @return the depth of the tree whose root is this node - */ - 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. - * - * @see #getDepth - * @return the number of levels above this node - */ - 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. - * - * @see #isNodeAncestor - * @return the root of the tree that contains this node - */ - 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. - * - * @see #preorderEnumeration - * @return the node that follows this node in a preorder traversal, or - * null if this node is last - */ - 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. - * - * @see #preorderEnumeration - * @return the node that precedes this node in a preorder traversal, or - * null if this node is the first - */ - 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. - * - * @see #postorderEnumeration - * @return an enumeration for traversing the tree in preorder - */ - 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. - * - * @see #depthFirstEnumeration - * @see #preorderEnumeration - * @return an enumeration for traversing the tree in postorder - */ - 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. - * - * @see #depthFirstEnumeration - * @return an enumeration for traversing the tree in breadth-first order - */ - 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. - * - * @see #breadthFirstEnumeration - * @see #postorderEnumeration - * @return an enumeration for traversing the tree in depth-first order - */ - 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. - * - * @see #isNodeAncestor - * @see #isNodeDescendant - * @exception IllegalArgumentException if ancestor is - * not an ancestor of this node - * @return an enumeration for following the path from an ancestor of - * this node to this one - */ - 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 - * @exception 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 - * @exception 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. - * - * @see #children - * @exception IllegalArgumentException if aChild is - * null or is not a child of this node - * @return the child of this node that immediately follows - * aChild - */ - 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. - * - * @exception IllegalArgumentException if aChild is null - * or is not a child of this node - * @return the child of this node that immediately precedes - * aChild - */ - 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. - * - * @see #children - * @return the sibling of this node that immediately follows this node - */ - 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 - * - * @see #getAllowsChildren - * @return true if this node has no children - */ - 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. - * - * @see #isLeaf - * @see #isNodeDescendant - * @return the first leaf in the subtree rooted at this node - */ - 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. - * - * @see #isLeaf - * @see #isNodeDescendant - * @return the last leaf in the subtree rooted at this node - */ - 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. - * - * @see #depthFirstEnumeration - * @see #isLeaf - * @return returns the next leaf past this node - */ - 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. - * - * @see #depthFirstEnumeration - * @see #isLeaf - * @return returns the leaf before this node - */ - 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. - * - * @see #isNodeAncestor - * @return the number of leaves beneath this node - */ - 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( - (TreeNode)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; - - final class QNode { - public Object object; - public QNode next; // null if end - public QNode(Object object, QNode next) { - this.object = object; - this.next = next; - } - } - - 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; - } - - } // 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultTreeModel.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultTreeModel.java deleted file mode 100644 index 2c8e897a..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/DefaultTreeModel.java +++ /dev/null @@ -1,666 +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 com.mp3.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}. - * - * @version 1.58 03/23/10 - * @author Rob Davis - * @author Ray Ryan - * @author Scott Violet - */ -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; - } - - /** - * 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 root of the tree. Returns null only if the tree has - * no nodes. - * - * @return the root of the tree - */ - public Object getRoot() { - return 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. - * - * @see #removeTreeModelListener - * @param l the listener to add - */ - public void addTreeModelListener(TreeModelListener l) { - listenerList.add(TreeModelListener.class, l); - } - - /** - * Removes a listener previously added with addTreeModelListener(). - * - * @see #addTreeModelListener - * @param l the listener to remove - */ - 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 (TreeModelListener[])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 - * @exception 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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/EventListenerList.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/EventListenerList.java deleted file mode 100644 index 434929b2..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/EventListenerList.java +++ /dev/null @@ -1,276 +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 com.mp3.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}. - * - * @version 1.38 03/23/10 - * @author Georges Saab - * @author Hans Muller - * @author James Gosling - */ -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. - * @exception 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 == (Class)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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/MutableTreeNode.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/MutableTreeNode.java deleted file mode 100644 index 45f0a45c..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/MutableTreeNode.java +++ /dev/null @@ -1,56 +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 com.mp3.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. - * - * @see DefaultMutableTreeNode - * @see javax.swing.JTree - * - * @version 1.13 03/23/10 - * @author Rob Davis - * @author Scott Violet - */ - -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModel.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModel.java deleted file mode 100644 index 5dd685e8..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModel.java +++ /dev/null @@ -1,143 +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 com.mp3.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. - * - * @see TreePath - * - * @version 1.27 03/23/10 - * @author Rob Davis - * @author Ray Ryan - */ -public interface TreeModel -{ - - /** - * Returns the root of the tree. Returns null - * only if the tree has no nodes. - * - * @return the root of the tree - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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. - * - * @see #addTreeModelListener - * @param l the listener to remove - */ - void removeTreeModelListener(TreeModelListener l); - -} diff --git a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelEvent.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelEvent.java deleted file mode 100644 index f5f72fdb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelEvent.java +++ /dev/null @@ -1,297 +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 com.mp3.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}. - * - * @version 1.35 03/23/10 - * @author Rob Davis - * @author Ray Ryan - * @author Scott Violet - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelListener.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeModelListener.java deleted file mode 100644 index 54198d08..00000000 --- a/jaudiotagger/src/main/java/com/mp3/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 com.mp3.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. - * - * @version 1.19 03/23/10 - * @author Rob Davis - * @author Ray Ryan - */ -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeNode.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeNode.java deleted file mode 100644 index c1896b42..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreeNode.java +++ /dev/null @@ -1,70 +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 com.mp3.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. - * - * @version 1.26 03/23/10 - * @author Rob Davis - * @author Scott Violet - */ - -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/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreePath.java b/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreePath.java deleted file mode 100644 index 04afcbfb..00000000 --- a/jaudiotagger/src/main/java/com/mp3/jaudiotagger/utils/tree/TreePath.java +++ /dev/null @@ -1,323 +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 com.mp3.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}. - * - * @version 1.32 03/23/10 - * @author Scott Violet - * @author Philip Milne - */ -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/settings.gradle.kts b/settings.gradle.kts index 3fd25555..9b157c76 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -29,5 +29,4 @@ include( ":android", ":desktop", ":web-app" -) -include(":jaudiotagger") +) \ No newline at end of file