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 #if defined HAVE_SYS_PARAM_H
00029 #include <sys/param.h>
00030 #endif
00031
00032 #include "tag_impl.h"
00033
00034 #include "io_strings.h"
00035
00036 using namespace dami;
00037
00038 size_t ID3_TagImpl::IsV2Tag(ID3_Reader& reader)
00039 {
00040 io::ExitTrigger et(reader);
00041 size_t tagSize = 0;
00042 String id = io::readText(reader, ID3_TagHeader::ID_SIZE);
00043 String ver = io::readText(reader, 2);
00044 char flags = reader.readChar();
00045 String size = io::readText(reader, 4);
00046
00047 if (id == ID3_TagHeader::ID &&
00048 (uchar) ver [0] < 0xFF && (uchar) ver [1] < 0xFF &&
00049 (uchar) size[0] < 0x80 && (uchar) size[1] < 0x80 &&
00050 (uchar) size[2] < 0x80 && (uchar) size[3] < 0x80)
00051 {
00052 io::StringReader sr(size);
00053 tagSize = io::readUInt28(sr) + ID3_TagHeader::SIZE;
00054 }
00055 else if (id != ID3_TagHeader::ID)
00056 {
00057
00058 }
00059 else if ((uchar)ver[0] >= 0xFF)
00060 {
00061
00062 }
00063 else if ((uchar)ver[1] >= 0xFF)
00064 {
00065
00066 }
00067 else if ((uchar)size[0] >= 0x80)
00068 {
00069
00070 }
00071 else if ((uchar)size[1] >= 0x80)
00072 {
00073
00074 }
00075 else if ((uchar)size[2] >= 0x80)
00076 {
00077
00078 }
00079 else if ((uchar)size[3] >= 0x80)
00080 {
00081
00082 }
00083 else
00084 {
00085
00086 }
00087
00088 return tagSize;
00089 }
00090
00091 ID3_TagImpl::ID3_TagImpl(const char *name)
00092 : _frames(),
00093 _cursor(_frames.begin()),
00094 _file_name(),
00095 _file_size(0),
00096 _prepended_bytes(0),
00097 _appended_bytes(0),
00098 _is_file_writable(false),
00099 _mp3_info(NULL)
00100 {
00101 this->Clear();
00102 if (name)
00103 {
00104 this->Link(name);
00105 }
00106 }
00107
00108 ID3_TagImpl::ID3_TagImpl(const ID3_Tag &tag)
00109 : _frames(),
00110 _cursor(_frames.begin()),
00111 _file_name(),
00112 _file_size(0),
00113 _prepended_bytes(0),
00114 _appended_bytes(0),
00115 _is_file_writable(false),
00116 _mp3_info(NULL)
00117 {
00118 *this = tag;
00119 }
00120
00121 ID3_TagImpl::~ID3_TagImpl()
00122 {
00123 this->Clear();
00124 }
00125
00126 void ID3_TagImpl::Clear()
00127 {
00128 for (iterator cur = _frames.begin(); cur != _frames.end(); ++cur)
00129 {
00130 if (*cur)
00131 {
00132 delete *cur;
00133 *cur = NULL;
00134 }
00135 }
00136 _frames.clear();
00137 _cursor = _frames.begin();
00138 _is_padded = true;
00139
00140 _hdr.Clear();
00141 _hdr.SetSpec(ID3V2_LATEST);
00142
00143 _tags_to_parse.clear();
00144 if (_mp3_info)
00145 delete _mp3_info;
00146
00147 _mp3_info = NULL;
00148
00149 _changed = true;
00150 }
00151
00152
00153 void ID3_TagImpl::AddFrame(const ID3_Frame& frame)
00154 {
00155 this->AddFrame(&frame);
00156 }
00157
00158 void ID3_TagImpl::AddFrame(const ID3_Frame* frame)
00159 {
00160 if (frame)
00161 {
00162 ID3_Frame* frm = new ID3_Frame(*frame);
00163 this->AttachFrame(frm);
00164 }
00165 }
00166
00167 bool ID3_TagImpl::AttachFrame(ID3_Frame *frame)
00168 {
00169
00170 if (NULL == frame)
00171 {
00172
00173 return false;
00174
00175 }
00176
00177 _frames.push_back(frame);
00178 _cursor = _frames.begin();
00179
00180 _changed = true;
00181 return true;
00182 }
00183
00184
00185 ID3_Frame* ID3_TagImpl::RemoveFrame(const ID3_Frame *frame)
00186 {
00187 ID3_Frame *frm = NULL;
00188
00189 iterator fi = Find(frame);
00190 if (fi != _frames.end())
00191 {
00192 frm = *fi;
00193 _frames.erase(fi);
00194 _cursor = _frames.begin();
00195 _changed = true;
00196 }
00197
00198 return frm;
00199 }
00200
00201
00202 bool ID3_TagImpl::HasChanged() const
00203 {
00204 bool changed = _changed;
00205
00206 if (! changed)
00207 {
00208 for (const_iterator fi = _frames.begin(); fi != _frames.end(); ++fi)
00209 {
00210 if (*fi)
00211 {
00212 changed = (*fi)->HasChanged();
00213 }
00214
00215 if (changed)
00216 {
00217 break;
00218 }
00219 }
00220 }
00221
00222 return changed;
00223 }
00224
00225 bool ID3_TagImpl::SetSpec(ID3_V2Spec spec)
00226 {
00227 bool changed = _hdr.SetSpec(spec);
00228 _changed = _changed || changed;
00229 return changed;
00230 }
00231
00232 ID3_V2Spec ID3_TagImpl::GetSpec() const
00233 {
00234 return _hdr.GetSpec();
00235 }
00236
00237 bool ID3_TagImpl::SetUnsync(bool b)
00238 {
00239 bool changed = _hdr.SetUnsync(b);
00240 _changed = changed || _changed;
00241 return changed;
00242 }
00243
00244 bool ID3_TagImpl::SetExtended(bool ext)
00245 {
00246 bool changed = _hdr.SetExtended(ext);
00247 _changed = changed || _changed;
00248 return changed;
00249 }
00250
00251 bool ID3_TagImpl::SetExperimental(bool exp)
00252 {
00253 bool changed = _hdr.SetExperimental(exp);
00254 _changed = changed || _changed;
00255 return changed;
00256 }
00257
00258 bool ID3_TagImpl::GetUnsync() const
00259 {
00260 return _hdr.GetUnsync();
00261 }
00262
00263 bool ID3_TagImpl::GetExtended() const
00264 {
00265 return _hdr.GetExtended();
00266 }
00267
00268 bool ID3_TagImpl::GetExperimental() const
00269 {
00270 return _hdr.GetExperimental();
00271 }
00272
00273 bool ID3_TagImpl::GetFooter() const
00274 {
00275 return _hdr.GetFooter();
00276 }
00277
00278 size_t ID3_TagImpl::GetExtendedBytes() const
00279 {
00280 if (this->GetExtended())
00281 if (this->GetSpec() == ID3V2_4_0)
00282 return 6;
00283 else if (this->GetSpec() == ID3V2_3_0)
00284 return 10;
00285 else
00286 return 0;
00287 else
00288 return 0;;
00289 }
00290
00291 bool ID3_TagImpl::SetPadding(bool pad)
00292 {
00293 bool changed = (_is_padded != pad);
00294 _changed = changed || _changed;
00295 if (changed)
00296 {
00297 _is_padded = pad;
00298 }
00299
00300 return changed;
00301 }
00302
00303
00304 ID3_TagImpl &
00305 ID3_TagImpl::operator=( const ID3_Tag &rTag )
00306 {
00307 this->Clear();
00308
00309 this->SetUnsync(rTag.GetUnsync());
00310 this->SetExtended(rTag.GetExtendedHeader());
00311 this->SetExperimental(rTag.GetExperimental());
00312
00313 ID3_Tag::ConstIterator* iter = rTag.CreateIterator();
00314 const ID3_Frame* frame = NULL;
00315 while (NULL != (frame = iter->GetNext()))
00316 {
00317 this->AttachFrame(new ID3_Frame(*frame));
00318 }
00319 delete iter;
00320 return *this;
00321 }
00322
00323 size_t ID3_GetDataSize(const ID3_TagImpl& tag)
00324 {
00325 return tag.GetFileSize() - tag.GetPrependedBytes() - tag.GetAppendedBytes();
00326 }
00327