1 // $Id: misc_support.cpp,v 1.39 2002/09/19 10:20:45 t1mpy Exp $
2 
3 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
4 // Copyright 1999, 2000  Scott Thomas Haug
5 // Copyright 2002 Thijmen Klok (thijmen@id3lib.org)
6 
7 // This library is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU Library General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or (at your
10 // option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with this library; if not, write to the Free Software Foundation,
19 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 
21 // The id3lib authors encourage improvements and optimisations to be sent to
22 // the id3lib coordinator.  Please see the README file for details on where to
23 // send such submissions.  See the AUTHORS file for a list of people who have
24 // contributed to id3lib.  See the ChangeLog file for a list of changes to
25 // id3lib.  These files are distributed with id3lib at
26 // http://download.sourceforge.net/id3lib/
27 
28 //#include <ctype.h>
29 #include <stdio.h>
30 
31 #include "misc_support.h"
32 //#include "field.h"
33 #include "id3/utils.h" // has <config.h> "id3/id3lib_streams.h" "id3/globals.h" "id3/id3lib_strings.h"
34 
35 //using namespace dami;
36 
ID3_GetString(const ID3_Frame * frame,ID3_FieldID fldName)37 char *ID3_GetString(const ID3_Frame *frame, ID3_FieldID fldName)
38 {
39   char *text = NULL;
40 //  if (NULL != frame)
41   ID3_Field* fld;
42   if (NULL != frame && NULL != (fld = frame->GetField(fldName)))
43   {
44 //    ID3_Field* fld = frame->GetField(fldName);
45     ID3_TextEnc enc = fld->GetEncoding();
46     fld->SetEncoding(ID3TE_ISO8859_1);
47     size_t nText = fld->Size();
48     text = new char[nText + 1];
49     fld->Get(text, nText + 1);
50     fld->SetEncoding(enc);
51   }
52   return text;
53 }
54 
ID3_GetString(const ID3_Frame * frame,ID3_FieldID fldName,size_t nIndex)55 char *ID3_GetString(const ID3_Frame *frame, ID3_FieldID fldName, size_t nIndex)
56 {
57   char *text = NULL;
58   if (NULL != frame)
59   {
60     size_t nText = frame->GetField(fldName)->Size();
61     text = new char[nText + 1];
62     frame->GetField(fldName)->Get(text, nText + 1, nIndex);
63   }
64   return text;
65 }
66 
ID3_FreeString(char * str)67 void ID3_FreeString(char *str)
68 {
69   if(str != NULL)
70     delete [] str;
71 }
72 
ID3_GetArtist(const ID3_Tag * tag)73 char *ID3_GetArtist(const ID3_Tag *tag)
74 {
75   char *sArtist = NULL;
76   if (NULL == tag)
77   {
78     return sArtist;
79   }
80 
81   ID3_Frame *frame = NULL;
82   if ((frame = tag->Find(ID3FID_LEADARTIST)) ||
83       (frame = tag->Find(ID3FID_BAND))       ||
84       (frame = tag->Find(ID3FID_CONDUCTOR))  ||
85       (frame = tag->Find(ID3FID_COMPOSER)))
86   {
87     sArtist = ID3_GetString(frame, ID3FN_TEXT);
88   }
89   return sArtist;
90 }
91 
ID3_AddArtist(ID3_Tag * tag,const char * text,bool replace)92 ID3_Frame* ID3_AddArtist(ID3_Tag *tag, const char *text, bool replace)
93 {
94   ID3_Frame* frame = NULL;
95   if (NULL != tag && NULL != text && strlen(text) > 0)
96   {
97     if (replace)
98     {
99       ID3_RemoveArtists(tag);
100     }
101     if (replace ||
102         (tag->Find(ID3FID_LEADARTIST) == NULL &&
103          tag->Find(ID3FID_BAND)       == NULL &&
104          tag->Find(ID3FID_CONDUCTOR)  == NULL &&
105          tag->Find(ID3FID_COMPOSER)   == NULL))
106     {
107       frame = new ID3_Frame(ID3FID_LEADARTIST);
108       if (frame)
109       {
110         frame->GetField(ID3FN_TEXT)->Set(text);
111         tag->AttachFrame(frame);
112       }
113     }
114   }
115   return frame;
116 }
117 
ID3_RemoveArtists(ID3_Tag * tag)118 size_t ID3_RemoveArtists(ID3_Tag *tag)
119 {
120   size_t num_removed = 0;
121   ID3_Frame *frame = NULL;
122 
123   if (NULL == tag)
124   {
125     return num_removed;
126   }
127 
128   while ((frame = tag->Find(ID3FID_LEADARTIST)))
129   {
130     frame = tag->RemoveFrame(frame);
131     delete frame;
132     num_removed++;
133   }
134   while ((frame = tag->Find(ID3FID_BAND)))
135   {
136     frame = tag->RemoveFrame(frame);
137     delete frame;
138     num_removed++;
139   }
140   while ((frame = tag->Find(ID3FID_CONDUCTOR)))
141   {
142     frame = tag->RemoveFrame(frame);
143     delete frame;
144     num_removed++;
145   }
146   while ((frame = tag->Find(ID3FID_COMPOSER)))
147   {
148     frame = tag->RemoveFrame(frame);
149     delete frame;
150     num_removed++;
151   }
152 
153   return num_removed;
154 }
155 
ID3_GetAlbum(const ID3_Tag * tag)156 char *ID3_GetAlbum(const ID3_Tag *tag)
157 {
158   char *sAlbum = NULL;
159   if (NULL == tag)
160   {
161     return sAlbum;
162   }
163 
164   ID3_Frame *frame = tag->Find(ID3FID_ALBUM);
165   if (frame != NULL)
166   {
167     sAlbum = ID3_GetString(frame, ID3FN_TEXT);
168   }
169   return sAlbum;
170 }
171 
ID3_AddAlbum(ID3_Tag * tag,const char * text,bool replace)172 ID3_Frame* ID3_AddAlbum(ID3_Tag *tag, const char *text, bool replace)
173 {
174   ID3_Frame* frame = NULL;
175   if (NULL != tag && NULL != text && strlen(text) > 0)
176   {
177     if (replace)
178     {
179       ID3_RemoveAlbums(tag);
180     }
181     if (replace || tag->Find(ID3FID_ALBUM) == NULL)
182     {
183       frame = new ID3_Frame(ID3FID_ALBUM);
184       if (frame)
185       {
186         frame->GetField(ID3FN_TEXT)->Set(text);
187         tag->AttachFrame(frame);
188       }
189     }
190   }
191 
192   return frame;
193 }
194 
ID3_RemoveAlbums(ID3_Tag * tag)195 size_t ID3_RemoveAlbums(ID3_Tag *tag)
196 {
197   size_t num_removed = 0;
198   ID3_Frame *frame = NULL;
199 
200   if (NULL == tag)
201   {
202     return num_removed;
203   }
204 
205   while ((frame = tag->Find(ID3FID_ALBUM)))
206   {
207     frame = tag->RemoveFrame(frame);
208     delete frame;
209     num_removed++;
210   }
211 
212   return num_removed;
213 }
214 
ID3_GetTitle(const ID3_Tag * tag)215 char *ID3_GetTitle(const ID3_Tag *tag)
216 {
217   char *sTitle = NULL;
218   if (NULL == tag)
219   {
220     return sTitle;
221   }
222 
223   ID3_Frame *frame = tag->Find(ID3FID_TITLE);
224   if (frame != NULL)
225   {
226     sTitle = ID3_GetString(frame, ID3FN_TEXT);
227   }
228   return sTitle;
229 }
230 
ID3_AddTitle(ID3_Tag * tag,const char * text,bool replace)231 ID3_Frame* ID3_AddTitle(ID3_Tag *tag, const char *text, bool replace)
232 {
233   ID3_Frame* frame = NULL;
234   if (NULL != tag && NULL != text && strlen(text) > 0)
235   {
236     if (replace)
237     {
238       ID3_RemoveTitles(tag);
239     }
240     if (replace || tag->Find(ID3FID_TITLE) == NULL)
241     {
242       frame = new ID3_Frame(ID3FID_TITLE);
243       if (frame)
244       {
245         frame->GetField(ID3FN_TEXT)->Set(text);
246         tag->AttachFrame(frame);
247       }
248     }
249   }
250 
251   return frame;
252 }
253 
ID3_RemoveTitles(ID3_Tag * tag)254 size_t ID3_RemoveTitles(ID3_Tag *tag)
255 {
256   size_t num_removed = 0;
257   ID3_Frame *frame = NULL;
258 
259   if (NULL == tag)
260   {
261     return num_removed;
262   }
263 
264   while ((frame = tag->Find(ID3FID_TITLE)))
265   {
266     frame = tag->RemoveFrame(frame);
267     delete frame;
268     num_removed++;
269   }
270 
271   return num_removed;
272 }
273 
ID3_GetYear(const ID3_Tag * tag)274 char *ID3_GetYear(const ID3_Tag *tag)
275 {
276   char *sYear = NULL;
277   if (NULL == tag)
278   {
279     return sYear;
280   }
281 
282   ID3_Frame *frame = tag->Find(ID3FID_YEAR);
283   if (frame != NULL)
284   {
285     sYear = ID3_GetString(frame, ID3FN_TEXT);
286   }
287   return sYear;
288 }
289 
ID3_AddYear(ID3_Tag * tag,const char * text,bool replace)290 ID3_Frame* ID3_AddYear(ID3_Tag *tag, const char *text, bool replace)
291 {
292   ID3_Frame* frame = NULL;
293   if (NULL != tag && NULL != text && strlen(text) > 0)
294   {
295     if (replace)
296     {
297       ID3_RemoveYears(tag);
298     }
299     if (replace || tag->Find(ID3FID_YEAR) == NULL)
300     {
301       frame = new ID3_Frame(ID3FID_YEAR);
302       if (NULL != frame)
303       {
304         frame->GetField(ID3FN_TEXT)->Set(text);
305         tag->AttachFrame(frame);
306       }
307     }
308   }
309 
310   return frame;
311 }
312 
ID3_RemoveYears(ID3_Tag * tag)313 size_t ID3_RemoveYears(ID3_Tag *tag)
314 {
315   size_t num_removed = 0;
316   ID3_Frame *frame = NULL;
317 
318   if (NULL == tag)
319   {
320     return num_removed;
321   }
322 
323   while ((frame = tag->Find(ID3FID_YEAR)))
324   {
325     frame = tag->RemoveFrame(frame);
326     delete frame;
327     num_removed++;
328   }
329 
330   return num_removed;
331 }
332 
ID3_GetComment(const ID3_Tag * tag,const char * desc)333 char *ID3_GetComment(const ID3_Tag *tag, const char* desc)
334 {
335   char *comment = NULL;
336   if (NULL == tag)
337   {
338     return comment;
339   }
340 
341   ID3_Frame* frame = NULL;
342   if (desc)
343   {
344     frame = tag->Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, desc);
345   }
346   else
347   {
348     frame = tag->Find(ID3FID_COMMENT);
349     if(frame == tag->Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, STR_V1_COMMENT_DESC))
350       frame = tag->Find(ID3FID_COMMENT);
351   }
352 
353   if (frame)
354     comment = ID3_GetString(frame, ID3FN_TEXT);
355   return comment;
356 }
357 
ID3_AddComment(ID3_Tag * tag,const char * text,bool replace)358 ID3_Frame* ID3_AddComment(ID3_Tag *tag, const char *text, bool replace)
359 {
360   return ID3_AddComment(tag, text, "", replace);
361 }
362 
ID3_AddComment(ID3_Tag * tag,const char * text,const char * desc,bool replace)363 ID3_Frame* ID3_AddComment(ID3_Tag *tag, const char *text,
364                           const char *desc, bool replace)
365 {
366   return ID3_AddComment(tag, text, desc, "XXX", replace);
367 }
368 
ID3_AddComment(ID3_Tag * tag,const char * text,const char * desc,const char * lang,bool replace)369 ID3_Frame* ID3_AddComment(ID3_Tag *tag, const char *text,
370                           const char *desc, const char* lang, bool replace)
371 {
372   ID3_Frame* frame = NULL;
373   if (NULL != tag  &&
374       NULL != text &&
375       NULL != desc &&
376       strlen(text) > 0)
377   {
378     bool bAdd = true;
379     if (replace)
380     {
381       ID3_RemoveComments(tag, desc);
382     }
383     else
384     {
385       // See if there is already a comment with this description
386       ID3_Tag::Iterator* iter = tag->CreateIterator();
387       ID3_Frame* frame = NULL;
388       while ((frame = iter->GetNext()) != NULL)
389       {
390         if (frame->GetID() == ID3FID_COMMENT)
391         {
392           char *tmp_desc = ID3_GetString(frame, ID3FN_DESCRIPTION);
393           if (strcmp(tmp_desc, desc) == 0)
394           {
395             bAdd = false;
396           }
397           delete [] tmp_desc;
398           if (!bAdd)
399           {
400             break;
401           }
402         }
403       }
404       delete iter;
405     }
406     if (bAdd)
407     {
408       frame = new ID3_Frame(ID3FID_COMMENT);
409       if (NULL != frame)
410       {
411         frame->GetField(ID3FN_LANGUAGE)->Set(lang);
412         frame->GetField(ID3FN_DESCRIPTION)->Set(desc);
413         frame->GetField(ID3FN_TEXT)->Set(text);
414         tag->AttachFrame(frame);
415       }
416     }
417   }
418   return frame;
419 }
420 
421 // Remove all comments with the given description (remove all comments if
422 // desc is NULL)
ID3_RemoveComments(ID3_Tag * tag,const char * desc)423 size_t ID3_RemoveComments(ID3_Tag *tag, const char *desc)
424 {
425   size_t num_removed = 0;
426 
427   if (NULL == tag)
428   {
429     return num_removed;
430   }
431 
432   ID3_Tag::Iterator* iter = tag->CreateIterator();
433   ID3_Frame* frame = NULL;
434   while ((frame = iter->GetNext()) != NULL)
435   {
436     if (frame->GetID() == ID3FID_COMMENT)
437     {
438       bool remove = false;
439       // A null description means remove all comments
440       if (NULL == desc)
441       {
442         remove = true;
443       }
444       else
445       {
446         // See if the description we have matches the description of the
447         // current comment.  If so, set the "remove the comment" flag to true.
448         char *tmp_desc = ID3_GetString(frame, ID3FN_DESCRIPTION);
449         remove = (strcmp(tmp_desc, desc) == 0);
450         delete [] tmp_desc;
451       }
452       if (remove)
453       {
454         frame = tag->RemoveFrame(frame);
455         delete frame;
456         num_removed++;
457       }
458     }
459   }
460   delete iter;
461 
462   return num_removed;
463 }
464 
ID3_GetTrack(const ID3_Tag * tag)465 char *ID3_GetTrack(const ID3_Tag *tag)
466 {
467   char *sTrack = NULL;
468   if (NULL == tag)
469   {
470     return sTrack;
471   }
472 
473   ID3_Frame *frame = tag->Find(ID3FID_TRACKNUM);
474   if (frame != NULL)
475   {
476     sTrack = ID3_GetString(frame, ID3FN_TEXT);
477   }
478   return sTrack;
479 }
480 
ID3_GetTrackNum(const ID3_Tag * tag)481 size_t ID3_GetTrackNum(const ID3_Tag *tag)
482 {
483   char *sTrack = ID3_GetTrack(tag);
484   size_t nTrack = 0;
485   if (NULL != sTrack)
486   {
487     nTrack = atoi(sTrack);
488     delete [] sTrack;
489   }
490   return nTrack;
491 }
492 
ID3_AddTrack(ID3_Tag * tag,uchar trk,uchar ttl,bool replace)493 ID3_Frame* ID3_AddTrack(ID3_Tag *tag, uchar trk, uchar ttl, bool replace)
494 {
495   ID3_Frame* frame = NULL;
496   if (NULL != tag && trk > 0)
497   {
498     if (replace)
499     {
500       ID3_RemoveTracks(tag);
501     }
502     if (replace || NULL == tag->Find(ID3FID_TRACKNUM))
503     {
504       frame = new ID3_Frame(ID3FID_TRACKNUM);
505       if (frame)
506       {
507         char *sTrack = NULL;
508         if (0 == ttl)
509         {
510           sTrack = new char[4];
511           sprintf(sTrack, "%lu", (luint) trk);
512         }
513         else
514         {
515           sTrack = new char[8];
516           sprintf(sTrack, "%lu/%lu", (luint) trk, (luint) ttl);
517         }
518 
519         frame->GetField(ID3FN_TEXT)->Set(sTrack);
520         tag->AttachFrame(frame);
521 
522         delete [] sTrack;
523       }
524     }
525   }
526 
527   return frame;
528 }
529 
530 //following routine courtesy of John George
ID3_GetPictureData(const ID3_Tag * tag,const char * TempPicPath)531 int ID3_GetPictureData(const ID3_Tag *tag, const char *TempPicPath)
532 {
533   if (NULL == tag)
534     return 0;
535   else
536   {
537     ID3_Frame* frame = NULL;
538     frame = tag->Find(ID3FID_PICTURE);
539     if (frame != NULL)
540     {
541       ID3_Field* myField = frame->GetField(ID3FN_DATA);
542       if (myField != NULL)
543       {
544         myField->ToFile(TempPicPath);
545         return (int)myField->Size();
546       }
547       else return 0;
548     }
549     else return 0;
550   }
551 }
552 
553 //following routine courtesy of John George
ID3_GetPictureMimeType(const ID3_Tag * tag)554 char* ID3_GetPictureMimeType(const ID3_Tag *tag)
555 {
556   char* sPicMimetype = NULL;
557   if (NULL == tag)
558     return sPicMimetype;
559 
560   ID3_Frame* frame = NULL;
561   frame = tag->Find(ID3FID_PICTURE);
562   if (frame != NULL)
563   {
564     sPicMimetype = ID3_GetString(frame, ID3FN_MIMETYPE);
565   }
566   return sPicMimetype;
567 }
568 
569 //following routine courtesy of John George
ID3_HasPicture(const ID3_Tag * tag)570 bool ID3_HasPicture(const ID3_Tag* tag)
571 {
572   if (NULL == tag)
573     return false;
574   else
575   {
576     ID3_Frame* frame = tag->Find(ID3FID_PICTURE);
577     if (frame != NULL)
578     {
579       ID3_Field* myField = frame->GetField(ID3FN_DATA);
580       if (myField != NULL)
581         return true;
582       else
583         return false;
584     }
585     else return false;
586   }
587 }
588 
589 //following routine courtesy of John George
ID3_AddPicture(ID3_Tag * tag,const char * TempPicPath,const char * MimeType,bool replace)590 ID3_Frame* ID3_AddPicture(ID3_Tag* tag, const char* TempPicPath, const char* MimeType, bool replace)
591 {
592   ID3_Frame* frame = NULL;
593   if (NULL != tag )
594   {
595     if (replace)
596       ID3_RemovePictures(tag);
597     if (replace || NULL == tag->Find(ID3FID_PICTURE))
598     {
599       frame = new ID3_Frame(ID3FID_PICTURE);
600       if (NULL != frame)
601       {
602         frame->GetField(ID3FN_DATA)->FromFile(TempPicPath);
603         frame->GetField(ID3FN_MIMETYPE)->Set(MimeType);
604         tag->AttachFrame(frame);
605       }
606     }
607   }
608   return frame;
609 }
610 
611 //following routine courtesy of John George
ID3_RemovePictures(ID3_Tag * tag)612 size_t ID3_RemovePictures(ID3_Tag* tag)
613 {
614   size_t num_removed = 0;
615   ID3_Frame* frame = NULL;
616 
617   if (NULL == tag)
618     return num_removed;
619 
620   while ((frame = tag->Find(ID3FID_PICTURE)))
621   {
622     frame = tag->RemoveFrame(frame);
623     delete frame;
624     num_removed++;
625   }
626   return num_removed;
627 }
628 
629 //following routine courtesy of John George
ID3_RemovePictureType(ID3_Tag * tag,ID3_PictureType pictype)630 size_t ID3_RemovePictureType(ID3_Tag* tag, ID3_PictureType pictype)
631 {
632   size_t bremoved = 0;
633   ID3_Frame* frame = NULL;
634 
635   if (NULL == tag)
636     return bremoved;
637 
638   ID3_Tag::Iterator* iter = tag->CreateIterator();
639 
640   while (NULL != (frame = iter->GetNext()))
641   {
642     if (frame->GetID() == ID3FID_PICTURE)
643     {
644       if (frame->GetField(ID3FN_PICTURETYPE)->Get() == (uint32)pictype)
645         break;
646     }
647   }
648   delete iter;
649 
650   if (NULL != frame)
651   {
652     frame = tag->RemoveFrame(frame);
653     delete frame;
654     bremoved = 1;
655   }
656   return bremoved;
657 }
658 
659 //following routine courtesy of John George
ID3_AddPicture(ID3_Tag * tag,const char * TempPicPath,const char * MimeType,ID3_PictureType pictype,const char * Description,bool replace)660 ID3_Frame* ID3_AddPicture(ID3_Tag *tag, const char *TempPicPath, const char *MimeType, ID3_PictureType pictype, const char* Description, bool replace)
661 {
662   ID3_Frame* frame = NULL;
663   if (NULL != tag )
664   {
665     if (replace)
666       ID3_RemovePictureType(tag, pictype);
667     if (replace || NULL == tag->Find(ID3FID_PICTURE))
668     {
669       frame = new ID3_Frame(ID3FID_PICTURE);
670       if (NULL != frame)
671       {
672         frame->GetField(ID3FN_DATA)->FromFile(TempPicPath);
673         frame->GetField(ID3FN_MIMETYPE)->Set(MimeType);
674         frame->GetField(ID3FN_PICTURETYPE)->Set((uint32)pictype);
675         frame->GetField(ID3FN_DESCRIPTION)->Set(Description);
676         tag->AttachFrame(frame);
677       }
678     }
679   }
680   return frame;
681 }
682 
683 //following routine courtesy of John George
ID3_GetPictureDataOfPicType(ID3_Tag * tag,const char * TempPicPath,ID3_PictureType pictype)684 size_t ID3_GetPictureDataOfPicType(ID3_Tag* tag, const char* TempPicPath, ID3_PictureType pictype)
685 {
686   if (NULL == tag)
687     return 0;
688   else
689   {
690     ID3_Frame* frame = NULL;
691     ID3_Tag::Iterator* iter = tag->CreateIterator();
692 
693     while (NULL != (frame = iter->GetNext() ))
694     {
695       if(frame->GetID() == ID3FID_PICTURE)
696       {
697         if(frame->GetField(ID3FN_PICTURETYPE)->Get() == (uint32)pictype)
698           break;
699       }
700     }
701     delete iter;
702 
703     if (frame != NULL)
704     {
705       ID3_Field* myField = frame->GetField(ID3FN_DATA);
706       if (myField != NULL)
707       {
708         myField->ToFile(TempPicPath);
709         return (size_t)myField->Size();
710       }
711       else return 0;
712     }
713     else return 0;
714   }
715 }
716 
717 //following routine courtesy of John George
ID3_GetMimeTypeOfPicType(ID3_Tag * tag,ID3_PictureType pictype)718 char* ID3_GetMimeTypeOfPicType(ID3_Tag* tag, ID3_PictureType pictype)
719 {
720   char* sPicMimetype = NULL;
721   if (NULL == tag)
722     return sPicMimetype;
723 
724   ID3_Frame* frame = NULL;
725   ID3_Tag::Iterator* iter = tag->CreateIterator();
726 
727   while (NULL != (frame = iter->GetNext()))
728   {
729     if(frame->GetID() == ID3FID_PICTURE)
730     {
731       if(frame->GetField(ID3FN_PICTURETYPE)->Get() == (uint32)pictype)
732         break;
733     }
734   }
735   delete iter;
736 
737   if (frame != NULL)
738   {
739     sPicMimetype = ID3_GetString(frame, ID3FN_MIMETYPE);
740   }
741   return sPicMimetype;
742 }
743 
744 //following routine courtesy of John George
ID3_GetDescriptionOfPicType(ID3_Tag * tag,ID3_PictureType pictype)745 char* ID3_GetDescriptionOfPicType(ID3_Tag* tag, ID3_PictureType pictype)
746 {
747   char* sPicDescription = NULL;
748   if (NULL == tag)
749     return sPicDescription;
750 
751   ID3_Frame* frame = NULL;
752   ID3_Tag::Iterator* iter = tag->CreateIterator();
753 
754   while (NULL != (frame = iter->GetNext()))
755   {
756     if(frame->GetID() == ID3FID_PICTURE)
757     {
758       if(frame->GetField(ID3FN_PICTURETYPE)->Get() == (uint32)pictype)
759         break;
760     }
761   }
762   delete iter;
763 
764   if (frame != NULL)
765   {
766     sPicDescription = ID3_GetString(frame, ID3FN_DESCRIPTION);
767   }
768   return sPicDescription;
769 }
770 
771 
ID3_RemoveTracks(ID3_Tag * tag)772 size_t ID3_RemoveTracks(ID3_Tag* tag)
773 {
774   size_t num_removed = 0;
775   ID3_Frame* frame = NULL;
776 
777   if (NULL == tag)
778   {
779     return num_removed;
780   }
781 
782   while ((frame = tag->Find(ID3FID_TRACKNUM)))
783   {
784     frame = tag->RemoveFrame(frame);
785     delete frame;
786     num_removed++;
787   }
788 
789   return num_removed;
790 }
791 
ID3_GetGenre(const ID3_Tag * tag)792 char *ID3_GetGenre(const ID3_Tag *tag)
793 {
794   char *sGenre = NULL;
795   if (NULL == tag)
796   {
797     return sGenre;
798   }
799 
800   ID3_Frame *frame = tag->Find(ID3FID_CONTENTTYPE);
801   if (frame != NULL)
802   {
803     sGenre = ID3_GetString(frame, ID3FN_TEXT);
804   }
805 
806   return sGenre;
807 }
808 
ID3_GetGenreNum(const ID3_Tag * tag)809 size_t ID3_GetGenreNum(const ID3_Tag *tag)
810 {
811   char *sGenre = ID3_GetGenre(tag);
812   size_t ulGenre = 0xFF;
813   if (NULL == sGenre)
814   {
815     return ulGenre;
816   }
817 
818   // If the genre string begins with "(ddd)", where "ddd" is a number, then
819   // "ddd" is the genre number---get it
820   if (sGenre[0] == '(')
821   {
822     char *pCur = &sGenre[1];
823     while (isdigit(*pCur))
824     {
825       pCur++;
826     }
827     if (*pCur == ')')
828     {
829       // if the genre number is greater than 255, its invalid.
830       ulGenre = dami::min(0xFF, atoi(&sGenre[1]));
831     }
832   }
833 
834   delete [] sGenre;
835   return ulGenre;
836 }
837 
838 //following routine courtesy of John George
ID3_AddGenre(ID3_Tag * tag,const char * genre,bool replace)839 ID3_Frame* ID3_AddGenre(ID3_Tag* tag, const char* genre, bool replace)
840 {
841   ID3_Frame* frame = NULL;
842   if (NULL != tag && NULL != genre && strlen(genre) > 0)
843   {
844     if (replace)
845     {
846       ID3_RemoveGenres(tag);
847     }
848     if (replace || NULL == tag->Find(ID3FID_CONTENTTYPE))
849     {
850       frame = new ID3_Frame(ID3FID_CONTENTTYPE);
851       if (NULL != frame)
852       {
853         frame->GetField(ID3FN_TEXT)->Set(genre);
854         tag->AttachFrame(frame);
855       }
856     }
857   }
858 
859   return frame;
860 }
861 
ID3_AddGenre(ID3_Tag * tag,size_t genreNum,bool replace)862 ID3_Frame* ID3_AddGenre(ID3_Tag *tag, size_t genreNum, bool replace)
863 {
864   if(0xFF != genreNum)
865   {
866     char sGenre[6];
867     sprintf(sGenre, "(%lu)", (luint) genreNum);
868     return(ID3_AddGenre(tag, sGenre, replace));
869   }
870   else
871   {
872     return(NULL);
873   }
874 }
875 
ID3_RemoveGenres(ID3_Tag * tag)876 size_t ID3_RemoveGenres(ID3_Tag *tag)
877 {
878   size_t num_removed = 0;
879   ID3_Frame *frame = NULL;
880 
881   if (NULL == tag)
882   {
883     return num_removed;
884   }
885 
886   while ((frame = tag->Find(ID3FID_CONTENTTYPE)))
887   {
888     frame = tag->RemoveFrame(frame);
889     delete frame;
890     num_removed++;
891   }
892 
893   return num_removed;
894 }
895 
ID3_GetLyrics(const ID3_Tag * tag)896 char *ID3_GetLyrics(const ID3_Tag *tag)
897 {
898   char *sLyrics = NULL;
899   if (NULL == tag)
900   {
901     return sLyrics;
902   }
903 
904   ID3_Frame *frame = tag->Find(ID3FID_UNSYNCEDLYRICS);
905   if (frame != NULL)
906   {
907     sLyrics = ID3_GetString(frame, ID3FN_TEXT);
908   }
909   return sLyrics;
910 }
911 
ID3_AddLyrics(ID3_Tag * tag,const char * text,bool replace)912 ID3_Frame* ID3_AddLyrics(ID3_Tag *tag, const char *text, bool replace)
913 {
914   return ID3_AddLyrics(tag, text, "", replace);
915 }
916 
ID3_AddLyrics(ID3_Tag * tag,const char * text,const char * desc,bool replace)917 ID3_Frame* ID3_AddLyrics(ID3_Tag *tag, const char *text, const char* desc,
918                          bool replace)
919 {
920   return ID3_AddLyrics(tag, text, desc, "XXX", replace);
921 }
922 
ID3_AddLyrics(ID3_Tag * tag,const char * text,const char * desc,const char * lang,bool replace)923 ID3_Frame* ID3_AddLyrics(ID3_Tag *tag, const char *text, const char* desc,
924                          const char* lang, bool replace)
925 {
926   ID3_Frame* frame = NULL;
927   if (NULL != tag && strlen(text) > 0)
928   {
929     if (replace)
930     {
931       ID3_RemoveLyrics(tag);
932     }
933     if (replace || tag->Find(ID3FID_UNSYNCEDLYRICS) == NULL)
934     {
935       frame = new ID3_Frame(ID3FID_UNSYNCEDLYRICS);
936       if (NULL != frame)
937       {
938         frame->GetField(ID3FN_LANGUAGE)->Set(lang);
939         frame->GetField(ID3FN_DESCRIPTION)->Set(desc);
940         frame->GetField(ID3FN_TEXT)->Set(text);
941         tag->AttachFrame(frame);
942       }
943     }
944   }
945 
946   return frame;
947 }
948 
ID3_RemoveLyrics(ID3_Tag * tag)949 size_t ID3_RemoveLyrics(ID3_Tag *tag)
950 {
951   size_t num_removed = 0;
952   ID3_Frame *frame = NULL;
953 
954   if (NULL == tag)
955   {
956     return num_removed;
957   }
958 
959   while ((frame = tag->Find(ID3FID_UNSYNCEDLYRICS)))
960   {
961     frame = tag->RemoveFrame(frame);
962     delete frame;
963     num_removed++;
964   }
965 
966   return num_removed;
967 }
968 
ID3_GetLyricist(const ID3_Tag * tag)969 char *ID3_GetLyricist(const ID3_Tag *tag)
970 {
971   char *sLyricist = NULL;
972   if (NULL == tag)
973   {
974     return sLyricist;
975   }
976 
977   ID3_Frame *frame = tag->Find(ID3FID_LYRICIST);
978   if (frame != NULL)
979   {
980     sLyricist = ID3_GetString(frame, ID3FN_TEXT);
981   }
982   return sLyricist;
983 }
984 
ID3_AddLyricist(ID3_Tag * tag,const char * text,bool replace)985 ID3_Frame* ID3_AddLyricist(ID3_Tag *tag, const char *text, bool replace)
986 {
987   ID3_Frame* frame = NULL;
988   if (NULL != tag && NULL != text && strlen(text) > 0)
989   {
990     if (replace)
991     {
992       ID3_RemoveLyricist(tag);
993     }
994     if (replace || (tag->Find(ID3FID_LYRICIST) == NULL))
995     {
996       frame = new ID3_Frame(ID3FID_LYRICIST);
997       if (frame)
998       {
999         frame->GetField(ID3FN_TEXT)->Set(text);
1000         tag->AttachFrame(frame);
1001       }
1002     }
1003   }
1004 
1005   return frame;
1006 }
1007 
ID3_RemoveLyricist(ID3_Tag * tag)1008 size_t ID3_RemoveLyricist(ID3_Tag *tag)
1009 {
1010   size_t num_removed = 0;
1011   ID3_Frame *frame = NULL;
1012 
1013   if (NULL == tag)
1014   {
1015     return num_removed;
1016   }
1017 
1018   while ((frame = tag->Find(ID3FID_LYRICIST)))
1019   {
1020     frame = tag->RemoveFrame(frame);
1021     delete frame;
1022     num_removed++;
1023   }
1024 
1025   return num_removed;
1026 }
1027 
ID3_AddSyncLyrics(ID3_Tag * tag,const uchar * data,size_t datasize,ID3_TimeStampFormat format,bool replace)1028 ID3_Frame* ID3_AddSyncLyrics(ID3_Tag *tag, const uchar *data, size_t datasize,
1029                              ID3_TimeStampFormat format, bool replace)
1030 {
1031   return ID3_AddSyncLyrics(tag, data, datasize, format, "", replace);
1032 }
1033 
ID3_AddSyncLyrics(ID3_Tag * tag,const uchar * data,size_t datasize,ID3_TimeStampFormat format,const char * desc,bool replace)1034 ID3_Frame* ID3_AddSyncLyrics(ID3_Tag *tag, const uchar *data, size_t datasize,
1035                              ID3_TimeStampFormat format, const char *desc,
1036                              bool replace)
1037 {
1038   return ID3_AddSyncLyrics(tag, data, datasize, format, desc, "XXX", replace);
1039 }
1040 
ID3_AddSyncLyrics(ID3_Tag * tag,const uchar * data,size_t datasize,ID3_TimeStampFormat format,const char * desc,const char * lang,bool replace)1041 ID3_Frame* ID3_AddSyncLyrics(ID3_Tag *tag, const uchar *data, size_t datasize,
1042                              ID3_TimeStampFormat format, const char *desc,
1043                              const char *lang, bool replace)
1044 {
1045   return ID3_AddSyncLyrics(tag, data, datasize, format, desc, lang,
1046                            ID3CT_LYRICS, replace);
1047 }
1048 
ID3_AddSyncLyrics(ID3_Tag * tag,const uchar * data,size_t datasize,ID3_TimeStampFormat format,const char * desc,const char * lang,ID3_ContentType type,bool replace)1049 ID3_Frame* ID3_AddSyncLyrics(ID3_Tag *tag, const uchar *data, size_t datasize,
1050                              ID3_TimeStampFormat format, const char *desc,
1051                              const char *lang, ID3_ContentType type,
1052                              bool replace)
1053 {
1054   ID3_Frame* frame = NULL;
1055   // language and descriptor should be mandatory
1056   if ((NULL == lang) || (NULL == desc))
1057   {
1058     return NULL;
1059   }
1060 
1061   // check if a SYLT frame of this language or descriptor already exists
1062   ID3_Frame* frmExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang);
1063   if (!frmExist)
1064   {
1065     frmExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc);
1066   }
1067 
1068   if (NULL != tag && NULL != data)
1069   {
1070     if (replace && frmExist)
1071     {
1072       frmExist = tag->RemoveFrame (frmExist);
1073       delete frmExist;
1074       frmExist = NULL;
1075     }
1076 
1077     // if the frame still exist, cannot continue
1078     if (frmExist)
1079     {
1080       return NULL;
1081     }
1082 
1083     ID3_Frame* frame = new ID3_Frame(ID3FID_SYNCEDLYRICS);
1084 
1085     frame->GetField(ID3FN_LANGUAGE)->Set(lang);
1086     frame->GetField(ID3FN_DESCRIPTION)->Set(desc);
1087     frame->GetField(ID3FN_TIMESTAMPFORMAT)->Set(format);
1088     frame->GetField(ID3FN_CONTENTTYPE)->Set(type);
1089     frame->GetField(ID3FN_DATA)->Set(data, datasize);
1090     tag->AttachFrame(frame);
1091   }
1092 
1093   return frame;
1094 }
1095 
ID3_GetSyncLyricsInfo(const ID3_Tag * tag,const char * desc,const char * lang,ID3_TimeStampFormat & format,ID3_ContentType & type,size_t & size)1096 ID3_Frame *ID3_GetSyncLyricsInfo(const ID3_Tag *tag, const char *desc,
1097                                  const char *lang,
1098                                  ID3_TimeStampFormat& format,
1099                                  ID3_ContentType& type, size_t& size)
1100 {
1101   // check if a SYLT frame of this language or descriptor exists
1102   ID3_Frame* frmExist = NULL;
1103   if (NULL != lang)
1104   {
1105     // search through language
1106     frmExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang);
1107   }
1108   else if (NULL != desc)
1109   {
1110     // search through descriptor
1111     frmExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc);
1112   }
1113   else
1114   {
1115     // both language and description not specified, search the first SYLT frame
1116     frmExist = tag->Find(ID3FID_SYNCEDLYRICS);
1117   }
1118 
1119   if (!frmExist)
1120   {
1121     return NULL;
1122   }
1123 
1124   // get the lyrics time stamp format
1125   format = static_cast<ID3_TimeStampFormat>(frmExist->GetField(ID3FN_TIMESTAMPFORMAT)->Get ());
1126 
1127   // get the lyrics content type
1128   type = static_cast<ID3_ContentType>(frmExist->GetField(ID3FN_CONTENTTYPE)->Get ());
1129 
1130   // get the lyrics size
1131   size = frmExist->GetField (ID3FN_DATA)->Size ();
1132 
1133   // return the frame pointer for further uses
1134   return frmExist;
1135 }
1136 
ID3_GetSyncLyrics(const ID3_Tag * tag,const char * lang,const char * desc,const uchar * & pData,size_t & size)1137 ID3_Frame *ID3_GetSyncLyrics(const ID3_Tag* tag, const char* lang,
1138                              const char* desc, const uchar* &pData, size_t& size)
1139 {
1140   // check if a SYLT frame of this language or descriptor exists
1141   ID3_Frame* frmExist = NULL;
1142   if (NULL != lang)
1143   {
1144     // search through language
1145     frmExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang);
1146   }
1147   else if (NULL != desc)
1148   {
1149     // search through descriptor
1150     frmExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc);
1151   }
1152   else
1153   {
1154     // both language and description not specified, search the first SYLT frame
1155     frmExist = tag->Find(ID3FID_SYNCEDLYRICS);
1156   }
1157 
1158   if (NULL == frmExist)
1159   {
1160     return NULL;
1161   }
1162 
1163   // get the lyrics size
1164   size = dami::min(size, frmExist->GetField(ID3FN_DATA)->Size());
1165 
1166   // get the lyrics data
1167   pData = frmExist->GetField (ID3FN_DATA)->GetRawBinary();
1168 
1169   // return the frame pointer for further uses
1170   return frmExist;
1171 }
1172 
1173