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