src/tag_impl.cpp

Go to the documentation of this file.
00001 // $Id: tag_impl.cpp,v 1.13 2002/09/21 17:23:32 t1mpy Exp $
00002 
00003 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
00004 // Copyright 1999, 2000  Scott Thomas Haug
00005 // Copyright 2002 Thijmen Klok (thijmen@id3lib.org)
00006 
00007 // This library is free software; you can redistribute it and/or modify it
00008 // under the terms of the GNU Library General Public License as published by
00009 // the Free Software Foundation; either version 2 of the License, or (at your
00010 // option) any later version.
00011 //
00012 // This library is distributed in the hope that it will be useful, but WITHOUT
00013 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015 // License for more details.
00016 //
00017 // You should have received a copy of the GNU Library General Public License
00018 // along with this library; if not, write to the Free Software Foundation,
00019 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 
00021 // The id3lib authors encourage improvements and optimisations to be sent to
00022 // the id3lib coordinator.  Please see the README file for details on where to
00023 // send such submissions.  See the AUTHORS file for a list of people who have
00024 // contributed to id3lib.  See the ChangeLog file for a list of changes to
00025 // id3lib.  These files are distributed with id3lib at
00026 // http://download.sourceforge.net/id3lib/
00027 
00028 #if defined HAVE_SYS_PARAM_H
00029 #include <sys/param.h>
00030 #endif
00031 
00032 #include "tag_impl.h" //has <stdio.h> "tag.h" "header_tag.h" "frame.h" "field.h" "spec.h" "id3lib_strings.h" "utils.h"
00033 //#include "io_helpers.h"
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     // clog << "*** IsV2Tag: Not an id3v2 tag header" << endl;
00058   }
00059   else if ((uchar)ver[0] >= 0xFF)
00060   {
00061     // clog << "*** IsV2Tag: Major offset" << endl;
00062   }
00063   else if ((uchar)ver[1] >= 0xFF)
00064   {
00065     // clog << "*** ISV2Tag: Minor offset" << endl;
00066   }
00067   else if ((uchar)size[0] >= 0x80)
00068   {
00069     // clog << "*** ISV2Tag: 1st size offset" << endl;
00070   }
00071   else if ((uchar)size[1] >= 0x80)
00072   {
00073     // clog << "*** ISV2Tag: 2nd size offset" << endl;
00074   }
00075   else if ((uchar)size[2] >= 0x80)
00076   {
00077     // clog << "*** ISV2Tag: 3rd size offset" << endl;
00078   }
00079   else if ((uchar)size[3] >= 0x80)
00080   {
00081     // clog << "*** ISV2Tag: 4th size offset" << endl;
00082   }
00083   else
00084   {
00085     // clog << "*** shouldn't get here!" << endl;
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) // need to do this before this->Clear()
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) // need to do this before this->Clear()
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; // Also deletes _mp3_header
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     // log this
00173     return false;
00174     //ID3_THROW(ID3E_NoData);
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; //minimal ID3v2.4 ext header size
00283     else if (this->GetSpec() == ID3V2_3_0)
00284       return 10; //minimal ID3v2.3 ext header size
00285     else
00286       return 0; //not implemented
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 

Generated on Mon Aug 20 17:48:46 2007 for id3lib by  doxygen 1.5.2