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

Generated on Thu Jan 3 07:35:55 2002 for id3lib by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001