Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

src/helpers.cpp

Go to the documentation of this file.
00001 // $Id: helpers.cpp,v 1.8 2000/10/29 01:37:29 eldamitri Exp $
00002 
00003 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
00004 // Copyright 1999, 2000  Scott Thomas Haug
00005 
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Library General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or (at your
00009 // option) any later version.
00010 //
00011 // This library is distributed in the hope that it will be useful, but WITHOUT
00012 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00014 // License for more details.
00015 //
00016 // You should have received a copy of the GNU Library General Public License
00017 // along with this library; if not, write to the Free Software Foundation,
00018 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 
00020 // The id3lib authors encourage improvements and optimisations to be sent to
00021 // the id3lib coordinator.  Please see the README file for details on where to
00022 // send such submissions.  See the AUTHORS file for a list of people who have
00023 // contributed to id3lib.  See the ChangeLog file for a list of changes to
00024 // id3lib.  These files are distributed with id3lib at
00025 // http://download.sourceforge.net/id3lib/
00026 
00027 #if defined HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030 
00031 
00032 
00033 #include <ctype.h>
00034 
00035 #include "helpers.h"
00036 #include "tag_impl.h"
00037 #include "frame.h"
00038 #include "field.h"
00039 #include "utils.h"
00040 
00041 using namespace dami;
00042 
00043 String id3::v2::getString(const ID3_Frame* frame, ID3_FieldID fldName)
00044 {
00045   if (!frame)
00046   {
00047     return "";
00048   }
00049   ID3_Field* fp = frame->GetField(fldName);
00050   if (!fp)
00051   {
00052     return "";
00053   }
00054   ID3_TextEnc enc = fp->GetEncoding();
00055   fp->SetEncoding(ID3TE_ASCII);
00056   
00057   String text(fp->GetRawText(), fp->Size());
00058   
00059   fp->SetEncoding(enc);
00060   return text;
00061 }
00062 
00063 String id3::v2::getStringAtIndex(const ID3_Frame* frame, ID3_FieldID fldName, 
00064                                  size_t nIndex)
00065 {
00066   if (!frame)
00067   {
00068     return "";
00069   }
00070   String text;
00071   ID3_Field* fp = frame->GetField(fldName);
00072   if (fp && fp->GetNumTextItems() < nIndex)
00073   {
00074     ID3_TextEnc enc = fp->GetEncoding();
00075     fp->SetEncoding(ID3TE_ASCII);
00076 
00077     text = fp->GetRawTextItem(nIndex);
00078     
00079     fp->SetEncoding(enc);
00080   }
00081   return text;
00082 }
00083 
00084 size_t id3::v2::removeFrames(ID3_TagImpl& tag, ID3_FrameID id)
00085 {
00086   size_t numRemoved = 0;
00087   ID3_Frame* frame = NULL;
00088 
00089   while ((frame = tag.Find(id)) != NULL)
00090   {
00091     frame = tag.RemoveFrame(frame);
00092     delete frame;
00093     numRemoved++;
00094   }
00095 
00096   return numRemoved;
00097 }
00098 
00099 String id3::v2::getFrameText(const ID3_TagImpl& tag, ID3_FrameID id)
00100 {
00101   ID3_Frame* frame = tag.Find(id);
00102   return getString(frame, ID3FN_TEXT);
00103 }
00104 
00105 ID3_Frame* id3::v2::setFrameText(ID3_TagImpl& tag, ID3_FrameID id, String text)
00106 {
00107   ID3_Frame* frame = tag.Find(id);
00108   if (!frame)
00109   {
00110     frame = new ID3_Frame(id);
00111     tag.AttachFrame(frame);
00112   }
00113   frame->GetField(ID3FN_TEXT)->Set(text.c_str());
00114   
00115   return frame;
00116 }
00117 
00118 ID3_Frame* id3::v2::hasArtist(const ID3_TagImpl& tag)
00119 {
00120   ID3_Frame* fp = NULL;
00121   (fp = tag.Find(ID3FID_LEADARTIST)) ||
00122   (fp = tag.Find(ID3FID_BAND))       ||
00123   (fp = tag.Find(ID3FID_CONDUCTOR))  ||
00124   (fp = tag.Find(ID3FID_COMPOSER));
00125   return fp;
00126 }
00127 
00128 String id3::v2::getArtist(const ID3_TagImpl& tag)
00129 {
00130   ID3_Frame* frame = hasArtist(tag);
00131   return getString(frame, ID3FN_TEXT);
00132 }
00133 
00134 ID3_Frame* id3::v2::setArtist(ID3_TagImpl& tag, String text)
00135 {
00136   removeArtists(tag);
00137   return setFrameText(tag, ID3FID_LEADARTIST, text);
00138 }
00139 
00140 size_t id3::v2::removeArtists(ID3_TagImpl& tag)
00141 {
00142   size_t numRemoved = 0;
00143   ID3_Frame* frame = NULL;
00144   
00145   while ((frame = hasArtist(tag)) != NULL)
00146   {
00147     frame = tag.RemoveFrame(frame);
00148     delete frame;
00149     numRemoved++;
00150   }
00151   
00152   return numRemoved;
00153 }
00154 
00155 String id3::v2::getAlbum(const ID3_TagImpl& tag)
00156 {
00157   return getFrameText(tag, ID3FID_ALBUM);
00158 }
00159 
00160 ID3_Frame* id3::v2::setAlbum(ID3_TagImpl& tag, String text)
00161 {
00162   return setFrameText(tag, ID3FID_ALBUM, text);
00163 }
00164 
00165 size_t id3::v2::removeAlbums(ID3_TagImpl& tag)
00166 {
00167   return removeFrames(tag, ID3FID_ALBUM);
00168 }
00169 
00170 String id3::v2::getTitle(const ID3_TagImpl& tag)
00171 {
00172   return getFrameText(tag, ID3FID_TITLE);
00173 }
00174 
00175 ID3_Frame* id3::v2::setTitle(ID3_TagImpl& tag, String text)
00176 {
00177   return setFrameText(tag, ID3FID_TITLE, text);
00178 }
00179 
00180 size_t id3::v2::removeTitles(ID3_TagImpl& tag)
00181 {
00182   return removeFrames(tag, ID3FID_TITLE);
00183 }
00184 
00185 String id3::v2::getYear(const ID3_TagImpl& tag)
00186 {
00187   return getFrameText(tag, ID3FID_YEAR);
00188 }
00189 
00190 ID3_Frame* id3::v2::setYear(ID3_TagImpl& tag, String text)
00191 {
00192   return setFrameText(tag, ID3FID_YEAR, text);
00193 }
00194 
00195 size_t id3::v2::removeYears(ID3_TagImpl& tag)
00196 {
00197   return removeFrames(tag, ID3FID_YEAR);
00198 }
00199 
00200 String id3::v2::getV1Comment(const ID3_TagImpl& tag)
00201 {
00202   ID3_Frame* frame;
00203   (frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, STR_V1_COMMENT_DESC)) ||
00204   (frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, ""                 )) ||
00205   (frame = tag.Find(ID3FID_COMMENT));
00206   return getString(frame, ID3FN_TEXT);
00207 }
00208 
00209 String id3::v2::getComment(const ID3_TagImpl& tag, String desc)
00210 {
00211   ID3_Frame* frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, desc.c_str());
00212   return getString(frame, ID3FN_TEXT);
00213 }
00214 
00215 ID3_Frame* id3::v2::setComment(ID3_TagImpl& tag, String text, String desc, 
00216                                String lang)
00217 {
00218   ID3D_NOTICE( "id3::v2::setComment: trying to find frame with description = " << desc );
00219   ID3_Frame* frame = NULL;
00220   // See if there is already a comment with this description
00221   for (ID3_TagImpl::iterator iter = tag.begin(); iter != tag.end(); ++iter)
00222   {
00223     frame = *iter;
00224     if (frame == NULL)
00225     {
00226       continue;
00227     }
00228     if (frame->GetID() == ID3FID_COMMENT)
00229     {
00230       String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
00231       if (tmpDesc == desc)
00232       {
00233         ID3D_NOTICE( "id3::v2::setComment: found frame with description = " << desc );
00234         break;
00235       }
00236     }
00237     frame = NULL;
00238   }
00239   if (frame == NULL)
00240   {
00241     ID3D_NOTICE( "id3::v2::setComment: creating new comment frame" );
00242     frame = new ID3_Frame(ID3FID_COMMENT);
00243     tag.AttachFrame(frame);
00244   }
00245   if (!frame)
00246   {
00247     ID3D_WARNING( "id3::v2::setComment: ack! no frame" );
00248   }
00249   else
00250   {
00251     frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
00252     frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
00253     frame->GetField(ID3FN_TEXT)->Set(text.c_str());
00254   }
00255 
00256   return frame;
00257 }
00258 
00259 // Remove all comments from the tag
00260 size_t id3::v2::removeAllComments(ID3_TagImpl& tag)
00261 {
00262   return removeFrames(tag, ID3FID_COMMENT);
00263 }
00264 
00265 // Remove all comments from the tag with the given description
00266 size_t id3::v2::removeComments(ID3_TagImpl& tag, String desc)
00267 {
00268   size_t numRemoved = 0;
00269 
00270   for (ID3_TagImpl::iterator iter = tag.begin(); iter != tag.end(); ++iter)
00271   {
00272     ID3_Frame* frame = *iter;
00273     if (frame == NULL)
00274     {
00275       continue;
00276     }
00277     if (frame->GetID() == ID3FID_COMMENT)
00278     {
00279       // See if the description we have matches the description of the 
00280       // current comment.  If so, remove the comment
00281       String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
00282       if (tmpDesc == desc)
00283       {
00284         frame = tag.RemoveFrame(frame);
00285         delete frame;
00286         numRemoved++;
00287       }
00288     }
00289   }
00290 
00291   return numRemoved;
00292 }
00293 
00294 String id3::v2::getTrack(const ID3_TagImpl& tag)
00295 {
00296   return getFrameText(tag, ID3FID_TRACKNUM);
00297 }
00298 
00299 size_t id3::v2::getTrackNum(const ID3_TagImpl& tag)
00300 {
00301   String sTrack = getTrack(tag);
00302   return ::atoi(sTrack.c_str());
00303 }
00304 
00305 ID3_Frame* id3::v2::setTrack(ID3_TagImpl& tag, uchar trk, uchar ttl)
00306 {
00307   ID3_Frame* frame = NULL;
00308   String track = toString((size_t)trk);
00309   if (ttl > 0)
00310   {
00311     track += "/";
00312     track += toString((size_t)ttl);
00313   }
00314   setFrameText(tag, ID3FID_TRACKNUM, track);
00315   
00316   return frame;
00317 }
00318 
00319 size_t id3::v2::removeTracks(ID3_TagImpl& tag)
00320 {
00321   return removeFrames(tag, ID3FID_TRACKNUM);
00322 }
00323 
00324 String id3::v2::getGenre(const ID3_TagImpl& tag)
00325 {
00326   return getFrameText(tag, ID3FID_CONTENTTYPE);
00327 }
00328 
00329 size_t id3::v2::getGenreNum(const ID3_TagImpl& tag)
00330 {
00331   String sGenre = getGenre(tag);
00332   size_t ulGenre = 0xFF;
00333   size_t size = sGenre.size();
00334 
00335   // If the genre string begins with "(ddd)", where "ddd" is a number, then 
00336   // "ddd" is the genre number---get it
00337   index_t i = 0;
00338   if (i < size && size && sGenre[i] == '(')
00339   {
00340     ++i;
00341     while (i < size && isdigit(sGenre[i]))
00342     {
00343       ++i;
00344     }
00345     if (i < size && sGenre[i] == ')')
00346     {
00347       // if the genre number is greater than 255, its invalid.
00348       ulGenre = min(0xFF, atoi(&sGenre[1]));
00349     }
00350   }
00351 
00352   return ulGenre;
00353 }
00354 
00355 ID3_Frame* id3::v2::setGenre(ID3_TagImpl& tag, size_t genre)
00356 {
00357   String sGenre = "(";
00358   sGenre += toString(genre) + ")";
00359   return setFrameText(tag, ID3FID_CONTENTTYPE, sGenre);
00360 }
00361 
00362 size_t id3::v2::removeGenres(ID3_TagImpl& tag)
00363 {
00364   return removeFrames(tag, ID3FID_CONTENTTYPE);
00365 }
00366 
00367 String id3::v2::getLyrics(const ID3_TagImpl& tag)
00368 {
00369   return getFrameText(tag, ID3FID_UNSYNCEDLYRICS);
00370 }
00371 
00372 ID3_Frame* id3::v2::setLyrics(ID3_TagImpl& tag, String text, String desc,
00373                               String lang)
00374 {
00375   ID3_Frame* frame = NULL;
00376   // See if there is already a comment with this description
00377   for (ID3_TagImpl::iterator iter = tag.begin(); iter != tag.end(); ++iter)
00378   {
00379     frame = *iter;
00380     if (frame == NULL)
00381     {
00382       continue;
00383     }
00384     if (frame->GetID() == ID3FID_COMMENT)
00385     {
00386       String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
00387       if (tmpDesc == desc)
00388       {
00389         break;
00390       }
00391     }
00392     frame = NULL;
00393   }
00394   if (frame == NULL)
00395   {
00396     frame = new ID3_Frame(ID3FID_UNSYNCEDLYRICS);
00397     tag.AttachFrame(frame);
00398   }
00399   frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
00400   frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
00401   frame->GetField(ID3FN_TEXT)->Set(text.c_str());
00402 
00403   return frame;
00404 }
00405 
00406 size_t id3::v2::removeLyrics(ID3_TagImpl& tag)
00407 {
00408   return removeFrames(tag, ID3FID_UNSYNCEDLYRICS);
00409 }
00410 
00411 String id3::v2::getLyricist(const ID3_TagImpl& tag)
00412 {
00413   return getFrameText(tag, ID3FID_LYRICIST);
00414 }
00415 
00416 ID3_Frame* id3::v2::setLyricist(ID3_TagImpl& tag, String text)
00417 {
00418   return setFrameText(tag, ID3FID_LYRICIST, text);
00419 }
00420 
00421 size_t id3::v2::removeLyricists(ID3_TagImpl& tag)
00422 {
00423   return removeFrames(tag, ID3FID_LYRICIST);
00424 }
00425 
00426 ID3_Frame* id3::v2::setSyncLyrics(ID3_TagImpl& tag, BString data,
00427                                   ID3_TimeStampFormat format, String desc, 
00428                                   String lang, ID3_ContentType type)
00429 {
00430   ID3_Frame* frame = NULL;
00431 
00432   // check if a SYLT frame of this language or descriptor already exists
00433   (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang)) ||
00434   (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc));
00435 
00436   if (!frame)
00437   {
00438     frame = new ID3_Frame(ID3FID_SYNCEDLYRICS);
00439     tag.AttachFrame(frame);
00440   }
00441   frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
00442   frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
00443   frame->GetField(ID3FN_TIMESTAMPFORMAT)->Set(format);
00444   frame->GetField(ID3FN_CONTENTTYPE)->Set(type);
00445   frame->GetField(ID3FN_DATA)->Set(data.data(), data.size());
00446 
00447   return frame;
00448 }
00449 
00450 BString id3::v2::getSyncLyrics(const ID3_TagImpl& tag, String lang, String desc)
00451 {
00452   // check if a SYLT frame of this language or descriptor exists
00453   ID3_Frame* frame = NULL;
00454   (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang)) ||
00455   (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc)) ||
00456   (frame = tag.Find(ID3FID_SYNCEDLYRICS));
00457   
00458   // get the lyrics size
00459   ID3_Field* fld = frame->GetField(ID3FN_DATA);
00460   return BString(reinterpret_cast<const BString::value_type *>(fld->GetRawBinary()), fld->Size());
00461 }
00462 

Generated at Sat Sep 8 15:51:09 2001 for id3lib by doxygen1.2.8 written by Dimitri van Heesch, © 1997-2001