Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "header_tag.h"
00030 #include "id3/utils.h"
00031 #include "tag.h"
00032 #include "io_helpers.h"
00033 #include "spec.h"
00034
00035 using namespace dami;
00036
00037 const char* const ID3_TagHeader::ID = "ID3";
00038
00039 bool ID3_TagHeader::SetSpec(ID3_V2Spec spec)
00040 {
00041 bool changed = this->ID3_Header::SetSpec(spec);
00042 if (changed)
00043 {
00044 if (_info)
00045 {
00046 _flags.set(HEADER_FLAG_EXPERIMENTAL, _info->is_experimental);
00047 _flags.set(HEADER_FLAG_EXTENDED, _info->is_extended);
00048 }
00049 }
00050 return changed;
00051 }
00052
00053 size_t ID3_TagHeader::Size() const
00054 {
00055 size_t bytesUsed = ID3_TagHeader::SIZE;
00056
00057 if (_info && _info->is_extended)
00058 {
00059 bytesUsed += _info->extended_bytes;
00060 }
00061
00062 return bytesUsed;
00063 }
00064
00065
00066 void ID3_TagHeader::Render(ID3_Writer& writer) const
00067 {
00068 writer.writeChars((uchar *) ID, strlen(ID));
00069
00070 writer.writeChar(ID3_V2SpecToVer(ID3V2_LATEST));
00071 writer.writeChar(ID3_V2SpecToRev(ID3V2_LATEST));
00072
00073
00074 writer.writeChar(static_cast<uchar>(_flags.get() & MASK8));
00075 io::writeUInt28(writer, this->GetDataSize());
00076
00077
00078 if (_flags.test(HEADER_FLAG_EXTENDED))
00079 {
00080 if (this->GetSpec() == ID3V2_4_0)
00081 {
00082 io::writeUInt28(writer, 6);
00083 io::writeBENumber(writer, 1, 1);
00084 io::writeBENumber(writer, 0, 1);
00085 }
00086 else if (this->GetSpec() == ID3V2_3_0)
00087 {
00088 io::writeBENumber(writer, 6, sizeof(uint32));
00089 for (size_t i = 0; i < 6; ++i)
00090 {
00091 if (writer.writeChar('\0') == ID3_Writer::END_OF_WRITER)
00092 {
00093 break;
00094 }
00095 }
00096 }
00097
00098 }
00099 }
00100
00101 bool ID3_TagHeader::Parse(ID3_Reader& reader)
00102 {
00103 io::ExitTrigger et(reader);
00104 if (!ID3_Tag::IsV2Tag(reader))
00105 {
00106 ID3D_NOTICE( "ID3_TagHeader::Parse(): not an id3v2 header" );
00107 return false;
00108 }
00109
00110 uchar id[3];
00111 reader.readChars(id, 3);
00112
00113 uchar major = reader.readChar();
00114 uchar minor = reader.readChar();
00115 this->SetSpec(ID3_VerRevToV2Spec(major, minor));
00116
00117
00118 _flags.set(static_cast<ID3_Flags::TYPE>(reader.readChar()));
00119
00120
00121 this->SetDataSize(io::readUInt28(reader));
00122
00123 if (_flags.test(HEADER_FLAG_EXTENDED) && this->GetSpec() == ID3V2_2_1)
00124 {
00125
00126 _flags.set(HEADER_FLAG_EXTENDED, false);
00127 _info->extended_bytes = 0;
00128
00129 }
00130 et.setExitPos(reader.getCur());
00131 return true;
00132 }
00133
00134 void ID3_TagHeader::ParseExtended(ID3_Reader& reader)
00135 {
00136 if (this->GetSpec() == ID3V2_3_0)
00137 {
00138
00139
00140
00141
00142
00143
00144 reader.setCur(reader.getCur()+4);
00145
00146 uint16 tmpval = io::readBENumber(reader, 2);
00147
00148 reader.setCur(reader.getCur()+4);
00149
00150 if (tmpval != 0)
00151 {
00152
00153 reader.setCur(reader.getCur()+4);
00154
00155 _info->extended_bytes = 14;
00156 }
00157 else
00158 _info->extended_bytes = 10;
00159 }
00160 if (this->GetSpec() == ID3V2_4_0)
00161 {
00162
00163
00164
00165
00166
00167 uint16 i;
00168 uint16 extrabytes;
00169
00170 io::readUInt28(reader);
00171 const int extflagbytes = reader.readChar();
00172 ID3_Flags* extflags[1];
00173 for (i = 0; i < extflagbytes; ++i)
00174 {
00175 extflags[i] = new ID3_Flags;
00176 extflags[i]->set(reader.readChar());
00177 }
00178 extrabytes = 0;
00179
00180 if (extflags[0]->test(EXT_HEADER_FLAG_BIT2))
00181 {
00182
00183
00184 extrabytes += 1;
00185 const int extheaderflagdatasize = reader.readChar();
00186 extrabytes += extheaderflagdatasize;
00187
00188 reader.setCur(reader.getCur() + extheaderflagdatasize);
00189
00190 }
00191 if (extflags[0]->test(EXT_HEADER_FLAG_BIT3))
00192 {
00193
00194
00195 extrabytes += 1;
00196 const int extheaderflagdatasize = reader.readChar();
00197 extrabytes += extheaderflagdatasize;
00198
00199 reader.setCur(reader.getCur() + extheaderflagdatasize);
00200
00201 }
00202 if (extflags[0]->test(EXT_HEADER_FLAG_BIT4))
00203 {
00204
00205
00206 extrabytes += 1;
00207 const int extheaderflagdatasize = reader.readChar();
00208 extrabytes += extheaderflagdatasize;
00209
00210 reader.setCur(reader.getCur() + extheaderflagdatasize);
00211
00212 }
00213 _info->extended_bytes = 5 + extflagbytes + extrabytes;
00214 }
00215
00216
00217 _flags.set(HEADER_FLAG_EXTENDED, false);
00218 if (_info)
00219 {
00220 _data_size -= _info->extended_bytes;
00221 _info->extended_bytes = 0;
00222 }
00223 }
00224