1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
#ifndef __ID3_Support_hpp__
#define __ID3_Support_hpp__ 1
// =================================================================================================
// Copyright Adobe
// Copyright 2008 Adobe
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it.
// =================================================================================================
#include "public/include/XMP_Environment.h" // ! This must be the first include.
#include "public/include/XMP_Const.h"
#include "public/include/XMP_IO.hpp"
#if XMP_WinBuild
#define stricmp _stricmp
#else
int stricmp ( const char * left, const char * right ); // Case insensitive ASCII compare.
#endif
// =================================================================================================
namespace ID3_Support {
// =============================================================================================
inline XMP_Int32 synchToInt32 ( XMP_Uns32 rawDataBE ) {
XMP_Validate ( (0 == (rawDataBE & 0x80808080)), "input not synchsafe", kXMPErr_InternalFailure );
XMP_Int32 r = (rawDataBE & 0x0000007F) + ((rawDataBE >> 1) & 0x00003F80) +
((rawDataBE >> 2) & 0x001FC000) + ((rawDataBE >> 3) & 0x0FE00000);
return r;
}
inline XMP_Uns32 int32ToSynch ( XMP_Int32 value ) {
XMP_Validate ( (0 <= 0x0FFFFFFF), "value too big", kXMPErr_InternalFailure );
XMP_Uns32 r = (value & 0x0000007F) + ((value & 0x00003F80) << 1) +
((value & 0x001FC000) << 2) + ((value & 0x0FE00000) << 3);
return r;
}
// =============================================================================================
bool InitializeGlobals(); // Initialize and terminate the known genre maps.
void TerminateGlobals();
// =============================================================================================
namespace GenreUtils {
void ConvertGenreToXMP ( const char * id3Genre, std::string * xmpGenre );
void ConvertGenreToID3 ( const char * xmpGenre, std::string * id3Genre );
// Internal utilities, exposed for unit testing:
const char * FindGenreName ( const std::string & code );
const char * FindGenreCode ( const std::string & name );
};
// =============================================================================================
class ID3Header { // Minimal support to read and write the ID3 header.
public:
const static size_t o_id = 0;
const static size_t o_vMajor = 3;
const static size_t o_vMinor = 4;
const static size_t o_flags = 5;
const static size_t o_size = 6;
const static size_t kID3_TagHeaderSize = 10; // This is the same in v2.2, v2.3, and v2.4.
char fields [kID3_TagHeaderSize];
~ID3Header() {};
// Read the v2 header into the fields buffer and check the version.
bool read ( XMP_IO* file );
// Set the size and write the the v2 header from the fields buffer.
void write ( XMP_IO* file, XMP_Int64 tagSize );
};
// =============================================================================================
class ID3v2Frame {
public:
// Applies to ID3 v2.2, v2.3, and v2.4. The metadata values are mostly the same, v2.2 has
// smaller frame headers and only supports UTF-16 Unicode.
const static XMP_Uns16 o_id = 0;
const static XMP_Uns16 o_size = 4; // size after unsync, excludes frame header.
const static XMP_Uns16 o_flags = 8;
const static int kV23_FrameHeaderSize = 10; // The header for v2.3 and v2.4.
const static int kV22_FrameHeaderSize = 6; // The header for v2.2.
char fields [kV23_FrameHeaderSize];
XMP_Uns32 id;
XMP_Uns16 flags;
char* content;
XMP_Int32 contentSize; // size of variable content, right as its stored in o_size
bool active; //default: true. flag is lowered, if another frame with replaces this one as "last meaningful frame of its kind"
bool changed; //default: false. flag is raised, if setString() is used
ID3v2Frame();
ID3v2Frame ( XMP_Uns32 id );
ID3v2Frame ( const ID3v2Frame& /*orig*/ ) = delete;
~ID3v2Frame() { this->release(); }
void release();
void setFrameValue ( const std::string& rawvalue, bool needDescriptor = false,
bool utf16 = false, bool isXMPPRIVFrame = false, bool needEncodingByte = true, bool isAlreadyEncoded = false );
XMP_Int64 read ( XMP_IO* file, XMP_Uns8 majorVersion );
void write ( XMP_IO* file, XMP_Uns8 majorVersion );
// two types of COMM frames should be preserved but otherwise ignored
// * a 6-field long header just having
// encoding(1 byte),lang(3 bytes) and 0x00 31 (no descriptor, "1" as content")
// perhaps only used to indicate client language
// * COMM frames whose description begins with engiTun, these are iTunes flags
//
// returns true: job done as expted
// false: do not use this frame, but preserve (i.e. iTunes marker COMM frame)
bool advancePastCOMMDescriptor ( XMP_Int32& pos );
// returns the frame content as a proper UTF8 string
// * w/o the initial encoding byte
// * dealing with BOM's
//
// @returns: by value: character string with the value
// as return value: false if frame is "not of intereset" despite a generally
// "interesting" frame ID, these are
// * iTunes-'marker' COMM frame
bool getFrameValue ( XMP_Uns8 majorVersion, XMP_Uns32 logicalID, std::string* utf8string );
};
// =============================================================================================
class ID3v1Tag { // Support for the fixed length v1 tag found at the end of the file.
public:
const static XMP_Uns16 o_tag = 0; // must be "TAG"
const static XMP_Uns16 o_title = 3;
const static XMP_Uns16 o_artist = 33;
const static XMP_Uns16 o_album = 63;
const static XMP_Uns16 o_year = 93;
const static XMP_Uns16 o_comment = 97;
const static XMP_Uns16 o_zero = 125; // must be zero for trackNo to be valid
const static XMP_Uns16 o_trackNo = 126; // trackNo
const static XMP_Uns16 o_genre = 127; // last byte: index, or 255
const static int kV1_TagSize = 128;
bool read ( XMP_IO* file, SXMPMeta* meta );
void write ( XMP_IO* file, SXMPMeta* meta );
};
}
#endif // __ID3_Support_hpp__
|